Merge "Migrate IUsbGadget to AIDL"
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index d6e6f50..92d7d54 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -23,9 +23,18 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
+aidl_interface_defaults {
+ name: "android.hardware.audio_defaults",
+ host_supported: true,
+ vendor_available: true,
+ stability: "vintf",
+}
+
aidl_interface {
name: "android.hardware.audio.common",
- vendor_available: true,
+ defaults: [
+ "android.hardware.audio_defaults",
+ ],
srcs: [
"android/hardware/audio/common/PlaybackTrackMetadata.aidl",
"android/hardware/audio/common/RecordTrackMetadata.aidl",
@@ -35,7 +44,6 @@
imports: [
"android.media.audio.common.types-V2",
],
- stability: "vintf",
backend: {
cpp: {
enabled: true,
@@ -87,19 +95,31 @@
],
}
+cc_defaults {
+ name: "latest_android_hardware_audio_common_ndk_shared",
+ shared_libs: [
+ latest_android_hardware_audio_common + "-ndk",
+ ],
+}
+
aidl_interface {
name: "android.hardware.audio.core",
- vendor_available: true,
+ defaults: [
+ "android.hardware.audio_defaults",
+ ],
srcs: [
+ "android/hardware/audio/core/AudioMode.aidl",
"android/hardware/audio/core/AudioPatch.aidl",
"android/hardware/audio/core/AudioRoute.aidl",
"android/hardware/audio/core/IConfig.aidl",
"android/hardware/audio/core/IModule.aidl",
"android/hardware/audio/core/IStreamIn.aidl",
"android/hardware/audio/core/IStreamOut.aidl",
+ "android/hardware/audio/core/ITelephony.aidl",
"android/hardware/audio/core/MmapBufferDescriptor.aidl",
"android/hardware/audio/core/ModuleDebug.aidl",
"android/hardware/audio/core/StreamDescriptor.aidl",
+ "android/hardware/audio/core/SurroundSoundConfig.aidl",
],
imports: [
"android.hardware.common-V2",
@@ -107,7 +127,6 @@
"android.hardware.audio.common-V1",
"android.media.audio.common.types-V2",
],
- stability: "vintf",
backend: {
// The C++ backend is disabled transitively due to use of FMQ.
cpp: {
@@ -145,17 +164,37 @@
aidl_interface {
name: "android.hardware.audio.effect",
- vendor_available: true,
+ defaults: [
+ "android.hardware.audio_defaults",
+ ],
srcs: [
+ "android/hardware/audio/effect/BassBoost.aidl",
+ "android/hardware/audio/effect/Capability.aidl",
+ "android/hardware/audio/effect/CommandId.aidl",
"android/hardware/audio/effect/Descriptor.aidl",
+ "android/hardware/audio/effect/Downmix.aidl",
+ "android/hardware/audio/effect/DynamicsProcessing.aidl",
+ "android/hardware/audio/effect/Equalizer.aidl",
+ "android/hardware/audio/effect/Flags.aidl",
+ "android/hardware/audio/effect/HapticGenerator.aidl",
"android/hardware/audio/effect/IEffect.aidl",
"android/hardware/audio/effect/IFactory.aidl",
+ "android/hardware/audio/effect/LoudnessEnhancer.aidl",
+ "android/hardware/audio/effect/Parameter.aidl",
+ "android/hardware/audio/effect/Processing.aidl",
+ "android/hardware/audio/effect/Reverb.aidl",
+ "android/hardware/audio/effect/State.aidl",
+ "android/hardware/audio/effect/VendorExtension.aidl",
+ "android/hardware/audio/effect/Virtualizer.aidl",
+ "android/hardware/audio/effect/Visualizer.aidl",
+ "android/hardware/audio/effect/Volume.aidl",
],
imports: [
+ "android.hardware.common-V2",
+ "android.hardware.common.fmq-V1",
"android.hardware.audio.common-V1",
"android.media.audio.common.types-V2",
],
- stability: "vintf",
backend: {
// The C++ backend is disabled transitively due to use of FMQ.
cpp: {
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/AudioMode.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/AudioMode.aidl
new file mode 100644
index 0000000..336f9b5
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/AudioMode.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@Backing(type="int") @VintfStability
+enum AudioMode {
+ NORMAL = 0,
+ RINGTONE = 1,
+ IN_CALL = 2,
+ IN_COMMUNICATION = 3,
+ CALL_SCREEN = 4,
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
index fd80715..163b7a0 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IConfig.aidl
@@ -34,4 +34,5 @@
package android.hardware.audio.core;
@VintfStability
interface IConfig {
+ android.hardware.audio.core.SurroundSoundConfig getSurroundSoundConfig();
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
index a8bbb15..be382c5 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IModule.aidl
@@ -35,6 +35,7 @@
@VintfStability
interface IModule {
void setModuleDebug(in android.hardware.audio.core.ModuleDebug debug);
+ @nullable android.hardware.audio.core.ITelephony getTelephony();
android.media.audio.common.AudioPort connectExternalDevice(in android.media.audio.common.AudioPort templateIdAndAdditionalData);
void disconnectExternalDevice(int portId);
android.hardware.audio.core.AudioPatch[] getAudioPatches();
@@ -49,6 +50,15 @@
boolean setAudioPortConfig(in android.media.audio.common.AudioPortConfig requested, out android.media.audio.common.AudioPortConfig suggested);
void resetAudioPatch(int patchId);
void resetAudioPortConfig(int portConfigId);
+ boolean getMasterMute();
+ void setMasterMute(boolean mute);
+ float getMasterVolume();
+ void setMasterVolume(float volume);
+ boolean getMicMute();
+ void setMicMute(boolean mute);
+ void updateAudioMode(android.hardware.audio.core.AudioMode mode);
+ void updateScreenRotation(android.hardware.audio.core.IModule.ScreenRotation rotation);
+ void updateScreenState(boolean isTurnedOn);
@VintfStability
parcelable OpenInputStreamArguments {
int portConfigId;
@@ -72,4 +82,11 @@
android.hardware.audio.core.IStreamOut stream;
android.hardware.audio.core.StreamDescriptor desc;
}
+ @Backing(type="int") @VintfStability
+ enum ScreenRotation {
+ DEG_0 = 0,
+ DEG_90 = 1,
+ DEG_180 = 2,
+ DEG_270 = 3,
+ }
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ITelephony.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ITelephony.aidl
new file mode 100644
index 0000000..a8c58c1
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/ITelephony.aidl
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@VintfStability
+interface ITelephony {
+ android.hardware.audio.core.AudioMode[] getSupportedAudioModes();
+ void switchAudioMode(android.hardware.audio.core.AudioMode mode);
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl
index db1ac22..3a77ad1 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/StreamDescriptor.aidl
@@ -39,16 +39,31 @@
int frameSizeBytes;
long bufferSizeFrames;
android.hardware.audio.core.StreamDescriptor.AudioBuffer audio;
- const int COMMAND_BURST = 1;
+ const int LATENCY_UNKNOWN = -1;
@FixedSize @VintfStability
parcelable Position {
long frames;
long timeNs;
}
+ @Backing(type="int") @VintfStability
+ enum State {
+ STANDBY = 1,
+ IDLE = 2,
+ ACTIVE = 3,
+ PAUSED = 4,
+ DRAINING = 5,
+ DRAIN_PAUSED = 6,
+ ERROR = 100,
+ }
@FixedSize @VintfStability
- parcelable Command {
- int code;
- int fmqByteCount;
+ union Command {
+ int hal_reserved_exit;
+ android.media.audio.common.Void start;
+ int burst;
+ android.media.audio.common.Void drain;
+ android.media.audio.common.Void standby;
+ android.media.audio.common.Void pause;
+ android.media.audio.common.Void flush;
}
@FixedSize @VintfStability
parcelable Reply {
@@ -57,6 +72,8 @@
android.hardware.audio.core.StreamDescriptor.Position observable;
android.hardware.audio.core.StreamDescriptor.Position hardware;
int latencyMs;
+ int xrunFrames;
+ android.hardware.audio.core.StreamDescriptor.State state = android.hardware.audio.core.StreamDescriptor.State.STANDBY;
}
@VintfStability
union AudioBuffer {
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/SurroundSoundConfig.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/SurroundSoundConfig.aidl
new file mode 100644
index 0000000..08a1537
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/SurroundSoundConfig.aidl
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.core;
+@JavaDerive(equals=true, toString=true) @VintfStability
+parcelable SurroundSoundConfig {
+ android.hardware.audio.core.SurroundSoundConfig.SurroundFormatFamily[] formatFamilies;
+ @VintfStability
+ parcelable SurroundFormatFamily {
+ android.media.audio.common.AudioFormatDescription primaryFormat;
+ android.media.audio.common.AudioFormatDescription[] subFormats;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl
new file mode 100644
index 0000000..979ebb8
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/BassBoost.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.effect;
+@VintfStability
+union BassBoost {
+ android.hardware.audio.effect.VendorExtension vendor;
+ int strengthPm;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.BassBoost.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ ParcelableHolder extension;
+ boolean strengthSupported;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl
new file mode 100644
index 0000000..06f2bfe
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Capability.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Capability {
+ android.hardware.audio.effect.VendorExtension vendorExtension;
+ android.hardware.audio.effect.BassBoost.Capability bassBoost;
+ android.hardware.audio.effect.Downmix.Capability downmix;
+ android.hardware.audio.effect.DynamicsProcessing.Capability dynamicsProcessing;
+ android.hardware.audio.effect.Equalizer.Capability equalizer;
+ android.hardware.audio.effect.HapticGenerator.Capability hapticGenerator;
+ android.hardware.audio.effect.LoudnessEnhancer.Capability loudnessEnhancer;
+ android.hardware.audio.effect.Reverb.Capability reverb;
+ android.hardware.audio.effect.Virtualizer.Capability virtualizer;
+ android.hardware.audio.effect.Visualizer.Capability visualizer;
+ android.hardware.audio.effect.Volume.Capability volume;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.aidl
new file mode 100644
index 0000000..79299ee
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/CommandId.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.effect;
+@Backing(type="int") @VintfStability
+enum CommandId {
+ START = 0,
+ STOP = 1,
+ RESET = 2,
+ VENDOR_COMMAND_0 = 256,
+ VENDOR_COMMAND_1 = 257,
+ VENDOR_COMMAND_2 = 258,
+ VENDOR_COMMAND_3 = 259,
+ VENDOR_COMMAND_4 = 260,
+ VENDOR_COMMAND_5 = 261,
+ VENDOR_COMMAND_6 = 262,
+ VENDOR_COMMAND_7 = 263,
+ VENDOR_COMMAND_8 = 264,
+ VENDOR_COMMAND_9 = 265,
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
index 94cacd9..990d369 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Descriptor.aidl
@@ -35,6 +35,7 @@
@VintfStability
parcelable Descriptor {
android.hardware.audio.effect.Descriptor.Common common;
+ android.hardware.audio.effect.Capability capability;
const String EFFECT_TYPE_UUID_ENV_REVERB = "c2e5d5f0-94bd-4763-9cac-4e234d06839e";
const String EFFECT_TYPE_UUID_PRESET_REVERB = "47382d60-ddd8-11db-bf3a-0002a5d5c51b";
const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b";
@@ -52,9 +53,15 @@
parcelable Identity {
android.media.audio.common.AudioUuid type;
android.media.audio.common.AudioUuid uuid;
+ @nullable android.media.audio.common.AudioUuid proxy;
}
@VintfStability
parcelable Common {
android.hardware.audio.effect.Descriptor.Identity id;
+ android.hardware.audio.effect.Flags flags;
+ int cpuLoad;
+ int memoryUsage;
+ @utf8InCpp String name;
+ @utf8InCpp String implementor;
}
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl
new file mode 100644
index 0000000..76f8ce5
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Downmix.aidl
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Downmix {
+ android.hardware.audio.effect.VendorExtension vendor;
+ android.hardware.audio.effect.Downmix.Type type;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.Downmix.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ ParcelableHolder extension;
+ }
+ @VintfStability
+ enum Type {
+ STRIP = 0,
+ FOLD = 1,
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl
new file mode 100644
index 0000000..ed4dc80
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/DynamicsProcessing.aidl
@@ -0,0 +1,116 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union DynamicsProcessing {
+ android.hardware.audio.effect.VendorExtension vendorExtension;
+ android.hardware.audio.effect.DynamicsProcessing.EngineArchitecture engineArchitecture;
+ android.hardware.audio.effect.DynamicsProcessing.BandChannelConfig preEq;
+ android.hardware.audio.effect.DynamicsProcessing.BandChannelConfig postEq;
+ android.hardware.audio.effect.DynamicsProcessing.EqBandConfig preEqBand;
+ android.hardware.audio.effect.DynamicsProcessing.EqBandConfig postEqBand;
+ android.hardware.audio.effect.DynamicsProcessing.BandChannelConfig mbc;
+ android.hardware.audio.effect.DynamicsProcessing.MbcBandConfig mbcBand;
+ android.hardware.audio.effect.DynamicsProcessing.LimiterConfig limiter;
+ float inputGainDb;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.DynamicsProcessing.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ ParcelableHolder extension;
+ }
+ enum ResolutionPreference {
+ FAVOR_FREQUENCY_RESOLUTION = 0,
+ FAVOR_TIME_RESOLUTION = 1,
+ }
+ @VintfStability
+ parcelable BandEnablement {
+ boolean inUse;
+ int bandCount;
+ }
+ @VintfStability
+ parcelable EngineArchitecture {
+ android.hardware.audio.effect.DynamicsProcessing.ResolutionPreference resolutionPreference = android.hardware.audio.effect.DynamicsProcessing.ResolutionPreference.FAVOR_FREQUENCY_RESOLUTION;
+ float preferredFrameDurationMs;
+ android.hardware.audio.effect.DynamicsProcessing.BandEnablement preEqBand;
+ android.hardware.audio.effect.DynamicsProcessing.BandEnablement postEqBand;
+ android.hardware.audio.effect.DynamicsProcessing.BandEnablement mbcBand;
+ boolean limiterInUse;
+ }
+ @VintfStability
+ parcelable BandChannelConfig {
+ int channel;
+ android.hardware.audio.effect.DynamicsProcessing.BandEnablement enablement;
+ }
+ @VintfStability
+ parcelable EqBandConfig {
+ int channel;
+ int band;
+ boolean enable;
+ float cutoffFrequency;
+ float gain;
+ }
+ @VintfStability
+ parcelable MbcBandConfig {
+ int channel;
+ int band;
+ boolean enable;
+ float cutoffFrequencyHz;
+ float gainDb;
+ float attackTimeMs;
+ float releaseTimeMs;
+ float ratio;
+ float thresholdDb;
+ float kneeWidthDb;
+ float noiseGateThresholdDb;
+ float expanderRatio;
+ float preGainDb;
+ float postGainDb;
+ }
+ @VintfStability
+ parcelable LimiterConfig {
+ int channel;
+ boolean enable;
+ boolean inUse;
+ int linkGroup;
+ float attackTimeMs;
+ float releaseTimeMs;
+ float ratio;
+ float thresholdDb;
+ float postGainDb;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl
new file mode 100644
index 0000000..d825eac
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Equalizer.aidl
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Equalizer {
+ android.hardware.audio.effect.VendorExtension vendorExtension;
+ android.hardware.audio.effect.Equalizer.BandLevel[] bandLevels;
+ int preset;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.Equalizer.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ ParcelableHolder extension;
+ android.hardware.audio.effect.Equalizer.BandFrequency[] bandFrequencies;
+ android.hardware.audio.effect.Equalizer.Preset[] presets;
+ }
+ @VintfStability
+ parcelable BandLevel {
+ int index;
+ int levelMb;
+ }
+ @VintfStability
+ parcelable BandFrequency {
+ int index;
+ int minMh;
+ int maxMh;
+ }
+ @VintfStability
+ parcelable Preset {
+ int index;
+ @utf8InCpp String name;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Flags.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Flags.aidl
new file mode 100644
index 0000000..285ff18
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Flags.aidl
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+parcelable Flags {
+ android.hardware.audio.effect.Flags.Type type = android.hardware.audio.effect.Flags.Type.INSERT;
+ android.hardware.audio.effect.Flags.Insert insert = android.hardware.audio.effect.Flags.Insert.ANY;
+ android.hardware.audio.effect.Flags.Volume volume = android.hardware.audio.effect.Flags.Volume.NONE;
+ android.hardware.audio.effect.Flags.HardwareAccelerator hwAcceleratorMode = android.hardware.audio.effect.Flags.HardwareAccelerator.NONE;
+ boolean offloadIndication;
+ boolean deviceIndication;
+ boolean audioModeIndication;
+ boolean audioSourceIndication;
+ boolean noProcessing;
+ @Backing(type="byte") @VintfStability
+ enum Type {
+ INSERT = 0,
+ AUXILIARY = 1,
+ REPLACE = 2,
+ PRE_PROC = 3,
+ POST_PROC = 4,
+ }
+ @Backing(type="byte") @VintfStability
+ enum Insert {
+ ANY = 0,
+ FIRST = 1,
+ LAST = 2,
+ EXCLUSIVE = 3,
+ }
+ @Backing(type="byte") @VintfStability
+ enum Volume {
+ NONE = 0,
+ CTRL = 1,
+ IND = 2,
+ MONITOR = 3,
+ }
+ @Backing(type="byte") @VintfStability
+ enum HardwareAccelerator {
+ NONE = 0,
+ SIMPLE = 1,
+ TUNNEL = 2,
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl
new file mode 100644
index 0000000..40a8d72
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/HapticGenerator.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.effect;
+@VintfStability
+union HapticGenerator {
+ android.hardware.audio.effect.VendorExtension vendorExtension;
+ android.hardware.audio.effect.HapticGenerator.HapticScale hapticScale;
+ android.hardware.audio.effect.HapticGenerator.VibratorInformation vibratorInfo;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.HapticGenerator.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ android.hardware.audio.effect.VendorExtension extension;
+ }
+ @Backing(type="int") @VintfStability
+ enum VibratorScale {
+ MUTE = -100,
+ VERY_LOW = -2,
+ LOW = -1,
+ NONE = 0,
+ HIGH = 1,
+ VERY_HIGH = 2,
+ }
+ @VintfStability
+ parcelable HapticScale {
+ int id;
+ android.hardware.audio.effect.HapticGenerator.VibratorScale scale = android.hardware.audio.effect.HapticGenerator.VibratorScale.MUTE;
+ }
+ @VintfStability
+ parcelable VibratorInformation {
+ float resonantFrequencyHz;
+ float qFactor;
+ float maxAmplitude;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl
index 7f868ad..8c196e7 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IEffect.aidl
@@ -34,7 +34,23 @@
package android.hardware.audio.effect;
@VintfStability
interface IEffect {
- void open();
+ android.hardware.audio.effect.IEffect.OpenEffectReturn open(in android.hardware.audio.effect.Parameter.Common common, in @nullable android.hardware.audio.effect.Parameter.Specific specific);
void close();
android.hardware.audio.effect.Descriptor getDescriptor();
+ void command(in android.hardware.audio.effect.CommandId commandId);
+ android.hardware.audio.effect.State getState();
+ void setParameter(in android.hardware.audio.effect.Parameter param);
+ android.hardware.audio.effect.Parameter getParameter(in android.hardware.audio.effect.Parameter.Id paramId);
+ @FixedSize @VintfStability
+ parcelable Status {
+ int status;
+ int fmqConsumed;
+ int fmqProduced;
+ }
+ @VintfStability
+ parcelable OpenEffectReturn {
+ android.hardware.common.fmq.MQDescriptor<android.hardware.audio.effect.IEffect.Status,android.hardware.common.fmq.SynchronizedReadWrite> statusMQ;
+ android.hardware.common.fmq.MQDescriptor<float,android.hardware.common.fmq.SynchronizedReadWrite> inputDataMQ;
+ android.hardware.common.fmq.MQDescriptor<float,android.hardware.common.fmq.SynchronizedReadWrite> outputDataMQ;
+ }
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl
index db06475..5b85d33 100644
--- a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/IFactory.aidl
@@ -34,7 +34,8 @@
package android.hardware.audio.effect;
@VintfStability
interface IFactory {
- android.hardware.audio.effect.Descriptor.Identity[] queryEffects(in @nullable android.media.audio.common.AudioUuid type, in @nullable android.media.audio.common.AudioUuid implementation);
+ android.hardware.audio.effect.Descriptor.Identity[] queryEffects(in @nullable android.media.audio.common.AudioUuid type, in @nullable android.media.audio.common.AudioUuid implementation, in @nullable android.media.audio.common.AudioUuid proxy);
+ android.hardware.audio.effect.Processing[] queryProcessing(in @nullable android.hardware.audio.effect.Processing.Type type);
android.hardware.audio.effect.IEffect createEffect(in android.media.audio.common.AudioUuid implUuid);
void destroyEffect(in android.hardware.audio.effect.IEffect handle);
}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/LoudnessEnhancer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/LoudnessEnhancer.aidl
new file mode 100644
index 0000000..5c6ca16
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/LoudnessEnhancer.aidl
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union LoudnessEnhancer {
+ android.hardware.audio.effect.VendorExtension vendor;
+ int gainMb;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.LoudnessEnhancer.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ android.hardware.audio.effect.VendorExtension extension;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
new file mode 100644
index 0000000..321c286
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Parameter.aidl
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Parameter {
+ android.hardware.audio.effect.Parameter.Common common;
+ android.media.audio.common.AudioDeviceDescription deviceDescription;
+ android.media.audio.common.AudioMode mode;
+ android.media.audio.common.AudioSource source;
+ android.hardware.audio.effect.Parameter.VolumeStereo volumeStereo;
+ android.hardware.audio.effect.Parameter.Specific specific;
+ @VintfStability
+ union Id {
+ int vendorEffectTag;
+ android.hardware.audio.effect.BassBoost.Id bassBoostTag;
+ android.hardware.audio.effect.Downmix.Id downmixTag;
+ android.hardware.audio.effect.DynamicsProcessing.Id dynamicsProcessingTag;
+ android.hardware.audio.effect.Equalizer.Id equalizerTag;
+ android.hardware.audio.effect.HapticGenerator.Id hapticGeneratorTag;
+ android.hardware.audio.effect.LoudnessEnhancer.Id loudnessEnhancerTag;
+ android.hardware.audio.effect.Reverb.Id reverbTag;
+ android.hardware.audio.effect.Virtualizer.Id virtualizerTag;
+ android.hardware.audio.effect.Visualizer.Id visualizerTag;
+ android.hardware.audio.effect.Volume.Id volumeTag;
+ android.hardware.audio.effect.Parameter.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Common {
+ int session;
+ int ioHandle;
+ android.media.audio.common.AudioConfig input;
+ android.media.audio.common.AudioConfig output;
+ }
+ @VintfStability
+ parcelable VolumeStereo {
+ float left;
+ float right;
+ }
+ @VintfStability
+ union Specific {
+ android.hardware.audio.effect.VendorExtension vendorEffect;
+ android.hardware.audio.effect.BassBoost bassBoost;
+ android.hardware.audio.effect.Downmix downmix;
+ android.hardware.audio.effect.DynamicsProcessing dynamicsProcessing;
+ android.hardware.audio.effect.Equalizer equalizer;
+ android.hardware.audio.effect.LoudnessEnhancer loudnessEnhancer;
+ android.hardware.audio.effect.HapticGenerator hapticGenerator;
+ android.hardware.audio.effect.Reverb reverb;
+ android.hardware.audio.effect.Virtualizer virtualizer;
+ android.hardware.audio.effect.Visualizer visualizer;
+ android.hardware.audio.effect.Volume volume;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl
new file mode 100644
index 0000000..a779ae4
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Processing.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.effect;
+@VintfStability
+parcelable Processing {
+ android.hardware.audio.effect.Processing.Type type;
+ android.hardware.audio.effect.Descriptor.Identity[] ids;
+ @VintfStability
+ union Type {
+ android.media.audio.common.AudioStreamType streamType = android.media.audio.common.AudioStreamType.INVALID;
+ android.media.audio.common.AudioSource source;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
new file mode 100644
index 0000000..8ad4848
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Reverb.aidl
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Reverb {
+ android.hardware.audio.effect.VendorExtension vendor;
+ int roomLevelMb;
+ int roomHfLevelMb;
+ int decayTimeMs;
+ int decayHfRatioPm;
+ int levelMb;
+ int delayMs;
+ int diffusionPm;
+ int densityPm;
+ boolean bypass;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.Reverb.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ android.hardware.audio.effect.VendorExtension extension;
+ int maxDecayTimeMs;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.aidl
new file mode 100644
index 0000000..3176b01
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/State.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.audio.effect;
+@Backing(type="byte") @VintfStability
+enum State {
+ INIT = 0,
+ IDLE = 1,
+ PROCESSING = 2,
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/VendorExtension.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/VendorExtension.aidl
new file mode 100644
index 0000000..b806334
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/VendorExtension.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+parcelable VendorExtension {
+ ParcelableHolder extension;
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Virtualizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Virtualizer.aidl
new file mode 100644
index 0000000..d4fb9e0
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Virtualizer.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.effect;
+@VintfStability
+union Virtualizer {
+ android.hardware.audio.effect.VendorExtension vendor;
+ int strengthPm;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.Virtualizer.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ android.hardware.audio.effect.VendorExtension extension;
+ boolean strengthSupported;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl
new file mode 100644
index 0000000..9ee19f0
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Visualizer.aidl
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.audio.effect;
+@VintfStability
+union Visualizer {
+ android.hardware.audio.effect.Visualizer.Id id;
+ android.hardware.audio.effect.VendorExtension vendor;
+ android.hardware.audio.effect.Visualizer.GetOnlyParameters getOnlyParameters;
+ android.hardware.audio.effect.Visualizer.SetOnlyParameters setOnlyParameters;
+ int captureSizeBytes;
+ android.hardware.audio.effect.Visualizer.ScalingMode scalingMode;
+ android.hardware.audio.effect.Visualizer.MeasurementMode measurementMode;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.Visualizer.GetOnlyParameters.Tag getOnlyParamTag;
+ android.hardware.audio.effect.Visualizer.SetOnlyParameters.Tag setOnlyParamTag;
+ android.hardware.audio.effect.Visualizer.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ android.hardware.audio.effect.VendorExtension extension;
+ int maxLatencyMs;
+ android.hardware.audio.effect.Visualizer.CaptureSizeRange captureSizeRange;
+ }
+ @VintfStability
+ parcelable CaptureSizeRange {
+ int minBytes;
+ int maxBytes;
+ }
+ @VintfStability
+ enum ScalingMode {
+ NORMALIZED = 0,
+ AS_PLAYED = 1,
+ }
+ @VintfStability
+ enum MeasurementMode {
+ NONE = 0,
+ PEAK_RMS = 1,
+ }
+ @VintfStability
+ union GetOnlyParameters {
+ android.hardware.audio.effect.Visualizer.GetOnlyParameters.Measurement measurement;
+ byte[] captureBytes;
+ @VintfStability
+ parcelable Measurement {
+ int rms;
+ int peak;
+ }
+ }
+ @VintfStability
+ union SetOnlyParameters {
+ int latencyMs;
+ }
+}
diff --git a/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.aidl
new file mode 100644
index 0000000..8c836b0
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.effect/current/android/hardware/audio/effect/Volume.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.effect;
+@VintfStability
+union Volume {
+ android.hardware.audio.effect.VendorExtension vendor;
+ int levelDb;
+ boolean mute;
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ android.hardware.audio.effect.Volume.Tag commonTag;
+ }
+ @VintfStability
+ parcelable Capability {
+ android.hardware.audio.effect.VendorExtension extension;
+ int maxLevel;
+ }
+}
diff --git a/audio/aidl/android/hardware/audio/core/AudioMode.aidl b/audio/aidl/android/hardware/audio/core/AudioMode.aidl
new file mode 100644
index 0000000..0943a55
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/AudioMode.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.
+ */
+
+package android.hardware.audio.core;
+
+/**
+ * The audio mode describes states of the audio system of the device that
+ * can significantly affect the rules of audio routing, volume control, etc.
+ * The audio mode is controlled by the framework, however the HAL has some
+ * flexibility in the choice of modes to support, see 'IModule.updateAudioMode'.
+ */
+@VintfStability
+@Backing(type="int")
+enum AudioMode {
+ /** No active calls. */
+ NORMAL = 0,
+ /** The device is playing the ringtone. */
+ RINGTONE = 1,
+ /** The call is handled by the telephony stack ("voice call"). */
+ IN_CALL = 2,
+ /** The call is handled by an application ("VoIP call"). */
+ IN_COMMUNICATION = 3,
+ /** Call screening is in progress. */
+ CALL_SCREEN = 4,
+}
diff --git a/audio/aidl/android/hardware/audio/core/IConfig.aidl b/audio/aidl/android/hardware/audio/core/IConfig.aidl
index c7bb414..c8ba6be 100644
--- a/audio/aidl/android/hardware/audio/core/IConfig.aidl
+++ b/audio/aidl/android/hardware/audio/core/IConfig.aidl
@@ -16,9 +16,22 @@
package android.hardware.audio.core;
+import android.hardware.audio.core.SurroundSoundConfig;
+
/**
* This interface provides system-wide configuration parameters for audio I/O
* (by "system" here we mean the device running Android).
*/
@VintfStability
-interface IConfig {}
+interface IConfig {
+ /**
+ * Returns the surround sound configuration used for the Audio Policy
+ * Manager initial configuration.
+ *
+ * This method will only be called during the initialization of the Audio
+ * Policy Manager, and must always return the same result.
+ *
+ * @return The surround sound configuration
+ */
+ SurroundSoundConfig getSurroundSoundConfig();
+}
diff --git a/audio/aidl/android/hardware/audio/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl
index 735f87f..be40051 100644
--- a/audio/aidl/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/android/hardware/audio/core/IModule.aidl
@@ -18,10 +18,12 @@
import android.hardware.audio.common.SinkMetadata;
import android.hardware.audio.common.SourceMetadata;
+import android.hardware.audio.core.AudioMode;
import android.hardware.audio.core.AudioPatch;
import android.hardware.audio.core.AudioRoute;
import android.hardware.audio.core.IStreamIn;
import android.hardware.audio.core.IStreamOut;
+import android.hardware.audio.core.ITelephony;
import android.hardware.audio.core.ModuleDebug;
import android.hardware.audio.core.StreamDescriptor;
import android.media.audio.common.AudioOffloadInfo;
@@ -60,6 +62,19 @@
void setModuleDebug(in ModuleDebug debug);
/**
+ * Retrieve the interface to control telephony audio.
+ *
+ * If the HAL module supports telephony functions, it must return an
+ * instance of the ITelephony interface. The same instance must be returned
+ * during the lifetime of the HAL module. If the HAL module does not support
+ * telephony, a null must be returned, without throwing any errors.
+ *
+ * @return An instance of the ITelephony interface implementation.
+ * @throws EX_ILLEGAL_STATE If there was an error creating an instance.
+ */
+ @nullable ITelephony getTelephony();
+
+ /**
* Set a device port of an external device into connected state.
*
* This method is used to inform the HAL module that an external device has
@@ -263,6 +278,9 @@
* be completing with an error, although data (zero filled) will still be
* provided.
*
+ * After the stream has been opened, it remains in the STANDBY state, see
+ * StreamDescriptor for more details.
+ *
* @return An opened input stream and the associated descriptor.
* @param args The pack of arguments, see 'OpenInputStreamArguments' parcelable.
* @throws EX_ILLEGAL_ARGUMENT In the following cases:
@@ -325,6 +343,9 @@
* StreamDescriptor will be completing with an error, although the data
* will still be accepted and immediately discarded.
*
+ * After the stream has been opened, it remains in the STANDBY state, see
+ * StreamDescriptor for more details.
+ *
* @return An opened output stream and the associated descriptor.
* @param args The pack of arguments, see 'OpenOutputStreamArguments' parcelable.
* @throws EX_ILLEGAL_ARGUMENT In the following cases:
@@ -481,4 +502,140 @@
* - If the port config is used by a patch.
*/
void resetAudioPortConfig(int portConfigId);
+
+ /**
+ * Get the current state of audio output muting.
+ *
+ * If the HAL module supports muting its combined output completely,
+ * this method returns whether muting is currently enabled.
+ *
+ * Note that muting operates independently from the master volume.
+ *
+ * @return Whether the output from the module is muted.
+ * @throws EX_UNSUPPORTED_OPERATION If muting of combined output
+ * is not supported by the module.
+ */
+ boolean getMasterMute();
+
+ /**
+ * Set the current value of the audio output muting.
+ *
+ * If the HAL module supports muting its combined output completely, this
+ * method controls the mute. Note that for modules supporting telephony,
+ * muting does not affect the voice call.
+ *
+ * For HAL modules not supporting this operation, it's functionality is
+ * typically emulated by the client, in the digital domain.
+ *
+ * @param mute Whether the output from the module is muted.
+ * @throws EX_UNSUPPORTED_OPERATION If muting of combined output
+ * is not supported by the module.
+ */
+ void setMasterMute(boolean mute);
+
+ /**
+ * Get the current value of the audio output attenuation.
+ *
+ * If the HAL module supports attenuating the level its combined output,
+ * this method returns the current attenuation value.
+ *
+ * @return Volume 1.0f means no attenuation (unity), 0.0f is mute.
+ * @throws EX_UNSUPPORTED_OPERATION If attenuation of combined output
+ * is not supported by the module.
+ */
+ float getMasterVolume();
+
+ /**
+ * Set the current value of the audio output attenuation.
+ *
+ * If the HAL module supports attenuating the level its combined output,
+ * this method sets the attenuation value. Note that for modules supporting
+ * telephony, the attenuation of the voice call volume is set separately
+ * via ITelephony interface.
+ *
+ * For HAL modules not supporting this operation, it's functionality is
+ * typically emulated by the client, in the digital domain.
+ *
+ * @param volume The new value, 1.0f means no attenuation (unity), 0.0f is mute.
+ * @throws EX_ILLEGAL_ARGUMENT If the value of the volume is outside of
+ * accepted range.
+ * @throws EX_UNSUPPORTED_OPERATION If attenuation of combined output
+ * is not supported by the module.
+ */
+ void setMasterVolume(float volume);
+
+ /**
+ * Get the current state of audio input muting.
+ *
+ * If the HAL module supports muting its external input, this method returns
+ * whether muting is currently enabled.
+ *
+ * @return Whether the input is muted.
+ * @throws EX_UNSUPPORTED_OPERATION If muting of input is not supported by
+ * the module.
+ */
+ boolean getMicMute();
+
+ /**
+ * Set the current value of the audio input muting.
+ *
+ * If the HAL module supports muting its external input, this method
+ * controls the mute.
+ *
+ * For HAL modules not supporting this operation, it's functionality is
+ * emulated by the client.
+ *
+ * @param mute Whether input is muted.
+ * @throws EX_UNSUPPORTED_OPERATION If muting of input is not supported by
+ * the module.
+ */
+ void setMicMute(boolean mute);
+
+ /**
+ * Notify the HAL module on the change of the current audio mode.
+ *
+ * The current audio mode is always controlled by the client. This is an
+ * informative notification sent to all modules, no reply is needed. The HAL
+ * module should silently ignore this notification if it does not need to
+ * be aware of the current audio mode.
+ *
+ * The client sends this notification to all HAL modules after successfully
+ * switching the telephony module by calling the 'ITelephony.switchAudioMode'
+ * method.
+ *
+ * @param mode The current mode.
+ */
+ void updateAudioMode(AudioMode mode);
+
+ @VintfStability
+ @Backing(type="int")
+ enum ScreenRotation {
+ /** Natural orientation. */
+ DEG_0 = 0,
+ DEG_90 = 1,
+ /** Upside down. */
+ DEG_180 = 2,
+ DEG_270 = 3,
+ }
+ /**
+ * Notify the HAL module on the change of the screen rotation.
+ *
+ * Informs the HAL of the current orientation of the device screen. This
+ * information can be used to optimize the output of built-in speakers.
+ * This is an informative notification sent to all modules, no reply is
+ * needed.
+ *
+ * @param rotation The current rotation.
+ */
+ void updateScreenRotation(ScreenRotation rotation);
+
+ /**
+ * Notify the HAL module on the change of the screen state.
+ *
+ * Informs the HAL whether the screen of the device is turned on. This is an
+ * informative notification sent to all modules, no reply is needed.
+ *
+ * @param isTurnedOn True if the screen is turned on.
+ */
+ void updateScreenState(boolean isTurnedOn);
}
diff --git a/audio/aidl/android/hardware/audio/core/ITelephony.aidl b/audio/aidl/android/hardware/audio/core/ITelephony.aidl
new file mode 100644
index 0000000..a872c7c
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/ITelephony.aidl
@@ -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.
+ */
+
+package android.hardware.audio.core;
+
+import android.hardware.audio.core.AudioMode;
+
+/**
+ * An instance of ITelephony manages settings which are specific to voice calls
+ * and SMS messaging functionality. This interface is optional to implement and
+ * provide by the vendor. It needs to be provided only if the device actually
+ * supports telephony.
+ */
+@VintfStability
+interface ITelephony {
+ /**
+ * Return the list of supported audio modes.
+ *
+ * The first 4 AudioModes: NORMAL, RINGTONE, IN_CALL, IN_COMMUNICATION must
+ * be supported by all implementations.
+ *
+ * This method is only called once, during the audio system initialization,
+ * and must return the same result all the time.
+ *
+ * @return The list of supported audio modes.
+ */
+ AudioMode[] getSupportedAudioModes();
+
+ /**
+ * Switch the HAL into a new audio mode.
+ *
+ * The current audio mode is always controlled by the client. The HAL must
+ * accept all modes returned by 'getSupportedAudioModes' and reject the
+ * rest. The HAL must return from this method only after switching itself
+ * to the specified mode, or throw an error if there was a problem during
+ * switching.
+ *
+ * @param mode The mode to switch to.
+ * @throws EX_UNSUPPORTED_OPERATION If the HAL does not support the specified mode.
+ * @throws EX_ILLEGAL_STATE If there was an error during switching.
+ */
+ void switchAudioMode(AudioMode mode);
+}
diff --git a/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
index 2b1ed8c..2b1fc99 100644
--- a/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
+++ b/audio/aidl/android/hardware/audio/core/StreamDescriptor.aidl
@@ -19,6 +19,7 @@
import android.hardware.audio.core.MmapBufferDescriptor;
import android.hardware.common.fmq.MQDescriptor;
import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.media.audio.common.Void;
/**
* Stream descriptor contains fast message queues and buffers used for sending
@@ -33,6 +34,72 @@
* internal components of the stream while serving commands invoked via the
* stream's AIDL interface and commands invoked via the command queue of the
* descriptor.
+ *
+ * There is a state machine defined for the stream, which executes on the
+ * thread handling the commands from the queue. The states are defined based
+ * on the model of idealized producer and consumer connected via a ring buffer.
+ * For input streams, the "producer" is hardware, the "consumer" is software,
+ * for outputs streams it's the opposite. When the producer is active, but
+ * the buffer is full, the following actions are possible:
+ * - if the consumer is active, the producer blocks until there is space,
+ * this behavior is only possible for software producers;
+ * - if the consumer is passive:
+ * - the producer can preserve the buffer contents—a s/w producer can
+ * keep the data on their side, while a h/w producer can only drop captured
+ * data in this case;
+ * - or the producer overwrites old data in the buffer.
+ * Similarly, when an active consumer faces an empty buffer, it can:
+ * - block until there is data (producer must be active), only possible
+ * for software consumers;
+ * - walk away with no data; when the consumer is hardware, it must emit
+ * silence in this case.
+ *
+ * The model is defined below, note the asymmetry regarding the 'IDLE' state
+ * between input and output streams:
+ *
+ * Producer | Buffer state | Consumer | Applies | State
+ * active? | | active? | to |
+ * ==========|==============|==========|=========|==============================
+ * No | Empty | No | Both | STANDBY
+ * ----------|--------------|----------|---------|-----------------------------
+ * Yes | Filling up | No | Input | IDLE, overwrite behavior
+ * ----------|--------------|----------|---------|-----------------------------
+ * No | Empty | Yes† | Output | IDLE, h/w emits silence
+ * ----------|--------------|----------|---------|-----------------------------
+ * Yes | Not empty | Yes | Both | ACTIVE, s/w x-runs counted
+ * ----------|--------------|----------|---------|-----------------------------
+ * Yes | Filling up | No | Input | PAUSED, drop behavior
+ * ----------|--------------|----------|---------|-----------------------------
+ * Yes | Filling up | No† | Output | PAUSED, s/w stops writing once
+ * | | | | the buffer is filled up;
+ * | | | | h/w emits silence.
+ * ----------|--------------|----------|---------|-----------------------------
+ * No | Not empty | Yes | Both | DRAINING
+ * ----------|--------------|----------|---------|-----------------------------
+ * No | Not empty | No† | Output | DRAIN_PAUSED,
+ * | | | | h/w emits silence.
+ *
+ * † - note that for output, "buffer empty, h/w consuming" has the same outcome
+ * as "buffer not empty, h/w not consuming", but logically these conditions
+ * are different.
+ *
+ * State machines of both input and output streams start from the 'STANDBY'
+ * state. Transitions between states happen naturally with changes in the
+ * states of the model elements. For simplicity, we restrict the change to one
+ * element only, for example, in the 'STANDBY' state, either the producer or the
+ * consumer can become active, but not both at the same time. States 'STANDBY',
+ * 'IDLE', 'READY', and '*PAUSED' are "stable"—they require an external event,
+ * whereas a change from the 'DRAINING' state can happen with time as the buffer
+ * gets empty.
+ *
+ * The state machine for input streams is defined in the `stream-in-sm.gv` file,
+ * for output streams—in the `stream-out-sm.gv` file. State machines define how
+ * commands (from the enum 'CommandCode') trigger state changes. The full list
+ * of states and commands is defined by constants of the 'State' enum. Note that
+ * the 'CLOSED' state does not have a constant in the interface because the
+ * client can never observe a stream with a functioning command queue in this
+ * state. The 'ERROR' state is a special state which the state machine enters
+ * when an unrecoverable hardware error is detected by the HAL module.
*/
@JavaDerive(equals=true, toString=true)
@VintfStability
@@ -55,30 +122,97 @@
long timeNs;
}
- /**
- * The command used for audio I/O, see 'AudioBuffer'. For MMap No IRQ mode
- * this command only provides updated positions and latency because actual
- * audio I/O is done via the 'AudioBuffer.mmap' shared buffer.
- */
- const int COMMAND_BURST = 1;
+ @VintfStability
+ @Backing(type="int")
+ enum State {
+ /**
+ * 'STANDBY' is the initial state of the stream, entered after
+ * opening. Since both the producer and the consumer are inactive in
+ * this state, it allows the HAL module to put associated hardware into
+ * "standby" mode to save power.
+ */
+ STANDBY = 1,
+ /**
+ * In the 'IDLE' state the audio hardware is active. For input streams,
+ * the hardware is filling buffer with captured data, overwriting old
+ * contents on buffer wraparounds. For output streams, the buffer is
+ * still empty, and the hardware is outputting zeroes. The HAL module
+ * must not account for any under- or overruns as the client is not
+ * expected to perform audio I/O.
+ */
+ IDLE = 2,
+ /**
+ * The active state of the stream in which it handles audio I/O. The HAL
+ * module can assume that the audio I/O will be periodic, thus inability
+ * of the client to provide or consume audio data on time must be
+ * considered as an under- or overrun and indicated via the 'xrunFrames'
+ * field of the reply.
+ */
+ ACTIVE = 3,
+ /**
+ * In the 'PAUSED' state the consumer is inactive. For input streams,
+ * the hardware stops updating the buffer as soon as it fills up (this
+ * is the difference from the 'IDLE' state). For output streams,
+ * "inactivity" of hardware means that it does not consume audio data,
+ * but rather emits silence.
+ */
+ PAUSED = 4,
+ /**
+ * In the 'DRAINING' state the producer is inactive, the consumer is
+ * finishing up on the buffer contents, emptying it up. As soon as it
+ * gets empty, the stream transfers itself into the next state.
+ */
+ DRAINING = 5,
+ /**
+ * Used for output streams only, pauses draining. This state is similar
+ * to the 'PAUSED' state, except that the client is not adding any
+ * new data. If it emits a 'BURST' command, this brings the stream
+ * into the regular 'PAUSED' state.
+ */
+ DRAIN_PAUSED = 6,
+ /**
+ * The ERROR state is entered when the stream has encountered an
+ * irrecoverable error from the lower layer. After entering it, the
+ * stream can only be closed.
+ */
+ ERROR = 100,
+ }
/**
* Used for sending commands to the HAL module. The client writes into
* the queue, the HAL module reads. The queue can only contain a single
* command.
+ *
+ * Variants of type 'Void' correspond to commands without
+ * arguments. Variants of other types correspond to commands with an
+ * argument. Would in future a need for a command with multiple argument
+ * arise, a Parcelable type should be used for the corresponding variant.
*/
@VintfStability
@FixedSize
- parcelable Command {
+ union Command {
/**
- * One of COMMAND_* codes.
+ * Reserved for the HAL implementation to allow unblocking the wait on a
+ * command and exiting the I/O thread. A command of this variant must
+ * never be sent from the client side. To prevent that, the
+ * implementation must pass a random cookie as the command argument,
+ * which is only known to the implementation.
*/
- int code;
+ int hal_reserved_exit;
/**
- * For output streams: the amount of bytes that the client requests the
- * HAL module to read from the 'audio.fmq' queue.
- * For input streams: the amount of bytes requested by the client to
- * read from the hardware into the 'audio.fmq' queue.
+ * See the state machines on the applicability of this command to
+ * different states.
+ */
+ Void start;
+ /**
+ * The 'burst' command used for audio I/O, see 'AudioBuffer'. The value
+ * specifies:
+ *
+ * - for output streams: the amount of bytes that the client requests the
+ * HAL module to use out of the data contained in the 'audio.fmq' queue.
+ *
+ * - for input streams: the amount of bytes requested by the client to
+ * read from the hardware into the 'audio.fmq' queue.
*
* In both cases it is allowed for this field to contain any
* non-negative number. The value 0 can be used if the client only needs
@@ -90,12 +224,54 @@
* return the amount of actually read or written data via the
* 'Reply.fmqByteCount' field. Thus, only attempts to pass a negative
* number must be constituted as a client's error.
+ *
+ * Differences for the MMap No IRQ mode:
+ *
+ * - this command only provides updated positions and latency because
+ * actual audio I/O is done via the 'AudioBuffer.mmap' shared buffer.
+ * The client does not synchronize reads and writes into the buffer
+ * with sending of this command.
+ *
+ * - the value must always be set to 0.
*/
- int fmqByteCount;
+ int burst;
+ /**
+ * See the state machines on the applicability of this command to
+ * different states.
+ */
+ Void drain;
+ /**
+ * See the state machines on the applicability of this command to
+ * different states.
+ *
+ * Note that it's left on the discretion of the HAL implementation to
+ * assess all the necessary conditions that could prevent hardware from
+ * being suspended. Even if it can not be suspended, the state machine
+ * must still enter the 'STANDBY' state for consistency. Since the
+ * buffer must remain empty in this state, even if capturing hardware is
+ * still active, captured data must be discarded.
+ */
+ Void standby;
+ /**
+ * See the state machines on the applicability of this command to
+ * different states.
+ */
+ Void pause;
+ /**
+ * See the state machines on the applicability of this command to
+ * different states.
+ */
+ Void flush;
}
MQDescriptor<Command, SynchronizedReadWrite> command;
/**
+ * The value used for the 'Reply.latencyMs' field when the effective
+ * latency can not be reported by the HAL module.
+ */
+ const int LATENCY_UNKNOWN = -1;
+
+ /**
* Used for providing replies to commands. The HAL module writes into
* the queue, the client reads. The queue can only contain a single reply,
* corresponding to the last command sent by the client.
@@ -107,29 +283,42 @@
* One of Binder STATUS_* statuses:
* - STATUS_OK: the command has completed successfully;
* - STATUS_BAD_VALUE: invalid value in the 'Command' structure;
- * - STATUS_INVALID_OPERATION: the mix port is not connected
- * to any producer or consumer, thus
- * positions can not be reported;
+ * - STATUS_INVALID_OPERATION: the command is not applicable in the
+ * current state of the stream, or to this
+ * type of the stream;
+ * - STATUS_NO_INIT: positions can not be reported because the mix port
+ * is not connected to any producer or consumer, or
+ * because the HAL module does not support positions
+ * reporting for this AudioSource (on input streams).
* - STATUS_NOT_ENOUGH_DATA: a read or write error has
* occurred for the 'audio.fmq' queue;
- *
*/
int status;
/**
- * For output streams: the amount of bytes actually consumed by the HAL
- * module from the 'audio.fmq' queue.
+ * Used with the 'burst' command only.
+ *
+ * For output streams: the amount of bytes of data actually consumed
+ * by the HAL module.
* For input streams: the amount of bytes actually provided by the HAL
* in the 'audio.fmq' queue.
*
- * The returned value must not exceed the value passed in the
- * 'fmqByteCount' field of the corresponding command or be negative.
+ * The returned value must not exceed the value passed as the
+ * argument of the corresponding command, or be negative.
*/
int fmqByteCount;
/**
+ * It is recommended to report the current position for any command.
+ * If the position can not be reported, the 'status' field must be
+ * set to 'NO_INIT'.
+ *
* For output streams: the moment when the specified stream position
* was presented to an external observer (i.e. presentation position).
* For input streams: the moment when data at the specified stream position
* was acquired (i.e. capture position).
+ *
+ * The observable position must never be reset by the HAL module.
+ * The data type of the frame counter is large enough to support
+ * continuous counting for years of operation.
*/
Position observable;
/**
@@ -138,9 +327,22 @@
*/
Position hardware;
/**
- * Current latency reported by the hardware.
+ * Current latency reported by the hardware. It is recommended to
+ * report the current latency for any command. If the value of latency
+ * can not be determined, this field must be set to 'LATENCY_UNKNOWN'.
*/
int latencyMs;
+ /**
+ * Number of frames lost due to an underrun (for input streams),
+ * or not provided on time (for output streams) for the **previous**
+ * transfer operation.
+ */
+ int xrunFrames;
+ /**
+ * The state that the stream was in while the HAL module was sending the
+ * reply.
+ */
+ State state = State.STANDBY;
}
MQDescriptor<Reply, SynchronizedReadWrite> reply;
@@ -170,42 +372,59 @@
@VintfStability
union AudioBuffer {
/**
- * The fast message queue used for all modes except MMap No IRQ. Both
- * reads and writes into this queue are non-blocking because access to
- * this queue is synchronized via the 'command' and 'reply' queues as
- * described below. The queue nevertheless uses 'SynchronizedReadWrite'
- * because there is only one reader, and the reading position must be
- * shared.
+ * The fast message queue used for BURST commands in all modes except
+ * MMap No IRQ. Both reads and writes into this queue are non-blocking
+ * because access to this queue is synchronized via the 'command' and
+ * 'reply' queues as described below. The queue nevertheless uses
+ * 'SynchronizedReadWrite' because there is only one reader, and the
+ * reading position must be shared.
+ *
+ * Note that the fast message queue is a transient buffer, only used for
+ * data transfer. Neither of the sides can use it to store any data
+ * outside of the 'BURST' operation. The consumer must always retrieve
+ * all data available in the fast message queue, even if it can not use
+ * it. The producer must re-send any unconsumed data on the next
+ * transfer operation. This restriction is posed in order to make the
+ * fast message queue fully transparent from the latency perspective.
*
* For output streams the following sequence of operations is used:
* 1. The client writes audio data into the 'audio.fmq' queue.
- * 2. The client writes the 'BURST' command into the 'command' queue,
+ * 2. The client writes the BURST command into the 'command' queue,
* and hangs on waiting on a read from the 'reply' queue.
* 3. The high priority thread in the HAL module wakes up due to 2.
- * 4. The HAL module reads the command and audio data.
+ * 4. The HAL module reads the command and audio data. According
+ * to the statement above, the HAL module must always read
+ * from the FMQ all the data it contains. The amount of data that
+ * the HAL module has actually consumed is indicated to the client
+ * via the 'reply.fmqByteCount' field.
* 5. The HAL module writes the command status and current positions
* into 'reply' queue, and hangs on waiting on a read from
* the 'command' queue.
* 6. The client wakes up due to 5. and reads the reply.
*
* For input streams the following sequence of operations is used:
- * 1. The client writes the 'BURST' command into the 'command' queue,
+ * 1. The client writes the BURST command into the 'command' queue,
* and hangs on waiting on a read from the 'reply' queue.
* 2. The high priority thread in the HAL module wakes up due to 1.
* 3. The HAL module writes audio data into the 'audio.fmq' queue.
+ * The value of 'reply.fmqByteCount' must be the equal to the amount
+ * of data in the queue.
* 4. The HAL module writes the command status and current positions
* into 'reply' queue, and hangs on waiting on a read from
* the 'command' queue.
* 5. The client wakes up due to 4.
- * 6. The client reads the reply and audio data.
+ * 6. The client reads the reply and audio data. The client must
+ * always read from the FMQ all the data it contains.
+ *
*/
MQDescriptor<byte, SynchronizedReadWrite> fmq;
/**
* MMap buffers are shared directly with the DSP, which operates
- * independently from the CPU. Writes and reads into these buffers
- * are not synchronized with 'command' and 'reply' queues. However,
- * the client still uses the 'BURST' command for obtaining current
- * positions from the HAL module.
+ * independently from the CPU. Writes and reads into these buffers are
+ * not synchronized with 'command' and 'reply' queues. However, the
+ * client still uses the same commands for controlling the audio data
+ * exchange and for obtaining current positions and latency from the HAL
+ * module.
*/
MmapBufferDescriptor mmap;
}
diff --git a/audio/aidl/android/hardware/audio/core/SurroundSoundConfig.aidl b/audio/aidl/android/hardware/audio/core/SurroundSoundConfig.aidl
new file mode 100644
index 0000000..eeda12a
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/SurroundSoundConfig.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.core;
+
+import android.media.audio.common.AudioFormatDescription;
+
+/**
+ * SurroundSoundConfig defines the multi-channel formats that can be enabled on
+ * (primarily TV) devices.
+ */
+@JavaDerive(equals=true, toString=true)
+@VintfStability
+parcelable SurroundSoundConfig {
+ @VintfStability
+ parcelable SurroundFormatFamily {
+ /**
+ * A primaryFormat shall get an entry in the Surround Settings dialog on TV
+ * devices. There must be a corresponding Java ENCODING_... constant
+ * defined in AudioFormat.java, and a display name defined in
+ * AudioFormat.toDisplayName.
+ */
+ AudioFormatDescription primaryFormat;
+ /**
+ * List of formats that shall be equivalent to the primaryFormat from the
+ * users' point of view and don't need a dedicated Surround Settings
+ * dialog entry.
+ */
+ AudioFormatDescription[] subFormats;
+ }
+ SurroundFormatFamily[] formatFamilies;
+}
diff --git a/audio/aidl/android/hardware/audio/core/stream-in-sm.gv b/audio/aidl/android/hardware/audio/core/stream-in-sm.gv
new file mode 100644
index 0000000..805dc32
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/stream-in-sm.gv
@@ -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.
+
+// To render: dot -Tpng stream-in-sm.gv -o stream-in-sm.png
+digraph stream_in_state_machine {
+ node [shape=doublecircle style=filled fillcolor=black width=0.5] I;
+ node [shape=point width=0.5] F;
+ node [shape=oval width=1];
+ node [fillcolor=lightgreen] STANDBY; // buffer is empty
+ node [fillcolor=tomato] CLOSED;
+ node [fillcolor=tomato] ERROR;
+ node [style=dashed] ANY_STATE;
+ node [fillcolor=lightblue style=filled];
+ I -> STANDBY;
+ STANDBY -> IDLE [label="start"]; // producer -> active
+ IDLE -> STANDBY [label="standby"]; // producer -> passive, buffer is cleared
+ IDLE -> ACTIVE [label="burst"]; // consumer -> active
+ ACTIVE -> ACTIVE [label="burst"];
+ ACTIVE -> PAUSED [label="pause"]; // consumer -> passive
+ ACTIVE -> DRAINING [label="drain"]; // producer -> passive
+ PAUSED -> ACTIVE [label="burst"]; // consumer -> active
+ PAUSED -> STANDBY [label="flush"]; // producer -> passive, buffer is cleared
+ DRAINING -> DRAINING [label="burst"];
+ DRAINING -> ACTIVE [label="start"]; // producer -> active
+ DRAINING -> STANDBY [label="<empty buffer>"]; // consumer deactivates
+ IDLE -> ERROR [label="<hardware failure>"];
+ ACTIVE -> ERROR [label="<hardware failure>"];
+ PAUSED -> ERROR [label="<hardware failure>"];
+ ANY_STATE -> CLOSED [label="→IStream*.close"];
+ CLOSED -> F;
+}
diff --git a/audio/aidl/android/hardware/audio/core/stream-out-sm.gv b/audio/aidl/android/hardware/audio/core/stream-out-sm.gv
new file mode 100644
index 0000000..6aa5c61
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/stream-out-sm.gv
@@ -0,0 +1,48 @@
+// 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.
+
+// To render: dot -Tpng stream-out-sm.gv -o stream-out-sm.png
+digraph stream_out_state_machine {
+ node [shape=doublecircle style=filled fillcolor=black width=0.5] I;
+ node [shape=point width=0.5] F;
+ node [shape=oval width=1];
+ node [fillcolor=lightgreen] STANDBY; // buffer is empty
+ node [fillcolor=lightgreen] IDLE; // buffer is empty
+ node [fillcolor=tomato] CLOSED;
+ node [fillcolor=tomato] ERROR;
+ node [style=dashed] ANY_STATE;
+ node [fillcolor=lightblue style=filled];
+ I -> STANDBY;
+ STANDBY -> IDLE [label="start"]; // consumer -> active
+ STANDBY -> PAUSED [label="burst"]; // producer -> active
+ IDLE -> STANDBY [label="standby"]; // consumer -> passive
+ IDLE -> ACTIVE [label="burst"]; // producer -> active
+ ACTIVE -> ACTIVE [label="burst"];
+ ACTIVE -> PAUSED [label="pause"]; // consumer -> passive (not consuming)
+ ACTIVE -> DRAINING [label="drain"]; // producer -> passive
+ PAUSED -> PAUSED [label="burst"];
+ PAUSED -> ACTIVE [label="start"]; // consumer -> active
+ PAUSED -> IDLE [label="flush"]; // producer -> passive, buffer is cleared
+ DRAINING -> IDLE [label="<empty buffer>"];
+ DRAINING -> ACTIVE [label="burst"]; // producer -> active
+ DRAINING -> DRAIN_PAUSED [label="pause"]; // consumer -> passive (not consuming)
+ DRAIN_PAUSED -> DRAINING [label="start"]; // consumer -> active
+ DRAIN_PAUSED -> PAUSED [label="burst"]; // producer -> active
+ DRAIN_PAUSED -> IDLE [label="flush"]; // buffer is cleared
+ IDLE -> ERROR [label="<hardware failure>"];
+ ACTIVE -> ERROR [label="<hardware failure>"];
+ DRAINING -> ERROR [label="<hardware failure>"];
+ ANY_STATE -> CLOSED [label="→IStream*.close"];
+ CLOSED -> F;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/BassBoost.aidl b/audio/aidl/android/hardware/audio/effect/BassBoost.aidl
new file mode 100644
index 0000000..810c188
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/BassBoost.aidl
@@ -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.
+ */
+
+package android.hardware.audio.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * Bass boost is an audio effect to boost or amplify low frequencies of the sound. It is comparable
+ * to a simple equalizer but limited to one band amplification in the low frequency range.
+ *
+ * All parameters defined in union BassBoost must be gettable and settable. The capabilities defined
+ * in BassBoost.Capability can only acquired with IEffect.getDescriptor() and not settable.
+ */
+@VintfStability
+union BassBoost {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ BassBoost.Tag commonTag;
+ }
+
+ /**
+ * Vendor BassBoost implementation definition for additional parameters.
+ */
+ VendorExtension vendor;
+
+ /**
+ * Capability supported by BassBoost implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ /**
+ * BassBoost capability extension, vendor can use this extension in case existing capability
+ * definition not enough.
+ */
+ ParcelableHolder extension;
+ /**
+ * Indicates whether setting strength is supported. False value indicates only one strength
+ * is supported and setParameter() method will return EX_ILLEGAL_ARGUMENT.
+ */
+ boolean strengthSupported;
+ }
+
+ /**
+ * The per mille strength of the bass boost effect.
+ *
+ * If the implementation does not support per mille accuracy for setting the strength, it is
+ * allowed to round the given strength to the nearest supported value. In this case {@link
+ * #IEffect.getParameter()} method should return the rounded value that was actually set.
+ *
+ * The valid range for strength is [0, 1000].
+ */
+ int strengthPm;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Capability.aidl b/audio/aidl/android/hardware/audio/effect/Capability.aidl
new file mode 100644
index 0000000..f741f33
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Capability.aidl
@@ -0,0 +1,61 @@
+/*
+ * 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.effect;
+
+import android.hardware.audio.effect.BassBoost;
+import android.hardware.audio.effect.Downmix;
+import android.hardware.audio.effect.DynamicsProcessing;
+import android.hardware.audio.effect.Equalizer;
+import android.hardware.audio.effect.HapticGenerator;
+import android.hardware.audio.effect.LoudnessEnhancer;
+import android.hardware.audio.effect.Reverb;
+import android.hardware.audio.effect.VendorExtension;
+import android.hardware.audio.effect.Virtualizer;
+import android.hardware.audio.effect.Visualizer;
+import android.hardware.audio.effect.Volume;
+
+/**
+ * Effect capability definitions.
+ * This data structure is used as part of effect Descriptor to identify effect capabilities which
+ * not meant to change at runtime.
+ */
+@VintfStability
+union Capability {
+ /**
+ * Vendor defined effect capability.
+ * This extension can be used when vendor have a new effect implementated and need
+ * capability definition for this new type of effect.
+ * If vendor want to extend existing effect capabilities, it is recommended to expose though
+ * the ParcelableHolder in each effect capability definition. For example:
+ * Equalizer.Capability.extension.
+ */
+ VendorExtension vendorExtension;
+
+ /**
+ * Effect capabilities.
+ */
+ BassBoost.Capability bassBoost;
+ Downmix.Capability downmix;
+ DynamicsProcessing.Capability dynamicsProcessing;
+ Equalizer.Capability equalizer;
+ HapticGenerator.Capability hapticGenerator;
+ LoudnessEnhancer.Capability loudnessEnhancer;
+ Reverb.Capability reverb;
+ Virtualizer.Capability virtualizer;
+ Visualizer.Capability visualizer;
+ Volume.Capability volume;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/CommandId.aidl b/audio/aidl/android/hardware/audio/effect/CommandId.aidl
new file mode 100644
index 0000000..d940b42
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/CommandId.aidl
@@ -0,0 +1,75 @@
+/*
+ * 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.effect;
+
+/**
+ * Defines all commands supported by the effect instance.
+ *
+ * There are three groups of commands:
+ * 1. Common part which MUST be supported by all effects.
+ * 2. Commands MUST be supported by a specific type of effect.
+ * 3. Extension commands for vendor.
+ */
+@VintfStability
+@Backing(type="int")
+enum CommandId {
+ /**
+ * Commands MUST be supported by all effects.
+ */
+ /**
+ * Start effect engine processing.
+ * An effect instance must start processing data and transfer to PROCESSING state if it is in
+ * IDLE state and have all necessary information. Otherwise it must:
+ * 1. Throw a EX_ILLEGAL_STATE exception if effect is not in IDLE state, or
+ * 2. Throw a EX_TRANSACTION_FAILED for all other errors.
+ *
+ * Depending on parameters set to the effect instance, effect may do process or reverse
+ * process after START command.
+ */
+ START = 0,
+ /**
+ * Stop effect engine processing with all resource kept.
+ * The currently processed audio data will be discarded if the effect engine is in PROCESSING
+ * state.
+ * Effect instance must do nothing and return ok when it receive STOP command in IDLE state.
+ */
+ STOP = 1,
+ /**
+ * Keep all parameter settings but reset the buffer content, stop engine processing, and transit
+ * instance state to IDLE if its in PROCESSING state.
+ * Effect instance must be able to handle RESET command at IDLE and PROCESSING states.
+ */
+ RESET = 2,
+
+ /**
+ * Commands MUST be supported by a specific type of effect.
+ */
+
+ /**
+ * Extension commands for vendor.
+ */
+ VENDOR_COMMAND_0 = 0x100,
+ VENDOR_COMMAND_1,
+ VENDOR_COMMAND_2,
+ VENDOR_COMMAND_3,
+ VENDOR_COMMAND_4,
+ VENDOR_COMMAND_5,
+ VENDOR_COMMAND_6,
+ VENDOR_COMMAND_7,
+ VENDOR_COMMAND_8,
+ VENDOR_COMMAND_9,
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
index 51b31c2..47c88dc 100644
--- a/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
+++ b/audio/aidl/android/hardware/audio/effect/Descriptor.aidl
@@ -16,43 +16,77 @@
package android.hardware.audio.effect;
+import android.hardware.audio.effect.Capability;
+import android.hardware.audio.effect.Flags;
import android.media.audio.common.AudioUuid;
/**
- * Effect descriptor contains all information (capabilities, attributes, and ownership) for an
- * effect implemented in the Audio Effect HAL. Framework uses this information to decide when and
- * how to apply the effect.
+ * Descriptor contains all information (capabilities, attributes, etc) for an effect implementation.
+ * The client uses this information to decide when and how to apply an effect implementation.
+ *
+ * Each type of effect can have more than one implementation (differentiated by implementation
+ * UUID), the effect proxy act as a combination of two implementations (usually one software and
+ * one offload implementation), so effect processing can be seamlessly switched between
+ * implementations in same proxy depending on the configuration and/or use case. If the optional
+ * proxy UUID is specified in Descriptor.Identity, then client must consider the effect instance as
+ * part of the effect proxy.
*/
@VintfStability
parcelable Descriptor {
/**
* UUID for effect types, these definitions are in sync with SDK, see @c AudioEffect.java.
*/
- // UUID for environmental reverberation effect type.
+ /**
+ * UUID for environmental reverberation effect type.
+ */
const String EFFECT_TYPE_UUID_ENV_REVERB = "c2e5d5f0-94bd-4763-9cac-4e234d06839e";
- // UUID for preset reverberation effect type.
+ /**
+ * UUID for preset reverberation effect type.
+ */
const String EFFECT_TYPE_UUID_PRESET_REVERB = "47382d60-ddd8-11db-bf3a-0002a5d5c51b";
- // UUID for equalizer effect type.
+ /**
+ * UUID for equalizer effect type.
+ */
const String EFFECT_TYPE_UUID_EQUALIZER = "0bed4300-ddd6-11db-8f34-0002a5d5c51b";
- // UUID for bass boost effect type.
+ /**
+ * UUID for bass boost effect type.
+ */
const String EFFECT_TYPE_UUID_BASS_BOOST = "0634f220-ddd4-11db-a0fc-0002a5d5c51b";
- // UUID for virtualizer effect type.
+ /**
+ * UUID for virtualizer effect type.
+ */
const String EFFECT_TYPE_UUID_VIRTUALIZER = "37cc2c00-dddd-11db-8577-0002a5d5c51b";
- // UUID for Automatic Gain Control (AGC) type.
+ /**
+ * UUID for Automatic Gain Control (AGC) type.
+ */
const String EFFECT_TYPE_UUID_AGC = "0a8abfe0-654c-11e0-ba26-0002a5d5c51b";
- // UUID for Acoustic Echo Canceler (AEC) type.
+ /**
+ * UUID for Acoustic Echo Canceler (AEC) type.
+ */
const String EFFECT_TYPE_UUID_AEC = "7b491460-8d4d-11e0-bd61-0002a5d5c51b";
- // UUID for Noise Suppressor (NS) type.
+ /**
+ * UUID for Noise Suppressor (NS) type.
+ */
const String EFFECT_TYPE_UUID_NS = "58b4b260-8e06-11e0-aa8e-0002a5d5c51b";
- // UUID for Loudness Enhancer type.
+ /**
+ * UUID for Loudness Enhancer type.
+ */
const String EFFECT_TYPE_UUID_LOUDNESS_ENHANCER = "fe3199be-aed0-413f-87bb-11260eb63cf1";
- // UUID for Dynamics Processing type.
+ /**
+ * UUID for Dynamics Processing type.
+ */
const String EFFECT_TYPE_UUID_DYNAMICS_PROCESSING = "7261676f-6d75-7369-6364-28e2fd3ac39e";
- // UUID for Haptic Generator type.
+ /**
+ * UUID for Haptic Generator type.
+ */
const String EFFECT_TYPE_UUID_HAPTIC_GENERATOR = "1411e6d6-aecd-4021-a1cf-a6aceb0d71e5";
- // UUID for Spatializer type.
+ /**
+ * UUID for Spatializer type.
+ */
const String EFFECT_TYPE_UUID_SPATIALIZER = "ccd4cf09-a79d-46c2-9aae-06a1698d6c8f";
- // UUID for Volume type. The volume effect is used for automated tests only.
+ /**
+ * UUID for Volume type. The volume effect is used for automated tests only.
+ */
const String EFFECT_TYPE_UUID_VOLUME = "09e8ede0-ddde-11db-b4f6-0002a5d5c51b";
/**
@@ -68,15 +102,48 @@
* UUID for this particular implementation.
*/
AudioUuid uuid;
+ /**
+ * Optional proxy UUID. This field must be set to the proxy effect type UUID if the effect
+ * implementation is part of a proxy effect.
+ */
+ @nullable AudioUuid proxy;
}
- // Common attributes of all effect implementation.
+ /**
+ * Common attributes of all effect implementation.
+ */
@VintfStability
parcelable Common {
/**
* Identity of effect implementation.
*/
Identity id;
+ /**
+ * Capability flags defined for the effect implementation.
+ */
+ Flags flags;
+ /**
+ * CPU load indication expressed in 0.1 MIPS units as estimated on an ARM9E core (ARMv5TE)
+ * with 0 WS.
+ */
+ int cpuLoad;
+ /**
+ * Data memory usage expressed in KB and includes only dynamically allocated memory.
+ */
+ int memoryUsage;
+ /**
+ * Human readable effect name, no intended to display on UI directly.
+ */
+ @utf8InCpp String name;
+ /**
+ * Human readable effect implementor name, no intended to display on UI directly.
+ */
+ @utf8InCpp String implementor;
}
Common common;
+
+ /**
+ * Effect implementation capability.
+ */
+ Capability capability;
}
diff --git a/audio/aidl/android/hardware/audio/effect/Downmix.aidl b/audio/aidl/android/hardware/audio/effect/Downmix.aidl
new file mode 100644
index 0000000..ee57baf
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Downmix.aidl
@@ -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.
+ */
+
+package android.hardware.audio.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * Downmix specific definitions.
+ *
+ * All parameters defined in union Downmix must be gettable and settable. The capabilities defined
+ * in Downmix.Capability can only acquired with IEffect.getDescriptor() and not settable.
+ */
+@VintfStability
+union Downmix {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ Downmix.Tag commonTag;
+ }
+
+ /**
+ * Vendor Downmix implementation definition for additional parameters.
+ */
+ VendorExtension vendor;
+
+ /**
+ * Capability supported by Downmix implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ /**
+ * Downmix capability extension, vendor can use this extension in case existing capability
+ * definition not enough.
+ */
+ ParcelableHolder extension;
+ }
+
+ @VintfStability
+ enum Type {
+ /**
+ * Throw away the extra channels.
+ */
+ STRIP,
+ /**
+ * Mix the extra channels with FL/FR.
+ */
+ FOLD,
+ }
+
+ /**
+ * Type of downmix.
+ */
+ Type type;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl b/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl
new file mode 100644
index 0000000..ee5dcad
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/DynamicsProcessing.aidl
@@ -0,0 +1,301 @@
+/*
+ * 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.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * DynamicsProcessing specific definitions.
+ *
+ * All parameters defined in union DynamicsProcessing must be gettable and settable. The
+ * capabilities defined in DynamicsProcessing.Capability can only acquired with
+ * IEffect.getDescriptor() and not settable.
+ */
+@VintfStability
+union DynamicsProcessing {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ DynamicsProcessing.Tag commonTag;
+ }
+
+ /**
+ * Vendor DynamicsProcessing implementation definition for additional parameters.
+ */
+ VendorExtension vendorExtension;
+
+ /**
+ * Capability supported by DynamicsProcessing implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ /**
+ * DynamicsProcessing capability extension, vendor can use this extension in case existing
+ * capability definition not enough.
+ */
+ ParcelableHolder extension;
+ }
+
+ /**
+ * Resolution preference definition.
+ */
+ enum ResolutionPreference {
+ /**
+ * Favors frequency domain based implementation.
+ */
+ FAVOR_FREQUENCY_RESOLUTION,
+ /**
+ * Favors tme domain based implementation.
+ */
+ FAVOR_TIME_RESOLUTION,
+ }
+
+ /**
+ * Band enablement configuration.
+ */
+ @VintfStability
+ parcelable BandEnablement {
+ /**
+ * True if multi-band stage is in use.
+ */
+ boolean inUse;
+ /**
+ * Number of bands configured for this stage.
+ */
+ int bandCount;
+ }
+
+ /**
+ * Effect engine configuration. Set the enablement of all stages.
+ */
+ @VintfStability
+ parcelable EngineArchitecture {
+ /**
+ * Resolution preference.
+ */
+ ResolutionPreference resolutionPreference = ResolutionPreference.FAVOR_FREQUENCY_RESOLUTION;
+ /**
+ * Preferred frame duration in milliseconds (ms).
+ */
+ float preferredFrameDurationMs;
+ /**
+ * PreEq stage (Multi-band Equalizer) configuration.
+ */
+ BandEnablement preEqBand;
+ /**
+ * PostEq stage (Multi-band Equalizer) configuration.
+ */
+ BandEnablement postEqBand;
+ /**
+ * MBC stage (Multi-band Compressor) configuration.
+ */
+ BandEnablement mbcBand;
+ /**
+ * True if Limiter stage is in use.
+ */
+ boolean limiterInUse;
+ }
+
+ /**
+ * Band enablement configuration for a specific channel.
+ */
+ @VintfStability
+ parcelable BandChannelConfig {
+ /**
+ * Channel index.
+ */
+ int channel;
+ /**
+ * Channel index.
+ */
+ BandEnablement enablement;
+ }
+
+ /**
+ * Equalizer band configuration for a specific channel and band.
+ */
+ @VintfStability
+ parcelable EqBandConfig {
+ /**
+ * Channel index.
+ */
+ int channel;
+ /**
+ * Band index, must in the range of [0, bandCount-1].
+ */
+ int band;
+ /**
+ * True if EQ stage is enabled.
+ */
+ boolean enable;
+ /**
+ * Topmost frequency number (in Hz) this band will process.
+ */
+ float cutoffFrequency;
+ /**
+ * Gain factor in decibels (dB).
+ */
+ float gain;
+ }
+
+ /**
+ * MBC configuration for a specific channel and band.
+ */
+ @VintfStability
+ parcelable MbcBandConfig {
+ /**
+ * Channel index.
+ */
+ int channel;
+ /**
+ * Band index, must in the range of [0, bandCount-1].
+ */
+ int band;
+ /**
+ * True if MBC stage is enabled.
+ */
+ boolean enable;
+ /**
+ * Topmost frequency number (in Hz) this band will process.
+ */
+ float cutoffFrequencyHz;
+ /**
+ * Gain factor in decibels (dB).
+ */
+ float gainDb;
+ /**
+ * Attack Time for compressor in milliseconds (ms).
+ */
+ float attackTimeMs;
+ /**
+ * Release Time for compressor in milliseconds (ms).
+ */
+ float releaseTimeMs;
+ /**
+ * Compressor ratio (N:1) (input:output).
+ */
+ float ratio;
+ /**
+ * Compressor threshold measured in decibels (dB) from 0 dB Full Scale (dBFS).
+ */
+ float thresholdDb;
+ /**
+ * Width in decibels (dB) around compressor threshold point.
+ */
+ float kneeWidthDb;
+ /**
+ * Noise gate threshold in decibels (dB) from 0 dB Full Scale (dBFS).
+ */
+ float noiseGateThresholdDb;
+ /**
+ * Expander ratio (1:N) (input:output) for signals below the Noise Gate Threshold.
+ */
+ float expanderRatio;
+ /**
+ * Gain applied to the signal BEFORE the compression in dB.
+ */
+ float preGainDb;
+ /**
+ * Gain applied to the signal AFTER compression in dB.
+ */
+ float postGainDb;
+ }
+
+ /**
+ * Limiter configuration for a specific channel.
+ */
+ @VintfStability
+ parcelable LimiterConfig {
+ /**
+ * Channel index.
+ */
+ int channel;
+ /**
+ * True if Limiter stage is enabled.
+ */
+ boolean enable;
+ /**
+ * True if Limiter stage is in use.
+ */
+ boolean inUse;
+ /**
+ * Index of group assigned to this Limiter. Only limiters that share the same linkGroup
+ * index will react together.
+ */
+ int linkGroup;
+ /**
+ * Attack Time for compressor in milliseconds (ms).
+ */
+ float attackTimeMs;
+ /**
+ * Release Time for compressor in milliseconds (ms).
+ */
+ float releaseTimeMs;
+ /**
+ * Compressor ratio (N:1) (input:output).
+ */
+ float ratio;
+ /**
+ * Compressor threshold measured in decibels (dB) from 0 dB Full Scale (dBFS).
+ */
+ float thresholdDb;
+ /**
+ * Gain applied to the signal AFTER compression in dB.
+ */
+ float postGainDb;
+ }
+
+ /**
+ * Effect engine architecture.
+ */
+ EngineArchitecture engineArchitecture;
+ /**
+ * PreEq stage per channel configuration.
+ */
+ BandChannelConfig preEq;
+ /**
+ * PostEq stage per channel configuration.
+ */
+ BandChannelConfig postEq;
+ /**
+ * PreEq stage per band configuration.
+ */
+ EqBandConfig preEqBand;
+ /**
+ * PostEq stage per band configuration.
+ */
+ EqBandConfig postEqBand;
+ /**
+ * MBC stage per channel configuration.
+ */
+ BandChannelConfig mbc;
+ /**
+ * PostEq stage per band configuration.
+ */
+ MbcBandConfig mbcBand;
+ /**
+ * Limiter stage configuration.
+ */
+ LimiterConfig limiter;
+ /**
+ * Input gain factor in decibels (dB). 0 dB means no change in level.
+ */
+ float inputGainDb;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Equalizer.aidl b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl
new file mode 100644
index 0000000..79a1c4f
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Equalizer.aidl
@@ -0,0 +1,104 @@
+/*
+ * 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.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * Equalizer specific definitions.
+ *
+ * All parameters defined in union Equalizer must be gettable and settable. The capabilities defined
+ * in Equalizer.Capability can only acquired with IEffect.getDescriptor() and not settable.
+ */
+@VintfStability
+union Equalizer {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ Equalizer.Tag commonTag;
+ }
+
+ /**
+ * Vendor Equalizer implementation definition for additional parameters.
+ */
+ VendorExtension vendorExtension;
+
+ /**
+ * Capability MUST be supported by Equalizer implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ /**
+ * Equalizer capability extension, vendor can use this extension in case existing capability
+ * definition not enough.
+ */
+ ParcelableHolder extension;
+
+ /**
+ * Bands frequency ranges supported.
+ */
+ BandFrequency[] bandFrequencies;
+
+ /**
+ * Presets name and index.
+ */
+ Preset[] presets;
+ }
+
+ /**
+ * Level setting for each band in millibels.
+ */
+ @VintfStability
+ parcelable BandLevel {
+ int index;
+ int levelMb;
+ }
+
+ /**
+ * Supported minimal and maximal frequency for each band in millihertz.
+ */
+ @VintfStability
+ parcelable BandFrequency {
+ int index;
+ int minMh;
+ int maxMh;
+ }
+
+ /**
+ * Factory presets supported.
+ */
+ @VintfStability
+ parcelable Preset {
+ int index;
+ /**
+ * Preset name, used to identify presets but no intended to display on UI directly.
+ */
+ @utf8InCpp String name;
+ }
+
+ /**
+ * Level for each band.
+ */
+ BandLevel[] bandLevels;
+ /**
+ * Index of current preset.
+ */
+ int preset;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Flags.aidl b/audio/aidl/android/hardware/audio/effect/Flags.aidl
new file mode 100644
index 0000000..f449c2d
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Flags.aidl
@@ -0,0 +1,147 @@
+/*
+ * 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.effect;
+
+/**
+ * Some common capability for an effect instance.
+ */
+@VintfStability
+parcelable Flags {
+ /**
+ * Type of connection.
+ */
+ @VintfStability
+ @Backing(type="byte")
+ enum Type {
+ /**
+ * After track process.
+ */
+ INSERT = 0,
+ /**
+ * Connect to track auxiliary output and use send level.
+ */
+ AUXILIARY = 1,
+ /**
+ * Rreplaces track process function; must implement SRC, volume and mono to stereo.
+ */
+ REPLACE = 2,
+ /**
+ * Applied below audio HAL on in.
+ */
+ PRE_PROC = 3,
+ /**
+ * Applied below audio HAL on out.
+ */
+ POST_PROC = 4,
+ }
+ Type type = Type.INSERT;
+
+ /**
+ * Insertion preference.
+ */
+ @VintfStability
+ @Backing(type="byte")
+ enum Insert {
+ ANY = 0,
+ /**
+ * First of the chain.
+ */
+ FIRST = 1,
+ /**
+ * Last of the chain.
+ */
+ LAST = 2,
+ /**
+ * Exclusive (only effect in the insert chain.
+ */
+ EXCLUSIVE = 3,
+ }
+ Insert insert = Insert.ANY;
+
+ @VintfStability
+ @Backing(type="byte")
+ enum Volume {
+ NONE = 0,
+ /**
+ * Implements volume control.
+ */
+ CTRL = 1,
+ /**
+ * Requires volume indication.
+ */
+ IND = 2,
+ /**
+ * Monitors requested volume.
+ */
+ MONITOR = 3,
+ }
+ Volume volume = Volume.NONE;
+
+ @VintfStability
+ @Backing(type="byte")
+ enum HardwareAccelerator {
+ /**
+ * No hardware acceleration
+ */
+ NONE = 0,
+ /**
+ * Non tunneled hw acceleration: effect reads the samples, send them to HW accelerated
+ * effect processor, reads back the processed samples and returns them to the output buffer.
+ */
+ SIMPLE = 1,
+ /**
+ * The effect interface is only used to control the effect engine. This mode is relevant for
+ * global effects actually applied by the audio hardware on the output stream.
+ */
+ TUNNEL = 2,
+ }
+ HardwareAccelerator hwAcceleratorMode = HardwareAccelerator.NONE;
+
+ /**
+ * Effect instance set this flag to true if it requires update on if the playback thread the
+ * effect attached to is offloaded or not. In this case the framework must call
+ * IEffect.setParameter(Parameter.offload) to notify effect instance when playback thread
+ * offload changes.
+ */
+ boolean offloadIndication;
+
+ /**
+ * Effect instance set this flag to true if it requires device change update. In this case the
+ * framework must call IEffect.setParameter(Parameter.device) to notify effect instance when the
+ * device changes.
+ */
+ boolean deviceIndication;
+
+ /**
+ * Effect instance set this flag to true if it requires audio mode change update. In this case
+ * the framework must call IEffect.setParameter(Parameter.mode) to notify effect instance when
+ * the audio mode changes.
+ */
+ boolean audioModeIndication;
+
+ /**
+ * Effect instance set this flag to true if it requires audio source change update. In this case
+ * the framework must call IEffect.setParameter(Parameter.source) to notify effect instance when
+ * the audio source changes.
+ */
+ boolean audioSourceIndication;
+
+ /**
+ * Set to true if no processing done for this effect instance.
+ */
+ boolean noProcessing;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl b/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl
new file mode 100644
index 0000000..944155f
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl
@@ -0,0 +1,95 @@
+/*
+ * 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.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * HapticGenerator specific definitions. HapticGenerator effect provide HapticGenerator control and
+ * mute/unmute functionality.
+ *
+ * All parameters defined in union HapticGenerator must be gettable and settable. The capabilities
+ * defined in HapticGenerator.Capability can only acquired with IEffect.getDescriptor() and not
+ * settable.
+ */
+@VintfStability
+union HapticGenerator {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ HapticGenerator.Tag commonTag;
+ }
+
+ /**
+ * Vendor HapticGenerator implementation definition for additional parameters.
+ */
+ VendorExtension vendorExtension;
+
+ /**
+ * Capability supported by HapticGenerator implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ /**
+ * HapticGenerator capability extension, vendor can use this extension in case existing
+ * capability definition not enough.
+ */
+ VendorExtension extension;
+ }
+
+ @VintfStability
+ @Backing(type="int")
+ enum VibratorScale {
+ MUTE = -100,
+ VERY_LOW = -2,
+ LOW = -1,
+ NONE = 0,
+ HIGH = 1,
+ VERY_HIGH = 2,
+ }
+
+ @VintfStability
+ parcelable HapticScale {
+ /**
+ * Audio track ID.
+ */
+ int id;
+ /**
+ * Haptic intensity.
+ */
+ VibratorScale scale = VibratorScale.MUTE;
+ }
+
+ /**
+ * Vibrator information including resonant frequency, Q factor.
+ */
+ @VintfStability
+ parcelable VibratorInformation {
+ /**
+ * Resonant frequency in Hz.
+ */
+ float resonantFrequencyHz;
+ float qFactor;
+ float maxAmplitude;
+ }
+
+ HapticScale hapticScale;
+ VibratorInformation vibratorInfo;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/IEffect.aidl b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
index d7a9501..3b957d7 100644
--- a/audio/aidl/android/hardware/audio/effect/IEffect.aidl
+++ b/audio/aidl/android/hardware/audio/effect/IEffect.aidl
@@ -16,24 +16,80 @@
package android.hardware.audio.effect;
+import android.hardware.audio.effect.CommandId;
import android.hardware.audio.effect.Descriptor;
+import android.hardware.audio.effect.Parameter;
+import android.hardware.audio.effect.State;
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
/**
* Effect interfaces definitions to configure and control the effect instance.
*/
@VintfStability
interface IEffect {
+ @VintfStability
+ @FixedSize
+ parcelable Status {
+ /**
+ * One of Binder STATUS_* statuses:
+ * - STATUS_OK: the command has completed successfully;
+ * - STATUS_BAD_VALUE: invalid value in the 'Command' structure;
+ * - STATUS_INVALID_OPERATION: the mix port is not connected
+ * to any producer or consumer, thus
+ * positions can not be reported;
+ * - STATUS_NOT_ENOUGH_DATA: a read or write error has
+ * occurred for the 'audio.fmq' queue;
+ *
+ */
+ int status;
+ /**
+ * The amount of audio data samples in the floating point format consumed by the effect
+ * instance.
+ */
+ int fmqConsumed;
+ /**
+ * The amount of audio data samples in the floating point format produced by the effect
+ * instance.
+ */
+ int fmqProduced;
+ }
+
/**
- * Open an effect instance, effect should not start processing data before receive START
- * command. All necessary information should be allocated and instance should transfer to IDLE
- * state after open() call has been handled successfully.
- * After open, the effect instance should be able to handle all IEffect interface calls.
+ * Return data structure of IEffect.open() interface.
+ */
+ @VintfStability
+ parcelable OpenEffectReturn {
+ /**
+ * Message queue for effect processing status.
+ */
+ MQDescriptor<Status, SynchronizedReadWrite> statusMQ;
+ /**
+ * Message queue for input data buffer.
+ */
+ MQDescriptor<float, SynchronizedReadWrite> inputDataMQ;
+ /**
+ * Message queue for output data buffer.
+ */
+ MQDescriptor<float, SynchronizedReadWrite> outputDataMQ;
+ }
+
+ /**
+ * Open an effect instance, effect must not start processing data before receive
+ * CommandId::START command. All necessary information should be allocated and instance must
+ * transfer to State::IDLE state after open() call has been handled successfully. After open,
+ * the effect instance must be able to handle all IEffect interface calls.
*
+ * @param common Parameters which MUST pass from client at open time.
+ * @param specific Effect specific parameters which can optional pass from client at open time.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported command.
* @throws a EX_UNSUPPORTED_OPERATION if device capability/resource is not enough or system
* failure happens.
* @note Open an already-opened effect instance should do nothing and should not throw an error.
*/
- void open();
+ OpenEffectReturn open(
+ in Parameter.Common common, in @nullable Parameter.Specific specific);
/**
* Called by the client to close the effect instance, processing thread should be destroyed and
@@ -45,7 +101,7 @@
*
* Effect instance close interface should always succeed unless:
* 1. The effect instance is not in a proper state to be closed, for example it's still in
- * processing state.
+ * State::PROCESSING state.
* 2. There is system/hardware related failure when close.
*
* @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to be closed.
@@ -62,4 +118,53 @@
* @return Descriptor The @c Descriptor of this effect instance.
*/
Descriptor getDescriptor();
+
+ /**
+ * Send a command (defined in enum CommandId) to the effect instance, instance state can be
+ * changed as result of command handling.
+ *
+ * Must be available for the effect instance after it has been open().
+ *
+ * @param commandId ID of the command send to the effect instance.
+ *
+ * @throws EX_ILLEGAL_STATE if the effect instance is not in a proper state to handle the
+ * command.
+ * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported command.
+ */
+ void command(in CommandId commandId);
+
+ /**
+ * Get current state of the effect instance.
+ *
+ * Must be available for the effect instance at anytime and should always succeed.
+ *
+ * @return Current effect instance state.
+ */
+ State getState();
+
+ /**
+ * Set a parameter to the effect instance.
+ *
+ * Must be available for the effect instance after open().
+ *
+ * @param param Parameter data to set to the effect instance.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported parameter.
+ */
+ void setParameter(in Parameter param);
+
+ /**
+ * Get a parameter from the effect instance with parameter ID.
+ *
+ * This interface must return the current parameter of the effect instance, if no parameter
+ * has been set by client yet, the default value must be returned.
+ *
+ * Must be available for the effect instance after open().
+ *
+ * @param paramId The tag enum of parameter to get.
+ * @return Parameter The parameter to get from the effect instance.
+ *
+ * @throws EX_ILLEGAL_ARGUMENT if the effect instance receive unsupported parameter tag.
+ */
+ Parameter getParameter(in Parameter.Id paramId);
}
diff --git a/audio/aidl/android/hardware/audio/effect/IFactory.aidl b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
index 4873d3a..5943359 100644
--- a/audio/aidl/android/hardware/audio/effect/IFactory.aidl
+++ b/audio/aidl/android/hardware/audio/effect/IFactory.aidl
@@ -18,6 +18,7 @@
import android.hardware.audio.effect.Descriptor;
import android.hardware.audio.effect.IEffect;
+import android.hardware.audio.effect.Processing;
import android.media.audio.common.AudioUuid;
/**
@@ -38,11 +39,24 @@
* null, used as a filter for effect type UUIDs.
* @param implementation Indicates the particular implementation of the effect in that type.
* This is an optional parameter, pass in null if this parameter is not necessary; if
- * non null, used as a filter for effect type UUIDs.
+ * non null, used as a filter for effect implementation UUIDs.
+ * @param proxy Indicates the proxy UUID filter to query.
+ * This is an optional parameter, pass in null if this parameter is not necessary; if
+ * non null, used as a filter for effect proxy UUIDs.
* @return List of effect identities supported and filtered by type/implementation UUID.
*/
- Descriptor.Identity[] queryEffects(
- in @nullable AudioUuid type, in @nullable AudioUuid implementation);
+ Descriptor.Identity[] queryEffects(in @nullable AudioUuid type,
+ in @nullable AudioUuid implementation, in @nullable AudioUuid proxy);
+
+ /**
+ * Return a list of defined processings, with the optional filter by Processing type.
+ * An effect can exist more than once in the returned list, which means this effect must be used
+ * in more than one processing type.
+ *
+ * @param type Type of processing to query, can be AudioStreamType, AudioSource, or null.
+ * @return list of processing defined with the optional filter by Processing.Type.
+ */
+ Processing[] queryProcessing(in @nullable Processing.Type type);
/**
* Called by the audio framework to create the effect (identified by the implementation UUID
diff --git a/audio/aidl/android/hardware/audio/effect/LoudnessEnhancer.aidl b/audio/aidl/android/hardware/audio/effect/LoudnessEnhancer.aidl
new file mode 100644
index 0000000..0441f10
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/LoudnessEnhancer.aidl
@@ -0,0 +1,61 @@
+/*
+ * 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.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * LoudnessEnhancer specific definitions.
+ *
+ * All parameters defined in union LoudnessEnhancer must be gettable and settable. The capabilities
+ * defined in LoudnessEnhancer.Capability can only acquired with IEffect.getDescriptor() and not
+ * settable.
+ */
+@VintfStability
+union LoudnessEnhancer {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ LoudnessEnhancer.Tag commonTag;
+ }
+
+ /**
+ * Vendor LoudnessEnhancer implementation definition for additional parameters.
+ */
+ VendorExtension vendor;
+
+ /**
+ * Capability supported by LoudnessEnhancer implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ /**
+ * LoudnessEnhancer capability extension, vendor can use this extension in case existing
+ * capability definition not enough.
+ */
+ VendorExtension extension;
+ }
+
+ /**
+ * The maximum gain in millibels (mB) applied to the signal to process, default value is 0 which
+ * corresponds to no amplification.
+ */
+ int gainMb;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Parameter.aidl b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
new file mode 100644
index 0000000..e7d3d5e
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Parameter.aidl
@@ -0,0 +1,162 @@
+/*
+ * 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.effect;
+
+import android.hardware.audio.effect.BassBoost;
+import android.hardware.audio.effect.Downmix;
+import android.hardware.audio.effect.DynamicsProcessing;
+import android.hardware.audio.effect.Equalizer;
+import android.hardware.audio.effect.HapticGenerator;
+import android.hardware.audio.effect.LoudnessEnhancer;
+import android.hardware.audio.effect.Reverb;
+import android.hardware.audio.effect.VendorExtension;
+import android.hardware.audio.effect.Virtualizer;
+import android.hardware.audio.effect.Visualizer;
+import android.hardware.audio.effect.Volume;
+import android.media.audio.common.AudioConfig;
+import android.media.audio.common.AudioDeviceDescription;
+import android.media.audio.common.AudioMode;
+import android.media.audio.common.AudioSource;
+
+/**
+ * Defines all parameters supported by the effect instance.
+ *
+ * There are three groups of parameters:
+ * 1. Common parameters are essential parameters, MUST pass to effects at open() interface.
+ * 2. Parameters defined for a specific effect type.
+ * 3. Extension parameters ParcelableHolder can be used for vendor effect definition.
+ *
+ */
+@VintfStability
+union Parameter {
+ /**
+ * Client can pass in Parameter.Id with the corresponding tag value in IEffect.getParameter()
+ * call to get android.hardware.audio.effect.Parameter.
+ *
+ * As an example, if a client want to get audio.hardware.audio.effect.Specific.Equalizer, the
+ * value of Id should be audio.hardware.audio.effect.Parameter.Specific.equalizer.
+ */
+ @VintfStability
+ union Id {
+ /**
+ * Parameter tag defined for vendor effects. Use int here so there is flexibility for vendor
+ * to define different tag.
+ */
+ int vendorEffectTag;
+ /**
+ * Parameter tag defined for nested parameters. Can be used to get any parameter defined in
+ * nested Union structure.
+ *
+ * Example:
+ * To get BassBoost strength in param from effectInstance:
+ * IEffect effectInstance;
+ * Parameter param;
+ * BassBoost::Id bassId = BassBoost::Id::make<BassBoost::Id::tag>(BassBoost::strengthPm);
+ * Parameter::Id id = Parameter::Id::make<Parameter::Id::bassBoostTag>(bassId);
+ * effectInstance.getParameter(id, ¶m);
+ *
+ */
+ BassBoost.Id bassBoostTag;
+ Downmix.Id downmixTag;
+ DynamicsProcessing.Id dynamicsProcessingTag;
+ Equalizer.Id equalizerTag;
+ HapticGenerator.Id hapticGeneratorTag;
+ LoudnessEnhancer.Id loudnessEnhancerTag;
+ Reverb.Id reverbTag;
+ Virtualizer.Id virtualizerTag;
+ Visualizer.Id visualizerTag;
+ Volume.Id volumeTag;
+ /**
+ * Non-nested parameter tag. Can be used to get any parameter defined in Union Parameter
+ * directly.
+ */
+ Parameter.Tag commonTag;
+ }
+
+ /**
+ * Common parameters MUST be supported by all effect implementations.
+ */
+ @VintfStability
+ parcelable Common {
+ /**
+ * Type of Audio device.
+ */
+ int session;
+ /**
+ * I/O Handle.
+ */
+ int ioHandle;
+ /**
+ * Input config.
+ */
+ AudioConfig input;
+ /**
+ * Output config.
+ */
+ AudioConfig output;
+ }
+ Common common;
+
+ /**
+ * Used by audio framework to set the device type to effect engine.
+ * Effect must implement setParameter(device) if Flags.deviceIndication set to true.
+ */
+ AudioDeviceDescription deviceDescription;
+ /**
+ * Used by audio framework to set the audio mode to effect engine.
+ * Effect must implement setParameter(mode) if Flags.audioModeIndication set to true.
+ */
+ AudioMode mode;
+ /**
+ * Used by audio framework to set the audio source to effect engine.
+ * Effect must implement setParameter(source) if Flags.audioSourceIndication set to true.
+ */
+ AudioSource source;
+
+ /**
+ * The volume gain for left and right channel, left and right equals to same value if it's mono.
+ */
+ @VintfStability
+ parcelable VolumeStereo {
+ float left;
+ float right;
+ }
+ /**
+ * Used by audio framework to delegate volume control to effect engine.
+ * Effect must implement setParameter(volume) if Flags.volume set to Volume.IND.
+ */
+ VolumeStereo volumeStereo;
+
+ /**
+ * Parameters MUST be supported by a Specific type of effect.
+ */
+ @VintfStability
+ union Specific {
+ VendorExtension vendorEffect;
+ BassBoost bassBoost;
+ Downmix downmix;
+ DynamicsProcessing dynamicsProcessing;
+ Equalizer equalizer;
+ LoudnessEnhancer loudnessEnhancer;
+ HapticGenerator hapticGenerator;
+ Reverb reverb;
+ Virtualizer virtualizer;
+ Visualizer visualizer;
+ Volume volume;
+ }
+ Specific specific;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Processing.aidl b/audio/aidl/android/hardware/audio/effect/Processing.aidl
new file mode 100644
index 0000000..ef32e8c
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Processing.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.audio.effect;
+
+import android.hardware.audio.effect.Descriptor;
+import android.media.audio.common.AudioSource;
+import android.media.audio.common.AudioStreamType;
+import android.media.audio.common.AudioUuid;
+
+/**
+ * List of effects which must be used for certain pre-processing or post-processing.
+ */
+@VintfStability
+parcelable Processing {
+ @VintfStability
+ union Type {
+ AudioStreamType streamType = AudioStreamType.INVALID;
+ AudioSource source;
+ }
+
+ /**
+ * Specifies the type of processing by referring to the output stream type (AudioStreamType) or
+ * the input stream source (AudioSource).
+ */
+ Type type;
+ /**
+ * List of effect identities for this processing.
+ */
+ Descriptor.Identity[] ids;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Reverb.aidl b/audio/aidl/android/hardware/audio/effect/Reverb.aidl
new file mode 100644
index 0000000..f60c2ea
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Reverb.aidl
@@ -0,0 +1,92 @@
+/*
+ * 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.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * Reverb specific definitions.
+ *
+ * All parameters defined in union Reverb must be gettable and settable. The capabilities defined in
+ * Reverb.Capability can only acquired with IEffect.getDescriptor() and not settable.
+ */
+@VintfStability
+union Reverb {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ Reverb.Tag commonTag;
+ }
+
+ /**
+ * Vendor Reverb implementation definition for additional parameters.
+ */
+ VendorExtension vendor;
+
+ /**
+ * Capability supported by effect implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ VendorExtension extension;
+
+ /**
+ * Max decay time supported in millisecond.
+ */
+ int maxDecayTimeMs;
+ }
+
+ /**
+ * Room level apply to the reverb effect in millibels.
+ */
+ int roomLevelMb;
+ /**
+ * Room HF level apply to the reverb effect in millibels.
+ */
+ int roomHfLevelMb;
+ /**
+ * Delay time apply to the reverb effect in milliseconds.
+ */
+ int decayTimeMs;
+ /**
+ * HF decay ratio in permilles.
+ */
+ int decayHfRatioPm;
+ /**
+ * Reverb level in millibels.
+ */
+ int levelMb;
+ /**
+ * Reverb delay in milliseconds.
+ */
+ int delayMs;
+ /**
+ * Diffusion in permilles.
+ */
+ int diffusionPm;
+ /**
+ * Density in permilles.
+ */
+ int densityPm;
+ /**
+ * Bypass reverb and copy input to output if set to true.
+ */
+ boolean bypass;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/State.aidl b/audio/aidl/android/hardware/audio/effect/State.aidl
new file mode 100644
index 0000000..85a4afc
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/State.aidl
@@ -0,0 +1,86 @@
+/*
+ * 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.effect;
+
+/**
+ * Possible states of an effect instance.
+ * A typical effect instance will be in INIT state when it is created with IFactory.createEffect()
+ * interface, transfer to IDLE after open(), and to PROCESSING after
+ * IEffect.command(Command.Id.START) command. When an effect instance receive STOP or RESET command,
+ * it should transfer to IDLE state after handle the command successfully. Effect instance should
+ * consume minimal resource and transfer to INIT state after it was close().
+ *
+ * Refer to State.gv for detailed state diagram.
+ */
+@VintfStability
+@Backing(type="byte")
+enum State {
+
+ /**
+ * An effect instance is in INIT state by default after it was created with
+ * IFactory.createEffect(). When an effect instance is in INIT state, it should have instance
+ * context initialized, and ready to handle IEffect.setParameter(), IEffect.open() as well as
+ * all getter interfaces.
+ *
+ * In INIT state, effect instance must:
+ * 1. Not handle any IEffect.command() and return EX_ILLEGAL_STATE with any Command.Id.
+ * 2. Be able to handle all parameter setting with IEffect.setParameter().
+ * 3. Be able to handle all getter interface calls like IEffect.getParameter() and
+ * IEffect.getState().
+ * 4. Be able to handle IEffect.open() successfully after configuration.
+ *
+ * Client is expected to do necessary configuration with IEffect.setParameter(), get all
+ * resource ready with IEffect.open(), and make sure effect instance transfer to IDLE state
+ * before sending commands with IEffect.command() interface. Effect instance must transfer
+ * from INIT to IDLE state after handle IEffect.open() call successfully.
+ */
+ INIT,
+ /**
+ * An effect instance transfer to IDLE state after it was open successfully with IEffect.open()
+ * in INIT state, or after it was stop/reset with Command.Id.STOP/RESET in PROCESSING state.
+ *
+ * In IDLE state, effect instance must:
+ * 1. Be able to start effect processing engine with IEffect.command(Command.Id.START) call.
+ * 2. Be able to handle all parameter setting with IEffect.setParameter().
+ * 3. Be able to handle all getter interface calls like IEffect.getParameter() and
+ * IEffect.getState().
+ *
+ * The following state transfer can happen in IDLE state:
+ * 1. Transfer to PROCESSING if instance receive an START command and start processing data
+ * successfully.
+ * 2. Transfer to INIT if instance receive a close() call.
+ */
+ IDLE,
+ /**
+ * An effect instance is in PROCESSING state after it receive an START command and start
+ * processing data successfully. Effect instance will transfer from PROCESSING to IDLE state if
+ * it receive an STOP or RESET command and handle the command successfully.
+ *
+ * When an instance is in PROCESSING state, client should try not to close() it directly,
+ * instead client should try to stop processing data first with STOP command before close(). In
+ * the case of a close() call received when instance in PROCESSING state, it should try to stop
+ * processing and transfer to IDLE first before close().
+ *
+ * In PROCESSING state, effect instance must:
+ * 1. Return EX_ILLEGAL_STATE if it's not able to handle any parameter settings at runtime.
+ * 2. Be able to handle STOP and RESET for IEffect.command() interface, and return
+ * EX_ILLEGAL_STATE for all other commands.
+ * 3. Must be able to handle all get* interface calls like IEffect.getParameter() and
+ * IEffect.getState().
+ */
+ PROCESSING,
+}
diff --git a/audio/aidl/android/hardware/audio/effect/VendorExtension.aidl b/audio/aidl/android/hardware/audio/effect/VendorExtension.aidl
new file mode 100644
index 0000000..c60f01a
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/VendorExtension.aidl
@@ -0,0 +1,25 @@
+/*
+ * 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.effect;
+
+/**
+ * Vendor exntension implementation definition, can be used for additional parameters.
+ */
+@VintfStability
+parcelable VendorExtension {
+ ParcelableHolder extension;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl b/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl
new file mode 100644
index 0000000..9d039bc
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Virtualizer.aidl
@@ -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.
+ */
+
+package android.hardware.audio.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * Virtualizer specific definitions. An audio virtualizer is a general name for an effect to
+ * spatialize audio channels.
+ *
+ * All parameters defined in union Virtualizer must be gettable and settable. The capabilities
+ * defined in Virtualizer.Capability can only acquired with IEffect.getDescriptor() and not
+ * settable.
+ */
+@VintfStability
+union Virtualizer {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ Virtualizer.Tag commonTag;
+ }
+
+ /**
+ * Vendor Virtualizer implementation definition for additional parameters.
+ */
+ VendorExtension vendor;
+
+ /**
+ * Capability supported by Virtualizer implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ /**
+ * Virtualizer capability extension, vendor can use this extension in case existing
+ * capability definition not enough.
+ */
+ VendorExtension extension;
+ /**
+ * Indicates whether setting strength is supported. False value indicates only one strength
+ * is supported and setParameter() method will always return EX_ILLEGAL_ARGUMENT.
+ */
+ boolean strengthSupported;
+ }
+
+ /**
+ * The per mille strength of the virtualizer effect.
+ *
+ * If the implementation does not support per mille accuracy for setting the strength, it is
+ * allowed to round the given strength to the nearest supported value. In this case {@link
+ * #IEffect.getParameter()} method should return the rounded value that was actually set.
+ *
+ * The valid range for strength is [0, 1000].
+ */
+ int strengthPm;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Visualizer.aidl b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl
new file mode 100644
index 0000000..4c1b71a
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Visualizer.aidl
@@ -0,0 +1,167 @@
+/*
+ * 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.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * Visualizer specific definitions. Visualizer enables application to retrieve part of the currently
+ * playing audio for visualization purpose
+ *
+ * All parameters defined in union Visualizer other than these in GetOnlyParameters and
+ * SetOnlyParameters must be gettable and settable. The capabilities defined in
+ * Visualizer.Capability can only acquired with IEffect.getDescriptor() and not settable.
+ *
+ */
+@VintfStability
+union Visualizer {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ GetOnlyParameters.Tag getOnlyParamTag;
+ SetOnlyParameters.Tag setOnlyParamTag;
+ Visualizer.Tag commonTag;
+ }
+ Id id;
+
+ /**
+ * Vendor Visualizer implementation definition for additional parameters.
+ */
+ VendorExtension vendor;
+
+ /**
+ * Capability supported by Visualizer implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ /**
+ * Visualizer capability extension, vendor can use this extension in case existing
+ * capability definition not enough.
+ */
+ VendorExtension extension;
+ /**
+ * Max latency supported in millseconds.
+ */
+ int maxLatencyMs;
+ /**
+ * Capture size range.
+ */
+ CaptureSizeRange captureSizeRange;
+ }
+
+ /**
+ * Supported capture size range in bytes.
+ */
+ @VintfStability
+ parcelable CaptureSizeRange {
+ int minBytes;
+ int maxBytes;
+ }
+
+ /**
+ * Type of scaling applied on the captured visualization data.
+ */
+ @VintfStability
+ enum ScalingMode {
+ /**
+ * Defines a capture mode where amplification is applied based on the content of the
+ * captured data. This is the default Visualizer mode, and is suitable for music
+ * visualization.
+ */
+ NORMALIZED = 0,
+ /**
+ * Defines a capture mode where the playback volume will affect (scale) the range of the
+ * captured data. A low playback volume will lead to low sample and fft values, and
+ * vice-versa.
+ */
+ AS_PLAYED,
+ }
+
+ /**
+ * Measurement modes to be performed.
+ */
+ @VintfStability
+ enum MeasurementMode {
+ /**
+ * No measurements are performed.
+ */
+ NONE = 0,
+ /**
+ * Defines a measurement mode which computes the peak and RMS value in mB below the "full
+ * scale", where 0mB is normally the maximum sample value (but see the note below). Minimum
+ * value depends on the resolution of audio samples used by the audio framework. The value
+ * of -9600mB is the minimum value for 16-bit audio systems and -14400mB or below for "high
+ * resolution" systems. Values for peak and RMS can be retrieved with {@link
+ * #getMeasurementPeakRms(MeasurementPeakRms)}.
+ */
+ PEAK_RMS,
+ }
+
+ /**
+ * Any parameter defined in this union must be gettable via getParameter(), but must not
+ * settable.
+ */
+ @VintfStability
+ union GetOnlyParameters {
+ /**
+ * Get the current measurements.
+ */
+ @VintfStability
+ parcelable Measurement {
+ int rms;
+ int peak;
+ }
+ Measurement measurement;
+
+ /**
+ * Gets the latest PCM capture, size of returned vector equals to @c captureSize.
+ */
+ byte[] captureBytes;
+ }
+ GetOnlyParameters getOnlyParameters;
+
+ /**
+ * Any parameter defined in this union must be settable via setParameter(), but must not
+ * gettable.
+ */
+ @VintfStability
+ union SetOnlyParameters {
+ /**
+ * Used by framework to inform the visualizer about the downstream latency (audio hardware
+ * driver estimated latency in milliseconds).
+ */
+ int latencyMs;
+ }
+ SetOnlyParameters setOnlyParameters;
+
+ /**
+ * Current capture size in bytes. The capture size must be a power of 2 in the range
+ * Capability.captureSizeRange.
+ */
+ int captureSizeBytes;
+ /**
+ * Visualizer capture mode
+ */
+ ScalingMode scalingMode;
+ /**
+ * Visualizer measurement mode.
+ */
+ MeasurementMode measurementMode;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/Volume.aidl b/audio/aidl/android/hardware/audio/effect/Volume.aidl
new file mode 100644
index 0000000..a3ce2f6
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/Volume.aidl
@@ -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.effect;
+
+import android.hardware.audio.effect.VendorExtension;
+
+/**
+ * Volume specific definitions. Volume effect provide volume control and mute/unmute functionality.
+ *
+ * All parameters defined in union Volume must be gettable and settable. The capabilities defined in
+ * Volume.Capability can only acquired with IEffect.getDescriptor() and not settable.
+ */
+@VintfStability
+union Volume {
+ /**
+ * Effect parameter tag to identify the parameters for getParameter().
+ */
+ @VintfStability
+ union Id {
+ int vendorExtensionTag;
+ Volume.Tag commonTag;
+ }
+
+ /**
+ * Vendor Volume implementation definition for additional parameters.
+ */
+ VendorExtension vendor;
+
+ /**
+ * Capability supported by Volume implementation.
+ */
+ @VintfStability
+ parcelable Capability {
+ /**
+ * Volume capability extension, vendor can use this extension in case existing capability
+ * definition not enough.
+ */
+ VendorExtension extension;
+
+ /**
+ * Volume strength supported in dB.
+ */
+ int maxLevel;
+ }
+
+ /**
+ * Current level in dB.
+ */
+ int levelDb;
+ /**
+ * Mute volume if true, when volume set to mute, the current level still saved and take effect
+ * when unmute.
+ */
+ boolean mute;
+}
diff --git a/audio/aidl/android/hardware/audio/effect/state.gv b/audio/aidl/android/hardware/audio/effect/state.gv
new file mode 100644
index 0000000..e19e6c7
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/effect/state.gv
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+// To render: "dot -Tpng state.gv -o state.png"
+digraph effect_state_machine {
+ node [shape=point style=filled fillcolor=black width=0.5] I;
+ node [shape=doublecircle] F;
+ node [shape=oval width=1];
+ node [fillcolor=lightgreen] INIT;
+ node [fillcolor=lightblue] IDLE;
+ node [fillcolor=lightyellow] PROCESSING;
+
+ I -> INIT [label="IFactory.createEffect" labelfontcolor="navy"];
+ INIT -> F [label="IFactory.destroyEffect"];
+ INIT -> IDLE [label="open()" labelfontcolor="lime"];
+ IDLE -> PROCESSING [label="command(START"];
+ PROCESSING -> IDLE [label="command(STOP)\ncommand(RESET)"];
+ IDLE -> INIT [label="close()"];
+
+ INIT -> INIT [label="getState\ngetDescriptor"];
+ IDLE -> IDLE [label="getXXX\nsetParameter\ncommand(RESET)"];
+ PROCESSING -> PROCESSING [label="getXXX\nsetParameter"];
+}
\ No newline at end of file
diff --git a/audio/aidl/common/StreamWorker.cpp b/audio/aidl/common/StreamWorker.cpp
index 9bca760..dda0e4a 100644
--- a/audio/aidl/common/StreamWorker.cpp
+++ b/audio/aidl/common/StreamWorker.cpp
@@ -44,6 +44,10 @@
mWorkerStateChangeRequest = true;
}
}
+ join();
+}
+
+void ThreadController::join() {
if (mWorker.joinable()) {
mWorker.join();
}
diff --git a/audio/aidl/common/include/StreamWorker.h b/audio/aidl/common/include/StreamWorker.h
index 6260eca..ab2ec26 100644
--- a/audio/aidl/common/include/StreamWorker.h
+++ b/audio/aidl/common/include/StreamWorker.h
@@ -39,6 +39,9 @@
~ThreadController() { stop(); }
bool start(const std::string& name, int priority);
+ // Note: 'pause' and 'resume' methods should only be used on the "driving" side.
+ // In the case of audio HAL I/O, the driving side is the client, because the HAL
+ // implementation always blocks on getting a command.
void pause() { switchWorkerStateSync(WorkerState::RUNNING, WorkerState::PAUSE_REQUESTED); }
void resume() { switchWorkerStateSync(WorkerState::PAUSED, WorkerState::RESUME_REQUESTED); }
bool hasError() {
@@ -50,6 +53,10 @@
return mError;
}
void stop();
+ // Direct use of 'join' assumes that the StreamLogic is not intended
+ // to run forever, and is guaranteed to exit by itself. This normally
+ // only happen in tests.
+ void join();
bool waitForAtLeastOneCycle();
// Only used by unit tests.
@@ -133,7 +140,8 @@
void resume() { mThread.resume(); }
bool hasError() { return mThread.hasError(); }
std::string getError() { return mThread.getError(); }
- void stop() { return mThread.stop(); }
+ void stop() { mThread.stop(); }
+ void join() { mThread.join(); }
bool waitForAtLeastOneCycle() { return mThread.waitForAtLeastOneCycle(); }
// Only used by unit tests.
diff --git a/audio/aidl/common/tests/streamworker_tests.cpp b/audio/aidl/common/tests/streamworker_tests.cpp
index e3e484d..8ea8424 100644
--- a/audio/aidl/common/tests/streamworker_tests.cpp
+++ b/audio/aidl/common/tests/streamworker_tests.cpp
@@ -160,6 +160,14 @@
EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
}
+TEST_P(StreamWorkerTest, WorkerJoin) {
+ ASSERT_TRUE(worker.start());
+ stream.setStopStatus();
+ worker.join();
+ EXPECT_FALSE(worker.hasError());
+ EXPECT_TRUE(worker.hasNoWorkerCycleCalled(kWorkerIdleCheckTime));
+}
+
TEST_P(StreamWorkerTest, WorkerError) {
ASSERT_TRUE(worker.start());
stream.setErrorStatus();
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 53ed908..2b9ed5b 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -21,6 +21,9 @@
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
],
+ header_libs: [
+ "libaudioaidl_headers",
+ ],
}
cc_library_static {
@@ -36,6 +39,7 @@
"Configuration.cpp",
"Module.cpp",
"Stream.cpp",
+ "Telephony.cpp",
],
visibility: [
":__subpackages__",
@@ -62,13 +66,24 @@
name: "aidlaudioeffectservice_defaults",
defaults: [
"latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
],
vendor: true,
shared_libs: [
+ "libaudioaidlcommon",
"libbase",
"libbinder_ndk",
- "android.hardware.audio.effect-V1-ndk",
- "libequalizer",
+ "libcutils",
+ "libfmq",
+ "liblog",
+ "libutils",
+ "android.hardware.common-V2-ndk",
+ "android.hardware.common.fmq-V1-ndk",
+ ],
+ header_libs: [
+ "libaudioaidl_headers",
+ "libaudio_system_headers",
+ "libsystem_headers",
],
cflags: [
"-Wall",
@@ -78,18 +93,11 @@
],
}
-cc_library_static {
- name: "libaudioeffectserviceexampleimpl",
- defaults: ["aidlaudioeffectservice_defaults"],
- export_include_dirs: [
- "include",
- "include/equalizer-impl/",
- ],
+filegroup {
+ name: "effectCommonFile",
srcs: [
- "EffectFactory.cpp",
- ],
- visibility: [
- ":__subpackages__",
+ "EffectThread.cpp",
+ "EffectImpl.cpp",
],
}
@@ -99,8 +107,30 @@
init_rc: ["android.hardware.audio.effect.service-aidl.example.rc"],
vintf_fragments: ["android.hardware.audio.effect.service-aidl.xml"],
defaults: ["aidlaudioeffectservice_defaults"],
- static_libs: [
- "libaudioeffectserviceexampleimpl",
+ shared_libs: [
+ "libbassboostsw",
+ "libbundleaidl",
+ "libdynamicsprocessingsw",
+ "libenvreverbsw",
+ "libequalizersw",
+ "libhapticgeneratorsw",
+ "libloudnessenhancersw",
+ "libpresetreverbsw",
+ "libtinyxml2",
+ "libvirtualizersw",
+ "libvisualizersw",
+ "libvolumesw",
],
- srcs: ["EffectMain.cpp"],
+ srcs: [
+ "EffectConfig.cpp",
+ "EffectFactory.cpp",
+ "EffectMain.cpp",
+ ],
+}
+
+cc_library_headers {
+ name: "libaudioaidl_headers",
+ export_include_dirs: ["include"],
+ vendor_available: true,
+ host_supported: true,
}
diff --git a/audio/aidl/default/Config.cpp b/audio/aidl/default/Config.cpp
index 3f7a3d3..0fdd5b4 100644
--- a/audio/aidl/default/Config.cpp
+++ b/audio/aidl/default/Config.cpp
@@ -13,7 +13,17 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+#define LOG_TAG "AHAL_Module"
+#include <android-base/logging.h>
#include "core-impl/Config.h"
-namespace aidl::android::hardware::audio::core {} // namespace aidl::android::hardware::audio::core
+namespace aidl::android::hardware::audio::core {
+ndk::ScopedAStatus Config::getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) {
+ SurroundSoundConfig surroundSoundConfig;
+ // TODO: parse from XML; for now, use empty config as default
+ *_aidl_return = std::move(surroundSoundConfig);
+ LOG(DEBUG) << __func__ << ": returning " << _aidl_return->toString();
+ return ndk::ScopedAStatus::ok();
+}
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/EffectConfig.cpp b/audio/aidl/default/EffectConfig.cpp
new file mode 100644
index 0000000..e1427ec
--- /dev/null
+++ b/audio/aidl/default/EffectConfig.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_EffectConfig"
+#include <android-base/logging.h>
+
+#include "effectFactory-impl/EffectConfig.h"
+
+using aidl::android::media::audio::common::AudioUuid;
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectConfig::EffectConfig(const std::string& file) {
+ tinyxml2::XMLDocument doc;
+ doc.LoadFile(file.c_str());
+ LOG(DEBUG) << __func__ << " loading " << file;
+ // parse the xml file into maps
+ if (doc.Error()) {
+ LOG(ERROR) << __func__ << " tinyxml2 failed to load " << file
+ << " error: " << doc.ErrorStr();
+ return;
+ }
+
+ auto registerFailure = [&](bool result) { mSkippedElements += result ? 0 : 1; };
+
+ for (auto& xmlConfig : getChildren(doc, "audio_effects_conf")) {
+ // Parse library
+ for (auto& xmlLibraries : getChildren(xmlConfig, "libraries")) {
+ for (auto& xmlLibrary : getChildren(xmlLibraries, "library")) {
+ registerFailure(parseLibrary(xmlLibrary));
+ }
+ }
+
+ // Parse effects
+ for (auto& xmlEffects : getChildren(xmlConfig, "effects")) {
+ for (auto& xmlEffect : getChildren(xmlEffects)) {
+ registerFailure(parseEffect(xmlEffect));
+ }
+ }
+
+ // Parse pre processing chains
+ for (auto& xmlPreprocess : getChildren(xmlConfig, "preprocess")) {
+ for (auto& xmlStream : getChildren(xmlPreprocess, "stream")) {
+ registerFailure(parseStream(xmlStream));
+ }
+ }
+
+ // Parse post processing chains
+ for (auto& xmlPostprocess : getChildren(xmlConfig, "postprocess")) {
+ for (auto& xmlStream : getChildren(xmlPostprocess, "stream")) {
+ registerFailure(parseStream(xmlStream));
+ }
+ }
+ }
+ LOG(DEBUG) << __func__ << " successfully parsed " << file << ", skipping " << mSkippedElements
+ << " element(s)";
+}
+
+std::vector<std::reference_wrapper<const tinyxml2::XMLElement>> EffectConfig::getChildren(
+ const tinyxml2::XMLNode& node, const char* childTag) {
+ std::vector<std::reference_wrapper<const tinyxml2::XMLElement>> children;
+ for (auto* child = node.FirstChildElement(childTag); child != nullptr;
+ child = child->NextSiblingElement(childTag)) {
+ children.emplace_back(*child);
+ }
+ return children;
+}
+
+bool EffectConfig::parseLibrary(const tinyxml2::XMLElement& xml) {
+ const char* name = xml.Attribute("name");
+ RETURN_VALUE_IF(!name, false, "noNameAttribute");
+ const char* path = xml.Attribute("path");
+ RETURN_VALUE_IF(!path, false, "noPathAttribute");
+
+ mLibraryMap[name] = path;
+ LOG(DEBUG) << __func__ << " " << name << " : " << path;
+ return true;
+}
+
+bool EffectConfig::parseEffect(const tinyxml2::XMLElement& xml) {
+ struct EffectLibraries effectLibraries;
+ std::vector<LibraryUuid> libraryUuids;
+ std::string name = xml.Attribute("name");
+ RETURN_VALUE_IF(name == "", false, "effectsNoName");
+
+ LOG(DEBUG) << __func__ << dump(xml);
+ struct LibraryUuid libraryUuid;
+ if (std::strcmp(xml.Name(), "effectProxy") == 0) {
+ // proxy lib and uuid
+ RETURN_VALUE_IF(!parseLibraryUuid(xml, libraryUuid, true), false, "parseProxyLibFailed");
+ effectLibraries.proxyLibrary = libraryUuid;
+ // proxy effect libs and UUID
+ auto xmlProxyLib = xml.FirstChildElement();
+ RETURN_VALUE_IF(!xmlProxyLib, false, "noLibForProxy");
+ while (xmlProxyLib) {
+ struct LibraryUuid tempLibraryUuid;
+ RETURN_VALUE_IF(!parseLibraryUuid(*xmlProxyLib, tempLibraryUuid), false,
+ "parseEffectLibFailed");
+ libraryUuids.push_back(std::move(tempLibraryUuid));
+ xmlProxyLib = xmlProxyLib->NextSiblingElement();
+ }
+ } else {
+ // expect only one library if not proxy
+ RETURN_VALUE_IF(!parseLibraryUuid(xml, libraryUuid), false, "parseEffectLibFailed");
+ libraryUuids.push_back(std::move(libraryUuid));
+ }
+
+ effectLibraries.libraries = std::move(libraryUuids);
+ mEffectsMap[name] = std::move(effectLibraries);
+ return true;
+}
+
+bool EffectConfig::parseStream(const tinyxml2::XMLElement& xml) {
+ LOG(DEBUG) << __func__ << dump(xml);
+ const char* type = xml.Attribute("type");
+ RETURN_VALUE_IF(!type, false, "noTypeInProcess");
+ RETURN_VALUE_IF(0 != mProcessingMap.count(type), false, "duplicateType");
+
+ for (auto& apply : getChildren(xml, "apply")) {
+ const char* name = apply.get().Attribute("effect");
+ RETURN_VALUE_IF(!name, false, "noEffectAttribute");
+ mProcessingMap[type].push_back(name);
+ LOG(DEBUG) << __func__ << " " << type << " : " << name;
+ }
+ return true;
+}
+
+bool EffectConfig::parseLibraryUuid(const tinyxml2::XMLElement& xml,
+ struct LibraryUuid& libraryUuid, bool isProxy) {
+ // Retrieve library name only if not effectProxy element
+ if (!isProxy) {
+ const char* name = xml.Attribute("library");
+ RETURN_VALUE_IF(!name, false, "noLibraryAttribute");
+ libraryUuid.name = name;
+ }
+
+ const char* uuid = xml.Attribute("uuid");
+ RETURN_VALUE_IF(!uuid, false, "noUuidAttribute");
+ RETURN_VALUE_IF(!stringToUuid(uuid, &libraryUuid.uuid), false, "invalidUuidAttribute");
+
+ LOG(DEBUG) << __func__ << (isProxy ? " proxy " : libraryUuid.name) << " : "
+ << libraryUuid.uuid.toString();
+ return true;
+}
+
+const char* EffectConfig::dump(const tinyxml2::XMLElement& element,
+ tinyxml2::XMLPrinter&& printer) const {
+ element.Accept(&printer);
+ return printer.CStr();
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectFactory.cpp b/audio/aidl/default/EffectFactory.cpp
index a9848fd..820b447 100644
--- a/audio/aidl/default/EffectFactory.cpp
+++ b/audio/aidl/default/EffectFactory.cpp
@@ -16,57 +16,209 @@
#define LOG_TAG "AHAL_EffectFactory"
#include <android-base/logging.h>
+#include <dlfcn.h>
+#include <unordered_set>
+#include "effect-impl/EffectTypes.h"
+#include "effect-impl/EffectUUID.h"
#include "effectFactory-impl/EffectFactory.h"
-#include "equalizer-impl/Equalizer.h"
-#include "visualizer-impl/Visualizer.h"
using aidl::android::media::audio::common::AudioUuid;
namespace aidl::android::hardware::audio::effect {
-Factory::Factory() {
- // TODO: implement this with xml parser on audio_effect.xml, and filter with optional
- // parameters.
- Descriptor::Identity id;
- id.type = EqualizerTypeUUID;
- id.uuid = EqualizerSwImplUUID;
- mIdentityList.push_back(id);
+Factory::Factory(const std::string& file) : mConfig(EffectConfig(file)) {
+ LOG(DEBUG) << __func__ << " with config file: " << file;
+ loadEffectLibs();
}
-ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type,
- const std::optional<AudioUuid>& in_instance,
+Factory::~Factory() {
+ if (auto count = mEffectUuidMap.size()) {
+ LOG(ERROR) << __func__ << " remaining " << count
+ << " effect instances not destroyed indicating resource leak!";
+ for (const auto& it : mEffectUuidMap) {
+ if (auto spEffect = it.first.lock()) {
+ LOG(ERROR) << __func__ << " erase remaining instance UUID " << it.second.toString();
+ destroyEffectImpl(spEffect);
+ }
+ }
+ }
+}
+
+ndk::ScopedAStatus Factory::queryEffects(const std::optional<AudioUuid>& in_type_uuid,
+ const std::optional<AudioUuid>& in_impl_uuid,
+ const std::optional<AudioUuid>& in_proxy_uuid,
std::vector<Descriptor::Identity>* _aidl_return) {
- std::copy_if(mIdentityList.begin(), mIdentityList.end(), std::back_inserter(*_aidl_return),
- [&](auto& desc) {
- return (!in_type.has_value() || in_type.value() == desc.type) &&
- (!in_instance.has_value() || in_instance.value() == desc.uuid);
- });
+ std::copy_if(
+ mIdentitySet.begin(), mIdentitySet.end(), std::back_inserter(*_aidl_return),
+ [&](auto& desc) {
+ return (!in_type_uuid.has_value() || in_type_uuid.value() == desc.type) &&
+ (!in_impl_uuid.has_value() || in_impl_uuid.value() == desc.uuid) &&
+ (!in_proxy_uuid.has_value() ||
+ (desc.proxy.has_value() && in_proxy_uuid.value() == desc.proxy.value()));
+ });
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Factory::createEffect(
- const AudioUuid& in_impl_uuid,
- std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>* _aidl_return) {
+ndk::ScopedAStatus Factory::queryProcessing(const std::optional<Processing::Type>& in_type,
+ std::vector<Processing>* _aidl_return) {
+ // TODO: implement this with audio_effect.xml.
+ if (in_type.has_value()) {
+ // return all matching process filter
+ LOG(DEBUG) << __func__ << " process type: " << in_type.value().toString();
+ }
+ LOG(DEBUG) << __func__ << " return " << _aidl_return->size();
+ return ndk::ScopedAStatus::ok();
+}
+
+#define RETURN_IF_BINDER_EXCEPTION(functor) \
+ { \
+ binder_exception_t exception = functor; \
+ if (EX_NONE != exception) { \
+ LOG(ERROR) << #functor << ": failed with error " << exception; \
+ return ndk::ScopedAStatus::fromExceptionCode(exception); \
+ } \
+ }
+
+ndk::ScopedAStatus Factory::createEffect(const AudioUuid& in_impl_uuid,
+ std::shared_ptr<IEffect>* _aidl_return) {
LOG(DEBUG) << __func__ << ": UUID " << in_impl_uuid.toString();
- if (in_impl_uuid == EqualizerSwImplUUID) {
- *_aidl_return = ndk::SharedRefBase::make<Equalizer>();
+ if (mEffectLibMap.count(in_impl_uuid)) {
+ auto& lib = mEffectLibMap[in_impl_uuid];
+ // didn't do dlsym yet
+ if (nullptr == lib.second) {
+ void* libHandle = lib.first.get();
+ auto dlInterface = std::make_unique<struct effect_dl_interface_s>();
+ dlInterface->createEffectFunc = (EffectCreateFunctor)dlsym(libHandle, "createEffect");
+ dlInterface->destroyEffectFunc =
+ (EffectDestroyFunctor)dlsym(libHandle, "destroyEffect");
+ if (!dlInterface->createEffectFunc || !dlInterface->destroyEffectFunc) {
+ LOG(ERROR) << __func__
+ << ": create or destroy symbol not exist in library: " << libHandle
+ << " with dlerror: " << dlerror();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+ }
+ lib.second = std::move(dlInterface);
+ }
+
+ auto& libInterface = lib.second;
+ std::shared_ptr<IEffect> effectSp;
+ RETURN_IF_BINDER_EXCEPTION(libInterface->createEffectFunc(&in_impl_uuid, &effectSp));
+ if (!effectSp) {
+ LOG(ERROR) << __func__ << ": library created null instance without return error!";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_TRANSACTION_FAILED);
+ }
+ *_aidl_return = effectSp;
+ mEffectUuidMap[std::weak_ptr<IEffect>(effectSp)] = in_impl_uuid;
+ LOG(DEBUG) << __func__ << ": instance " << effectSp.get() << " created successfully";
+ return ndk::ScopedAStatus::ok();
} else {
- LOG(ERROR) << __func__ << ": UUID "
- << " not supported";
+ LOG(ERROR) << __func__ << ": library doesn't exist";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
return ndk::ScopedAStatus::ok();
}
-ndk::ScopedAStatus Factory::destroyEffect(
- const std::shared_ptr<::aidl::android::hardware::audio::effect::IEffect>& in_handle) {
- if (in_handle) {
- // TODO: b/245393900 need check the instance state with IEffect.getState before destroy.
+ndk::ScopedAStatus Factory::destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle) {
+ std::weak_ptr<IEffect> wpHandle(in_handle);
+ // find UUID with key (std::weak_ptr<IEffect>)
+ if (auto uuidIt = mEffectUuidMap.find(wpHandle); uuidIt != mEffectUuidMap.end()) {
+ auto& uuid = uuidIt->second;
+ // find implementation library with UUID
+ if (auto libIt = mEffectLibMap.find(uuid); libIt != mEffectLibMap.end()) {
+ if (libIt->second.second->destroyEffectFunc) {
+ RETURN_IF_BINDER_EXCEPTION(libIt->second.second->destroyEffectFunc(in_handle));
+ }
+ } else {
+ LOG(ERROR) << __func__ << ": UUID " << uuid.toString() << " does not exist in libMap!";
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ mEffectUuidMap.erase(uuidIt);
return ndk::ScopedAStatus::ok();
} else {
+ LOG(ERROR) << __func__ << ": instance " << in_handle << " does not exist!";
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
}
+// go over the map and cleanup all expired weak_ptrs.
+void Factory::cleanupEffectMap() {
+ for (auto it = mEffectUuidMap.begin(); it != mEffectUuidMap.end();) {
+ if (nullptr == it->first.lock()) {
+ it = mEffectUuidMap.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+ndk::ScopedAStatus Factory::destroyEffect(const std::shared_ptr<IEffect>& in_handle) {
+ LOG(DEBUG) << __func__ << ": instance " << in_handle.get();
+ ndk::ScopedAStatus status = destroyEffectImpl(in_handle);
+ // always do the cleanup
+ cleanupEffectMap();
+ return status;
+}
+
+void Factory::openEffectLibrary(const AudioUuid& impl, const std::string& libName) {
+ std::function<void(void*)> dlClose = [](void* handle) -> void {
+ if (handle && dlclose(handle)) {
+ LOG(ERROR) << "dlclose failed " << dlerror();
+ }
+ };
+
+ auto libHandle =
+ std::unique_ptr<void, decltype(dlClose)>{dlopen(libName.c_str(), RTLD_LAZY), dlClose};
+ if (!libHandle) {
+ LOG(ERROR) << __func__ << ": dlopen failed, err: " << dlerror();
+ return;
+ }
+
+ LOG(DEBUG) << __func__ << " dlopen lib:" << libName << "\nimpl:" << impl.toString()
+ << "\nhandle:" << libHandle;
+ mEffectLibMap.insert({impl, std::make_pair(std::move(libHandle), nullptr)});
+}
+
+void Factory::createIdentityWithConfig(const EffectConfig::LibraryUuid& configLib,
+ const AudioUuid& typeUuid,
+ const std::optional<AudioUuid> proxyUuid) {
+ static const auto& libMap = mConfig.getLibraryMap();
+ const std::string& libName = configLib.name;
+ if (auto path = libMap.find(libName); path != libMap.end()) {
+ Descriptor::Identity id;
+ id.type = typeUuid;
+ id.uuid = configLib.uuid;
+ id.proxy = proxyUuid;
+ LOG(DEBUG) << __func__ << ": typeUuid " << id.type.toString() << "\nimplUuid "
+ << id.uuid.toString() << " proxyUuid "
+ << (proxyUuid.has_value() ? proxyUuid->toString() : "null");
+ openEffectLibrary(id.uuid, path->second);
+ mIdentitySet.insert(std::move(id));
+ } else {
+ LOG(ERROR) << __func__ << ": library " << libName << " not exist!";
+ return;
+ }
+}
+
+void Factory::loadEffectLibs() {
+ const auto& configEffectsMap = mConfig.getEffectsMap();
+ for (const auto& configEffects : configEffectsMap) {
+ if (auto typeUuid = kUuidNameTypeMap.find(configEffects.first /* effect name */);
+ typeUuid != kUuidNameTypeMap.end()) {
+ const auto& configLibs = configEffects.second;
+ std::optional<AudioUuid> proxyUuid;
+ if (configLibs.proxyLibrary.has_value()) {
+ const auto& proxyLib = configLibs.proxyLibrary.value();
+ proxyUuid = proxyLib.uuid;
+ }
+ for (const auto& configLib : configLibs.libraries) {
+ createIdentityWithConfig(configLib, typeUuid->second, proxyUuid);
+ }
+ } else {
+ LOG(ERROR) << __func__ << ": can not find type UUID for effect " << configEffects.first
+ << " skipping!";
+ }
+ }
+}
+
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectImpl.cpp b/audio/aidl/default/EffectImpl.cpp
new file mode 100644
index 0000000..2754bb6
--- /dev/null
+++ b/audio/aidl/default/EffectImpl.cpp
@@ -0,0 +1,256 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_EffectImpl"
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectTypes.h"
+#include "include/effect-impl/EffectTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus EffectImpl::open(const Parameter::Common& common,
+ const std::optional<Parameter::Specific>& specific,
+ OpenEffectReturn* ret) {
+ LOG(DEBUG) << __func__;
+ {
+ std::lock_guard lg(mMutex);
+ RETURN_OK_IF(mState != State::INIT);
+ mContext = createContext(common);
+ RETURN_IF(!mContext, EX_ILLEGAL_ARGUMENT, "createContextFailed");
+ setContext(mContext);
+ }
+
+ RETURN_IF_ASTATUS_NOT_OK(setParameterCommon(common), "setCommParamErr");
+ if (specific.has_value()) {
+ RETURN_IF_ASTATUS_NOT_OK(setParameterSpecific(specific.value()), "setSpecParamErr");
+ }
+
+ RETURN_IF(createThread(LOG_TAG) != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
+ "FailedToCreateWorker");
+
+ {
+ std::lock_guard lg(mMutex);
+ mContext->dupeFmq(ret);
+ mState = State::IDLE;
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectImpl::close() {
+ std::lock_guard lg(mMutex);
+ RETURN_OK_IF(mState == State::INIT);
+ RETURN_IF(mState == State::PROCESSING, EX_ILLEGAL_STATE, "closeAtProcessing");
+
+ // stop the worker thread, ignore the return code
+ RETURN_IF(destroyThread() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
+ "FailedToDestroyWorker");
+ RETURN_IF(releaseContext() != RetCode::SUCCESS, EX_UNSUPPORTED_OPERATION,
+ "FailedToCreateWorker");
+ mState = State::INIT;
+ LOG(DEBUG) << __func__;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectImpl::setParameter(const Parameter& param) {
+ LOG(DEBUG) << __func__ << " with: " << param.toString();
+
+ auto tag = param.getTag();
+ switch (tag) {
+ case Parameter::common:
+ case Parameter::deviceDescription:
+ case Parameter::mode:
+ case Parameter::source:
+ FALLTHROUGH_INTENDED;
+ case Parameter::volumeStereo:
+ return setParameterCommon(param);
+ case Parameter::specific: {
+ return setParameterSpecific(param.get<Parameter::specific>());
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "ParameterNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus EffectImpl::getParameter(const Parameter::Id& id, Parameter* param) {
+ LOG(DEBUG) << __func__ << id.toString();
+ auto tag = id.getTag();
+ switch (tag) {
+ case Parameter::Id::commonTag: {
+ RETURN_IF_ASTATUS_NOT_OK(getParameterCommon(id.get<Parameter::Id::commonTag>(), param),
+ "CommonParamNotSupported");
+ break;
+ }
+ case Parameter::Id::vendorEffectTag: {
+ LOG(DEBUG) << __func__ << " noop for vendor tag";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "vendortagNotSupported");
+ }
+ default: {
+ Parameter::Specific specific;
+ RETURN_IF_ASTATUS_NOT_OK(getParameterSpecific(id, &specific), "SpecParamNotSupported");
+ param->set<Parameter::specific>(specific);
+ break;
+ }
+ }
+ LOG(DEBUG) << __func__ << param->toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectImpl::setParameterCommon(const Parameter& param) {
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ auto tag = param.getTag();
+ switch (tag) {
+ case Parameter::common:
+ RETURN_IF(mContext->setCommon(param.get<Parameter::common>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setCommFailed");
+ break;
+ case Parameter::deviceDescription:
+ RETURN_IF(mContext->setOutputDevice(param.get<Parameter::deviceDescription>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setDeviceFailed");
+ break;
+ case Parameter::mode:
+ RETURN_IF(mContext->setAudioMode(param.get<Parameter::mode>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setModeFailed");
+ break;
+ case Parameter::source:
+ RETURN_IF(mContext->setAudioSource(param.get<Parameter::source>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setSourceFailed");
+ break;
+ case Parameter::volumeStereo:
+ RETURN_IF(mContext->setVolumeStereo(param.get<Parameter::volumeStereo>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setVolumeStereoFailed");
+ break;
+ default: {
+ LOG(ERROR) << __func__ << " unsupportedParameterTag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "commonParamNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectImpl::getParameterCommon(const Parameter::Tag& tag, Parameter* param) {
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+ switch (tag) {
+ case Parameter::common: {
+ param->set<Parameter::common>(mContext->getCommon());
+ break;
+ }
+ case Parameter::deviceDescription: {
+ param->set<Parameter::deviceDescription>(mContext->getOutputDevice());
+ break;
+ }
+ case Parameter::mode: {
+ param->set<Parameter::mode>(mContext->getAudioMode());
+ break;
+ }
+ case Parameter::source: {
+ param->set<Parameter::source>(mContext->getAudioSource());
+ break;
+ }
+ case Parameter::volumeStereo: {
+ param->set<Parameter::volumeStereo>(mContext->getVolumeStereo());
+ break;
+ }
+ default: {
+ LOG(DEBUG) << __func__ << " unsupported tag " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "tagNotSupported");
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectImpl::getState(State* state) {
+ std::lock_guard lg(mMutex);
+ *state = mState;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EffectImpl::command(CommandId command) {
+ std::lock_guard lg(mMutex);
+ LOG(DEBUG) << __func__ << ": receive command: " << toString(command) << " at state "
+ << toString(mState);
+ RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "CommandStateError");
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ switch (command) {
+ case CommandId::START:
+ RETURN_IF(mState == State::INIT, EX_ILLEGAL_STATE, "instanceNotOpen");
+ RETURN_OK_IF(mState == State::PROCESSING);
+ RETURN_IF_ASTATUS_NOT_OK(commandStart(), "commandStartFailed");
+ mState = State::PROCESSING;
+ startThread();
+ return ndk::ScopedAStatus::ok();
+ case CommandId::STOP:
+ RETURN_OK_IF(mState == State::IDLE);
+ mState = State::IDLE;
+ RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed");
+ stopThread();
+ return ndk::ScopedAStatus::ok();
+ case CommandId::RESET:
+ RETURN_OK_IF(mState == State::IDLE);
+ mState = State::IDLE;
+ RETURN_IF_ASTATUS_NOT_OK(commandStop(), "commandStopFailed");
+ stopThread();
+ mContext->resetBuffer();
+ return ndk::ScopedAStatus::ok();
+ default:
+ LOG(ERROR) << __func__ << " instance still processing";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "CommandIdNotSupported");
+ }
+ LOG(DEBUG) << __func__ << " transfer to state: " << toString(mState);
+ return ndk::ScopedAStatus::ok();
+}
+
+void EffectImpl::cleanUp() {
+ command(CommandId::STOP);
+ close();
+}
+
+IEffect::Status EffectImpl::status(binder_status_t status, size_t consumed, size_t produced) {
+ IEffect::Status ret;
+ ret.status = status;
+ ret.fmqConsumed = consumed;
+ ret.fmqProduced = produced;
+ return ret;
+}
+
+// A placeholder processing implementation to copy samples from input to output
+IEffect::Status EffectImpl::effectProcessImpl(float* in, float* out, int processSamples) {
+ // lock before access context/parameters
+ std::lock_guard lg(mMutex);
+ IEffect::Status status = {EX_NULL_POINTER, 0, 0};
+ RETURN_VALUE_IF(!mContext, status, "nullContext");
+ auto frameSize = mContext->getInputFrameSize();
+ RETURN_VALUE_IF(0 == frameSize, status, "frameSizeIs0");
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " samples " << processSamples
+ << " frames " << processSamples * sizeof(float) / frameSize;
+ for (int i = 0; i < processSamples; i++) {
+ *out++ = *in++;
+ }
+ LOG(DEBUG) << __func__ << " done processing " << processSamples << " samples";
+ return {STATUS_OK, processSamples, processSamples};
+}
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/EffectMain.cpp b/audio/aidl/default/EffectMain.cpp
index 3219dd6..ca81204 100644
--- a/audio/aidl/default/EffectMain.cpp
+++ b/audio/aidl/default/EffectMain.cpp
@@ -19,21 +19,31 @@
#include <android-base/logging.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <system/audio_config.h>
+
+/** Default name of effect configuration file. */
+static const char* kDefaultConfigName = "audio_effects_config.xml";
int main() {
// This is a debug implementation, always enable debug logging.
android::base::SetMinimumLogSeverity(::android::base::DEBUG);
ABinderProcess_setThreadPoolMaxThreadCount(0);
+ auto configFile = android::audio_find_readable_configuration_file(kDefaultConfigName);
+ if (configFile == "") {
+ LOG(ERROR) << __func__ << ": config file " << kDefaultConfigName << " not found!";
+ return EXIT_FAILURE;
+ }
+ LOG(DEBUG) << __func__ << ": start factory with configFile:" << configFile;
auto effectFactory =
- ndk::SharedRefBase::make<aidl::android::hardware::audio::effect::Factory>();
+ ndk::SharedRefBase::make<aidl::android::hardware::audio::effect::Factory>(configFile);
std::string serviceName = std::string() + effectFactory->descriptor + "/default";
binder_status_t status =
AServiceManager_addService(effectFactory->asBinder().get(), serviceName.c_str());
CHECK_EQ(STATUS_OK, status);
- LOG(DEBUG) << __func__ << ": effectFactoryName:" << serviceName;
+ LOG(DEBUG) << __func__ << ": effectFactory: " << serviceName << " start";
ABinderProcess_joinThreadPool();
return EXIT_FAILURE; // should not reach
}
diff --git a/audio/aidl/default/EffectThread.cpp b/audio/aidl/default/EffectThread.cpp
new file mode 100644
index 0000000..80f120b
--- /dev/null
+++ b/audio/aidl/default/EffectThread.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "AHAL_EffectThread"
+#include <android-base/logging.h>
+#include <pthread.h>
+#include <sys/resource.h>
+
+#include "effect-impl/EffectThread.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+EffectThread::EffectThread() {
+ LOG(DEBUG) << __func__;
+}
+
+EffectThread::~EffectThread() {
+ destroyThread();
+ LOG(DEBUG) << __func__ << " done";
+};
+
+RetCode EffectThread::createThread(const std::string& name, const int priority) {
+ if (mThread.joinable()) {
+ LOG(WARNING) << __func__ << " thread already created, no-op";
+ return RetCode::SUCCESS;
+ }
+ mName = name;
+ mPriority = priority;
+ mThread = std::thread(&EffectThread::threadLoop, this);
+ LOG(DEBUG) << __func__ << " " << name << " priority " << mPriority << " done";
+ return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::destroyThread() {
+ {
+ std::lock_guard lg(mMutex);
+ mStop = mExit = true;
+ }
+ mCv.notify_one();
+
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+ LOG(DEBUG) << __func__ << " done";
+ return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::startThread() {
+ if (!mThread.joinable()) {
+ LOG(ERROR) << __func__ << " thread already destroyed";
+ return RetCode::ERROR_THREAD;
+ }
+
+ {
+ std::lock_guard lg(mMutex);
+ if (!mStop) {
+ LOG(WARNING) << __func__ << " already start";
+ return RetCode::SUCCESS;
+ }
+ mStop = false;
+ }
+
+ mCv.notify_one();
+ LOG(DEBUG) << __func__ << " done";
+ return RetCode::SUCCESS;
+}
+
+RetCode EffectThread::stopThread() {
+ if (!mThread.joinable()) {
+ LOG(ERROR) << __func__ << " thread already destroyed";
+ return RetCode::ERROR_THREAD;
+ }
+
+ {
+ std::lock_guard lg(mMutex);
+ if (mStop) {
+ LOG(WARNING) << __func__ << " already stop";
+ return RetCode::SUCCESS;
+ }
+ mStop = true;
+ }
+ LOG(DEBUG) << __func__ << " done";
+ return RetCode::SUCCESS;
+}
+
+void EffectThread::threadLoop() {
+ pthread_setname_np(pthread_self(), mName.substr(0, MAX_TASK_COMM_LEN - 1).c_str());
+ setpriority(PRIO_PROCESS, 0, mPriority);
+ while (true) {
+ bool needExit = false;
+ {
+ std::unique_lock l(mMutex);
+ mCv.wait(l, [&]() REQUIRES(mMutex) {
+ needExit = mExit;
+ return mExit || !mStop;
+ });
+ }
+ if (needExit) {
+ LOG(WARNING) << __func__ << " EXIT!";
+ return;
+ }
+ // process without lock
+ process();
+ }
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index deaca49..6863fe3 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -25,6 +25,7 @@
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
#include "core-impl/Module.h"
+#include "core-impl/Telephony.h"
#include "core-impl/utils.h"
using aidl::android::hardware::audio::common::SinkMetadata;
@@ -245,6 +246,15 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Module::getTelephony(std::shared_ptr<ITelephony>* _aidl_return) {
+ if (mTelephony == nullptr) {
+ mTelephony = ndk::SharedRefBase::make<Telephony>();
+ }
+ *_aidl_return = mTelephony;
+ LOG(DEBUG) << __func__ << ": returning instance of ITelephony: " << _aidl_return->get();
+ return ndk::ScopedAStatus::ok();
+}
+
ndk::ScopedAStatus Module::connectExternalDevice(const AudioPort& in_templateIdAndAdditionalData,
AudioPort* _aidl_return) {
const int32_t templateId = in_templateIdAndAdditionalData.id;
@@ -779,4 +789,60 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
}
+ndk::ScopedAStatus Module::getMasterMute(bool* _aidl_return) {
+ *_aidl_return = mMasterMute;
+ LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::setMasterMute(bool in_mute) {
+ LOG(DEBUG) << __func__ << ": " << in_mute;
+ mMasterMute = in_mute;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::getMasterVolume(float* _aidl_return) {
+ *_aidl_return = mMasterVolume;
+ LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::setMasterVolume(float in_volume) {
+ LOG(DEBUG) << __func__ << ": " << in_volume;
+ if (in_volume >= 0.0f && in_volume <= 1.0f) {
+ mMasterVolume = in_volume;
+ return ndk::ScopedAStatus::ok();
+ }
+ LOG(ERROR) << __func__ << ": invalid master volume value: " << in_volume;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+}
+
+ndk::ScopedAStatus Module::getMicMute(bool* _aidl_return) {
+ *_aidl_return = mMicMute;
+ LOG(DEBUG) << __func__ << ": returning " << *_aidl_return;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::setMicMute(bool in_mute) {
+ LOG(DEBUG) << __func__ << ": " << in_mute;
+ mMicMute = in_mute;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::updateAudioMode(AudioMode in_mode) {
+ // No checks for supported audio modes here, it's an informative notification.
+ LOG(DEBUG) << __func__ << ": " << toString(in_mode);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::updateScreenRotation(ScreenRotation in_rotation) {
+ LOG(DEBUG) << __func__ << ": " << toString(in_rotation);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Module::updateScreenState(bool in_isTurnedOn) {
+ LOG(DEBUG) << __func__ << ": " << in_isTurnedOn;
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Stream.cpp b/audio/aidl/default/Stream.cpp
index 312df72..21dc4b6 100644
--- a/audio/aidl/default/Stream.cpp
+++ b/audio/aidl/default/Stream.cpp
@@ -85,126 +85,344 @@
return "";
}
+void StreamWorkerCommonLogic::populateReply(StreamDescriptor::Reply* reply,
+ bool isConnected) const {
+ if (isConnected) {
+ reply->status = STATUS_OK;
+ reply->observable.frames = mFrameCount;
+ reply->observable.timeNs = ::android::elapsedRealtimeNano();
+ } else {
+ reply->status = STATUS_NO_INIT;
+ }
+}
+
const std::string StreamInWorkerLogic::kThreadName = "reader";
StreamInWorkerLogic::Status StreamInWorkerLogic::cycle() {
StreamDescriptor::Command command{};
if (!mCommandMQ->readBlocking(&command, 1)) {
LOG(ERROR) << __func__ << ": reading of command from MQ failed";
+ mState = StreamDescriptor::State::ERROR;
return Status::ABORT;
}
StreamDescriptor::Reply reply{};
- if (command.code == StreamContext::COMMAND_EXIT &&
- command.fmqByteCount == mInternalCommandCookie) {
- LOG(DEBUG) << __func__ << ": received EXIT command";
- // This is an internal command, no need to reply.
- return Status::EXIT;
- } else if (command.code == StreamDescriptor::COMMAND_BURST && command.fmqByteCount >= 0) {
- LOG(DEBUG) << __func__ << ": received BURST read command for " << command.fmqByteCount
- << " bytes";
- usleep(3000); // Simulate a blocking call into the driver.
- const size_t byteCount = std::min({static_cast<size_t>(command.fmqByteCount),
- mDataMQ->availableToWrite(), mDataBufferSize});
- const bool isConnected = mIsConnected;
- // Simulate reading of data, or provide zeroes if the stream is not connected.
- for (size_t i = 0; i < byteCount; ++i) {
- using buffer_type = decltype(mDataBuffer)::element_type;
- constexpr int kBufferValueRange = std::numeric_limits<buffer_type>::max() -
- std::numeric_limits<buffer_type>::min() + 1;
- mDataBuffer[i] = isConnected ? (std::rand() % kBufferValueRange) +
- std::numeric_limits<buffer_type>::min()
- : 0;
- }
- bool success = byteCount > 0 ? mDataMQ->write(&mDataBuffer[0], byteCount) : true;
- if (success) {
- LOG(DEBUG) << __func__ << ": writing of " << byteCount << " bytes into data MQ"
- << " succeeded; connected? " << isConnected;
- // Frames are provided and counted regardless of connection status.
- reply.fmqByteCount = byteCount;
- mFrameCount += byteCount / mFrameSize;
- if (isConnected) {
- reply.status = STATUS_OK;
- reply.observable.frames = mFrameCount;
- reply.observable.timeNs = ::android::elapsedRealtimeNano();
+ reply.status = STATUS_BAD_VALUE;
+ using Tag = StreamDescriptor::Command::Tag;
+ switch (command.getTag()) {
+ case Tag::hal_reserved_exit:
+ if (const int32_t cookie = command.get<Tag::hal_reserved_exit>();
+ cookie == mInternalCommandCookie) {
+ LOG(DEBUG) << __func__ << ": received EXIT command";
+ setClosed();
+ // This is an internal command, no need to reply.
+ return Status::EXIT;
} else {
+ LOG(WARNING) << __func__ << ": EXIT command has a bad cookie: " << cookie;
+ }
+ break;
+ case Tag::start:
+ LOG(DEBUG) << __func__ << ": received START read command";
+ if (mState == StreamDescriptor::State::STANDBY ||
+ mState == StreamDescriptor::State::DRAINING) {
+ populateReply(&reply, mIsConnected);
+ mState = mState == StreamDescriptor::State::STANDBY
+ ? StreamDescriptor::State::IDLE
+ : StreamDescriptor::State::ACTIVE;
+ } else {
+ LOG(WARNING) << __func__ << ": START command can not be handled in the state "
+ << toString(mState);
reply.status = STATUS_INVALID_OPERATION;
}
- } else {
- LOG(WARNING) << __func__ << ": writing of " << byteCount
- << " bytes of data to MQ failed";
- reply.status = STATUS_NOT_ENOUGH_DATA;
- }
- reply.latencyMs = Module::kLatencyMs;
- } else {
- LOG(WARNING) << __func__ << ": invalid command (" << command.toString()
- << ") or count: " << command.fmqByteCount;
- reply.status = STATUS_BAD_VALUE;
+ break;
+ case Tag::burst:
+ if (const int32_t fmqByteCount = command.get<Tag::burst>(); fmqByteCount >= 0) {
+ LOG(DEBUG) << __func__ << ": received BURST read command for " << fmqByteCount
+ << " bytes";
+ if (mState == StreamDescriptor::State::IDLE ||
+ mState == StreamDescriptor::State::ACTIVE ||
+ mState == StreamDescriptor::State::PAUSED ||
+ mState == StreamDescriptor::State::DRAINING) {
+ if (!read(fmqByteCount, &reply)) {
+ mState = StreamDescriptor::State::ERROR;
+ }
+ if (mState == StreamDescriptor::State::IDLE ||
+ mState == StreamDescriptor::State::PAUSED) {
+ mState = StreamDescriptor::State::ACTIVE;
+ } else if (mState == StreamDescriptor::State::DRAINING) {
+ // To simplify the reference code, we assume that the read operation
+ // has consumed all the data remaining in the hardware buffer.
+ // TODO: Provide parametrization on the duration of draining to test
+ // handling of commands during the 'DRAINING' state.
+ mState = StreamDescriptor::State::STANDBY;
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": BURST command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": invalid burst byte count: " << fmqByteCount;
+ }
+ break;
+ case Tag::drain:
+ LOG(DEBUG) << __func__ << ": received DRAIN read command";
+ if (mState == StreamDescriptor::State::ACTIVE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::DRAINING;
+ } else {
+ LOG(WARNING) << __func__ << ": DRAIN command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::standby:
+ LOG(DEBUG) << __func__ << ": received STANDBY read command";
+ if (mState == StreamDescriptor::State::IDLE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::STANDBY;
+ } else {
+ LOG(WARNING) << __func__ << ": FLUSH command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::pause:
+ LOG(DEBUG) << __func__ << ": received PAUSE read command";
+ if (mState == StreamDescriptor::State::ACTIVE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::PAUSED;
+ } else {
+ LOG(WARNING) << __func__ << ": PAUSE command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::flush:
+ LOG(DEBUG) << __func__ << ": received FLUSH read command";
+ if (mState == StreamDescriptor::State::PAUSED) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::STANDBY;
+ } else {
+ LOG(WARNING) << __func__ << ": FLUSH command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
}
+ reply.state = mState;
LOG(DEBUG) << __func__ << ": writing reply " << reply.toString();
if (!mReplyMQ->writeBlocking(&reply, 1)) {
LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
+ mState = StreamDescriptor::State::ERROR;
return Status::ABORT;
}
return Status::CONTINUE;
}
+bool StreamInWorkerLogic::read(size_t clientSize, StreamDescriptor::Reply* reply) {
+ // Can switch the state to ERROR if a driver error occurs.
+ const size_t byteCount = std::min({clientSize, mDataMQ->availableToWrite(), mDataBufferSize});
+ const bool isConnected = mIsConnected;
+ bool fatal = false;
+ // Simulate reading of data, or provide zeroes if the stream is not connected.
+ for (size_t i = 0; i < byteCount; ++i) {
+ using buffer_type = decltype(mDataBuffer)::element_type;
+ constexpr int kBufferValueRange = std::numeric_limits<buffer_type>::max() -
+ std::numeric_limits<buffer_type>::min() + 1;
+ mDataBuffer[i] = isConnected ? (std::rand() % kBufferValueRange) +
+ std::numeric_limits<buffer_type>::min()
+ : 0;
+ }
+ usleep(3000); // Simulate a blocking call into the driver.
+ // Set 'fatal = true' if a driver error occurs.
+ if (bool success = byteCount > 0 ? mDataMQ->write(&mDataBuffer[0], byteCount) : true; success) {
+ LOG(DEBUG) << __func__ << ": writing of " << byteCount << " bytes into data MQ"
+ << " succeeded; connected? " << isConnected;
+ // Frames are provided and counted regardless of connection status.
+ reply->fmqByteCount += byteCount;
+ mFrameCount += byteCount / mFrameSize;
+ populateReply(reply, isConnected);
+ } else {
+ LOG(WARNING) << __func__ << ": writing of " << byteCount << " bytes of data to MQ failed";
+ reply->status = STATUS_NOT_ENOUGH_DATA;
+ }
+ reply->latencyMs = Module::kLatencyMs;
+ return !fatal;
+}
+
const std::string StreamOutWorkerLogic::kThreadName = "writer";
StreamOutWorkerLogic::Status StreamOutWorkerLogic::cycle() {
StreamDescriptor::Command command{};
if (!mCommandMQ->readBlocking(&command, 1)) {
LOG(ERROR) << __func__ << ": reading of command from MQ failed";
+ mState = StreamDescriptor::State::ERROR;
return Status::ABORT;
}
StreamDescriptor::Reply reply{};
- if (command.code == StreamContext::COMMAND_EXIT &&
- command.fmqByteCount == mInternalCommandCookie) {
- LOG(DEBUG) << __func__ << ": received EXIT command";
- // This is an internal command, no need to reply.
- return Status::EXIT;
- } else if (command.code == StreamDescriptor::COMMAND_BURST && command.fmqByteCount >= 0) {
- LOG(DEBUG) << __func__ << ": received BURST write command for " << command.fmqByteCount
- << " bytes";
- const size_t byteCount = std::min({static_cast<size_t>(command.fmqByteCount),
- mDataMQ->availableToRead(), mDataBufferSize});
- bool success = byteCount > 0 ? mDataMQ->read(&mDataBuffer[0], byteCount) : true;
- if (success) {
- const bool isConnected = mIsConnected;
- LOG(DEBUG) << __func__ << ": reading of " << byteCount << " bytes from data MQ"
- << " succeeded; connected? " << isConnected;
- // Frames are consumed and counted regardless of connection status.
- reply.fmqByteCount = byteCount;
- mFrameCount += byteCount / mFrameSize;
- if (isConnected) {
- reply.status = STATUS_OK;
- reply.observable.frames = mFrameCount;
- reply.observable.timeNs = ::android::elapsedRealtimeNano();
+ reply.status = STATUS_BAD_VALUE;
+ using Tag = StreamDescriptor::Command::Tag;
+ switch (command.getTag()) {
+ case Tag::hal_reserved_exit:
+ if (const int32_t cookie = command.get<Tag::hal_reserved_exit>();
+ cookie == mInternalCommandCookie) {
+ LOG(DEBUG) << __func__ << ": received EXIT command";
+ setClosed();
+ // This is an internal command, no need to reply.
+ return Status::EXIT;
} else {
+ LOG(WARNING) << __func__ << ": EXIT command has a bad cookie: " << cookie;
+ }
+ break;
+ case Tag::start:
+ LOG(DEBUG) << __func__ << ": received START write command";
+ switch (mState) {
+ case StreamDescriptor::State::STANDBY:
+ mState = StreamDescriptor::State::IDLE;
+ break;
+ case StreamDescriptor::State::PAUSED:
+ mState = StreamDescriptor::State::ACTIVE;
+ break;
+ case StreamDescriptor::State::DRAIN_PAUSED:
+ mState = StreamDescriptor::State::PAUSED;
+ break;
+ default:
+ LOG(WARNING) << __func__ << ": START command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ if (reply.status != STATUS_INVALID_OPERATION) {
+ populateReply(&reply, mIsConnected);
+ }
+ break;
+ case Tag::burst:
+ if (const int32_t fmqByteCount = command.get<Tag::burst>(); fmqByteCount >= 0) {
+ LOG(DEBUG) << __func__ << ": received BURST write command for " << fmqByteCount
+ << " bytes";
+ if (mState !=
+ StreamDescriptor::State::ERROR) { // BURST can be handled in all valid states
+ if (!write(fmqByteCount, &reply)) {
+ mState = StreamDescriptor::State::ERROR;
+ }
+ if (mState == StreamDescriptor::State::STANDBY ||
+ mState == StreamDescriptor::State::DRAIN_PAUSED) {
+ mState = StreamDescriptor::State::PAUSED;
+ } else if (mState == StreamDescriptor::State::IDLE ||
+ mState == StreamDescriptor::State::DRAINING) {
+ mState = StreamDescriptor::State::ACTIVE;
+ } // When in 'ACTIVE' and 'PAUSED' do not need to change the state.
+ } else {
+ LOG(WARNING) << __func__ << ": BURST command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ } else {
+ LOG(WARNING) << __func__ << ": invalid burst byte count: " << fmqByteCount;
+ }
+ break;
+ case Tag::drain:
+ LOG(DEBUG) << __func__ << ": received DRAIN write command";
+ if (mState == StreamDescriptor::State::ACTIVE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::IDLE;
+ // Since there is no actual hardware that would be draining the buffer,
+ // in order to simplify the reference code, we assume that draining
+ // happens instantly, thus skipping the 'DRAINING' state.
+ // TODO: Provide parametrization on the duration of draining to test
+ // handling of commands during the 'DRAINING' state.
+ } else {
+ LOG(WARNING) << __func__ << ": DRAIN command can not be handled in the state "
+ << toString(mState);
reply.status = STATUS_INVALID_OPERATION;
}
- usleep(3000); // Simulate a blocking call into the driver.
- } else {
- LOG(WARNING) << __func__ << ": reading of " << byteCount
- << " bytes of data from MQ failed";
- reply.status = STATUS_NOT_ENOUGH_DATA;
- }
- reply.latencyMs = Module::kLatencyMs;
- } else {
- LOG(WARNING) << __func__ << ": invalid command (" << command.toString()
- << ") or count: " << command.fmqByteCount;
- reply.status = STATUS_BAD_VALUE;
+ break;
+ case Tag::standby:
+ LOG(DEBUG) << __func__ << ": received STANDBY write command";
+ if (mState == StreamDescriptor::State::IDLE) {
+ usleep(1000); // Simulate a blocking call into the driver.
+ populateReply(&reply, mIsConnected);
+ // Can switch the state to ERROR if a driver error occurs.
+ mState = StreamDescriptor::State::STANDBY;
+ } else {
+ LOG(WARNING) << __func__ << ": STANDBY command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::pause:
+ LOG(DEBUG) << __func__ << ": received PAUSE write command";
+ if (mState == StreamDescriptor::State::ACTIVE ||
+ mState == StreamDescriptor::State::DRAINING) {
+ populateReply(&reply, mIsConnected);
+ mState = mState == StreamDescriptor::State::ACTIVE
+ ? StreamDescriptor::State::PAUSED
+ : StreamDescriptor::State::DRAIN_PAUSED;
+ } else {
+ LOG(WARNING) << __func__ << ": PAUSE command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
+ case Tag::flush:
+ LOG(DEBUG) << __func__ << ": received FLUSH write command";
+ if (mState == StreamDescriptor::State::PAUSED ||
+ mState == StreamDescriptor::State::DRAIN_PAUSED) {
+ populateReply(&reply, mIsConnected);
+ mState = StreamDescriptor::State::IDLE;
+ } else {
+ LOG(WARNING) << __func__ << ": FLUSH command can not be handled in the state "
+ << toString(mState);
+ reply.status = STATUS_INVALID_OPERATION;
+ }
+ break;
}
+ reply.state = mState;
LOG(DEBUG) << __func__ << ": writing reply " << reply.toString();
if (!mReplyMQ->writeBlocking(&reply, 1)) {
LOG(ERROR) << __func__ << ": writing of reply " << reply.toString() << " to MQ failed";
+ mState = StreamDescriptor::State::ERROR;
return Status::ABORT;
}
return Status::CONTINUE;
}
+bool StreamOutWorkerLogic::write(size_t clientSize, StreamDescriptor::Reply* reply) {
+ const size_t readByteCount = mDataMQ->availableToRead();
+ // Amount of data that the HAL module is going to actually use.
+ const size_t byteCount = std::min({clientSize, readByteCount, mDataBufferSize});
+ bool fatal = false;
+ if (bool success = readByteCount > 0 ? mDataMQ->read(&mDataBuffer[0], readByteCount) : true) {
+ const bool isConnected = mIsConnected;
+ LOG(DEBUG) << __func__ << ": reading of " << readByteCount << " bytes from data MQ"
+ << " succeeded; connected? " << isConnected;
+ // Frames are consumed and counted regardless of connection status.
+ reply->fmqByteCount += byteCount;
+ mFrameCount += byteCount / mFrameSize;
+ populateReply(reply, isConnected);
+ usleep(3000); // Simulate a blocking call into the driver.
+ // Set 'fatal = true' if a driver error occurs.
+ } else {
+ LOG(WARNING) << __func__ << ": reading of " << readByteCount
+ << " bytes of data from MQ failed";
+ reply->status = STATUS_NOT_ENOUGH_DATA;
+ }
+ reply->latencyMs = Module::kLatencyMs;
+ return !fatal;
+}
+
template <class Metadata, class StreamWorker>
StreamCommon<Metadata, StreamWorker>::~StreamCommon() {
- if (!mIsClosed) {
+ if (!isClosed()) {
LOG(ERROR) << __func__ << ": stream was not closed prior to destruction, resource leak";
stopWorker();
// The worker and the context should clean up by themselves via destructors.
@@ -214,13 +432,13 @@
template <class Metadata, class StreamWorker>
ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::close() {
LOG(DEBUG) << __func__;
- if (!mIsClosed) {
+ if (!isClosed()) {
stopWorker();
LOG(DEBUG) << __func__ << ": joining the worker thread...";
mWorker.stop();
LOG(DEBUG) << __func__ << ": worker thread joined";
mContext.reset();
- mIsClosed = true;
+ mWorker.setClosed();
return ndk::ScopedAStatus::ok();
} else {
LOG(ERROR) << __func__ << ": stream was already closed";
@@ -231,13 +449,14 @@
template <class Metadata, class StreamWorker>
void StreamCommon<Metadata, StreamWorker>::stopWorker() {
if (auto commandMQ = mContext.getCommandMQ(); commandMQ != nullptr) {
- LOG(DEBUG) << __func__ << ": asking the worker to stop...";
- StreamDescriptor::Command cmd;
- cmd.code = StreamContext::COMMAND_EXIT;
- cmd.fmqByteCount = mContext.getInternalCommandCookie();
- // FIXME: This can block in the case when the client wrote a command
- // while the stream worker's cycle is not running. Need to revisit
- // when implementing standby and pause/resume.
+ LOG(DEBUG) << __func__ << ": asking the worker to exit...";
+ auto cmd =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::hal_reserved_exit>(
+ mContext.getInternalCommandCookie());
+ // Note: never call 'pause' and 'resume' methods of StreamWorker
+ // in the HAL implementation. These methods are to be used by
+ // the client side only. Preventing the worker loop from running
+ // on the HAL side can cause a deadlock.
if (!commandMQ->writeBlocking(&cmd, 1)) {
LOG(ERROR) << __func__ << ": failed to write exit command to the MQ";
}
@@ -248,7 +467,7 @@
template <class Metadata, class StreamWorker>
ndk::ScopedAStatus StreamCommon<Metadata, StreamWorker>::updateMetadata(const Metadata& metadata) {
LOG(DEBUG) << __func__;
- if (!mIsClosed) {
+ if (!isClosed()) {
mMetadata = metadata;
return ndk::ScopedAStatus::ok();
}
diff --git a/audio/aidl/default/Telephony.cpp b/audio/aidl/default/Telephony.cpp
new file mode 100644
index 0000000..1854b35
--- /dev/null
+++ b/audio/aidl/default/Telephony.cpp
@@ -0,0 +1,41 @@
+/*
+ * 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/binder_to_string.h>
+#define LOG_TAG "AHAL_Telephony"
+#include <android-base/logging.h>
+
+#include "core-impl/Telephony.h"
+
+namespace aidl::android::hardware::audio::core {
+
+ndk::ScopedAStatus Telephony::getSupportedAudioModes(std::vector<AudioMode>* _aidl_return) {
+ *_aidl_return = mSupportedAudioModes;
+ LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Telephony::switchAudioMode(AudioMode in_mode) {
+ if (std::find(mSupportedAudioModes.begin(), mSupportedAudioModes.end(), in_mode) !=
+ mSupportedAudioModes.end()) {
+ LOG(DEBUG) << __func__ << ": " << toString(in_mode);
+ return ndk::ScopedAStatus::ok();
+ }
+ LOG(ERROR) << __func__ << ": unsupported mode " << toString(in_mode);
+ return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/audio_effects_config.xml b/audio/aidl/default/audio_effects_config.xml
new file mode 100644
index 0000000..f4ac8fe
--- /dev/null
+++ b/audio/aidl/default/audio_effects_config.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<audio_effects_conf version="2.0" xmlns="http://schemas.android.com/audio/audio_effects_conf/v2_0">
+ <!-- Overview.
+ This example config file was copy from existing one: frameworks/av/media/libeffects/data/
+ audio_effects.xml, with effect library names updated to AIDL libraries we currently have.
+
+ All "library" attributes in "effect" element must must match a "library" element with the
+ same value of the "name" attribute.
+ All "effect" attributes in "preprocess" and "postprocess" element must match an "effect"
+ element with the same value of the "name" attribute.
+
+ AIDL EffectFactory are relying on the "name" attribute in "effect" element to identify the
+ effect type, so it's necessary to have the mapping from name to effect type UUID. Make
+ sure to either use existing effect name as key of
+ ::android::hardware::audio::effect::kUuidNameTypeMap, or add a new {name, typeUUID} map
+ item to the kUuidNameTypeMap.
+
+ Existing audio_effects.xml should working without any change as long as:
+ 1. "path" attribute of "library" element matches with the actual effect library name.
+ 2. "name" attribute of "effect" and "effectProxy" element correctly added as key of
+ kUuidNameTypeMap, with value matches Identity.type in Descriptor.aidl.
+ 3. "uuid" attribute of "effect" element matches Identity.uuid in Descriptor.aidl.
+ 4. "uuid" attribute of "effectProxy" element matches Identity.proxy in Descriptor.aidl.
+ -->
+
+ <!-- List of effect libraries to load.
+ Each library element must contain a "name" attribute and a "path" attribute giving the
+ name of a library .so file on the target device.
+ -->
+ <libraries>
+ <library name="bassboostsw" path="libbassboostsw.so"/>
+ <library name="bundle" path="libbundleaidl.so"/>
+ <library name="dynamics_processingsw" path="libdynamicsprocessingsw.so"/>
+ <library name="equalizersw" path="libequalizersw.so"/>
+ <library name="haptic_generatorsw" path="libhapticgeneratorsw.so"/>
+ <library name="loudness_enhancersw" path="libloudnessenhancersw.so"/>
+ <library name="env_reverbsw" path="libenvreverbsw.so"/>
+ <library name="preset_reverbsw" path="libpresetreverbsw.so"/>
+ <library name="virtualizersw" path="libvirtualizersw.so"/>
+ <library name="visualizersw" path="libvisualizersw.so"/>
+ <library name="volumesw" path="libvolumesw.so"/>
+ </libraries>
+
+ <!-- list of effects to load.
+ Each "effect" element must contain a "name", "library" and a "uuid" attribute.
+ The value of the "library" attribute must correspond to the name of one library element in
+ the "libraries" element.
+ The "name" attribute used to specific effect type, and should be mapping to a key of
+ aidl::android::hardware::audio::effect::kUuidNameTypeMap.
+ The "uuid" attribute is the implementation specific UUID as specified by the effect vendor.
+
+ Effect proxy can be supported with "effectProxy" element, each sub-element should contain
+ "library" and "uuid" attribute, all other attributes were ignored. Framework side use
+ result of IFactory.queryEffects() to decide which effect implementation should be part of
+ proxy and which not.
+
+ Only "name", "library", and "uuid" attributes in "effects" element are meaningful and
+ parsed out by EffectConfig class, all other attributes are ignored.
+ Only "name" and "uuid" attributes in "effectProxy" element are meaningful and parsed out
+ by EffectConfig class, all other attributes are ignored.
+ -->
+
+ <effects>
+ <effect name="bassboost" library="bassboostsw" uuid="fa8181f2-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="dynamics_processing" library="dynamics_processingsw" uuid="fa818d78-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="haptic_generator" library="haptic_generatorsw" uuid="fa819110-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="loudness_enhancer" library="loudness_enhancersw" uuid="fa819610-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="env_reverb" library="env_reverbsw" uuid="fa819886-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="preset_reverb" library="preset_reverbsw" uuid="fa8199c6-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="virtualizer" library="virtualizersw" uuid="fa819d86-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="visualizer" library="visualizersw" uuid="fa81a0f6-588b-11ed-9b6a-0242ac120002"/>
+ <effect name="volume" library="volumesw" uuid="fa81a718-588b-11ed-9b6a-0242ac120002"/>
+ <effectProxy name="equalizer" uuid="c8e70ecd-48ca-456e-8a4f-0002a5d5c51b">
+ <libsw library="equalizersw" uuid="0bed4300-847d-11df-bb17-0002a5d5c51b"/>
+ <libsw library="bundle" uuid="ce772f20-847d-11df-bb17-0002a5d5c51b"/>
+ </effectProxy>
+ </effects>
+
+ <!-- Audio pre processor configurations.
+ The pre processor configuration is described in a "preprocess" element and consists in a
+ list of elements each describing pre processor settings for a given use case or "stream".
+ Each stream element has a "type" attribute corresponding to the input source used.
+ Valid types are these defined in system/hardware/interfaces/media/aidl/android/media/audio/
+ common/AudioSource.aidl.
+ Each "stream" element contains a list of "apply" elements indicating one effect to apply.
+ The effect to apply is designated by its name in the "effects" elements.
+ If there are more than one effect apply to one stream, the audio framework will apply them
+ in the same equence as they listed in "stream" element.
+
+ <preprocess>
+ <stream type="voice_communication">
+ <apply effect="aec"/>
+ <apply effect="ns"/>
+ </stream>
+ </preprocess>
+ -->
+
+ <!-- Audio post processor configurations.
+ The post processor configuration is described in a "postprocess" element and consists in a
+ list of elements each describing post processor settings for a given use case or "stream".
+ Each stream element has a "type" attribute corresponding to the stream type used.
+ Valid types are these defined in system/hardware/interfaces/media/aidl/android/media/audio/
+ common/AudioStreamType.aidl.
+ Each "stream" element contains a list of "apply" elements indicating one effect to apply.
+ The effect to apply is designated by its name in the "effects" elements.
+ If there are more than one effect apply to one stream, the audio framework will apply them
+ in the same equence as they listed in "stream" element.
+
+ <postprocess>
+ <stream type="music">
+ <apply effect="music_post_proc"/>
+ </stream>
+ <stream type="voice_call">
+ <apply effect="voice_post_proc"/>
+ </stream>
+ <stream type="notification">
+ <apply effect="notification_post_proc"/>
+ </stream>
+ </postprocess>
+ -->
+
+</audio_effects_conf>
diff --git a/audio/aidl/default/bassboost/Android.bp b/audio/aidl/default/bassboost/Android.bp
new file mode 100644
index 0000000..f22eb95
--- /dev/null
+++ b/audio/aidl/default/bassboost/Android.bp
@@ -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.
+ */
+
+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: "libbassboostsw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "BassBoostSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/bassboost/BassBoostSw.cpp b/audio/aidl/default/bassboost/BassBoostSw.cpp
new file mode 100644
index 0000000..c52d16f
--- /dev/null
+++ b/audio/aidl/default/bassboost/BassBoostSw.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_BassBoostSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "BassBoostSw.h"
+
+using aidl::android::hardware::audio::effect::BassBoostSw;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kBassBoostSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kBassBoostSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<BassBoostSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ return EX_NONE;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus BassBoostSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BassBoostSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::bassBoost != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ mSpecificParam = specific.get<Parameter::Specific::bassBoost>();
+ LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BassBoostSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::bassBoostTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ specific->set<Parameter::Specific::bassBoost>(mSpecificParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> BassBoostSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<BassBoostSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode BassBoostSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status BassBoostSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/bassboost/BassBoostSw.h b/audio/aidl/default/bassboost/BassBoostSw.h
new file mode 100644
index 0000000..90a8887
--- /dev/null
+++ b/audio/aidl/default/bassboost/BassBoostSw.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class BassBoostSwContext final : public EffectContext {
+ public:
+ BassBoostSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+ // TODO: add specific context here
+};
+
+class BassBoostSw final : public EffectImpl {
+ public:
+ BassBoostSw() { LOG(DEBUG) << __func__; }
+ ~BassBoostSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<BassBoostSwContext> mContext;
+ /* capabilities */
+ const BassBoost::Capability kCapability;
+ /* Effect descriptor */
+ const Descriptor kDescriptor = {
+ .common = {.id = {.type = kBassBoostTypeUUID,
+ .uuid = kBassBoostSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "BassBoostSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::bassBoost>(kCapability)};
+
+ /* parameters */
+ BassBoost mSpecificParam;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/config/audio_policy_configuration.xsd b/audio/aidl/default/config/audio_policy_configuration.xsd
new file mode 100644
index 0000000..2c18a1e
--- /dev/null
+++ b/audio/aidl/default/config/audio_policy_configuration.xsd
@@ -0,0 +1,829 @@
+<?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:enumeration value="AUDIO_FORMAT_APTX_ADAPTIVE_QLEA"/>
+ <xs:enumeration value="AUDIO_FORMAT_APTX_ADAPTIVE_R4"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS_HD_MA"/>
+ <xs:enumeration value="AUDIO_FORMAT_DTS_UHD_P2"/>
+ </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/aidl/default/dynamicProcessing/Android.bp b/audio/aidl/default/dynamicProcessing/Android.bp
new file mode 100644
index 0000000..3697ba3
--- /dev/null
+++ b/audio/aidl/default/dynamicProcessing/Android.bp
@@ -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.
+ */
+
+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: "libdynamicsprocessingsw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "DynamicsProcessingSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
new file mode 100644
index 0000000..3920a58
--- /dev/null
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.cpp
@@ -0,0 +1,119 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_DynamicsProcessingSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "DynamicsProcessingSw.h"
+
+using aidl::android::hardware::audio::effect::DynamicsProcessingSw;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kDynamicsProcessingSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kDynamicsProcessingSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<DynamicsProcessingSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ return EX_NONE;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus DynamicsProcessingSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DynamicsProcessingSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::dynamicsProcessing != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ mSpecificParam = specific.get<Parameter::Specific::dynamicsProcessing>();
+ LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus DynamicsProcessingSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::dynamicsProcessingTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ specific->set<Parameter::Specific::dynamicsProcessing>(mSpecificParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> DynamicsProcessingSw::createContext(
+ const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<DynamicsProcessingSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode DynamicsProcessingSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status DynamicsProcessingSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
new file mode 100644
index 0000000..2bc2762
--- /dev/null
+++ b/audio/aidl/default/dynamicProcessing/DynamicsProcessingSw.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class DynamicsProcessingSwContext final : public EffectContext {
+ public:
+ DynamicsProcessingSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+ // TODO: add specific context here
+};
+
+class DynamicsProcessingSw final : public EffectImpl {
+ public:
+ DynamicsProcessingSw() { LOG(DEBUG) << __func__; }
+ ~DynamicsProcessingSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<DynamicsProcessingSwContext> mContext;
+ /* capabilities */
+ const DynamicsProcessing::Capability kCapability;
+ /* Effect descriptor */
+ const Descriptor kDescriptor = {
+ .common = {.id = {.type = kDynamicsProcessingTypeUUID,
+ .uuid = kDynamicsProcessingSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "DynamicsProcessingSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::dynamicsProcessing>(kCapability)};
+
+ /* parameters */
+ DynamicsProcessing mSpecificParam;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/envReverb/Android.bp b/audio/aidl/default/envReverb/Android.bp
new file mode 100644
index 0000000..c239ee5
--- /dev/null
+++ b/audio/aidl/default/envReverb/Android.bp
@@ -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.
+ */
+
+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: "libenvreverbsw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "EnvReverbSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.cpp b/audio/aidl/default/envReverb/EnvReverbSw.cpp
new file mode 100644
index 0000000..ad447ab
--- /dev/null
+++ b/audio/aidl/default/envReverb/EnvReverbSw.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_EnvReverbSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "EnvReverbSw.h"
+
+using aidl::android::hardware::audio::effect::EnvReverbSw;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kEnvReverbSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kEnvReverbSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<EnvReverbSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ return EX_NONE;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus EnvReverbSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EnvReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::reverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ mSpecificParam = specific.get<Parameter::Specific::reverb>();
+ LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EnvReverbSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::reverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ specific->set<Parameter::Specific::reverb>(mSpecificParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EnvReverbSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<EnvReverbSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode EnvReverbSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EnvReverbSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/envReverb/EnvReverbSw.h b/audio/aidl/default/envReverb/EnvReverbSw.h
new file mode 100644
index 0000000..5a9ab27
--- /dev/null
+++ b/audio/aidl/default/envReverb/EnvReverbSw.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EnvReverbSwContext final : public EffectContext {
+ public:
+ EnvReverbSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+ // TODO: add specific context here
+};
+
+class EnvReverbSw final : public EffectImpl {
+ public:
+ EnvReverbSw() { LOG(DEBUG) << __func__; }
+ ~EnvReverbSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<EnvReverbSwContext> mContext;
+ /* capabilities */
+ const Reverb::Capability kCapability;
+ /* Effect descriptor */
+ const Descriptor kDescriptor = {
+ .common = {.id = {.type = kEnvReverbTypeUUID,
+ .uuid = kEnvReverbSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "EnvReverbSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::reverb>(kCapability)};
+
+ /* parameters */
+ Reverb mSpecificParam;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/equalizer/Android.bp b/audio/aidl/default/equalizer/Android.bp
index b842149..8de6b1a 100644
--- a/audio/aidl/default/equalizer/Android.bp
+++ b/audio/aidl/default/equalizer/Android.bp
@@ -24,20 +24,15 @@
}
cc_library_shared {
- name: "libequalizer",
- vendor: true,
- shared_libs: [
- "libbase",
- "libbinder_ndk",
- "libstagefright_foundation",
- ],
+ name: "libequalizersw",
defaults: [
+ "aidlaudioeffectservice_defaults",
"latest_android_media_audio_common_types_ndk_shared",
"latest_android_hardware_audio_effect_ndk_shared",
],
- include_dirs: ["hardware/interfaces/audio/aidl/default/include/equalizer-impl"],
srcs: [
- "Equalizer.cpp",
+ "EqualizerSw.cpp",
+ ":effectCommonFile",
],
visibility: [
"//hardware/interfaces/audio/aidl/default",
diff --git a/audio/aidl/default/equalizer/Equalizer.cpp b/audio/aidl/default/equalizer/Equalizer.cpp
deleted file mode 100644
index 8b157fa..0000000
--- a/audio/aidl/default/equalizer/Equalizer.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define LOG_TAG "AHAL_Equalizer"
-#include <android-base/logging.h>
-
-#include "Equalizer.h"
-
-namespace aidl::android::hardware::audio::effect {
-
-ndk::ScopedAStatus Equalizer::open() {
- LOG(DEBUG) << __func__;
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Equalizer::close() {
- LOG(DEBUG) << __func__;
- return ndk::ScopedAStatus::ok();
-}
-
-ndk::ScopedAStatus Equalizer::getDescriptor(Descriptor* _aidl_return) {
- LOG(DEBUG) << __func__ << "descriptor " << mDesc.toString();
- *_aidl_return = mDesc;
- return ndk::ScopedAStatus::ok();
-}
-
-} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/equalizer/EqualizerSw.cpp b/audio/aidl/default/equalizer/EqualizerSw.cpp
new file mode 100644
index 0000000..d61ef97
--- /dev/null
+++ b/audio/aidl/default/equalizer/EqualizerSw.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_EqualizerSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "EqualizerSw.h"
+
+using aidl::android::hardware::audio::effect::EqualizerSw;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kEqualizerSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kEqualizerSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<EqualizerSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus EqualizerSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDesc.toString();
+ *_aidl_return = kDesc;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus EqualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::equalizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& eqParam = specific.get<Parameter::Specific::equalizer>();
+ auto tag = eqParam.getTag();
+ switch (tag) {
+ case Equalizer::preset: {
+ RETURN_IF(mContext->setEqPreset(eqParam.get<Equalizer::preset>()) != RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ case Equalizer::bandLevels: {
+ RETURN_IF(mContext->setEqBandLevels(eqParam.get<Equalizer::bandLevels>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setBandLevelsFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "EqTagNotSupported");
+ }
+ }
+
+ LOG(ERROR) << __func__ << " unsupported eq param tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "ParamNotSupported");
+}
+
+ndk::ScopedAStatus EqualizerSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::equalizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto eqId = id.get<Parameter::Id::equalizerTag>();
+ auto eqIdTag = eqId.getTag();
+ switch (eqIdTag) {
+ case Equalizer::Id::commonTag:
+ return getParameterEqualizer(eqId.get<Equalizer::Id::commonTag>(), specific);
+ default:
+ LOG(ERROR) << __func__ << " tag " << toString(eqIdTag) << " not supported";
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "EqualizerTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus EqualizerSw::getParameterEqualizer(const Equalizer::Tag& tag,
+ Parameter::Specific* specific) {
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ Equalizer eqParam;
+ switch (tag) {
+ case Equalizer::bandLevels: {
+ eqParam.set<Equalizer::bandLevels>(mContext->getEqBandLevels());
+ break;
+ }
+ case Equalizer::preset: {
+ eqParam.set<Equalizer::preset>(mContext->getEqPreset());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " not handled tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "unsupportedTag");
+ }
+ }
+
+ specific->set<Parameter::Specific::equalizer>(eqParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> EqualizerSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<EqualizerSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode EqualizerSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status EqualizerSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/equalizer/EqualizerSw.h b/audio/aidl/default/equalizer/EqualizerSw.h
new file mode 100644
index 0000000..aa4587a
--- /dev/null
+++ b/audio/aidl/default/equalizer/EqualizerSw.h
@@ -0,0 +1,125 @@
+/*
+ * 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/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EqualizerSwContext final : public EffectContext {
+ public:
+ EqualizerSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+
+ RetCode setEqPreset(const int& presetIdx) {
+ if (presetIdx < 0 || presetIdx >= NUM_OF_PRESETS) {
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ mPreset = presetIdx;
+ return RetCode::SUCCESS;
+ }
+ int getEqPreset() { return mPreset; }
+
+ RetCode setEqBandLevels(const std::vector<Equalizer::BandLevel>& bandLevels) {
+ if (bandLevels.size() > NUM_OF_BANDS) {
+ LOG(ERROR) << __func__ << " return because size exceed " << NUM_OF_BANDS;
+ return RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ RetCode ret = RetCode::SUCCESS;
+ for (auto& it : bandLevels) {
+ if (it.index >= NUM_OF_BANDS || it.index < 0) {
+ LOG(ERROR) << __func__ << " index illegal, skip: " << it.index << " - "
+ << it.levelMb;
+ ret = RetCode::ERROR_ILLEGAL_PARAMETER;
+ }
+ mBandLevels[it.index] = it.levelMb;
+ }
+ return ret;
+ }
+
+ std::vector<Equalizer::BandLevel> getEqBandLevels() {
+ std::vector<Equalizer::BandLevel> bandLevels;
+ for (int i = 0; i < NUM_OF_BANDS; i++) {
+ bandLevels.push_back({i, mBandLevels[i]});
+ }
+ return bandLevels;
+ }
+
+ private:
+ static const int NUM_OF_BANDS = 5;
+ static const int NUM_OF_PRESETS = 10;
+ static const int PRESET_CUSTOM = -1;
+ // preset band level
+ int mPreset = PRESET_CUSTOM;
+ int32_t mBandLevels[NUM_OF_BANDS] = {3, 0, 0, 0, 3};
+
+ // Add equalizer specific context for processing here
+};
+
+class EqualizerSw final : public EffectImpl {
+ public:
+ EqualizerSw() { LOG(DEBUG) << __func__; }
+ ~EqualizerSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<EqualizerSwContext> mContext;
+ /* capabilities */
+ const std::vector<Equalizer::BandFrequency> mBandFrequency = {{0, 30000, 120000},
+ {1, 120001, 460000},
+ {2, 460001, 1800000},
+ {3, 1800001, 7000000},
+ {4, 7000001, 20000000}};
+ // presets supported by the device
+ const std::vector<Equalizer::Preset> mPresets = {
+ {0, "Normal"}, {1, "Classical"}, {2, "Dance"}, {3, "Flat"}, {4, "Folk"},
+ {5, "Heavy Metal"}, {6, "Hip Hop"}, {7, "Jazz"}, {8, "Pop"}, {9, "Rock"}};
+
+ const Equalizer::Capability kEqCap = {.bandFrequencies = mBandFrequency, .presets = mPresets};
+ // Effect descriptor.
+ const Descriptor kDesc = {.common = {.id = {.type = kEqualizerTypeUUID,
+ .uuid = kEqualizerSwImplUUID,
+ .proxy = kEqualizerProxyUUID},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "EqualizerSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::equalizer>(kEqCap)};
+
+ ndk::ScopedAStatus getParameterEqualizer(const Equalizer::Tag& tag,
+ Parameter::Specific* specific);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/hapticGenerator/Android.bp b/audio/aidl/default/hapticGenerator/Android.bp
new file mode 100644
index 0000000..a632130
--- /dev/null
+++ b/audio/aidl/default/hapticGenerator/Android.bp
@@ -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.
+ */
+
+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: "libhapticgeneratorsw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "HapticGeneratorSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
new file mode 100644
index 0000000..fd5ea34
--- /dev/null
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_HapticGeneratorSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "HapticGeneratorSw.h"
+
+using aidl::android::hardware::audio::effect::HapticGeneratorSw;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kHapticGeneratorSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kHapticGeneratorSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<HapticGeneratorSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ return EX_NONE;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus HapticGeneratorSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus HapticGeneratorSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::hapticGenerator != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ mSpecificParam = specific.get<Parameter::Specific::hapticGenerator>();
+ LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus HapticGeneratorSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::hapticGeneratorTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ specific->set<Parameter::Specific::hapticGenerator>(mSpecificParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> HapticGeneratorSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<HapticGeneratorSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode HapticGeneratorSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status HapticGeneratorSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
new file mode 100644
index 0000000..518aa87
--- /dev/null
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class HapticGeneratorSwContext final : public EffectContext {
+ public:
+ HapticGeneratorSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+ // TODO: add specific context here
+};
+
+class HapticGeneratorSw final : public EffectImpl {
+ public:
+ HapticGeneratorSw() { LOG(DEBUG) << __func__; }
+ ~HapticGeneratorSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<HapticGeneratorSwContext> mContext;
+ /* capabilities */
+ const HapticGenerator::Capability kCapability;
+ /* Effect descriptor */
+ const Descriptor kDescriptor = {
+ .common = {.id = {.type = kHapticGeneratorTypeUUID,
+ .uuid = kHapticGeneratorSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "HapticGeneratorSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::hapticGenerator>(kCapability)};
+
+ /* parameters */
+ HapticGenerator mSpecificParam;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/core-impl/Config.h b/audio/aidl/default/include/core-impl/Config.h
index b62a14b..4555efd 100644
--- a/audio/aidl/default/include/core-impl/Config.h
+++ b/audio/aidl/default/include/core-impl/Config.h
@@ -20,6 +20,8 @@
namespace aidl::android::hardware::audio::core {
-class Config : public BnConfig {};
+class Config : public BnConfig {
+ ndk::ScopedAStatus getSurroundSoundConfig(SurroundSoundConfig* _aidl_return) override;
+};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Module.h b/audio/aidl/default/include/core-impl/Module.h
index 61516b2..0086743 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -35,6 +35,7 @@
private:
ndk::ScopedAStatus setModuleDebug(
const ::aidl::android::hardware::audio::core::ModuleDebug& in_debug) override;
+ ndk::ScopedAStatus getTelephony(std::shared_ptr<ITelephony>* _aidl_return) override;
ndk::ScopedAStatus connectExternalDevice(
const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
@@ -70,6 +71,17 @@
bool* _aidl_return) override;
ndk::ScopedAStatus resetAudioPatch(int32_t in_patchId) override;
ndk::ScopedAStatus resetAudioPortConfig(int32_t in_portConfigId) override;
+ ndk::ScopedAStatus getMasterMute(bool* _aidl_return) override;
+ ndk::ScopedAStatus setMasterMute(bool in_mute) override;
+ ndk::ScopedAStatus getMasterVolume(float* _aidl_return) override;
+ ndk::ScopedAStatus setMasterVolume(float in_volume) override;
+ ndk::ScopedAStatus getMicMute(bool* _aidl_return) override;
+ ndk::ScopedAStatus setMicMute(bool in_mute) override;
+ ndk::ScopedAStatus updateAudioMode(
+ ::aidl::android::hardware::audio::core::AudioMode in_mode) override;
+ ndk::ScopedAStatus updateScreenRotation(
+ ::aidl::android::hardware::audio::core::IModule::ScreenRotation in_rotation) override;
+ ndk::ScopedAStatus updateScreenState(bool in_isTurnedOn) override;
void cleanUpPatch(int32_t patchId);
ndk::ScopedAStatus createStreamContext(
@@ -88,12 +100,18 @@
std::unique_ptr<internal::Configuration> mConfig;
ModuleDebug mDebug;
+ // Since it is required to return the same instance of the ITelephony, even
+ // if the client has released it on its side, we need to hold it via a strong pointer.
+ std::shared_ptr<ITelephony> mTelephony;
// ids of ports created at runtime via 'connectExternalDevice'.
std::set<int32_t> mConnectedDevicePorts;
Streams mStreams;
// Maps port ids and port config ids to patch ids.
// Multimap because both ports and configs can be used by multiple patches.
std::multimap<int32_t, int32_t> mPatches;
+ bool mMasterMute = false;
+ float mMasterVolume = 1.0f;
+ bool mMicMute = false;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/core-impl/Stream.h b/audio/aidl/default/include/core-impl/Stream.h
index 488edf1..5ee0f82 100644
--- a/audio/aidl/default/include/core-impl/Stream.h
+++ b/audio/aidl/default/include/core-impl/Stream.h
@@ -54,8 +54,8 @@
int8_t, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
DataMQ;
- // Ensure that this value is not used by any of StreamDescriptor.COMMAND_*
- static constexpr int COMMAND_EXIT = -1;
+ // Ensure that this value is not used by any of StreamDescriptor.State enums
+ static constexpr int32_t STATE_CLOSED = -1;
StreamContext() = default;
StreamContext(std::unique_ptr<CommandMQ> commandMQ, std::unique_ptr<ReplyMQ> replyMQ,
@@ -99,6 +99,10 @@
class StreamWorkerCommonLogic : public ::android::hardware::audio::common::StreamLogic {
public:
+ bool isClosed() const {
+ return static_cast<int32_t>(mState.load()) == StreamContext::STATE_CLOSED;
+ }
+ void setClosed() { mState = static_cast<StreamDescriptor::State>(StreamContext::STATE_CLOSED); }
void setIsConnected(bool connected) { mIsConnected = connected; }
protected:
@@ -109,9 +113,12 @@
mReplyMQ(context.getReplyMQ()),
mDataMQ(context.getDataMQ()) {}
std::string init() override;
+ void populateReply(StreamDescriptor::Reply* reply, bool isConnected) const;
- // Used both by the main and worker threads.
+ // Atomic fields are used both by the main and worker threads.
std::atomic<bool> mIsConnected = false;
+ static_assert(std::atomic<StreamDescriptor::State>::is_always_lock_free);
+ std::atomic<StreamDescriptor::State> mState = StreamDescriptor::State::STANDBY;
// All fields are used on the worker thread only.
const int mInternalCommandCookie;
const size_t mFrameSize;
@@ -132,6 +139,9 @@
protected:
Status cycle() override;
+
+ private:
+ bool read(size_t clientSize, StreamDescriptor::Reply* reply);
};
using StreamInWorker = ::android::hardware::audio::common::StreamWorker<StreamInWorkerLogic>;
@@ -143,6 +153,9 @@
protected:
Status cycle() override;
+
+ private:
+ bool write(size_t clientSize, StreamDescriptor::Reply* reply);
};
using StreamOutWorker = ::android::hardware::audio::common::StreamWorker<StreamOutWorkerLogic>;
@@ -155,7 +168,7 @@
? ndk::ScopedAStatus::ok()
: ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_STATE);
}
- bool isClosed() const { return mIsClosed; }
+ bool isClosed() const { return mWorker.isClosed(); }
void setIsConnected(bool connected) { mWorker.setIsConnected(connected); }
ndk::ScopedAStatus updateMetadata(const Metadata& metadata);
@@ -168,9 +181,6 @@
Metadata mMetadata;
StreamContext mContext;
StreamWorker mWorker;
- // This variable is checked in the destructor which can be called on an arbitrary Binder thread,
- // thus we need to ensure that any changes made by other threads are sequentially consistent.
- std::atomic<bool> mIsClosed = false;
};
class StreamIn
diff --git a/audio/aidl/default/include/core-impl/Telephony.h b/audio/aidl/default/include/core-impl/Telephony.h
new file mode 100644
index 0000000..597f3d6
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/Telephony.h
@@ -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.
+ */
+
+#pragma once
+
+#include <android/binder_enums.h>
+
+#include <aidl/android/hardware/audio/core/BnTelephony.h>
+
+namespace aidl::android::hardware::audio::core {
+
+class Telephony : public BnTelephony {
+ private:
+ ndk::ScopedAStatus getSupportedAudioModes(std::vector<AudioMode>* _aidl_return) override;
+ ndk::ScopedAStatus switchAudioMode(AudioMode in_mode) override;
+
+ const std::vector<AudioMode> mSupportedAudioModes = {::ndk::enum_range<AudioMode>().begin(),
+ ::ndk::enum_range<AudioMode>().end()};
+};
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/include/effect-impl/EffectContext.h b/audio/aidl/default/include/effect-impl/EffectContext.h
new file mode 100644
index 0000000..f608e12
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectContext.h
@@ -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.
+ */
+
+#pragma once
+#include <Utils.h>
+#include <android-base/logging.h>
+#include <utils/Log.h>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include "EffectTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectContext {
+ public:
+ typedef ::android::AidlMessageQueue<
+ IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ StatusMQ;
+ typedef ::android::AidlMessageQueue<
+ float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ DataMQ;
+
+ EffectContext(size_t statusDepth, const Parameter::Common& common) {
+ mSessionId = common.session;
+ auto& input = common.input;
+ auto& output = common.output;
+
+ LOG_ALWAYS_FATAL_IF(
+ input.base.format.pcm != aidl::android::media::audio::common::PcmType::FLOAT_32_BIT,
+ "inputFormatNotFloat");
+ LOG_ALWAYS_FATAL_IF(output.base.format.pcm !=
+ aidl::android::media::audio::common::PcmType::FLOAT_32_BIT,
+ "outputFormatNotFloat");
+ mInputFrameSize = ::android::hardware::audio::common::getFrameSizeInBytes(
+ input.base.format, input.base.channelMask);
+ mOutputFrameSize = ::android::hardware::audio::common::getFrameSizeInBytes(
+ output.base.format, output.base.channelMask);
+ // in/outBuffer size in float (FMQ data format defined for DataMQ)
+ size_t inBufferSizeInFloat = input.frameCount * mInputFrameSize / sizeof(float);
+ size_t outBufferSizeInFloat = output.frameCount * mOutputFrameSize / sizeof(float);
+
+ mStatusMQ = std::make_shared<StatusMQ>(statusDepth, true /*configureEventFlagWord*/);
+ mInputMQ = std::make_shared<DataMQ>(inBufferSizeInFloat);
+ mOutputMQ = std::make_shared<DataMQ>(outBufferSizeInFloat);
+
+ if (!mStatusMQ->isValid() || !mInputMQ->isValid() || !mOutputMQ->isValid()) {
+ LOG(ERROR) << __func__ << " created invalid FMQ";
+ }
+ mWorkBuffer.reserve(std::max(inBufferSizeInFloat, outBufferSizeInFloat));
+ }
+ virtual ~EffectContext() {}
+
+ std::shared_ptr<StatusMQ> getStatusFmq() { return mStatusMQ; }
+ std::shared_ptr<DataMQ> getInputDataFmq() { return mInputMQ; }
+ std::shared_ptr<DataMQ> getOutputDataFmq() { return mOutputMQ; }
+
+ float* getWorkBuffer() { return static_cast<float*>(mWorkBuffer.data()); }
+ // TODO: update with actual available size
+ size_t availableToRead() { return mWorkBuffer.capacity(); }
+ size_t availableToWrite() { return mWorkBuffer.capacity(); }
+
+ // reset buffer status by abandon all data and status in FMQ
+ void resetBuffer() {
+ auto buffer = getWorkBuffer();
+ std::vector<IEffect::Status> status(mStatusMQ->availableToRead());
+ mInputMQ->read(buffer, mInputMQ->availableToRead());
+ mOutputMQ->read(buffer, mOutputMQ->availableToRead());
+ mStatusMQ->read(status.data(), mStatusMQ->availableToRead());
+ }
+
+ void dupeFmq(IEffect::OpenEffectReturn* effectRet) {
+ if (effectRet) {
+ effectRet->statusMQ = getStatusFmq()->dupeDesc();
+ effectRet->inputDataMQ = getInputDataFmq()->dupeDesc();
+ effectRet->outputDataMQ = getOutputDataFmq()->dupeDesc();
+ }
+ }
+ size_t getInputFrameSize() { return mInputFrameSize; }
+ size_t getOutputFrameSize() { return mOutputFrameSize; }
+ int getSessionId() { return mSessionId; }
+
+ virtual RetCode setOutputDevice(
+ const aidl::android::media::audio::common::AudioDeviceDescription& device) {
+ mOutputDevice = device;
+ return RetCode::SUCCESS;
+ }
+ virtual aidl::android::media::audio::common::AudioDeviceDescription getOutputDevice() {
+ return mOutputDevice;
+ }
+
+ virtual RetCode setAudioMode(const aidl::android::media::audio::common::AudioMode& mode) {
+ mMode = mode;
+ return RetCode::SUCCESS;
+ }
+ virtual aidl::android::media::audio::common::AudioMode getAudioMode() { return mMode; }
+
+ virtual RetCode setAudioSource(const aidl::android::media::audio::common::AudioSource& source) {
+ mSource = source;
+ return RetCode::SUCCESS;
+ }
+ virtual aidl::android::media::audio::common::AudioSource getAudioSource() { return mSource; }
+
+ virtual RetCode setVolumeStereo(const Parameter::VolumeStereo& volumeStereo) {
+ mVolumeStereo = volumeStereo;
+ return RetCode::SUCCESS;
+ }
+ virtual Parameter::VolumeStereo getVolumeStereo() { return mVolumeStereo; }
+
+ virtual RetCode setCommon(const Parameter::Common& common) {
+ mCommon = common;
+ LOG(ERROR) << __func__ << mCommon.toString();
+ return RetCode::SUCCESS;
+ }
+ virtual Parameter::Common getCommon() {
+ LOG(ERROR) << __func__ << mCommon.toString();
+ return mCommon;
+ }
+
+ protected:
+ // common parameters
+ int mSessionId = INVALID_AUDIO_SESSION_ID;
+ size_t mInputFrameSize, mOutputFrameSize;
+ Parameter::Common mCommon;
+ aidl::android::media::audio::common::AudioDeviceDescription mOutputDevice;
+ aidl::android::media::audio::common::AudioMode mMode;
+ aidl::android::media::audio::common::AudioSource mSource;
+ Parameter::VolumeStereo mVolumeStereo;
+
+ private:
+ // fmq and buffers
+ std::shared_ptr<StatusMQ> mStatusMQ;
+ std::shared_ptr<DataMQ> mInputMQ;
+ std::shared_ptr<DataMQ> mOutputMQ;
+ // TODO handle effect process input and output
+ // work buffer set by effect instances, the access and update are in same thread
+ std::vector<float> mWorkBuffer;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectImpl.h b/audio/aidl/default/include/effect-impl/EffectImpl.h
new file mode 100644
index 0000000..d9825da
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectImpl.h
@@ -0,0 +1,83 @@
+/*
+ * 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/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+#include <mutex>
+
+#include "EffectTypes.h"
+#include "effect-impl/EffectContext.h"
+#include "effect-impl/EffectTypes.h"
+#include "effect-impl/EffectWorker.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectImpl : public BnEffect, public EffectWorker {
+ public:
+ EffectImpl() = default;
+ virtual ~EffectImpl() = default;
+
+ /**
+ * Each effect implementation CAN override these methods if necessary
+ * If you would like implement IEffect::open completely, override EffectImpl::open(), if you
+ * want to keep most of EffectImpl logic but have a little customize, try override openImpl().
+ * openImpl() will be called at the beginning of EffectImpl::open() without lock protection.
+ *
+ * Same for closeImpl().
+ */
+ virtual ndk::ScopedAStatus open(const Parameter::Common& common,
+ const std::optional<Parameter::Specific>& specific,
+ OpenEffectReturn* ret) override;
+ virtual ndk::ScopedAStatus close() override;
+ virtual ndk::ScopedAStatus command(CommandId id) override;
+ virtual ndk::ScopedAStatus commandStart() { return ndk::ScopedAStatus::ok(); }
+ virtual ndk::ScopedAStatus commandStop() { return ndk::ScopedAStatus::ok(); }
+ virtual ndk::ScopedAStatus commandReset() { return ndk::ScopedAStatus::ok(); }
+
+ virtual ndk::ScopedAStatus getState(State* state) override;
+ virtual ndk::ScopedAStatus setParameter(const Parameter& param) override;
+ virtual ndk::ScopedAStatus getParameter(const Parameter::Id& id, Parameter* param) override;
+ virtual IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+
+ virtual ndk::ScopedAStatus setParameterCommon(const Parameter& param);
+ virtual ndk::ScopedAStatus getParameterCommon(const Parameter::Tag& tag, Parameter* param);
+
+ /* Methods MUST be implemented by each effect instances */
+ virtual ndk::ScopedAStatus getDescriptor(Descriptor* desc) = 0;
+ virtual ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) = 0;
+ virtual ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) = 0;
+ virtual std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) = 0;
+ virtual RetCode releaseContext() = 0;
+
+ protected:
+ /*
+ * Lock is required if effectProcessImpl (which is running in an independent thread) needs to
+ * access state and parameters.
+ */
+ std::mutex mMutex;
+ State mState GUARDED_BY(mMutex) = State::INIT;
+
+ IEffect::Status status(binder_status_t status, size_t consumed, size_t produced);
+ void cleanUp();
+
+ private:
+ std::shared_ptr<EffectContext> mContext GUARDED_BY(mMutex);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectThread.h b/audio/aidl/default/include/effect-impl/EffectThread.h
new file mode 100644
index 0000000..09a0000
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectThread.h
@@ -0,0 +1,58 @@
+/*
+ * 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 <atomic>
+#include <string>
+#include <thread>
+
+#include <android-base/thread_annotations.h>
+#include <system/thread_defs.h>
+
+#include "effect-impl/EffectTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class EffectThread {
+ public:
+ // default priority is same as HIDL: ANDROID_PRIORITY_URGENT_AUDIO
+ EffectThread();
+ virtual ~EffectThread();
+
+ // called by effect implementation.
+ RetCode createThread(const std::string& name,
+ const int priority = ANDROID_PRIORITY_URGENT_AUDIO);
+ RetCode destroyThread();
+ RetCode startThread();
+ RetCode stopThread();
+
+ // Will call process() in a loop if the thread is running.
+ void threadLoop();
+
+ // User of EffectThread must implement the effect processing logic in this method.
+ virtual void process() = 0;
+ const int MAX_TASK_COMM_LEN = 15;
+
+ private:
+ std::mutex mMutex;
+ std::condition_variable mCv;
+ bool mExit GUARDED_BY(mMutex) = false;
+ bool mStop GUARDED_BY(mMutex) = true;
+ std::thread mThread;
+ int mPriority;
+ std::string mName;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectTypes.h b/audio/aidl/default/include/effect-impl/EffectTypes.h
new file mode 100644
index 0000000..fc6a01d
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectTypes.h
@@ -0,0 +1,124 @@
+/*
+ * 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 <ostream>
+#include <string>
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <android-base/logging.h>
+
+typedef binder_exception_t (*EffectCreateFunctor)(
+ const ::aidl::android::media::audio::common::AudioUuid*,
+ std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>*);
+typedef binder_exception_t (*EffectDestroyFunctor)(
+ const std::shared_ptr<aidl::android::hardware::audio::effect::IEffect>&);
+
+struct effect_dl_interface_s {
+ EffectCreateFunctor createEffectFunc;
+ EffectDestroyFunctor destroyEffectFunc;
+};
+
+namespace aidl::android::hardware::audio::effect {
+
+enum class RetCode {
+ SUCCESS,
+ ERROR_ILLEGAL_PARAMETER, /* Illegal parameter */
+ ERROR_THREAD, /* Effect thread error */
+ ERROR_NULL_POINTER, /* NULL pointer */
+ ERROR_ALIGNMENT_ERROR, /* Memory alignment error */
+ ERROR_BLOCK_SIZE_EXCEED, /* Maximum block size exceeded */
+ ERROR_EFFECT_LIB_ERROR
+};
+
+static const int INVALID_AUDIO_SESSION_ID = -1;
+
+inline std::ostream& operator<<(std::ostream& out, const RetCode& code) {
+ switch (code) {
+ case RetCode::SUCCESS:
+ return out << "SUCCESS";
+ case RetCode::ERROR_ILLEGAL_PARAMETER:
+ return out << "ERROR_ILLEGAL_PARAMETER";
+ case RetCode::ERROR_THREAD:
+ return out << "ERROR_THREAD";
+ case RetCode::ERROR_NULL_POINTER:
+ return out << "ERROR_NULL_POINTER";
+ case RetCode::ERROR_ALIGNMENT_ERROR:
+ return out << "ERROR_ALIGNMENT_ERROR";
+ case RetCode::ERROR_BLOCK_SIZE_EXCEED:
+ return out << "ERROR_BLOCK_SIZE_EXCEED";
+ case RetCode::ERROR_EFFECT_LIB_ERROR:
+ return out << "ERROR_EFFECT_LIB_ERROR";
+ }
+
+ return out << "EnumError: " << code;
+}
+
+#define RETURN_IF_ASTATUS_NOT_OK(status, message) \
+ do { \
+ const ::ndk::ScopedAStatus curr_status = (status); \
+ if (!curr_status.isOk()) { \
+ LOG(ERROR) << __func__ << ":" << __LINE__ \
+ << "return with status: " << curr_status.getDescription() << (message); \
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage( \
+ curr_status.getExceptionCode(), (message)); \
+ } \
+ } while (0)
+
+#define RETURN_IF(expr, exception, message) \
+ do { \
+ if (expr) { \
+ LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr " << #expr; \
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage((exception), (message)); \
+ } \
+ } while (0)
+
+#define RETURN_OK_IF(expr) \
+ do { \
+ if (expr) { \
+ LOG(INFO) << __func__ << ":" << __LINE__ << " return with expr " << #expr; \
+ return ndk::ScopedAStatus::ok(); \
+ } \
+ } while (0)
+
+#define RETURN_VALUE_IF(expr, ret, log) \
+ do { \
+ if (expr) { \
+ LOG(ERROR) << __func__ << ":" << __LINE__ << " return with expr " << #expr << (log); \
+ return ret; \
+ } \
+ } while (0)
+
+static inline bool stringToUuid(const char* str,
+ ::aidl::android::media::audio::common::AudioUuid* uuid) {
+ RETURN_VALUE_IF(!uuid || !str, false, "nullPtr");
+
+ uint32_t tmp[10];
+ if (sscanf(str, "%08x-%04x-%04x-%04x-%02x%02x%02x%02x%02x%02x", tmp, tmp + 1, tmp + 2, tmp + 3,
+ tmp + 4, tmp + 5, tmp + 6, tmp + 7, tmp + 8, tmp + 9) < 10) {
+ return false;
+ }
+
+ uuid->timeLow = (uint32_t)tmp[0];
+ uuid->timeMid = (uint16_t)tmp[1];
+ uuid->timeHiAndVersion = (uint16_t)tmp[2];
+ uuid->clockSeq = (uint16_t)tmp[3];
+ uuid->node.insert(uuid->node.end(), {(uint8_t)tmp[4], (uint8_t)tmp[5], (uint8_t)tmp[6],
+ (uint8_t)tmp[7], (uint8_t)tmp[8], (uint8_t)tmp[9]});
+ return true;
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectUUID.h b/audio/aidl/default/include/effect-impl/EffectUUID.h
new file mode 100644
index 0000000..7709eab
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectUUID.h
@@ -0,0 +1,204 @@
+/*
+ * 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 <map>
+
+#include <aidl/android/media/audio/common/AudioUuid.h>
+
+namespace aidl::android::hardware::audio::effect {
+
+using ::aidl::android::media::audio::common::AudioUuid;
+
+// ec7178ec-e5e1-4432-a3f4-4657e6795210
+static const AudioUuid kEffectNullUuid = {static_cast<int32_t>(0xec7178ec),
+ 0xe5e1,
+ 0x4432,
+ 0xa3f4,
+ {0x46, 0x57, 0xe6, 0x79, 0x52, 0x10}};
+// Zero UUID
+static const AudioUuid kEffectZeroUuid = {
+ static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
+
+// 0634f220-ddd4-11db-a0fc-0002a5d5c51b
+static const AudioUuid kBassBoostTypeUUID = {static_cast<int32_t>(0x0634f220),
+ 0xddd4,
+ 0x11db,
+ 0xa0fc,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// fa8181f2-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kBassBoostSwImplUUID = {static_cast<int32_t>(0xfa8181f2),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa81862a-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kDownmixTypeUUID = {static_cast<int32_t>(0xfa81862a),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa8187ba-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kDownmixSwImplUUID = {static_cast<int32_t>(0xfa8187ba),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 0bed4300-ddd6-11db-8f34-0002a5d5c51b.
+static const AudioUuid kEqualizerTypeUUID = {static_cast<int32_t>(0x0bed4300),
+ 0xddd6,
+ 0x11db,
+ 0x8f34,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// 0bed4300-847d-11df-bb17-0002a5d5c51b
+static const AudioUuid kEqualizerSwImplUUID = {static_cast<int32_t>(0x0bed4300),
+ 0x847d,
+ 0x11df,
+ 0xbb17,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// ce772f20-847d-11df-bb17-0002a5d5c51b
+static const AudioUuid kEqualizerBundleImplUUID = {static_cast<int32_t>(0xce772f20),
+ 0x847d,
+ 0x11df,
+ 0xbb17,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// c8e70ecd-48ca-456e-8a4f-0002a5d5c51b
+static const AudioUuid kEqualizerProxyUUID = {static_cast<int32_t>(0xc8e70ecd),
+ 0x48ca,
+ 0x456e,
+ 0x8a4f,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// 7261676f-6d75-7369-6364-28e2fd3ac39e
+static const AudioUuid kDynamicsProcessingTypeUUID = {static_cast<int32_t>(0x7261676f),
+ 0x6d75,
+ 0x7369,
+ 0x6364,
+ {0x28, 0xe2, 0xfd, 0x3a, 0xc3, 0x9e}};
+// fa818d78-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kDynamicsProcessingSwImplUUID = {static_cast<int32_t>(0xfa818d78),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 1411e6d6-aecd-4021-a1cf-a6aceb0d71e5
+static const AudioUuid kHapticGeneratorTypeUUID = {static_cast<int32_t>(0x1411e6d6),
+ 0xaecd,
+ 0x4021,
+ 0xa1cf,
+ {0xa6, 0xac, 0xeb, 0x0d, 0x71, 0xe5}};
+// fa819110-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kHapticGeneratorSwImplUUID = {static_cast<int32_t>(0xfa819110),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fe3199be-aed0-413f-87bb-11260eb63cf1
+static const AudioUuid kLoudnessEnhancerTypeUUID = {static_cast<int32_t>(0xfe3199be),
+ 0xaed0,
+ 0x413f,
+ 0x87bb,
+ {0x11, 0x26, 0x0e, 0xb6, 0x3c, 0xf1}};
+// fa819610-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kLoudnessEnhancerSwImplUUID = {static_cast<int32_t>(0xfa819610),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// c2e5d5f0-94bd-4763-9cac-4e234d06839e
+static const AudioUuid kEnvReverbTypeUUID = {static_cast<int32_t>(0xc2e5d5f0),
+ 0x94bd,
+ 0x4763,
+ 0x9cac,
+ {0x4e, 0x23, 0x4d, 0x06, 0x83, 0x9e}};
+// fa819886-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kEnvReverbSwImplUUID = {static_cast<int32_t>(0xfa819886),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 47382d60-ddd8-11db-bf3a-0002a5d5c51b
+static const AudioUuid kPresetReverbTypeUUID = {static_cast<int32_t>(0x47382d60),
+ 0xddd8,
+ 0x11db,
+ 0xbf3a,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// fa8199c6-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kPresetReverbSwImplUUID = {static_cast<int32_t>(0xfa8199c6),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// 37cc2c00-dddd-11db-8577-0002a5d5c51b
+static const AudioUuid kVirtualizerTypeUUID = {static_cast<int32_t>(0x37cc2c00),
+ 0xdddd,
+ 0x11db,
+ 0x8577,
+ {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
+// fa819d86-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kVirtualizerSwImplUUID = {static_cast<int32_t>(0xfa819d86),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa819f3e-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kVisualizerTypeUUID = {static_cast<int32_t>(0xfa819f3e),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa81a0f6-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kVisualizerSwImplUUID = {static_cast<int32_t>(0xfa81a0f6),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa81a2b8-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kVolumeTypeUUID = {static_cast<int32_t>(0xfa81a2b8),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+// fa81a718-588b-11ed-9b6a-0242ac120002
+static const AudioUuid kVolumeSwImplUUID = {static_cast<int32_t>(0xfa81a718),
+ 0x588b,
+ 0x11ed,
+ 0x9b6a,
+ {0x02, 0x42, 0xac, 0x12, 0x00, 0x02}};
+
+/**
+ * @brief A map between effect name and effect type UUID.
+ * All <name> attribution in effect/effectProxy of audio_effects.xml should be listed in this map.
+ * We need this map is because existing audio_effects.xml don't have a type UUID defined.
+ */
+static const std::map<const std::string /* effect type */, const AudioUuid&> kUuidNameTypeMap = {
+ {"bassboost", kBassBoostTypeUUID},
+ {"downmix", kDownmixTypeUUID},
+ {"dynamics_processing", kDynamicsProcessingTypeUUID},
+ {"equalizer", kEqualizerTypeUUID},
+ {"haptic_generator", kHapticGeneratorTypeUUID},
+ {"loudness_enhancer", kLoudnessEnhancerTypeUUID},
+ {"env_reverb", kEnvReverbTypeUUID},
+ {"preset_reverb", kPresetReverbTypeUUID},
+ {"reverb_env_aux", kEnvReverbTypeUUID},
+ {"reverb_env_ins", kEnvReverbTypeUUID},
+ {"reverb_pre_aux", kPresetReverbTypeUUID},
+ {"reverb_pre_ins", kPresetReverbTypeUUID},
+ {"virtualizer", kVirtualizerTypeUUID},
+ {"visualizer", kVisualizerTypeUUID},
+ {"volume", kVolumeTypeUUID},
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effect-impl/EffectWorker.h b/audio/aidl/default/include/effect-impl/EffectWorker.h
new file mode 100644
index 0000000..6a78eab
--- /dev/null
+++ b/audio/aidl/default/include/effect-impl/EffectWorker.h
@@ -0,0 +1,74 @@
+/*
+ * 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 <algorithm>
+#include <memory>
+#include <mutex>
+#include <string>
+
+#include "EffectContext.h"
+#include "EffectThread.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+std::string toString(RetCode& code);
+
+class EffectWorker : public EffectThread {
+ public:
+ // set effect context for worker, suppose to only happen once here
+ void setContext(std::shared_ptr<EffectContext> context) {
+ std::call_once(mOnceFlag, [&]() { mContext = context; });
+ };
+
+ // handle FMQ and call effect implemented virtual function
+ void process() override {
+ RETURN_VALUE_IF(!mContext, void(), "nullContext");
+ std::shared_ptr<EffectContext::StatusMQ> statusMQ = mContext->getStatusFmq();
+ std::shared_ptr<EffectContext::DataMQ> inputMQ = mContext->getInputDataFmq();
+ std::shared_ptr<EffectContext::DataMQ> outputMQ = mContext->getOutputDataFmq();
+
+ // Only this worker will read from input data MQ and write to output data MQ.
+ auto readSamples = inputMQ->availableToRead(), writeSamples = outputMQ->availableToWrite();
+ if (readSamples && writeSamples) {
+ auto processSamples = std::min(readSamples, writeSamples);
+ LOG(DEBUG) << __func__ << " available to read " << readSamples << " available to write "
+ << writeSamples << " process " << processSamples;
+
+ auto buffer = mContext->getWorkBuffer();
+ inputMQ->read(buffer, processSamples);
+
+ IEffect::Status status = effectProcessImpl(buffer, buffer, processSamples);
+ outputMQ->write(buffer, status.fmqProduced);
+ statusMQ->writeBlocking(&status, 1);
+ LOG(DEBUG) << __func__ << " done processing, effect consumed " << status.fmqConsumed
+ << " produced " << status.fmqProduced;
+ } else {
+ // TODO: maybe add some sleep here to avoid busy waiting
+ }
+ }
+
+ // must implement by each effect implementation
+ // TODO: consider if this interface need adjustment to handle in-place processing
+ virtual IEffect::Status effectProcessImpl(float* in, float* out, int processSamples) = 0;
+
+ private:
+ // make sure the context only set once.
+ std::once_flag mOnceFlag;
+ std::shared_ptr<EffectContext> mContext;
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectConfig.h b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
new file mode 100644
index 0000000..2b904f5
--- /dev/null
+++ b/audio/aidl/default/include/effectFactory-impl/EffectConfig.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <cutils/properties.h>
+#include <tinyxml2.h>
+
+#include "effect-impl/EffectTypes.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+/**
+ * Library contains a mapping from library name to path.
+ * Effect contains a mapping from effect name to Libraries and implementation UUID.
+ * Pre/post processor contains a mapping from processing name to effect names.
+ */
+class EffectConfig {
+ public:
+ explicit EffectConfig(const std::string& file);
+
+ // <library>
+ struct Library {
+ std::string name;
+ std::string path;
+ };
+ struct LibraryUuid {
+ std::string name; // library name
+ ::aidl::android::media::audio::common::AudioUuid uuid;
+ };
+ // <effects>
+ struct EffectLibraries {
+ std::optional<struct LibraryUuid> proxyLibrary;
+ std::vector<struct LibraryUuid> libraries;
+ };
+
+ int getSkippedElements() const { return mSkippedElements; }
+ const std::unordered_map<std::string, std::string> getLibraryMap() const { return mLibraryMap; }
+ const std::unordered_map<std::string, struct EffectLibraries> getEffectsMap() const {
+ return mEffectsMap;
+ }
+ const std::unordered_map<std::string, std::vector<std::string>> getProcessingMap() const {
+ return mProcessingMap;
+ }
+
+ private:
+ int mSkippedElements;
+ /* Parsed Libraries result */
+ std::unordered_map<std::string, std::string> mLibraryMap;
+ /* Parsed Effects result */
+ std::unordered_map<std::string, struct EffectLibraries> mEffectsMap;
+ /* Parsed pre/post processing result */
+ std::unordered_map<std::string, std::vector<std::string>> mProcessingMap;
+
+ /** @return all `node`s children that are elements and match the tag if provided. */
+ std::vector<std::reference_wrapper<const tinyxml2::XMLElement>> getChildren(
+ const tinyxml2::XMLNode& node, const char* childTag = nullptr);
+
+ /** Parse a library xml note and push the result in mLibraryMap or return false on failure. */
+ bool parseLibrary(const tinyxml2::XMLElement& xml);
+
+ /** Parse an effect from an xml element describing it.
+ * @return true and pushes the effect in mEffectsMap on success, false on failure.
+ */
+ bool parseEffect(const tinyxml2::XMLElement& xml);
+
+ bool parseStream(const tinyxml2::XMLElement& xml);
+
+ // Function to parse effect.library name and effect.uuid from xml
+ bool parseLibraryUuid(const tinyxml2::XMLElement& xml, struct LibraryUuid& libraryUuid,
+ bool isProxy = false);
+
+ const char* dump(const tinyxml2::XMLElement& element,
+ tinyxml2::XMLPrinter&& printer = {}) const;
+};
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
index 8da5525..7edace0 100644
--- a/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
+++ b/audio/aidl/default/include/effectFactory-impl/EffectFactory.h
@@ -16,31 +16,47 @@
#pragma once
+#include <any>
+#include <map>
#include <optional>
+#include <set>
#include <vector>
#include <aidl/android/hardware/audio/effect/BnFactory.h>
+#include "EffectConfig.h"
namespace aidl::android::hardware::audio::effect {
class Factory : public BnFactory {
public:
- Factory();
+ explicit Factory(const std::string& file);
/**
* @brief Get identity of all effects supported by the device, with the optional filter by type
* and/or by instance UUID.
*
* @param in_type Type UUID.
* @param in_instance Instance UUID.
+ * @param in_proxy Proxy UUID.
* @param out_descriptor List of identities .
* @return ndk::ScopedAStatus
*/
ndk::ScopedAStatus queryEffects(
const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_type,
const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_instance,
+ const std::optional<::aidl::android::media::audio::common::AudioUuid>& in_proxy,
std::vector<Descriptor::Identity>* out_descriptor) override;
/**
+ * @brief Query list of defined processing, with the optional filter by AudioStreamType
+ *
+ * @param in_type Type of processing, could be AudioStreamType or AudioSource. Optional.
+ * @param _aidl_return List of processing filtered by in_type.
+ * @return ndk::ScopedAStatus
+ */
+ ndk::ScopedAStatus queryProcessing(const std::optional<Processing::Type>& in_type,
+ std::vector<Processing>* _aidl_return) override;
+
+ /**
* @brief Create an effect instance for a certain implementation (identified by UUID).
*
* @param in_impl_uuid Effect implementation UUID.
@@ -63,7 +79,28 @@
override;
private:
- // List of effect descriptors supported by the devices.
- std::vector<Descriptor::Identity> mIdentityList;
+ const EffectConfig mConfig;
+ ~Factory();
+ // Set of effect descriptors supported by the devices.
+ std::set<Descriptor::Identity> mIdentitySet;
+
+ std::map<aidl::android::media::audio::common::AudioUuid /* implementationUUID */,
+ std::pair<std::unique_ptr<void, std::function<void(void*)>> /* dlHandle */,
+ std::unique_ptr<struct effect_dl_interface_s>>>
+ mEffectLibMap;
+ std::map<std::weak_ptr<IEffect>, aidl::android::media::audio::common::AudioUuid,
+ std::owner_less<>>
+ mEffectUuidMap;
+
+ ndk::ScopedAStatus destroyEffectImpl(const std::shared_ptr<IEffect>& in_handle);
+ void cleanupEffectMap();
+ void openEffectLibrary(const ::aidl::android::media::audio::common::AudioUuid& impl,
+ const std::string& libName);
+ void createIdentityWithConfig(
+ const EffectConfig::LibraryUuid& configLib,
+ const ::aidl::android::media::audio::common::AudioUuid& typeUuid,
+ const std::optional<::aidl::android::media::audio::common::AudioUuid> proxyUuid);
+ void loadEffectLibs();
};
+
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/equalizer-impl/Equalizer.h b/audio/aidl/default/include/equalizer-impl/Equalizer.h
deleted file mode 100644
index ea16cb9..0000000
--- a/audio/aidl/default/include/equalizer-impl/Equalizer.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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/effect/BnEffect.h>
-#include <cstdlib>
-
-namespace aidl::android::hardware::audio::effect {
-
-// Equalizer type UUID.
-static const ::aidl::android::media::audio::common::AudioUuid EqualizerTypeUUID = {
- static_cast<int32_t>(0x0bed4300),
- 0xddd6,
- 0x11db,
- 0x8f34,
- {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-
-// Equalizer implementation UUID.
-static const ::aidl::android::media::audio::common::AudioUuid EqualizerSwImplUUID = {
- static_cast<int32_t>(0x0bed4300),
- 0x847d,
- 0x11df,
- 0xbb17,
- {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-
-class Equalizer : public BnEffect {
- public:
- Equalizer() = default;
- ndk::ScopedAStatus open() override;
- ndk::ScopedAStatus close() override;
- ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
-
- private:
- // Effect descriptor.
- Descriptor mDesc = {.common = {.id = {.type = EqualizerTypeUUID, .uuid = EqualizerSwImplUUID}}};
-};
-} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/include/visualizer-impl/Visualizer.h b/audio/aidl/default/include/visualizer-impl/Visualizer.h
deleted file mode 100644
index 4b82dd0..0000000
--- a/audio/aidl/default/include/visualizer-impl/Visualizer.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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 <cstdlib>
-
-namespace aidl::android::hardware::audio::effect {
-
-// Visualizer implementation UUID.
-static const ::aidl::android::media::audio::common::AudioUuid VisualizerUUID = {
- static_cast<int32_t>(0x1d4033c0),
- 0x8557,
- 0x11df,
- 0x9f2d,
- {0x00, 0x02, 0xa5, 0xd5, 0xc5, 0x1b}};
-
-} // namespace aidl::android::hardware::audio::effect
\ No newline at end of file
diff --git a/audio/aidl/default/loudnessEnhancer/Android.bp b/audio/aidl/default/loudnessEnhancer/Android.bp
new file mode 100644
index 0000000..3a0ac73
--- /dev/null
+++ b/audio/aidl/default/loudnessEnhancer/Android.bp
@@ -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.
+ */
+
+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: "libloudnessenhancersw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "LoudnessEnhancerSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp
new file mode 100644
index 0000000..9d2b978
--- /dev/null
+++ b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.cpp
@@ -0,0 +1,162 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_LoudnessEnhancerSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "LoudnessEnhancerSw.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kLoudnessEnhancerSwImplUUID;
+using aidl::android::hardware::audio::effect::LoudnessEnhancerSw;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kLoudnessEnhancerSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<LoudnessEnhancerSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ return EX_NONE;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus LoudnessEnhancerSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus LoudnessEnhancerSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::loudnessEnhancer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ auto& leParam = specific.get<Parameter::Specific::loudnessEnhancer>();
+ auto tag = leParam.getTag();
+
+ switch (tag) {
+ case LoudnessEnhancer::gainMb: {
+ RETURN_IF(mContext->setLeGainMb(leParam.get<LoudnessEnhancer::gainMb>()) !=
+ RetCode::SUCCESS,
+ EX_ILLEGAL_ARGUMENT, "setGainMbFailed");
+ return ndk::ScopedAStatus::ok();
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+ }
+ }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::loudnessEnhancerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ auto leId = id.get<Parameter::Id::loudnessEnhancerTag>();
+ auto leIdTag = leId.getTag();
+ switch (leIdTag) {
+ case LoudnessEnhancer::Id::commonTag:
+ return getParameterLoudnessEnhancer(leId.get<LoudnessEnhancer::Id::commonTag>(),
+ specific);
+ default:
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(leIdTag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+ }
+}
+
+ndk::ScopedAStatus LoudnessEnhancerSw::getParameterLoudnessEnhancer(
+ const LoudnessEnhancer::Tag& tag, Parameter::Specific* specific) {
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ LoudnessEnhancer leParam;
+ switch (tag) {
+ case LoudnessEnhancer::gainMb: {
+ leParam.set<LoudnessEnhancer::gainMb>(mContext->getLeGainMb());
+ break;
+ }
+ default: {
+ LOG(ERROR) << __func__ << " unsupported tag: " << toString(tag);
+ return ndk::ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_ILLEGAL_ARGUMENT, "LoudnessEnhancerTagNotSupported");
+ }
+ }
+
+ specific->set<Parameter::Specific::loudnessEnhancer>(leParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> LoudnessEnhancerSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<LoudnessEnhancerSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode LoudnessEnhancerSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status LoudnessEnhancerSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.h
new file mode 100644
index 0000000..856bf0b
--- /dev/null
+++ b/audio/aidl/default/loudnessEnhancer/LoudnessEnhancerSw.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/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class LoudnessEnhancerSwContext final : public EffectContext {
+ public:
+ LoudnessEnhancerSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+
+ RetCode setLeGainMb(int gainMb) {
+ // TODO : Add implementation to apply new gain
+ mGainMb = gainMb;
+ return RetCode::SUCCESS;
+ }
+ int getLeGainMb() const { return mGainMb; }
+
+ private:
+ int mGainMb = 0; // Default Gain
+};
+
+class LoudnessEnhancerSw final : public EffectImpl {
+ public:
+ LoudnessEnhancerSw() { LOG(DEBUG) << __func__; }
+ ~LoudnessEnhancerSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<LoudnessEnhancerSwContext> mContext;
+ /* capabilities */
+ const LoudnessEnhancer::Capability kCapability;
+ /* Effect descriptor */
+ const Descriptor kDescriptor = {
+ .common = {.id = {.type = kLoudnessEnhancerTypeUUID,
+ .uuid = kLoudnessEnhancerSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "LoudnessEnhancerSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::loudnessEnhancer>(kCapability)};
+
+ ndk::ScopedAStatus getParameterLoudnessEnhancer(const LoudnessEnhancer::Tag& tag,
+ Parameter::Specific* specific);
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/presetReverb/Android.bp b/audio/aidl/default/presetReverb/Android.bp
new file mode 100644
index 0000000..4148511
--- /dev/null
+++ b/audio/aidl/default/presetReverb/Android.bp
@@ -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.
+ */
+
+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: "libpresetreverbsw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "PresetReverbSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/presetReverb/PresetReverbSw.cpp b/audio/aidl/default/presetReverb/PresetReverbSw.cpp
new file mode 100644
index 0000000..069d0ff
--- /dev/null
+++ b/audio/aidl/default/presetReverb/PresetReverbSw.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_PresetReverbSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "PresetReverbSw.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kPresetReverbSwImplUUID;
+using aidl::android::hardware::audio::effect::PresetReverbSw;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kPresetReverbSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<PresetReverbSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ return EX_NONE;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus PresetReverbSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresetReverbSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::reverb != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ mSpecificParam = specific.get<Parameter::Specific::reverb>();
+ LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus PresetReverbSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::reverbTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ specific->set<Parameter::Specific::reverb>(mSpecificParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> PresetReverbSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<PresetReverbSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode PresetReverbSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status PresetReverbSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/presetReverb/PresetReverbSw.h b/audio/aidl/default/presetReverb/PresetReverbSw.h
new file mode 100644
index 0000000..75a5a94
--- /dev/null
+++ b/audio/aidl/default/presetReverb/PresetReverbSw.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class PresetReverbSwContext final : public EffectContext {
+ public:
+ PresetReverbSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+ // TODO: add specific context here
+};
+
+class PresetReverbSw final : public EffectImpl {
+ public:
+ PresetReverbSw() { LOG(DEBUG) << __func__; }
+ ~PresetReverbSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<PresetReverbSwContext> mContext;
+ /* capabilities */
+ const Reverb::Capability kCapability;
+ /* Effect descriptor */
+ const Descriptor kDescriptor = {
+ .common = {.id = {.type = kPresetReverbTypeUUID,
+ .uuid = kPresetReverbSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "PresetReverbSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::reverb>(kCapability)};
+
+ /* parameters */
+ Reverb mSpecificParam;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/virtualizer/Android.bp b/audio/aidl/default/virtualizer/Android.bp
new file mode 100644
index 0000000..ba38f5c
--- /dev/null
+++ b/audio/aidl/default/virtualizer/Android.bp
@@ -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.
+ */
+
+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: "libvirtualizersw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "VirtualizerSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.cpp b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
new file mode 100644
index 0000000..9688fc8
--- /dev/null
+++ b/audio/aidl/default/virtualizer/VirtualizerSw.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_VirtualizerSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "VirtualizerSw.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kVirtualizerSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::audio::effect::VirtualizerSw;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kVirtualizerSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<VirtualizerSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ return EX_NONE;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus VirtualizerSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VirtualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::virtualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ mSpecificParam = specific.get<Parameter::Specific::virtualizer>();
+ LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VirtualizerSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::virtualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ specific->set<Parameter::Specific::virtualizer>(mSpecificParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> VirtualizerSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<VirtualizerSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode VirtualizerSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status VirtualizerSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/virtualizer/VirtualizerSw.h b/audio/aidl/default/virtualizer/VirtualizerSw.h
new file mode 100644
index 0000000..e4de8b3
--- /dev/null
+++ b/audio/aidl/default/virtualizer/VirtualizerSw.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VirtualizerSwContext final : public EffectContext {
+ public:
+ VirtualizerSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+ // TODO: add specific context here
+};
+
+class VirtualizerSw final : public EffectImpl {
+ public:
+ VirtualizerSw() { LOG(DEBUG) << __func__; }
+ ~VirtualizerSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<VirtualizerSwContext> mContext;
+ /* capabilities */
+ const Virtualizer::Capability kCapability;
+ /* Effect descriptor */
+ const Descriptor kDescriptor = {
+ .common = {.id = {.type = kVirtualizerTypeUUID,
+ .uuid = kVirtualizerSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "VirtualizerSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::virtualizer>(kCapability)};
+
+ /* parameters */
+ Virtualizer mSpecificParam;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/visualizer/Android.bp b/audio/aidl/default/visualizer/Android.bp
new file mode 100644
index 0000000..5041be8
--- /dev/null
+++ b/audio/aidl/default/visualizer/Android.bp
@@ -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.
+ */
+
+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: "libvisualizersw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "VisualizerSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/visualizer/VisualizerSw.cpp b/audio/aidl/default/visualizer/VisualizerSw.cpp
new file mode 100644
index 0000000..24a7bef
--- /dev/null
+++ b/audio/aidl/default/visualizer/VisualizerSw.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_VisualizerSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "VisualizerSw.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kVisualizerSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::audio::effect::VisualizerSw;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kVisualizerSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<VisualizerSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ return EX_NONE;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus VisualizerSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::visualizer != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ mSpecificParam = specific.get<Parameter::Specific::visualizer>();
+ LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VisualizerSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::visualizerTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ specific->set<Parameter::Specific::visualizer>(mSpecificParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> VisualizerSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<VisualizerSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode VisualizerSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status VisualizerSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/visualizer/VisualizerSw.h b/audio/aidl/default/visualizer/VisualizerSw.h
new file mode 100644
index 0000000..bccd6e9
--- /dev/null
+++ b/audio/aidl/default/visualizer/VisualizerSw.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VisualizerSwContext final : public EffectContext {
+ public:
+ VisualizerSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+ // TODO: add specific context here
+};
+
+class VisualizerSw final : public EffectImpl {
+ public:
+ VisualizerSw() { LOG(DEBUG) << __func__; }
+ ~VisualizerSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<VisualizerSwContext> mContext;
+ /* capabilities */
+ const Visualizer::Capability kCapability;
+ /* Effect descriptor */
+ const Descriptor kDescriptor = {
+ .common = {.id = {.type = kVisualizerTypeUUID,
+ .uuid = kVisualizerSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "VisualizerSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::visualizer>(kCapability)};
+
+ /* parameters */
+ Visualizer mSpecificParam;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/volume/Android.bp b/audio/aidl/default/volume/Android.bp
new file mode 100644
index 0000000..505ee67
--- /dev/null
+++ b/audio/aidl/default/volume/Android.bp
@@ -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.
+ */
+
+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: "libvolumesw",
+ defaults: [
+ "aidlaudioeffectservice_defaults",
+ "latest_android_media_audio_common_types_ndk_shared",
+ "latest_android_hardware_audio_effect_ndk_shared",
+ ],
+ srcs: [
+ "VolumeSw.cpp",
+ ":effectCommonFile",
+ ],
+ visibility: [
+ "//hardware/interfaces/audio/aidl/default",
+ ],
+}
diff --git a/audio/aidl/default/volume/VolumeSw.cpp b/audio/aidl/default/volume/VolumeSw.cpp
new file mode 100644
index 0000000..b8af921
--- /dev/null
+++ b/audio/aidl/default/volume/VolumeSw.cpp
@@ -0,0 +1,118 @@
+/*
+ * 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 <cstddef>
+#define LOG_TAG "AHAL_VolumeSw"
+#include <Utils.h>
+#include <algorithm>
+#include <unordered_set>
+
+#include <android-base/logging.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "VolumeSw.h"
+
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::kVolumeSwImplUUID;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::audio::effect::VolumeSw;
+using aidl::android::media::audio::common::AudioUuid;
+
+extern "C" binder_exception_t createEffect(const AudioUuid* in_impl_uuid,
+ std::shared_ptr<IEffect>* instanceSpp) {
+ if (!in_impl_uuid || *in_impl_uuid != kVolumeSwImplUUID) {
+ LOG(ERROR) << __func__ << "uuid not supported";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+ if (instanceSpp) {
+ *instanceSpp = ndk::SharedRefBase::make<VolumeSw>();
+ LOG(DEBUG) << __func__ << " instance " << instanceSpp->get() << " created";
+ return EX_NONE;
+ } else {
+ LOG(ERROR) << __func__ << " invalid input parameter!";
+ return EX_ILLEGAL_ARGUMENT;
+ }
+}
+
+extern "C" binder_exception_t destroyEffect(const std::shared_ptr<IEffect>& instanceSp) {
+ if (!instanceSp) {
+ return EX_NONE;
+ }
+ State state;
+ ndk::ScopedAStatus status = instanceSp->getState(&state);
+ if (!status.isOk() || State::INIT != state) {
+ LOG(ERROR) << __func__ << " instance " << instanceSp.get()
+ << " in state: " << toString(state) << ", status: " << status.getDescription();
+ return EX_ILLEGAL_STATE;
+ }
+ LOG(DEBUG) << __func__ << " instance " << instanceSp.get() << " destroyed";
+ return EX_NONE;
+}
+
+namespace aidl::android::hardware::audio::effect {
+
+ndk::ScopedAStatus VolumeSw::getDescriptor(Descriptor* _aidl_return) {
+ LOG(DEBUG) << __func__ << kDescriptor.toString();
+ *_aidl_return = kDescriptor;
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VolumeSw::setParameterSpecific(const Parameter::Specific& specific) {
+ RETURN_IF(Parameter::Specific::volume != specific.getTag(), EX_ILLEGAL_ARGUMENT,
+ "EffectNotSupported");
+ std::lock_guard lg(mMutex);
+ RETURN_IF(!mContext, EX_NULL_POINTER, "nullContext");
+
+ mSpecificParam = specific.get<Parameter::Specific::volume>();
+ LOG(DEBUG) << __func__ << " success with: " << specific.toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus VolumeSw::getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) {
+ auto tag = id.getTag();
+ RETURN_IF(Parameter::Id::volumeTag != tag, EX_ILLEGAL_ARGUMENT, "wrongIdTag");
+ specific->set<Parameter::Specific::volume>(mSpecificParam);
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<EffectContext> VolumeSw::createContext(const Parameter::Common& common) {
+ if (mContext) {
+ LOG(DEBUG) << __func__ << " context already exist";
+ return mContext;
+ }
+ mContext = std::make_shared<VolumeSwContext>(1 /* statusFmqDepth */, common);
+ return mContext;
+}
+
+RetCode VolumeSw::releaseContext() {
+ if (mContext) {
+ mContext.reset();
+ }
+ return RetCode::SUCCESS;
+}
+
+// Processing method running in EffectWorker thread.
+IEffect::Status VolumeSw::effectProcessImpl(float* in, float* out, int process) {
+ // TODO: get data buffer and process.
+ LOG(DEBUG) << __func__ << " in " << in << " out " << out << " process " << process;
+ for (int i = 0; i < process; i++) {
+ *out++ = *in++;
+ }
+ return {STATUS_OK, process, process};
+}
+
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/volume/VolumeSw.h b/audio/aidl/default/volume/VolumeSw.h
new file mode 100644
index 0000000..86e01c1
--- /dev/null
+++ b/audio/aidl/default/volume/VolumeSw.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/effect/BnEffect.h>
+#include <fmq/AidlMessageQueue.h>
+#include <cstdlib>
+#include <memory>
+
+#include "effect-impl/EffectImpl.h"
+#include "effect-impl/EffectUUID.h"
+
+namespace aidl::android::hardware::audio::effect {
+
+class VolumeSwContext final : public EffectContext {
+ public:
+ VolumeSwContext(int statusDepth, const Parameter::Common& common)
+ : EffectContext(statusDepth, common) {
+ LOG(DEBUG) << __func__;
+ }
+ // TODO: add specific context here
+};
+
+class VolumeSw final : public EffectImpl {
+ public:
+ VolumeSw() { LOG(DEBUG) << __func__; }
+ ~VolumeSw() {
+ cleanUp();
+ LOG(DEBUG) << __func__;
+ }
+
+ ndk::ScopedAStatus getDescriptor(Descriptor* _aidl_return) override;
+ ndk::ScopedAStatus setParameterSpecific(const Parameter::Specific& specific) override;
+ ndk::ScopedAStatus getParameterSpecific(const Parameter::Id& id,
+ Parameter::Specific* specific) override;
+ IEffect::Status effectProcessImpl(float* in, float* out, int process) override;
+ std::shared_ptr<EffectContext> createContext(const Parameter::Common& common) override;
+ RetCode releaseContext() override;
+
+ private:
+ std::shared_ptr<VolumeSwContext> mContext;
+ /* capabilities */
+ const Volume::Capability kCapability;
+ /* Effect descriptor */
+ const Descriptor kDescriptor = {
+ .common = {.id = {.type = kVolumeTypeUUID,
+ .uuid = kVolumeSwImplUUID,
+ .proxy = std::nullopt},
+ .flags = {.type = Flags::Type::INSERT,
+ .insert = Flags::Insert::FIRST,
+ .volume = Flags::Volume::CTRL},
+ .name = "VolumeSw",
+ .implementor = "The Android Open Source Project"},
+ .capability = Capability::make<Capability::volume>(kCapability)};
+
+ /* parameters */
+ Volume mSpecificParam;
+};
+} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/vts/Android.bp b/audio/aidl/vts/Android.bp
index 6ea7cef..03e9fca 100644
--- a/audio/aidl/vts/Android.bp
+++ b/audio/aidl/vts/Android.bp
@@ -7,35 +7,31 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
-cc_test {
- name: "VtsHalAudioCoreTargetTest",
+cc_defaults {
+ name: "VtsHalAudioTargetTestDefaults",
defaults: [
- "VtsHalTargetTestDefaults",
- "use_libaidlvintf_gtest_helper_static",
"latest_android_hardware_audio_common_ndk_static",
- "latest_android_hardware_audio_core_ndk_static",
"latest_android_media_audio_common_types_ndk_static",
+ "use_libaidlvintf_gtest_helper_static",
+ "VtsHalTargetTestDefaults",
],
shared_libs: [
"libbinder_ndk",
- "libcutils",
"libfmq",
],
static_libs: [
+ "android.hardware.audio.effect-V1-ndk",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
"libaudioaidlcommon",
],
+ header_libs: ["libaudioaidl_headers"],
cflags: [
"-Wall",
"-Wextra",
"-Werror",
"-Wthread-safety",
],
- srcs: [
- "ModuleConfig.cpp",
- "VtsHalAudioCoreTargetTest.cpp",
- ],
test_suites: [
"general-tests",
"vts",
@@ -43,29 +39,40 @@
}
cc_test {
- name: "VtsHalAudioEffectTargetTest",
+ name: "VtsHalAudioCoreTargetTest",
defaults: [
- "latest_android_media_audio_common_types_ndk_static",
- "VtsHalTargetTestDefaults",
- "use_libaidlvintf_gtest_helper_static",
- ],
- srcs: [
- "VtsHalAudioEffectTargetTest.cpp",
+ "VtsHalAudioTargetTestDefaults",
+ "latest_android_hardware_audio_core_ndk_static",
],
shared_libs: [
- "libbinder_ndk",
+ "libcutils",
],
- static_libs: [
- "android.hardware.audio.effect-V1-ndk",
+ srcs: [
+ "ModuleConfig.cpp",
+ "VtsHalAudioCoreTargetTest.cpp",
],
- cflags: [
- "-Wall",
- "-Wextra",
- "-Werror",
- "-Wthread-safety",
- ],
- test_suites: [
- "general-tests",
- "vts",
- ],
+}
+
+cc_test {
+ name: "VtsHalAudioEffectFactoryTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalAudioEffectFactoryTargetTest.cpp"],
+}
+
+cc_test {
+ name: "VtsHalAudioEffectTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalAudioEffectTargetTest.cpp"],
+}
+
+cc_test {
+ name: "VtsHalEqualizerTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalEqualizerTargetTest.cpp"],
+}
+
+cc_test {
+ name: "VtsHalLoudnessEnhancerTargetTest",
+ defaults: ["VtsHalAudioTargetTestDefaults"],
+ srcs: ["VtsHalLoudnessEnhancerTargetTest.cpp"],
}
diff --git a/audio/aidl/vts/AudioHalBinderServiceUtil.h b/audio/aidl/vts/AudioHalBinderServiceUtil.h
index e928286..c8d81b1 100644
--- a/audio/aidl/vts/AudioHalBinderServiceUtil.h
+++ b/audio/aidl/vts/AudioHalBinderServiceUtil.h
@@ -21,6 +21,7 @@
#include <mutex>
#include <android-base/properties.h>
+#include <android/binder_auto_utils.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
@@ -34,7 +35,7 @@
if (mBinder == nullptr) {
LOG(ERROR) << "Failed to get service " << serviceName;
} else {
- LOG(DEBUG) << "succeed to get service " << serviceName;
+ LOG(DEBUG) << "Succeeded to get service " << serviceName;
}
return mBinder;
}
diff --git a/audio/aidl/vts/EffectFactoryHelper.h b/audio/aidl/vts/EffectFactoryHelper.h
new file mode 100644
index 0000000..dc766dd
--- /dev/null
+++ b/audio/aidl/vts/EffectFactoryHelper.h
@@ -0,0 +1,80 @@
+/*
+ * 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 <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <android/binder_auto_utils.h>
+
+#include "TestUtils.h"
+#include "effect-impl/EffectUUID.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::media::audio::common::AudioUuid;
+
+class EffectFactoryHelper {
+ public:
+ explicit EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
+
+ void ConnectToFactoryService() {
+ mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName));
+ ASSERT_NE(mEffectFactory, nullptr);
+ }
+
+ void RestartFactoryService() {
+ ASSERT_NE(mEffectFactory, nullptr);
+ mEffectFactory = IFactory::fromBinder(binderUtil.restartService());
+ ASSERT_NE(mEffectFactory, nullptr);
+ }
+
+ std::shared_ptr<IFactory> GetFactory() const { return mEffectFactory; }
+
+ static std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>>
+ getAllEffectDescriptors(std::string serviceName, std::optional<AudioUuid> type = std::nullopt) {
+ AudioHalBinderServiceUtil util;
+ auto names = android::getAidlHalInstanceNames(serviceName);
+ std::vector<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>> result;
+
+ for (const auto& name : names) {
+ auto factory = IFactory::fromBinder(util.connectToService(name));
+ if (factory) {
+ if (std::vector<Descriptor::Identity> ids;
+ factory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids).isOk()) {
+ for (const auto& id : ids) {
+ if (type.has_value() && id.type != type.value()) {
+ continue;
+ }
+ result.emplace_back(factory, id);
+ }
+ }
+ }
+ }
+
+ return result;
+ }
+
+ private:
+ std::shared_ptr<IFactory> mEffectFactory;
+ std::string mServiceName;
+ AudioHalBinderServiceUtil binderUtil;
+};
diff --git a/audio/aidl/vts/EffectHelper.h b/audio/aidl/vts/EffectHelper.h
new file mode 100644
index 0000000..73a1f49
--- /dev/null
+++ b/audio/aidl/vts/EffectHelper.h
@@ -0,0 +1,184 @@
+/*
+ * 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 <algorithm>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <aidl/android/media/audio/common/AudioChannelLayout.h>
+#include <android/binder_auto_utils.h>
+#include <fmq/AidlMessageQueue.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectFactoryHelper.h"
+#include "TestUtils.h"
+
+using namespace android;
+using aidl::android::hardware::audio::effect::CommandId;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::State;
+using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
+using aidl::android::media::audio::common::AudioChannelLayout;
+using aidl::android::media::audio::common::AudioFormatDescription;
+using aidl::android::media::audio::common::AudioFormatType;
+using aidl::android::media::audio::common::AudioUuid;
+using aidl::android::media::audio::common::PcmType;
+
+const AudioFormatDescription kDefaultFormatDescription = {
+ .type = AudioFormatType::PCM, .pcm = PcmType::FLOAT_32_BIT, .encoding = ""};
+
+typedef ::android::AidlMessageQueue<IEffect::Status,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ StatusMQ;
+typedef ::android::AidlMessageQueue<float,
+ ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ DataMQ;
+
+class EffectHelper {
+ public:
+ static void create(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect>& effect,
+ Descriptor::Identity id, binder_status_t status = EX_NONE) {
+ ASSERT_NE(factory, nullptr);
+ EXPECT_STATUS(status, factory->createEffect(id.uuid, &effect));
+ if (status == EX_NONE) {
+ ASSERT_NE(effect, nullptr) << id.uuid.toString();
+ }
+ }
+
+ static void destroy(std::shared_ptr<IFactory> factory, std::shared_ptr<IEffect> effect,
+ binder_status_t status = EX_NONE) {
+ ASSERT_NE(factory, nullptr);
+ ASSERT_NE(effect, nullptr);
+ EXPECT_STATUS(status, factory->destroyEffect(effect));
+ }
+
+ static void open(std::shared_ptr<IEffect> effect, const Parameter::Common& common,
+ const std::optional<Parameter::Specific>& specific,
+ IEffect::OpenEffectReturn* ret, binder_status_t status = EX_NONE) {
+ ASSERT_NE(effect, nullptr);
+ EXPECT_STATUS(status, effect->open(common, specific, ret));
+ }
+
+ static void open(std::shared_ptr<IEffect> effect, int session = 0,
+ binder_status_t status = EX_NONE) {
+ ASSERT_NE(effect, nullptr);
+ Parameter::Common common = EffectHelper::createParamCommon(session);
+ IEffect::OpenEffectReturn ret;
+ open(effect, common, std::nullopt /* specific */, &ret, status);
+ }
+
+ static void close(std::shared_ptr<IEffect> effect, binder_status_t status = EX_NONE) {
+ if (effect) {
+ EXPECT_STATUS(status, effect->close());
+ }
+ }
+ static void getDescriptor(std::shared_ptr<IEffect> effect, Descriptor& desc,
+ binder_status_t status = EX_NONE) {
+ ASSERT_NE(effect, nullptr);
+ EXPECT_STATUS(status, effect->getDescriptor(&desc));
+ }
+ static void expectState(std::shared_ptr<IEffect> effect, State expectState,
+ binder_status_t status = EX_NONE) {
+ ASSERT_NE(effect, nullptr);
+ State state;
+ EXPECT_STATUS(status, effect->getState(&state));
+ EXPECT_EQ(expectState, state);
+ }
+ static void command(std::shared_ptr<IEffect> effect, CommandId command,
+ binder_status_t status = EX_NONE) {
+ ASSERT_NE(effect, nullptr);
+ EXPECT_STATUS(status, effect->command(command));
+ }
+ static void allocateInputData(const Parameter::Common common, std::unique_ptr<DataMQ>& mq,
+ std::vector<float>& buffer) {
+ ASSERT_NE(mq, nullptr);
+ auto frameSize = android::hardware::audio::common::getFrameSizeInBytes(
+ common.input.base.format, common.input.base.channelMask);
+ const size_t floatsToWrite = mq->availableToWrite();
+ EXPECT_NE(0UL, floatsToWrite);
+ EXPECT_EQ(frameSize * common.input.frameCount, floatsToWrite * sizeof(float));
+ buffer.resize(floatsToWrite);
+ std::fill(buffer.begin(), buffer.end(), 0x5a);
+ }
+ static void writeToFmq(std::unique_ptr<DataMQ>& mq, const std::vector<float>& buffer) {
+ const size_t available = mq->availableToWrite();
+ EXPECT_NE(0Ul, available);
+ auto bufferFloats = buffer.size();
+ auto floatsToWrite = std::min(available, bufferFloats);
+ EXPECT_TRUE(mq->write(buffer.data(), floatsToWrite));
+ }
+ static void readFromFmq(std::unique_ptr<StatusMQ>& statusMq, size_t statusNum,
+ std::unique_ptr<DataMQ>& dataMq, size_t expectFloats,
+ std::vector<float>& buffer) {
+ IEffect::Status status{};
+ EXPECT_TRUE(statusMq->readBlocking(&status, statusNum));
+ EXPECT_EQ(STATUS_OK, status.status);
+ if (statusNum != 0) {
+ EXPECT_EQ(expectFloats, (unsigned)status.fmqProduced);
+ EXPECT_EQ(expectFloats, dataMq->availableToRead());
+ if (expectFloats != 0) {
+ EXPECT_TRUE(dataMq->read(buffer.data(), expectFloats));
+ }
+ }
+ }
+ static Parameter::Common createParamCommon(
+ int session = 0, int ioHandle = -1, int iSampleRate = 48000, int oSampleRate = 48000,
+ long iFrameCount = 0x100, long oFrameCount = 0x100,
+ AudioChannelLayout inputChannelLayout =
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO),
+ AudioChannelLayout outputChannelLayout =
+ AudioChannelLayout::make<AudioChannelLayout::layoutMask>(
+ AudioChannelLayout::LAYOUT_STEREO)) {
+ Parameter::Common common;
+ common.session = session;
+ common.ioHandle = ioHandle;
+
+ auto& input = common.input;
+ auto& output = common.output;
+ input.base.sampleRate = iSampleRate;
+ input.base.channelMask = inputChannelLayout;
+ input.base.format = kDefaultFormatDescription;
+ input.frameCount = iFrameCount;
+ output.base.sampleRate = oSampleRate;
+ output.base.channelMask = outputChannelLayout;
+ output.base.format = kDefaultFormatDescription;
+ output.frameCount = oFrameCount;
+ return common;
+ }
+
+ typedef ::android::AidlMessageQueue<
+ IEffect::Status, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ StatusMQ;
+ typedef ::android::AidlMessageQueue<
+ float, ::aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ DataMQ;
+
+ class EffectParam {
+ public:
+ std::unique_ptr<StatusMQ> statusMQ;
+ std::unique_ptr<DataMQ> inputMQ;
+ std::unique_ptr<DataMQ> outputMQ;
+ };
+};
diff --git a/audio/aidl/vts/TestUtils.h b/audio/aidl/vts/TestUtils.h
index 2fc109a..5e4d56a 100644
--- a/audio/aidl/vts/TestUtils.h
+++ b/audio/aidl/vts/TestUtils.h
@@ -21,15 +21,6 @@
#include <android/binder_auto_utils.h>
#include <gtest/gtest_pred_impl.h>
-namespace ndk {
-
-std::ostream& operator<<(std::ostream& str, const ScopedAStatus& status) {
- str << status.getDescription();
- return str;
-}
-
-} // namespace ndk
-
namespace android::hardware::audio::common::testing {
namespace detail {
diff --git a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
index 2381200..5e9aa7f 100644
--- a/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreTargetTest.cpp
@@ -15,6 +15,7 @@
*/
#include <algorithm>
+#include <cmath>
#include <limits>
#include <memory>
#include <optional>
@@ -29,11 +30,12 @@
#include <Utils.h>
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
-#include <aidl/android/hardware/audio/core/IConfig.h>
#include <aidl/android/hardware/audio/core/IModule.h>
+#include <aidl/android/hardware/audio/core/ITelephony.h>
#include <aidl/android/media/audio/common/AudioIoFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
#include <android-base/chrono_utils.h>
+#include <android/binder_enums.h>
#include <fmq/AidlMessageQueue.h>
#include "AudioHalBinderServiceUtil.h"
@@ -45,11 +47,13 @@
using aidl::android::hardware::audio::common::RecordTrackMetadata;
using aidl::android::hardware::audio::common::SinkMetadata;
using aidl::android::hardware::audio::common::SourceMetadata;
+using aidl::android::hardware::audio::core::AudioMode;
using aidl::android::hardware::audio::core::AudioPatch;
using aidl::android::hardware::audio::core::AudioRoute;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::IStreamIn;
using aidl::android::hardware::audio::core::IStreamOut;
+using aidl::android::hardware::audio::core::ITelephony;
using aidl::android::hardware::audio::core::ModuleDebug;
using aidl::android::hardware::audio::core::StreamDescriptor;
using aidl::android::hardware::common::fmq::SynchronizedReadWrite;
@@ -66,9 +70,11 @@
using aidl::android::media::audio::common::AudioPortExt;
using aidl::android::media::audio::common::AudioSource;
using aidl::android::media::audio::common::AudioUsage;
+using aidl::android::media::audio::common::Void;
using android::hardware::audio::common::isBitPositionFlagSet;
using android::hardware::audio::common::StreamLogic;
using android::hardware::audio::common::StreamWorker;
+using ndk::enum_range;
using ndk::ScopedAStatus;
template <typename T>
@@ -171,25 +177,49 @@
AudioPortConfig mConfig;
};
-class AudioCoreModule : public testing::TestWithParam<std::string> {
+template <typename PropType, class Instance, typename Getter, typename Setter>
+void TestAccessors(Instance* inst, Getter getter, Setter setter,
+ const std::vector<PropType>& validValues,
+ const std::vector<PropType>& invalidValues, bool* isSupported) {
+ PropType initialValue{};
+ ScopedAStatus status = (inst->*getter)(&initialValue);
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ *isSupported = false;
+ return;
+ }
+ *isSupported = true;
+ for (const auto v : validValues) {
+ EXPECT_IS_OK((inst->*setter)(v)) << "for valid value: " << v;
+ PropType currentValue{};
+ EXPECT_IS_OK((inst->*getter)(¤tValue));
+ EXPECT_EQ(v, currentValue);
+ }
+ for (const auto v : invalidValues) {
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, (inst->*setter)(v)) << "for invalid value: " << v;
+ }
+ EXPECT_IS_OK((inst->*setter)(initialValue)) << "Failed to restore the initial value";
+}
+
+// Can be used as a base for any test here, does not depend on the fixture GTest parameters.
+class AudioCoreModuleBase {
public:
// The default buffer size is used mostly for negative tests.
static constexpr int kDefaultBufferSizeFrames = 256;
- void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(ConnectToService());
+ void SetUpImpl(const std::string& moduleName) {
+ ASSERT_NO_FATAL_FAILURE(ConnectToService(moduleName));
debug.flags().simulateDeviceConnections = true;
ASSERT_NO_FATAL_FAILURE(debug.SetUp(module.get()));
}
- void TearDown() override {
+ void TearDownImpl() {
if (module != nullptr) {
EXPECT_IS_OK(module->setModuleDebug(ModuleDebug{}));
}
}
- void ConnectToService() {
- module = IModule::fromBinder(binderUtil.connectToService(GetParam()));
+ void ConnectToService(const std::string& moduleName) {
+ module = IModule::fromBinder(binderUtil.connectToService(moduleName));
ASSERT_NE(module, nullptr);
}
@@ -269,6 +299,13 @@
WithDebugFlags debug;
};
+class AudioCoreModule : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override { ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam())); }
+
+ void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
+};
+
class WithDevicePortConnectedState {
public:
explicit WithDevicePortConnectedState(const AudioPort& idAndData) : mIdAndData(idAndData) {}
@@ -352,21 +389,36 @@
std::unique_ptr<DataMQ> mDataMQ;
};
-class StreamCommonLogic : public StreamLogic {
+class StreamLogicDriver {
public:
- StreamDescriptor::Position getLastObservablePosition() {
- std::lock_guard<std::mutex> lock(mLock);
- return mLastReply.observable;
- }
+ virtual ~StreamLogicDriver() = default;
+ // Return 'true' to stop the worker.
+ virtual bool done() = 0;
+ // For 'Writer' logic, if the 'actualSize' is 0, write is skipped.
+ // The 'fmqByteCount' from the returned command is passed as is to the HAL.
+ virtual StreamDescriptor::Command getNextCommand(int maxDataSize,
+ int* actualSize = nullptr) = 0;
+ // Return 'true' to indicate that no further processing is needed,
+ // for example, the driver is expecting a bad status to be returned.
+ // The logic cycle will return with 'CONTINUE' status. Otherwise,
+ // the reply will be validated and then passed to 'processValidReply'.
+ virtual bool interceptRawReply(const StreamDescriptor::Reply& reply) = 0;
+ // Return 'false' to indicate that the contents of the reply are unexpected.
+ // Will abort the logic cycle.
+ virtual bool processValidReply(const StreamDescriptor::Reply& reply) = 0;
+};
+class StreamCommonLogic : public StreamLogic {
protected:
- explicit StreamCommonLogic(const StreamContext& context)
+ StreamCommonLogic(const StreamContext& context, StreamLogicDriver* driver)
: mCommandMQ(context.getCommandMQ()),
mReplyMQ(context.getReplyMQ()),
mDataMQ(context.getDataMQ()),
- mData(context.getBufferSizeBytes()) {}
+ mData(context.getBufferSizeBytes()),
+ mDriver(driver) {}
StreamContext::CommandMQ* getCommandMQ() const { return mCommandMQ; }
StreamContext::ReplyMQ* getReplyMQ() const { return mReplyMQ; }
+ StreamLogicDriver* getDriver() const { return mDriver; }
std::string init() override { return ""; }
@@ -374,19 +426,20 @@
StreamContext::ReplyMQ* mReplyMQ;
StreamContext::DataMQ* mDataMQ;
std::vector<int8_t> mData;
- std::mutex mLock;
- StreamDescriptor::Reply mLastReply GUARDED_BY(mLock);
+ StreamLogicDriver* const mDriver;
};
class StreamReaderLogic : public StreamCommonLogic {
public:
- explicit StreamReaderLogic(const StreamContext& context) : StreamCommonLogic(context) {}
+ StreamReaderLogic(const StreamContext& context, StreamLogicDriver* driver)
+ : StreamCommonLogic(context, driver) {}
protected:
Status cycle() override {
- StreamDescriptor::Command command{};
- command.code = StreamDescriptor::COMMAND_BURST;
- command.fmqByteCount = mData.size();
+ if (getDriver()->done()) {
+ return Status::EXIT;
+ }
+ StreamDescriptor::Command command = getDriver()->getNextCommand(mData.size());
if (!mCommandMQ->writeBlocking(&command, 1)) {
LOG(ERROR) << __func__ << ": writing of command into MQ failed";
return Status::ABORT;
@@ -396,25 +449,55 @@
LOG(ERROR) << __func__ << ": reading of reply from MQ failed";
return Status::ABORT;
}
+ if (getDriver()->interceptRawReply(reply)) {
+ return Status::CONTINUE;
+ }
if (reply.status != STATUS_OK) {
LOG(ERROR) << __func__ << ": received error status: " << statusToString(reply.status);
return Status::ABORT;
}
- if (reply.fmqByteCount < 0 || reply.fmqByteCount > command.fmqByteCount) {
+ if (reply.fmqByteCount < 0 ||
+ (command.getTag() == StreamDescriptor::Command::Tag::burst &&
+ reply.fmqByteCount > command.get<StreamDescriptor::Command::Tag::burst>())) {
LOG(ERROR) << __func__
<< ": received invalid byte count in the reply: " << reply.fmqByteCount;
return Status::ABORT;
}
- {
- std::lock_guard<std::mutex> lock(mLock);
- mLastReply = reply;
+ if (static_cast<size_t>(reply.fmqByteCount) != mDataMQ->availableToRead()) {
+ LOG(ERROR) << __func__
+ << ": the byte count in the reply is not the same as the amount of "
+ << "data available in the MQ: " << reply.fmqByteCount
+ << " != " << mDataMQ->availableToRead();
}
- const size_t readCount = std::min({mDataMQ->availableToRead(),
- static_cast<size_t>(reply.fmqByteCount), mData.size()});
- if (readCount == 0 || mDataMQ->read(mData.data(), readCount)) {
+ if (reply.latencyMs < 0 && reply.latencyMs != StreamDescriptor::LATENCY_UNKNOWN) {
+ LOG(ERROR) << __func__ << ": received invalid latency value: " << reply.latencyMs;
+ return Status::ABORT;
+ }
+ if (reply.xrunFrames < 0) {
+ LOG(ERROR) << __func__ << ": received invalid xrunFrames value: " << reply.xrunFrames;
+ return Status::ABORT;
+ }
+ if (std::find(enum_range<StreamDescriptor::State>().begin(),
+ enum_range<StreamDescriptor::State>().end(),
+ reply.state) == enum_range<StreamDescriptor::State>().end()) {
+ LOG(ERROR) << __func__ << ": received invalid stream state: " << toString(reply.state);
+ return Status::ABORT;
+ }
+ const bool acceptedReply = getDriver()->processValidReply(reply);
+ if (const size_t readCount = mDataMQ->availableToRead(); readCount > 0) {
+ std::vector<int8_t> data(readCount);
+ if (mDataMQ->read(data.data(), readCount)) {
+ memcpy(mData.data(), data.data(), std::min(mData.size(), data.size()));
+ goto checkAcceptedReply;
+ }
+ LOG(ERROR) << __func__ << ": reading of " << readCount << " data bytes from MQ failed";
+ return Status::ABORT;
+ } // readCount == 0
+ checkAcceptedReply:
+ if (acceptedReply) {
return Status::CONTINUE;
}
- LOG(ERROR) << __func__ << ": reading of " << readCount << " data bytes from MQ failed";
+ LOG(ERROR) << __func__ << ": unacceptable reply: " << reply.toString();
return Status::ABORT;
}
};
@@ -422,17 +505,20 @@
class StreamWriterLogic : public StreamCommonLogic {
public:
- explicit StreamWriterLogic(const StreamContext& context) : StreamCommonLogic(context) {}
+ StreamWriterLogic(const StreamContext& context, StreamLogicDriver* driver)
+ : StreamCommonLogic(context, driver) {}
protected:
Status cycle() override {
- if (!mDataMQ->write(mData.data(), mData.size())) {
+ if (getDriver()->done()) {
+ return Status::EXIT;
+ }
+ int actualSize = 0;
+ StreamDescriptor::Command command = getDriver()->getNextCommand(mData.size(), &actualSize);
+ if (actualSize != 0 && !mDataMQ->write(mData.data(), mData.size())) {
LOG(ERROR) << __func__ << ": writing of " << mData.size() << " bytes to MQ failed";
return Status::ABORT;
}
- StreamDescriptor::Command command{};
- command.code = StreamDescriptor::COMMAND_BURST;
- command.fmqByteCount = mData.size();
if (!mCommandMQ->writeBlocking(&command, 1)) {
LOG(ERROR) << __func__ << ": writing of command into MQ failed";
return Status::ABORT;
@@ -442,20 +528,45 @@
LOG(ERROR) << __func__ << ": reading of reply from MQ failed";
return Status::ABORT;
}
+ if (getDriver()->interceptRawReply(reply)) {
+ return Status::CONTINUE;
+ }
if (reply.status != STATUS_OK) {
LOG(ERROR) << __func__ << ": received error status: " << statusToString(reply.status);
return Status::ABORT;
}
- if (reply.fmqByteCount < 0 || reply.fmqByteCount > command.fmqByteCount) {
+ if (reply.fmqByteCount < 0 ||
+ (command.getTag() == StreamDescriptor::Command::Tag::burst &&
+ reply.fmqByteCount > command.get<StreamDescriptor::Command::Tag::burst>())) {
LOG(ERROR) << __func__
<< ": received invalid byte count in the reply: " << reply.fmqByteCount;
return Status::ABORT;
}
- {
- std::lock_guard<std::mutex> lock(mLock);
- mLastReply = reply;
+ if (mDataMQ->availableToWrite() != mDataMQ->getQuantumCount()) {
+ LOG(ERROR) << __func__ << ": the HAL module did not consume all data from the data MQ: "
+ << "available to write " << mDataMQ->availableToWrite()
+ << ", total size: " << mDataMQ->getQuantumCount();
+ return Status::ABORT;
}
- return Status::CONTINUE;
+ if (reply.latencyMs < 0 && reply.latencyMs != StreamDescriptor::LATENCY_UNKNOWN) {
+ LOG(ERROR) << __func__ << ": received invalid latency value: " << reply.latencyMs;
+ return Status::ABORT;
+ }
+ if (reply.xrunFrames < 0) {
+ LOG(ERROR) << __func__ << ": received invalid xrunFrames value: " << reply.xrunFrames;
+ return Status::ABORT;
+ }
+ if (std::find(enum_range<StreamDescriptor::State>().begin(),
+ enum_range<StreamDescriptor::State>().end(),
+ reply.state) == enum_range<StreamDescriptor::State>().end()) {
+ LOG(ERROR) << __func__ << ": received invalid stream state: " << toString(reply.state);
+ return Status::ABORT;
+ }
+ if (getDriver()->processValidReply(reply)) {
+ return Status::CONTINUE;
+ }
+ LOG(ERROR) << __func__ << ": unacceptable reply: " << reply.toString();
+ return Status::ABORT;
}
};
using StreamWriter = StreamWorker<StreamWriterLogic>;
@@ -466,52 +577,6 @@
using Worker = std::conditional_t<is_input, StreamReader, StreamWriter>;
};
-// A dedicated version to test replies to invalid commands.
-class StreamInvalidCommandLogic : public StreamCommonLogic {
- public:
- StreamInvalidCommandLogic(const StreamContext& context,
- const std::vector<StreamDescriptor::Command>& commands)
- : StreamCommonLogic(context), mCommands(commands) {}
-
- std::vector<std::string> getUnexpectedStatuses() {
- std::lock_guard<std::mutex> lock(mLock);
- return mUnexpectedStatuses;
- }
-
- protected:
- Status cycle() override {
- // Send all commands in one cycle to simplify testing.
- // Extra logging helps to sort out issues with unexpected HAL behavior.
- for (const auto& command : mCommands) {
- LOG(INFO) << __func__ << ": writing command " << command.toString() << " into MQ...";
- if (!getCommandMQ()->writeBlocking(&command, 1)) {
- LOG(ERROR) << __func__ << ": writing of command into MQ failed";
- return Status::ABORT;
- }
- StreamDescriptor::Reply reply{};
- LOG(INFO) << __func__ << ": reading reply for command " << command.toString() << "...";
- if (!getReplyMQ()->readBlocking(&reply, 1)) {
- LOG(ERROR) << __func__ << ": reading of reply from MQ failed";
- return Status::ABORT;
- }
- LOG(INFO) << __func__ << ": received status " << statusToString(reply.status)
- << " for command " << command.toString();
- if (reply.status != STATUS_BAD_VALUE) {
- std::string s = command.toString();
- s.append(", ").append(statusToString(reply.status));
- std::lock_guard<std::mutex> lock(mLock);
- mUnexpectedStatuses.push_back(std::move(s));
- }
- };
- return Status::EXIT;
- }
-
- private:
- const std::vector<StreamDescriptor::Command> mCommands;
- std::mutex mLock;
- std::vector<std::string> mUnexpectedStatuses GUARDED_BY(mLock);
-};
-
template <typename Stream>
class WithStream {
public:
@@ -1208,6 +1273,152 @@
}
}
+TEST_P(AudioCoreModule, MasterMute) {
+ bool isSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestAccessors<bool>(module.get(), &IModule::getMasterMute,
+ &IModule::setMasterMute, {false, true}, {},
+ &isSupported));
+ if (!isSupported) {
+ GTEST_SKIP() << "Master mute is not supported";
+ }
+ // TODO: Test that master mute actually mutes output.
+}
+
+TEST_P(AudioCoreModule, MasterVolume) {
+ bool isSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestAccessors<float>(
+ module.get(), &IModule::getMasterVolume, &IModule::setMasterVolume, {0.0f, 0.5f, 1.0f},
+ {-0.1, 1.1, NAN, INFINITY, -INFINITY, 1 + std::numeric_limits<float>::epsilon()},
+ &isSupported));
+ if (!isSupported) {
+ GTEST_SKIP() << "Master volume is not supported";
+ }
+ // TODO: Test that master volume actually attenuates output.
+}
+
+TEST_P(AudioCoreModule, MicMute) {
+ bool isSupported = false;
+ EXPECT_NO_FATAL_FAILURE(TestAccessors<bool>(module.get(), &IModule::getMicMute,
+ &IModule::setMicMute, {false, true}, {},
+ &isSupported));
+ if (!isSupported) {
+ GTEST_SKIP() << "Mic mute is not supported";
+ }
+ // TODO: Test that mic mute actually mutes input.
+}
+
+TEST_P(AudioCoreModule, UpdateAudioMode) {
+ for (const auto mode : ::ndk::enum_range<AudioMode>()) {
+ EXPECT_IS_OK(module->updateAudioMode(mode)) << toString(mode);
+ }
+ EXPECT_IS_OK(module->updateAudioMode(AudioMode::NORMAL));
+}
+
+TEST_P(AudioCoreModule, UpdateScreenRotation) {
+ for (const auto rotation : ::ndk::enum_range<IModule::ScreenRotation>()) {
+ EXPECT_IS_OK(module->updateScreenRotation(rotation)) << toString(rotation);
+ }
+ EXPECT_IS_OK(module->updateScreenRotation(IModule::ScreenRotation::DEG_0));
+}
+
+TEST_P(AudioCoreModule, UpdateScreenState) {
+ EXPECT_IS_OK(module->updateScreenState(false));
+ EXPECT_IS_OK(module->updateScreenState(true));
+}
+
+class AudioCoreTelephony : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam()));
+ ASSERT_IS_OK(module->getTelephony(&telephony));
+ }
+
+ void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
+
+ std::shared_ptr<ITelephony> telephony;
+};
+
+TEST_P(AudioCoreTelephony, GetSupportedAudioModes) {
+ if (telephony == nullptr) {
+ GTEST_SKIP() << "Telephony is not supported";
+ }
+ std::vector<AudioMode> modes1;
+ ASSERT_IS_OK(telephony->getSupportedAudioModes(&modes1));
+ const std::vector<AudioMode> kMandatoryModes = {AudioMode::NORMAL, AudioMode::RINGTONE,
+ AudioMode::IN_CALL,
+ AudioMode::IN_COMMUNICATION};
+ for (const auto mode : kMandatoryModes) {
+ EXPECT_NE(modes1.end(), std::find(modes1.begin(), modes1.end(), mode))
+ << "Mandatory mode not supported: " << toString(mode);
+ }
+ std::vector<AudioMode> modes2;
+ ASSERT_IS_OK(telephony->getSupportedAudioModes(&modes2));
+ ASSERT_EQ(modes1.size(), modes2.size())
+ << "Sizes of audio mode arrays do not match across consequent calls to "
+ << "getSupportedAudioModes";
+ std::sort(modes1.begin(), modes1.end());
+ std::sort(modes2.begin(), modes2.end());
+ EXPECT_EQ(modes1, modes2);
+};
+
+TEST_P(AudioCoreTelephony, SwitchAudioMode) {
+ if (telephony == nullptr) {
+ GTEST_SKIP() << "Telephony is not supported";
+ }
+ std::vector<AudioMode> supportedModes;
+ ASSERT_IS_OK(telephony->getSupportedAudioModes(&supportedModes));
+ std::set<AudioMode> unsupportedModes = {
+ // Start with all, remove supported ones
+ ::ndk::enum_range<AudioMode>().begin(), ::ndk::enum_range<AudioMode>().end()};
+ for (const auto mode : supportedModes) {
+ EXPECT_IS_OK(telephony->switchAudioMode(mode)) << toString(mode);
+ unsupportedModes.erase(mode);
+ }
+ for (const auto mode : unsupportedModes) {
+ EXPECT_STATUS(EX_UNSUPPORTED_OPERATION, telephony->switchAudioMode(mode)) << toString(mode);
+ }
+}
+
+class StreamLogicDriverInvalidCommand : public StreamLogicDriver {
+ public:
+ StreamLogicDriverInvalidCommand(const std::vector<StreamDescriptor::Command>& commands)
+ : mCommands(commands) {}
+
+ std::string getUnexpectedStatuses() {
+ // This method is intended to be called after the worker thread has joined,
+ // thus no extra synchronization is needed.
+ std::string s;
+ if (!mStatuses.empty()) {
+ s = std::string("Pairs of (command, actual status): ")
+ .append((android::internal::ToString(mStatuses)));
+ }
+ return s;
+ }
+
+ bool done() override { return mNextCommand >= mCommands.size(); }
+ StreamDescriptor::Command getNextCommand(int, int* actualSize) override {
+ if (actualSize != nullptr) *actualSize = 0;
+ return mCommands[mNextCommand++];
+ }
+ bool interceptRawReply(const StreamDescriptor::Reply& reply) override {
+ if (reply.status != STATUS_BAD_VALUE) {
+ std::string s = mCommands[mNextCommand - 1].toString();
+ s.append(", ").append(statusToString(reply.status));
+ mStatuses.push_back(std::move(s));
+ // If the HAL does not recognize the command as invalid,
+ // retrieve the data etc.
+ return reply.status != STATUS_OK;
+ }
+ return true;
+ }
+ bool processValidReply(const StreamDescriptor::Reply&) override { return true; }
+
+ private:
+ const std::vector<StreamDescriptor::Command> mCommands;
+ size_t mNextCommand = 0;
+ std::vector<std::string> mStatuses;
+};
+
template <typename Stream>
class AudioStream : public AudioCoreModule {
public:
@@ -1315,19 +1526,6 @@
EXPECT_NO_FATAL_FAILURE(OpenTwiceSamePortConfigImpl(portConfig.value()));
}
- void ReadOrWrite(bool useSetupSequence2, bool validateObservablePosition) {
- const auto allPortConfigs =
- moduleConfig->getPortConfigsForMixPorts(IOTraits<Stream>::is_input);
- if (allPortConfigs.empty()) {
- GTEST_SKIP() << "No mix ports have attached devices";
- }
- for (const auto& portConfig : allPortConfigs) {
- EXPECT_NO_FATAL_FAILURE(
- ReadOrWriteImpl(portConfig, useSetupSequence2, validateObservablePosition))
- << portConfig.toString();
- }
- }
-
void ResetPortConfigWithOpenStream() {
const auto portConfig = moduleConfig->getSingleConfigForMixPort(IOTraits<Stream>::is_input);
if (!portConfig.has_value()) {
@@ -1357,131 +1555,40 @@
<< stream1.getPortId();
}
- template <class Worker>
- void WaitForObservablePositionAdvance(Worker& worker) {
- static constexpr int kWriteDurationUs = 50 * 1000;
- static constexpr std::chrono::milliseconds kPositionChangeTimeout{10000};
- int64_t framesInitial;
- framesInitial = worker.getLastObservablePosition().frames;
- ASSERT_FALSE(worker.hasError());
- bool timedOut = false;
- int64_t frames = framesInitial;
- for (android::base::Timer elapsed;
- frames <= framesInitial && !worker.hasError() &&
- !(timedOut = (elapsed.duration() >= kPositionChangeTimeout));) {
- usleep(kWriteDurationUs);
- frames = worker.getLastObservablePosition().frames;
- }
- EXPECT_FALSE(timedOut);
- EXPECT_FALSE(worker.hasError()) << worker.getError();
- EXPECT_GT(frames, framesInitial);
- }
-
- void ReadOrWriteImpl(const AudioPortConfig& portConfig, bool useSetupSequence2,
- bool validateObservablePosition) {
- if (!useSetupSequence2) {
- ASSERT_NO_FATAL_FAILURE(
- ReadOrWriteSetupSequence1(portConfig, validateObservablePosition));
- } else {
- ASSERT_NO_FATAL_FAILURE(
- ReadOrWriteSetupSequence2(portConfig, validateObservablePosition));
- }
- }
-
- // Set up a patch first, then open a stream.
- void ReadOrWriteSetupSequence1(const AudioPortConfig& portConfig,
- bool validateObservablePosition) {
- auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
- IOTraits<Stream>::is_input, portConfig);
- ASSERT_FALSE(devicePorts.empty());
- auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
- WithAudioPatch patch(IOTraits<Stream>::is_input, portConfig, devicePortConfig);
- ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
-
- WithStream<Stream> stream(patch.getPortConfig(IOTraits<Stream>::is_input));
- ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
- typename IOTraits<Stream>::Worker worker(*stream.getContext());
-
- ASSERT_TRUE(worker.start());
- ASSERT_TRUE(worker.waitForAtLeastOneCycle());
- if (validateObservablePosition) {
- ASSERT_NO_FATAL_FAILURE(WaitForObservablePositionAdvance(worker));
- }
- }
-
- // Open a stream, then set up a patch for it.
- void ReadOrWriteSetupSequence2(const AudioPortConfig& portConfig,
- bool validateObservablePosition) {
- WithStream<Stream> stream(portConfig);
- ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
- typename IOTraits<Stream>::Worker worker(*stream.getContext());
-
- auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
- IOTraits<Stream>::is_input, portConfig);
- ASSERT_FALSE(devicePorts.empty());
- auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
- WithAudioPatch patch(IOTraits<Stream>::is_input, stream.getPortConfig(), devicePortConfig);
- ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
-
- ASSERT_TRUE(worker.start());
- ASSERT_TRUE(worker.waitForAtLeastOneCycle());
- if (validateObservablePosition) {
- ASSERT_NO_FATAL_FAILURE(WaitForObservablePositionAdvance(worker));
- }
- }
-
void SendInvalidCommandImpl(const AudioPortConfig& portConfig) {
- std::vector<StreamDescriptor::Command> commands(6);
- commands[0].code = -1;
- commands[1].code = StreamDescriptor::COMMAND_BURST - 1;
- commands[2].code = std::numeric_limits<int32_t>::min();
- commands[3].code = std::numeric_limits<int32_t>::max();
- commands[4].code = StreamDescriptor::COMMAND_BURST;
- commands[4].fmqByteCount = -1;
- commands[5].code = StreamDescriptor::COMMAND_BURST;
- commands[5].fmqByteCount = std::numeric_limits<int32_t>::min();
+ std::vector<StreamDescriptor::Command> commands = {
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::hal_reserved_exit>(
+ 0),
+ // TODO: For proper testing of input streams, need to put the stream into
+ // a state which accepts BURST commands.
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(-1),
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(
+ std::numeric_limits<int32_t>::min()),
+ };
WithStream<Stream> stream(portConfig);
ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
- StreamWorker<StreamInvalidCommandLogic> writer(*stream.getContext(), commands);
- ASSERT_TRUE(writer.start());
- writer.waitForAtLeastOneCycle();
- auto unexpectedStatuses = writer.getUnexpectedStatuses();
- EXPECT_EQ(0UL, unexpectedStatuses.size())
- << "Pairs of (command, actual status): "
- << android::internal::ToString(unexpectedStatuses);
+ StreamLogicDriverInvalidCommand driver(commands);
+ typename IOTraits<Stream>::Worker worker(*stream.getContext(), &driver);
+ ASSERT_TRUE(worker.start());
+ worker.join();
+ EXPECT_EQ("", driver.getUnexpectedStatuses());
}
};
using AudioStreamIn = AudioStream<IStreamIn>;
using AudioStreamOut = AudioStream<IStreamOut>;
-#define TEST_IO_STREAM(method_name) \
+#define TEST_IN_AND_OUT_STREAM(method_name) \
TEST_P(AudioStreamIn, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); } \
TEST_P(AudioStreamOut, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); }
-#define TEST_IO_STREAM_2(method_name, arg1, arg2) \
- TEST_P(AudioStreamIn, method_name##_##arg1##_##arg2) { \
- ASSERT_NO_FATAL_FAILURE(method_name(arg1, arg2)); \
- } \
- TEST_P(AudioStreamOut, method_name##_##arg1##_##arg2) { \
- ASSERT_NO_FATAL_FAILURE(method_name(arg1, arg2)); \
- }
-TEST_IO_STREAM(CloseTwice);
-TEST_IO_STREAM(OpenAllConfigs);
-TEST_IO_STREAM(OpenInvalidBufferSize);
-TEST_IO_STREAM(OpenInvalidDirection);
-TEST_IO_STREAM(OpenOverMaxCount);
-TEST_IO_STREAM(OpenTwiceSamePortConfig);
-// Use of constants makes comprehensible test names.
-constexpr bool SetupSequence1 = false;
-constexpr bool SetupSequence2 = true;
-constexpr bool SetupOnly = false;
-constexpr bool ValidateObservablePosition = true;
-TEST_IO_STREAM_2(ReadOrWrite, SetupSequence1, SetupOnly);
-TEST_IO_STREAM_2(ReadOrWrite, SetupSequence2, SetupOnly);
-TEST_IO_STREAM_2(ReadOrWrite, SetupSequence1, ValidateObservablePosition);
-TEST_IO_STREAM_2(ReadOrWrite, SetupSequence2, ValidateObservablePosition);
-TEST_IO_STREAM(ResetPortConfigWithOpenStream);
-TEST_IO_STREAM(SendInvalidCommand);
+TEST_IN_AND_OUT_STREAM(CloseTwice);
+TEST_IN_AND_OUT_STREAM(OpenAllConfigs);
+TEST_IN_AND_OUT_STREAM(OpenInvalidBufferSize);
+TEST_IN_AND_OUT_STREAM(OpenInvalidDirection);
+TEST_IN_AND_OUT_STREAM(OpenOverMaxCount);
+TEST_IN_AND_OUT_STREAM(OpenTwiceSamePortConfig);
+TEST_IN_AND_OUT_STREAM(ResetPortConfigWithOpenStream);
+TEST_IN_AND_OUT_STREAM(SendInvalidCommand);
TEST_P(AudioStreamOut, OpenTwicePrimary) {
const auto mixPorts = moduleConfig->getMixPorts(false);
@@ -1523,6 +1630,165 @@
<< "when no offload info is provided for a compressed offload mix port";
}
+using CommandAndState = std::pair<StreamDescriptor::Command, StreamDescriptor::State>;
+
+class StreamLogicDefaultDriver : public StreamLogicDriver {
+ public:
+ explicit StreamLogicDefaultDriver(const std::vector<CommandAndState>& commands)
+ : mCommands(commands) {}
+
+ // The three methods below is intended to be called after the worker
+ // thread has joined, thus no extra synchronization is needed.
+ bool hasObservablePositionIncrease() const { return mObservablePositionIncrease; }
+ bool hasRetrogradeObservablePosition() const { return mRetrogradeObservablePosition; }
+ std::string getUnexpectedStateTransition() const { return mUnexpectedTransition; }
+
+ bool done() override { return mNextCommand >= mCommands.size(); }
+ StreamDescriptor::Command getNextCommand(int maxDataSize, int* actualSize) override {
+ auto command = mCommands[mNextCommand++].first;
+ if (command.getTag() == StreamDescriptor::Command::Tag::burst) {
+ if (actualSize != nullptr) {
+ // In the output scenario, reduce slightly the fmqByteCount to verify
+ // that the HAL module always consumes all data from the MQ.
+ if (maxDataSize > 1) maxDataSize--;
+ *actualSize = maxDataSize;
+ }
+ command.set<StreamDescriptor::Command::Tag::burst>(maxDataSize);
+ } else {
+ if (actualSize != nullptr) *actualSize = 0;
+ }
+ return command;
+ }
+ bool interceptRawReply(const StreamDescriptor::Reply&) override { return false; }
+ bool processValidReply(const StreamDescriptor::Reply& reply) override {
+ if (mPreviousFrames.has_value()) {
+ if (reply.observable.frames > mPreviousFrames.value()) {
+ mObservablePositionIncrease = true;
+ } else if (reply.observable.frames < mPreviousFrames.value()) {
+ mRetrogradeObservablePosition = true;
+ }
+ }
+ mPreviousFrames = reply.observable.frames;
+
+ const auto& lastCommandState = mCommands[mNextCommand - 1];
+ if (lastCommandState.second != reply.state) {
+ std::string s = std::string("Unexpected transition from the state ")
+ .append(mPreviousState)
+ .append(" to ")
+ .append(toString(reply.state))
+ .append(" caused by the command ")
+ .append(lastCommandState.first.toString());
+ LOG(ERROR) << __func__ << ": " << s;
+ mUnexpectedTransition = std::move(s);
+ return false;
+ }
+ return true;
+ }
+
+ protected:
+ const std::vector<CommandAndState>& mCommands;
+ size_t mNextCommand = 0;
+ std::optional<int64_t> mPreviousFrames;
+ std::string mPreviousState = "<initial state>";
+ bool mObservablePositionIncrease = false;
+ bool mRetrogradeObservablePosition = false;
+ std::string mUnexpectedTransition;
+};
+
+using NamedCommandSequence = std::pair<std::string, std::vector<CommandAndState>>;
+enum { PARAM_MODULE_NAME, PARAM_CMD_SEQ, PARAM_SETUP_SEQ };
+using StreamIoTestParameters =
+ std::tuple<std::string /*moduleName*/, NamedCommandSequence, bool /*useSetupSequence2*/>;
+template <typename Stream>
+class AudioStreamIo : public AudioCoreModuleBase,
+ public testing::TestWithParam<StreamIoTestParameters> {
+ public:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(SetUpImpl(std::get<PARAM_MODULE_NAME>(GetParam())));
+ ASSERT_NO_FATAL_FAILURE(SetUpModuleConfig());
+ }
+
+ void Run() {
+ const auto allPortConfigs =
+ moduleConfig->getPortConfigsForMixPorts(IOTraits<Stream>::is_input);
+ if (allPortConfigs.empty()) {
+ GTEST_SKIP() << "No mix ports have attached devices";
+ }
+ for (const auto& portConfig : allPortConfigs) {
+ SCOPED_TRACE(portConfig.toString());
+ const auto& commandsAndStates = std::get<PARAM_CMD_SEQ>(GetParam()).second;
+ if (!std::get<PARAM_SETUP_SEQ>(GetParam())) {
+ ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq1(portConfig, commandsAndStates));
+ } else {
+ ASSERT_NO_FATAL_FAILURE(RunStreamIoCommandsImplSeq2(portConfig, commandsAndStates));
+ }
+ }
+ }
+
+ bool ValidateObservablePosition(const AudioPortConfig& /*portConfig*/) {
+ // May return false based on the portConfig, e.g. for telephony ports.
+ return true;
+ }
+
+ // Set up a patch first, then open a stream.
+ void RunStreamIoCommandsImplSeq1(const AudioPortConfig& portConfig,
+ const std::vector<CommandAndState>& commandsAndStates) {
+ auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
+ IOTraits<Stream>::is_input, portConfig);
+ ASSERT_FALSE(devicePorts.empty());
+ auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+ WithAudioPatch patch(IOTraits<Stream>::is_input, portConfig, devicePortConfig);
+ ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+
+ WithStream<Stream> stream(patch.getPortConfig(IOTraits<Stream>::is_input));
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ StreamLogicDefaultDriver driver(commandsAndStates);
+ typename IOTraits<Stream>::Worker worker(*stream.getContext(), &driver);
+
+ ASSERT_TRUE(worker.start());
+ worker.join();
+ EXPECT_FALSE(worker.hasError()) << worker.getError();
+ EXPECT_EQ("", driver.getUnexpectedStateTransition());
+ if (ValidateObservablePosition(portConfig)) {
+ EXPECT_TRUE(driver.hasObservablePositionIncrease());
+ EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
+ }
+ }
+
+ // Open a stream, then set up a patch for it.
+ void RunStreamIoCommandsImplSeq2(const AudioPortConfig& portConfig,
+ const std::vector<CommandAndState>& commandsAndStates) {
+ WithStream<Stream> stream(portConfig);
+ ASSERT_NO_FATAL_FAILURE(stream.SetUp(module.get(), kDefaultBufferSizeFrames));
+ StreamLogicDefaultDriver driver(commandsAndStates);
+ typename IOTraits<Stream>::Worker worker(*stream.getContext(), &driver);
+
+ auto devicePorts = moduleConfig->getAttachedDevicesPortsForMixPort(
+ IOTraits<Stream>::is_input, portConfig);
+ ASSERT_FALSE(devicePorts.empty());
+ auto devicePortConfig = moduleConfig->getSingleConfigForDevicePort(devicePorts[0]);
+ WithAudioPatch patch(IOTraits<Stream>::is_input, stream.getPortConfig(), devicePortConfig);
+ ASSERT_NO_FATAL_FAILURE(patch.SetUp(module.get()));
+
+ ASSERT_TRUE(worker.start());
+ worker.join();
+ EXPECT_FALSE(worker.hasError()) << worker.getError();
+ EXPECT_EQ("", driver.getUnexpectedStateTransition());
+ if (ValidateObservablePosition(portConfig)) {
+ EXPECT_TRUE(driver.hasObservablePositionIncrease());
+ EXPECT_FALSE(driver.hasRetrogradeObservablePosition());
+ }
+ }
+};
+using AudioStreamIoIn = AudioStreamIo<IStreamIn>;
+using AudioStreamIoOut = AudioStreamIo<IStreamOut>;
+
+#define TEST_IN_AND_OUT_STREAM_IO(method_name) \
+ TEST_P(AudioStreamIoIn, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); } \
+ TEST_P(AudioStreamIoOut, method_name) { ASSERT_NO_FATAL_FAILURE(method_name()); }
+
+TEST_IN_AND_OUT_STREAM_IO(Run);
+
// Tests specific to audio patches. The fixure class is named 'AudioModulePatch'
// to avoid clashing with 'AudioPatch' class.
class AudioModulePatch : public AudioCoreModule {
@@ -1696,6 +1962,10 @@
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreModule);
+INSTANTIATE_TEST_SUITE_P(AudioCoreTelephonyTest, AudioCoreTelephony,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+ android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreTelephony);
INSTANTIATE_TEST_SUITE_P(AudioStreamInTest, AudioStreamIn,
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
@@ -1704,6 +1974,117 @@
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamOut);
+
+static const StreamDescriptor::Command kStartCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::start>(Void{});
+static const StreamDescriptor::Command kBurstCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::burst>(0);
+static const StreamDescriptor::Command kDrainCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::drain>(Void{});
+static const StreamDescriptor::Command kStandbyCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::standby>(Void{});
+static const StreamDescriptor::Command kPauseCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::pause>(Void{});
+static const StreamDescriptor::Command kFlushCommand =
+ StreamDescriptor::Command::make<StreamDescriptor::Command::Tag::flush>(Void{});
+static const NamedCommandSequence kReadOrWriteSeq =
+ std::make_pair(std::string("ReadOrWrite"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE)});
+static const NamedCommandSequence kDrainInSeq =
+ std::make_pair(std::string("Drain"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kDrainCommand, StreamDescriptor::State::DRAINING),
+ std::make_pair(kStartCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kDrainCommand, StreamDescriptor::State::DRAINING),
+ // TODO: This will need to be changed once DRAIN starts taking time.
+ std::make_pair(kBurstCommand, StreamDescriptor::State::STANDBY)});
+static const NamedCommandSequence kDrainOutSeq =
+ std::make_pair(std::string("Drain"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ // TODO: This will need to be changed once DRAIN starts taking time.
+ std::make_pair(kDrainCommand, StreamDescriptor::State::IDLE)});
+// TODO: This will need to be changed once DRAIN starts taking time so we can pause it.
+static const NamedCommandSequence kDrainPauseOutSeq = std::make_pair(
+ std::string("DrainPause"),
+ std::vector<CommandAndState>{std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kDrainCommand, StreamDescriptor::State::IDLE)});
+static const NamedCommandSequence kStandbySeq =
+ std::make_pair(std::string("Standby"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kStandbyCommand, StreamDescriptor::State::STANDBY),
+ // Perform a read or write in order to advance observable position
+ // (this is verified by tests).
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE)});
+static const NamedCommandSequence kPauseInSeq =
+ std::make_pair(std::string("Pause"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kFlushCommand, StreamDescriptor::State::STANDBY)});
+static const NamedCommandSequence kPauseOutSeq =
+ std::make_pair(std::string("Pause"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kStartCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kStartCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED)});
+static const NamedCommandSequence kFlushInSeq =
+ std::make_pair(std::string("Flush"),
+ std::vector<CommandAndState>{
+ std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kFlushCommand, StreamDescriptor::State::STANDBY)});
+static const NamedCommandSequence kFlushOutSeq = std::make_pair(
+ std::string("Flush"),
+ std::vector<CommandAndState>{std::make_pair(kStartCommand, StreamDescriptor::State::IDLE),
+ std::make_pair(kBurstCommand, StreamDescriptor::State::ACTIVE),
+ std::make_pair(kPauseCommand, StreamDescriptor::State::PAUSED),
+ std::make_pair(kFlushCommand, StreamDescriptor::State::IDLE)});
+std::string GetStreamIoTestName(const testing::TestParamInfo<StreamIoTestParameters>& info) {
+ return android::PrintInstanceNameToString(
+ testing::TestParamInfo<std::string>{std::get<PARAM_MODULE_NAME>(info.param),
+ info.index})
+ .append("_")
+ .append(std::get<PARAM_CMD_SEQ>(info.param).first)
+ .append("_SetupSeq")
+ .append(std::get<PARAM_SETUP_SEQ>(info.param) ? "2" : "1");
+}
+INSTANTIATE_TEST_SUITE_P(
+ AudioStreamIoInTest, AudioStreamIoIn,
+ testing::Combine(testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+ testing::Values(kReadOrWriteSeq, kDrainInSeq, kStandbySeq, kPauseInSeq,
+ kFlushInSeq),
+ testing::Values(false, true)),
+ GetStreamIoTestName);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamIoIn);
+INSTANTIATE_TEST_SUITE_P(
+ AudioStreamIoOutTest, AudioStreamIoOut,
+ testing::Combine(testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+ testing::Values(kReadOrWriteSeq, kDrainOutSeq, kDrainPauseOutSeq,
+ kStandbySeq, kPauseOutSeq, kFlushOutSeq),
+ testing::Values(false, true)),
+ GetStreamIoTestName);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioStreamIoOut);
+
INSTANTIATE_TEST_SUITE_P(AudioPatchTest, AudioModulePatch,
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
diff --git a/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
new file mode 100644
index 0000000..8ae963e
--- /dev/null
+++ b/audio/aidl/vts/VtsHalAudioEffectFactoryTargetTest.cpp
@@ -0,0 +1,289 @@
+/*
+ * 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 <memory>
+#include <set>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "VtsHalAudioEffectFactory"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectFactoryHelper.h"
+#include "TestUtils.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kEffectNullUuid;
+using aidl::android::hardware::audio::effect::kEffectZeroUuid;
+using aidl::android::hardware::audio::effect::Processing;
+using aidl::android::media::audio::common::AudioSource;
+using aidl::android::media::audio::common::AudioStreamType;
+using aidl::android::media::audio::common::AudioUuid;
+
+/// Effect factory testing.
+class EffectFactoryTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ mFactoryHelper = std::make_unique<EffectFactoryHelper>(GetParam());
+ connectAndGetFactory();
+ }
+
+ void TearDown() override {
+ for (auto& effect : mEffects) {
+ const auto status = mEffectFactory->destroyEffect(effect);
+ EXPECT_STATUS(EX_NONE, status);
+ }
+ }
+
+ std::unique_ptr<EffectFactoryHelper> mFactoryHelper;
+ std::shared_ptr<IFactory> mEffectFactory;
+ std::vector<std::shared_ptr<IEffect>> mEffects;
+ const Descriptor::Identity kNullDesc = {.uuid = kEffectNullUuid};
+ const Descriptor::Identity kZeroDesc = {.uuid = kEffectZeroUuid};
+
+ template <typename Functor>
+ void ForEachId(const std::vector<Descriptor::Identity> ids, Functor functor) {
+ for (const auto& id : ids) {
+ SCOPED_TRACE(id.toString());
+ functor(id);
+ }
+ }
+ template <typename Functor>
+ void ForEachEffect(std::vector<std::shared_ptr<IEffect>> effects, Functor functor) {
+ for (auto& effect : effects) {
+ functor(effect);
+ }
+ }
+
+ std::vector<std::shared_ptr<IEffect>> createWithIds(
+ const std::vector<Descriptor::Identity> ids,
+ const binder_status_t expectStatus = EX_NONE) {
+ std::vector<std::shared_ptr<IEffect>> effects;
+ for (const auto& id : ids) {
+ std::shared_ptr<IEffect> effect;
+ EXPECT_STATUS(expectStatus, mEffectFactory->createEffect(id.uuid, &effect));
+ if (expectStatus == EX_NONE) {
+ EXPECT_NE(effect, nullptr) << " null effect with uuid: " << id.uuid.toString();
+ effects.push_back(std::move(effect));
+ }
+ }
+ return effects;
+ }
+ void destroyEffects(std::vector<std::shared_ptr<IEffect>> effects,
+ const binder_status_t expectStatus = EX_NONE) {
+ for (const auto& effect : effects) {
+ EXPECT_STATUS(expectStatus, mEffectFactory->destroyEffect(effect));
+ }
+ }
+ void creatAndDestroyIds(const std::vector<Descriptor::Identity> ids) {
+ for (const auto& id : ids) {
+ auto effects = createWithIds({id});
+ ASSERT_NO_FATAL_FAILURE(destroyEffects(effects));
+ }
+ }
+ void connectAndGetFactory() {
+ ASSERT_NO_FATAL_FAILURE(mFactoryHelper->ConnectToFactoryService());
+ mEffectFactory = mFactoryHelper->GetFactory();
+ ASSERT_NE(mEffectFactory, nullptr);
+ }
+};
+
+TEST_P(EffectFactoryTest, SetupAndTearDown) {
+ // Intentionally empty test body.
+}
+
+TEST_P(EffectFactoryTest, CanBeRestarted) {
+ ASSERT_NO_FATAL_FAILURE(mFactoryHelper->RestartFactoryService());
+}
+
+/**
+ * @brief Check at least support list of effect must be supported by aosp:
+ * https://developer.android.com/reference/android/media/audiofx/AudioEffect
+ */
+TEST_P(EffectFactoryTest, ExpectAllAospEffectTypes) {
+ std::vector<Descriptor::Identity> ids;
+ std::set<AudioUuid> typeUuidSet(
+ {aidl::android::hardware::audio::effect::kBassBoostTypeUUID,
+ aidl::android::hardware::audio::effect::kEqualizerTypeUUID,
+ aidl::android::hardware::audio::effect::kEnvReverbTypeUUID,
+ aidl::android::hardware::audio::effect::kPresetReverbTypeUUID,
+ aidl::android::hardware::audio::effect::kDynamicsProcessingTypeUUID,
+ aidl::android::hardware::audio::effect::kHapticGeneratorTypeUUID,
+ aidl::android::hardware::audio::effect::kVirtualizerTypeUUID});
+
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
+ EXPECT_TRUE(ids.size() >= typeUuidSet.size());
+ for (const auto& id : ids) {
+ typeUuidSet.erase(id.type);
+ }
+ std::string msg = " missing type UUID:\n";
+ for (const auto& uuid : typeUuidSet) {
+ msg += (uuid.toString() + "\n");
+ }
+ SCOPED_TRACE(msg);
+ EXPECT_EQ(0UL, typeUuidSet.size());
+}
+
+TEST_P(EffectFactoryTest, QueryNullTypeUuid) {
+ std::vector<Descriptor::Identity> ids;
+ EXPECT_IS_OK(mEffectFactory->queryEffects(kEffectNullUuid, std::nullopt, std::nullopt, &ids));
+ EXPECT_EQ(ids.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, QueriedNullImplUuid) {
+ std::vector<Descriptor::Identity> ids;
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, kEffectNullUuid, std::nullopt, &ids));
+ EXPECT_EQ(ids.size(), 0UL);
+}
+
+TEST_P(EffectFactoryTest, QueriedNullProxyUuid) {
+ std::vector<Descriptor::Identity> ids;
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, kEffectNullUuid, &ids));
+ EXPECT_EQ(ids.size(), 0UL);
+}
+
+// create all effects, and then destroy them all together
+TEST_P(EffectFactoryTest, CreateAndDestroyEffects) {
+ std::vector<Descriptor::Identity> ids;
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
+ EXPECT_NE(ids.size(), 0UL);
+
+ std::vector<std::shared_ptr<IEffect>> effects;
+ effects = createWithIds(ids);
+ EXPECT_EQ(ids.size(), effects.size());
+ destroyEffects(effects);
+}
+
+TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
+ std::vector<Descriptor::Identity> ids;
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
+ EXPECT_NE(ids.size(), 0UL);
+
+ std::vector<std::shared_ptr<IEffect>> effects = createWithIds(ids);
+ EXPECT_EQ(ids.size(), effects.size());
+ std::vector<std::shared_ptr<IEffect>> effects2 = createWithIds(ids);
+ EXPECT_EQ(ids.size(), effects2.size());
+ std::vector<std::shared_ptr<IEffect>> effects3 = createWithIds(ids);
+ EXPECT_EQ(ids.size(), effects3.size());
+
+ destroyEffects(effects);
+ destroyEffects(effects2);
+ destroyEffects(effects3);
+}
+
+// create and destroy each effect one by one
+TEST_P(EffectFactoryTest, CreateAndDestroyEffectsOneByOne) {
+ std::vector<Descriptor::Identity> ids;
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
+ EXPECT_NE(ids.size(), 0UL);
+
+ creatAndDestroyIds(ids);
+}
+
+// for each effect: repeat 3 times create and destroy
+TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
+ std::vector<Descriptor::Identity> ids;
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
+ EXPECT_NE(ids.size(), 0UL);
+
+ creatAndDestroyIds(ids);
+ creatAndDestroyIds(ids);
+ creatAndDestroyIds(ids);
+}
+
+// Expect EX_ILLEGAL_ARGUMENT when create with invalid UUID.
+TEST_P(EffectFactoryTest, CreateWithInvalidUuid) {
+ std::vector<Descriptor::Identity> ids = {kNullDesc, kZeroDesc};
+ auto effects = createWithIds(ids, EX_ILLEGAL_ARGUMENT);
+ EXPECT_EQ(effects.size(), 0UL);
+}
+
+// Expect EX_ILLEGAL_ARGUMENT when destroy null interface.
+TEST_P(EffectFactoryTest, DestroyWithInvalidInterface) {
+ std::shared_ptr<IEffect> spDummyEffect(nullptr);
+ destroyEffects({spDummyEffect}, EX_ILLEGAL_ARGUMENT);
+}
+
+// Same descriptor ID should work after service restart.
+TEST_P(EffectFactoryTest, CreateDestroyWithRestart) {
+ std::vector<Descriptor::Identity> ids;
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
+ EXPECT_NE(ids.size(), 0UL);
+ creatAndDestroyIds(ids);
+
+ mFactoryHelper->RestartFactoryService();
+
+ connectAndGetFactory();
+ creatAndDestroyIds(ids);
+}
+
+// Effect handle invalid after restart.
+TEST_P(EffectFactoryTest, EffectInvalidAfterRestart) {
+ std::vector<Descriptor::Identity> ids;
+ EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, std::nullopt, &ids));
+ EXPECT_NE(ids.size(), 0UL);
+ std::vector<std::shared_ptr<IEffect>> effects = createWithIds(ids);
+
+ ASSERT_NO_FATAL_FAILURE(mFactoryHelper->RestartFactoryService());
+
+ connectAndGetFactory();
+ destroyEffects(effects, EX_ILLEGAL_ARGUMENT);
+}
+
+// expect no error with the queryProcessing interface, but don't check number of processing
+TEST_P(EffectFactoryTest, QueryProcess) {
+ std::vector<Processing> processing;
+ EXPECT_IS_OK(mEffectFactory->queryProcessing(std::nullopt, &processing));
+
+ Processing::Type streamType =
+ Processing::Type::make<Processing::Type::streamType>(AudioStreamType::SYSTEM);
+ std::vector<Processing> processingFilteredByStream;
+ EXPECT_IS_OK(mEffectFactory->queryProcessing(streamType, &processingFilteredByStream));
+
+ Processing::Type source =
+ Processing::Type::make<Processing::Type::source>(AudioSource::DEFAULT);
+ std::vector<Processing> processingFilteredBySource;
+ EXPECT_IS_OK(mEffectFactory->queryProcessing(source, &processingFilteredBySource));
+
+ EXPECT_TRUE(processing.size() >= processingFilteredByStream.size());
+ EXPECT_TRUE(processing.size() >= processingFilteredBySource.size());
+}
+
+INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
+ android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactoryTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
\ No newline at end of file
diff --git a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
index 8b5eb13..8212149 100644
--- a/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioEffectTargetTest.cpp
@@ -14,303 +14,763 @@
* limitations under the License.
*/
+#define LOG_TAG "VtsHalAudioEffectTargetTest"
+
+#include <chrono>
#include <memory>
#include <string>
-#include <unordered_map>
-#include <unordered_set>
#include <vector>
-#define LOG_TAG "VtsHalAudioEffect"
-
+#include <Utils.h>
#include <aidl/Gtest.h>
#include <aidl/Vintf.h>
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
#include <android-base/logging.h>
-#include <android-base/properties.h>
#include <android/binder_interface_utils.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
-
-#include <aidl/android/hardware/audio/effect/IFactory.h>
+#include <fmq/AidlMessageQueue.h>
#include "AudioHalBinderServiceUtil.h"
+#include "EffectFactoryHelper.h"
+#include "EffectHelper.h"
#include "TestUtils.h"
using namespace android;
using ndk::ScopedAStatus;
+using aidl::android::hardware::audio::effect::CommandId;
using aidl::android::hardware::audio::effect::Descriptor;
using aidl::android::hardware::audio::effect::IEffect;
using aidl::android::hardware::audio::effect::IFactory;
-using aidl::android::media::audio::common::AudioUuid;
+using aidl::android::hardware::audio::effect::Parameter;
+using aidl::android::hardware::audio::effect::State;
-class EffectFactoryHelper {
+enum ParamName { PARAM_INSTANCE_NAME };
+using EffectTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>>;
+
+class AudioEffectTest : public testing::TestWithParam<EffectTestParam>, public EffectHelper {
public:
- explicit EffectFactoryHelper(const std::string& name) : mServiceName(name) {}
+ AudioEffectTest() { std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam()); }
- void ConnectToFactoryService() {
- mEffectFactory = IFactory::fromBinder(binderUtil.connectToService(mServiceName));
- ASSERT_NE(mEffectFactory, nullptr);
- }
+ void SetUp() override {}
+ void TearDown() override {}
- void RestartFactoryService() {
- ASSERT_NE(mEffectFactory, nullptr);
- mEffectFactory = IFactory::fromBinder(binderUtil.restartService());
- ASSERT_NE(mEffectFactory, nullptr);
- }
-
- void QueryAllEffects() {
- EXPECT_NE(mEffectFactory, nullptr);
- EXPECT_IS_OK(mEffectFactory->queryEffects(std::nullopt, std::nullopt, &mCompleteIds));
- }
-
- void QueryEffects(const std::optional<AudioUuid>& in_type,
- const std::optional<AudioUuid>& in_instance,
- std::vector<Descriptor::Identity>* _aidl_return) {
- EXPECT_NE(mEffectFactory, nullptr);
- EXPECT_IS_OK(mEffectFactory->queryEffects(in_type, in_instance, _aidl_return));
- mIds = *_aidl_return;
- }
-
- void CreateEffects() {
- EXPECT_NE(mEffectFactory, nullptr);
- for (const auto& id : mIds) {
- std::shared_ptr<IEffect> effect;
- EXPECT_IS_OK(mEffectFactory->createEffect(id.uuid, &effect));
- EXPECT_NE(effect, nullptr) << id.toString();
- mEffectIdMap[effect] = id;
- }
- }
-
- void DestroyEffects() {
- EXPECT_NE(mEffectFactory, nullptr);
- for (const auto& it : mEffectIdMap) {
- EXPECT_IS_OK(mEffectFactory->destroyEffect(it.first));
- }
- mEffectIdMap.clear();
- }
-
- std::shared_ptr<IFactory> GetFactory() { return mEffectFactory; }
- const std::vector<Descriptor::Identity>& GetEffectIds() { return mIds; }
- const std::vector<Descriptor::Identity>& GetCompleteEffectIdList() { return mCompleteIds; }
- const std::unordered_map<std::shared_ptr<IEffect>, Descriptor::Identity>& GetEffectMap() {
- return mEffectIdMap;
- }
-
- private:
- std::shared_ptr<IFactory> mEffectFactory;
- std::string mServiceName;
- AudioHalBinderServiceUtil binderUtil;
- std::vector<Descriptor::Identity> mIds;
- std::vector<Descriptor::Identity> mCompleteIds;
- std::unordered_map<std::shared_ptr<IEffect>, Descriptor::Identity> mEffectIdMap;
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ Descriptor::Identity mIdentity;
};
-/// Effect factory testing.
-class EffectFactoryTest : public testing::TestWithParam<std::string> {
- public:
- void SetUp() override { ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService()); }
-
- void TearDown() override { mFactory.DestroyEffects(); }
-
- EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
-
- // TODO: these UUID can get from config file
- // ec7178ec-e5e1-4432-a3f4-4657e6795210
- const AudioUuid nullUuid = {static_cast<int32_t>(0xec7178ec),
- 0xe5e1,
- 0x4432,
- 0xa3f4,
- {0x46, 0x57, 0xe6, 0x79, 0x52, 0x10}};
- const AudioUuid zeroUuid = {
- static_cast<int32_t>(0x0), 0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0}};
-};
-
-TEST_P(EffectFactoryTest, SetupAndTearDown) {
+TEST_P(AudioEffectTest, SetupAndTearDown) {
// Intentionally empty test body.
}
-TEST_P(EffectFactoryTest, CanBeRestarted) {
- ASSERT_NO_FATAL_FAILURE(mFactory.RestartFactoryService());
+TEST_P(AudioEffectTest, CreateAndDestroy) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-TEST_P(EffectFactoryTest, QueriedDescriptorList) {
- std::vector<Descriptor::Identity> descriptors;
- mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
- EXPECT_NE(descriptors.size(), 0UL);
+TEST_P(AudioEffectTest, OpenAndClose) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-TEST_P(EffectFactoryTest, DescriptorUUIDNotNull) {
- std::vector<Descriptor::Identity> descriptors;
- mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
- // TODO: Factory eventually need to return the full list of MUST supported AOSP effects.
- for (auto& desc : descriptors) {
- EXPECT_NE(desc.type, zeroUuid);
- EXPECT_NE(desc.uuid, zeroUuid);
- }
+TEST_P(AudioEffectTest, CloseUnopenedEffect) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-TEST_P(EffectFactoryTest, QueriedDescriptorNotExistType) {
- std::vector<Descriptor::Identity> descriptors;
- mFactory.QueryEffects(nullUuid, std::nullopt, &descriptors);
- EXPECT_EQ(descriptors.size(), 0UL);
+TEST_P(AudioEffectTest, DoubleOpenAndClose) {
+ std::shared_ptr<IEffect> effect1, effect2;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect1));
+ ASSERT_NO_FATAL_FAILURE(open(effect2, 1 /* session */));
+ ASSERT_NO_FATAL_FAILURE(close(effect1));
+ ASSERT_NO_FATAL_FAILURE(close(effect2));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect1));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect2));
}
-TEST_P(EffectFactoryTest, QueriedDescriptorNotExistInstance) {
- std::vector<Descriptor::Identity> descriptors;
- mFactory.QueryEffects(std::nullopt, nullUuid, &descriptors);
- EXPECT_EQ(descriptors.size(), 0UL);
+TEST_P(AudioEffectTest, TripleOpenAndClose) {
+ std::shared_ptr<IEffect> effect1, effect2, effect3;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect3, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect1));
+ ASSERT_NO_FATAL_FAILURE(open(effect2, 1 /* session */));
+ ASSERT_NO_FATAL_FAILURE(open(effect3, 2 /* session */));
+ ASSERT_NO_FATAL_FAILURE(close(effect1));
+ ASSERT_NO_FATAL_FAILURE(close(effect2));
+ ASSERT_NO_FATAL_FAILURE(close(effect3));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect1));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect2));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect3));
}
-TEST_P(EffectFactoryTest, CreateAndDestroyRepeat) {
- std::vector<Descriptor::Identity> descriptors;
- mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
- auto numIds = mFactory.GetEffectIds().size();
- EXPECT_NE(numIds, 0UL);
-
- EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
- mFactory.CreateEffects();
- EXPECT_EQ(mFactory.GetEffectMap().size(), numIds);
- mFactory.DestroyEffects();
- EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
-
- // Create and destroy again
- mFactory.CreateEffects();
- EXPECT_EQ(mFactory.GetEffectMap().size(), numIds);
- mFactory.DestroyEffects();
- EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
+TEST_P(AudioEffectTest, GetDescritorBeforeOpen) {
+ std::shared_ptr<IEffect> effect;
+ Descriptor desc;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, desc));
+ EXPECT_EQ(mIdentity.toString(), desc.common.id.toString());
+ EXPECT_NE("", desc.common.name);
+ EXPECT_NE("", desc.common.implementor);
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-TEST_P(EffectFactoryTest, CreateMultipleInstanceOfSameEffect) {
- std::vector<Descriptor::Identity> descriptors;
- mFactory.QueryEffects(std::nullopt, std::nullopt, &descriptors);
- auto numIds = mFactory.GetEffectIds().size();
- EXPECT_NE(numIds, 0UL);
-
- EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
- mFactory.CreateEffects();
- EXPECT_EQ(mFactory.GetEffectMap().size(), numIds);
- // Create effect instances of same implementation
- mFactory.CreateEffects();
- EXPECT_EQ(mFactory.GetEffectMap().size(), 2 * numIds);
-
- mFactory.CreateEffects();
- EXPECT_EQ(mFactory.GetEffectMap().size(), 3 * numIds);
-
- mFactory.DestroyEffects();
- EXPECT_EQ(mFactory.GetEffectMap().size(), 0UL);
+TEST_P(AudioEffectTest, GetDescritorAfterOpen) {
+ std::shared_ptr<IEffect> effect;
+ Descriptor beforeOpen, afterOpen, afterClose;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, beforeOpen));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, afterOpen));
+ EXPECT_EQ(beforeOpen.toString(), afterOpen.toString()) << "\n"
+ << beforeOpen.toString() << "\n"
+ << afterOpen.toString();
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, afterClose));
+ EXPECT_EQ(beforeOpen.toString(), afterClose.toString()) << "\n"
+ << beforeOpen.toString() << "\n"
+ << afterClose.toString();
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-INSTANTIATE_TEST_SUITE_P(EffectFactoryTest, EffectFactoryTest,
- testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
- android::PrintInstanceNameToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EffectFactoryTest);
+TEST_P(AudioEffectTest, DescriptorExistAndUnique) {
+ std::shared_ptr<IEffect> effect;
+ Descriptor desc;
-/// Effect testing.
-class AudioEffect : public testing::TestWithParam<std::string> {
- public:
- void SetUp() override {
- ASSERT_NO_FATAL_FAILURE(mFactory.ConnectToFactoryService());
- ASSERT_NO_FATAL_FAILURE(mFactory.CreateEffects());
+ auto descList = EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor);
+ std::set<Descriptor::Identity> idSet;
+ for (const auto& it : descList) {
+ auto& id = it.second;
+ EXPECT_EQ(0ul, idSet.count(id));
+ idSet.insert(id);
}
- void TearDown() override {
- CloseEffects();
- ASSERT_NO_FATAL_FAILURE(mFactory.DestroyEffects());
- }
-
- void OpenEffects() {
- auto open = [](const std::shared_ptr<IEffect>& effect) { EXPECT_IS_OK(effect->open()); };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(open));
- }
-
- void CloseEffects() {
- auto close = [](const std::shared_ptr<IEffect>& effect) { EXPECT_IS_OK(effect->close()); };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(close));
- }
-
- void GetEffectDescriptors() {
- auto get = [](const std::shared_ptr<IEffect>& effect) {
- Descriptor desc;
- EXPECT_IS_OK(effect->getDescriptor(&desc));
- };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(get));
- }
-
- template <typename Functor>
- void ForEachEffect(Functor functor) {
- auto effectMap = mFactory.GetEffectMap();
- for (const auto& it : effectMap) {
- SCOPED_TRACE(it.second.toString());
- functor(it.first);
- }
- }
-
- EffectFactoryHelper mFactory = EffectFactoryHelper(GetParam());
-};
-
-TEST_P(AudioEffect, OpenEffectTest) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(getDescriptor(effect, desc));
+ EXPECT_EQ(1ul, idSet.count(desc.common.id));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-TEST_P(AudioEffect, OpenAndCloseEffect) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+/// State testing.
+// An effect instance is in INIT state by default after it was created.
+TEST_P(AudioEffectTest, InitStateAfterCreation) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-TEST_P(AudioEffect, CloseUnopenedEffectTest) {
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+// An effect instance transfer to IDLE state after IEffect.ASSERT_NO_FATAL_FAILURE(open().
+TEST_P(AudioEffectTest, IdleStateAfterOpen) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-TEST_P(AudioEffect, DoubleOpenCloseEffects) {
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
-
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
-
- EXPECT_NO_FATAL_FAILURE(OpenEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
- EXPECT_NO_FATAL_FAILURE(CloseEffects());
+// An effect instance is in PROCESSING state after it receive an START command.
+TEST_P(AudioEffectTest, ProcessingStateAfterStart) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-TEST_P(AudioEffect, GetDescriptors) {
- EXPECT_NO_FATAL_FAILURE(GetEffectDescriptors());
+// An effect instance transfer to IDLE state after Command.Id.STOP in PROCESSING state.
+TEST_P(AudioEffectTest, IdleStateAfterStop) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-TEST_P(AudioEffect, DescriptorIdExistAndUnique) {
- auto checker = [&](const std::shared_ptr<IEffect>& effect) {
- Descriptor desc;
- std::vector<Descriptor::Identity> idList;
- EXPECT_IS_OK(effect->getDescriptor(&desc));
- mFactory.QueryEffects(desc.common.id.type, desc.common.id.uuid, &idList);
- EXPECT_EQ(idList.size(), 1UL);
- };
- EXPECT_NO_FATAL_FAILURE(ForEachEffect(checker));
-
- // Check unique with a set
- auto stringHash = [](const Descriptor::Identity& id) {
- return std::hash<std::string>()(id.toString());
- };
- auto vec = mFactory.GetCompleteEffectIdList();
- std::unordered_set<Descriptor::Identity, decltype(stringHash)> idSet(0, stringHash);
- for (auto it : vec) {
- EXPECT_EQ(idSet.count(it), 0UL);
- idSet.insert(it);
- }
+// An effect instance transfer to IDLE state after Command.Id.RESET in PROCESSING state.
+TEST_P(AudioEffectTest, IdleStateAfterReset) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
}
-INSTANTIATE_TEST_SUITE_P(AudioEffectTest, AudioEffect,
- testing::ValuesIn(android::getAidlHalInstanceNames(IFactory::descriptor)),
- android::PrintInstanceNameToString);
-GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffect);
+// An effect instance transfer to INIT after IEffect.ASSERT_NO_FATAL_FAILURE(close().
+TEST_P(AudioEffectTest, InitStateAfterClose) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// An effect instance shouldn't accept any command before open.
+TEST_P(AudioEffectTest, NoCommandAcceptedBeforeOpen) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET, EX_ILLEGAL_STATE));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// No-op when receive STOP command in IDLE state.
+TEST_P(AudioEffectTest, StopCommandInIdleStateNoOp) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// No-op when receive RESET command in IDLE state.
+TEST_P(AudioEffectTest, ResetCommandInIdleStateNoOp) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Repeat START and STOP command.
+TEST_P(AudioEffectTest, RepeatStartAndStop) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Repeat START and RESET command.
+TEST_P(AudioEffectTest, RepeatStartAndReset) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Try to close an effect instance at PROCESSING state.
+TEST_P(AudioEffectTest, CloseProcessingStateEffects) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+
+ ASSERT_NO_FATAL_FAILURE(close(effect, EX_ILLEGAL_STATE));
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+TEST_P(AudioEffectTest, DestroyOpenEffects) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect, EX_ILLEGAL_STATE));
+}
+
+// Expect EX_ILLEGAL_STATE if the effect instance is not in a proper state to be destroyed.
+TEST_P(AudioEffectTest, DestroyProcessingEffects) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect, EX_ILLEGAL_STATE));
+}
+
+TEST_P(AudioEffectTest, NormalSequenceStates) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::INIT));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+/// Parameter testing.
+// Verify parameters pass in open can be successfully get.
+TEST_P(AudioEffectTest, VerifyCommonParametersAfterOpen) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+
+ Parameter::Common common = EffectHelper::createParamCommon();
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+
+ Parameter get = Parameter(), expect = Parameter();
+ expect.set<Parameter::common>(common);
+ Parameter::Id id;
+ id.set<Parameter::Id::commonTag>(Parameter::common);
+ EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_EQ(expect, get) << expect.toString() << " vs " << get.toString();
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Verify parameters pass in set can be successfully get.
+TEST_P(AudioEffectTest, SetAndGetCommonParameter) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
+ Parameter get = Parameter(), set = Parameter();
+ set.set<Parameter::common>(common);
+ EXPECT_IS_OK(effect->setParameter(set));
+
+ Parameter::Id id;
+ id.set<Parameter::Id::commonTag>(Parameter::common);
+ EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Verify parameters set and get in PROCESSING state.
+TEST_P(AudioEffectTest, SetAndGetParameterInProcessing) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
+ Parameter get = Parameter(), set = Parameter();
+ set.set<Parameter::common>(common);
+ EXPECT_IS_OK(effect->setParameter(set));
+
+ Parameter::Id id;
+ id.set<Parameter::Id::commonTag>(Parameter::common);
+ EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Verify parameters set and get in IDLE state.
+TEST_P(AudioEffectTest, SetAndGetParameterInIdle) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
+ Parameter get = Parameter(), set = Parameter();
+ set.set<Parameter::common>(common);
+ EXPECT_IS_OK(effect->setParameter(set));
+
+ Parameter::Id id;
+ id.set<Parameter::Id::commonTag>(Parameter::common);
+ EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Verify Parameters kept after stop.
+TEST_P(AudioEffectTest, SetAndGetParameterAfterStop) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
+ Parameter get = Parameter(), set = Parameter();
+ set.set<Parameter::common>(common);
+ EXPECT_IS_OK(effect->setParameter(set));
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ Parameter::Id id;
+ id.set<Parameter::Id::commonTag>(Parameter::common);
+ EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Verify Parameters kept after reset.
+TEST_P(AudioEffectTest, SetAndGetParameterAfterReset) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(open(effect));
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */);
+ Parameter get = Parameter(), set = Parameter();
+ set.set<Parameter::common>(common);
+ EXPECT_IS_OK(effect->setParameter(set));
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::RESET));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ Parameter::Id id;
+ id.set<Parameter::Id::commonTag>(Parameter::common);
+ EXPECT_IS_OK(effect->getParameter(id, &get));
+ EXPECT_EQ(set, get) << set.toString() << " vs " << get.toString();
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+/// Data processing test
+// Send data to effects and expect it to be consumed by checking statusMQ.
+TEST_P(AudioEffectTest, ConsumeDataInProcessingState) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+
+ std::vector<float> buffer;
+ EffectHelper::allocateInputData(common, inputMQ, buffer);
+ EffectHelper::writeToFmq(inputMQ, buffer);
+ EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Send data to effects and expect it to be consumed after effect restart.
+TEST_P(AudioEffectTest, ConsumeDataAfterRestart) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+
+ std::vector<float> buffer;
+ EffectHelper::allocateInputData(common, inputMQ, buffer);
+ EffectHelper::writeToFmq(inputMQ, buffer);
+ EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Send data to IDLE effects and expect it to be consumed after effect start.
+TEST_P(AudioEffectTest, SendDataAtIdleAndConsumeDataInProcessing) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+
+ std::vector<float> buffer;
+ EffectHelper::allocateInputData(common, inputMQ, buffer);
+ EffectHelper::writeToFmq(inputMQ, buffer);
+ EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+
+ EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Send data multiple times.
+TEST_P(AudioEffectTest, ProcessDataMultipleTimes) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+
+ std::vector<float> buffer;
+ EffectHelper::allocateInputData(common, inputMQ, buffer);
+ EffectHelper::writeToFmq(inputMQ, buffer);
+ EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+
+ EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
+ // expect no status and data after consume
+ EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
+
+ EffectHelper::writeToFmq(inputMQ, buffer);
+ EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
+ // expect no status and data after consume
+ EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Send data to IDLE state effects and expect it not be consumed.
+TEST_P(AudioEffectTest, NotConsumeDataInIdleState) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ std::vector<float> buffer;
+ EffectHelper::allocateInputData(common, inputMQ, buffer);
+ EffectHelper::writeToFmq(inputMQ, buffer);
+ EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::PROCESSING));
+ EffectHelper::readFromFmq(statusMQ, 1, outputMQ, buffer.size(), buffer);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect, State::IDLE));
+
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Send data to closed effects and expect it not be consumed.
+TEST_P(AudioEffectTest, NotConsumeDataByClosedEffect) {
+ std::shared_ptr<IEffect> effect;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect, mIdentity));
+
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(effect, common, std::nullopt /* specific */, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(close(effect));
+
+ auto statusMQ = std::make_unique<EffectHelper::StatusMQ>(ret.statusMQ);
+ auto inputMQ = std::make_unique<EffectHelper::DataMQ>(ret.inputDataMQ);
+ auto outputMQ = std::make_unique<EffectHelper::DataMQ>(ret.outputDataMQ);
+
+ std::vector<float> buffer;
+ EffectHelper::allocateInputData(common, inputMQ, buffer);
+ EffectHelper::writeToFmq(inputMQ, buffer);
+ EffectHelper::readFromFmq(statusMQ, 0, outputMQ, 0, buffer);
+
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect));
+}
+
+// Send data to multiple effects.
+TEST_P(AudioEffectTest, ConsumeDataMultipleEffects) {
+ std::shared_ptr<IEffect> effect1, effect2;
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect1, mIdentity));
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, effect2, mIdentity));
+
+ Parameter::Common common1 = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ Parameter::Common common2 = EffectHelper::createParamCommon(
+ 1 /* session */, 1 /* ioHandle */, 48000 /* iSampleRate */, 48000 /* oSampleRate */,
+ 2 * kInputFrameCount /* iFrameCount */, 2 * kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret1, ret2;
+ ASSERT_NO_FATAL_FAILURE(open(effect1, common1, std::nullopt /* specific */, &ret1, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(effect2, common2, std::nullopt /* specific */, &ret2, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(command(effect1, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect1, State::PROCESSING));
+ ASSERT_NO_FATAL_FAILURE(command(effect2, CommandId::START));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect2, State::PROCESSING));
+
+ auto statusMQ1 = std::make_unique<EffectHelper::StatusMQ>(ret1.statusMQ);
+ auto inputMQ1 = std::make_unique<EffectHelper::DataMQ>(ret1.inputDataMQ);
+ auto outputMQ1 = std::make_unique<EffectHelper::DataMQ>(ret1.outputDataMQ);
+
+ std::vector<float> buffer1, buffer2;
+ EffectHelper::allocateInputData(common1, inputMQ1, buffer1);
+ EffectHelper::writeToFmq(inputMQ1, buffer1);
+ EffectHelper::readFromFmq(statusMQ1, 1, outputMQ1, buffer1.size(), buffer1);
+
+ auto statusMQ2 = std::make_unique<EffectHelper::StatusMQ>(ret2.statusMQ);
+ auto inputMQ2 = std::make_unique<EffectHelper::DataMQ>(ret2.inputDataMQ);
+ auto outputMQ2 = std::make_unique<EffectHelper::DataMQ>(ret2.outputDataMQ);
+ EffectHelper::allocateInputData(common2, inputMQ2, buffer2);
+ EffectHelper::writeToFmq(inputMQ2, buffer2);
+ EffectHelper::readFromFmq(statusMQ2, 1, outputMQ2, buffer2.size(), buffer2);
+
+ ASSERT_NO_FATAL_FAILURE(command(effect1, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect1, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect1));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect1));
+
+ ASSERT_NO_FATAL_FAILURE(command(effect2, CommandId::STOP));
+ ASSERT_NO_FATAL_FAILURE(expectState(effect2, State::IDLE));
+ ASSERT_NO_FATAL_FAILURE(close(effect2));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, effect2));
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ SingleEffectInstanceTest, AudioEffectTest,
+ ::testing::Combine(testing::ValuesIn(
+ EffectFactoryHelper::getAllEffectDescriptors(IFactory::descriptor))),
+ [](const testing::TestParamInfo<AudioEffectTest::ParamType>& info) {
+ auto msSinceEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+ auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+ std::ostringstream address;
+ address << msSinceEpoch << "_factory_" << instance.first.get();
+ std::string name = address.str() + "_UUID_timeLow_" +
+ ::android::internal::ToString(instance.second.uuid.timeLow) +
+ "_timeMid_" +
+ ::android::internal::ToString(instance.second.uuid.timeMid);
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioEffectTest);
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
ABinderProcess_setThreadPoolMaxThreadCount(1);
ABinderProcess_startThreadPool();
return RUN_ALL_TESTS();
-}
\ No newline at end of file
+}
diff --git a/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
new file mode 100644
index 0000000..f19dff6
--- /dev/null
+++ b/audio/aidl/vts/VtsHalEqualizerTargetTest.cpp
@@ -0,0 +1,353 @@
+/*
+ * 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 <algorithm>
+#include <limits>
+#include <map>
+#include <memory>
+#include <string>
+#include <vector>
+
+#define LOG_TAG "VtsHalEqualizerTest"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+
+#include <Utils.h>
+#include <aidl/android/hardware/audio/effect/IEffect.h>
+#include <aidl/android/hardware/audio/effect/IFactory.h>
+
+#include "AudioHalBinderServiceUtil.h"
+#include "EffectHelper.h"
+#include "TestUtils.h"
+#include "effect-impl/EffectUUID.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Capability;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::Equalizer;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kEqualizerTypeUUID;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific effect (equalizer) parameter checking, general IEffect interfaces
+ * testing performed in VtsAudioEfectTargetTest.
+ */
+
+enum ParamName { PARAM_INSTANCE_NAME, PARAM_BAND_LEVEL };
+using EqualizerParamTestParam =
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
+
+/*
+Testing parameter range, assuming the parameter supported by effect is in this range.
+This range is verified with IEffect.getDescriptor(), for any index supported vts expect EX_NONE
+from IEffect.setParameter(), otherwise expect EX_ILLEGAL_ARGUMENT.
+*/
+const std::vector<int> kBandLevels = {0, -10, 10}; // needs update with implementation
+
+class EqualizerTest : public ::testing::TestWithParam<EqualizerParamTestParam>,
+ public EffectHelper {
+ public:
+ EqualizerTest() : mBandLevel(std::get<PARAM_BAND_LEVEL>(GetParam())) {
+ std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ }
+
+ void SetUp() override {
+ ASSERT_NE(nullptr, mFactory);
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mIdentity));
+
+ Parameter::Specific specific = getDefaultParamSpecific();
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+ ASSERT_NE(nullptr, mEffect);
+ ASSERT_NO_FATAL_FAILURE(setTagRange());
+ }
+ void TearDown() override {
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
+
+ std::pair<int, int> setPresetIndexRange(const Equalizer::Capability& cap) const {
+ const auto [min, max] =
+ std::minmax_element(cap.presets.begin(), cap.presets.end(),
+ [](const auto& a, const auto& b) { return a.index < b.index; });
+ return {min->index, max->index};
+ }
+ std::pair<int, int> setBandIndexRange(const Equalizer::Capability& cap) const {
+ const auto [min, max] =
+ std::minmax_element(cap.bandFrequencies.begin(), cap.bandFrequencies.end(),
+ [](const auto& a, const auto& b) { return a.index < b.index; });
+ return {min->index, max->index};
+ }
+ void setTagRange() {
+ Descriptor desc;
+ ASSERT_STATUS(EX_NONE, mEffect->getDescriptor(&desc));
+ Equalizer::Capability& eqCap = desc.capability.get<Capability::equalizer>();
+ mPresetIndex = setPresetIndexRange(eqCap);
+ mBandIndex = setBandIndexRange(eqCap);
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor::Identity mIdentity;
+ std::pair<int, int> mPresetIndex;
+ std::pair<int, int> mBandIndex;
+ const int mBandLevel;
+ Descriptor mDesc;
+
+ void SetAndGetEqualizerParameters() {
+ ASSERT_NE(nullptr, mEffect);
+ for (auto& it : mTags) {
+ auto& tag = it.first;
+ auto& eq = it.second;
+
+ // validate parameter
+ const bool valid = isTagInRange(it.first, it.second);
+ const binder_exception_t expected = valid ? EX_NONE : EX_ILLEGAL_ARGUMENT;
+
+ // set
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::equalizer>(eq);
+ expectParam.set<Parameter::specific>(specific);
+ EXPECT_STATUS(expected, mEffect->setParameter(expectParam))
+ << expectParam.toString() << "\n"
+ << mDesc.toString();
+
+ // only get if parameter in range and set success
+ if (expected == EX_NONE) {
+ Parameter getParam;
+ Parameter::Id id;
+ Equalizer::Id eqId;
+ eqId.set<Equalizer::Id::commonTag>(tag);
+ id.set<Parameter::Id::equalizerTag>(eqId);
+ // if set success, then get should match
+ EXPECT_STATUS(expected, mEffect->getParameter(id, &getParam));
+ EXPECT_TRUE(isEqParameterExpected(expectParam, getParam))
+ << "\nexpect:" << expectParam.toString()
+ << "\ngetParam:" << getParam.toString();
+ }
+ }
+ }
+
+ bool isEqParameterExpected(const Parameter& expect, const Parameter& target) {
+ // if parameter same, then for sure they are matched
+ if (expect == target) return true;
+
+ // if not, see if target include the expect parameter, and others all default (0).
+ /*
+ * This is to verify the case of client setParameter to a single bandLevel ({3, -1} for
+ * example), and return of getParameter must be [{0, 0}, {1, 0}, {2, 0}, {3, -1}, {4, 0}]
+ */
+ EXPECT_EQ(expect.getTag(), Parameter::specific);
+ EXPECT_EQ(target.getTag(), Parameter::specific);
+
+ Parameter::Specific expectSpec = expect.get<Parameter::specific>(),
+ targetSpec = target.get<Parameter::specific>();
+ EXPECT_EQ(expectSpec.getTag(), Parameter::Specific::equalizer);
+ EXPECT_EQ(targetSpec.getTag(), Parameter::Specific::equalizer);
+
+ Equalizer expectEq = expectSpec.get<Parameter::Specific::equalizer>(),
+ targetEq = targetSpec.get<Parameter::Specific::equalizer>();
+ EXPECT_EQ(expectEq.getTag(), targetEq.getTag());
+
+ auto eqTag = targetEq.getTag();
+ switch (eqTag) {
+ case Equalizer::bandLevels: {
+ auto expectBl = expectEq.get<Equalizer::bandLevels>();
+ std::sort(expectBl.begin(), expectBl.end(),
+ [](const auto& a, const auto& b) { return a.index < b.index; });
+ expectBl.erase(std::unique(expectBl.begin(), expectBl.end()), expectBl.end());
+ auto targetBl = targetEq.get<Equalizer::bandLevels>();
+ return std::includes(targetBl.begin(), targetBl.end(), expectBl.begin(),
+ expectBl.end());
+ }
+ case Equalizer::preset: {
+ return expectEq.get<Equalizer::preset>() == targetEq.get<Equalizer::preset>();
+ }
+ default:
+ return false;
+ }
+ return false;
+ }
+
+ void addPresetParam(int preset) {
+ Equalizer eq;
+ eq.set<Equalizer::preset>(preset);
+ mTags.push_back({Equalizer::preset, eq});
+ }
+
+ void addBandLevelsParam(std::vector<Equalizer::BandLevel>& bandLevels) {
+ Equalizer eq;
+ eq.set<Equalizer::bandLevels>(bandLevels);
+ mTags.push_back({Equalizer::bandLevels, eq});
+ }
+
+ bool isTagInRange(const Equalizer::Tag& tag, const Equalizer& eq) const {
+ switch (tag) {
+ case Equalizer::preset: {
+ int index = eq.get<Equalizer::preset>();
+ return index >= mPresetIndex.first && index <= mPresetIndex.second;
+ }
+ case Equalizer::bandLevels: {
+ auto& bandLevel = eq.get<Equalizer::bandLevels>();
+ return isBandInRange(bandLevel);
+ }
+ default:
+ return false;
+ }
+ return false;
+ }
+
+ bool isBandInRange(const std::vector<Equalizer::BandLevel>& bandLevel) const {
+ for (auto& it : bandLevel) {
+ if (it.index < mBandIndex.first || it.index > mBandIndex.second) return false;
+ }
+ return true;
+ }
+
+ Parameter::Specific getDefaultParamSpecific() {
+ Equalizer eq = Equalizer::make<Equalizer::preset>(0);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::equalizer>(eq);
+ return specific;
+ }
+
+ private:
+ std::vector<std::pair<Equalizer::Tag, Equalizer>> mTags;
+
+ bool validCapabilityTag(Capability& cap) { return cap.getTag() == Capability::equalizer; }
+
+ void CleanUp() { mTags.clear(); }
+};
+
+TEST_P(EqualizerTest, SetAndGetPresetOutOfLowerBound) {
+ addPresetParam(mPresetIndex.second - 1);
+ ASSERT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetPresetOutOfUpperBound) {
+ addPresetParam(mPresetIndex.second + 1);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetPresetAtLowerBound) {
+ addPresetParam(mPresetIndex.first);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetPresetAtHigherBound) {
+ addPresetParam(mPresetIndex.second);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetPresetInBound) {
+ addPresetParam((mPresetIndex.first + mPresetIndex.second) >> 1);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetBandOutOfLowerBound) {
+ std::vector<Equalizer::BandLevel> bandLevels{{mBandIndex.first - 1, mBandLevel}};
+ addBandLevelsParam(bandLevels);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetBandOutOfUpperBound) {
+ std::vector<Equalizer::BandLevel> bandLevels{{mBandIndex.second + 1, mBandLevel}};
+ addBandLevelsParam(bandLevels);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetBandAtLowerBound) {
+ std::vector<Equalizer::BandLevel> bandLevels{{mBandIndex.first, mBandLevel}};
+ addBandLevelsParam(bandLevels);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetBandAtHigherBound) {
+ std::vector<Equalizer::BandLevel> bandLevels{{mBandIndex.second, mBandLevel}};
+ addBandLevelsParam(bandLevels);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetBandInBound) {
+ std::vector<Equalizer::BandLevel> bandLevels{
+ {(mBandIndex.first + mBandIndex.second) >> 1, mBandLevel}};
+ addBandLevelsParam(bandLevels);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetMultiBands) {
+ addPresetParam(mPresetIndex.first);
+ std::vector<Equalizer::BandLevel> bandLevels{
+ {mBandIndex.first, mBandLevel},
+ {mBandIndex.second, mBandLevel},
+ {(mBandIndex.first + mBandIndex.second) >> 1, mBandLevel}};
+ addBandLevelsParam(bandLevels);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+TEST_P(EqualizerTest, SetAndGetMultipleParams) {
+ std::vector<Equalizer::BandLevel> bandLevels{
+ {(mBandIndex.first + mBandIndex.second) >> 1, mBandLevel}};
+ addBandLevelsParam(bandLevels);
+ addPresetParam((mPresetIndex.first + mPresetIndex.second) >> 1);
+ EXPECT_NO_FATAL_FAILURE(SetAndGetEqualizerParameters());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ EqualizerTest, EqualizerTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kEqualizerTypeUUID)),
+ testing::ValuesIn(kBandLevels)),
+ [](const testing::TestParamInfo<EqualizerTest::ParamType>& info) {
+ auto msSinceEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+ auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+ std::string bandLevel = std::to_string(std::get<PARAM_BAND_LEVEL>(info.param));
+ std::ostringstream address;
+ address << msSinceEpoch << "_factory_" << instance.first.get();
+ std::string name = address.str() + "_UUID_timeLow_" +
+ ::android::internal::ToString(instance.second.uuid.timeLow) +
+ "_timeMid_" +
+ ::android::internal::ToString(instance.second.uuid.timeMid) +
+ "_bandLevel_" + bandLevel;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EqualizerTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.cpp
new file mode 100644
index 0000000..1485657
--- /dev/null
+++ b/audio/aidl/vts/VtsHalLoudnessEnhancerTargetTest.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.
+ */
+
+#include <aidl/Vintf.h>
+
+#define LOG_TAG "VtsHalLoudnessEnhancerTest"
+
+#include <Utils.h>
+#include "EffectHelper.h"
+
+using namespace android;
+
+using aidl::android::hardware::audio::effect::Capability;
+using aidl::android::hardware::audio::effect::Descriptor;
+using aidl::android::hardware::audio::effect::IEffect;
+using aidl::android::hardware::audio::effect::IFactory;
+using aidl::android::hardware::audio::effect::kLoudnessEnhancerTypeUUID;
+using aidl::android::hardware::audio::effect::LoudnessEnhancer;
+using aidl::android::hardware::audio::effect::Parameter;
+
+/**
+ * Here we focus on specific parameter checking, general IEffect interfaces testing performed in
+ * VtsAudioEffectTargetTest.
+ */
+enum ParamName { PARAM_INSTANCE_NAME, PARAM_GAIN_MB };
+using LoudnessEnhancerParamTestParam =
+ std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor::Identity>, int>;
+
+// Every int 32 bit value is a valid gain, so testing the corner cases and one regular value.
+// TODO : Update the test values once range/capability is updated by implementation.
+const std::vector<int> kGainMbValues = {std::numeric_limits<int>::min(), 100,
+ std::numeric_limits<int>::max()};
+
+class LoudnessEnhancerParamTest : public ::testing::TestWithParam<LoudnessEnhancerParamTestParam>,
+ public EffectHelper {
+ public:
+ LoudnessEnhancerParamTest() : mParamGainMb(std::get<PARAM_GAIN_MB>(GetParam())) {
+ std::tie(mFactory, mIdentity) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ }
+
+ void SetUp() override {
+ ASSERT_NE(nullptr, mFactory);
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mIdentity));
+
+ Parameter::Specific specific = getDefaultParamSpecific();
+ Parameter::Common common = EffectHelper::createParamCommon(
+ 0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
+ kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
+ IEffect::OpenEffectReturn ret;
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+ ASSERT_NE(nullptr, mEffect);
+ }
+ void TearDown() override {
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ }
+
+ Parameter::Specific getDefaultParamSpecific() {
+ LoudnessEnhancer le = LoudnessEnhancer::make<LoudnessEnhancer::gainMb>(0);
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::loudnessEnhancer>(le);
+ return specific;
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor::Identity mIdentity;
+ int mParamGainMb = 0;
+
+ void SetAndGetParameters() {
+ for (auto& it : mTags) {
+ auto& tag = it.first;
+ auto& le = it.second;
+
+ // set parameter
+ Parameter expectParam;
+ Parameter::Specific specific;
+ specific.set<Parameter::Specific::loudnessEnhancer>(le);
+ expectParam.set<Parameter::specific>(specific);
+ // All values are valid, set parameter should succeed
+ EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString();
+
+ // get parameter
+ Parameter getParam;
+ Parameter::Id id;
+ LoudnessEnhancer::Id leId;
+ leId.set<LoudnessEnhancer::Id::commonTag>(tag);
+ id.set<Parameter::Id::loudnessEnhancerTag>(leId);
+ EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
+
+ EXPECT_EQ(expectParam, getParam) << "\nexpect:" << expectParam.toString()
+ << "\ngetParam:" << getParam.toString();
+ }
+ }
+
+ void addGainMbParam(int gainMb) {
+ LoudnessEnhancer le;
+ le.set<LoudnessEnhancer::gainMb>(gainMb);
+ mTags.push_back({LoudnessEnhancer::gainMb, le});
+ }
+
+ private:
+ std::vector<std::pair<LoudnessEnhancer::Tag, LoudnessEnhancer>> mTags;
+ void CleanUp() { mTags.clear(); }
+};
+
+TEST_P(LoudnessEnhancerParamTest, SetAndGetGainMb) {
+ EXPECT_NO_FATAL_FAILURE(addGainMbParam(mParamGainMb));
+ SetAndGetParameters();
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ LoudnessEnhancerTest, LoudnessEnhancerParamTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kLoudnessEnhancerTypeUUID)),
+ testing::ValuesIn(kGainMbValues)),
+ [](const testing::TestParamInfo<LoudnessEnhancerParamTest::ParamType>& info) {
+ auto msSinceEpoch = std::chrono::duration_cast<std::chrono::nanoseconds>(
+ std::chrono::system_clock::now().time_since_epoch())
+ .count();
+ auto instance = std::get<PARAM_INSTANCE_NAME>(info.param);
+ std::string gainMb = std::to_string(std::get<PARAM_GAIN_MB>(info.param));
+
+ std::ostringstream address;
+ address << msSinceEpoch << "_factory_" << instance.first.get();
+ std::string name = address.str() + "_UUID_timeLow_" +
+ ::android::internal::ToString(instance.second.uuid.timeLow) +
+ "_timeMid_" +
+ ::android::internal::ToString(instance.second.uuid.timeMid) +
+ "_gainMb" + gainMb;
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(LoudnessEnhancerParamTest);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
index e46e5b4..98e49a2 100644
--- a/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
+++ b/audio/core/all-versions/vts/functional/AudioPrimaryHidlHalTest.h
@@ -1014,9 +1014,8 @@
if (mDataPosition == 0) mOnDataStart();
const size_t dataSize = std::min(mData.size() - mDataPosition, mDataMQ->availableToWrite());
bool success = mDataMQ->write(mData.data() + mDataPosition, dataSize);
+ bool wrapped = false;
ALOGE_IF(!success, "data message queue write failed");
- mDataPosition += dataSize;
- if (mDataPosition >= mData.size()) mDataPosition = 0;
mEfGroup->wake(static_cast<uint32_t>(MessageQueueFlagBits::NOT_EMPTY));
uint32_t efState = 0;
@@ -1034,6 +1033,11 @@
ALOGE("bad write status: %d", writeStatus.retval);
success = false;
}
+ mDataPosition += writeStatus.reply.written;
+ if (mDataPosition >= mData.size()) {
+ mDataPosition = 0;
+ wrapped = true;
+ }
}
if (ret == -EAGAIN || ret == -EINTR) {
// Spurious wakeup. This normally retries no more than once.
@@ -1042,7 +1046,7 @@
ALOGE("bad wait status: %d", ret);
success = false;
}
- if (success && mDataPosition == 0) {
+ if (wrapped) {
success = mOnDataWrap();
}
return success;
@@ -1270,6 +1274,8 @@
if (!xsd::isTelephonyDevice(address.deviceType)) {
metadata.source = toString(xsd::AudioSource::AUDIO_SOURCE_UNPROCESSED);
metadata.channelMask = getConfig().base.channelMask;
+ } else {
+ address.deviceType = toString(xsd::AudioDevice::AUDIO_DEVICE_IN_DEFAULT);
}
#if MAJOR_VERSION == 7 && MINOR_VERSION >= 1
auto flagsIt = std::find(flags.begin(), flags.end(),
diff --git a/audio/effect/all-versions/default/Effect.cpp b/audio/effect/all-versions/default/Effect.cpp
index b57dc63..5dc42dc 100644
--- a/audio/effect/all-versions/default/Effect.cpp
+++ b/audio/effect/all-versions/default/Effect.cpp
@@ -700,8 +700,21 @@
void* dataPtr = halDataSize > 0 ? &halData[0] : NULL;
void* resultPtr = halResultSize > 0 ? &halResult[0] : NULL;
- status_t status =
- (*mHandle)->command(mHandle, commandId, halDataSize, dataPtr, &halResultSize, resultPtr);
+ status_t status = BAD_VALUE;
+ switch (commandId) {
+ case 'gtid': // retrieve the tid, used for spatializer priority boost
+ if (halDataSize == 0 && resultMaxSize == sizeof(int32_t)) {
+ auto ptid = (int32_t*)resultPtr;
+ ptid[0] = mProcessThread ? mProcessThread->getTid() : -1;
+ status = OK;
+ break; // we have handled 'gtid' here.
+ }
+ [[fallthrough]]; // allow 'gtid' overload (checked halDataSize and resultMaxSize).
+ default:
+ status = (*mHandle)->command(mHandle, commandId, halDataSize, dataPtr, &halResultSize,
+ resultPtr);
+ break;
+ }
hidl_vec<uint8_t> result;
if (status == OK && resultPtr != NULL) {
result.setToExternal(&halResult[0], halResultSize);
diff --git a/automotive/evs/aidl/Android.bp b/automotive/evs/aidl/Android.bp
index 1c908aa..8aaa1ce 100644
--- a/automotive/evs/aidl/Android.bp
+++ b/automotive/evs/aidl/Android.bp
@@ -30,7 +30,7 @@
stability: "vintf",
imports: [
"android.hardware.common-V2",
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
],
backend: {
java: {
@@ -53,7 +53,7 @@
version: "1",
imports: [
"android.hardware.common-V2",
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
],
},
],
diff --git a/automotive/remoteaccess/hal/default/Android.bp b/automotive/remoteaccess/hal/default/Android.bp
new file mode 100644
index 0000000..a2bf86c
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/Android.bp
@@ -0,0 +1,109 @@
+/*
+ * 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: ["Android-Apache-2.0"],
+}
+
+cc_binary {
+ name: "android.hardware.automotive.remoteaccess@V1-default-service",
+ vendor: true,
+ vintf_fragments: ["remoteaccess-default-service.xml"],
+ init_rc: ["remoteaccess-default-service.rc"],
+ relative_install_path: "hw",
+ srcs: ["src/RemoteAccessImpl.cpp"],
+ whole_static_libs: [
+ "RemoteAccessService",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "liblog",
+ "libutils",
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ defaults: [
+ "vhalclient_defaults",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
+ ],
+}
+
+cc_library {
+ name: "RemoteAccessService",
+ vendor_available: true,
+ local_include_dirs: ["include"],
+ export_include_dirs: ["include"],
+ srcs: [
+ "src/RemoteAccessService.cpp",
+ ],
+ whole_static_libs: [
+ "android.hardware.automotive.remoteaccess-V1-ndk",
+ "wakeup_client_protos",
+ "libvhalclient",
+ ],
+ defaults: [
+ "vhalclient_defaults",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libutils",
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+}
+
+cc_fuzz {
+ name: "android.hardware.automotive.remoteaccess@V1-default-service.aidl_fuzzer",
+ srcs: ["fuzzer/fuzzer.cpp"],
+ whole_static_libs: [
+ "RemoteAccessService",
+ ],
+ static_libs: [
+ "libgtest",
+ "libgmock",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "liblog",
+ "libutils",
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ defaults: [
+ "vhalclient_defaults",
+ "service_fuzzer_defaults",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
+ ],
+ fuzz_config: {
+ cc: [
+ "shanyu@google.com",
+ ],
+ },
+}
diff --git a/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp
new file mode 100644
index 0000000..292c80e
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/fuzzer/fuzzer.cpp
@@ -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.
+ */
+
+#include <RemoteAccessService.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+#include <gmock/gmock.h>
+#include <grpcpp/test/mock_stream.h>
+#include <wakeup_client.grpc.pb.h>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+using ::grpc::ClientAsyncReaderInterface;
+using ::grpc::ClientAsyncResponseReaderInterface;
+using ::grpc::ClientContext;
+using ::grpc::ClientReader;
+using ::grpc::ClientReaderInterface;
+using ::grpc::CompletionQueue;
+using ::grpc::Status;
+using ::grpc::testing::MockClientReader;
+using ::testing::_;
+using ::testing::Return;
+
+class MockGrpcClientStub : public WakeupClient::StubInterface {
+ public:
+ ClientReaderInterface<GetRemoteTasksResponse>* GetRemoteTasksRaw(
+ [[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetRemoteTasksRequest& request) override {
+ MockClientReader<GetRemoteTasksResponse>* mockClientReader =
+ new MockClientReader<GetRemoteTasksResponse>();
+ ON_CALL(*mockClientReader, Finish()).WillByDefault(Return(Status::OK));
+ ON_CALL(*mockClientReader, Read(_)).WillByDefault(Return(false));
+ return mockClientReader;
+ }
+
+ Status NotifyWakeupRequired([[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const NotifyWakeupRequiredRequest& request,
+ [[maybe_unused]] NotifyWakeupRequiredResponse* response) {
+ return Status::OK;
+ }
+
+ // Async methods which we do not care.
+ ClientAsyncReaderInterface<GetRemoteTasksResponse>* AsyncGetRemoteTasksRaw(
+ [[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetRemoteTasksRequest& request,
+ [[maybe_unused]] CompletionQueue* cq, [[maybe_unused]] void* tag) {
+ return nullptr;
+ }
+
+ ClientAsyncReaderInterface<GetRemoteTasksResponse>* PrepareAsyncGetRemoteTasksRaw(
+ [[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetRemoteTasksRequest& request,
+ [[maybe_unused]] CompletionQueue* cq) {
+ return nullptr;
+ }
+
+ ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>* AsyncNotifyWakeupRequiredRaw(
+ [[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const NotifyWakeupRequiredRequest& request,
+ [[maybe_unused]] CompletionQueue* cq) {
+ return nullptr;
+ }
+
+ ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>*
+ PrepareAsyncNotifyWakeupRequiredRaw([[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const NotifyWakeupRequiredRequest& request,
+ [[maybe_unused]] CompletionQueue* c) {
+ return nullptr;
+ }
+};
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ android::hardware::automotive::remoteaccess::MockGrpcClientStub stub;
+ std::shared_ptr<android::hardware::automotive::remoteaccess::RemoteAccessService> service =
+ ndk::SharedRefBase::make<
+ android::hardware::automotive::remoteaccess::RemoteAccessService>(&stub);
+ android::fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
diff --git a/automotive/remoteaccess/hal/default/include/RemoteAccessService.h b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
new file mode 100644
index 0000000..74c2af4
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/include/RemoteAccessService.h
@@ -0,0 +1,116 @@
+/*
+ * 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 <IVhalClient.h>
+#include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
+#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteAccess.h>
+#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
+#include <aidl/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.h>
+#include <android-base/thread_annotations.h>
+#include <android/binder_auto_utils.h>
+#include <utils/SystemClock.h>
+#include <wakeup_client.grpc.pb.h>
+
+#include <string>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+// A IRemoteTaskCallback implementation for debug purpose.
+class DebugRemoteTaskCallback final
+ : public aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback {
+ public:
+ DebugRemoteTaskCallback() { mStartTimeMillis = android::uptimeMillis(); };
+
+ ndk::ScopedAStatus onRemoteTaskRequested(const std::string& clientId,
+ const std::vector<uint8_t>& data) override;
+ std::string printTasks();
+
+ private:
+ struct TaskData {
+ std::string clientId;
+ std::vector<uint8_t> data;
+ };
+
+ std::mutex mLock;
+ int64_t mStartTimeMillis;
+ std::vector<TaskData> mTasks;
+};
+
+class RemoteAccessService
+ : public aidl::android::hardware::automotive::remoteaccess::BnRemoteAccess {
+ public:
+ explicit RemoteAccessService(WakeupClient::StubInterface* grpcStub);
+
+ ~RemoteAccessService();
+
+ ndk::ScopedAStatus getDeviceId(std::string* deviceId) override;
+
+ ndk::ScopedAStatus getWakeupServiceName(std::string* wakeupServiceName) override;
+
+ ndk::ScopedAStatus setRemoteTaskCallback(
+ const std::shared_ptr<
+ aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback>&
+ callback) override;
+
+ ndk::ScopedAStatus clearRemoteTaskCallback() override;
+
+ ndk::ScopedAStatus notifyApStateChange(
+ const aidl::android::hardware::automotive::remoteaccess::ApState& newState) override;
+
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+ private:
+ // For testing.
+ friend class RemoteAccessServiceUnitTest;
+
+ static bool checkDumpPermission();
+
+ WakeupClient::StubInterface* mGrpcStub;
+ std::thread mThread;
+ std::mutex mLock;
+ std::condition_variable mCv;
+ std::shared_ptr<aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback>
+ mRemoteTaskCallback GUARDED_BY(mLock);
+ std::unique_ptr<grpc::ClientContext> mGetRemoteTasksContext GUARDED_BY(mLock);
+ // Associated with mCv to notify the task loop to stop waiting and exit.
+ bool mTaskWaitStopped GUARDED_BY(mLock);
+ // A mutex to make sure startTaskLoop does not overlap with stopTaskLoop.
+ std::mutex mStartStopTaskLoopLock;
+ bool mTaskLoopRunning GUARDED_BY(mStartStopTaskLoopLock);
+ // Default wait time before retry connecting to remote access client is 10s.
+ size_t mRetryWaitInMs = 10'000;
+ std::shared_ptr<DebugRemoteTaskCallback> mDebugCallback;
+
+ void runTaskLoop();
+ void maybeStartTaskLoop();
+ void maybeStopTaskLoop();
+ ndk::ScopedAStatus getDeviceIdWithClient(
+ android::frameworks::automotive::vhal::IVhalClient& client, std::string* deviceId);
+
+ void setRetryWaitInMs(size_t retryWaitInMs) { mRetryWaitInMs = retryWaitInMs; }
+ void dumpHelp(int fd);
+};
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/hal/default/proto/Android.bp b/automotive/remoteaccess/hal/default/proto/Android.bp
new file mode 100644
index 0000000..3e0dba1
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/proto/Android.bp
@@ -0,0 +1,79 @@
+// 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"],
+}
+
+genrule {
+ name: "wakeup_client_pb_h",
+ tools: [
+ "aprotoc",
+ "protoc-gen-grpc-cpp-plugin",
+ ],
+ cmd: "$(location aprotoc) -I$$(dirname $(in)) -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+ srcs: [
+ "wakeup_client.proto",
+ ],
+ out: [
+ "wakeup_client.pb.h",
+ "wakeup_client.grpc.pb.h",
+ ],
+}
+
+genrule {
+ name: "wakeup_client_pb_cc",
+ tools: [
+ "aprotoc",
+ "protoc-gen-grpc-cpp-plugin",
+ ],
+ cmd: "$(location aprotoc) -I$$(dirname $(in)) -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
+ srcs: [
+ "wakeup_client.proto",
+ ],
+ out: [
+ "wakeup_client.pb.cc",
+ "wakeup_client.grpc.pb.cc",
+ ],
+}
+
+cc_library_static {
+ name: "wakeup_client_protos",
+ vendor_available: true,
+ host_supported: true,
+ include_dirs: [
+ "external/protobuf/src",
+ ],
+ generated_headers: [
+ "wakeup_client_pb_h",
+ ],
+ export_generated_headers: [
+ "wakeup_client_pb_h",
+ ],
+ generated_sources: [
+ "wakeup_client_pb_cc",
+ ],
+ shared_libs: [
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+}
diff --git a/automotive/remoteaccess/impl/default/proto/wakeup_client.proto b/automotive/remoteaccess/hal/default/proto/wakeup_client.proto
similarity index 100%
rename from automotive/remoteaccess/impl/default/proto/wakeup_client.proto
rename to automotive/remoteaccess/hal/default/proto/wakeup_client.proto
diff --git a/automotive/remoteaccess/impl/default/client/remoteaccess-default-service.rc b/automotive/remoteaccess/hal/default/remoteaccess-default-service.rc
similarity index 100%
rename from automotive/remoteaccess/impl/default/client/remoteaccess-default-service.rc
rename to automotive/remoteaccess/hal/default/remoteaccess-default-service.rc
diff --git a/automotive/remoteaccess/impl/default/client/remoteaccess-default-service.xml b/automotive/remoteaccess/hal/default/remoteaccess-default-service.xml
similarity index 100%
rename from automotive/remoteaccess/impl/default/client/remoteaccess-default-service.xml
rename to automotive/remoteaccess/hal/default/remoteaccess-default-service.xml
diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
new file mode 100644
index 0000000..8720c2f
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessImpl.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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 "RemoteAccessImpl"
+
+#include "RemoteAccessService.h"
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <grpcpp/create_channel.h>
+#include <stdlib.h>
+#include <utils/Log.h>
+
+constexpr char SERVICE_NAME[] = "android.hardware.automotive.remoteaccess.IRemoteAccess/default";
+
+int main(int /* argc */, char* /* argv */[]) {
+ ALOGI("Registering RemoteAccessService as service...");
+
+#ifndef GRPC_SERVICE_ADDRESS
+ ALOGE("GRPC_SERVICE_ADDRESS is not defined, exiting");
+ exit(1);
+#endif
+ auto channel = grpc::CreateChannel(GRPC_SERVICE_ADDRESS, grpc::InsecureChannelCredentials());
+ auto clientStub = android::hardware::automotive::remoteaccess::WakeupClient::NewStub(channel);
+ auto service = ndk::SharedRefBase::make<
+ android::hardware::automotive::remoteaccess::RemoteAccessService>(clientStub.get());
+
+ binder_exception_t err = AServiceManager_addService(service->asBinder().get(), SERVICE_NAME);
+ if (err != EX_NONE) {
+ ALOGE("failed to register android.hardware.automotive.remote.IRemoteAccess service, "
+ "exception: %d",
+ err);
+ exit(1);
+ }
+
+ if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
+ ALOGE("%s", "failed to set thread pool max thread count");
+ exit(1);
+ }
+ ABinderProcess_startThreadPool();
+
+ ALOGI("RemoteAccess service Ready");
+
+ ABinderProcess_joinThreadPool();
+
+ ALOGW("Should not reach here");
+
+ return 0;
+}
diff --git a/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
new file mode 100644
index 0000000..5cd58d3
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/src/RemoteAccessService.cpp
@@ -0,0 +1,355 @@
+/*
+ * 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 "RemoteAccessService.h"
+
+#include <VehicleUtils.h>
+#include <aidl/android/hardware/automotive/vehicle/VehicleProperty.h>
+#include <android-base/stringprintf.h>
+#include <android/binder_status.h>
+#include <grpc++/grpc++.h>
+#include <private/android_filesystem_config.h>
+#include <utils/Log.h>
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+namespace {
+
+using ::aidl::android::hardware::automotive::remoteaccess::ApState;
+using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback;
+using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
+using ::android::base::ScopedLockAssertion;
+using ::android::base::StringAppendF;
+using ::android::base::StringPrintf;
+using ::android::frameworks::automotive::vhal::IVhalClient;
+using ::android::hardware::automotive::vehicle::toInt;
+using ::grpc::ClientContext;
+using ::grpc::ClientReaderInterface;
+using ::grpc::Status;
+using ::grpc::StatusCode;
+using ::ndk::ScopedAStatus;
+
+const std::string WAKEUP_SERVICE_NAME = "com.google.vehicle.wakeup";
+constexpr char COMMAND_SET_AP_STATE[] = "--set-ap-state";
+constexpr char COMMAND_START_DEBUG_CALLBACK[] = "--start-debug-callback";
+constexpr char COMMAND_STOP_DEBUG_CALLBACK[] = "--stop-debug-callback";
+constexpr char COMMAND_SHOW_TASK[] = "--show-task";
+constexpr char COMMAND_GET_DEVICE_ID[] = "--get-device-id";
+
+std::vector<uint8_t> stringToBytes(const std::string& s) {
+ const char* data = s.data();
+ return std::vector<uint8_t>(data, data + s.size());
+}
+
+ScopedAStatus rpcStatusToScopedAStatus(const Status& status, const std::string& errorMsg) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ status.error_code(), (errorMsg + ", error: " + status.error_message()).c_str());
+}
+
+std::string printBytes(const std::vector<uint8_t>& bytes) {
+ std::string s;
+ for (size_t i = 0; i < bytes.size(); i++) {
+ StringAppendF(&s, "%02x", bytes[i]);
+ }
+ return s;
+}
+
+bool checkBoolFlag(const char* flag) {
+ return !strcmp(flag, "1") || !strcmp(flag, "0");
+}
+
+void dprintErrorStatus(int fd, const char* detail, const ScopedAStatus& status) {
+ dprintf(fd, "%s, code: %d, error: %s\n", detail, status.getStatus(), status.getMessage());
+}
+
+} // namespace
+
+RemoteAccessService::RemoteAccessService(WakeupClient::StubInterface* grpcStub)
+ : mGrpcStub(grpcStub){};
+
+RemoteAccessService::~RemoteAccessService() {
+ maybeStopTaskLoop();
+}
+
+void RemoteAccessService::maybeStartTaskLoop() {
+ std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
+ if (mTaskLoopRunning) {
+ return;
+ }
+
+ mThread = std::thread([this]() { runTaskLoop(); });
+
+ mTaskLoopRunning = true;
+}
+
+void RemoteAccessService::maybeStopTaskLoop() {
+ std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
+ if (!mTaskLoopRunning) {
+ return;
+ }
+
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ // Try to stop the reading stream.
+ if (mGetRemoteTasksContext) {
+ mGetRemoteTasksContext->TryCancel();
+ mGetRemoteTasksContext.reset();
+ }
+ mTaskWaitStopped = true;
+ mCv.notify_all();
+ }
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+
+ mTaskLoopRunning = false;
+}
+
+void RemoteAccessService::runTaskLoop() {
+ GetRemoteTasksRequest request = {};
+ std::unique_ptr<ClientReaderInterface<GetRemoteTasksResponse>> reader;
+ while (true) {
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mGetRemoteTasksContext.reset(new ClientContext());
+ reader = mGrpcStub->GetRemoteTasks(mGetRemoteTasksContext.get(), request);
+ }
+ GetRemoteTasksResponse response;
+ while (reader->Read(&response)) {
+ ALOGI("Receiving one task from remote task client");
+
+ std::shared_ptr<IRemoteTaskCallback> callback;
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ callback = mRemoteTaskCallback;
+ }
+ if (callback == nullptr) {
+ ALOGD("No callback registered, task ignored");
+ continue;
+ }
+ ALOGD("Calling onRemoteTaskRequested callback for client ID: %s",
+ response.clientid().c_str());
+ ScopedAStatus callbackStatus = callback->onRemoteTaskRequested(
+ response.clientid(), stringToBytes(response.data()));
+ if (!callbackStatus.isOk()) {
+ ALOGE("Failed to call onRemoteTaskRequested callback, status: %d, message: %s",
+ callbackStatus.getStatus(), callbackStatus.getMessage());
+ }
+ }
+ Status status = reader->Finish();
+
+ ALOGE("GetRemoteTasks stream breaks, code: %d, message: %s, sleeping for 10s and retry",
+ status.error_code(), status.error_message().c_str());
+ // The long lasting connection should not return. But if the server returns, retry after
+ // 10s.
+ {
+ std::unique_lock lk(mLock);
+ if (mCv.wait_for(lk, std::chrono::milliseconds(mRetryWaitInMs), [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mTaskWaitStopped;
+ })) {
+ // If the stopped flag is set, we are quitting, exit the loop.
+ break;
+ }
+ }
+ }
+}
+
+ScopedAStatus RemoteAccessService::getDeviceId(std::string* deviceId) {
+#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+ auto vhalClient = IVhalClient::tryCreate();
+ if (vhalClient == nullptr) {
+ ALOGE("Failed to connect to VHAL");
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ /*errorCode=*/0, "Failed to connect to VHAL to get device ID");
+ }
+ return getDeviceIdWithClient(*vhalClient.get(), deviceId);
+#else
+ // Don't use VHAL client in fuzzing since IPC is not allowed.
+ return ScopedAStatus::ok();
+#endif
+}
+
+ScopedAStatus RemoteAccessService::getDeviceIdWithClient(IVhalClient& vhalClient,
+ std::string* deviceId) {
+ auto result = vhalClient.getValueSync(
+ *vhalClient.createHalPropValue(toInt(VehicleProperty::INFO_VIN)));
+ if (!result.ok()) {
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ /*errorCode=*/0,
+ ("failed to get INFO_VIN from VHAL: " + result.error().message()).c_str());
+ }
+ *deviceId = (*result)->getStringValue();
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::getWakeupServiceName(std::string* wakeupServiceName) {
+ *wakeupServiceName = WAKEUP_SERVICE_NAME;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::setRemoteTaskCallback(
+ const std::shared_ptr<IRemoteTaskCallback>& callback) {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mRemoteTaskCallback = callback;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::clearRemoteTaskCallback() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mRemoteTaskCallback.reset();
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus RemoteAccessService::notifyApStateChange(const ApState& newState) {
+ ClientContext context;
+ NotifyWakeupRequiredRequest request = {};
+ request.set_iswakeuprequired(newState.isWakeupRequired);
+ NotifyWakeupRequiredResponse response = {};
+ Status status = mGrpcStub->NotifyWakeupRequired(&context, request, &response);
+ if (!status.ok()) {
+ return rpcStatusToScopedAStatus(status, "Failed to notify isWakeupRequired");
+ }
+
+ if (newState.isReadyForRemoteTask) {
+ maybeStartTaskLoop();
+ } else {
+ maybeStopTaskLoop();
+ }
+ return ScopedAStatus::ok();
+}
+
+bool RemoteAccessService::checkDumpPermission() {
+ uid_t uid = AIBinder_getCallingUid();
+ return uid == AID_ROOT || uid == AID_SHELL || uid == AID_SYSTEM;
+}
+
+void RemoteAccessService::dumpHelp(int fd) {
+ dprintf(fd, "%s",
+ (std::string("RemoteAccess HAL debug interface, Usage: \n") + COMMAND_SET_AP_STATE +
+ " [0/1](isReadyForRemoteTask) [0/1](isWakeupRequired) Set the new AP state\n" +
+ COMMAND_START_DEBUG_CALLBACK +
+ " Start a debug callback that will record the received tasks\n" +
+ COMMAND_STOP_DEBUG_CALLBACK + " Stop the debug callback\n" + COMMAND_SHOW_TASK +
+ " Show tasks received by debug callback\n" + COMMAND_GET_DEVICE_ID +
+ " Get device id\n")
+ .c_str());
+}
+
+binder_status_t RemoteAccessService::dump(int fd, const char** args, uint32_t numArgs) {
+ if (!checkDumpPermission()) {
+ dprintf(fd, "Caller must be root, system or shell\n");
+ return STATUS_PERMISSION_DENIED;
+ }
+
+ if (numArgs == 0) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+
+ if (!strcmp(args[0], COMMAND_SET_AP_STATE)) {
+ if (numArgs < 3) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ ApState apState = {};
+ const char* remoteTaskFlag = args[1];
+ if (!strcmp(remoteTaskFlag, "1") && !strcmp(remoteTaskFlag, "0")) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ if (!checkBoolFlag(args[1])) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ if (!strcmp(args[1], "1")) {
+ apState.isReadyForRemoteTask = true;
+ }
+ if (!checkBoolFlag(args[2])) {
+ dumpHelp(fd);
+ return STATUS_OK;
+ }
+ if (!strcmp(args[2], "1")) {
+ apState.isWakeupRequired = true;
+ }
+ auto status = notifyApStateChange(apState);
+ if (!status.isOk()) {
+ dprintErrorStatus(fd, "Failed to set AP state", status);
+ } else {
+ dprintf(fd, "successfully set the new AP state\n");
+ }
+ } else if (!strcmp(args[0], COMMAND_START_DEBUG_CALLBACK)) {
+ mDebugCallback = ndk::SharedRefBase::make<DebugRemoteTaskCallback>();
+ setRemoteTaskCallback(mDebugCallback);
+ dprintf(fd, "Debug callback registered\n");
+ } else if (!strcmp(args[0], COMMAND_STOP_DEBUG_CALLBACK)) {
+ if (mDebugCallback) {
+ mDebugCallback.reset();
+ }
+ clearRemoteTaskCallback();
+ dprintf(fd, "Debug callback unregistered\n");
+ } else if (!strcmp(args[0], COMMAND_SHOW_TASK)) {
+ if (mDebugCallback) {
+ dprintf(fd, "%s", mDebugCallback->printTasks().c_str());
+ } else {
+ dprintf(fd, "Debug callback is not currently used, use \"%s\" first.\n",
+ COMMAND_START_DEBUG_CALLBACK);
+ }
+ } else if (!strcmp(args[0], COMMAND_GET_DEVICE_ID)) {
+ std::string deviceId;
+ auto status = getDeviceId(&deviceId);
+ if (!status.isOk()) {
+ dprintErrorStatus(fd, "Failed to get device ID", status);
+ } else {
+ dprintf(fd, "Device Id: %s\n", deviceId.c_str());
+ }
+ } else {
+ dumpHelp(fd);
+ }
+
+ return STATUS_OK;
+}
+
+ScopedAStatus DebugRemoteTaskCallback::onRemoteTaskRequested(const std::string& clientId,
+ const std::vector<uint8_t>& data) {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mTasks.push_back({
+ .clientId = clientId,
+ .data = data,
+ });
+ return ScopedAStatus::ok();
+}
+
+std::string DebugRemoteTaskCallback::printTasks() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ std::string s = StringPrintf("Received %zu tasks in %f seconds", mTasks.size(),
+ (android::uptimeMillis() - mStartTimeMillis) / 1000.);
+ for (size_t i = 0; i < mTasks.size(); i++) {
+ StringAppendF(&s, "Client Id: %s, Data: %s\n", mTasks[i].clientId.c_str(),
+ printBytes(mTasks[i].data).c_str());
+ }
+ return s;
+}
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/hal/default/test/Android.bp b/automotive/remoteaccess/hal/default/test/Android.bp
new file mode 100644
index 0000000..227175a
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/test/Android.bp
@@ -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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_test {
+ name: "RemoteAccessServiceUnitTest",
+ vendor: true,
+ srcs: ["*.cpp"],
+ whole_static_libs: [
+ "RemoteAccessService",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "liblog",
+ "libutils",
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ ],
+ // libgrpc++.so is installed as root, require root to access it.
+ require_root: true,
+ static_libs: [
+ "libgtest",
+ "libgmock",
+ ],
+ defaults: [
+ "vhalclient_defaults",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ ],
+ test_suites: ["device-tests"],
+}
diff --git a/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
new file mode 100644
index 0000000..8c4fa08
--- /dev/null
+++ b/automotive/remoteaccess/hal/default/test/RemoteAccessServiceUnitTest.cpp
@@ -0,0 +1,373 @@
+/*
+ * 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 "RemoteAccessService.h"
+
+#include <AidlHalPropValue.h>
+#include <IVhalClient.h>
+#include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
+#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
+#include <aidl/android/hardware/automotive/vehicle/VehiclePropValue.h>
+#include <gmock/gmock.h>
+#include <grpcpp/test/mock_stream.h>
+#include <gtest/gtest.h>
+#include <wakeup_client.grpc.pb.h>
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+namespace {
+
+using ::android::base::ScopedLockAssertion;
+using ::android::frameworks::automotive::vhal::AidlHalPropValue;
+using ::android::frameworks::automotive::vhal::IHalPropConfig;
+using ::android::frameworks::automotive::vhal::IHalPropValue;
+using ::android::frameworks::automotive::vhal::ISubscriptionCallback;
+using ::android::frameworks::automotive::vhal::ISubscriptionClient;
+using ::android::frameworks::automotive::vhal::IVhalClient;
+using ::android::frameworks::automotive::vhal::VhalClientResult;
+
+using ::aidl::android::hardware::automotive::remoteaccess::ApState;
+using ::aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropValue;
+
+using ::grpc::ClientAsyncReaderInterface;
+using ::grpc::ClientAsyncResponseReaderInterface;
+using ::grpc::ClientContext;
+using ::grpc::ClientReader;
+using ::grpc::ClientReaderInterface;
+using ::grpc::CompletionQueue;
+using ::grpc::Status;
+using ::grpc::testing::MockClientReader;
+using ::ndk::ScopedAStatus;
+using ::testing::_;
+using ::testing::DoAll;
+using ::testing::Return;
+using ::testing::SetArgPointee;
+
+constexpr char kTestVin[] = "test_VIN";
+
+} // namespace
+
+class MockGrpcClientStub : public WakeupClient::StubInterface {
+ public:
+ MOCK_METHOD(ClientReaderInterface<GetRemoteTasksResponse>*, GetRemoteTasksRaw,
+ (ClientContext * context, const GetRemoteTasksRequest& request));
+ MOCK_METHOD(Status, NotifyWakeupRequired,
+ (ClientContext * context, const NotifyWakeupRequiredRequest& request,
+ NotifyWakeupRequiredResponse* response));
+ // Async methods which we do not care.
+ MOCK_METHOD(ClientAsyncReaderInterface<GetRemoteTasksResponse>*, AsyncGetRemoteTasksRaw,
+ (ClientContext * context, const GetRemoteTasksRequest& request, CompletionQueue* cq,
+ void* tag));
+ MOCK_METHOD(ClientAsyncReaderInterface<GetRemoteTasksResponse>*, PrepareAsyncGetRemoteTasksRaw,
+ (ClientContext * context, const GetRemoteTasksRequest& request,
+ CompletionQueue* cq));
+ MOCK_METHOD(ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>*,
+ AsyncNotifyWakeupRequiredRaw,
+ (ClientContext * context, const NotifyWakeupRequiredRequest& request,
+ CompletionQueue* cq));
+ MOCK_METHOD(ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>*,
+ PrepareAsyncNotifyWakeupRequiredRaw,
+ (ClientContext * context, const NotifyWakeupRequiredRequest& request,
+ CompletionQueue* cq));
+};
+
+class FakeVhalClient final : public android::frameworks::automotive::vhal::IVhalClient {
+ public:
+ inline bool isAidlVhal() { return true; }
+
+ VhalClientResult<std::unique_ptr<IHalPropValue>> getValueSync(
+ const IHalPropValue& requestValue) override {
+ auto propValue = std::make_unique<AidlHalPropValue>(requestValue.getPropId());
+ propValue->setStringValue(kTestVin);
+ return propValue;
+ }
+
+ std::unique_ptr<IHalPropValue> createHalPropValue(int32_t propId) override {
+ return std::make_unique<AidlHalPropValue>(propId);
+ }
+
+ // Functions we do not care.
+ std::unique_ptr<IHalPropValue> createHalPropValue([[maybe_unused]] int32_t propId,
+ [[maybe_unused]] int32_t areaId) override {
+ return nullptr;
+ }
+
+ void getValue([[maybe_unused]] const IHalPropValue& requestValue,
+ [[maybe_unused]] std::shared_ptr<GetValueCallbackFunc> callback) override {}
+
+ void setValue([[maybe_unused]] const IHalPropValue& requestValue,
+ [[maybe_unused]] std::shared_ptr<SetValueCallbackFunc> callback) override {}
+
+ VhalClientResult<void> setValueSync([[maybe_unused]] const IHalPropValue& requestValue) {
+ return {};
+ }
+
+ VhalClientResult<void> addOnBinderDiedCallback(
+ [[maybe_unused]] std::shared_ptr<OnBinderDiedCallbackFunc> callback) override {
+ return {};
+ }
+
+ VhalClientResult<void> removeOnBinderDiedCallback(
+ [[maybe_unused]] std::shared_ptr<OnBinderDiedCallbackFunc> callback) override {
+ return {};
+ }
+
+ VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getAllPropConfigs() override {
+ return std::vector<std::unique_ptr<IHalPropConfig>>();
+ }
+
+ VhalClientResult<std::vector<std::unique_ptr<IHalPropConfig>>> getPropConfigs(
+ [[maybe_unused]] std::vector<int32_t> propIds) override {
+ return std::vector<std::unique_ptr<IHalPropConfig>>();
+ }
+
+ std::unique_ptr<ISubscriptionClient> getSubscriptionClient(
+ [[maybe_unused]] std::shared_ptr<ISubscriptionCallback> callback) override {
+ return nullptr;
+ }
+};
+
+class FakeRemoteTaskCallback : public BnRemoteTaskCallback {
+ public:
+ ScopedAStatus onRemoteTaskRequested(const std::string& clientId,
+ const std::vector<uint8_t>& data) override {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mDataByClientId[clientId] = data;
+ mTaskCount++;
+ mCv.notify_all();
+ return ScopedAStatus::ok();
+ }
+
+ std::vector<uint8_t> getData(const std::string& clientId) { return mDataByClientId[clientId]; }
+
+ bool wait(size_t taskCount, size_t timeoutInSec) {
+ std::unique_lock<std::mutex> lock(mLock);
+ return mCv.wait_for(lock, std::chrono::seconds(timeoutInSec), [taskCount, this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mTaskCount >= taskCount;
+ });
+ }
+
+ private:
+ std::mutex mLock;
+ std::unordered_map<std::string, std::vector<uint8_t>> mDataByClientId GUARDED_BY(mLock);
+ size_t mTaskCount GUARDED_BY(mLock) = 0;
+ std::condition_variable mCv;
+};
+
+class RemoteAccessServiceUnitTest : public ::testing::Test {
+ public:
+ virtual void SetUp() override {
+ mGrpcWakeupClientStub = std::make_unique<MockGrpcClientStub>();
+ mService = ndk::SharedRefBase::make<RemoteAccessService>(mGrpcWakeupClientStub.get());
+ }
+
+ MockGrpcClientStub* getGrpcWakeupClientStub() { return mGrpcWakeupClientStub.get(); }
+
+ RemoteAccessService* getService() { return mService.get(); }
+
+ void setRetryWaitInMs(size_t retryWaitInMs) { mService->setRetryWaitInMs(retryWaitInMs); }
+
+ ScopedAStatus getDeviceIdWithClient(IVhalClient& vhalClient, std::string* deviceId) {
+ return mService->getDeviceIdWithClient(vhalClient, deviceId);
+ }
+
+ private:
+ std::unique_ptr<MockGrpcClientStub> mGrpcWakeupClientStub;
+ std::shared_ptr<RemoteAccessService> mService;
+};
+
+TEST_F(RemoteAccessServiceUnitTest, TestGetWakeupServiceName) {
+ std::string serviceName;
+
+ ScopedAStatus status = getService()->getWakeupServiceName(&serviceName);
+
+ EXPECT_TRUE(status.isOk());
+ EXPECT_EQ(serviceName, "com.google.vehicle.wakeup");
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestNotifyApStateChangeWakeupRequired) {
+ bool isWakeupRequired = false;
+ EXPECT_CALL(*getGrpcWakeupClientStub(), NotifyWakeupRequired)
+ .WillOnce([&isWakeupRequired]([[maybe_unused]] ClientContext* context,
+ const NotifyWakeupRequiredRequest& request,
+ [[maybe_unused]] NotifyWakeupRequiredResponse* response) {
+ isWakeupRequired = request.iswakeuprequired();
+ return Status();
+ });
+
+ ApState newState = {
+ .isWakeupRequired = true,
+ };
+ ScopedAStatus status = getService()->notifyApStateChange(newState);
+
+ EXPECT_TRUE(status.isOk());
+ EXPECT_TRUE(isWakeupRequired);
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasks) {
+ GetRemoteTasksResponse response1;
+ std::vector<uint8_t> testData = {0xde, 0xad, 0xbe, 0xef};
+ response1.set_clientid("1");
+ response1.set_data(testData.data(), testData.size());
+ GetRemoteTasksResponse response2;
+ response2.set_clientid("2");
+ std::shared_ptr<FakeRemoteTaskCallback> callback =
+ ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
+
+ ON_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw)
+ .WillByDefault(
+ [response1, response2]([[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetRemoteTasksRequest& request) {
+ // mockReader ownership will be transferred to the client so we don't own it
+ // here.
+ MockClientReader<GetRemoteTasksResponse>* mockClientReader =
+ new MockClientReader<GetRemoteTasksResponse>();
+ EXPECT_CALL(*mockClientReader, Finish()).WillOnce(Return(Status::OK));
+ EXPECT_CALL(*mockClientReader, Read(_))
+ .WillOnce(DoAll(SetArgPointee<0>(response1), Return(true)))
+ .WillOnce(DoAll(SetArgPointee<0>(response2), Return(true)))
+ .WillRepeatedly(Return(false));
+ return mockClientReader;
+ });
+
+ getService()->setRemoteTaskCallback(callback);
+ // Start the long live connection to receive tasks.
+ ApState newState = {
+ .isReadyForRemoteTask = true,
+ };
+ ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
+
+ ASSERT_TRUE(callback->wait(/*taskCount=*/2, /*timeoutInSec=*/10))
+ << "Did not receive enough tasks";
+ EXPECT_EQ(callback->getData("1"), testData);
+ EXPECT_EQ(callback->getData("2"), std::vector<uint8_t>());
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasksRetryConnection) {
+ GetRemoteTasksResponse response;
+ std::shared_ptr<FakeRemoteTaskCallback> callback =
+ ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
+
+ ON_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw)
+ .WillByDefault([response]([[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetRemoteTasksRequest& request) {
+ // mockReader ownership will be transferred to the client so we don't own it here.
+ MockClientReader<GetRemoteTasksResponse>* mockClientReader =
+ new MockClientReader<GetRemoteTasksResponse>();
+ EXPECT_CALL(*mockClientReader, Finish()).WillOnce(Return(Status::OK));
+ // Connection fails after receiving one task. Should retry after some time.
+ EXPECT_CALL(*mockClientReader, Read(_))
+ .WillOnce(DoAll(SetArgPointee<0>(response), Return(true)))
+ .WillRepeatedly(Return(false));
+ return mockClientReader;
+ });
+
+ getService()->setRemoteTaskCallback(callback);
+ setRetryWaitInMs(100);
+ // Start the long live connection to receive tasks.
+ ApState newState = {
+ .isReadyForRemoteTask = true,
+ };
+ ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
+
+ ASSERT_TRUE(callback->wait(/*taskCount=*/2, /*timeoutInSec=*/10))
+ << "Did not receive enough tasks";
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasksDefaultNotReady) {
+ GetRemoteTasksResponse response1;
+ std::vector<uint8_t> testData = {0xde, 0xad, 0xbe, 0xef};
+ response1.set_clientid("1");
+ response1.set_data(testData.data(), testData.size());
+ GetRemoteTasksResponse response2;
+ response2.set_clientid("2");
+ std::shared_ptr<FakeRemoteTaskCallback> callback =
+ ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
+
+ EXPECT_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw).Times(0);
+
+ // Default state is not ready for remote tasks, so no callback will be called.
+ getService()->setRemoteTaskCallback(callback);
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(100));
+}
+
+TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasksNotReadyAfterReady) {
+ GetRemoteTasksResponse response1;
+ std::vector<uint8_t> testData = {0xde, 0xad, 0xbe, 0xef};
+ response1.set_clientid("1");
+ response1.set_data(testData.data(), testData.size());
+ GetRemoteTasksResponse response2;
+ response2.set_clientid("2");
+ std::shared_ptr<FakeRemoteTaskCallback> callback =
+ ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
+
+ ON_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw)
+ .WillByDefault(
+ [response1, response2]([[maybe_unused]] ClientContext* context,
+ [[maybe_unused]] const GetRemoteTasksRequest& request) {
+ // mockReader ownership will be transferred to the client so we don't own it
+ // here.
+ MockClientReader<GetRemoteTasksResponse>* mockClientReader =
+ new MockClientReader<GetRemoteTasksResponse>();
+ EXPECT_CALL(*mockClientReader, Finish()).WillOnce(Return(Status::OK));
+ EXPECT_CALL(*mockClientReader, Read(_))
+ .WillOnce(DoAll(SetArgPointee<0>(response1), Return(true)))
+ .WillOnce(DoAll(SetArgPointee<0>(response2), Return(true)))
+ .WillRepeatedly(Return(false));
+ return mockClientReader;
+ });
+ // Should only be called once when is is ready for remote task.
+ EXPECT_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw).Times(1);
+
+ getService()->setRemoteTaskCallback(callback);
+ setRetryWaitInMs(100);
+ // Start the long live connection to receive tasks.
+ ApState newState = {
+ .isReadyForRemoteTask = true,
+ };
+ ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
+ ASSERT_TRUE(callback->wait(/*taskCount=*/2, /*timeoutInSec=*/10))
+ << "Did not receive enough tasks";
+
+ // Stop the long live connection.
+ newState.isReadyForRemoteTask = false;
+ ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
+
+ // Wait for the retry delay, but the loop should already exit.
+ std::this_thread::sleep_for(std::chrono::milliseconds(150));
+}
+
+TEST_F(RemoteAccessServiceUnitTest, testGetDeviceId) {
+ std::string deviceId;
+
+ FakeVhalClient vhalClient;
+
+ ASSERT_TRUE(getDeviceIdWithClient(vhalClient, &deviceId).isOk());
+ ASSERT_EQ(deviceId, kTestVin);
+}
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/impl/default/client/Android.bp b/automotive/remoteaccess/impl/default/client/Android.bp
deleted file mode 100644
index 6327637..0000000
--- a/automotive/remoteaccess/impl/default/client/Android.bp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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: ["Android-Apache-2.0"],
-}
-
-cc_binary {
- name: "android.hardware.automotive.remoteaccess@V1-default-service",
- vendor: true,
- vintf_fragments: ["remoteaccess-default-service.xml"],
- init_rc: ["remoteaccess-default-service.rc"],
- relative_install_path: "hw",
- srcs: ["src/RemoteAccessImpl.cpp"],
- whole_static_libs: [
- "RemoteAccessService",
- ],
- shared_libs: [
- "libbinder_ndk",
- "liblog",
- "libutils",
- "libgrpc++",
- "libprotobuf-cpp-full",
- ],
- cflags: [
- "-Wno-unused-parameter",
- ],
-}
-
-cc_library {
- name: "RemoteAccessService",
- vendor: true,
- local_include_dirs: ["include"],
- export_include_dirs: ["include"],
- srcs: [
- "src/RemoteAccessService.cpp",
- ],
- whole_static_libs: [
- "android.hardware.automotive.remoteaccess-V1-ndk",
- "wakeup_client_protos",
- ],
- shared_libs: [
- "libbase",
- "libbinder_ndk",
- "liblog",
- "libutils",
- "libgrpc++",
- "libprotobuf-cpp-full",
- ],
- cflags: [
- "-Wno-unused-parameter",
- ],
-}
diff --git a/automotive/remoteaccess/impl/default/client/include/RemoteAccessService.h b/automotive/remoteaccess/impl/default/client/include/RemoteAccessService.h
deleted file mode 100644
index 806440a..0000000
--- a/automotive/remoteaccess/impl/default/client/include/RemoteAccessService.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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/automotive/remoteaccess/ApState.h>
-#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteAccess.h>
-#include <aidl/android/hardware/automotive/remoteaccess/IRemoteTaskCallback.h>
-#include <android-base/thread_annotations.h>
-#include <wakeup_client.grpc.pb.h>
-
-#include <string>
-#include <thread>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace remoteaccess {
-
-class RemoteAccessService
- : public aidl::android::hardware::automotive::remoteaccess::BnRemoteAccess {
- public:
- explicit RemoteAccessService(WakeupClient::StubInterface* grpcStub);
-
- ~RemoteAccessService();
-
- ndk::ScopedAStatus getDeviceId(std::string* deviceId) override;
-
- ndk::ScopedAStatus getWakeupServiceName(std::string* wakeupServiceName) override;
-
- ndk::ScopedAStatus setRemoteTaskCallback(
- const std::shared_ptr<
- aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback>&
- callback) override;
-
- ndk::ScopedAStatus clearRemoteTaskCallback() override;
-
- ndk::ScopedAStatus notifyApStateChange(
- const aidl::android::hardware::automotive::remoteaccess::ApState& newState) override;
-
- private:
- // For testing.
- friend class RemoteAccessServiceUnitTest;
-
- WakeupClient::StubInterface* mGrpcStub;
- std::thread mThread;
- std::mutex mLock;
- std::condition_variable mCv;
- std::shared_ptr<aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback>
- mRemoteTaskCallback GUARDED_BY(mLock);
- std::unique_ptr<grpc::ClientContext> mGetRemoteTasksContext GUARDED_BY(mLock);
- // Associated with mCv to notify the task loop to stop waiting and exit.
- bool mTaskWaitStopped GUARDED_BY(mLock);
- // A mutex to make sure startTaskLoop does not overlap with stopTaskLoop.
- std::mutex mStartStopTaskLoopLock;
- bool mTaskLoopRunning GUARDED_BY(mStartStopTaskLoopLock);
- // Default wait time before retry connecting to remote access client is 10s.
- size_t mRetryWaitInMs = 10'000;
-
- void runTaskLoop();
- void maybeStartTaskLoop();
- void maybeStopTaskLoop();
-
- void setRetryWaitInMs(size_t retryWaitInMs) { mRetryWaitInMs = retryWaitInMs; }
-};
-
-} // namespace remoteaccess
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/remoteaccess/impl/default/client/src/RemoteAccessImpl.cpp b/automotive/remoteaccess/impl/default/client/src/RemoteAccessImpl.cpp
deleted file mode 100644
index 7431898..0000000
--- a/automotive/remoteaccess/impl/default/client/src/RemoteAccessImpl.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 "RemoteAccessImpl"
-
-#include "RemoteAccessService.h"
-
-#include <android/binder_manager.h>
-#include <android/binder_process.h>
-#include <utils/Log.h>
-
-int main(int /* argc */, char* /* argv */[]) {
- ALOGI("Registering RemoteAccessService as service...");
-
- // TODO(b/241483300): Create GrpcClientStub here.
- auto service = ndk::SharedRefBase::make<
- android::hardware::automotive::remoteaccess::RemoteAccessService>(nullptr);
-
- binder_exception_t err = AServiceManager_addService(
- service->asBinder().get(), "android.hardware.automotive.remote.IRemoteAccess/default");
- if (err != EX_NONE) {
- ALOGE("failed to register android.hardware.automotive.remote.IRemoteAccess service, "
- "exception: %d",
- err);
- return 1;
- }
-
- if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
- ALOGE("%s", "failed to set thread pool max thread count");
- return 1;
- }
- ABinderProcess_startThreadPool();
-
- ALOGI("RemoteAccess service Ready");
-
- ABinderProcess_joinThreadPool();
-
- ALOGW("Should not reach here");
-
- return 0;
-}
diff --git a/automotive/remoteaccess/impl/default/client/src/RemoteAccessService.cpp b/automotive/remoteaccess/impl/default/client/src/RemoteAccessService.cpp
deleted file mode 100644
index 6b97840..0000000
--- a/automotive/remoteaccess/impl/default/client/src/RemoteAccessService.cpp
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
- * 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 "RemoteAccessService.h"
-
-#include <android/binder_status.h>
-#include <grpc++/grpc++.h>
-#include <utils/Log.h>
-#include <chrono>
-#include <thread>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace remoteaccess {
-
-namespace {
-
-using ::aidl::android::hardware::automotive::remoteaccess::ApState;
-using ::aidl::android::hardware::automotive::remoteaccess::IRemoteTaskCallback;
-using ::android::base::ScopedLockAssertion;
-using ::grpc::ClientContext;
-using ::grpc::ClientReaderInterface;
-using ::grpc::Status;
-using ::grpc::StatusCode;
-using ::ndk::ScopedAStatus;
-
-const std::string WAKEUP_SERVICE_NAME = "com.google.vehicle.wakeup";
-
-std::vector<uint8_t> stringToBytes(const std::string& s) {
- const char* data = s.data();
- return std::vector<uint8_t>(data, data + s.size());
-}
-
-ScopedAStatus rpcStatusToScopedAStatus(const Status& status, const std::string& errorMsg) {
- return ScopedAStatus::fromServiceSpecificErrorWithMessage(
- status.error_code(), (errorMsg + ", error: " + status.error_message()).c_str());
-}
-
-} // namespace
-
-RemoteAccessService::RemoteAccessService(WakeupClient::StubInterface* grpcStub)
- : mGrpcStub(grpcStub){};
-
-RemoteAccessService::~RemoteAccessService() {
- maybeStopTaskLoop();
-}
-
-void RemoteAccessService::maybeStartTaskLoop() {
- std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
- if (mTaskLoopRunning) {
- return;
- }
-
- mThread = std::thread([this]() { runTaskLoop(); });
-
- mTaskLoopRunning = true;
-}
-
-void RemoteAccessService::maybeStopTaskLoop() {
- std::lock_guard<std::mutex> lockGuard(mStartStopTaskLoopLock);
- if (!mTaskLoopRunning) {
- return;
- }
-
- {
- std::lock_guard<std::mutex> lockGuard(mLock);
- // Try to stop the reading stream.
- if (mGetRemoteTasksContext) {
- mGetRemoteTasksContext->TryCancel();
- mGetRemoteTasksContext.reset();
- }
- mTaskWaitStopped = true;
- mCv.notify_all();
- }
- if (mThread.joinable()) {
- mThread.join();
- }
-
- mTaskLoopRunning = false;
-}
-
-void RemoteAccessService::runTaskLoop() {
- GetRemoteTasksRequest request = {};
- std::unique_ptr<ClientReaderInterface<GetRemoteTasksResponse>> reader;
- while (true) {
- {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mGetRemoteTasksContext.reset(new ClientContext());
- reader = mGrpcStub->GetRemoteTasks(mGetRemoteTasksContext.get(), request);
- }
- GetRemoteTasksResponse response;
- while (reader->Read(&response)) {
- std::shared_ptr<IRemoteTaskCallback> callback;
- {
- std::lock_guard<std::mutex> lockGuard(mLock);
- callback = mRemoteTaskCallback;
- }
- if (callback == nullptr) {
- continue;
- }
- ScopedAStatus callbackStatus = callback->onRemoteTaskRequested(
- response.clientid(), stringToBytes(response.data()));
- if (!callbackStatus.isOk()) {
- ALOGE("Failed to call onRemoteTaskRequested callback, status: %d, message: %s",
- callbackStatus.getStatus(), callbackStatus.getMessage());
- }
- }
- Status status = reader->Finish();
-
- ALOGE("GetRemoteTasks stream breaks, code: %d, message: %s, sleeping for 10s and retry",
- status.error_code(), status.error_message().c_str());
- // The long lasting connection should not return. But if the server returns, retry after
- // 10s.
- {
- std::unique_lock lk(mLock);
- if (mCv.wait_for(lk, std::chrono::milliseconds(mRetryWaitInMs), [this] {
- ScopedLockAssertion lockAssertion(mLock);
- return mTaskWaitStopped;
- })) {
- // If the stopped flag is set, we are quitting, exit the loop.
- break;
- }
- }
- }
-}
-
-ScopedAStatus RemoteAccessService::getDeviceId(std::string* deviceId) {
- // TODO(b/241483300): Call VHAL to get VIN.
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::getWakeupServiceName(std::string* wakeupServiceName) {
- *wakeupServiceName = WAKEUP_SERVICE_NAME;
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::setRemoteTaskCallback(
- [[maybe_unused]] const std::shared_ptr<IRemoteTaskCallback>& callback) {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mRemoteTaskCallback = callback;
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::clearRemoteTaskCallback() {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mRemoteTaskCallback.reset();
- return ScopedAStatus::ok();
-}
-
-ScopedAStatus RemoteAccessService::notifyApStateChange(const ApState& newState) {
- ClientContext context;
- NotifyWakeupRequiredRequest request = {};
- request.set_iswakeuprequired(newState.isWakeupRequired);
- NotifyWakeupRequiredResponse response = {};
- Status status = mGrpcStub->NotifyWakeupRequired(&context, request, &response);
- if (!status.ok()) {
- return rpcStatusToScopedAStatus(status, "Failed to notify isWakeupRequired");
- }
-
- if (newState.isReadyForRemoteTask) {
- maybeStartTaskLoop();
- } else {
- maybeStopTaskLoop();
- }
- return ScopedAStatus::ok();
-}
-
-} // namespace remoteaccess
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/remoteaccess/impl/default/proto/Android.bp b/automotive/remoteaccess/impl/default/proto/Android.bp
deleted file mode 100644
index 31b9d0e..0000000
--- a/automotive/remoteaccess/impl/default/proto/Android.bp
+++ /dev/null
@@ -1,81 +0,0 @@
-// 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"],
-}
-
-genrule {
- name: "wakeup_client_pb_h",
- tools: [
- "aprotoc",
- "protoc-gen-grpc-cpp-plugin",
- ],
- cmd: "$(location aprotoc) -I$$(dirname $(in)) -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
- srcs: [
- "wakeup_client.proto",
- ],
- out: [
- "wakeup_client.pb.h",
- "wakeup_client.grpc.pb.h",
- ],
- vendor: true,
-}
-
-genrule {
- name: "wakeup_client_pb_cc",
- tools: [
- "aprotoc",
- "protoc-gen-grpc-cpp-plugin",
- ],
- cmd: "$(location aprotoc) -I$$(dirname $(in)) -Iexternal/protobuf/src --plugin=protoc-gen-grpc=$(location protoc-gen-grpc-cpp-plugin) $(in) --grpc_out=$(genDir) --cpp_out=$(genDir)",
- srcs: [
- "wakeup_client.proto",
- ],
- out: [
- "wakeup_client.pb.cc",
- "wakeup_client.grpc.pb.cc",
- ],
- vendor: true,
-}
-
-cc_library_static {
- name: "wakeup_client_protos",
- vendor: true,
- host_supported: true,
- include_dirs: [
- "external/protobuf/src",
- ],
- generated_headers: [
- "wakeup_client_pb_h",
- ],
- export_generated_headers: [
- "wakeup_client_pb_h",
- ],
- generated_sources: [
- "wakeup_client_pb_cc",
- ],
- shared_libs: [
- "libgrpc++",
- "libprotobuf-cpp-full",
- ],
- cflags: [
- "-Wno-unused-parameter",
- ],
-}
diff --git a/automotive/remoteaccess/impl/default/test/Android.bp b/automotive/remoteaccess/impl/default/test/Android.bp
deleted file mode 100644
index e92440f..0000000
--- a/automotive/remoteaccess/impl/default/test/Android.bp
+++ /dev/null
@@ -1,43 +0,0 @@
-// 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: ["Android-Apache-2.0"],
-}
-
-cc_test {
- name: "RemoteAccessServiceUnitTest",
- vendor: true,
- srcs: ["*.cpp"],
- whole_static_libs: [
- "RemoteAccessService",
- ],
- shared_libs: [
- "libbinder_ndk",
- "liblog",
- "libutils",
- "libgrpc++",
- "libprotobuf-cpp-full",
- ],
- // libgrpc++.so is installed as root, require root to access it.
- require_root: true,
- static_libs: [
- "libgtest",
- "libgmock",
- ],
- cflags: [
- "-Wno-unused-parameter",
- ],
- test_suites: ["device-tests"],
-}
diff --git a/automotive/remoteaccess/impl/default/test/RemoteAccessServiceUnitTest.cpp b/automotive/remoteaccess/impl/default/test/RemoteAccessServiceUnitTest.cpp
deleted file mode 100644
index 11523f6..0000000
--- a/automotive/remoteaccess/impl/default/test/RemoteAccessServiceUnitTest.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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 "RemoteAccessService.h"
-
-#include <aidl/android/hardware/automotive/remoteaccess/ApState.h>
-#include <aidl/android/hardware/automotive/remoteaccess/BnRemoteTaskCallback.h>
-#include <gmock/gmock.h>
-#include <grpcpp/test/mock_stream.h>
-#include <gtest/gtest.h>
-#include <wakeup_client.grpc.pb.h>
-#include <chrono>
-#include <thread>
-
-namespace android {
-namespace hardware {
-namespace automotive {
-namespace remoteaccess {
-
-using ::android::base::ScopedLockAssertion;
-
-using ::aidl::android::hardware::automotive::remoteaccess::ApState;
-using ::aidl::android::hardware::automotive::remoteaccess::BnRemoteTaskCallback;
-
-using ::grpc::ClientAsyncReaderInterface;
-using ::grpc::ClientAsyncResponseReaderInterface;
-using ::grpc::ClientContext;
-using ::grpc::ClientReader;
-using ::grpc::ClientReaderInterface;
-using ::grpc::CompletionQueue;
-using ::grpc::Status;
-using ::grpc::testing::MockClientReader;
-using ::ndk::ScopedAStatus;
-using ::testing::_;
-using ::testing::DoAll;
-using ::testing::Return;
-using ::testing::SetArgPointee;
-
-class MockGrpcClientStub : public WakeupClient::StubInterface {
- public:
- MOCK_METHOD(ClientReaderInterface<GetRemoteTasksResponse>*, GetRemoteTasksRaw,
- (ClientContext * context, const GetRemoteTasksRequest& request));
- MOCK_METHOD(Status, NotifyWakeupRequired,
- (ClientContext * context, const NotifyWakeupRequiredRequest& request,
- NotifyWakeupRequiredResponse* response));
- // Async methods which we do not care.
- MOCK_METHOD(ClientAsyncReaderInterface<GetRemoteTasksResponse>*, AsyncGetRemoteTasksRaw,
- (ClientContext * context, const GetRemoteTasksRequest& request, CompletionQueue* cq,
- void* tag));
- MOCK_METHOD(ClientAsyncReaderInterface<GetRemoteTasksResponse>*, PrepareAsyncGetRemoteTasksRaw,
- (ClientContext * context, const GetRemoteTasksRequest& request,
- CompletionQueue* cq));
- MOCK_METHOD(ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>*,
- AsyncNotifyWakeupRequiredRaw,
- (ClientContext * context, const NotifyWakeupRequiredRequest& request,
- CompletionQueue* cq));
- MOCK_METHOD(ClientAsyncResponseReaderInterface<NotifyWakeupRequiredResponse>*,
- PrepareAsyncNotifyWakeupRequiredRaw,
- (ClientContext * context, const NotifyWakeupRequiredRequest& request,
- CompletionQueue* cq));
-};
-
-class FakeRemoteTaskCallback : public BnRemoteTaskCallback {
- public:
- ScopedAStatus onRemoteTaskRequested(const std::string& clientId,
- const std::vector<uint8_t>& data) override {
- std::lock_guard<std::mutex> lockGuard(mLock);
- mDataByClientId[clientId] = data;
- mTaskCount++;
- mCv.notify_all();
- return ScopedAStatus::ok();
- }
-
- std::vector<uint8_t> getData(const std::string& clientId) { return mDataByClientId[clientId]; }
-
- bool wait(size_t taskCount, size_t timeoutInSec) {
- std::unique_lock<std::mutex> lock(mLock);
- return mCv.wait_for(lock, std::chrono::seconds(timeoutInSec), [taskCount, this] {
- ScopedLockAssertion lockAssertion(mLock);
- return mTaskCount >= taskCount;
- });
- }
-
- private:
- std::mutex mLock;
- std::unordered_map<std::string, std::vector<uint8_t>> mDataByClientId GUARDED_BY(mLock);
- size_t mTaskCount GUARDED_BY(mLock) = 0;
- std::condition_variable mCv;
-};
-
-class RemoteAccessServiceUnitTest : public ::testing::Test {
- public:
- virtual void SetUp() override {
- mGrpcWakeupClientStub = std::make_unique<MockGrpcClientStub>();
- mService = ndk::SharedRefBase::make<RemoteAccessService>(mGrpcWakeupClientStub.get());
- }
-
- MockGrpcClientStub* getGrpcWakeupClientStub() { return mGrpcWakeupClientStub.get(); }
-
- RemoteAccessService* getService() { return mService.get(); }
-
- void setRetryWaitInMs(size_t retryWaitInMs) { mService->setRetryWaitInMs(retryWaitInMs); }
-
- private:
- std::unique_ptr<MockGrpcClientStub> mGrpcWakeupClientStub;
- std::shared_ptr<RemoteAccessService> mService;
- MockClientReader<GetRemoteTasksResponse>* mMockTaskReader;
-};
-
-TEST_F(RemoteAccessServiceUnitTest, TestGetWakeupServiceName) {
- std::string serviceName;
-
- ScopedAStatus status = getService()->getWakeupServiceName(&serviceName);
-
- EXPECT_TRUE(status.isOk());
- EXPECT_EQ(serviceName, "com.google.vehicle.wakeup");
-}
-
-TEST_F(RemoteAccessServiceUnitTest, TestNotifyApStateChangeWakeupRequired) {
- bool isWakeupRequired = false;
- EXPECT_CALL(*getGrpcWakeupClientStub(), NotifyWakeupRequired)
- .WillOnce([&isWakeupRequired]([[maybe_unused]] ClientContext* context,
- const NotifyWakeupRequiredRequest& request,
- [[maybe_unused]] NotifyWakeupRequiredResponse* response) {
- isWakeupRequired = request.iswakeuprequired();
- return Status();
- });
-
- ApState newState = {
- .isWakeupRequired = true,
- };
- ScopedAStatus status = getService()->notifyApStateChange(newState);
-
- EXPECT_TRUE(status.isOk());
- EXPECT_TRUE(isWakeupRequired);
-}
-
-TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasks) {
- GetRemoteTasksResponse response1;
- std::vector<uint8_t> testData = {0xde, 0xad, 0xbe, 0xef};
- response1.set_clientid("1");
- response1.set_data(testData.data(), testData.size());
- GetRemoteTasksResponse response2;
- response2.set_clientid("2");
- std::shared_ptr<FakeRemoteTaskCallback> callback =
- ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
-
- ON_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw)
- .WillByDefault(
- [response1, response2]([[maybe_unused]] ClientContext* context,
- [[maybe_unused]] const GetRemoteTasksRequest& request) {
- // mockReader ownership will be transferred to the client so we don't own it
- // here.
- MockClientReader<GetRemoteTasksResponse>* mockClientReader =
- new MockClientReader<GetRemoteTasksResponse>();
- EXPECT_CALL(*mockClientReader, Finish()).WillOnce(Return(Status::OK));
- EXPECT_CALL(*mockClientReader, Read(_))
- .WillOnce(DoAll(SetArgPointee<0>(response1), Return(true)))
- .WillOnce(DoAll(SetArgPointee<0>(response2), Return(true)))
- .WillRepeatedly(Return(false));
- return mockClientReader;
- });
-
- getService()->setRemoteTaskCallback(callback);
- // Start the long live connection to receive tasks.
- ApState newState = {
- .isReadyForRemoteTask = true,
- };
- ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
-
- ASSERT_TRUE(callback->wait(/*taskCount=*/2, /*timeoutInSec=*/10))
- << "Did not receive enough tasks";
- EXPECT_EQ(callback->getData("1"), testData);
- EXPECT_EQ(callback->getData("2"), std::vector<uint8_t>());
-}
-
-TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasksRetryConnection) {
- GetRemoteTasksResponse response;
- std::shared_ptr<FakeRemoteTaskCallback> callback =
- ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
-
- ON_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw)
- .WillByDefault([response]([[maybe_unused]] ClientContext* context,
- [[maybe_unused]] const GetRemoteTasksRequest& request) {
- // mockReader ownership will be transferred to the client so we don't own it here.
- MockClientReader<GetRemoteTasksResponse>* mockClientReader =
- new MockClientReader<GetRemoteTasksResponse>();
- EXPECT_CALL(*mockClientReader, Finish()).WillOnce(Return(Status::OK));
- // Connection fails after receiving one task. Should retry after some time.
- EXPECT_CALL(*mockClientReader, Read(_))
- .WillOnce(DoAll(SetArgPointee<0>(response), Return(true)))
- .WillRepeatedly(Return(false));
- return mockClientReader;
- });
-
- getService()->setRemoteTaskCallback(callback);
- setRetryWaitInMs(100);
- // Start the long live connection to receive tasks.
- ApState newState = {
- .isReadyForRemoteTask = true,
- };
- ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
-
- ASSERT_TRUE(callback->wait(/*taskCount=*/2, /*timeoutInSec=*/10))
- << "Did not receive enough tasks";
-}
-
-TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasksDefaultNotReady) {
- GetRemoteTasksResponse response1;
- std::vector<uint8_t> testData = {0xde, 0xad, 0xbe, 0xef};
- response1.set_clientid("1");
- response1.set_data(testData.data(), testData.size());
- GetRemoteTasksResponse response2;
- response2.set_clientid("2");
- std::shared_ptr<FakeRemoteTaskCallback> callback =
- ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
-
- EXPECT_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw).Times(0);
-
- // Default state is not ready for remote tasks, so no callback will be called.
- getService()->setRemoteTaskCallback(callback);
-
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
-}
-
-TEST_F(RemoteAccessServiceUnitTest, TestGetRemoteTasksNotReadyAfterReady) {
- GetRemoteTasksResponse response1;
- std::vector<uint8_t> testData = {0xde, 0xad, 0xbe, 0xef};
- response1.set_clientid("1");
- response1.set_data(testData.data(), testData.size());
- GetRemoteTasksResponse response2;
- response2.set_clientid("2");
- std::shared_ptr<FakeRemoteTaskCallback> callback =
- ndk::SharedRefBase::make<FakeRemoteTaskCallback>();
-
- ON_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw)
- .WillByDefault(
- [response1, response2]([[maybe_unused]] ClientContext* context,
- [[maybe_unused]] const GetRemoteTasksRequest& request) {
- // mockReader ownership will be transferred to the client so we don't own it
- // here.
- MockClientReader<GetRemoteTasksResponse>* mockClientReader =
- new MockClientReader<GetRemoteTasksResponse>();
- EXPECT_CALL(*mockClientReader, Finish()).WillOnce(Return(Status::OK));
- EXPECT_CALL(*mockClientReader, Read(_))
- .WillOnce(DoAll(SetArgPointee<0>(response1), Return(true)))
- .WillOnce(DoAll(SetArgPointee<0>(response2), Return(true)))
- .WillRepeatedly(Return(false));
- return mockClientReader;
- });
- // Should only be called once when is is ready for remote task.
- EXPECT_CALL(*getGrpcWakeupClientStub(), GetRemoteTasksRaw).Times(1);
-
- getService()->setRemoteTaskCallback(callback);
- setRetryWaitInMs(100);
- // Start the long live connection to receive tasks.
- ApState newState = {
- .isReadyForRemoteTask = true,
- };
- ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
- ASSERT_TRUE(callback->wait(/*taskCount=*/2, /*timeoutInSec=*/10))
- << "Did not receive enough tasks";
-
- // Stop the long live connection.
- newState.isReadyForRemoteTask = false;
- ASSERT_TRUE(getService()->notifyApStateChange(newState).isOk());
-
- // Wait for the retry delay, but the loop should already exit.
- std::this_thread::sleep_for(std::chrono::milliseconds(150));
-}
-
-} // namespace remoteaccess
-} // namespace automotive
-} // namespace hardware
-} // namespace android
diff --git a/automotive/remoteaccess/test_grpc_server/README.md b/automotive/remoteaccess/test_grpc_server/README.md
new file mode 100644
index 0000000..6bc1829
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/README.md
@@ -0,0 +1,314 @@
+# Test GRPC Server.
+
+A test GRPC server that implements wakeup_client.proto. This test server acts
+as a reference implementation for a remote wakeup client running on TCU. The
+test server does not communicate with any actual network server. It has the
+following behavior:
+
+* It starts a GRPC server on 'DGRPC_SERVICE_ADDRESS' compile flag which is
+ localhost:50051. The GRPC server provides the service according to
+ hardware/interfaces/automotive/remoteaccess/hal/default/proto/wakeup_client.proto.
+
+ In real implementation, DGRPC_SERVICE_ADDRESS can be specified to any IP
+ address where the TCU can be exposed to Application Processor. The default
+ remote access HAL implementation
+ (hardware/interfaces/automotive/remoteaccess/hal/default/Android.bp) also
+ uses DGRPC_SERVICE_ADDRESS to find this GRPC server, so it must have the
+ same IP address.
+
+* It generates a fake task using FakeTaskGenerator every 'kTaskIntervalInMs' ms.
+
+ In real implementation, it should receive task from the remote server.
+
+* Each fake task has an increasing unique client ID. The task data is always
+ what's defined for 'DATA' variable.
+
+ In real implementation, the client ID and task data should come from the
+ remote server.
+
+* The generated tasks are put into a task queue which is a priority queue sorted
+ by task received time.
+
+ In real implementation, if the server provides a task timestamp, then this
+ queue can be sorted by that task timestamp instead.
+
+* When the Application processor is started, the remote access HAL running on
+ Android will call 'GetRemoteTasks' to establish a long-live connection. This
+ connection is used to deliver all task data from remote wakeup client to
+ remote access HAL, which eventually to car service and applications.
+
+ When the 'GetRemoteTasks' is called, the wakeup client must send all the
+ pending tasks through the 'ServerWriter'. If no task is pending, then it must
+ block and wait for a new task to arrive.
+
+ If one task data fails to be sent through the channel, it likely means
+ the other side (Application processor) is shutting down or has closed the
+ channel. The wakeup client must put the task back to the pending queue and
+ wait for a new 'GetRemoteTasks' request to retry sending the task.
+
+* When a new task arrives, if 'WakeupRequired' is true, then try to wakeup
+ the Application Processor by sending a specific CAN message. It is possible that
+ the waking up is already in progress. This is okay since Vehicle Processor
+ should ignore wakeup message if a wakeup is already in progress.
+
+* When 'WakeupRequired' is updated from false to true, if there are unexpired
+ pending tasks in the task queue, try to wakeup Application Processor.
+
+ This is to handle the situation when a task arrives while the device is
+ shutting down. During the device shutdown, the channel to deliver the remote
+ tasks to Application Processor is shutdown so the new task will be added to the
+ task queue. 'WakeupRequired' will be set to false to prevent the wakeup
+ message preventing the shutdown. After the shutdown is complete,
+ 'WakeupRequired' will be set to true and this wakeup client must try to wake
+ up the device again to execute the pending tasks.
+
+* Every pending task has a timeout: 'kTaskTimeoutInMs'. If the pending task
+ is not delivered to remote access HAL before the timeout (through
+ GetRemoteTasks), the task timed out and a warning message is logged.
+
+ In real implementation, this kTaskTimeoutInMs has to be set long enough to
+ allow an Android bootup to happen. 20s is a reasonable value. When a task
+ timed out, the wakeup client should also report to remote task server about
+ the task timeout failure.
+
+## How to build the test wakeup client
+
+* Under android root: `source build/envsetup.sh`
+
+* `lunch sdk_car_x86_64-userdebug`
+
+* `make -j TestWakeupClientServer`
+
+* `make -j ApPowerControlLib`
+
+## How to push the test wakeup client to a TCU which runs Android.
+
+* Make the target device writable:
+
+ `adb root`
+
+ `adb remount` (remount might take a while)
+
+ `adb reboot`
+
+ `adb root`
+
+ `adb remount`
+
+* Under android root: `cd $ANDROID_PRODUCT_OUT`
+
+* `adb push vendor/bin/TestWakeupClientServer /vendor/bin`
+
+* `adb push vendor/lib/ApPowerControlLib.so /vendor/lib`
+
+* `adb shell`
+
+* `su`
+
+* `/vendor/bin/TestWakeupClientServer`
+
+## How to build and test the test wakeup client using one car emulator.
+
+In this test setup we will use one car emulator
+(sdk_car_x86_64-userdebug). We assume both the TCU and the remote access HAL
+runs on the same Android system, and they communicate through local loopback
+interface.
+
+* Under android root, `source build/envsetup.sh`
+
+* `lunch sdk_car_x86_64-userdebug`
+
+* `m -j`
+
+* Run the emulator, the '-read-only' flag is required to run multiple instances:
+
+ `emulator -writable-system -read-only`
+
+* The android lunch target: sdk_car_x86_64-userdebug and
+ cf_x86_64_auto-userdebug already contains the default remote access HAL. For
+ other lunch target, you can add the default remote access HAL by adding
+ 'android.hardware.automotive.remoteaccess@V1-default-service' to
+ 'PRODUCT_PACKAGES' variable in mk file, see `device/generic/car/common/car.mk`
+ as example.
+
+ To verify whether remote access HAL is running, you can use the following
+ command to check:
+
+ `dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default`
+
+* Make the target device writable:
+
+ `adb root`
+
+ `adb remount` (remount might take a while)
+
+ `adb reboot`
+
+ `adb root`
+
+ `adb remount`
+
+* `make -j TestWakeupClientServer`
+
+* `adb push $ANDROID_PRODUCT_OUT/vendor/bin/TestWakeupClientServer /vendor/bin`
+
+* `adb shell`
+
+* `emulator_car_x86_64:/ # su`
+
+* `emulator_car_x86_64:/ # /vendor/bin/TestWakeupClientServer`
+
+* Remote access HAL should start by default when the car emulator starts. Now
+ the test wake up client should also be running and generating fake tasks.
+
+ Start a new session under android root
+
+ `source build/envsetup.sh`
+
+ `lunch sdk_car_x86_64-userdebug`
+
+ `adb shell`
+
+ `emulator_car_x86_64:/ # su`
+
+* Issue the command to start a simple debug callback that will capture all the
+ received tasks at the remote access HAL side:
+
+ `emulator_car_x86_64:/ # dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --start-debug-callback`
+
+* Issue the following debug command to remote access HAL to establish the
+ communication channel between it and the test wakeup client. This command
+ also notifies that wakeup is not required:
+
+ `emulator_car_x86_64:/ # dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --set-ap-state 1 0`
+
+* Wait for a while, issue the following command to show the received fake tasks:
+
+ `emulator_car_x86_64:/ # dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --show-task`
+
+ You should expect to see some received tasks printed out.
+
+* Simulate the Application Processor is shutting down by issuing the following
+ command:
+
+ `emulator_car_x86_64:/ # dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --set-ap-state 0 0`
+
+* Wait for a while, issue the following command to show received tasks again:
+
+ `emulator_car_x86_64:/ # dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --show-task`
+
+ You should expect to see no new tasks received since remote access HAL already
+ closed the communication channel.
+
+* Simulate the Application Processor is already shutdown and wake up is required
+ now:
+
+ `emulator_car_x86_64:/ # dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --set-ap-state 0 1`
+
+ Now you should expect to see the test wakeup client printing out messages
+ that it is trying to wake up application processor.
+
+* Simulate the Application Processor is waken up:
+
+ `emulator_car_x86_64:/ # dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --set-ap-state 1 0`
+
+* A new communication channel should have been established and all pending
+ non-expired tasks should be delivered to the remote access HAL.
+
+ `emulator_car_x86_64:/ # dumpsys android.hardware.automotive.remoteaccess.IRemoteAccess/default --show-task`
+
+* Now you can issue `ctrl c` on the first adb shell to stop the test wakeup
+ client.
+
+* After the test, you can use `ctrl D` to exit the adb shell.
+
+## How to build and test the test wakeup client using two car emulators.
+
+In this test case, we are going to use two car emulators, one as the
+Application Processor, one as the TCU.
+
+* Change the IP address to allow IP communication between different emulator
+ instances. For detail about why we change it this way, see [interconnecting
+ emulator instance](https://developer.android.com/studio/run/emulator-networking#connecting).
+
+ Change 'DGRPC_SERVICE_ADDRESS' in `[android_root]/hardware/interfaces/automotive/remoteaccess/test_grpc_server/impl/Android.bp` to
+ `10.0.2.15:50051`.
+
+ Change `DGRPC_SERVICE_ADDRESS` in '[android_root]/hardware/interfaces/automotive/remoteaccess/hal/defaut/Android.bp' to
+ `10.0.2.2:50051`.
+
+* Under android root: `source build/envsetup.sh`
+
+* `lunch sdk_car_x86_64-userdebug`
+
+* `m -j`
+
+* Start one car emulator as TCU
+
+ `emulator -writable-system -read-only`
+
+* Start a new shell session. Connect to the emulator's console,
+ see [Start and stop a console session](https://developer.android.com/studio/run/emulator-console#console-session)
+ for detail.
+
+ `telnet localhost 5554`
+
+* `auth auth_token` where auth_token must match the contents of the
+ `~/.emulator_console_auth_token` file.
+
+* `redir add tcp:50051:50051`
+
+* Exit the telnet session using 'ctrl-C'
+
+ Make the target device writable:
+
+ Under android root:
+
+ `source build/envsetup.sh`
+
+ `lunch sdk_car_x86_64-userdebug`
+
+ `adb root`
+
+ `adb remount` (remount might take a while)
+
+ `adb reboot`
+
+ `adb root`
+
+ `adb remount`
+
+* `make -j TestWakeupClientServer`
+
+* `adb push $ANDROID_PRODUCT_OUT/vendor/bin/TestWakeupClientServer /vendor/bin`
+
+* `adb shell`
+
+* `emulator_car_x86_64:/ # su`
+
+* `emulator_car_x86_64:/ # /vendor/bin/TestWakeupClientServer`
+
+* Start a new shell under android root, start another car emulator as the Application Processor:
+
+ `source build/envsetup.sh`
+
+ `lunch sdk_car_x86_64-userdebug`
+
+ `emulator -writable-system -read-only`
+
+* Open a new shell under android root:
+
+ `source build/envsetup.sh`
+
+ `lunch sdk_car_x86_64-userdebug`
+
+* Connect to adb shell for the application processor:
+
+ `adb -s emulator-5556 shell`
+
+ `emulator_car_x86_64:/ # su`
+
+* Follow the test instructions for one car emulator using the 'dumpsys'
+ commands.
+
+* After the test, you can use `ctrl D` to exit the adb shell.
diff --git a/automotive/remoteaccess/test_grpc_server/impl/Android.bp b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
new file mode 100644
index 0000000..152b528
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/Android.bp
@@ -0,0 +1,43 @@
+// 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_binary {
+ name: "TestWakeupClientServer",
+ vendor: true,
+ srcs: ["src/*.cpp"],
+ local_include_dirs: ["include"],
+ shared_libs: [
+ "libbase",
+ "libutils",
+ "libgrpc++",
+ "libprotobuf-cpp-full",
+ "//hardware/interfaces/automotive/remoteaccess/test_grpc_server/lib:ApPowerControlLib",
+ ],
+ whole_static_libs: [
+ "wakeup_client_protos",
+ ],
+ cflags: [
+ "-Wno-unused-parameter",
+ "-DGRPC_SERVICE_ADDRESS=\"localhost:50051\"",
+ ],
+}
diff --git a/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
new file mode 100644
index 0000000..6b86b35
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/include/TestWakeupClientServiceImpl.h
@@ -0,0 +1,139 @@
+/*
+ * 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 <android-base/thread_annotations.h>
+#include <utils/Looper.h>
+#include <wakeup_client.grpc.pb.h>
+#include <condition_variable>
+#include <mutex>
+#include <queue>
+#include <string>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+// A class to generate fake task for testing. Not required for real implementation. In real
+// implementation, the task should come from remote task server. This class is thread-safe.
+class FakeTaskGenerator final {
+ public:
+ GetRemoteTasksResponse generateTask();
+
+ private:
+ // Simulates the client ID for each task.
+ std::atomic<int> mCurrentClientId = 0;
+ constexpr static uint8_t DATA[] = {0xde, 0xad, 0xbe, 0xef};
+};
+
+struct TaskInfo {
+ // This is unique per-task. Note that a task might be popped and put back into the task queue,
+ // it will have a new task ID but the same clientId in the task data.
+ int taskId;
+ int64_t timestampInMs;
+ GetRemoteTasksResponse taskData;
+};
+
+struct TaskInfoComparator {
+ // We want the smallest timestamp and smallest task ID on top.
+ bool operator()(const TaskInfo& l, const TaskInfo& r) {
+ return l.timestampInMs > r.timestampInMs ||
+ (l.timestampInMs == r.timestampInMs && l.taskId > r.taskId);
+ }
+};
+
+// forward-declaration.
+class TaskQueue;
+
+class TaskTimeoutMessageHandler final : public android::MessageHandler {
+ public:
+ TaskTimeoutMessageHandler(TaskQueue* taskQueue);
+ void handleMessage(const android::Message& message) override;
+
+ private:
+ TaskQueue* mTaskQueue;
+};
+
+// TaskQueue is thread-safe.
+class TaskQueue final {
+ public:
+ TaskQueue();
+ ~TaskQueue();
+
+ void add(const GetRemoteTasksResponse& response);
+ std::optional<GetRemoteTasksResponse> maybePopOne();
+ void waitForTask();
+ void stopWait();
+ void handleTaskTimeout();
+ bool isEmpty();
+
+ private:
+ std::thread mCheckTaskTimeoutThread;
+ std::mutex mLock;
+ std::priority_queue<TaskInfo, std::vector<TaskInfo>, TaskInfoComparator> mTasks
+ GUARDED_BY(mLock);
+ // A variable to notify mTasks is not empty.
+ std::condition_variable mTasksNotEmptyCv;
+ bool mStopped GUARDED_BY(mLock);
+ android::sp<Looper> mLooper;
+ android::sp<TaskTimeoutMessageHandler> mTaskTimeoutMessageHandler;
+ std::atomic<int> mTaskIdCounter = 0;
+
+ void checkForTestTimeoutLoop();
+ void waitForTaskWithLock(std::unique_lock<std::mutex>& lock);
+};
+
+class TestWakeupClientServiceImpl final : public WakeupClient::Service {
+ public:
+ TestWakeupClientServiceImpl();
+
+ ~TestWakeupClientServiceImpl();
+
+ grpc::Status GetRemoteTasks(grpc::ServerContext* context, const GetRemoteTasksRequest* request,
+ grpc::ServerWriter<GetRemoteTasksResponse>* writer) override;
+
+ grpc::Status NotifyWakeupRequired(grpc::ServerContext* context,
+ const NotifyWakeupRequiredRequest* request,
+ NotifyWakeupRequiredResponse* response) override;
+
+ private:
+ // This is a thread for communicating with remote wakeup server (via network) and receive tasks
+ // from it.
+ std::thread mThread;
+ // A variable to notify server is stopping.
+ std::condition_variable mServerStoppedCv;
+ // Whether wakeup AP is required for executing tasks.
+ std::atomic<bool> mWakeupRequired = true;
+ std::mutex mLock;
+ bool mServerStopped GUARDED_BY(mLock);
+
+ // Thread-safe. For test impl only.
+ FakeTaskGenerator mFakeTaskGenerator;
+ // Thread-sfae.
+ TaskQueue mTaskQueue;
+
+ void fakeTaskGenerateLoop();
+
+ void wakeupApplicationProcessor();
+};
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
new file mode 100644
index 0000000..7dcd31e
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/TestWakeupClientServiceImpl.cpp
@@ -0,0 +1,256 @@
+/*
+ * 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 "TestWakeupClientServiceImpl.h"
+
+#include "ApPowerControl.h"
+
+#include <android-base/stringprintf.h>
+#include <inttypes.h>
+#include <utils/Looper.h>
+#include <utils/SystemClock.h>
+#include <chrono>
+#include <thread>
+
+namespace android {
+namespace hardware {
+namespace automotive {
+namespace remoteaccess {
+
+namespace {
+
+using ::android::uptimeMillis;
+using ::android::base::ScopedLockAssertion;
+using ::android::base::StringPrintf;
+using ::grpc::ServerContext;
+using ::grpc::ServerWriter;
+using ::grpc::Status;
+
+constexpr int kTaskIntervalInMs = 5'000;
+constexpr int64_t KTaskTimeoutInMs = 20'000;
+
+} // namespace
+
+GetRemoteTasksResponse FakeTaskGenerator::generateTask() {
+ int clientId = mCurrentClientId++;
+ GetRemoteTasksResponse response;
+ response.set_data(std::string(reinterpret_cast<const char*>(DATA), sizeof(DATA)));
+ std::string clientIdStr = StringPrintf("%d", clientId);
+ response.set_clientid(clientIdStr);
+ return response;
+}
+
+TaskTimeoutMessageHandler::TaskTimeoutMessageHandler(TaskQueue* taskQueue)
+ : mTaskQueue(taskQueue) {}
+
+void TaskTimeoutMessageHandler::handleMessage(const android::Message& message) {
+ mTaskQueue->handleTaskTimeout();
+}
+
+TaskQueue::TaskQueue() {
+ mTaskTimeoutMessageHandler = android::sp<TaskTimeoutMessageHandler>::make(this);
+ mLooper = Looper::prepare(/*opts=*/0);
+ mCheckTaskTimeoutThread = std::thread([this] { checkForTestTimeoutLoop(); });
+}
+
+TaskQueue::~TaskQueue() {
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mStopped = true;
+ }
+ while (true) {
+ // Remove all pending timeout handlers from queue.
+ if (!maybePopOne().has_value()) {
+ break;
+ }
+ }
+ if (mCheckTaskTimeoutThread.joinable()) {
+ mCheckTaskTimeoutThread.join();
+ }
+}
+
+std::optional<GetRemoteTasksResponse> TaskQueue::maybePopOne() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ if (mTasks.size() == 0) {
+ return std::nullopt;
+ }
+ TaskInfo response = std::move(mTasks.top());
+ mTasks.pop();
+ mLooper->removeMessages(mTaskTimeoutMessageHandler, response.taskId);
+ return std::move(response.taskData);
+}
+
+void TaskQueue::add(const GetRemoteTasksResponse& task) {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ if (mStopped) {
+ return;
+ }
+ int taskId = mTaskIdCounter++;
+ mTasks.push(TaskInfo{
+ .taskId = taskId,
+ .timestampInMs = uptimeMillis(),
+ .taskData = task,
+ });
+ android::Message message(taskId);
+ mLooper->sendMessageDelayed(KTaskTimeoutInMs * 1000, mTaskTimeoutMessageHandler, message);
+ mTasksNotEmptyCv.notify_all();
+}
+
+void TaskQueue::waitForTask() {
+ std::unique_lock<std::mutex> lock(mLock);
+ waitForTaskWithLock(lock);
+}
+
+void TaskQueue::waitForTaskWithLock(std::unique_lock<std::mutex>& lock) {
+ mTasksNotEmptyCv.wait(lock, [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mTasks.size() > 0 || mStopped;
+ });
+}
+
+void TaskQueue::stopWait() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mStopped = true;
+ mTasksNotEmptyCv.notify_all();
+}
+
+bool TaskQueue::isEmpty() {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ return mTasks.size() == 0 || mStopped;
+}
+
+void TaskQueue::checkForTestTimeoutLoop() {
+ Looper::setForThread(mLooper);
+
+ while (true) {
+ {
+ std::unique_lock<std::mutex> lock(mLock);
+ if (mStopped) {
+ return;
+ }
+ }
+
+ mLooper->pollAll(/*timeoutMillis=*/-1);
+ }
+}
+
+void TaskQueue::handleTaskTimeout() {
+ // We know which task timed-out from the taskId in the message. However, there is no easy way
+ // to remove a specific task with the task ID from the priority_queue, so we just check from
+ // the top of the queue (which have the oldest tasks).
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ int64_t now = uptimeMillis();
+ while (mTasks.size() > 0) {
+ const TaskInfo& taskInfo = mTasks.top();
+ if (taskInfo.timestampInMs + KTaskTimeoutInMs > now) {
+ break;
+ }
+ // In real implementation, this should report task failure to remote wakeup server.
+ printf("Task for client ID: %s timed-out, added at %" PRId64 " ms, now %" PRId64 " ms",
+ taskInfo.taskData.clientid().c_str(), taskInfo.timestampInMs, now);
+ mTasks.pop();
+ }
+}
+
+TestWakeupClientServiceImpl::TestWakeupClientServiceImpl() {
+ mThread = std::thread([this] { fakeTaskGenerateLoop(); });
+}
+
+TestWakeupClientServiceImpl::~TestWakeupClientServiceImpl() {
+ {
+ std::lock_guard<std::mutex> lockGuard(mLock);
+ mServerStopped = true;
+ mServerStoppedCv.notify_all();
+ }
+ mTaskQueue.stopWait();
+ if (mThread.joinable()) {
+ mThread.join();
+ }
+}
+
+void TestWakeupClientServiceImpl::fakeTaskGenerateLoop() {
+ // In actual implementation, this should communicate with the remote server and receives tasks
+ // from it. Here we simulate receiving one remote task every {kTaskIntervalInMs}ms.
+ while (true) {
+ mTaskQueue.add(mFakeTaskGenerator.generateTask());
+ printf("Received a new task\n");
+ if (mWakeupRequired) {
+ wakeupApplicationProcessor();
+ }
+
+ printf("Sleeping for %d seconds until next task\n", kTaskIntervalInMs);
+
+ std::unique_lock lk(mLock);
+ if (mServerStoppedCv.wait_for(lk, std::chrono::milliseconds(kTaskIntervalInMs), [this] {
+ ScopedLockAssertion lockAssertion(mLock);
+ return mServerStopped;
+ })) {
+ // If the stopped flag is set, we are quitting, exit the loop.
+ return;
+ }
+ }
+}
+
+Status TestWakeupClientServiceImpl::GetRemoteTasks(ServerContext* context,
+ const GetRemoteTasksRequest* request,
+ ServerWriter<GetRemoteTasksResponse>* writer) {
+ printf("GetRemoteTasks called\n");
+ while (true) {
+ mTaskQueue.waitForTask();
+
+ while (true) {
+ auto maybeTask = mTaskQueue.maybePopOne();
+ if (!maybeTask.has_value()) {
+ // No task left, loop again and wait for another task(s).
+ break;
+ }
+ // Loop through all the task in the queue but obtain lock for each element so we don't
+ // hold lock while writing the response.
+ const GetRemoteTasksResponse& response = maybeTask.value();
+ if (!writer->Write(response)) {
+ // Broken stream, maybe the client is shutting down.
+ printf("Failed to deliver remote task to remote access HAL\n");
+ // The task failed to be sent, add it back to the queue. The order might change, but
+ // it is okay.
+ mTaskQueue.add(response);
+ return Status::CANCELLED;
+ }
+ }
+ }
+ return Status::OK;
+}
+
+Status TestWakeupClientServiceImpl::NotifyWakeupRequired(ServerContext* context,
+ const NotifyWakeupRequiredRequest* request,
+ NotifyWakeupRequiredResponse* response) {
+ if (request->iswakeuprequired() && !mWakeupRequired && !mTaskQueue.isEmpty()) {
+ // If wakeup is now required and previously not required, this means we have finished
+ // shutting down the device. If there are still pending tasks, try waking up AP again
+ // to finish executing those tasks.
+ wakeupApplicationProcessor();
+ }
+ mWakeupRequired = request->iswakeuprequired();
+ return Status::OK;
+}
+
+void TestWakeupClientServiceImpl::wakeupApplicationProcessor() {
+ wakeupAp();
+}
+
+} // namespace remoteaccess
+} // namespace automotive
+} // namespace hardware
+} // namespace android
diff --git a/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
new file mode 100644
index 0000000..52698b5
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/impl/src/main.cpp
@@ -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.
+ */
+
+#include <string>
+
+#include "TestWakeupClientServiceImpl.h"
+
+#include <grpc/grpc.h>
+#include <grpcpp/security/server_credentials.h>
+#include <grpcpp/server.h>
+#include <grpcpp/server_builder.h>
+
+using ::android::hardware::automotive::remoteaccess::TestWakeupClientServiceImpl;
+using ::grpc::Server;
+using ::grpc::ServerBuilder;
+using ::grpc::ServerWriter;
+
+void RunServer() {
+ std::string serverAddress(GRPC_SERVICE_ADDRESS);
+ std::shared_ptr<TestWakeupClientServiceImpl> service =
+ std::make_unique<TestWakeupClientServiceImpl>();
+
+ ServerBuilder builder;
+ builder.AddListeningPort(serverAddress, grpc::InsecureServerCredentials());
+ builder.RegisterService(service.get());
+ std::unique_ptr<Server> server(builder.BuildAndStart());
+ printf("Test Remote Access GRPC Server listening on %s\n", serverAddress.c_str());
+ server->Wait();
+}
+
+int main(int argc, char** argv) {
+ RunServer();
+ return 0;
+}
diff --git a/automotive/remoteaccess/test_grpc_server/lib/Android.bp b/automotive/remoteaccess/test_grpc_server/lib/Android.bp
new file mode 100644
index 0000000..7e95f53
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/lib/Android.bp
@@ -0,0 +1,32 @@
+// 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.
+
+soong_namespace {}
+
+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: "ApPowerControlLib",
+ vendor: true,
+ srcs: ["*.cpp"],
+ local_include_dirs: ["."],
+ export_include_dirs: ["."],
+}
diff --git a/automotive/remoteaccess/test_grpc_server/lib/ApPowerControl.cpp b/automotive/remoteaccess/test_grpc_server/lib/ApPowerControl.cpp
new file mode 100644
index 0000000..862fed1
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/lib/ApPowerControl.cpp
@@ -0,0 +1,23 @@
+/*
+ * 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 "ApPowerControl.h"
+
+#include <cstdio>
+
+void wakeupAp() {
+ printf("Waking up application processor...\n");
+}
diff --git a/automotive/remoteaccess/test_grpc_server/lib/ApPowerControl.h b/automotive/remoteaccess/test_grpc_server/lib/ApPowerControl.h
new file mode 100644
index 0000000..9560576
--- /dev/null
+++ b/automotive/remoteaccess/test_grpc_server/lib/ApPowerControl.h
@@ -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.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Wakeup application processor if not already waken up.
+void wakeupAp();
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 7c8e1f5..9e4f252 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -1632,10 +1632,8 @@
*
* The Android properties are:
*
- * int32Values[0] : Input code identifying the function representing this event. Valid event
- * types are defined by CustomInputType.CUSTOM_EVENT_F1 up to
- * CustomInputType.CUSTOM_EVENT_F10. They represent the custom event to be
- * defined by OEM partners.
+ * int32Values[0] : Input code identifying the function representing this event. OEMs are free
+ * to use any signed 32 bits number to represent the input code value.
* int32Values[1] : target display type defined in VehicleDisplay. Events not tied to specific
* display must be sent to VehicleDisplay#MAIN.
* int32Values[2] : repeat counter, if 0 then event is not repeated. Values 1 or above means
@@ -5326,10 +5324,11 @@
*/
enum CustomInputType : int32_t {
/**
- * Ten functions representing the custom input code to be defined and implemented by OEM
- * partners.
+ * Ten optional function codes to be used in case OEM don't need more than 10 input code values.
*
- * OEMs need to formally contact Android team if more than 10 functions are required.
+ * OEMs are free to use any signed 32 bits number to represent the input code value.
+ * The following function keys are only for convenience and any other integer values are
+ * also allowed.
*/
CUSTOM_EVENT_F1 = 1001,
CUSTOM_EVENT_F2 = 1002,
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl
new file mode 100644
index 0000000..9720aca
--- /dev/null
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.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.vehicle;
+@Backing(type="int") @VintfStability
+enum VehicleApPowerBootupReason {
+ USER_POWER_ON = 0,
+ SYSTEM_USER_DETECTION = 1,
+ SYSTEM_REMOTE_ACCESS = 2,
+}
diff --git a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 64c7ce7..24fd518 100644
--- a/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl/aidl_api/android.hardware.automotive.vehicle/current/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -119,12 +119,15 @@
DOOR_POS = 373295872,
DOOR_MOVE = 373295873,
DOOR_LOCK = 371198722,
+ DOOR_CHILD_LOCK_ENABLED = 371198723,
MIRROR_Z_POS = 339741504,
MIRROR_Z_MOVE = 339741505,
MIRROR_Y_POS = 339741506,
MIRROR_Y_MOVE = 339741507,
MIRROR_LOCK = 287312708,
MIRROR_FOLD = 287312709,
+ MIRROR_AUTO_FOLD_ENABLED = 337644358,
+ MIRROR_AUTO_TILT_ENABLED = 337644359,
SEAT_MEMORY_SELECT = 356518784,
SEAT_MEMORY_SET = 356518785,
SEAT_BELT_BUCKLED = 354421634,
@@ -152,10 +155,23 @@
SEAT_HEADREST_ANGLE_MOVE = 356518808,
SEAT_HEADREST_FORE_AFT_POS = 356518809,
SEAT_HEADREST_FORE_AFT_MOVE = 356518810,
+ SEAT_EASY_ACCESS_ENABLED = 354421661,
+ SEAT_AIRBAG_ENABLED = 354421662,
+ SEAT_CUSHION_SIDE_SUPPORT_POS = 356518815,
+ SEAT_CUSHION_SIDE_SUPPORT_MOVE = 356518816,
+ SEAT_LUMBAR_VERTICAL_POS = 356518817,
+ SEAT_LUMBAR_VERTICAL_MOVE = 356518818,
SEAT_OCCUPANCY = 356518832,
WINDOW_POS = 322964416,
WINDOW_MOVE = 322964417,
WINDOW_LOCK = 320867268,
+ STEERING_WHEEL_DEPTH_POS = 289410016,
+ STEERING_WHEEL_DEPTH_MOVE = 289410017,
+ STEERING_WHEEL_HEIGHT_POS = 289410018,
+ STEERING_WHEEL_HEIGHT_MOVE = 289410019,
+ STEERING_WHEEL_THEFT_LOCK_ENABLED = 287312868,
+ STEERING_WHEEL_LOCKED = 287312869,
+ STEERING_WHEEL_EASY_ACCESS_ENABLED = 287312870,
VEHICLE_MAP_SERVICE = 299895808,
OBD2_LIVE_FRAME = 299896064,
OBD2_FREEZE_FRAME = 299896065,
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.aidl
new file mode 100644
index 0000000..e325b38
--- /dev/null
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleApPowerBootupReason.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.
+ */
+
+package android.hardware.automotive.vehicle;
+
+/**
+ * Vehicle AP power bootup reason.
+ */
+@VintfStability
+@Backing(type="int")
+enum VehicleApPowerBootupReason {
+ /**
+ * Power on due to user's pressing of power key or rotating of ignition
+ * switch.
+ */
+ USER_POWER_ON = 0,
+ /**
+ * Automatic power on triggered by door unlock or any other kind of automatic
+ * user detection.
+ */
+ SYSTEM_USER_DETECTION = 1,
+ /**
+ * Automatic power on to execute a remote task. This is triggered by
+ * receiving a wakeup message from TCU wakeup client.
+ */
+ SYSTEM_REMOTE_ACCESS = 2,
+}
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 11cda3d..b6886c0 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -16,6 +16,8 @@
package android.hardware.automotive.vehicle;
+import android.hardware.automotive.vehicle.VehicleArea;
+import android.hardware.automotive.vehicle.VehiclePropertyGroup;
import android.hardware.automotive.vehicle.VehiclePropertyType;
/**
* Declares all vehicle properties. VehicleProperty has a bitwise structure.
@@ -457,6 +459,9 @@
/**
* Parking brake state.
*
+ * This property is true indicates that the car's parking brake is currently engaged. False
+ * implies that the car's parking brake is currently disengaged.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
*/
@@ -465,6 +470,15 @@
/**
* Auto-apply parking brake.
*
+ * This property is true indicates that the car's automatic parking brake feature is currently
+ * enabled. False indicates that the car's automatic parking brake feature is currently
+ * disabled.
+ *
+ * This property is often confused with PARKING_BRAKE_ON. The difference is that
+ * PARKING_BRAKE_ON describes whether the actual parking brake is currently on/off, whereas
+ * PARKING_BRAKE_AUTO_APPLY describes whether the feature of automatic parking brake is enabled/
+ * disabled, and does not describe the current state of the actual parking brake.
+ *
* @change_mode VehiclePropertyChangeMode.ON_CHANGE
* @access VehiclePropertyAccess.READ
*/
@@ -1306,6 +1320,18 @@
DOOR_LOCK = 0x0B02 + 0x10000000 + 0x06000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:DOOR,VehiclePropertyType:BOOLEAN
/**
+ * Door child lock feature enabled
+ *
+ * Returns true if the door child lock feature is enabled and false if it is disabled.
+ *
+ * If enabled, the door is unable to be opened from the inside.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ DOOR_CHILD_LOCK_ENABLED =
+ 0x0B03 + VehiclePropertyGroup.SYSTEM + VehicleArea.DOOR + VehiclePropertyType.BOOLEAN,
+ /**
* Mirror Z Position
*
* Positive value indicates tilt upwards, negative value is downwards
@@ -1365,6 +1391,35 @@
*/
MIRROR_FOLD = 0x0B45 + 0x10000000 + 0x01000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:BOOLEAN
+
+ /**
+ * Represents property for Mirror Auto Fold feature.
+ *
+ * This property is true when the feature for automatically folding the vehicle's side mirrors
+ * (for example, when the mirrors fold inward automatically when one exits and locks the
+ * vehicle) is enabled.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+
+ MIRROR_AUTO_FOLD_ENABLED =
+ 0x0B46 + VehiclePropertyGroup.SYSTEM + VehicleArea.MIRROR + VehiclePropertyType.BOOLEAN,
+
+ /**
+ * Represents property for Mirror Auto Tilt feature.
+ *
+ * This property is true when the feature for automatically tilting the vehicle's side mirrors
+ * (for example, when the mirrors tilt downward automatically when one reverses the vehicle) is
+ * enabled.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+
+ MIRROR_AUTO_TILT_ENABLED =
+ 0x0B47 + VehiclePropertyGroup.SYSTEM + VehicleArea.MIRROR + VehiclePropertyType.BOOLEAN,
+
/**
* Seat memory select
*
@@ -1667,6 +1722,102 @@
SEAT_HEADREST_FORE_AFT_MOVE = 0x0B9A + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
/**
+ * Represents property for Seat easy access feature.
+ *
+ * If true, the seat will automatically adjust to make it easier for the occupant to enter and
+ * exit the vehicle.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ SEAT_EASY_ACCESS_ENABLED =
+ 0x0B9D + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
+ /**
+ * Represents feature to enable/disable a seat's ability to deploy airbag(s) when triggered
+ * (e.g. by a crash).
+ *
+ * If true, it means the seat's airbags are enabled, and if triggered (e.g. by a crash), they
+ * will deploy. If false, it means the seat's airbags are disabled, and they will not deploy
+ * under any circumstance. This property does not indicate if the airbags are deployed or not.
+ *
+ * This property can be set to VehiclePropertyAccess.READ read only for the sake of regulation
+ * or safety concerns.
+ */
+ SEAT_AIRBAG_ENABLED =
+ 0x0B9E + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.BOOLEAN,
+ /**
+ * Represents property for seat’s hipside (bottom cushion’s side) support position.
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers
+ * between minInt32Value and maxInt32Value are supported.
+ *
+ * maxInt32Value indicates the widest cushion side support setting (i.e. least support).
+ * minInt32Value indicates the thinnest cushion side support setting (i.e most support).
+ *
+ * This value is not in any particular unit but in a specified range of steps.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ SEAT_CUSHION_SIDE_SUPPORT_POS =
+ 0x0B9F + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
+ /**
+ * Represents property for movement direction and speed of seat cushion side support.
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers
+ * between minInt32Value and maxInt32Value must be supported.
+ *
+ * maxInt32Value in default area's VehicleAreaConfig represents the maximum movement speed of
+ * the seat cushion side support in the growing wider direction (i.e. less support).
+ * minInt32Value in default area's VehicleAreaConfig represents the maximum movement speed of
+ * the seat cushion side support in the growing thinner direction (i.e. more support).
+ *
+ * Larger absolute values, either positive or negative, indicate a faster movement speed. Once
+ * the seat cushion side support reaches the positional limit, the value resets to 0.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ SEAT_CUSHION_SIDE_SUPPORT_MOVE =
+ 0x0BA0 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
+ /**
+ * Represents property for seat’s lumbar support vertical position.
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers
+ * between minInt32Value and maxInt32Value are supported.
+ *
+ * maxInt32Value indicates the highest position.
+ * minInt32Value indicates the lowest position.
+ *
+ * This value is not in any particular unit but in a specified range of steps.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ SEAT_LUMBAR_VERTICAL_POS =
+ 0x0BA1 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
+ /**
+ * Represents property for vertical movement direction and speed of seat lumbar support.
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All integers
+ * between minInt32Value and maxInt32Value must be supported.
+ *
+ * maxInt32Value in default area's VehicleAreaConfig indicates the lumbar support is moving at
+ * the fastest upward speed.
+ * minInt32Value in default area's VehicleAreaConfig indicates the lumbar support is moving at
+ * the fastest downward speed.
+ *
+ * Larger absolute values, either positive or negative, indicate a faster movement speed. Once
+ * the seat cushion side support reaches the positional limit, the value resets to 0.
+ *
+ * This value is not in any particular unit but in a specified range of steps.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ SEAT_LUMBAR_VERTICAL_MOVE =
+ 0x0BA2 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
+ /**
* Seat Occupancy
*
* Indicates whether a particular seat is occupied or not, to the best of the car's ability
@@ -1736,6 +1887,111 @@
WINDOW_LOCK = 0x0BC4 + 0x10000000 + 0x03000000
+ 0x00200000, // VehiclePropertyGroup:SYSTEM,VehicleArea:WINDOW,VehiclePropertyType:BOOLEAN
/**
+ * Steering wheel depth position
+ *
+ * All steering wheel properties' unique ids start from 0x0BE0.
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
+ * minInt32Value and maxInt32Value must be supported.
+ *
+ * The maxInt32Value in default area's VehicleAreaConfig indicates the steering wheel position
+ * closest to the driver. The minInt32Value in default area's VehicleAreaConfig indicates the
+ * steering wheel position furthest to the driver.
+ *
+ * This value is not in any particular unit but in a specified range of steps.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ STEERING_WHEEL_DEPTH_POS =
+ 0x0BE0 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
+ * Steering wheel depth movement
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
+ * minInt32Value and maxInt32Value must be supported.
+ *
+ * The maxInt32Value in default area's VehicleAreaConfig indicates the steering wheel moving
+ * towards the driver. The minInt32Value in default area's VehicleAreaConfig indicates the
+ * steering wheel moving away from the driver. Larger integers, either positive or negative,
+ * indicate a faster movement speed. Once the steering wheel reaches the positional limit, the
+ * value resets to 0.
+ *
+ * This value is not in any particular unit but in a specified range of steps.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ STEERING_WHEEL_DEPTH_MOVE =
+ 0x0BE1 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
+ * Steering wheel height position
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
+ * minInt32Value and maxInt32Value must be supported.
+ *
+ * The maxInt32Value in default area's VehicleAreaConfig indicates the steering wheel being in
+ * the highest position. The minInt32Value in default area's VehicleAreaConfig indicates the
+ * steering wheel being in the lowest position.
+ *
+ * This value is not in any particular unit but in a specified range of steps.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ STEERING_WHEEL_HEIGHT_POS =
+ 0x0BE2 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
+ * Steering wheel height movement
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
+ * minInt32Value and maxInt32Value must be supported.
+ *
+ * The maxInt32Value in default area's VehicleAreaConfig indicates the steering wheel moving
+ * upwards. The minInt32Value in default area's VehicleAreaConfig indicates the steering wheel
+ * moving downwards. Larger integers, either positive or negative, indicate a faster movement
+ * speed. Once the steering wheel reaches the positional limit, the value resets to 0.
+ *
+ * This value is not in any particular unit but in a specified range of steps.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ STEERING_WHEEL_HEIGHT_MOVE =
+ 0x0BE3 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
+ * Steering wheel theft lock feature enabled
+ *
+ * If true, the steering wheel will lock automatically to prevent theft in certain
+ * situations.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ STEERING_WHEEL_THEFT_LOCK_ENABLED =
+ 0x0BE4 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
+ /**
+ * Steering wheel locked
+ *
+ * If true, the steering wheel's position is locked and not changeable.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ STEERING_WHEEL_LOCKED =
+ 0x0BE5 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
+ /**
+ * Steering wheel easy access feature enabled
+ *
+ * If true, the driver’s steering wheel will automatically adjust to make it easier for the
+ * driver to enter and exit the vehicle.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ */
+ STEERING_WHEEL_EASY_ACCESS_ENABLED =
+ 0x0BE6 + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.BOOLEAN,
+ /**
* Vehicle Maps Service (VMS) message
*
* This property uses MIXED data to communicate vms messages.
@@ -2877,5 +3133,4 @@
*/
SUPPORTED_PROPERTY_IDS = 0x0F48 + 0x10000000 + 0x01000000
+ 0x00410000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32_VEC
-
}
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
index c91afe2..d5182dd 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
@@ -119,12 +119,15 @@
{VehicleProperty::DOOR_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::DOOR_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::DOOR_LOCK, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::DOOR_CHILD_LOCK_ENABLED, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::MIRROR_Z_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::MIRROR_Z_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::MIRROR_Y_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::MIRROR_Y_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::MIRROR_LOCK, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::MIRROR_FOLD, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::MIRROR_AUTO_FOLD_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::MIRROR_AUTO_TILT_ENABLED, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_MEMORY_SELECT, VehiclePropertyAccess::WRITE},
{VehicleProperty::SEAT_MEMORY_SET, VehiclePropertyAccess::WRITE},
{VehicleProperty::SEAT_BELT_BUCKLED, VehiclePropertyAccess::READ_WRITE},
@@ -152,10 +155,23 @@
{VehicleProperty::SEAT_HEADREST_ANGLE_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_HEADREST_FORE_AFT_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_HEADREST_FORE_AFT_MOVE, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::SEAT_EASY_ACCESS_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::SEAT_AIRBAG_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::SEAT_LUMBAR_VERTICAL_POS, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::SEAT_LUMBAR_VERTICAL_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_OCCUPANCY, VehiclePropertyAccess::READ},
{VehicleProperty::WINDOW_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::WINDOW_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::WINDOW_LOCK, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::STEERING_WHEEL_DEPTH_POS, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::STEERING_WHEEL_DEPTH_MOVE, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::STEERING_WHEEL_HEIGHT_POS, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::STEERING_WHEEL_HEIGHT_MOVE, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::STEERING_WHEEL_THEFT_LOCK_ENABLED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::STEERING_WHEEL_LOCKED, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::STEERING_WHEEL_EASY_ACCESS_ENABLED, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::VEHICLE_MAP_SERVICE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::OBD2_LIVE_FRAME, VehiclePropertyAccess::READ},
{VehicleProperty::OBD2_FREEZE_FRAME, VehiclePropertyAccess::READ},
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
index 807be5d..47bad2c 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
@@ -119,12 +119,15 @@
{VehicleProperty::DOOR_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::DOOR_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::DOOR_LOCK, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::DOOR_CHILD_LOCK_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::MIRROR_Z_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::MIRROR_Z_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::MIRROR_Y_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::MIRROR_Y_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::MIRROR_LOCK, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::MIRROR_FOLD, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::MIRROR_AUTO_FOLD_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::MIRROR_AUTO_TILT_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_MEMORY_SELECT, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_MEMORY_SET, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_BELT_BUCKLED, VehiclePropertyChangeMode::ON_CHANGE},
@@ -152,10 +155,23 @@
{VehicleProperty::SEAT_HEADREST_ANGLE_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_HEADREST_FORE_AFT_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_HEADREST_FORE_AFT_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::SEAT_EASY_ACCESS_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::SEAT_AIRBAG_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::SEAT_LUMBAR_VERTICAL_POS, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::SEAT_LUMBAR_VERTICAL_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_OCCUPANCY, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::WINDOW_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::WINDOW_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::WINDOW_LOCK, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::STEERING_WHEEL_DEPTH_POS, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::STEERING_WHEEL_DEPTH_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::STEERING_WHEEL_HEIGHT_POS, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::STEERING_WHEEL_HEIGHT_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::STEERING_WHEEL_THEFT_LOCK_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::STEERING_WHEEL_LOCKED, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::STEERING_WHEEL_EASY_ACCESS_ENABLED, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::VEHICLE_MAP_SERVICE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::OBD2_LIVE_FRAME, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::OBD2_FREEZE_FRAME, VehiclePropertyChangeMode::ON_CHANGE},
diff --git a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
index e698f84..85a62d3 100644
--- a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
@@ -111,12 +111,15 @@
Map.entry(VehicleProperty.DOOR_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.DOOR_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.DOOR_LOCK, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.DOOR_CHILD_LOCK_ENABLED, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.MIRROR_Z_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.MIRROR_Z_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.MIRROR_Y_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.MIRROR_Y_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.MIRROR_LOCK, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.MIRROR_FOLD, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.MIRROR_AUTO_FOLD_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.MIRROR_AUTO_TILT_ENABLED, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_MEMORY_SELECT, VehiclePropertyAccess.WRITE),
Map.entry(VehicleProperty.SEAT_MEMORY_SET, VehiclePropertyAccess.WRITE),
Map.entry(VehicleProperty.SEAT_BELT_BUCKLED, VehiclePropertyAccess.READ_WRITE),
@@ -144,10 +147,23 @@
Map.entry(VehicleProperty.SEAT_HEADREST_ANGLE_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_HEADREST_FORE_AFT_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_HEADREST_FORE_AFT_MOVE, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.SEAT_EASY_ACCESS_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.SEAT_AIRBAG_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.SEAT_CUSHION_SIDE_SUPPORT_POS, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.SEAT_CUSHION_SIDE_SUPPORT_MOVE, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.SEAT_LUMBAR_VERTICAL_POS, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.SEAT_LUMBAR_VERTICAL_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_OCCUPANCY, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.WINDOW_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.WINDOW_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.WINDOW_LOCK, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_DEPTH_POS, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_DEPTH_MOVE, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_HEIGHT_POS, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_HEIGHT_MOVE, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_THEFT_LOCK_ENABLED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_LOCKED, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_EASY_ACCESS_ENABLED, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.VEHICLE_MAP_SERVICE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.OBD2_LIVE_FRAME, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.OBD2_FREEZE_FRAME, VehiclePropertyAccess.READ),
diff --git a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
index fe69450..46b9663 100644
--- a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
@@ -111,12 +111,15 @@
Map.entry(VehicleProperty.DOOR_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.DOOR_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.DOOR_LOCK, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.DOOR_CHILD_LOCK_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.MIRROR_Z_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.MIRROR_Z_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.MIRROR_Y_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.MIRROR_Y_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.MIRROR_LOCK, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.MIRROR_FOLD, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.MIRROR_AUTO_FOLD_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.MIRROR_AUTO_TILT_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_MEMORY_SELECT, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_MEMORY_SET, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_BELT_BUCKLED, VehiclePropertyChangeMode.ON_CHANGE),
@@ -144,10 +147,23 @@
Map.entry(VehicleProperty.SEAT_HEADREST_ANGLE_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_HEADREST_FORE_AFT_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_HEADREST_FORE_AFT_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.SEAT_EASY_ACCESS_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.SEAT_AIRBAG_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.SEAT_CUSHION_SIDE_SUPPORT_POS, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.SEAT_CUSHION_SIDE_SUPPORT_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.SEAT_LUMBAR_VERTICAL_POS, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.SEAT_LUMBAR_VERTICAL_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_OCCUPANCY, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.WINDOW_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.WINDOW_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.WINDOW_LOCK, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_DEPTH_POS, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_DEPTH_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_HEIGHT_POS, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_HEIGHT_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_THEFT_LOCK_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_LOCKED, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_EASY_ACCESS_ENABLED, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.VEHICLE_MAP_SERVICE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.OBD2_LIVE_FRAME, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.OBD2_FREEZE_FRAME, VehiclePropertyChangeMode.ON_CHANGE),
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index b6811b6..bd80ad5 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -1036,6 +1036,178 @@
]
},
{
+ "property": "VehicleProperty::SEAT_EASY_ACCESS_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_AIRBAG_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT"
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_LUMBAR_VERTICAL_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -10,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::SEAT_LUMBAR_VERTICAL_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::SEAT_OCCUPANCY",
"areas": [
{
@@ -1929,6 +2101,22 @@
]
},
{
+ "property": "VehicleProperty::DOOR_CHILD_LOCK_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::DOOR_2_LEFT"
+ },
+ {
+ "areaId": "Constants::DOOR_2_RIGHT"
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::DOOR_POS",
"defaultValue": {
"int32Values": [
@@ -1964,6 +2152,36 @@
]
},
{
+ "property": "VehicleProperty::DOOR_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::DOOR_1_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_1_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_2_LEFT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ },
+ {
+ "areaId": "Constants::DOOR_2_RIGHT",
+ "minInt32Value": -1,
+ "maxInt32Value": 1
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::MIRROR_Z_POS",
"defaultValue": {
"int32Values": [
@@ -2080,6 +2298,32 @@
}
},
{
+ "property": "VehicleProperty::MIRROR_AUTO_FOLD_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::MIRROR_DRIVER_LEFT_RIGHT"
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::MIRROR_AUTO_TILT_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 1
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::MIRROR_DRIVER_LEFT_RIGHT"
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::WINDOW_LOCK",
"areas": [
{
@@ -2163,6 +2407,90 @@
]
},
{
+ "property": "VehicleProperty::STEERING_WHEEL_DEPTH_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_DEPTH_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_HEIGHT_POS",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_HEIGHT_MOVE",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "minInt32Value": -2,
+ "maxInt32Value": 2
+ }
+ ]
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_THEFT_LOCK_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_LOCKED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
+ "property": "VehicleProperty::STEERING_WHEEL_EASY_ACCESS_ENABLED",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ }
+ },
+ {
"property": "VehicleProperty::WHEEL_TICK",
"defaultValue": {
"int64Values": [
diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
index 5de206b..7eefe2a 100644
--- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -44,6 +44,8 @@
using ::aidl::android::hardware::automotive::vehicle::VehicleArea;
using ::aidl::android::hardware::automotive::vehicle::VehicleProperty;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyAccess;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyChangeMode;
+using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyGroup;
using ::aidl::android::hardware::automotive::vehicle::VehiclePropertyType;
using ::android::getAidlHalInstanceNames;
using ::android::base::ScopedLockAssertion;
@@ -114,6 +116,9 @@
class VtsHalAutomotiveVehicleTargetTest : public testing::TestWithParam<ServiceDescriptor> {
public:
+ void verifyProperty(VehicleProperty propId, VehiclePropertyAccess access,
+ VehiclePropertyChangeMode changeMode, VehiclePropertyGroup group,
+ VehicleArea area, VehiclePropertyType propertyType);
virtual void SetUp() override {
auto descriptor = GetParam();
if (descriptor.isAidlService) {
@@ -420,6 +425,158 @@
}
}
+// Helper function to compare actual vs expected property config
+void VtsHalAutomotiveVehicleTargetTest::verifyProperty(VehicleProperty propId,
+ VehiclePropertyAccess access,
+ VehiclePropertyChangeMode changeMode,
+ VehiclePropertyGroup group, VehicleArea area,
+ VehiclePropertyType propertyType) {
+ int expectedPropId = toInt(propId);
+ int expectedAccess = toInt(access);
+ int expectedChangeMode = toInt(changeMode);
+ int expectedGroup = toInt(group);
+ int expectedArea = toInt(area);
+ int expectedPropertyType = toInt(propertyType);
+
+ auto result = mVhalClient->getPropConfigs({expectedPropId});
+ ASSERT_TRUE(result.ok()) << "Failed to get required property config, error: "
+ << result.error().message();
+
+ if (result.value().size() == 0) {
+ GTEST_SKIP() << "Property has not been implemented";
+ }
+ ASSERT_EQ(result.value().size(), 1u)
+ << StringPrintf("Expect to get exactly 1 config, got %zu", result.value().size());
+
+ const auto& config = result.value().at(0);
+ int actualPropId = config->getPropId();
+ int actualAccess = config->getAccess();
+ int actualChangeMode = config->getChangeMode();
+ int actualGroup = actualPropId & toInt(VehiclePropertyGroup::MASK);
+ int actualArea = actualPropId & toInt(VehicleArea::MASK);
+ int actualPropertyType = actualPropId & toInt(VehiclePropertyType::MASK);
+
+ ASSERT_EQ(actualPropId, expectedPropId)
+ << StringPrintf("Expect to get property ID: %i, got %i", expectedPropId, actualPropId);
+
+ if (expectedAccess == toInt(VehiclePropertyAccess::READ_WRITE)) {
+ ASSERT_TRUE(actualAccess == expectedAccess ||
+ actualAccess == toInt(VehiclePropertyAccess::READ))
+ << StringPrintf("Expect to get VehiclePropertyAccess: %i or %i, got %i",
+ expectedAccess, toInt(VehiclePropertyAccess::READ), actualAccess);
+ } else {
+ ASSERT_EQ(actualAccess, expectedAccess) << StringPrintf(
+ "Expect to get VehiclePropertyAccess: %i, got %i", expectedAccess, actualAccess);
+ }
+
+ ASSERT_EQ(actualChangeMode, expectedChangeMode)
+ << StringPrintf("Expect to get VehiclePropertyChangeMode: %i, got %i",
+ expectedChangeMode, actualChangeMode);
+ ASSERT_EQ(actualGroup, expectedGroup) << StringPrintf(
+ "Expect to get VehiclePropertyGroup: %i, got %i", expectedGroup, actualGroup);
+ ASSERT_EQ(actualArea, expectedArea)
+ << StringPrintf("Expect to get VehicleArea: %i, got %i", expectedArea, actualArea);
+ ASSERT_EQ(actualPropertyType, expectedPropertyType)
+ << StringPrintf("Expect to get VehiclePropertyType: %i, got %i", expectedPropertyType,
+ actualPropertyType);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyDoorChildLockEnabledConfig) {
+ verifyProperty(VehicleProperty::DOOR_CHILD_LOCK_ENABLED, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::DOOR, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySteeringWheelDepthPosConfig) {
+ verifyProperty(VehicleProperty::STEERING_WHEEL_DEPTH_POS, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySteeringWheelDepthMoveConfig) {
+ verifyProperty(VehicleProperty::STEERING_WHEEL_DEPTH_MOVE, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySteeringWheelHeightPosConfig) {
+ verifyProperty(VehicleProperty::STEERING_WHEEL_HEIGHT_POS, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySteeringWheelHeightMoveConfig) {
+ verifyProperty(VehicleProperty::STEERING_WHEEL_HEIGHT_MOVE, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySteeringWheelTheftLockEnabledConfig) {
+ verifyProperty(VehicleProperty::STEERING_WHEEL_THEFT_LOCK_ENABLED,
+ VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySteeringWheelLockedConfig) {
+ verifyProperty(VehicleProperty::STEERING_WHEEL_LOCKED, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySteeringWheelEasyAccessEnabledConfig) {
+ verifyProperty(VehicleProperty::STEERING_WHEEL_EASY_ACCESS_ENABLED,
+ VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyMirrorAutoFoldEnabledConfig) {
+ verifyProperty(VehicleProperty::MIRROR_AUTO_FOLD_ENABLED, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::MIRROR, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyMirrorAutoTiltEnabledConfig) {
+ verifyProperty(VehicleProperty::MIRROR_AUTO_TILT_ENABLED, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::MIRROR, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatEasyAccessEnabledConfig) {
+ verifyProperty(VehicleProperty::SEAT_EASY_ACCESS_ENABLED, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::SEAT, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatAirbagEnabledConfig) {
+ verifyProperty(VehicleProperty::SEAT_AIRBAG_ENABLED, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::SEAT, VehiclePropertyType::BOOLEAN);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatCushionSideSupportPosConfig) {
+ verifyProperty(VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_POS,
+ VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::SEAT, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatCushionSideSupportMoveConfig) {
+ verifyProperty(VehicleProperty::SEAT_CUSHION_SIDE_SUPPORT_MOVE,
+ VehiclePropertyAccess::READ_WRITE, VehiclePropertyChangeMode::ON_CHANGE,
+ VehiclePropertyGroup::SYSTEM, VehicleArea::SEAT, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatLumbarVerticalPosConfig) {
+ verifyProperty(VehicleProperty::SEAT_LUMBAR_VERTICAL_POS, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::SEAT, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatLumbarVerticalMoveConfig) {
+ verifyProperty(VehicleProperty::SEAT_LUMBAR_VERTICAL_MOVE, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::SEAT, VehiclePropertyType::INT32);
+}
+
std::vector<ServiceDescriptor> getDescriptors() {
std::vector<ServiceDescriptor> descriptors;
for (std::string name : getAidlHalInstanceNames(IVehicle::descriptor)) {
diff --git a/biometrics/fingerprint/aidl/OWNERS b/biometrics/OWNERS
similarity index 100%
rename from biometrics/fingerprint/aidl/OWNERS
rename to biometrics/OWNERS
diff --git a/biometrics/common/aidl/Android.bp b/biometrics/common/aidl/Android.bp
index 167e0c7..3cd76fd 100644
--- a/biometrics/common/aidl/Android.bp
+++ b/biometrics/common/aidl/Android.bp
@@ -31,7 +31,5 @@
version: "2",
imports: [],
},
-
],
-
}
diff --git a/biometrics/common/aidl/OWNERS b/biometrics/common/aidl/OWNERS
deleted file mode 100644
index 36d7261..0000000
--- a/biometrics/common/aidl/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-ilyamaty@google.com
-kchyn@google.com
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl
index d4433c5..1eb8541 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/CommonProps.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.common;
+/* @hide */
@VintfStability
parcelable CommonProps {
int sensorId;
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl
index ad11dda..471ed2b 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ComponentInfo.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.common;
+/* @hide */
@VintfStability
parcelable ComponentInfo {
String componentId;
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ICancellationSignal.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ICancellationSignal.aidl
index 2bc6a6d..670114f 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ICancellationSignal.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/ICancellationSignal.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.common;
+/* @hide */
@VintfStability
interface ICancellationSignal {
oneway void cancel();
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl
index 9d1cb8f..5e184bc 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationContext.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.common;
+/* @hide */
@VintfStability
parcelable OperationContext {
int id = 0;
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationReason.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationReason.aidl
index 3da3a6a..a5b2990 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationReason.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/OperationReason.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.common;
+/* @hide */
@Backing(type="byte") @VintfStability
enum OperationReason {
UNKNOWN = 0,
diff --git a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/SensorStrength.aidl b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/SensorStrength.aidl
index 6675d09..aa77322 100644
--- a/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/SensorStrength.aidl
+++ b/biometrics/common/aidl/aidl_api/android.hardware.biometrics.common/current/android/hardware/biometrics/common/SensorStrength.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.common;
+/* @hide */
@Backing(type="byte") @VintfStability
enum SensorStrength {
CONVENIENCE = 0,
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl
index 2f5af5d..cdedf4f 100644
--- a/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/CommonProps.aidl
@@ -18,7 +18,9 @@
import android.hardware.biometrics.common.ComponentInfo;
import android.hardware.biometrics.common.SensorStrength;
-
+/**
+ * @hide
+ */
@VintfStability
parcelable CommonProps {
/**
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl
index b268eef..1da9cf6 100644
--- a/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/ComponentInfo.aidl
@@ -15,7 +15,9 @@
*/
package android.hardware.biometrics.common;
-
+/**
+ * @hide
+ */
@VintfStability
parcelable ComponentInfo {
/**
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/ICancellationSignal.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/ICancellationSignal.aidl
index 1010256..b9b1f39 100644
--- a/biometrics/common/aidl/android/hardware/biometrics/common/ICancellationSignal.aidl
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/ICancellationSignal.aidl
@@ -15,9 +15,10 @@
*/
package android.hardware.biometrics.common;
-
+/**
+ * @hide
+ */
@VintfStability
oneway interface ICancellationSignal {
void cancel();
}
-
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl
index 72fe660..a1c7a1f 100644
--- a/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/OperationContext.aidl
@@ -20,6 +20,7 @@
/**
* Additional context associated with an operation.
+ * @hide
*/
@VintfStability
parcelable OperationContext {
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/OperationReason.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/OperationReason.aidl
index abc25ed..a93cebc 100644
--- a/biometrics/common/aidl/android/hardware/biometrics/common/OperationReason.aidl
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/OperationReason.aidl
@@ -15,7 +15,9 @@
*/
package android.hardware.biometrics.common;
-
+/**
+ * @hide
+ */
@VintfStability
@Backing(type="byte")
enum OperationReason {
diff --git a/biometrics/common/aidl/android/hardware/biometrics/common/SensorStrength.aidl b/biometrics/common/aidl/android/hardware/biometrics/common/SensorStrength.aidl
index 790691c..b5c0999 100644
--- a/biometrics/common/aidl/android/hardware/biometrics/common/SensorStrength.aidl
+++ b/biometrics/common/aidl/android/hardware/biometrics/common/SensorStrength.aidl
@@ -15,7 +15,9 @@
*/
package android.hardware.biometrics.common;
-
+/**
+ * @hide
+ */
@VintfStability
@Backing(type="byte")
enum SensorStrength {
@@ -40,4 +42,4 @@
* HardwareAuthToken(s).
*/
STRONG,
-}
\ No newline at end of file
+}
diff --git a/biometrics/common/util/Android.bp b/biometrics/common/util/Android.bp
index 918ef72..b990812 100644
--- a/biometrics/common/util/Android.bp
+++ b/biometrics/common/util/Android.bp
@@ -13,6 +13,6 @@
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.biometrics.common-V2-ndk",
+ "android.hardware.biometrics.common-V3-ndk",
],
}
diff --git a/biometrics/common/util/include/util/Util.h b/biometrics/common/util/include/util/Util.h
index 29ec0f8..da19dc6 100644
--- a/biometrics/common/util/include/util/Util.h
+++ b/biometrics/common/util/include/util/Util.h
@@ -40,7 +40,7 @@
// by parts of the UI or fail if there is no latency. For example, the
// Face settings page constantly runs auth and the enrollment UI uses a
// cancel/restart cycle that requires some latency while the activities change.
-#define DEFAULT_LATENCY 800
+#define DEFAULT_LATENCY 400
class Util {
public:
@@ -66,4 +66,4 @@
}
};
-} // namespace aidl::android::hardware::biometrics
\ No newline at end of file
+} // namespace aidl::android::hardware::biometrics
diff --git a/biometrics/face/1.0/vts/functional/OWNERS b/biometrics/face/1.0/vts/functional/OWNERS
deleted file mode 100644
index 7651b69..0000000
--- a/biometrics/face/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 432605
-ilyamaty@google.com
diff --git a/biometrics/face/aidl/Android.bp b/biometrics/face/aidl/Android.bp
index 0bec0c5..7b11335 100644
--- a/biometrics/face/aidl/Android.bp
+++ b/biometrics/face/aidl/Android.bp
@@ -14,9 +14,9 @@
"android/hardware/biometrics/face/**/*.aidl",
],
imports: [
- "android.hardware.biometrics.common",
+ "android.hardware.biometrics.common-V3",
"android.hardware.common-V2",
- "android.hardware.keymaster-V3",
+ "android.hardware.keymaster-V4",
],
stability: "vintf",
backend: {
diff --git a/biometrics/face/aidl/OWNERS b/biometrics/face/aidl/OWNERS
deleted file mode 100644
index 36d7261..0000000
--- a/biometrics/face/aidl/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-ilyamaty@google.com
-kchyn@google.com
diff --git a/biometrics/face/aidl/default/Android.bp b/biometrics/face/aidl/default/Android.bp
index 63a3645..876a91f 100644
--- a/biometrics/face/aidl/default/Android.bp
+++ b/biometrics/face/aidl/default/Android.bp
@@ -16,8 +16,8 @@
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.biometrics.face-V2-ndk",
- "android.hardware.biometrics.common-V2-ndk",
+ "android.hardware.biometrics.face-V3-ndk",
+ "android.hardware.biometrics.common-V3-ndk",
"android.hardware.biometrics.common.thread",
"android.hardware.biometrics.common.util",
],
@@ -49,9 +49,9 @@
],
static_libs: [
"libandroid.hardware.biometrics.face.VirtualProps",
- "android.hardware.biometrics.face-V2-ndk",
- "android.hardware.biometrics.common-V2-ndk",
- "android.hardware.keymaster-V3-ndk",
+ "android.hardware.biometrics.face-V3-ndk",
+ "android.hardware.biometrics.common-V3-ndk",
+ "android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
],
vendor: true,
diff --git a/biometrics/face/aidl/default/face-default.xml b/biometrics/face/aidl/default/face-default.xml
index e6ef842..8f2fbb8 100644
--- a/biometrics/face/aidl/default/face-default.xml
+++ b/biometrics/face/aidl/default/face-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.biometrics.face</name>
- <version>2</version>
+ <version>3</version>
<fqname>IFace/default</fqname>
</hal>
</manifest>
diff --git a/biometrics/face/aidl/vts/Android.bp b/biometrics/face/aidl/vts/Android.bp
index 4171ac3..f62c4e4 100644
--- a/biometrics/face/aidl/vts/Android.bp
+++ b/biometrics/face/aidl/vts/Android.bp
@@ -15,10 +15,10 @@
],
srcs: ["VtsHalBiometricsFaceTargetTest.cpp"],
static_libs: [
- "android.hardware.biometrics.common-V2-ndk",
- "android.hardware.biometrics.face-V2-ndk",
+ "android.hardware.biometrics.common-V3-ndk",
+ "android.hardware.biometrics.face-V3-ndk",
"android.hardware.common-V2-ndk",
- "android.hardware.keymaster-V3-ndk",
+ "android.hardware.keymaster-V4-ndk",
],
shared_libs: [
"libbinder_ndk",
diff --git a/biometrics/fingerprint/2.1/vts/functional/OWNERS b/biometrics/fingerprint/2.1/vts/functional/OWNERS
deleted file mode 100644
index 0014ce9..0000000
--- a/biometrics/fingerprint/2.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 114777
-ilyamaty@google.com
diff --git a/biometrics/fingerprint/2.2/vts/functional/OWNERS b/biometrics/fingerprint/2.2/vts/functional/OWNERS
deleted file mode 100644
index 0014ce9..0000000
--- a/biometrics/fingerprint/2.2/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 114777
-ilyamaty@google.com
diff --git a/biometrics/fingerprint/aidl/Android.bp b/biometrics/fingerprint/aidl/Android.bp
index 0bd6422..f749822 100644
--- a/biometrics/fingerprint/aidl/Android.bp
+++ b/biometrics/fingerprint/aidl/Android.bp
@@ -14,8 +14,8 @@
"android/hardware/biometrics/fingerprint/**/*.aidl",
],
imports: [
- "android.hardware.biometrics.common",
- "android.hardware.keymaster-V3",
+ "android.hardware.biometrics.common-V3",
+ "android.hardware.keymaster-V4",
],
stability: "vintf",
backend: {
@@ -41,7 +41,5 @@
"android.hardware.keymaster-V3",
],
},
-
],
-
}
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
index c51aa03..0cc619f 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.fingerprint;
+/* @hide */
@Backing(type="byte") @VintfStability
enum AcquiredInfo {
UNKNOWN = 0,
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl
index af7bc3c..45ce2eb 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/Error.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.fingerprint;
+/* @hide */
@Backing(type="byte") @VintfStability
enum Error {
UNKNOWN = 0,
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
index 9c208c4..67af20d 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.fingerprint;
+/* @hide */
@Backing(type="byte") @VintfStability
enum FingerprintSensorType {
UNKNOWN = 0,
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl
index 5d3df6f..0b6f300 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.fingerprint;
+/* @hide */
@VintfStability
interface IFingerprint {
android.hardware.biometrics.fingerprint.SensorProps[] getSensorProps();
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
index 30f299d..f305855 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.fingerprint;
+/* @hide */
@VintfStability
interface ISession {
void generateChallenge();
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index 3c40ad6..be18ffe 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.fingerprint;
+/* @hide */
@VintfStability
interface ISessionCallback {
void onChallengeGenerated(in long challenge);
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/PointerContext.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/PointerContext.aidl
index 43db6cf..999b324 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/PointerContext.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/PointerContext.aidl
@@ -32,7 +32,8 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.fingerprint;
-@VintfStability
+/* @hide */
+@JavaDerive(equals=true) @VintfStability
parcelable PointerContext {
int pointerId = -1;
float x = 0.000000f;
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl
index 295fde9..dc6a62d 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorLocation.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.fingerprint;
+/* @hide */
@VintfStability
parcelable SensorLocation {
int displayId;
diff --git a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl
index 782d289..a77d5f2 100644
--- a/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl
+++ b/biometrics/fingerprint/aidl/aidl_api/android.hardware.biometrics.fingerprint/current/android/hardware/biometrics/fingerprint/SensorProps.aidl
@@ -32,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.biometrics.fingerprint;
+/* @hide */
@VintfStability
parcelable SensorProps {
android.hardware.biometrics.common.CommonProps commonProps;
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
index 8ec8574..d3aa98a 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/AcquiredInfo.aidl
@@ -15,7 +15,9 @@
*/
package android.hardware.biometrics.fingerprint;
-
+/**
+ * @hide
+ */
@VintfStability
@Backing(type="byte")
enum AcquiredInfo {
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl
index e69859a..d8d47fa 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/Error.aidl
@@ -15,7 +15,9 @@
*/
package android.hardware.biometrics.fingerprint;
-
+/**
+ * @hide
+ */
@VintfStability
@Backing(type="byte")
enum Error {
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
index dbe7137..7caa154 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/FingerprintSensorType.aidl
@@ -15,7 +15,9 @@
*/
package android.hardware.biometrics.fingerprint;
-
+/**
+ * @hide
+ */
@VintfStability
@Backing(type="byte")
enum FingerprintSensorType {
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
index 75f90a1..f4febad 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/IFingerprint.aidl
@@ -19,7 +19,9 @@
import android.hardware.biometrics.fingerprint.ISession;
import android.hardware.biometrics.fingerprint.ISessionCallback;
import android.hardware.biometrics.fingerprint.SensorProps;
-
+/**
+ * @hide
+ */
@VintfStability
interface IFingerprint {
/**
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
index db01145..f4f7804 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISession.aidl
@@ -45,6 +45,7 @@
* ISession only supports execution of one non-interrupting operation at a time, regardless of
* whether it's cancellable. The framework must wait for a callback indicating the end of the
* current non-interrupting operation before a new non-interrupting operation can be started.
+ * @hide
*/
@VintfStability
interface ISession {
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
index f699966..24b169e 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/ISessionCallback.aidl
@@ -19,7 +19,9 @@
import android.hardware.biometrics.fingerprint.AcquiredInfo;
import android.hardware.biometrics.fingerprint.Error;
import android.hardware.keymaster.HardwareAuthToken;
-
+/**
+ * @hide
+ */
@VintfStability
interface ISessionCallback {
/**
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/PointerContext.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/PointerContext.aidl
index e025d34..582e6cf 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/PointerContext.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/PointerContext.aidl
@@ -18,7 +18,9 @@
/**
* Additional context associated with a pointer event.
+ * @hide
*/
+@JavaDerive(equals=true)
@VintfStability
parcelable PointerContext {
/**
@@ -64,7 +66,7 @@
boolean isAod = false;
/**
- * The time of the user interaction that produced this event, in milliseconds.
+ * The time when this event was created, in milliseconds.
*
* This is obtained from MotionEvent#getEventTime, which uses SystemClock.uptimeMillis() as
* the clock.
@@ -74,10 +76,10 @@
long time = 0;
/**
- * The time of the first user interaction in this gesture, in milliseconds.
+ * This event is part of some gesture. This is the time when MotionEvent#ACTION_DOWN was
+ * created for that gesture, in milliseconds.
*
- * If this event is MotionEvent#ACTION_DOWN, it means it's the first event in this gesture,
- * and `gestureStart` will be equal to `time`.
+ * If this event is MotionEvent#ACTION_DOWN, then this value is equal to `time`.
*
* This is obtained from MotionEvent#getDownTime, which uses SystemClock.uptimeMillis() as
* the clock.
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl
index d12605c..a065a7c 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorLocation.aidl
@@ -15,7 +15,9 @@
*/
package android.hardware.biometrics.fingerprint;
-
+/**
+ * @hide
+ */
@VintfStability
parcelable SensorLocation {
/**
diff --git a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl
index fb516da..d4e9ec6 100644
--- a/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl
+++ b/biometrics/fingerprint/aidl/android/hardware/biometrics/fingerprint/SensorProps.aidl
@@ -19,7 +19,9 @@
import android.hardware.biometrics.common.CommonProps;
import android.hardware.biometrics.fingerprint.FingerprintSensorType;
import android.hardware.biometrics.fingerprint.SensorLocation;
-
+/**
+ * @hide
+ */
@VintfStability
parcelable SensorProps {
/**
diff --git a/biometrics/fingerprint/aidl/default/Android.bp b/biometrics/fingerprint/aidl/default/Android.bp
index dc0199c..fe224c9 100644
--- a/biometrics/fingerprint/aidl/default/Android.bp
+++ b/biometrics/fingerprint/aidl/default/Android.bp
@@ -15,6 +15,7 @@
vintf_fragments: ["fingerprint-example.xml"],
local_include_dirs: ["include"],
srcs: [
+ "FakeLockoutTracker.cpp",
"FakeFingerprintEngine.cpp",
"FakeFingerprintEngineRear.cpp",
"FakeFingerprintEngineUdfps.cpp",
@@ -26,8 +27,8 @@
shared_libs: [
"libbase",
"libbinder_ndk",
- "android.hardware.biometrics.fingerprint-V2-ndk",
- "android.hardware.biometrics.common-V2-ndk",
+ "android.hardware.biometrics.fingerprint-V3-ndk",
+ "android.hardware.biometrics.common-V3-ndk",
"android.hardware.biometrics.common.thread",
"android.hardware.biometrics.common.util",
],
@@ -40,6 +41,7 @@
srcs: [
"tests/FakeFingerprintEngineTest.cpp",
"FakeFingerprintEngine.cpp",
+ "FakeLockoutTracker.cpp",
],
shared_libs: [
"libbase",
@@ -48,9 +50,9 @@
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
- "android.hardware.biometrics.fingerprint-V2-ndk",
- "android.hardware.biometrics.common-V2-ndk",
- "android.hardware.keymaster-V3-ndk",
+ "android.hardware.biometrics.fingerprint-V3-ndk",
+ "android.hardware.biometrics.common-V3-ndk",
+ "android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
],
vendor: true,
@@ -65,6 +67,7 @@
"tests/FakeFingerprintEngineUdfpsTest.cpp",
"FakeFingerprintEngineUdfps.cpp",
"FakeFingerprintEngine.cpp",
+ "FakeLockoutTracker.cpp",
],
shared_libs: [
"libbase",
@@ -73,9 +76,33 @@
],
static_libs: [
"libandroid.hardware.biometrics.fingerprint.VirtualProps",
- "android.hardware.biometrics.fingerprint-V2-ndk",
- "android.hardware.biometrics.common-V2-ndk",
- "android.hardware.keymaster-V3-ndk",
+ "android.hardware.biometrics.fingerprint-V3-ndk",
+ "android.hardware.biometrics.common-V3-ndk",
+ "android.hardware.keymaster-V4-ndk",
+ "android.hardware.biometrics.common.util",
+ ],
+ vendor: true,
+ test_suites: ["general-tests"],
+ require_root: true,
+}
+
+cc_test {
+ name: "android.hardware.biometrics.fingerprint.FakeLockoutTrackerTest",
+ local_include_dirs: ["include"],
+ srcs: [
+ "tests/FakeLockoutTrackerTest.cpp",
+ "FakeLockoutTracker.cpp",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "android.hardware.biometrics.common.thread",
+ ],
+ static_libs: [
+ "libandroid.hardware.biometrics.fingerprint.VirtualProps",
+ "android.hardware.biometrics.fingerprint-V3-ndk",
+ "android.hardware.biometrics.common-V3-ndk",
+ "android.hardware.keymaster-V4-ndk",
"android.hardware.biometrics.common.util",
],
vendor: true,
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
index 68a1f26..90ec8f2 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngine.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -15,6 +15,7 @@
*/
#include "FakeFingerprintEngine.h"
+#include <regex>
#include "Fingerprint.h"
#include <android-base/logging.h>
@@ -47,7 +48,7 @@
void FakeFingerprintEngine::enrollImpl(ISessionCallback* cb,
const keymaster::HardwareAuthToken& hat,
const std::future<void>& cancel) {
- BEGIN_OP(FingerprintHalProperties::operation_enroll_latency().value_or(DEFAULT_LATENCY));
+ BEGIN_OP(getLatency(FingerprintHalProperties::operation_enroll_latency()));
// Do proper HAT verification in the real implementation.
if (hat.mac.empty()) {
@@ -56,43 +57,58 @@
return;
}
- if (FingerprintHalProperties::operation_enroll_fails().value_or(false)) {
- LOG(ERROR) << "Fail: operation_enroll_fails";
- cb->onError(Error::VENDOR, 0 /* vendorError */);
+ // Force error-out
+ auto err = FingerprintHalProperties::operation_enroll_error().value_or(0);
+ if (err != 0) {
+ LOG(ERROR) << "Fail: operation_enroll_error";
+ auto ec = convertError(err);
+ cb->onError(ec.first, ec.second);
return;
}
- // format is "<id>:<progress_ms>,<progress_ms>,...:<result>
+ // Format is "<id>:<progress_ms-[acquiredInfo..]>,...:<result>
auto nextEnroll = FingerprintHalProperties::next_enrollment().value_or("");
auto parts = Util::split(nextEnroll, ":");
if (parts.size() != 3) {
- LOG(ERROR) << "Fail: invalid next_enrollment";
+ LOG(ERROR) << "Fail: invalid next_enrollment:" << nextEnroll;
cb->onError(Error::VENDOR, 0 /* vendorError */);
return;
}
auto enrollmentId = std::stoi(parts[0]);
- auto progress = Util::split(parts[1], ",");
- for (size_t i = 0; i < progress.size(); i++) {
- auto left = progress.size() - i - 1;
- SLEEP_MS(std::stoi(progress[i]));
+ auto progress = parseEnrollmentCapture(parts[1]);
+ for (size_t i = 0; i < progress.size(); i += 2) {
+ auto left = (progress.size() - i) / 2 - 1;
+ auto duration = progress[i][0];
+ auto acquired = progress[i + 1];
+ auto N = acquired.size();
- if (shouldCancel(cancel)) {
- LOG(ERROR) << "Fail: cancel";
- cb->onError(Error::CANCELED, 0 /* vendorCode */);
- return;
+ for (int j = 0; j < N; j++) {
+ SLEEP_MS(duration / N);
+
+ if (shouldCancel(cancel)) {
+ LOG(ERROR) << "Fail: cancel";
+ cb->onError(Error::CANCELED, 0 /* vendorCode */);
+ return;
+ }
+ auto ac = convertAcquiredInfo(acquired[j]);
+ cb->onAcquired(ac.first, ac.second);
}
- cb->onAcquired(AcquiredInfo::GOOD, 0 /* vendorCode */);
if (left == 0 && !IS_TRUE(parts[2])) { // end and failed
LOG(ERROR) << "Fail: requested by caller: " << nextEnroll;
FingerprintHalProperties::next_enrollment({});
cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorCode */);
} else { // progress and update props if last time
+ LOG(INFO) << "onEnroll: " << enrollmentId << " left: " << left;
if (left == 0) {
auto enrollments = FingerprintHalProperties::enrollments();
enrollments.emplace_back(enrollmentId);
FingerprintHalProperties::enrollments(enrollments);
FingerprintHalProperties::next_enrollment({});
+ // change authenticatorId after new enrollment
+ auto id = FingerprintHalProperties::authenticator_id().value_or(0);
+ auto newId = id + 1;
+ FingerprintHalProperties::authenticator_id(newId);
LOG(INFO) << "Enrolled: " << enrollmentId;
}
cb->onEnrollmentProgress(enrollmentId, left);
@@ -102,14 +118,46 @@
void FakeFingerprintEngine::authenticateImpl(ISessionCallback* cb, int64_t /* operationId */,
const std::future<void>& cancel) {
- BEGIN_OP(FingerprintHalProperties::operation_authenticate_latency().value_or(DEFAULT_LATENCY));
+ BEGIN_OP(getLatency(FingerprintHalProperties::operation_authenticate_latency()));
- auto now = Util::getSystemNanoTime();
- int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(0);
+ int64_t now = Util::getSystemNanoTime();
+ int64_t duration = FingerprintHalProperties::operation_authenticate_duration().value_or(10);
+ auto acquired = FingerprintHalProperties::operation_authenticate_acquired().value_or("1");
+ auto acquiredInfos = parseIntSequence(acquired);
+ int N = acquiredInfos.size();
+
+ if (N == 0) {
+ LOG(ERROR) << "Fail to parse authentiate acquired info: " + acquired;
+ cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+ return;
+ }
+
+ // got lockout?
+ FakeLockoutTracker::LockoutMode lockoutMode = mLockoutTracker.getMode();
+ if (lockoutMode == FakeLockoutTracker::LockoutMode::kPermanent) {
+ LOG(ERROR) << "Fail: lockout permanent";
+ cb->onLockoutPermanent();
+ return;
+ } else if (lockoutMode == FakeLockoutTracker::LockoutMode::kTimed) {
+ int64_t timeLeft = mLockoutTracker.getLockoutTimeLeft();
+ LOG(ERROR) << "Fail: lockout timed " << timeLeft;
+ cb->onLockoutTimed(timeLeft);
+ }
+
+ int i = 0;
do {
if (FingerprintHalProperties::operation_authenticate_fails().value_or(false)) {
LOG(ERROR) << "Fail: operation_authenticate_fails";
- cb->onError(Error::VENDOR, 0 /* vendorError */);
+ mLockoutTracker.addFailedAttempt();
+ cb->onAuthenticationFailed();
+ return;
+ }
+
+ auto err = FingerprintHalProperties::operation_authenticate_error().value_or(0);
+ if (err != 0) {
+ LOG(ERROR) << "Fail: operation_authenticate_error";
+ auto ec = convertError(err);
+ cb->onError(ec.first, ec.second);
return;
}
@@ -126,39 +174,79 @@
return;
}
- auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
- auto enrolls = FingerprintHalProperties::enrollments();
- auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
- if (id > 0 && isEnrolled) {
- cb->onAuthenticationSucceeded(id, {} /* hat */);
- return;
+ if (i < N) {
+ auto ac = convertAcquiredInfo(acquiredInfos[i]);
+ cb->onAcquired(ac.first, ac.second);
+ i++;
}
- SLEEP_MS(100);
+ SLEEP_MS(duration / N);
} while (!Util::hasElapsed(now, duration));
- LOG(ERROR) << "Fail: not enrolled";
- cb->onAuthenticationFailed();
- cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+ auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
+ auto enrolls = FingerprintHalProperties::enrollments();
+ auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
+ if (id > 0 && isEnrolled) {
+ cb->onAuthenticationSucceeded(id, {} /* hat */);
+ mLockoutTracker.reset();
+ return;
+ } else {
+ LOG(ERROR) << "Fail: fingerprint not enrolled";
+ cb->onAuthenticationFailed();
+ mLockoutTracker.addFailedAttempt();
+ }
}
void FakeFingerprintEngine::detectInteractionImpl(ISessionCallback* cb,
const std::future<void>& cancel) {
- BEGIN_OP(FingerprintHalProperties::operation_detect_interaction_latency().value_or(
- DEFAULT_LATENCY));
+ BEGIN_OP(getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
- if (FingerprintHalProperties::operation_detect_interaction_fails().value_or(false)) {
- LOG(ERROR) << "Fail: operation_detect_interaction_fails";
- cb->onError(Error::VENDOR, 0 /* vendorError */);
+ int64_t duration =
+ FingerprintHalProperties::operation_detect_interaction_duration().value_or(10);
+
+ auto detectInteractionSupported =
+ FingerprintHalProperties::detect_interaction().value_or(false);
+ if (!detectInteractionSupported) {
+ LOG(ERROR) << "Detect interaction is not supported";
+ cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
return;
}
- if (shouldCancel(cancel)) {
- LOG(ERROR) << "Fail: cancel";
- cb->onError(Error::CANCELED, 0 /* vendorCode */);
+ auto acquired = FingerprintHalProperties::operation_detect_interaction_acquired().value_or("1");
+ auto acquiredInfos = parseIntSequence(acquired);
+ int N = acquiredInfos.size();
+ int64_t now = Util::getSystemNanoTime();
+
+ if (N == 0) {
+ LOG(ERROR) << "Fail to parse detect interaction acquired info: " + acquired;
+ cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
return;
}
+ int i = 0;
+ do {
+ auto err = FingerprintHalProperties::operation_detect_interaction_error().value_or(0);
+ if (err != 0) {
+ LOG(ERROR) << "Fail: operation_detect_interaction_error";
+ auto ec = convertError(err);
+ cb->onError(ec.first, ec.second);
+ return;
+ }
+
+ if (shouldCancel(cancel)) {
+ LOG(ERROR) << "Fail: cancel";
+ cb->onError(Error::CANCELED, 0 /* vendorCode */);
+ return;
+ }
+
+ if (i < N) {
+ auto ac = convertAcquiredInfo(acquiredInfos[i]);
+ cb->onAcquired(ac.first, ac.second);
+ i++;
+ }
+ SLEEP_MS(duration / N);
+ } while (!Util::hasElapsed(now, duration));
+
auto id = FingerprintHalProperties::enrollment_hit().value_or(0);
auto enrolls = FingerprintHalProperties::enrollments();
auto isEnrolled = std::find(enrolls.begin(), enrolls.end(), id) != enrolls.end();
@@ -211,26 +299,40 @@
void FakeFingerprintEngine::getAuthenticatorIdImpl(ISessionCallback* cb) {
BEGIN_OP(0);
- int64_t authenticatorId = FingerprintHalProperties::authenticator_id().value_or(0);
- if (FingerprintHalProperties::enrollments().size() > 0 && authenticatorId == 0) {
- authenticatorId = 99999999; // default authenticatorId, TODO(b/230515082)
+ int64_t authenticatorId;
+ if (FingerprintHalProperties::enrollments().size() == 0) {
+ authenticatorId = 0;
+ } else {
+ authenticatorId = FingerprintHalProperties::authenticator_id().value_or(0);
+ if (authenticatorId == 0) authenticatorId = 1;
}
cb->onAuthenticatorIdRetrieved(authenticatorId);
}
void FakeFingerprintEngine::invalidateAuthenticatorIdImpl(ISessionCallback* cb) {
BEGIN_OP(0);
- auto id = FingerprintHalProperties::authenticator_id().value_or(0);
- auto newId = id + 1;
+ int64_t newId;
+ if (FingerprintHalProperties::enrollments().size() == 0) {
+ newId = 0;
+ } else {
+ auto id = FingerprintHalProperties::authenticator_id().value_or(0);
+ newId = id + 1;
+ }
FingerprintHalProperties::authenticator_id(newId);
cb->onAuthenticatorIdInvalidated(newId);
}
void FakeFingerprintEngine::resetLockoutImpl(ISessionCallback* cb,
- const keymaster::HardwareAuthToken& /*hat*/) {
+ const keymaster::HardwareAuthToken& hat) {
BEGIN_OP(0);
+ if (hat.mac.empty()) {
+ LOG(ERROR) << "Fail: hat in resetLockout()";
+ cb->onError(Error::UNABLE_TO_PROCESS, 0 /* vendorError */);
+ return;
+ }
FingerprintHalProperties::lockout(false);
cb->onLockoutCleared();
+ mLockoutTracker.reset();
}
ndk::ScopedAStatus FakeFingerprintEngine::onPointerDownImpl(int32_t /*pointerId*/, int32_t /*x*/,
@@ -286,4 +388,129 @@
return {0 /* displayId (not used) */, 0 /* sensorLocationX */, 0 /* sensorLocationY */,
0 /* sensorRadius */, "" /* display */};
}
+
+std::vector<int32_t> FakeFingerprintEngine::parseIntSequence(const std::string& str,
+ const std::string& sep) {
+ std::vector<std::string> seqs = Util::split(str, sep);
+ std::vector<int32_t> res;
+
+ for (const auto& seq : seqs) {
+ int32_t val;
+ if (ParseInt(seq, &val)) {
+ res.push_back(val);
+ } else {
+ LOG(WARNING) << "Invalid int sequence:" + str;
+ res.clear();
+ break;
+ }
+ }
+
+ return res;
+}
+
+bool FakeFingerprintEngine::parseEnrollmentCaptureSingle(const std::string& str,
+ std::vector<std::vector<int32_t>>& res) {
+ std::vector<int32_t> defaultAcquiredInfo = {(int32_t)AcquiredInfo::GOOD};
+ bool aborted = true;
+
+ do {
+ std::smatch sms;
+ // Parses strings like "1000-[5,1]" or "500"
+ std::regex ex("((\\d+)(-\\[([\\d|,]+)\\])?)");
+ if (!regex_match(str.cbegin(), str.cend(), sms, ex)) break;
+ int32_t duration;
+ if (!ParseInt(sms.str(2), &duration)) break;
+ res.push_back({duration});
+ if (!sms.str(4).empty()) {
+ auto acqv = parseIntSequence(sms.str(4));
+ if (acqv.empty()) break;
+ res.push_back(acqv);
+ } else
+ res.push_back(defaultAcquiredInfo);
+ aborted = false;
+ } while (0);
+
+ return !aborted;
+}
+
+std::vector<std::vector<int32_t>> FakeFingerprintEngine::parseEnrollmentCapture(
+ const std::string& str) {
+ std::vector<std::vector<int32_t>> res;
+
+ std::string s(str);
+ s.erase(std::remove_if(s.begin(), s.end(), ::isspace), s.end());
+ bool aborted = false;
+ std::smatch sms;
+ // Parses strings like "1000-[5,1],500,800-[6,5,1]"
+ // ---------- --- -----------
+ // into parts: A B C
+ while (regex_search(s, sms, std::regex("^(,)?(\\d+(-\\[[\\d|,]+\\])?)"))) {
+ if (!parseEnrollmentCaptureSingle(sms.str(2), res)) {
+ aborted = true;
+ break;
+ }
+ s = sms.suffix();
+ }
+ if (aborted || s.length() != 0) {
+ res.clear();
+ LOG(ERROR) << "Failed to parse enrollment captures:" + str;
+ }
+
+ return res;
+}
+
+std::pair<AcquiredInfo, int32_t> FakeFingerprintEngine::convertAcquiredInfo(int32_t code) {
+ std::pair<AcquiredInfo, int32_t> res;
+ if (code > FINGERPRINT_ACQUIRED_VENDOR_BASE) {
+ res.first = AcquiredInfo::VENDOR;
+ res.second = code - FINGERPRINT_ACQUIRED_VENDOR_BASE;
+ } else {
+ res.first = (AcquiredInfo)code;
+ res.second = 0;
+ }
+ return res;
+}
+
+std::pair<Error, int32_t> FakeFingerprintEngine::convertError(int32_t code) {
+ std::pair<Error, int32_t> res;
+ if (code > FINGERPRINT_ERROR_VENDOR_BASE) {
+ res.first = Error::VENDOR;
+ res.second = code - FINGERPRINT_ERROR_VENDOR_BASE;
+ } else {
+ res.first = (Error)code;
+ res.second = 0;
+ }
+ return res;
+}
+
+int32_t FakeFingerprintEngine::getLatency(
+ const std::vector<std::optional<std::int32_t>>& latencyIn) {
+ int32_t res = DEFAULT_LATENCY;
+
+ std::vector<int32_t> latency;
+ for (auto x : latencyIn)
+ if (x.has_value()) latency.push_back(*x);
+
+ switch (latency.size()) {
+ case 0:
+ break;
+ case 1:
+ res = latency[0];
+ break;
+ case 2:
+ res = getRandomInRange(latency[0], latency[1]);
+ break;
+ default:
+ LOG(ERROR) << "ERROR: unexpected input of size " << latency.size();
+ break;
+ }
+
+ return res;
+}
+
+int32_t FakeFingerprintEngine::getRandomInRange(int32_t bound1, int32_t bound2) {
+ std::uniform_int_distribution<int32_t> dist(std::min(bound1, bound2), std::max(bound1, bound2));
+ return dist(mRandom);
+}
+
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp
index d8579a4..3cdfc70 100644
--- a/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp
+++ b/biometrics/fingerprint/aidl/default/FakeFingerprintEngineUdfps.cpp
@@ -23,10 +23,16 @@
#include "util/CancellationSignal.h"
#include "util/Util.h"
+#undef LOG_TAG
+#define LOG_TAG "FingerprintVirtualHalUdfps"
+
using namespace ::android::fingerprint::virt;
namespace aidl::android::hardware::biometrics::fingerprint {
+FakeFingerprintEngineUdfps::FakeFingerprintEngineUdfps()
+ : FakeFingerprintEngine(), mWorkMode(WorkMode::kIdle), mPointerDownTime(0), mUiReadyTime(0) {}
+
SensorLocation FakeFingerprintEngineUdfps::defaultSensorLocation() {
return {0 /* displayId (not used) */, defaultSensorLocationX /* sensorLocationX */,
defaultSensorLocationY /* sensorLocationY */, defaultSensorRadius /* sensorRadius */,
@@ -37,22 +43,95 @@
int32_t /*x*/, int32_t /*y*/,
float /*minor*/, float /*major*/) {
BEGIN_OP(0);
-
- // TODO(b/230515082): if need to handle display touch events
-
+ // verify whetehr touch coordinates/area matching sensor location ?
+ mPointerDownTime = Util::getSystemNanoTime();
+ if (FingerprintHalProperties::control_illumination().value_or(false)) {
+ fingerDownAction();
+ }
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus FakeFingerprintEngineUdfps::onPointerUpImpl(int32_t /*pointerId*/) {
BEGIN_OP(0);
- // TODO(b/230515082)
+ mUiReadyTime = 0;
+ mPointerDownTime = 0;
return ndk::ScopedAStatus::ok();
}
ndk::ScopedAStatus FakeFingerprintEngineUdfps::onUiReadyImpl() {
BEGIN_OP(0);
- // TODO(b/230515082)
+
+ if (Util::hasElapsed(mPointerDownTime, uiReadyTimeoutInMs * 100)) {
+ LOG(ERROR) << "onUiReady() arrives too late after onPointerDown()";
+ } else {
+ fingerDownAction();
+ }
return ndk::ScopedAStatus::ok();
}
+void FakeFingerprintEngineUdfps::fingerDownAction() {
+ switch (mWorkMode) {
+ case WorkMode::kAuthenticate:
+ onAuthenticateFingerDown();
+ break;
+ case WorkMode::kEnroll:
+ onEnrollFingerDown();
+ break;
+ case WorkMode::kDetectInteract:
+ onDetectInteractFingerDown();
+ break;
+ default:
+ LOG(WARNING) << "unexpected call: onUiReady()";
+ break;
+ }
+
+ mUiReadyTime = 0;
+ mPointerDownTime = 0;
+}
+
+void FakeFingerprintEngineUdfps::onAuthenticateFingerDown() {
+ FakeFingerprintEngine::authenticateImpl(mCb, mOperationId, mCancelVec[0]);
+}
+
+void FakeFingerprintEngineUdfps::onEnrollFingerDown() {
+ // Any use case to emulate display touch for each capture during enrollment?
+ FakeFingerprintEngine::enrollImpl(mCb, mHat, mCancelVec[0]);
+}
+
+void FakeFingerprintEngineUdfps::onDetectInteractFingerDown() {
+ FakeFingerprintEngine::detectInteractionImpl(mCb, mCancelVec[0]);
+}
+
+void FakeFingerprintEngineUdfps::enrollImpl(ISessionCallback* cb,
+ const keymaster::HardwareAuthToken& hat,
+ const std::future<void>& cancel) {
+ updateContext(WorkMode::kEnroll, cb, const_cast<std::future<void>&>(cancel), 0, hat);
+}
+
+void FakeFingerprintEngineUdfps::authenticateImpl(ISessionCallback* cb, int64_t operationId,
+ const std::future<void>& cancel) {
+ updateContext(WorkMode::kAuthenticate, cb, const_cast<std::future<void>&>(cancel), operationId,
+ keymaster::HardwareAuthToken());
+}
+
+void FakeFingerprintEngineUdfps::detectInteractionImpl(ISessionCallback* cb,
+ const std::future<void>& cancel) {
+ updateContext(WorkMode::kDetectInteract, cb, const_cast<std::future<void>&>(cancel), 0,
+ keymaster::HardwareAuthToken());
+}
+
+void FakeFingerprintEngineUdfps::updateContext(WorkMode mode, ISessionCallback* cb,
+ std::future<void>& cancel, int64_t operationId,
+ const keymaster::HardwareAuthToken& hat) {
+ mPointerDownTime = 0;
+ mUiReadyTime = 0;
+ mCancelVec.clear();
+
+ mCancelVec.push_back(std::move(cancel));
+ mWorkMode = mode;
+ mCb = cb;
+ mOperationId = operationId;
+ mHat = hat;
+}
+
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
new file mode 100644
index 0000000..5996406
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/FakeLockoutTracker.cpp
@@ -0,0 +1,77 @@
+/*
+ * 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 "FakeLockoutTracker.h"
+#include <fingerprint.sysprop.h>
+#include "util/Util.h"
+
+using namespace ::android::fingerprint::virt;
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+void FakeLockoutTracker::reset() {
+ mFailedCount = 0;
+ mLockoutTimedStart = 0;
+ mCurrentMode = LockoutMode::kNone;
+}
+
+void FakeLockoutTracker::addFailedAttempt() {
+ bool enabled = FingerprintHalProperties::lockout_enable().value_or(false);
+ if (enabled) {
+ mFailedCount++;
+ int32_t lockoutTimedThreshold =
+ FingerprintHalProperties::lockout_timed_threshold().value_or(5);
+ int32_t lockoutPermanetThreshold =
+ FingerprintHalProperties::lockout_permanent_threshold().value_or(20);
+ if (mFailedCount >= lockoutPermanetThreshold) {
+ mCurrentMode = LockoutMode::kPermanent;
+ FingerprintHalProperties::lockout(true);
+ } else if (mFailedCount >= lockoutTimedThreshold) {
+ if (mCurrentMode == LockoutMode::kNone) {
+ mCurrentMode = LockoutMode::kTimed;
+ mLockoutTimedStart = Util::getSystemNanoTime();
+ }
+ }
+ } else {
+ reset();
+ }
+}
+
+FakeLockoutTracker::LockoutMode FakeLockoutTracker::getMode() {
+ if (mCurrentMode == LockoutMode::kTimed) {
+ int32_t lockoutTimedDuration =
+ FingerprintHalProperties::lockout_timed_duration().value_or(10 * 100);
+ if (Util::hasElapsed(mLockoutTimedStart, lockoutTimedDuration)) {
+ mCurrentMode = LockoutMode::kNone;
+ mLockoutTimedStart = 0;
+ }
+ }
+
+ return mCurrentMode;
+}
+
+int64_t FakeLockoutTracker::getLockoutTimeLeft() {
+ int64_t res = 0;
+
+ if (mLockoutTimedStart > 0) {
+ auto now = Util::getSystemNanoTime();
+ auto left = now - mLockoutTimedStart;
+ res = (left > 0) ? (left / 1000000LL) : 0;
+ }
+
+ return res;
+}
+} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/Fingerprint.cpp b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
index 922781c..be93224 100644
--- a/biometrics/fingerprint/aidl/default/Fingerprint.cpp
+++ b/biometrics/fingerprint/aidl/default/Fingerprint.cpp
@@ -15,11 +15,13 @@
*/
#include "Fingerprint.h"
-
-#include <fingerprint.sysprop.h>
#include "Session.h"
+#include <fingerprint.sysprop.h>
+
+#include <android-base/file.h>
#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
using namespace ::android::fingerprint::virt;
@@ -64,19 +66,31 @@
{HW_COMPONENT_ID, HW_VERSION, FW_VERSION, SERIAL_NUMBER, "" /* softwareVersion */},
{SW_COMPONENT_ID, "" /* hardwareVersion */, "" /* firmwareVersion */,
"" /* serialNumber */, SW_VERSION}};
+ auto sensorId = FingerprintHalProperties::sensor_id().value_or(SENSOR_ID);
+ auto sensorStrength =
+ FingerprintHalProperties::sensor_strength().value_or((int)SENSOR_STRENGTH);
+ auto maxEnrollments =
+ FingerprintHalProperties::max_enrollments().value_or(MAX_ENROLLMENTS_PER_USER);
+ auto navigationGuesture = FingerprintHalProperties::navigation_guesture().value_or(false);
+ auto detectInteraction = FingerprintHalProperties::detect_interaction().value_or(false);
+ auto displayTouch = FingerprintHalProperties::display_touch().value_or(true);
+ auto controlIllumination = FingerprintHalProperties::control_illumination().value_or(false);
- common::CommonProps commonProps = {SENSOR_ID, SENSOR_STRENGTH, MAX_ENROLLMENTS_PER_USER,
- componentInfo};
+ common::CommonProps commonProps = {sensorId, (common::SensorStrength)sensorStrength,
+ maxEnrollments, componentInfo};
SensorLocation sensorLocation = mEngine->getSensorLocation();
- LOG(INFO) << "sensor type:" << (int)mSensorType << " location:" << sensorLocation.toString();
+ LOG(INFO) << "sensor type:" << ::android::internal::ToString(mSensorType)
+ << " location:" << sensorLocation.toString();
*out = {{commonProps,
mSensorType,
{sensorLocation},
- SUPPORTS_NAVIGATION_GESTURES,
- false /* supportsDetectInteraction */}};
+ navigationGuesture,
+ detectInteraction,
+ displayTouch,
+ controlIllumination}};
return ndk::ScopedAStatus::ok();
}
@@ -92,4 +106,96 @@
return ndk::ScopedAStatus::ok();
}
+binder_status_t Fingerprint::dump(int fd, const char** /*args*/, uint32_t numArgs) {
+ if (fd < 0) {
+ LOG(ERROR) << "Fingerprint::dump fd invalid: " << fd;
+ return STATUS_BAD_VALUE;
+ } else {
+ LOG(INFO) << "Fingerprint::dump fd:" << fd << "numArgs:" << numArgs;
+ }
+
+ dprintf(fd, "----- FingerprintVirtualHal::dump -----\n");
+ std::vector<SensorProps> sps(1);
+ getSensorProps(&sps);
+ for (auto& sp : sps) {
+ ::android::base::WriteStringToFd(sp.toString(), fd);
+ }
+ ::android::base::WriteStringToFd(mEngine->toString(), fd);
+
+ fsync(fd);
+ return STATUS_OK;
+}
+
+binder_status_t Fingerprint::handleShellCommand(int in, int out, int err, const char** args,
+ uint32_t numArgs) {
+ LOG(INFO) << "Fingerprint::handleShellCommand in:" << in << " out:" << out << " err:" << err
+ << " numArgs:" << numArgs;
+
+ if (numArgs == 0) {
+ LOG(INFO) << "Fingerprint::handleShellCommand: available commands";
+ onHelp(out);
+ return STATUS_OK;
+ }
+
+ for (auto&& str : std::vector<std::string_view>(args, args + numArgs)) {
+ std::string option = str.data();
+ if (option.find("clearconfig") != std::string::npos ||
+ option.find("resetconfig") != std::string::npos) {
+ resetConfigToDefault();
+ }
+ if (option.find("help") != std::string::npos) {
+ onHelp(out);
+ }
+ }
+
+ return STATUS_OK;
+}
+
+void Fingerprint::onHelp(int fd) {
+ dprintf(fd, "Virtual HAL commands:\n");
+ dprintf(fd, " help: print this help\n");
+ dprintf(fd, " resetconfig: reset all configuration to default\n");
+ dprintf(fd, "\n");
+ fsync(fd);
+}
+
+void Fingerprint::resetConfigToDefault() {
+ LOG(INFO) << "reset virtual HAL configuration to default";
+#define RESET_CONFIG_O(__NAME__) \
+ if (FingerprintHalProperties::__NAME__()) FingerprintHalProperties::__NAME__(std::nullopt)
+#define RESET_CONFIG_V(__NAME__) \
+ if (!FingerprintHalProperties::__NAME__().empty()) \
+ FingerprintHalProperties::__NAME__({std::nullopt})
+
+ RESET_CONFIG_O(type);
+ RESET_CONFIG_V(enrollments);
+ RESET_CONFIG_O(enrollment_hit);
+ RESET_CONFIG_O(authenticator_id);
+ RESET_CONFIG_O(challenge);
+ RESET_CONFIG_O(lockout);
+ RESET_CONFIG_O(operation_authenticate_fails);
+ RESET_CONFIG_O(operation_detect_interaction_error);
+ RESET_CONFIG_O(operation_enroll_error);
+ RESET_CONFIG_V(operation_authenticate_latency);
+ RESET_CONFIG_V(operation_detect_interaction_latency);
+ RESET_CONFIG_V(operation_enroll_latency);
+ RESET_CONFIG_O(operation_authenticate_duration);
+ RESET_CONFIG_O(operation_authenticate_error);
+ RESET_CONFIG_O(sensor_location);
+ RESET_CONFIG_O(operation_authenticate_acquired);
+ RESET_CONFIG_O(operation_detect_interaction_duration);
+ RESET_CONFIG_O(operation_detect_interaction_acquired);
+ RESET_CONFIG_O(sensor_id);
+ RESET_CONFIG_O(sensor_strength);
+ RESET_CONFIG_O(max_enrollments);
+ RESET_CONFIG_O(navigation_guesture);
+ RESET_CONFIG_O(detect_interaction);
+ RESET_CONFIG_O(display_touch);
+ RESET_CONFIG_O(control_illumination);
+ RESET_CONFIG_O(lockout_enable);
+ RESET_CONFIG_O(lockout_timed_threshold);
+ RESET_CONFIG_O(lockout_timed_duration);
+ RESET_CONFIG_O(lockout_permanent_threshold);
+}
+
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/README.md b/biometrics/fingerprint/aidl/default/README.md
index bb6bb48..49b6c9d 100644
--- a/biometrics/fingerprint/aidl/default/README.md
+++ b/biometrics/fingerprint/aidl/default/README.md
@@ -57,6 +57,7 @@
```shell
$ adb shell setprop vendor.fingerprint.virtual.next_enrollment 1:100,100,100:true
```
+
3. Navigate to `Settings -> Security -> Fingerprint Unlock` and follow the
prompts.
4. Verify the enrollments in the UI:
@@ -65,7 +66,7 @@
$ adb shell getprop persist.vendor.fingerprint.virtual.enrollments
```
-### Authenticate
+## Authenticate
To authenticate successfully set the enrolled id that should succeed. Unset it
or change the value to make authenticate operations fail:
@@ -74,10 +75,91 @@
$ adb shell setprop vendor.fingerprint.virtual.enrollment_hit 1
````
-### View HAL State
+## Acquired Info Insertion
+
+Fingerprint image acquisition states at HAL are reported to framework via onAcquired() callback. The valid acquired state info for AIDL HAL include
+
+{UNKNOWN(0), GOOD(1), PARTIAL(2), INSUFFICIENT(3), SENSOR_DIRTY(4), TOO_SLOW(5), TOO_FAST(6), VENDOR(7), START(8), TOO_DARK(9), TOO_BRIGHT(10), IMMOBILE(11), RETRYING_CAPTURE(12)}
+
+Refer to [AcquiredInfo.aidl](../android/hardware/biometrics/fingerprint/AcquiredInfo.aidl) for details
+
+
+The states can be specified in sequence for the HAL operations involving fingerprint image captures, namely authenticate, enrollment and detectInteraction
+
+```shell
+$ adb shell setprop vendor.fingerprint.virtual.operation_authenticate_acquired 6,9,1
+$ adb shell setprop vendor.fingerprint.virtual.operation_detect_interaction_acquired 6,1
+$ adb shell setprop vendor.fingerprint.virtual.next_enrollment 2:1000-[5,1],500:true
+
+#next_enrollment format example:
+.---------------------- enrollment id (2)
+| .------------------ the image capture 1 duration (1000ms)
+| | .-------------- acquired info first (TOO_SLOW)
+| | | .------------ acquired info second (GOOD)
+| | | | .-------- the image capture 2 duration (500ms)
+| | | | | .---- enrollment end status (success)
+| | | | | |
+| | | | | |
+| | | | | |
+2:1000-[5,1],500:true
+```
+For vendor specific acquired info, acquiredInfo = 1000 + vendorAcquiredInfo
+
+## Error Insertion
+The valid error codes for AIDL HAL include
+
+{UNKNOWN(0), HW_UNAVAILABLE(1), UNABLE_TO_PROCESS(2), TIMEOUT(3), NO_SPACE(4), CANCELED(5), UNABLE_TO_REMOVE(6), VENDOR(7), BAD_CALIBRATION(8)}
+
+Refer to [Error.aidl](../android/hardware/biometrics/fingerprint/Error.aidl) for details
+
+
+There are many HAL operations which can result in errors, refer to [here](fingerprint.sysprop) file for details.
+
+```shell
+$ adb shell setprop vendor.fingerprint.virtual.operation_authenticate_error 8
+```
+For vendor specific error, errorCode = 1000 + vendorErrorCode
+
+## Latency Insertion
+Three HAL operations (authenticate, enrollment and detect interaction) latency can be optionally specified in multiple ways
+1. default latency is fixed at 400 ms if not specified via sysprop
+2. specify authenticate operation latency to 900 ms
+ ```shell adb shell setprop vendor.fingerprint.virtual.operation_authenticate_latency 900```
+3. specify authenticate operation latency between 600 to 1200 ms in unifrom distribution
+ ```shelladb shell setprop vendor.fingerprint.virtual.operation_authenticate_latency 600,1200```
+
+## Lockout
+To force the device into lockout state
+```shell
+$ adb shell setprop persist.vendor.fingerprint.virtual.lockout true
+```
+To test permanent lockout based on the failed authentication attempts (e.g. 7)
+```shell
+$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_permanent_threshold 7
+$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_enable true
+```
+To test timed lockout based on the failed authentication attempts (e.g. 8 seconds on 5 attempts)
+```shell
+$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_timed_duration 8000
+$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_timed_threshold 5
+$ adb shell setprop persist.vendor.fingerprint.virtual.lockout_enable true
+```
+
+## Reset all configurations to default
+The following command will reset virtual configurations (related system properties) to default value.
+```shell
+$ adb shell cmd android.hardware.biometrics.fingerprint.IFingerprint/virtual resetconfig
+$ adb reboot
+```
+
+## View HAL State
To view all the properties of the HAL (see `fingerprint.sysprop` file for the API):
```shell
$ adb shell getprop | grep vendor.fingerprint.virtual
```
+To dump virtual HAL internal data
+```shell
+adb shell dumpsys android.hardware.biometrics.fingerprint.IFingerprint/virtual
+```
diff --git a/biometrics/fingerprint/aidl/default/Session.cpp b/biometrics/fingerprint/aidl/default/Session.cpp
index e51f677..7ab5af3 100644
--- a/biometrics/fingerprint/aidl/default/Session.cpp
+++ b/biometrics/fingerprint/aidl/default/Session.cpp
@@ -20,6 +20,9 @@
#include "util/CancellationSignal.h"
+#undef LOG_TAG
+#define LOG_TAG "FingerprintVirtualHalSession"
+
namespace aidl::android::hardware::biometrics::fingerprint {
Session::Session(int sensorId, int userId, std::shared_ptr<ISessionCallback> cb,
diff --git a/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt b/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
index 9dfb74d..e69de29 100644
--- a/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
+++ b/biometrics/fingerprint/aidl/default/api/android.hardware.biometrics.fingerprint.VirtualProps-current.txt
@@ -1,91 +0,0 @@
-props {
- owner: Vendor
- module: "android.fingerprint.virt.FingerprintHalProperties"
- prop {
- api_name: "authenticator_id"
- type: Long
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.authenticator_id"
- }
- prop {
- api_name: "challenge"
- type: Long
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.challenge"
- }
- prop {
- api_name: "enrollment_hit"
- type: Integer
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.enrollment_hit"
- }
- prop {
- api_name: "enrollments"
- type: IntegerList
- access: ReadWrite
- prop_name: "persist.vendor.fingerprint.virtual.enrollments"
- }
- prop {
- api_name: "lockout"
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.lockout"
- }
- prop {
- api_name: "next_enrollment"
- type: String
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.next_enrollment"
- }
- prop {
- api_name: "operation_authenticate_duration"
- type: Integer
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.operation_authenticate_duration"
- }
- prop {
- api_name: "operation_authenticate_fails"
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.operation_authenticate_fails"
- }
- prop {
- api_name: "operation_authenticate_latency"
- type: Integer
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.operation_authenticate_latency"
- }
- prop {
- api_name: "operation_detect_interaction_fails"
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_fails"
- }
- prop {
- api_name: "operation_detect_interaction_latency"
- type: Integer
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_latency"
- }
- prop {
- api_name: "operation_enroll_fails"
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.operation_enroll_fails"
- }
- prop {
- api_name: "operation_enroll_latency"
- type: Integer
- access: ReadWrite
- prop_name: "vendor.fingerprint.virtual.operation_enroll_latency"
- }
- prop {
- api_name: "sensor_location"
- type: String
- access: ReadWrite
- prop_name: "persist.vendor.fingerprint.virtual.sensor_location"
- }
- prop {
- api_name: "type"
- type: String
- access: ReadWrite
- prop_name: "persist.vendor.fingerprint.virtual.type"
- enum_values: "default|rear|udfps|side"
- }
-}
diff --git a/biometrics/fingerprint/aidl/default/fingerprint-example.xml b/biometrics/fingerprint/aidl/default/fingerprint-example.xml
index 05d1279..e977b98 100644
--- a/biometrics/fingerprint/aidl/default/fingerprint-example.xml
+++ b/biometrics/fingerprint/aidl/default/fingerprint-example.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.biometrics.fingerprint</name>
- <version>2</version>
+ <version>3</version>
<fqname>IFingerprint/virtual</fqname>
</hal>
</manifest>
diff --git a/biometrics/fingerprint/aidl/default/fingerprint.sysprop b/biometrics/fingerprint/aidl/default/fingerprint.sysprop
index 85e93b0..6a6c297 100644
--- a/biometrics/fingerprint/aidl/default/fingerprint.sysprop
+++ b/biometrics/fingerprint/aidl/default/fingerprint.sysprop
@@ -7,7 +7,7 @@
prop {
prop_name: "persist.vendor.fingerprint.virtual.type"
type: String
- scope: Public
+ scope: Internal
access: ReadWrite
enum_values: "default|rear|udfps|side"
api_name: "type"
@@ -17,7 +17,7 @@
prop {
prop_name: "persist.vendor.fingerprint.virtual.enrollments"
type: IntegerList
- scope: Public
+ scope: Internal
access: ReadWrite
api_name: "enrollments"
}
@@ -27,27 +27,31 @@
prop {
prop_name: "vendor.fingerprint.virtual.enrollment_hit"
type: Integer
- scope: Public
+ scope: Internal
access: ReadWrite
api_name: "enrollment_hit"
}
-# the next enrollment in the format: "<id>:<delay>,<delay>,...:<result>"
-# for example: "2:0:true"
+# the next enrollment in the format of:
+# "<id>:<delay>,<delay>,...:<result>"
+# <delay> = <duration-[acquiredInfos]>
+# [acquiredInfos] = [acquiredInfo1, acquiredInfo2, ...]
+# (refer to README.md file for acquiredInfo values)
+# e.g. "2:100,20:true", "2:100-[5,1],20:true"
# this property is reset after enroll completes
prop {
prop_name: "vendor.fingerprint.virtual.next_enrollment"
type: String
- scope: Public
+ scope: Internal
access: ReadWrite
api_name: "next_enrollment"
}
# value for getAuthenticatorId or 0
prop {
- prop_name: "vendor.fingerprint.virtual.authenticator_id"
+ prop_name: "persist.vendor.fingerprint.virtual.authenticator_id"
type: Long
- scope: Public
+ scope: Internal
access: ReadWrite
api_name: "authenticator_id"
}
@@ -56,70 +60,71 @@
prop {
prop_name: "vendor.fingerprint.virtual.challenge"
type: Long
- scope: Public
+ scope: Internal
access: ReadWrite
api_name: "challenge"
}
-# if locked out
-prop {
- prop_name: "vendor.fingerprint.virtual.lockout"
- type: Boolean
- scope: Public
- access: ReadWrite
- api_name: "lockout"
-}
-
# force all authenticate operations to fail
prop {
prop_name: "vendor.fingerprint.virtual.operation_authenticate_fails"
type: Boolean
- scope: Public
+ scope: Internal
access: ReadWrite
api_name: "operation_authenticate_fails"
}
-# force all detectInteraction operations to fail
+# force all detectInteraction operations to error out
+# error consists of errorCode and vendorErrorCode
+# valid errorCodes are listed in README.md file
+# vendorErrorCode = (error>1000) ? error-1000 : 0
+# e.g. error(1002) --> errorCode(7) and vendorErrorCode(2)
prop {
- prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_fails"
- type: Boolean
- scope: Public
+ prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_error"
+ type: Integer
+ scope: Internal
access: ReadWrite
- api_name: "operation_detect_interaction_fails"
+ api_name: "operation_detect_interaction_error"
}
-# force all enroll operations to fail
+# force all enroll operations to result in error
prop {
- prop_name: "vendor.fingerprint.virtual.operation_enroll_fails"
- type: Boolean
- scope: Public
+ prop_name: "vendor.fingerprint.virtual.operation_enroll_error"
+ type: Integer
+ scope: Internal
access: ReadWrite
- api_name: "operation_enroll_fails"
+ api_name: "operation_enroll_error"
}
# add a latency to authentication operations
+# default to 400ms
+# [x] = x ms
+# [x,y] = randomly between x and y ms
+# others = invalid
prop {
prop_name: "vendor.fingerprint.virtual.operation_authenticate_latency"
- type: Integer
- scope: Public
+ type: IntegerList
+ scope: Internal
access: ReadWrite
api_name: "operation_authenticate_latency"
}
# add a latency to detectInteraction operations
+# refer to `operation_authenticate_latency` above for usage
prop {
prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_latency"
- type: Integer
- scope: Public
+ type: IntegerList
+ scope: Internal
access: ReadWrite
api_name: "operation_detect_interaction_latency"
}
# add a latency to enroll operations
+# refer to `operation_authenticate_latency` above for usage
prop {
prop_name: "vendor.fingerprint.virtual.operation_enroll_latency"
- type: Integer
- scope: Public
+ type: IntegerList
+ scope: Internal
access: ReadWrite
api_name: "operation_enroll_latency"
}
@@ -129,17 +134,167 @@
prop {
prop_name: "vendor.fingerprint.virtual.operation_authenticate_duration"
type: Integer
- scope: Public
+ scope: Internal
access: ReadWrite
api_name: "operation_authenticate_duration"
}
+# insert error for authenticate operations
+prop {
+ prop_name: "vendor.fingerprint.virtual.operation_authenticate_error"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "operation_authenticate_error"
+}
+
# sensor location
# <x>:<y>:<radius> in pixel
prop {
prop_name: "persist.vendor.fingerprint.virtual.sensor_location"
type: String
- scope: Public
+ scope: Internal
access: ReadWrite
api_name: "sensor_location"
}
+
+# acquired info during authentication in format of sequence
+prop {
+ prop_name: "vendor.fingerprint.virtual.operation_authenticate_acquired"
+ type: String
+ scope: Internal
+ access: ReadWrite
+ api_name: "operation_authenticate_acquired"
+}
+
+# millisecond duration for detect interaction operations
+# (waits for changes to enrollment_hit)
+prop {
+ prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_duration"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "operation_detect_interaction_duration"
+}
+
+# acquired info during detect interaction operation in format of sequence
+# e.g. 5,6,1 (TOO_SLOW, TOO_FAST, GOOD)
+# onAcquired() callback will be invoked in sequence
+# vendorAcquiredCode = (acquired>1000) ? acquired-1000 : 0
+prop {
+ prop_name: "vendor.fingerprint.virtual.operation_detect_interaction_acquired"
+ type: String
+ scope: Internal
+ access: ReadWrite
+ api_name: "operation_detect_interaction_acquired"
+}
+
+# sensor id (default: 5)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.sensor_id"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "sensor_id"
+}
+
+# sensor strength (default: 2)
+# [0=CONVENECE, 1=WEAK, 2=STRONG]
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.sensor_strength"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "sensor_strength"
+}
+
+# max enrollments per user (default: 5)
+#
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.max_enrollments"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "max_enrollments"
+}
+
+# whether support navigation guestures (default: false)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.navigation_guesture"
+ type: Boolean
+ scope: Internal
+ access: ReadWrite
+ api_name: "navigation_guesture"
+}
+
+# whether support detect interaction (default: false)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.detect_interaction"
+ type: Boolean
+ scope: Internal
+ access: ReadWrite
+ api_name: "detect_interaction"
+}
+
+# whether support display touch by hal (default: true)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.udfps.display_touch"
+ type: Boolean
+ scope: Internal
+ access: ReadWrite
+ api_name: "display_touch"
+}
+
+# whether support illumination control by hal (default: false)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.udfps.control_illumination"
+ type: Boolean
+ scope: Internal
+ access: ReadWrite
+ api_name: "control_illumination"
+}
+
+# force to be locked out (default: false)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.lockout"
+ type: Boolean
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout"
+}
+
+# whether support lockout based on the failed auth attempts (default: false)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.lockout_enable"
+ type: Boolean
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout_enable"
+}
+
+# temporarily lockout threshold in number of consecutive failed auth attempts (default: 5)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_threshold"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout_timed_threshold"
+}
+
+# temporary lockout duration in ms (default: 10000ms)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.lockout_timed_duration"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout_timed_duration"
+}
+
+# permanently lockout threshold in number of consecutive failed auth attempts (default: 20)
+prop {
+ prop_name: "persist.vendor.fingerprint.virtual.lockout_permanent_threshold"
+ type: Integer
+ scope: Internal
+ access: ReadWrite
+ api_name: "lockout_permanent_threshold"
+}
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
index d7df818..1279cd9 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngine.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -15,8 +15,13 @@
*/
#pragma once
+
+#define LOG_TAG "FingerprintVirtualHal"
+
#include <aidl/android/hardware/biometrics/common/SensorStrength.h>
#include <aidl/android/hardware/biometrics/fingerprint/ISessionCallback.h>
+#include <android/binder_to_string.h>
+#include <string>
#include <random>
@@ -24,6 +29,8 @@
#include <future>
#include <vector>
+#include "FakeLockoutTracker.h"
+
using namespace ::aidl::android::hardware::biometrics::common;
namespace aidl::android::hardware::biometrics::fingerprint {
@@ -36,11 +43,11 @@
void generateChallengeImpl(ISessionCallback* cb);
void revokeChallengeImpl(ISessionCallback* cb, int64_t challenge);
- void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
- const std::future<void>& cancel);
- void authenticateImpl(ISessionCallback* cb, int64_t operationId,
- const std::future<void>& cancel);
- void detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel);
+ virtual void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
+ const std::future<void>& cancel);
+ virtual void authenticateImpl(ISessionCallback* cb, int64_t operationId,
+ const std::future<void>& cancel);
+ virtual void detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel);
void enumerateEnrollmentsImpl(ISessionCallback* cb);
void removeEnrollmentsImpl(ISessionCallback* cb, const std::vector<int32_t>& enrollmentIds);
void getAuthenticatorIdImpl(ISessionCallback* cb);
@@ -59,7 +66,33 @@
virtual SensorLocation defaultSensorLocation();
+ std::vector<int32_t> parseIntSequence(const std::string& str, const std::string& sep = ",");
+
+ std::vector<std::vector<int32_t>> parseEnrollmentCapture(const std::string& str);
+
+ int32_t getLatency(const std::vector<std::optional<std::int32_t>>& latencyVec);
+
std::mt19937 mRandom;
+
+ virtual std::string toString() const {
+ std::ostringstream os;
+ os << "----- FakeFingerprintEngine:: -----" << std::endl;
+ os << "acquiredVendorInfoBase:" << FINGERPRINT_ACQUIRED_VENDOR_BASE;
+ os << ", errorVendorBase:" << FINGERPRINT_ERROR_VENDOR_BASE << std::endl;
+ os << mLockoutTracker.toString();
+ return os.str();
+ }
+
+ private:
+ static constexpr int32_t FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000;
+ static constexpr int32_t FINGERPRINT_ERROR_VENDOR_BASE = 1000;
+ std::pair<AcquiredInfo, int32_t> convertAcquiredInfo(int32_t code);
+ std::pair<Error, int32_t> convertError(int32_t code);
+ bool parseEnrollmentCaptureSingle(const std::string& str,
+ std::vector<std::vector<int32_t>>& res);
+ int32_t getRandomInRange(int32_t bound1, int32_t bound2);
+
+ FakeLockoutTracker mLockoutTracker;
};
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineRear.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineRear.h
index 1600a4b..14d5399 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineRear.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineRear.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
index 4e44d16..c2fc005 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineSide.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
diff --git a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h
index b86af73..c5e93e7 100644
--- a/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h
+++ b/biometrics/fingerprint/aidl/default/include/FakeFingerprintEngineUdfps.h
@@ -28,17 +28,55 @@
static constexpr int32_t defaultSensorLocationY = 1600;
static constexpr int32_t defaultSensorRadius = 150;
- FakeFingerprintEngineUdfps() : FakeFingerprintEngine() {}
+ static constexpr int32_t uiReadyTimeoutInMs = 5000;
+
+ FakeFingerprintEngineUdfps();
~FakeFingerprintEngineUdfps() {}
- virtual ndk::ScopedAStatus onPointerDownImpl(int32_t pointerId, int32_t x, int32_t y,
- float minor, float major) override;
+ ndk::ScopedAStatus onPointerDownImpl(int32_t pointerId, int32_t x, int32_t y, float minor,
+ float major) override;
- virtual ndk::ScopedAStatus onPointerUpImpl(int32_t pointerId) override;
+ ndk::ScopedAStatus onPointerUpImpl(int32_t pointerId) override;
- virtual ndk::ScopedAStatus onUiReadyImpl() override;
+ ndk::ScopedAStatus onUiReadyImpl() override;
- virtual SensorLocation defaultSensorLocation() override;
+ SensorLocation defaultSensorLocation() override;
+
+ void enrollImpl(ISessionCallback* cb, const keymaster::HardwareAuthToken& hat,
+ const std::future<void>& cancel);
+ void authenticateImpl(ISessionCallback* cb, int64_t operationId,
+ const std::future<void>& cancel);
+ void detectInteractionImpl(ISessionCallback* cb, const std::future<void>& cancel);
+
+ enum class WorkMode : int8_t { kIdle = 0, kAuthenticate, kEnroll, kDetectInteract };
+
+ WorkMode getWorkMode() { return mWorkMode; }
+
+ std::string toString() const {
+ std::ostringstream os;
+ os << FakeFingerprintEngine::toString();
+ os << "----- FakeFingerprintEngineUdfps -----" << std::endl;
+ os << "mWorkMode:" << (int)mWorkMode;
+ os << ", mUiReadyTime:" << mUiReadyTime;
+ os << ", mPointerDownTime:" << mPointerDownTime << std::endl;
+ return os.str();
+ }
+
+ private:
+ void onAuthenticateFingerDown();
+ void onEnrollFingerDown();
+ void onDetectInteractFingerDown();
+ void fingerDownAction();
+ void updateContext(WorkMode mode, ISessionCallback* cb, std::future<void>& cancel,
+ int64_t operationId, const keymaster::HardwareAuthToken& hat);
+
+ WorkMode mWorkMode;
+ ISessionCallback* mCb;
+ keymaster::HardwareAuthToken mHat;
+ std::vector<std::future<void>> mCancelVec;
+ int64_t mOperationId;
+ int64_t mPointerDownTime;
+ int64_t mUiReadyTime;
};
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/FakeLockoutTracker.h b/biometrics/fingerprint/aidl/default/include/FakeLockoutTracker.h
new file mode 100644
index 0000000..a1b6128
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/include/FakeLockoutTracker.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <android/binder_to_string.h>
+#include <stdint.h>
+#include <string>
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+class FakeLockoutTracker {
+ public:
+ FakeLockoutTracker() : mFailedCount(0) {}
+ ~FakeLockoutTracker() {}
+
+ enum class LockoutMode : int8_t { kNone = 0, kTimed, kPermanent };
+
+ void reset();
+ LockoutMode getMode();
+ void addFailedAttempt();
+ int64_t getLockoutTimeLeft();
+ inline std::string toString() const {
+ std::ostringstream os;
+ os << "----- FakeLockoutTracker:: -----" << std::endl;
+ os << "FakeLockoutTracker::mFailedCount:" << mFailedCount;
+ os << ", FakeLockoutTracker::mCurrentMode:" << (int)mCurrentMode;
+ os << std::endl;
+ return os.str();
+ }
+
+ private:
+ int32_t mFailedCount;
+ int64_t mLockoutTimedStart;
+ LockoutMode mCurrentMode;
+};
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/include/Fingerprint.h b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
index 64aafa3..fc4fb8d 100644
--- a/biometrics/fingerprint/aidl/default/include/Fingerprint.h
+++ b/biometrics/fingerprint/aidl/default/include/Fingerprint.h
@@ -16,8 +16,6 @@
#pragma once
-#define LOG_TAG "FingerprintVirtualHal"
-
#include <aidl/android/hardware/biometrics/fingerprint/BnFingerprint.h>
#include "FakeFingerprintEngine.h"
@@ -39,8 +37,13 @@
ndk::ScopedAStatus createSession(int32_t sensorId, int32_t userId,
const std::shared_ptr<ISessionCallback>& cb,
std::shared_ptr<ISession>* out) override;
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs);
+ binder_status_t handleShellCommand(int in, int out, int err, const char** argv, uint32_t argc);
private:
+ void resetConfigToDefault();
+ void onHelp(int);
+
std::unique_ptr<FakeFingerprintEngine> mEngine;
WorkerThread mWorker;
std::shared_ptr<Session> mSession;
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
index 8696d26..a200b39 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineTest.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2021 The Android Open Source Project
+ * 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.
@@ -21,6 +21,7 @@
#include <aidl/android/hardware/biometrics/fingerprint/BnSessionCallback.h>
#include "FakeFingerprintEngine.h"
+#include "util/Util.h"
using namespace ::android::fingerprint::virt;
using namespace ::aidl::android::hardware::biometrics::fingerprint;
@@ -38,8 +39,9 @@
mLastChallengeRevoked = challenge;
return ndk::ScopedAStatus::ok();
};
- ::ndk::ScopedAStatus onError(fingerprint::Error error, int32_t) override {
+ ::ndk::ScopedAStatus onError(fingerprint::Error error, int32_t vendorCode) override {
mError = error;
+ mErrorVendorCode = vendorCode;
return ndk::ScopedAStatus::ok();
};
::ndk::ScopedAStatus onEnrollmentProgress(int32_t enrollmentId, int32_t remaining) override {
@@ -62,7 +64,10 @@
mInteractionDetectedCount++;
return ndk::ScopedAStatus::ok();
};
- ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
+ ndk::ScopedAStatus onAcquired(AcquiredInfo info, int32_t vendorCode) override {
+ mLastAcquiredInfo = (int32_t)info;
+ mLastAcquiredVendorCode = vendorCode;
+ mLastAcquiredCount++;
return ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus onEnrollmentsEnumerated(
@@ -94,6 +99,7 @@
ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
Error mError = Error::UNKNOWN;
+ int32_t mErrorVendorCode = 0;
int64_t mLastChallenge = -1;
int64_t mLastChallengeRevoked = -1;
int32_t mLastEnrolled = -1;
@@ -105,17 +111,29 @@
bool mAuthenticatorIdInvalidated = false;
bool mLockoutPermanent = false;
int mInteractionDetectedCount = 0;
+ int32_t mLastAcquiredInfo = -1;
+ int32_t mLastAcquiredVendorCode = -1;
+ int32_t mLastAcquiredCount = 0;
};
class FakeFingerprintEngineTest : public ::testing::Test {
protected:
void SetUp() override {
- FingerprintHalProperties::operation_enroll_latency(0);
- FingerprintHalProperties::operation_authenticate_latency(0);
- FingerprintHalProperties::operation_detect_interaction_latency(0);
+ FingerprintHalProperties::operation_enroll_latency({0});
+ FingerprintHalProperties::operation_authenticate_latency({0});
+ FingerprintHalProperties::operation_detect_interaction_latency({0});
mCallback = ndk::SharedRefBase::make<TestSessionCallback>();
}
+ void TearDown() override {
+ FingerprintHalProperties::operation_authenticate_error(0);
+ FingerprintHalProperties::operation_detect_interaction_error(0);
+ FingerprintHalProperties::operation_authenticate_acquired("");
+ FingerprintHalProperties::operation_enroll_latency({});
+ FingerprintHalProperties::operation_authenticate_latency({});
+ FingerprintHalProperties::operation_detect_interaction_latency({});
+ }
+
FakeFingerprintEngine mEngine;
std::shared_ptr<TestSessionCallback> mCallback;
std::promise<void> mCancel;
@@ -135,11 +153,13 @@
TEST_F(FakeFingerprintEngineTest, ResetLockout) {
FingerprintHalProperties::lockout(true);
- mEngine.resetLockoutImpl(mCallback.get(), {});
+ keymaster::HardwareAuthToken hat{.mac = {2, 4}};
+ mEngine.resetLockoutImpl(mCallback.get(), hat);
ASSERT_FALSE(FingerprintHalProperties::lockout().value_or(true));
}
TEST_F(FakeFingerprintEngineTest, AuthenticatorId) {
+ FingerprintHalProperties::enrollments({1});
FingerprintHalProperties::authenticator_id(50);
mEngine.getAuthenticatorIdImpl(mCallback.get());
ASSERT_EQ(50, mCallback->mLastAuthenticatorId);
@@ -162,6 +182,7 @@
ASSERT_EQ(1, FingerprintHalProperties::enrollments().size());
ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value());
ASSERT_EQ(4, mCallback->mLastEnrolled);
+ ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
}
TEST_F(FakeFingerprintEngineTest, EnrollCancel) {
@@ -189,12 +210,28 @@
ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
}
+TEST_F(FakeFingerprintEngineTest, EnrollAcquired) {
+ FingerprintHalProperties::enrollments({});
+ FingerprintHalProperties::next_enrollment("4:0,5-[12,1013]:true");
+ keymaster::HardwareAuthToken hat{.mac = {2, 4}};
+ int32_t prevCnt = mCallback->mLastAcquiredCount;
+ mEngine.enrollImpl(mCallback.get(), hat, mCancel.get_future());
+ ASSERT_FALSE(FingerprintHalProperties::next_enrollment().has_value());
+ ASSERT_EQ(1, FingerprintHalProperties::enrollments().size());
+ ASSERT_EQ(4, FingerprintHalProperties::enrollments()[0].value());
+ ASSERT_EQ(4, mCallback->mLastEnrolled);
+ ASSERT_EQ(prevCnt + 3, mCallback->mLastAcquiredCount);
+ ASSERT_EQ(7, mCallback->mLastAcquiredInfo);
+ ASSERT_EQ(13, mCallback->mLastAcquiredVendorCode);
+}
+
TEST_F(FakeFingerprintEngineTest, Authenticate) {
FingerprintHalProperties::enrollments({1, 2});
FingerprintHalProperties::enrollment_hit(2);
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
ASSERT_FALSE(mCallback->mAuthenticateFailed);
ASSERT_EQ(2, mCallback->mLastAuthenticated);
+ ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
}
TEST_F(FakeFingerprintEngineTest, AuthenticateCancel) {
@@ -211,7 +248,6 @@
FingerprintHalProperties::enrollment_hit({});
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
ASSERT_TRUE(mCallback->mAuthenticateFailed);
- ASSERT_EQ(mCallback->mError, Error::UNABLE_TO_PROCESS);
}
TEST_F(FakeFingerprintEngineTest, AuthenticateNotEnrolled) {
@@ -219,7 +255,6 @@
FingerprintHalProperties::enrollment_hit(3);
mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
ASSERT_TRUE(mCallback->mAuthenticateFailed);
- ASSERT_EQ(mCallback->mError, Error::UNABLE_TO_PROCESS);
}
TEST_F(FakeFingerprintEngineTest, AuthenticateLockout) {
@@ -231,14 +266,46 @@
ASSERT_NE(mCallback->mError, Error::UNKNOWN);
}
-TEST_F(FakeFingerprintEngineTest, InteractionDetect) {
+TEST_F(FakeFingerprintEngineTest, AuthenticateError8) {
+ FingerprintHalProperties::operation_authenticate_error(8);
+ mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+ ASSERT_EQ(mCallback->mError, (Error)8);
+ ASSERT_EQ(mCallback->mErrorVendorCode, 0);
+}
+
+TEST_F(FakeFingerprintEngineTest, AuthenticateError9) {
+ FingerprintHalProperties::operation_authenticate_error(1009);
+ mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+ ASSERT_EQ(mCallback->mError, (Error)7);
+ ASSERT_EQ(mCallback->mErrorVendorCode, 9);
+}
+
+TEST_F(FakeFingerprintEngineTest, AuthenticateAcquired) {
+ FingerprintHalProperties::lockout(false);
FingerprintHalProperties::enrollments({1, 2});
FingerprintHalProperties::enrollment_hit(2);
+ FingerprintHalProperties::operation_authenticate_acquired("4,1009");
+ int32_t prevCount = mCallback->mLastAcquiredCount;
+ mEngine.authenticateImpl(mCallback.get(), 0, mCancel.get_future());
+ ASSERT_FALSE(mCallback->mAuthenticateFailed);
+ ASSERT_EQ(2, mCallback->mLastAuthenticated);
+ ASSERT_EQ(prevCount + 2, mCallback->mLastAcquiredCount);
+ ASSERT_EQ(7, mCallback->mLastAcquiredInfo);
+ ASSERT_EQ(9, mCallback->mLastAcquiredVendorCode);
+}
+
+TEST_F(FakeFingerprintEngineTest, InteractionDetect) {
+ FingerprintHalProperties::detect_interaction(true);
+ FingerprintHalProperties::enrollments({1, 2});
+ FingerprintHalProperties::enrollment_hit(2);
+ FingerprintHalProperties::operation_detect_interaction_acquired("");
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
+ ASSERT_EQ(1, mCallback->mLastAcquiredInfo);
}
TEST_F(FakeFingerprintEngineTest, InteractionDetectCancel) {
+ FingerprintHalProperties::detect_interaction(true);
FingerprintHalProperties::enrollments({1, 2});
FingerprintHalProperties::enrollment_hit(2);
mCancel.set_value();
@@ -248,6 +315,7 @@
}
TEST_F(FakeFingerprintEngineTest, InteractionDetectNotSet) {
+ FingerprintHalProperties::detect_interaction(true);
FingerprintHalProperties::enrollments({1, 2});
FingerprintHalProperties::enrollment_hit({});
mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
@@ -261,6 +329,28 @@
ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
}
+TEST_F(FakeFingerprintEngineTest, InteractionDetectError) {
+ FingerprintHalProperties::detect_interaction(true);
+ FingerprintHalProperties::operation_detect_interaction_error(8);
+ mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+ ASSERT_EQ(0, mCallback->mInteractionDetectedCount);
+ ASSERT_EQ(mCallback->mError, (Error)8);
+ ASSERT_EQ(mCallback->mErrorVendorCode, 0);
+}
+
+TEST_F(FakeFingerprintEngineTest, InteractionDetectAcquired) {
+ FingerprintHalProperties::detect_interaction(true);
+ FingerprintHalProperties::enrollments({1, 2});
+ FingerprintHalProperties::enrollment_hit(2);
+ FingerprintHalProperties::operation_detect_interaction_acquired("4,1013");
+ int32_t prevCount = mCallback->mLastAcquiredCount;
+ mEngine.detectInteractionImpl(mCallback.get(), mCancel.get_future());
+ ASSERT_EQ(1, mCallback->mInteractionDetectedCount);
+ ASSERT_EQ(prevCount + 2, mCallback->mLastAcquiredCount);
+ ASSERT_EQ(7, mCallback->mLastAcquiredInfo);
+ ASSERT_EQ(13, mCallback->mLastAcquiredVendorCode);
+}
+
TEST_F(FakeFingerprintEngineTest, EnumerateEnrolled) {
FingerprintHalProperties::enrollments({2, 4, 8});
mEngine.enumerateEnrollmentsImpl(mCallback.get());
@@ -290,6 +380,93 @@
}
}
+TEST_F(FakeFingerprintEngineTest, parseIntSequence) {
+ std::vector<int32_t> seqV;
+ seqV = mEngine.parseIntSequence("");
+ ASSERT_EQ(0, seqV.size());
+ seqV = mEngine.parseIntSequence("2");
+ ASSERT_EQ(1, seqV.size());
+ ASSERT_EQ(2, seqV[0]);
+ seqV = mEngine.parseIntSequence("2,3,4");
+ std::vector<int32_t> expV{2, 3, 4};
+ ASSERT_EQ(expV, seqV);
+ seqV = mEngine.parseIntSequence("2,3,a");
+ ASSERT_EQ(0, seqV.size());
+ seqV = mEngine.parseIntSequence("2, 3, 4");
+ ASSERT_EQ(expV, seqV);
+ seqV = mEngine.parseIntSequence("123,456");
+ ASSERT_EQ(2, seqV.size());
+ std::vector<int32_t> expV1{123, 456};
+ ASSERT_EQ(expV1, seqV);
+ seqV = mEngine.parseIntSequence("12f3,456");
+ ASSERT_EQ(0, seqV.size());
+}
+
+TEST_F(FakeFingerprintEngineTest, parseEnrollmentCaptureOk) {
+ std::vector<std::vector<int32_t>> ecV;
+ ecV = mEngine.parseEnrollmentCapture("100,200,300");
+ ASSERT_EQ(6, ecV.size());
+ std::vector<std::vector<int32_t>> expE{{100}, {200}, {300}};
+ std::vector<int32_t> defC{1};
+ for (int i = 0; i < ecV.size(); i += 2) {
+ ASSERT_EQ(expE[i / 2], ecV[i]);
+ ASSERT_EQ(defC, ecV[i + 1]);
+ }
+ ecV = mEngine.parseEnrollmentCapture("100");
+ ASSERT_EQ(2, ecV.size());
+ ASSERT_EQ(expE[0], ecV[0]);
+ ASSERT_EQ(defC, ecV[1]);
+
+ ecV = mEngine.parseEnrollmentCapture("100-[5,6,7]");
+ std::vector<int32_t> expC{5, 6, 7};
+ ASSERT_EQ(2, ecV.size());
+ for (int i = 0; i < ecV.size(); i += 2) {
+ ASSERT_EQ(expE[i / 2], ecV[i]);
+ ASSERT_EQ(expC, ecV[i + 1]);
+ }
+ ecV = mEngine.parseEnrollmentCapture("100-[5,6,7], 200, 300-[9,10]");
+ std::vector<std::vector<int32_t>> expC1{{5, 6, 7}, {1}, {9, 10}};
+ ASSERT_EQ(6, ecV.size());
+ for (int i = 0; i < ecV.size(); i += 2) {
+ ASSERT_EQ(expE[i / 2], ecV[i]);
+ ASSERT_EQ(expC1[i / 2], ecV[i + 1]);
+ }
+ ecV = mEngine.parseEnrollmentCapture("100-[5,6,7], 200-[2,1], 300-[9]");
+ std::vector<std::vector<int32_t>> expC2{{5, 6, 7}, {2, 1}, {9}};
+ ASSERT_EQ(ecV.size(), 6);
+ for (int i = 0; i < ecV.size(); i += 2) {
+ ASSERT_EQ(expE[i / 2], ecV[i]);
+ ASSERT_EQ(expC2[i / 2], ecV[i + 1]);
+ }
+}
+
+TEST_F(FakeFingerprintEngineTest, parseEnrollmentCaptureFail) {
+ std::vector<std::string> badStr{"10c", "100-5", "100-[5,6,7", "100-5,6,7]",
+ "100,2x0,300", "200-[f]", "a,b"};
+ std::vector<std::vector<int32_t>> ecV;
+ for (const auto& s : badStr) {
+ ecV = mEngine.parseEnrollmentCapture(s);
+ ASSERT_EQ(ecV.size(), 0);
+ }
+}
+
+TEST_F(FakeFingerprintEngineTest, randomLatency) {
+ FingerprintHalProperties::operation_detect_interaction_latency({});
+ ASSERT_EQ(DEFAULT_LATENCY,
+ mEngine.getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
+ FingerprintHalProperties::operation_detect_interaction_latency({10});
+ ASSERT_EQ(10,
+ mEngine.getLatency(FingerprintHalProperties::operation_detect_interaction_latency()));
+ FingerprintHalProperties::operation_detect_interaction_latency({1, 1000});
+ std::set<int32_t> latencySet;
+ for (int i = 0; i < 100; i++) {
+ latencySet.insert(mEngine.getLatency(
+ FingerprintHalProperties::operation_detect_interaction_latency()));
+ }
+ ASSERT_TRUE(latencySet.size() > 95);
+ FingerprintHalProperties::operation_detect_interaction_latency({});
+}
+
} // namespace aidl::android::hardware::biometrics::fingerprint
int main(int argc, char** argv) {
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
index 485f401..f551899 100644
--- a/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
+++ b/biometrics/fingerprint/aidl/default/tests/FakeFingerprintEngineUdfpsTest.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <aidl/android/hardware/biometrics/fingerprint/BnSessionCallback.h>
#include <android/binder_process.h>
#include <fingerprint.sysprop.h>
#include <gtest/gtest.h>
@@ -29,6 +30,69 @@
namespace aidl::android::hardware::biometrics::fingerprint {
+class TestSessionCallback : public BnSessionCallback {
+ public:
+ ndk::ScopedAStatus onChallengeGenerated(int64_t /*challenge*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onChallengeRevoked(int64_t /*challenge*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onError(fingerprint::Error /*error*/, int32_t /*vendorCode*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onEnrollmentProgress(int32_t /*enrollmentId*/,
+ int32_t /*remaining*/) override {
+ mEnrollmentProgress++;
+ return ndk::ScopedAStatus::ok();
+ };
+
+ ::ndk::ScopedAStatus onAuthenticationSucceeded(int32_t /*enrollmentId*/,
+ const keymaster::HardwareAuthToken&) override {
+ mAuthenticationSuccess++;
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onAuthenticationFailed() override {
+ mAuthenticationFailure++;
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onInteractionDetected() override {
+ mDetectInteraction++;
+ return ndk::ScopedAStatus::ok();
+ };
+ ndk::ScopedAStatus onAcquired(AcquiredInfo /*info*/, int32_t /*vendorCode*/) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onEnrollmentsEnumerated(
+ const std::vector<int32_t>& /*enrollmentIds*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onEnrollmentsRemoved(
+ const std::vector<int32_t>& /*enrollmentIds*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onAuthenticatorIdRetrieved(int64_t /*authenticatorId*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onAuthenticatorIdInvalidated(int64_t /*authenticatorId*/) override {
+ return ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onLockoutPermanent() override { return ndk::ScopedAStatus::ok(); };
+ ndk::ScopedAStatus onLockoutTimed(int64_t /* timeout */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus onLockoutCleared() override { return ndk::ScopedAStatus::ok(); }
+ ndk::ScopedAStatus onSessionClosed() override { return ndk::ScopedAStatus::ok(); }
+
+ int32_t getAuthenticationCount() { return mAuthenticationSuccess + mAuthenticationFailure; }
+ int32_t getDetectInteractionCount() { return mDetectInteraction; }
+
+ int32_t mAuthenticationSuccess = 0;
+ int32_t mAuthenticationFailure = 0;
+ int32_t mEnrollmentProgress = 0;
+ int32_t mDetectInteraction = 0;
+};
+
class FakeFingerprintEngineUdfpsTest : public ::testing::Test {
protected:
void SetUp() override {}
@@ -47,14 +111,10 @@
sc.sensorRadius == FakeFingerprintEngineUdfps::defaultSensorRadius && sc.display == "");
}
-TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocation) {
- FingerprintHalProperties::sensor_location("");
- SensorLocation sc = mEngine.getSensorLocation();
- ASSERT_TRUE(isDefaultLocation(sc));
-
+TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocationOk) {
auto loc = "100:200:30";
FingerprintHalProperties::sensor_location(loc);
- sc = mEngine.getSensorLocation();
+ SensorLocation sc = mEngine.getSensorLocation();
ASSERT_TRUE(sc.sensorLocationX == 100);
ASSERT_TRUE(sc.sensorLocationY == 200);
ASSERT_TRUE(sc.sensorRadius == 30);
@@ -66,27 +126,59 @@
ASSERT_TRUE(sc.sensorLocationY == 200);
ASSERT_TRUE(sc.sensorRadius == 30);
ASSERT_TRUE(sc.display == "screen1");
-
- loc = "100";
- FingerprintHalProperties::sensor_location(loc);
- sc = mEngine.getSensorLocation();
- ASSERT_TRUE(isDefaultLocation(sc));
-
- loc = "10:20";
- FingerprintHalProperties::sensor_location(loc);
- sc = mEngine.getSensorLocation();
- ASSERT_TRUE(isDefaultLocation(sc));
-
- loc = "10,20,5";
- FingerprintHalProperties::sensor_location(loc);
- sc = mEngine.getSensorLocation();
- ASSERT_TRUE(isDefaultLocation(sc));
-
- loc = "a:b:c";
- FingerprintHalProperties::sensor_location(loc);
- sc = mEngine.getSensorLocation();
- ASSERT_TRUE(isDefaultLocation(sc));
}
+TEST_F(FakeFingerprintEngineUdfpsTest, getSensorLocationBad) {
+ const std::vector<std::string> badStr{"", "100", "10:20", "10,20,5", "a:b:c"};
+ SensorLocation sc;
+ for (const auto& s : badStr) {
+ FingerprintHalProperties::sensor_location(s);
+ sc = mEngine.getSensorLocation();
+ ASSERT_TRUE(isDefaultLocation(sc));
+ }
+}
+
+TEST_F(FakeFingerprintEngineUdfpsTest, initialization) {
+ ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kIdle);
+}
+
+TEST_F(FakeFingerprintEngineUdfpsTest, authenticate) {
+ std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
+ std::promise<void> cancel;
+ mEngine.authenticateImpl(cb.get(), 1, cancel.get_future());
+ ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kAuthenticate);
+ mEngine.onPointerDownImpl(1, 2, 3, 4.0, 5.0);
+ ASSERT_EQ(cb->getAuthenticationCount(), 0);
+ mEngine.onUiReadyImpl();
+ ASSERT_EQ(cb->getAuthenticationCount(), 1);
+}
+
+TEST_F(FakeFingerprintEngineUdfpsTest, enroll) {
+ std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
+ std::promise<void> cancel;
+ keymaster::HardwareAuthToken hat{.mac = {5, 6}};
+ FingerprintHalProperties::next_enrollment("5:0,0:true");
+ mEngine.enrollImpl(cb.get(), hat, cancel.get_future());
+ ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kEnroll);
+ mEngine.onPointerDownImpl(1, 2, 3, 4.0, 5.0);
+ ASSERT_EQ(cb->mEnrollmentProgress, 0);
+ mEngine.onUiReadyImpl();
+ ASSERT_TRUE(cb->mEnrollmentProgress > 0);
+}
+
+TEST_F(FakeFingerprintEngineUdfpsTest, detectInteraction) {
+ FingerprintHalProperties::detect_interaction(true);
+ FingerprintHalProperties::enrollments({1, 2});
+ FingerprintHalProperties::enrollment_hit(2);
+ FingerprintHalProperties::operation_detect_interaction_acquired("");
+ std::shared_ptr<TestSessionCallback> cb = ndk::SharedRefBase::make<TestSessionCallback>();
+ std::promise<void> cancel;
+ mEngine.detectInteractionImpl(cb.get(), cancel.get_future());
+ ASSERT_TRUE(mEngine.getWorkMode() == FakeFingerprintEngineUdfps::WorkMode::kDetectInteract);
+ mEngine.onPointerDownImpl(1, 2, 3, 4.0, 5.0);
+ ASSERT_EQ(cb->getDetectInteractionCount(), 0);
+ mEngine.onUiReadyImpl();
+ ASSERT_EQ(cb->getDetectInteractionCount(), 1);
+}
// More
} // namespace aidl::android::hardware::biometrics::fingerprint
diff --git a/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
new file mode 100644
index 0000000..1b071ee
--- /dev/null
+++ b/biometrics/fingerprint/aidl/default/tests/FakeLockoutTrackerTest.cpp
@@ -0,0 +1,95 @@
+/*
+ * 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/binder_process.h>
+#include <fingerprint.sysprop.h>
+#include <gtest/gtest.h>
+
+#include <android-base/logging.h>
+
+#include "FakeLockoutTracker.h"
+#include "util/Util.h"
+
+using namespace ::android::fingerprint::virt;
+using namespace ::aidl::android::hardware::biometrics::fingerprint;
+
+namespace aidl::android::hardware::biometrics::fingerprint {
+
+class FakeLockoutTrackerTest : public ::testing::Test {
+ protected:
+ static constexpr int32_t LOCKOUT_TIMED_THRESHOLD = 3;
+ static constexpr int32_t LOCKOUT_PERMANENT_THRESHOLD = 5;
+ static constexpr int32_t LOCKOUT_TIMED_DURATION = 100;
+
+ void SetUp() override {
+ FingerprintHalProperties::lockout_timed_threshold(LOCKOUT_TIMED_THRESHOLD);
+ FingerprintHalProperties::lockout_timed_duration(LOCKOUT_TIMED_DURATION);
+ FingerprintHalProperties::lockout_permanent_threshold(LOCKOUT_PERMANENT_THRESHOLD);
+ }
+
+ void TearDown() override {
+ // reset to default
+ FingerprintHalProperties::lockout_timed_threshold(5);
+ FingerprintHalProperties::lockout_timed_duration(20);
+ FingerprintHalProperties::lockout_permanent_threshold(10000);
+ FingerprintHalProperties::lockout_enable(false);
+ FingerprintHalProperties::lockout(false);
+ }
+
+ FakeLockoutTracker mLockoutTracker;
+};
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptDisable) {
+ FingerprintHalProperties::lockout_enable(false);
+ for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD + 1; i++) mLockoutTracker.addFailedAttempt();
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
+ mLockoutTracker.reset();
+}
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptLockoutTimed) {
+ FingerprintHalProperties::lockout_enable(true);
+ for (int i = 0; i < LOCKOUT_TIMED_THRESHOLD; i++) mLockoutTracker.addFailedAttempt();
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kTimed);
+ // time left
+ int N = 5;
+ int64_t prevTimeLeft = INT_MIN;
+ for (int i = 0; i < N; i++) {
+ SLEEP_MS(LOCKOUT_TIMED_DURATION / N + 1);
+ int64_t currTimeLeft = mLockoutTracker.getLockoutTimeLeft();
+ ASSERT_TRUE(currTimeLeft > prevTimeLeft);
+ prevTimeLeft = currTimeLeft;
+ }
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kNone);
+ mLockoutTracker.reset();
+}
+
+TEST_F(FakeLockoutTrackerTest, addFailedAttemptPermanent) {
+ FingerprintHalProperties::lockout_enable(true);
+ for (int i = 0; i < LOCKOUT_PERMANENT_THRESHOLD - 1; i++) mLockoutTracker.addFailedAttempt();
+ ASSERT_NE(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
+ mLockoutTracker.addFailedAttempt();
+ ASSERT_EQ(mLockoutTracker.getMode(), FakeLockoutTracker::LockoutMode::kPermanent);
+ ASSERT_TRUE(FingerprintHalProperties::lockout());
+ mLockoutTracker.reset();
+}
+
+} // namespace aidl::android::hardware::biometrics::fingerprint
+
+int main(int argc, char** argv) {
+ testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/biometrics/fingerprint/aidl/vts/Android.bp b/biometrics/fingerprint/aidl/vts/Android.bp
index a474f66..1652905 100644
--- a/biometrics/fingerprint/aidl/vts/Android.bp
+++ b/biometrics/fingerprint/aidl/vts/Android.bp
@@ -15,9 +15,9 @@
],
srcs: ["VtsHalBiometricsFingerprintTargetTest.cpp"],
static_libs: [
- "android.hardware.biometrics.common-V2-ndk",
- "android.hardware.biometrics.fingerprint-V2-ndk",
- "android.hardware.keymaster-V3-ndk",
+ "android.hardware.biometrics.common-V3-ndk",
+ "android.hardware.biometrics.fingerprint-V3-ndk",
+ "android.hardware.keymaster-V4-ndk",
],
shared_libs: [
"libbinder_ndk",
diff --git a/bluetooth/1.0/default/OWNERS b/bluetooth/1.0/default/OWNERS
deleted file mode 100644
index 5df5bfe..0000000
--- a/bluetooth/1.0/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-eisenbach@google.com
-mylesgw@google.com
-pavlin@google.com
diff --git a/bluetooth/1.0/default/bluetooth_hci.cc b/bluetooth/1.0/default/bluetooth_hci.cc
index a2211f4..869c723 100644
--- a/bluetooth/1.0/default/bluetooth_hci.cc
+++ b/bluetooth/1.0/default/bluetooth_hci.cc
@@ -33,7 +33,8 @@
class BluetoothDeathRecipient : public hidl_death_recipient {
public:
- BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
+ BluetoothDeathRecipient(const sp<IBluetoothHci> hci)
+ : mHci(hci), has_died_(false) {}
virtual void serviceDied(
uint64_t /*cookie*/,
@@ -51,7 +52,7 @@
};
BluetoothHci::BluetoothHci()
- : death_recipient_(new BluetoothDeathRecipient(this)) {}
+ : death_recipient_(new BluetoothDeathRecipient(this)) {bt_enabled = 0;}
Return<void> BluetoothHci::initialize(
const ::android::sp<IBluetoothHciCallbacks>& cb) {
@@ -61,8 +62,19 @@
return Void();
}
+ if (bt_enabled == 1) {
+ ALOGE("initialize was called!");
+ return Void();
+ }
+ bt_enabled = 1;
death_recipient_->setHasDied(false);
cb->linkToDeath(death_recipient_, 0);
+ unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) {
+ if (death_recipient->getHasDied())
+ ALOGI("Skipping unlink call, service died.");
+ else
+ cb->unlinkToDeath(death_recipient);
+ };
bool rc = VendorInterface::Initialize(
[cb](bool status) {
@@ -112,6 +124,12 @@
Return<void> BluetoothHci::close() {
ALOGI("BluetoothHci::close()");
+
+ if (bt_enabled != 1) {
+ ALOGE("should initialize first!");
+ return Void();
+ }
+ bt_enabled = 0;
unlink_cb_(death_recipient_);
VendorInterface::Shutdown();
return Void();
@@ -134,6 +152,11 @@
void BluetoothHci::sendDataToController(const uint8_t type,
const hidl_vec<uint8_t>& data) {
+ if (bt_enabled != 1) {
+ ALOGE("should initialize first!");
+ return;
+ }
+
VendorInterface::get()->Send(type, data.data(), data.size());
}
diff --git a/bluetooth/1.0/default/bluetooth_hci.h b/bluetooth/1.0/default/bluetooth_hci.h
index c966990..5130c87 100644
--- a/bluetooth/1.0/default/bluetooth_hci.h
+++ b/bluetooth/1.0/default/bluetooth_hci.h
@@ -48,6 +48,7 @@
void sendDataToController(const uint8_t type, const hidl_vec<uint8_t>& data);
::android::sp<BluetoothDeathRecipient> death_recipient_;
std::function<void(sp<BluetoothDeathRecipient>&)> unlink_cb_;
+ int bt_enabled;
};
extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name);
diff --git a/bluetooth/1.0/default/vendor_interface.cc b/bluetooth/1.0/default/vendor_interface.cc
index 1d15dd6..c23d667 100644
--- a/bluetooth/1.0/default/vendor_interface.cc
+++ b/bluetooth/1.0/default/vendor_interface.cc
@@ -36,6 +36,8 @@
"BLUETOOTH_VENDOR_LIB_INTERFACE";
static const int INVALID_FD = -1;
+std::mutex vendor_mutex_;
+std::mutex initcb_mutex_;
namespace {
@@ -47,13 +49,25 @@
uint16_t opcode;
} internal_command;
+enum {
+ VENDOR_STATE_INIT = 1,
+ VENDOR_STATE_OPENING, /* during opening */
+ VENDOR_STATE_OPENED, /* open in fops_open */
+ VENDOR_STATE_CLOSING, /* during closing */
+ VENDOR_STATE_CLOSED, /* closed */
+
+ VENDOR_STATE_MSG_NUM
+} ;
+
+uint8_t vstate = VENDOR_STATE_INIT;
+
// True when LPM is not enabled yet or wake is not asserted.
bool lpm_wake_deasserted;
uint32_t lpm_timeout_ms;
bool recent_activity_flag;
VendorInterface* g_vendor_interface = nullptr;
-std::mutex wakeup_mutex_;
+static VendorInterface vendor_interface;
HC_BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec<uint8_t>& data) {
size_t packet_size = data.size() + sizeof(HC_BT_HDR);
@@ -167,11 +181,8 @@
InitializeCompleteCallback initialize_complete_cb,
PacketReadCallback event_cb, PacketReadCallback acl_cb,
PacketReadCallback sco_cb, PacketReadCallback iso_cb) {
- if (g_vendor_interface) {
- ALOGE("%s: No previous Shutdown()?", __func__);
- return false;
- }
- g_vendor_interface = new VendorInterface();
+ ALOGI("%s: VendorInterface::Initialize", __func__);
+ g_vendor_interface = &vendor_interface;
return g_vendor_interface->Open(initialize_complete_cb, event_cb, acl_cb,
sco_cb, iso_cb);
}
@@ -179,9 +190,8 @@
void VendorInterface::Shutdown() {
LOG_ALWAYS_FATAL_IF(!g_vendor_interface, "%s: No Vendor interface!",
__func__);
+ ALOGI("%s: VendorInterface::Shutdown", __func__);
g_vendor_interface->Close();
- delete g_vendor_interface;
- g_vendor_interface = nullptr;
}
VendorInterface* VendorInterface::get() { return g_vendor_interface; }
@@ -191,144 +201,189 @@
PacketReadCallback acl_cb,
PacketReadCallback sco_cb,
PacketReadCallback iso_cb) {
- initialize_complete_cb_ = initialize_complete_cb;
+ {
+ std::unique_lock<std::mutex> guard(vendor_mutex_);
+ if (vstate == VENDOR_STATE_OPENED) {
+ ALOGW("VendorInterface opened!");
+ return true;
+ }
- // Initialize vendor interface
+ if ((vstate == VENDOR_STATE_CLOSING) ||
+ (vstate == VENDOR_STATE_OPENING)) {
+ ALOGW("VendorInterface open/close is on-going !");
+ return true;
+ }
- lib_handle_ = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
- if (!lib_handle_) {
- ALOGE("%s unable to open %s (%s)", __func__, VENDOR_LIBRARY_NAME,
- dlerror());
- return false;
- }
+ vstate = VENDOR_STATE_OPENING;
+ ALOGI("%s: VendorInterface::Open", __func__);
- lib_interface_ = reinterpret_cast<bt_vendor_interface_t*>(
- dlsym(lib_handle_, VENDOR_LIBRARY_SYMBOL_NAME));
- if (!lib_interface_) {
- ALOGE("%s unable to find symbol %s in %s (%s)", __func__,
- VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
- return false;
- }
+ initialize_complete_cb_ = initialize_complete_cb;
+ // Initialize vendor interface
+
+ lib_handle_ = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
+ if (!lib_handle_) {
+ ALOGE("%s unable to open %s (%s)", __func__, VENDOR_LIBRARY_NAME,
+ dlerror());
+ return false;
+ }
+
+ lib_interface_ = reinterpret_cast<bt_vendor_interface_t*>(
+ dlsym(lib_handle_, VENDOR_LIBRARY_SYMBOL_NAME));
+ if (!lib_interface_) {
+ ALOGE("%s unable to find symbol %s in %s (%s)", __func__,
+ VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
+ return false;
+ }
// Get the local BD address
- uint8_t local_bda[BluetoothAddress::kBytes];
- if (!BluetoothAddress::get_local_address(local_bda)) {
- LOG_ALWAYS_FATAL("%s: No Bluetooth Address!", __func__);
- }
- int status = lib_interface_->init(&lib_callbacks, (unsigned char*)local_bda);
- if (status) {
- ALOGE("%s unable to initialize vendor library: %d", __func__, status);
- return false;
- }
+ uint8_t local_bda[BluetoothAddress::kBytes] = {0, 0, 0, 0, 0, 0};
+ if (!BluetoothAddress::get_local_address(local_bda)) {
+ // BT driver will get BD address from NVRAM for MTK solution
+ ALOGW("%s: No pre-set Bluetooth Address!", __func__);
+ }
+ int status = lib_interface_->init(&lib_callbacks, (unsigned char*)local_bda);
+ if (status) {
+ ALOGE("%s unable to initialize vendor library: %d", __func__, status);
+ return false;
+ }
- ALOGD("%s vendor library loaded", __func__);
+ ALOGD("%s vendor library loaded", __func__);
// Power on the controller
- int power_state = BT_VND_PWR_ON;
- lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
+ int power_state = BT_VND_PWR_ON;
+ lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
// Get the UART socket(s)
- int fd_list[CH_MAX] = {0};
- int fd_count = lib_interface_->op(BT_VND_OP_USERIAL_OPEN, &fd_list);
+ int fd_list[CH_MAX] = {0};
+ int fd_count = lib_interface_->op(BT_VND_OP_USERIAL_OPEN, &fd_list);
- if (fd_count < 1 || fd_count > CH_MAX - 1) {
- ALOGE("%s: fd_count %d is invalid!", __func__, fd_count);
- return false;
- }
-
- for (int i = 0; i < fd_count; i++) {
- if (fd_list[i] == INVALID_FD) {
- ALOGE("%s: fd %d is invalid!", __func__, fd_list[i]);
+ if (fd_count < 1 || fd_count > CH_MAX - 1) {
+ ALOGE("%s: fd_count %d is invalid!", __func__, fd_count);
return false;
}
- }
- event_cb_ = event_cb;
- PacketReadCallback intercept_events = [this](const hidl_vec<uint8_t>& event) {
- HandleIncomingEvent(event);
- };
+ for (int i = 0; i < fd_count; i++) {
+ if (fd_list[i] == INVALID_FD) {
+ ALOGE("%s: fd %d is invalid!", __func__, fd_list[i]);
+ return false;
+ }
+ }
- if (fd_count == 1) {
- hci::H4Protocol* h4_hci =
- new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb, iso_cb);
- fd_watcher_.WatchFdForNonBlockingReads(
- fd_list[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
- hci_ = h4_hci;
- } else {
- hci::MctProtocol* mct_hci =
- new hci::MctProtocol(fd_list, intercept_events, acl_cb);
- fd_watcher_.WatchFdForNonBlockingReads(
- fd_list[CH_EVT], [mct_hci](int fd) { mct_hci->OnEventDataReady(fd); });
- fd_watcher_.WatchFdForNonBlockingReads(
- fd_list[CH_ACL_IN], [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); });
- hci_ = mct_hci;
- }
+ event_cb_ = event_cb;
+ PacketReadCallback intercept_events = [this](const hidl_vec<uint8_t>& event) {
+ HandleIncomingEvent(event);
+ };
+
+ if (fd_count == 1) {
+ hci::H4Protocol* h4_hci =
+ new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb, iso_cb);
+ fd_watcher_.WatchFdForNonBlockingReads(
+ fd_list[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
+ hci_ = h4_hci;
+ } else {
+ hci::MctProtocol* mct_hci =
+ new hci::MctProtocol(fd_list, intercept_events, acl_cb);
+ fd_watcher_.WatchFdForNonBlockingReads(
+ fd_list[CH_EVT], [mct_hci](int fd) { mct_hci->OnEventDataReady(fd); });
+ fd_watcher_.WatchFdForNonBlockingReads(
+ fd_list[CH_ACL_IN],
+ [mct_hci](int fd) { mct_hci->OnAclDataReady(fd); });
+ hci_ = mct_hci;
+ }
// Initially, the power management is off.
- lpm_wake_deasserted = true;
+ lpm_wake_deasserted = true;
// Start configuring the firmware
- firmware_startup_timer_ = new FirmwareStartupTimer();
- lib_interface_->op(BT_VND_OP_FW_CFG, nullptr);
+ firmware_startup_timer_ = new FirmwareStartupTimer();
+ lib_interface_->op(BT_VND_OP_FW_CFG, nullptr);
+ vstate = VENDOR_STATE_OPENED;
+ ALOGI("%s: VendorInterface::Open done!!!", __func__);
+ } // vendor_mutex_ done
return true;
}
void VendorInterface::Close() {
// These callbacks may send HCI events (vendor-dependent), so make sure to
// StopWatching the file descriptor after this.
+
+ if (vstate != VENDOR_STATE_OPENED) {
+ ALOGW("VendorInterface is not allow close(%d)", vstate);
+ return;
+ }
+ vstate = VENDOR_STATE_CLOSING;
+ ALOGI("%s: VendorInterface::Close", __func__);
+
if (lib_interface_ != nullptr) {
+ lib_interface_->cleanup();
bt_vendor_lpm_mode_t mode = BT_VND_LPM_DISABLE;
lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
}
- fd_watcher_.StopWatchingFileDescriptors();
+ {
+ std::unique_lock<std::mutex> guard(vendor_mutex_);
- if (hci_ != nullptr) {
- delete hci_;
- hci_ = nullptr;
- }
+ fd_watcher_.StopWatchingFileDescriptors();
+ if (hci_ != nullptr) {
+ delete hci_;
+ hci_ = nullptr;
+ }
- if (lib_interface_ != nullptr) {
- lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr);
+ if (lib_interface_ != nullptr) {
+ lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr);
- int power_state = BT_VND_PWR_OFF;
- lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
+ int power_state = BT_VND_PWR_OFF;
+ lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
- lib_interface_->cleanup();
- lib_interface_ = nullptr;
- }
+ lib_interface_ = nullptr;
+ }
- if (lib_handle_ != nullptr) {
- dlclose(lib_handle_);
- lib_handle_ = nullptr;
- }
+ if (lib_handle_ != nullptr) {
+ dlclose(lib_handle_);
+ lib_handle_ = nullptr;
+ }
- if (firmware_startup_timer_ != nullptr) {
- delete firmware_startup_timer_;
- firmware_startup_timer_ = nullptr;
- }
+ if (firmware_startup_timer_ != nullptr) {
+ delete firmware_startup_timer_;
+ firmware_startup_timer_ = nullptr;
+ }
+ vstate = VENDOR_STATE_CLOSED;
+ } // vendor_mutex_ done
+ ALOGI("%s: VendorInterface::Close done!!!", __func__);
}
size_t VendorInterface::Send(uint8_t type, const uint8_t* data, size_t length) {
- std::unique_lock<std::mutex> lock(wakeup_mutex_);
- recent_activity_flag = true;
+ {
+ std::unique_lock<std::mutex> guard(vendor_mutex_);
- if (lpm_wake_deasserted == true) {
- // Restart the timer.
- fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
+ if (vstate != VENDOR_STATE_OPENED) {
+ ALOGW("VendorInterface is not open yet(%d)!", vstate);
+ return 0;
+ }
+ ALOGI("%s: VendorInterface::Send", __func__);
+
+ if (lib_interface_ == nullptr) {
+ ALOGE("lib_interface_ is null");
+ return 0;
+ }
+ recent_activity_flag = true;
+ if (lpm_wake_deasserted == true) {
+ // Restart the timer.
+ fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
[this]() { OnTimeout(); });
- // Assert wake.
- lpm_wake_deasserted = false;
- bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT;
- lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
- ALOGV("%s: Sent wake before (%02x)", __func__, data[0] | (data[1] << 8));
- }
+ // Assert wake.
+ lpm_wake_deasserted = false;
+ bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT;
+ lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
+ ALOGV("%s: Sent wake before (%02x)", __func__, data[0] | (data[1] << 8));
+ }
- return hci_->Send(type, data, length);
+ return hci_ ? hci_->Send(type, data, length) : 0;
+ } // vendor_mutex_ done
}
void VendorInterface::OnFirmwareConfigured(uint8_t result) {
@@ -339,25 +394,36 @@
firmware_startup_timer_ = nullptr;
}
- if (initialize_complete_cb_ != nullptr) {
- initialize_complete_cb_(result == 0);
- initialize_complete_cb_ = nullptr;
+ {
+ std::unique_lock<std::mutex> guard(initcb_mutex_);
+ ALOGD("%s OnFirmwareConfigured get lock", __func__);
+ if (initialize_complete_cb_ != nullptr) {
+ LOG_ALWAYS_FATAL_IF((result != 0),
+ "%s: Failed to init firmware!", __func__);
+ initialize_complete_cb_(result == 0);
+ }
+ } // initcb_mutex_ done
+
+ if (lib_interface_ != nullptr) {
+ lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms);
+ ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms);
+
+ bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE;
+ lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
+
+ ALOGD("%s Calling StartLowPowerWatchdog()", __func__);
+ fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
+ [this]() { OnTimeout(); });
+ }
+ else {
+ ALOGE("lib_interface_ is null");
}
- lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms);
- ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms);
-
- bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE;
- lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
-
- ALOGD("%s Calling StartLowPowerWatchdog()", __func__);
- fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
- [this]() { OnTimeout(); });
+ initialize_complete_cb_ = nullptr;
}
void VendorInterface::OnTimeout() {
ALOGV("%s", __func__);
- std::unique_lock<std::mutex> lock(wakeup_mutex_);
if (recent_activity_flag == false) {
lpm_wake_deasserted = true;
bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_DEASSERT;
diff --git a/bluetooth/1.0/default/vendor_interface.h b/bluetooth/1.0/default/vendor_interface.h
index 040f31a..2df3946 100644
--- a/bluetooth/1.0/default/vendor_interface.h
+++ b/bluetooth/1.0/default/vendor_interface.h
@@ -22,6 +22,8 @@
#include "bt_vendor_lib.h"
#include "hci_protocol.h"
+extern std::mutex initcb_mutex_;
+
namespace android {
namespace hardware {
namespace bluetooth {
@@ -45,10 +47,9 @@
size_t Send(uint8_t type, const uint8_t* data, size_t length);
void OnFirmwareConfigured(uint8_t result);
-
- private:
virtual ~VendorInterface() = default;
+ private:
bool Open(InitializeCompleteCallback initialize_complete_cb,
PacketReadCallback event_cb, PacketReadCallback acl_cb,
PacketReadCallback sco_cb, PacketReadCallback iso_cb);
diff --git a/bluetooth/1.0/vts/OWNERS b/bluetooth/1.0/vts/OWNERS
deleted file mode 100644
index 58d3a66..0000000
--- a/bluetooth/1.0/vts/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-zachoverflow@google.com
-siyuanh@google.com
-mylesgw@google.com
-jpawlowski@google.com
-apanicke@google.com
-stng@google.com
-hsz@google.com
-
diff --git a/bluetooth/1.0/vts/functional/OWNERS b/bluetooth/1.0/vts/functional/OWNERS
deleted file mode 100644
index 7f02612..0000000
--- a/bluetooth/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 27441
-bluetooth-reviews@google.com
diff --git a/bluetooth/1.1/default/OWNERS b/bluetooth/1.1/default/OWNERS
deleted file mode 100644
index 0c01df6..0000000
--- a/bluetooth/1.1/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-zachoverflow@google.com
-mylesgw@google.com
-jpawlowski@google.com
diff --git a/bluetooth/1.1/vts/OWNERS b/bluetooth/1.1/vts/OWNERS
deleted file mode 100644
index ff6fd93..0000000
--- a/bluetooth/1.1/vts/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-zachoverflow@google.com
-siyuanh@google.com
-mylesgw@google.com
-jpawlowski@google.com
-hsz@google.com
-
diff --git a/bluetooth/OWNERS b/bluetooth/OWNERS
new file mode 100644
index 0000000..f401b8c
--- /dev/null
+++ b/bluetooth/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 27441
+
+henrichataing@google.com
+mylesgw@google.com
+siyuanh@google.com
diff --git a/bluetooth/aidl/Android.bp b/bluetooth/aidl/Android.bp
new file mode 100644
index 0000000..1788ed3
--- /dev/null
+++ b/bluetooth/aidl/Android.bp
@@ -0,0 +1,37 @@
+// This is the expected build file, but it may not be right in all cases
+
+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",
+ vendor_available: true,
+ host_supported: true,
+ srcs: ["android/hardware/bluetooth/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ // FIXME should this be disabled?
+ // prefer NDK backend which can be used anywhere
+ // If you disable this, you also need to delete the C++
+ // translate code.
+ enabled: true,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ ndk: {
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.btservices",
+ ],
+ min_sdk_version: "33",
+ },
+ },
+}
diff --git a/bluetooth/aidl/aidl_api/android.hardware.bluetooth/current/android/hardware/bluetooth/IBluetoothHci.aidl b/bluetooth/aidl/aidl_api/android.hardware.bluetooth/current/android/hardware/bluetooth/IBluetoothHci.aidl
new file mode 100644
index 0000000..8b1cad2
--- /dev/null
+++ b/bluetooth/aidl/aidl_api/android.hardware.bluetooth/current/android/hardware/bluetooth/IBluetoothHci.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;
+@VintfStability
+interface IBluetoothHci {
+ void close();
+ void initialize(in android.hardware.bluetooth.IBluetoothHciCallbacks callback);
+ void sendAclData(in byte[] data);
+ void sendHciCommand(in byte[] command);
+ void sendIsoData(in byte[] data);
+ void sendScoData(in byte[] data);
+}
diff --git a/bluetooth/aidl/aidl_api/android.hardware.bluetooth/current/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl b/bluetooth/aidl/aidl_api/android.hardware.bluetooth/current/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl
new file mode 100644
index 0000000..aecff7f
--- /dev/null
+++ b/bluetooth/aidl/aidl_api/android.hardware.bluetooth/current/android/hardware/bluetooth/IBluetoothHciCallbacks.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;
+@VintfStability
+interface IBluetoothHciCallbacks {
+ void aclDataReceived(in byte[] data);
+ void hciEventReceived(in byte[] event);
+ void initializationComplete(in android.hardware.bluetooth.Status status);
+ void isoDataReceived(in byte[] data);
+ void scoDataReceived(in byte[] data);
+}
diff --git a/bluetooth/aidl/aidl_api/android.hardware.bluetooth/current/android/hardware/bluetooth/Status.aidl b/bluetooth/aidl/aidl_api/android.hardware.bluetooth/current/android/hardware/bluetooth/Status.aidl
new file mode 100644
index 0000000..da429b8
--- /dev/null
+++ b/bluetooth/aidl/aidl_api/android.hardware.bluetooth/current/android/hardware/bluetooth/Status.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;
+@Backing(type="int") @VintfStability
+enum Status {
+ SUCCESS = 0,
+ ALREADY_INITIALIZED = 1,
+ UNABLE_TO_OPEN_INTERFACE = 2,
+ HARDWARE_INITIALIZATION_ERROR = 3,
+ UNKNOWN = 4,
+}
diff --git a/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHci.aidl b/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHci.aidl
new file mode 100644
index 0000000..db12986
--- /dev/null
+++ b/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHci.aidl
@@ -0,0 +1,73 @@
+/*
+ * 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;
+
+import android.hardware.bluetooth.IBluetoothHciCallbacks;
+
+/**
+ * The Host Controller Interface (HCI) is the layer defined by the Bluetooth
+ * specification between the software that runs on the host and the Bluetooth
+ * controller chip. This boundary is the natural choice for a Hardware
+ * Abstraction Layer (HAL). Dealing only in HCI packets and events simplifies
+ * the stack and abstracts away power management, initialization, and other
+ * implementation-specific details related to the hardware.
+ */
+@VintfStability
+interface IBluetoothHci {
+ /**
+ * Close the HCI interface
+ */
+ void close();
+
+ /**
+ * Initialize the Bluetooth interface and set the callbacks.
+ */
+ void initialize(in IBluetoothHciCallbacks callback);
+
+ /**
+ * Send an HCI ACL data packet (as specified in the Bluetooth Specification
+ * V4.2, Vol 2, Part 5, Section 5.4.2) to the Bluetooth controller.
+ * Packets must be processed in order.
+ * @param data HCI data packet to be sent
+ */
+ void sendAclData(in byte[] data);
+
+ /**
+ * Send an HCI command (as specified in the Bluetooth Specification
+ * V4.2, Vol 2, Part 5, Section 5.4.1) to the Bluetooth controller.
+ * Commands must be executed in order.
+ *
+ * @param command is the HCI command to be sent
+ */
+ void sendHciCommand(in byte[] command);
+
+ /**
+ * Send an ISO data packet (as specified in the Bluetooth Core
+ * Specification v5.2) to the Bluetooth controller.
+ * Packets must be processed in order.
+ * @param data HCI data packet to be sent
+ */
+ void sendIsoData(in byte[] data);
+
+ /**
+ * Send an SCO data packet (as specified in the Bluetooth Specification
+ * V4.2, Vol 2, Part 5, Section 5.4.3) to the Bluetooth controller.
+ * Packets must be processed in order.
+ * @param data HCI data packet to be sent
+ */
+ void sendScoData(in byte[] data);
+}
diff --git a/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl b/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl
new file mode 100644
index 0000000..000333e
--- /dev/null
+++ b/bluetooth/aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.aidl
@@ -0,0 +1,56 @@
+/*
+ * 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;
+
+import android.hardware.bluetooth.Status;
+
+/**
+ * The interface from the Bluetooth Controller to the stack.
+ */
+@VintfStability
+interface IBluetoothHciCallbacks {
+ /**
+ * Send an ACL data packet from the controller to the host.
+ * @param data the ACL HCI packet to be passed to the host stack
+ */
+ void aclDataReceived(in byte[] data);
+
+ /**
+ * This function is invoked when an HCI event is received from the
+ * Bluetooth controller to be forwarded to the Bluetooth stack.
+ * @param event is the HCI event to be sent to the Bluetooth stack.
+ */
+ void hciEventReceived(in byte[] event);
+
+ /**
+ * Invoked when the Bluetooth controller initialization has been
+ * completed.
+ */
+ void initializationComplete(in Status status);
+
+ /**
+ * Send a ISO data packet from the controller to the host.
+ * @param data the ISO HCI packet to be passed to the host stack
+ */
+ void isoDataReceived(in byte[] data);
+
+ /**
+ * Send a SCO data packet from the controller to the host.
+ * @param data the SCO HCI packet to be passed to the host stack
+ */
+ void scoDataReceived(in byte[] data);
+}
diff --git a/bluetooth/aidl/android/hardware/bluetooth/Status.aidl b/bluetooth/aidl/android/hardware/bluetooth/Status.aidl
new file mode 100644
index 0000000..4ec251a
--- /dev/null
+++ b/bluetooth/aidl/android/hardware/bluetooth/Status.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;
+
+@VintfStability
+@Backing(type="int")
+enum Status {
+ SUCCESS,
+ ALREADY_INITIALIZED,
+ UNABLE_TO_OPEN_INTERFACE,
+ HARDWARE_INITIALIZATION_ERROR,
+ UNKNOWN,
+}
diff --git a/bluetooth/aidl/default/Android.bp b/bluetooth/aidl/default/Android.bp
new file mode 100644
index 0000000..d1761f5
--- /dev/null
+++ b/bluetooth/aidl/default/Android.bp
@@ -0,0 +1,79 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+cc_defaults {
+ name: "android.hardware.bluetooth-service-build-defaults",
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ ],
+ shared_libs: [
+ "android.hardware.bluetooth-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "android.hardware.bluetooth.async",
+ "android.hardware.bluetooth.hci",
+ ],
+}
+
+cc_library_static {
+ name: "libbluetoothhcihalimpl",
+ vendor_available: true,
+ host_supported: true,
+ defaults: ["android.hardware.bluetooth-service-build-defaults"],
+ srcs: [
+ "BluetoothHci.cpp",
+ ],
+}
+
+cc_binary {
+ name: "android.hardware.bluetooth-service.default",
+ relative_install_path: "hw",
+ init_rc: ["bluetooth-service-default.rc"],
+ vintf_fragments: ["bluetooth-service-default.xml"],
+ vendor: true,
+ defaults: ["android.hardware.bluetooth-service-build-defaults"],
+ srcs: [
+ "service.cpp",
+ ],
+ shared_libs: [
+ "android.hardware.bluetooth-V1-ndk",
+ "libbase",
+ "libbinder_ndk",
+ "libhidlbase",
+ "libutils",
+ "liblog",
+ ],
+ static_libs: [
+ "libbluetoothhcihalimpl",
+ ],
+}
+
+cc_fuzz {
+ name: "android.hardware.bluetooth-service.default_fuzzer",
+ host_supported: true,
+ defaults: ["service_fuzzer_defaults"],
+ srcs: [
+ "test/fuzzer.cpp",
+ ],
+ static_libs: [
+ "android.hardware.bluetooth.async",
+ "android.hardware.bluetooth.hci",
+ "android.hardware.bluetooth-V1-ndk",
+ "libbluetoothhcihalimpl",
+ "liblog",
+ ],
+ fuzz_config: {
+ componentid: 27441,
+ cc: [
+ "mylesgw@google.com",
+ ],
+ },
+}
diff --git a/bluetooth/aidl/default/BluetoothHci.cpp b/bluetooth/aidl/default/BluetoothHci.cpp
new file mode 100644
index 0000000..4d4896d
--- /dev/null
+++ b/bluetooth/aidl/default/BluetoothHci.cpp
@@ -0,0 +1,194 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "android.hardware.bluetooth.service.default"
+
+#include "BluetoothHci.h"
+
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <poll.h>
+#include <string.h>
+#include <sys/uio.h>
+#include <termios.h>
+
+#include "log/log.h"
+
+namespace {
+int SetTerminalRaw(int fd) {
+ termios terminal_settings;
+ int rval = tcgetattr(fd, &terminal_settings);
+ if (rval < 0) {
+ return rval;
+ }
+ cfmakeraw(&terminal_settings);
+ rval = tcsetattr(fd, TCSANOW, &terminal_settings);
+ return rval;
+}
+} // namespace
+
+using namespace ::android::hardware::bluetooth::hci;
+using namespace ::android::hardware::bluetooth::async;
+
+namespace aidl::android::hardware::bluetooth::impl {
+
+void OnDeath(void* cookie);
+
+class BluetoothDeathRecipient {
+ public:
+ BluetoothDeathRecipient(BluetoothHci* hci) : mHci(hci) {}
+
+ void LinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
+ mCb = cb;
+ clientDeathRecipient_ = AIBinder_DeathRecipient_new(OnDeath);
+ auto linkToDeathReturnStatus = AIBinder_linkToDeath(
+ mCb->asBinder().get(), clientDeathRecipient_, this /* cookie */);
+ LOG_ALWAYS_FATAL_IF(linkToDeathReturnStatus != STATUS_OK,
+ "Unable to link to death recipient");
+ }
+
+ void UnlinkToDeath(const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
+ LOG_ALWAYS_FATAL_IF(cb != mCb, "Unable to unlink mismatched pointers");
+ }
+
+ void serviceDied() {
+ if (mCb != nullptr && !AIBinder_isAlive(mCb->asBinder().get())) {
+ ALOGE("Bluetooth remote service has died");
+ } else {
+ ALOGE("BluetoothDeathRecipient::serviceDied called but service not dead");
+ return;
+ }
+ has_died_ = true;
+ mHci->close();
+ }
+ BluetoothHci* mHci;
+ std::shared_ptr<IBluetoothHciCallbacks> mCb;
+ AIBinder_DeathRecipient* clientDeathRecipient_;
+ bool getHasDied() const { return has_died_; }
+
+ private:
+ bool has_died_{false};
+};
+
+void OnDeath(void* cookie) {
+ auto* death_recipient = static_cast<BluetoothDeathRecipient*>(cookie);
+ death_recipient->serviceDied();
+}
+
+BluetoothHci::BluetoothHci(const std::string& dev_path) {
+ char property_bytes[PROPERTY_VALUE_MAX];
+ property_get("vendor.ser.bt-uart", property_bytes, dev_path.c_str());
+ mDevPath = std::string(property_bytes);
+ mDeathRecipient = std::make_shared<BluetoothDeathRecipient>(this);
+}
+
+ndk::ScopedAStatus BluetoothHci::initialize(
+ const std::shared_ptr<IBluetoothHciCallbacks>& cb) {
+ ALOGI(__func__);
+
+ mFd = open(mDevPath.c_str(), O_RDWR);
+ if (mFd < 0) {
+ ALOGE("Could not connect to bt: %s (%s)", mDevPath.c_str(),
+ strerror(errno));
+ return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
+ }
+ if (int ret = SetTerminalRaw(mFd) < 0) {
+ ALOGE("Could not make %s a raw terminal %d(%s)", mDevPath.c_str(), ret,
+ strerror(errno));
+ return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
+ }
+
+ mCb = cb;
+ if (mCb == nullptr) {
+ ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
+ return ndk::ScopedAStatus::fromServiceSpecificError(STATUS_BAD_VALUE);
+ }
+
+ mDeathRecipient->LinkToDeath(mCb);
+
+ auto init_ret = cb->initializationComplete(Status::SUCCESS);
+ if (!init_ret.isOk()) {
+ if (!mDeathRecipient->getHasDied()) {
+ ALOGE("Error sending init callback, but no death notification.");
+ }
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ STATUS_FAILED_TRANSACTION);
+ }
+ mH4 = std::make_shared<H4Protocol>(
+ mFd,
+ [](const std::vector<uint8_t>& /* raw_command */) {
+ LOG_ALWAYS_FATAL("Unexpected command!");
+ },
+ [this](const std::vector<uint8_t>& raw_event) {
+ mCb->hciEventReceived(raw_event);
+ },
+ [this](const std::vector<uint8_t>& raw_acl) {
+ mCb->hciEventReceived(raw_acl);
+ },
+ [this](const std::vector<uint8_t>& raw_sco) {
+ mCb->hciEventReceived(raw_sco);
+ },
+ [this](const std::vector<uint8_t>& raw_iso) {
+ mCb->hciEventReceived(raw_iso);
+ },
+ [this]() {
+ ALOGI("HCI socket device disconnected");
+ mFdWatcher.StopWatchingFileDescriptors();
+ });
+ mFdWatcher.WatchFdForNonBlockingReads(mFd,
+ [this](int) { mH4->OnDataReady(); });
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothHci::close() {
+ ALOGI(__func__);
+ mFdWatcher.StopWatchingFileDescriptors();
+ ::close(mFd);
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothHci::sendHciCommand(
+ const std::vector<uint8_t>& packet) {
+ send(PacketType::COMMAND, packet);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothHci::sendAclData(
+ const std::vector<uint8_t>& packet) {
+ send(PacketType::ACL_DATA, packet);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothHci::sendScoData(
+ const std::vector<uint8_t>& packet) {
+ send(PacketType::SCO_DATA, packet);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus BluetoothHci::sendIsoData(
+ const std::vector<uint8_t>& packet) {
+ send(PacketType::ISO_DATA, packet);
+ return ndk::ScopedAStatus::ok();
+}
+
+void BluetoothHci::send(PacketType type, const std::vector<uint8_t>& v) {
+ mH4->Send(type, v);
+}
+
+} // namespace aidl::android::hardware::bluetooth::impl
diff --git a/bluetooth/aidl/default/BluetoothHci.h b/bluetooth/aidl/default/BluetoothHci.h
new file mode 100644
index 0000000..0ed0623
--- /dev/null
+++ b/bluetooth/aidl/default/BluetoothHci.h
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/bluetooth/BnBluetoothHci.h>
+#include <aidl/android/hardware/bluetooth/IBluetoothHciCallbacks.h>
+#include <log/log.h>
+
+#include <string>
+
+#include "async_fd_watcher.h"
+#include "h4_protocol.h"
+
+namespace aidl::android::hardware::bluetooth::impl {
+
+class BluetoothDeathRecipient;
+
+// This Bluetooth HAL implementation connects with a serial port at dev_path_.
+class BluetoothHci : public BnBluetoothHci {
+ public:
+ BluetoothHci(const std::string& dev_path = "/dev/hvc5");
+
+ ndk::ScopedAStatus initialize(
+ const std::shared_ptr<IBluetoothHciCallbacks>& cb) override;
+
+ ndk::ScopedAStatus sendHciCommand(
+ const std::vector<uint8_t>& packet) override;
+
+ ndk::ScopedAStatus sendAclData(const std::vector<uint8_t>& packet) override;
+
+ ndk::ScopedAStatus sendScoData(const std::vector<uint8_t>& packet) override;
+
+ ndk::ScopedAStatus sendIsoData(const std::vector<uint8_t>& packet) override;
+
+ ndk::ScopedAStatus close() override;
+
+ static void OnPacketReady();
+
+ static BluetoothHci* get();
+
+ private:
+ int mFd{-1};
+ std::shared_ptr<IBluetoothHciCallbacks> mCb = nullptr;
+
+ std::shared_ptr<::android::hardware::bluetooth::hci::H4Protocol> mH4;
+
+ std::shared_ptr<BluetoothDeathRecipient> mDeathRecipient;
+
+ std::string mDevPath;
+
+ ::android::hardware::bluetooth::async::AsyncFdWatcher mFdWatcher;
+
+ void send(::android::hardware::bluetooth::hci::PacketType type,
+ const std::vector<uint8_t>& packet);
+};
+
+} // namespace aidl::android::hardware::bluetooth::impl
diff --git a/bluetooth/aidl/default/bluetooth-service-default.rc b/bluetooth/aidl/default/bluetooth-service-default.rc
new file mode 100644
index 0000000..1841c77
--- /dev/null
+++ b/bluetooth/aidl/default/bluetooth-service-default.rc
@@ -0,0 +1,6 @@
+service bluetooth_hal_service /vendor/bin/hw/android.hardware.bluetooth-service.default
+ class hal
+ capabilities BLOCK_SUSPEND NET_ADMIN SYS_NICE
+ user bluetooth
+ group bluetooth
+ task_profiles HighPerformance
diff --git a/bluetooth/aidl/default/bluetooth-service-default.xml b/bluetooth/aidl/default/bluetooth-service-default.xml
new file mode 100644
index 0000000..bb05995
--- /dev/null
+++ b/bluetooth/aidl/default/bluetooth-service-default.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.bluetooth</name>
+ <fqname>IBluetoothHci/default</fqname>
+ </hal>
+</manifest>
diff --git a/bluetooth/aidl/default/service.cpp b/bluetooth/aidl/default/service.cpp
new file mode 100644
index 0000000..9af2a08
--- /dev/null
+++ b/bluetooth/aidl/default/service.cpp
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "aidl.android.hardware.bluetooth.service.default"
+
+#include <aidl/android/hardware/bluetooth/IBluetoothHci.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <hidl/HidlSupport.h>
+#include <hidl/HidlTransportSupport.h>
+
+#include "BluetoothHci.h"
+
+using ::aidl::android::hardware::bluetooth::impl::BluetoothHci;
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+
+int main(int /* argc */, char** /* argv */) {
+ ALOGI("Bluetooth HAL starting");
+ if (!ABinderProcess_setThreadPoolMaxThreadCount(1)) {
+ ALOGI("failed to set thread pool max thread count");
+ return 1;
+ }
+
+ std::shared_ptr<BluetoothHci> service =
+ ndk::SharedRefBase::make<BluetoothHci>();
+ std::string instance = std::string() + BluetoothHci::descriptor + "/default";
+ auto result =
+ AServiceManager_addService(service->asBinder().get(), instance.c_str());
+ if (result == STATUS_OK) {
+ ABinderProcess_joinThreadPool();
+ } else {
+ ALOGE("Could not register as a service!");
+ }
+ return 0;
+}
diff --git a/bluetooth/aidl/default/test/fuzzer.cpp b/bluetooth/aidl/default/test/fuzzer.cpp
new file mode 100644
index 0000000..e7a1eef
--- /dev/null
+++ b/bluetooth/aidl/default/test/fuzzer.cpp
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ */
+
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "BluetoothHci.h"
+
+using aidl::android::hardware::bluetooth::impl::BluetoothHci;
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto service = SharedRefBase::make<BluetoothHci>();
+
+ fuzzService(service->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
diff --git a/bluetooth/async/Android.bp b/bluetooth/async/Android.bp
new file mode 100644
index 0000000..bd7d7b8
--- /dev/null
+++ b/bluetooth/async/Android.bp
@@ -0,0 +1,41 @@
+package {
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+ name: "android.hardware.bluetooth.async",
+ vendor_available: true,
+ host_supported: true,
+ srcs: [
+ "async_fd_watcher.cc",
+ ],
+ export_include_dirs: ["."],
+ shared_libs: [
+ "liblog",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+}
+
+cc_test {
+ name: "bluetooth-vendor-interface-async-test",
+ host_supported: true,
+ srcs: [
+ "test/async_fd_watcher_unittest.cc",
+ ],
+ shared_libs: [
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "android.hardware.bluetooth.async",
+ "libgmock",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ test_suites: ["general-tests"],
+}
diff --git a/bluetooth/async/async_fd_watcher.cc b/bluetooth/async/async_fd_watcher.cc
new file mode 100644
index 0000000..fb634ff
--- /dev/null
+++ b/bluetooth/async/async_fd_watcher.cc
@@ -0,0 +1,176 @@
+/*
+ * 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.
+ */
+
+#include "async_fd_watcher.h"
+
+#include <string.h>
+
+#include <algorithm>
+#include <atomic>
+#include <condition_variable>
+#include <map>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+#include "fcntl.h"
+#include "log/log.h"
+#include "sys/select.h"
+#include "unistd.h"
+
+static const int INVALID_FD = -1;
+
+namespace android::hardware::bluetooth::async {
+
+int AsyncFdWatcher::WatchFdForNonBlockingReads(
+ int file_descriptor, const ReadCallback& on_read_fd_ready_callback) {
+ // Add file descriptor and callback
+ {
+ std::unique_lock<std::mutex> guard(internal_mutex_);
+ watched_fds_[file_descriptor] = on_read_fd_ready_callback;
+ }
+
+ // Start the thread if not started yet
+ return tryStartThread();
+}
+
+int AsyncFdWatcher::ConfigureTimeout(
+ const std::chrono::milliseconds timeout,
+ const TimeoutCallback& on_timeout_callback) {
+ // Add timeout and callback
+ {
+ std::unique_lock<std::mutex> guard(timeout_mutex_);
+ timeout_cb_ = on_timeout_callback;
+ timeout_ms_ = timeout;
+ }
+
+ notifyThread();
+ return 0;
+}
+
+void AsyncFdWatcher::StopWatchingFileDescriptors() { stopThread(); }
+
+AsyncFdWatcher::~AsyncFdWatcher() {}
+
+// Make sure to call this with at least one file descriptor ready to be
+// watched upon or the thread routine will return immediately
+int AsyncFdWatcher::tryStartThread() {
+ if (std::atomic_exchange(&running_, true)) return 0;
+
+ // Set up the communication channel
+ int pipe_fds[2];
+ if (pipe2(pipe_fds, O_NONBLOCK)) return -1;
+
+ notification_listen_fd_ = pipe_fds[0];
+ notification_write_fd_ = pipe_fds[1];
+
+ thread_ = std::thread([this]() { ThreadRoutine(); });
+ if (!thread_.joinable()) return -1;
+
+ return 0;
+}
+
+int AsyncFdWatcher::stopThread() {
+ if (!std::atomic_exchange(&running_, false)) return 0;
+
+ notifyThread();
+ if (std::this_thread::get_id() != thread_.get_id()) {
+ thread_.join();
+ }
+
+ {
+ std::unique_lock<std::mutex> guard(internal_mutex_);
+ watched_fds_.clear();
+ }
+
+ {
+ std::unique_lock<std::mutex> guard(timeout_mutex_);
+ timeout_cb_ = nullptr;
+ }
+
+ close(notification_listen_fd_);
+ close(notification_write_fd_);
+
+ return 0;
+}
+
+int AsyncFdWatcher::notifyThread() {
+ uint8_t buffer[] = {0};
+ if (TEMP_FAILURE_RETRY(write(notification_write_fd_, &buffer, 1)) < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+void AsyncFdWatcher::ThreadRoutine() {
+ while (running_) {
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+ FD_SET(notification_listen_fd_, &read_fds);
+ int max_read_fd = INVALID_FD;
+ for (auto& it : watched_fds_) {
+ FD_SET(it.first, &read_fds);
+ max_read_fd = std::max(max_read_fd, it.first);
+ }
+
+ struct timeval timeout;
+ struct timeval* timeout_ptr = NULL;
+ if (timeout_ms_ > std::chrono::milliseconds(0)) {
+ timeout.tv_sec = timeout_ms_.count() / 1000;
+ timeout.tv_usec = (timeout_ms_.count() % 1000) * 1000;
+ timeout_ptr = &timeout;
+ }
+
+ // Wait until there is data available to read on some FD.
+ int nfds = std::max(notification_listen_fd_, max_read_fd);
+ int retval = select(nfds + 1, &read_fds, NULL, NULL, timeout_ptr);
+
+ // There was some error.
+ if (retval < 0) continue;
+
+ // Timeout.
+ if (retval == 0) {
+ // Allow the timeout callback to modify the timeout.
+ TimeoutCallback saved_cb;
+ {
+ std::unique_lock<std::mutex> guard(timeout_mutex_);
+ if (timeout_ms_ > std::chrono::milliseconds(0)) saved_cb = timeout_cb_;
+ }
+ if (saved_cb != nullptr) saved_cb();
+ continue;
+ }
+
+ // Read data from the notification FD.
+ if (FD_ISSET(notification_listen_fd_, &read_fds)) {
+ char buffer[] = {0};
+ TEMP_FAILURE_RETRY(read(notification_listen_fd_, buffer, 1));
+ continue;
+ }
+
+ // Invoke the data ready callbacks if appropriate.
+ {
+ // Hold the mutex to make sure that the callbacks are still valid.
+ std::unique_lock<std::mutex> guard(internal_mutex_);
+ for (auto& it : watched_fds_) {
+ if (FD_ISSET(it.first, &read_fds)) {
+ it.second(it.first);
+ }
+ }
+ }
+ }
+}
+
+} // namespace android::hardware::bluetooth::async
diff --git a/bluetooth/async/async_fd_watcher.h b/bluetooth/async/async_fd_watcher.h
new file mode 100644
index 0000000..b50a7a0
--- /dev/null
+++ b/bluetooth/async/async_fd_watcher.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <map>
+#include <mutex>
+#include <thread>
+
+namespace android::hardware::bluetooth::async {
+
+using ReadCallback = std::function<void(int)>;
+using TimeoutCallback = std::function<void(void)>;
+
+class AsyncFdWatcher {
+ public:
+ AsyncFdWatcher() = default;
+ ~AsyncFdWatcher();
+
+ int WatchFdForNonBlockingReads(int file_descriptor,
+ const ReadCallback& on_read_fd_ready_callback);
+ int ConfigureTimeout(const std::chrono::milliseconds timeout,
+ const TimeoutCallback& on_timeout_callback);
+ void StopWatchingFileDescriptors();
+
+ private:
+ AsyncFdWatcher(const AsyncFdWatcher&) = delete;
+ AsyncFdWatcher& operator=(const AsyncFdWatcher&) = delete;
+
+ int tryStartThread();
+ int stopThread();
+ int notifyThread();
+ void ThreadRoutine();
+
+ std::atomic_bool running_{false};
+ std::thread thread_;
+ std::mutex internal_mutex_;
+ std::mutex timeout_mutex_;
+
+ std::map<int, ReadCallback> watched_fds_;
+ int notification_listen_fd_;
+ int notification_write_fd_;
+ TimeoutCallback timeout_cb_;
+ std::chrono::milliseconds timeout_ms_;
+};
+
+} // namespace android::hardware::bluetooth::async
diff --git a/bluetooth/async/test/async_fd_watcher_unittest.cc b/bluetooth/async/test/async_fd_watcher_unittest.cc
new file mode 100644
index 0000000..6d75f10
--- /dev/null
+++ b/bluetooth/async/test/async_fd_watcher_unittest.cc
@@ -0,0 +1,377 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "async_fd_watcher_unittest"
+
+#include "async_fd_watcher.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cstdint>
+#include <cstring>
+#include <vector>
+
+namespace android::hardware::bluetooth::async_test {
+
+using android::hardware::bluetooth::async::AsyncFdWatcher;
+
+class AsyncFdWatcherSocketTest : public ::testing::Test {
+ public:
+ static const uint16_t kPort = 6111;
+ static const size_t kBufferSize = 16;
+
+ bool CheckBufferEquals() {
+ return strcmp(server_buffer_, client_buffer_) == 0;
+ }
+
+ protected:
+ int StartServer() {
+ ALOGD("%s", __func__);
+ struct sockaddr_in serv_addr;
+ int fd = socket(AF_INET, SOCK_STREAM, 0);
+ EXPECT_FALSE(fd < 0);
+
+ memset(&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ serv_addr.sin_port = htons(kPort);
+ int reuse_flag = 1;
+ EXPECT_FALSE(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag,
+ sizeof(reuse_flag)) < 0);
+ EXPECT_FALSE(bind(fd, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0);
+
+ ALOGD("%s before listen", __func__);
+ listen(fd, 1);
+ return fd;
+ }
+
+ int AcceptConnection(int fd) {
+ ALOGD("%s", __func__);
+ struct sockaddr_in cli_addr;
+ memset(&cli_addr, 0, sizeof(cli_addr));
+ socklen_t clilen = sizeof(cli_addr);
+
+ int connection_fd = accept(fd, (struct sockaddr*)&cli_addr, &clilen);
+ EXPECT_FALSE(connection_fd < 0);
+
+ return connection_fd;
+ }
+
+ void ReadIncomingMessage(int fd) {
+ ALOGD("%s", __func__);
+ int n = TEMP_FAILURE_RETRY(read(fd, server_buffer_, kBufferSize - 1));
+ EXPECT_FALSE(n < 0);
+
+ if (n == 0) { // got EOF
+ ALOGD("%s: EOF", __func__);
+ } else {
+ ALOGD("%s: Got something", __func__);
+ n = write(fd, "1", 1);
+ }
+ }
+
+ void SetUp() override {
+ ALOGD("%s", __func__);
+ memset(server_buffer_, 0, kBufferSize);
+ memset(client_buffer_, 0, kBufferSize);
+ }
+
+ void ConfigureServer() {
+ socket_fd_ = StartServer();
+
+ conn_watcher_.WatchFdForNonBlockingReads(socket_fd_, [this](int fd) {
+ int connection_fd = AcceptConnection(fd);
+ ALOGD("%s: Conn_watcher fd = %d", __func__, fd);
+
+ conn_watcher_.ConfigureTimeout(std::chrono::seconds(0), []() {
+ bool connection_timeout_cleared = false;
+ ASSERT_TRUE(connection_timeout_cleared);
+ });
+
+ ALOGD("%s: 3", __func__);
+ async_fd_watcher_.WatchFdForNonBlockingReads(
+ connection_fd, [this](int fd) { ReadIncomingMessage(fd); });
+
+ // Time out if it takes longer than a second.
+ SetTimeout(std::chrono::seconds(1));
+ });
+ conn_watcher_.ConfigureTimeout(std::chrono::seconds(1), []() {
+ bool connection_timeout = true;
+ ASSERT_FALSE(connection_timeout);
+ });
+ }
+
+ void CleanUpServer() {
+ async_fd_watcher_.StopWatchingFileDescriptors();
+ conn_watcher_.StopWatchingFileDescriptors();
+ close(socket_fd_);
+ }
+
+ void TearDown() override {
+ ALOGD("%s 3", __func__);
+ EXPECT_TRUE(CheckBufferEquals());
+ }
+
+ void OnTimeout() {
+ ALOGD("%s", __func__);
+ timed_out_ = true;
+ }
+
+ void ClearTimeout() {
+ ALOGD("%s", __func__);
+ timed_out_ = false;
+ }
+
+ bool TimedOut() {
+ ALOGD("%s %d", __func__, timed_out_ ? 1 : 0);
+ return timed_out_;
+ }
+
+ void SetTimeout(std::chrono::milliseconds timeout_ms) {
+ ALOGD("%s", __func__);
+ async_fd_watcher_.ConfigureTimeout(timeout_ms, [this]() { OnTimeout(); });
+ ClearTimeout();
+ }
+
+ int ConnectClient() {
+ ALOGD("%s", __func__);
+ int socket_cli_fd = socket(AF_INET, SOCK_STREAM, 0);
+ EXPECT_FALSE(socket_cli_fd < 0);
+
+ struct sockaddr_in serv_addr;
+ memset((void*)&serv_addr, 0, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ serv_addr.sin_port = htons(kPort);
+
+ int result =
+ connect(socket_cli_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
+ EXPECT_FALSE(result < 0);
+
+ return socket_cli_fd;
+ }
+
+ void WriteFromClient(int socket_cli_fd) {
+ ALOGD("%s", __func__);
+ strcpy(client_buffer_, "1");
+ int n = write(socket_cli_fd, client_buffer_, strlen(client_buffer_));
+ EXPECT_TRUE(n > 0);
+ }
+
+ void AwaitServerResponse(int socket_cli_fd) {
+ ALOGD("%s", __func__);
+ int n = read(socket_cli_fd, client_buffer_, 1);
+ ALOGD("%s done", __func__);
+ EXPECT_TRUE(n > 0);
+ }
+
+ private:
+ AsyncFdWatcher async_fd_watcher_;
+ AsyncFdWatcher conn_watcher_;
+ int socket_fd_;
+ char server_buffer_[kBufferSize];
+ char client_buffer_[kBufferSize];
+ bool timed_out_;
+};
+
+// Use a single AsyncFdWatcher to signal a connection to the server socket.
+TEST_F(AsyncFdWatcherSocketTest, Connect) {
+ int socket_fd = StartServer();
+
+ AsyncFdWatcher conn_watcher;
+ conn_watcher.WatchFdForNonBlockingReads(socket_fd, [this](int fd) {
+ int connection_fd = AcceptConnection(fd);
+ close(connection_fd);
+ });
+
+ // Fail if the client doesn't connect within 1 second.
+ conn_watcher.ConfigureTimeout(std::chrono::seconds(1), []() {
+ bool connection_timeout = true;
+ ASSERT_FALSE(connection_timeout);
+ });
+
+ int socket_cli_fd = ConnectClient();
+ conn_watcher.StopWatchingFileDescriptors();
+ close(socket_fd);
+ close(socket_cli_fd);
+}
+
+// Use a single AsyncFdWatcher to signal a connection to the server socket.
+TEST_F(AsyncFdWatcherSocketTest, TimedOutConnect) {
+ int socket_fd = StartServer();
+ bool timed_out = false;
+ bool* timeout_ptr = &timed_out;
+
+ AsyncFdWatcher conn_watcher;
+ conn_watcher.WatchFdForNonBlockingReads(socket_fd, [this](int fd) {
+ int connection_fd = AcceptConnection(fd);
+ close(connection_fd);
+ });
+
+ // Set the timeout flag after 100ms.
+ conn_watcher.ConfigureTimeout(std::chrono::milliseconds(100),
+ [timeout_ptr]() { *timeout_ptr = true; });
+ EXPECT_FALSE(timed_out);
+ sleep(1);
+ EXPECT_TRUE(timed_out);
+ conn_watcher.StopWatchingFileDescriptors();
+ close(socket_fd);
+}
+
+// Modify the timeout in a timeout callback.
+TEST_F(AsyncFdWatcherSocketTest, TimedOutSchedulesTimeout) {
+ int socket_fd = StartServer();
+ bool timed_out = false;
+ bool timed_out2 = false;
+
+ AsyncFdWatcher conn_watcher;
+ conn_watcher.WatchFdForNonBlockingReads(socket_fd, [this](int fd) {
+ int connection_fd = AcceptConnection(fd);
+ close(connection_fd);
+ });
+
+ // Set a timeout flag in each callback.
+ conn_watcher.ConfigureTimeout(std::chrono::milliseconds(500),
+ [&conn_watcher, &timed_out, &timed_out2]() {
+ timed_out = true;
+ conn_watcher.ConfigureTimeout(
+ std::chrono::seconds(1),
+ [&timed_out2]() { timed_out2 = true; });
+ });
+ EXPECT_FALSE(timed_out);
+ EXPECT_FALSE(timed_out2);
+ sleep(1);
+ EXPECT_TRUE(timed_out);
+ EXPECT_FALSE(timed_out2);
+ sleep(1);
+ EXPECT_TRUE(timed_out);
+ EXPECT_TRUE(timed_out2);
+ conn_watcher.StopWatchingFileDescriptors();
+ close(socket_fd);
+}
+
+MATCHER_P(ReadAndMatchSingleChar, byte,
+ "Reads a byte from the file descriptor and matches the value against "
+ "byte") {
+ char inbuf[1] = {0};
+
+ int n = TEMP_FAILURE_RETRY(read(arg, inbuf, 1));
+
+ TEMP_FAILURE_RETRY(write(arg, inbuf, 1));
+ if (n != 1) {
+ return false;
+ }
+ return inbuf[0] == byte;
+};
+
+// Use a single AsyncFdWatcher to watch two file descriptors.
+TEST_F(AsyncFdWatcherSocketTest, WatchTwoFileDescriptors) {
+ int sockfd1[2];
+ int sockfd2[2];
+ socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd1);
+ socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd2);
+
+ testing::MockFunction<void(int)> cb1;
+ testing::MockFunction<void(int)> cb2;
+
+ AsyncFdWatcher watcher;
+ watcher.WatchFdForNonBlockingReads(sockfd1[0], cb1.AsStdFunction());
+
+ watcher.WatchFdForNonBlockingReads(sockfd2[0], cb2.AsStdFunction());
+
+ EXPECT_CALL(cb1, Call(ReadAndMatchSingleChar('1')));
+ char one_buf[1] = {'1'};
+ TEMP_FAILURE_RETRY(write(sockfd1[1], one_buf, sizeof(one_buf)));
+
+ EXPECT_CALL(cb2, Call(ReadAndMatchSingleChar('2')));
+ char two_buf[1] = {'2'};
+ TEMP_FAILURE_RETRY(write(sockfd2[1], two_buf, sizeof(two_buf)));
+
+ // Blocking read instead of a flush.
+ TEMP_FAILURE_RETRY(read(sockfd1[1], one_buf, sizeof(one_buf)));
+ TEMP_FAILURE_RETRY(read(sockfd2[1], two_buf, sizeof(two_buf)));
+
+ watcher.StopWatchingFileDescriptors();
+}
+
+// Use two AsyncFdWatchers to set up a server socket.
+TEST_F(AsyncFdWatcherSocketTest, ClientServer) {
+ ConfigureServer();
+ int socket_cli_fd = ConnectClient();
+
+ WriteFromClient(socket_cli_fd);
+
+ AwaitServerResponse(socket_cli_fd);
+
+ close(socket_cli_fd);
+ CleanUpServer();
+}
+
+// Use two AsyncFdWatchers to set up a server socket, which times out.
+TEST_F(AsyncFdWatcherSocketTest, TimeOutTest) {
+ ConfigureServer();
+ int socket_cli_fd = ConnectClient();
+
+ while (!TimedOut()) sleep(1);
+
+ close(socket_cli_fd);
+ CleanUpServer();
+}
+
+// Use two AsyncFdWatchers to set up a server socket, which times out.
+TEST_F(AsyncFdWatcherSocketTest, RepeatedTimeOutTest) {
+ ConfigureServer();
+ int socket_cli_fd = ConnectClient();
+ ClearTimeout();
+
+ // Time out when there are no writes.
+ EXPECT_FALSE(TimedOut());
+ sleep(2);
+ EXPECT_TRUE(TimedOut());
+ ClearTimeout();
+
+ // Don't time out when there is a write.
+ WriteFromClient(socket_cli_fd);
+ AwaitServerResponse(socket_cli_fd);
+ EXPECT_FALSE(TimedOut());
+ ClearTimeout();
+
+ // Time out when the write is late.
+ sleep(2);
+ WriteFromClient(socket_cli_fd);
+ AwaitServerResponse(socket_cli_fd);
+ EXPECT_TRUE(TimedOut());
+ ClearTimeout();
+
+ // Time out when there is a pause after a write.
+ WriteFromClient(socket_cli_fd);
+ sleep(2);
+ AwaitServerResponse(socket_cli_fd);
+ EXPECT_TRUE(TimedOut());
+ ClearTimeout();
+
+ close(socket_cli_fd);
+ CleanUpServer();
+}
+
+} // namespace android::hardware::bluetooth::async_test
diff --git a/bluetooth/audio/utils/Android.bp b/bluetooth/audio/utils/Android.bp
index 674dd11..70797a7 100644
--- a/bluetooth/audio/utils/Android.bp
+++ b/bluetooth/audio/utils/Android.bp
@@ -63,6 +63,31 @@
generated_headers: ["le_audio_codec_capabilities"],
}
+cc_test {
+ name: "BluetoothLeAudioCodecsProviderTest",
+ srcs: [
+ "aidl_session/BluetoothLeAudioCodecsProvider.cpp",
+ "aidl_session/BluetoothLeAudioCodecsProviderTest.cpp",
+ ],
+ header_libs: [
+ "libxsdc-utils",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "android.hardware.bluetooth.audio-V2-ndk",
+ "libxml2",
+ ],
+ test_suites: [
+ "general-tests",
+ ],
+ test_options: {
+ unit_test: false,
+ },
+ generated_sources: ["le_audio_codec_capabilities"],
+ generated_headers: ["le_audio_codec_capabilities"],
+}
+
xsd_config {
name: "le_audio_codec_capabilities",
srcs: ["le_audio_codec_capabilities/le_audio_codec_capabilities.xsd"],
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
index 855dd28..faebbbf 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothAudioCodecs.cpp
@@ -398,8 +398,11 @@
}
if (kDefaultOffloadLeAudioCapabilities.empty()) {
+ auto le_audio_offload_setting =
+ BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile();
kDefaultOffloadLeAudioCapabilities =
- BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities();
+ BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
+ le_audio_offload_setting);
}
return kDefaultOffloadLeAudioCapabilities;
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
index bf49270..1dec900 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.cpp
@@ -34,20 +34,40 @@
static std::vector<LeAudioCodecCapabilitiesSetting> leAudioCodecCapabilities;
-std::vector<LeAudioCodecCapabilitiesSetting>
-BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities() {
- if (!leAudioCodecCapabilities.empty()) {
- return leAudioCodecCapabilities;
- }
+static bool isInvalidFileContent = false;
- const auto le_audio_offload_setting =
+std::optional<setting::LeAudioOffloadSetting>
+BluetoothLeAudioCodecsProvider::ParseFromLeAudioOffloadSettingFile() {
+ if (!leAudioCodecCapabilities.empty() || isInvalidFileContent) {
+ return std::nullopt;
+ }
+ auto le_audio_offload_setting =
setting::readLeAudioOffloadSetting(kLeAudioCodecCapabilitiesFile);
if (!le_audio_offload_setting.has_value()) {
LOG(ERROR) << __func__ << ": Failed to read "
<< kLeAudioCodecCapabilitiesFile;
+ }
+ return le_audio_offload_setting;
+}
+
+std::vector<LeAudioCodecCapabilitiesSetting>
+BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
+ const std::optional<setting::LeAudioOffloadSetting>&
+ le_audio_offload_setting) {
+ if (!leAudioCodecCapabilities.empty()) {
+ return leAudioCodecCapabilities;
+ }
+
+ if (!le_audio_offload_setting.has_value()) {
+ LOG(ERROR)
+ << __func__
+ << ": input le_audio_offload_setting content need to be non empty";
return {};
}
+ ClearLeAudioCodecCapabilities();
+ isInvalidFileContent = true;
+
std::vector<setting::Scenario> supported_scenarios =
GetScenarios(le_audio_offload_setting);
if (supported_scenarios.empty()) {
@@ -79,9 +99,18 @@
leAudioCodecCapabilities =
ComposeLeAudioCodecCapabilities(supported_scenarios);
+ isInvalidFileContent = leAudioCodecCapabilities.empty();
+
return leAudioCodecCapabilities;
}
+void BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities() {
+ leAudioCodecCapabilities.clear();
+ configuration_map_.clear();
+ codec_configuration_map_.clear();
+ strategy_configuration_map_.clear();
+}
+
std::vector<setting::Scenario> BluetoothLeAudioCodecsProvider::GetScenarios(
const std::optional<setting::LeAudioOffloadSetting>&
le_audio_offload_setting) {
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
index 402235f..e879984 100644
--- a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProvider.h
@@ -31,8 +31,13 @@
class BluetoothLeAudioCodecsProvider {
public:
+ static std::optional<setting::LeAudioOffloadSetting>
+ ParseFromLeAudioOffloadSettingFile();
static std::vector<LeAudioCodecCapabilitiesSetting>
- GetLeAudioCodecCapabilities();
+ GetLeAudioCodecCapabilities(
+ const std::optional<setting::LeAudioOffloadSetting>&
+ le_audio_offload_setting);
+ static void ClearLeAudioCodecCapabilities();
private:
static inline std::unordered_map<std::string, setting::Configuration>
diff --git a/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
new file mode 100644
index 0000000..5393cd7
--- /dev/null
+++ b/bluetooth/audio/utils/aidl_session/BluetoothLeAudioCodecsProviderTest.cpp
@@ -0,0 +1,373 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <optional>
+#include <tuple>
+
+#include "BluetoothLeAudioCodecsProvider.h"
+
+using aidl::android::hardware::bluetooth::audio::BluetoothLeAudioCodecsProvider;
+using aidl::android::hardware::bluetooth::audio::
+ LeAudioCodecCapabilitiesSetting;
+using aidl::android::hardware::bluetooth::audio::setting::AudioLocation;
+using aidl::android::hardware::bluetooth::audio::setting::CodecConfiguration;
+using aidl::android::hardware::bluetooth::audio::setting::
+ CodecConfigurationList;
+using aidl::android::hardware::bluetooth::audio::setting::CodecType;
+using aidl::android::hardware::bluetooth::audio::setting::Configuration;
+using aidl::android::hardware::bluetooth::audio::setting::ConfigurationList;
+using aidl::android::hardware::bluetooth::audio::setting::LeAudioOffloadSetting;
+using aidl::android::hardware::bluetooth::audio::setting::Scenario;
+using aidl::android::hardware::bluetooth::audio::setting::ScenarioList;
+using aidl::android::hardware::bluetooth::audio::setting::StrategyConfiguration;
+using aidl::android::hardware::bluetooth::audio::setting::
+ StrategyConfigurationList;
+
+typedef std::tuple<std::vector<ScenarioList>, std::vector<ConfigurationList>,
+ std::vector<CodecConfigurationList>,
+ std::vector<StrategyConfigurationList>>
+ OffloadSetting;
+
+// Define valid components for each list
+// Scenario
+static const Scenario kValidScenario(std::make_optional("OneChanStereo_16_1"),
+ std::make_optional("OneChanStereo_16_1"));
+// Configuration
+static const Configuration kValidConfigOneChanStereo_16_1(
+ std::make_optional("OneChanStereo_16_1"), std::make_optional("LC3_16k_1"),
+ std::make_optional("STEREO_ONE_CIS_PER_DEVICE"));
+// CodecConfiguration
+static const CodecConfiguration kValidCodecLC3_16k_1(
+ std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
+ std::nullopt, std::make_optional(16000), std::make_optional(7500),
+ std::make_optional(30), std::nullopt);
+// StrategyConfiguration
+static const StrategyConfiguration kValidStrategyStereoOneCis(
+ std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+ std::make_optional(AudioLocation::STEREO), std::make_optional(2),
+ std::make_optional(1));
+static const StrategyConfiguration kValidStrategyStereoTwoCis(
+ std::make_optional("STEREO_TWO_CISES_PER_DEVICE"),
+ std::make_optional(AudioLocation::STEREO), std::make_optional(1),
+ std::make_optional(2));
+static const StrategyConfiguration kValidStrategyMonoOneCis(
+ std::make_optional("MONO_ONE_CIS_PER_DEVICE"),
+ std::make_optional(AudioLocation::MONO), std::make_optional(1),
+ std::make_optional(1));
+
+// Define valid test list built from above valid components
+// Scenario, Configuration, CodecConfiguration, StrategyConfiguration
+static const std::vector<ScenarioList> kValidScenarioList = {
+ ScenarioList(std::vector<Scenario>{kValidScenario})};
+static const std::vector<ConfigurationList> kValidConfigurationList = {
+ ConfigurationList(
+ std::vector<Configuration>{kValidConfigOneChanStereo_16_1})};
+static const std::vector<CodecConfigurationList> kValidCodecConfigurationList =
+ {CodecConfigurationList(
+ std::vector<CodecConfiguration>{kValidCodecLC3_16k_1})};
+static const std::vector<StrategyConfigurationList>
+ kValidStrategyConfigurationList = {
+ StrategyConfigurationList(std::vector<StrategyConfiguration>{
+ kValidStrategyStereoOneCis, kValidStrategyStereoTwoCis,
+ kValidStrategyMonoOneCis})};
+
+class BluetoothLeAudioCodecsProviderTest
+ : public ::testing::TestWithParam<OffloadSetting> {
+ public:
+ static std::vector<OffloadSetting> CreateTestCases(
+ const std::vector<ScenarioList>& scenario_lists,
+ const std::vector<ConfigurationList>& configuration_lists,
+ const std::vector<CodecConfigurationList>& codec_configuration_lists,
+ const std::vector<StrategyConfigurationList>&
+ strategy_configuration_lists) {
+ // make each vector in output test_cases has only one element
+ // to match the input of test params
+ // normally only one vector in input has multiple elements
+ // we just split elements in this vector to several vector
+ std::vector<OffloadSetting> test_cases;
+ for (const auto& scenario_list : scenario_lists) {
+ for (const auto& configuration_list : configuration_lists) {
+ for (const auto& codec_configuration_list : codec_configuration_lists) {
+ for (const auto& strategy_configuration_list :
+ strategy_configuration_lists) {
+ test_cases.push_back(CreateTestCase(
+ scenario_list, configuration_list, codec_configuration_list,
+ strategy_configuration_list));
+ }
+ }
+ }
+ }
+ return test_cases;
+ }
+
+ protected:
+ void Initialize() {
+ BluetoothLeAudioCodecsProvider::ClearLeAudioCodecCapabilities();
+ }
+
+ std::vector<LeAudioCodecCapabilitiesSetting> RunTestCase() {
+ auto& [scenario_lists, configuration_lists, codec_configuration_lists,
+ strategy_configuration_lists] = GetParam();
+ LeAudioOffloadSetting le_audio_offload_setting(
+ scenario_lists, configuration_lists, codec_configuration_lists,
+ strategy_configuration_lists);
+ auto le_audio_codec_capabilities =
+ BluetoothLeAudioCodecsProvider::GetLeAudioCodecCapabilities(
+ std::make_optional(le_audio_offload_setting));
+ return le_audio_codec_capabilities;
+ }
+
+ private:
+ static inline OffloadSetting CreateTestCase(
+ const ScenarioList& scenario_list,
+ const ConfigurationList& configuration_list,
+ const CodecConfigurationList& codec_configuration_list,
+ const StrategyConfigurationList& strategy_configuration_list) {
+ return std::make_tuple(
+ std::vector<ScenarioList>{scenario_list},
+ std::vector<ConfigurationList>{configuration_list},
+ std::vector<CodecConfigurationList>{codec_configuration_list},
+ std::vector<StrategyConfigurationList>{strategy_configuration_list});
+ }
+};
+
+class GetScenariosTest : public BluetoothLeAudioCodecsProviderTest {
+ public:
+ static std::vector<ScenarioList> CreateInvalidScenarios() {
+ std::vector<ScenarioList> invalid_scenario_test_cases;
+ invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
+ Scenario(std::nullopt, std::make_optional("OneChanStereo_16_1"))}));
+
+ invalid_scenario_test_cases.push_back(ScenarioList(std::vector<Scenario>{
+ Scenario(std::make_optional("OneChanStereo_16_1"), std::nullopt)}));
+
+ invalid_scenario_test_cases.push_back(ScenarioList(
+ std::vector<Scenario>{Scenario(std::nullopt, std::nullopt)}));
+
+ invalid_scenario_test_cases.push_back(
+ ScenarioList(std::vector<Scenario>{}));
+
+ return invalid_scenario_test_cases;
+ }
+};
+
+TEST_P(GetScenariosTest, InvalidScenarios) {
+ Initialize();
+ auto le_audio_codec_capabilities = RunTestCase();
+ ASSERT_TRUE(le_audio_codec_capabilities.empty());
+}
+
+class UpdateConfigurationsToMapTest
+ : public BluetoothLeAudioCodecsProviderTest {
+ public:
+ static std::vector<ConfigurationList> CreateInvalidConfigurations() {
+ std::vector<ConfigurationList> invalid_configuration_test_cases;
+ invalid_configuration_test_cases.push_back(
+ ConfigurationList(std::vector<Configuration>{
+ Configuration(std::nullopt, std::make_optional("LC3_16k_1"),
+ std::make_optional("STEREO_ONE_CIS_PER_DEVICE"))}));
+
+ invalid_configuration_test_cases.push_back(
+ ConfigurationList(std::vector<Configuration>{Configuration(
+ std::make_optional("OneChanStereo_16_1"), std::nullopt,
+ std::make_optional("STEREO_ONE_CIS_PER_DEVICE"))}));
+
+ invalid_configuration_test_cases.push_back(
+ ConfigurationList(std::vector<Configuration>{
+ Configuration(std::make_optional("OneChanStereo_16_1"),
+ std::make_optional("LC3_16k_1"), std::nullopt)}));
+
+ invalid_configuration_test_cases.push_back(
+ ConfigurationList(std::vector<Configuration>{}));
+
+ return invalid_configuration_test_cases;
+ }
+};
+
+TEST_P(UpdateConfigurationsToMapTest, InvalidConfigurations) {
+ Initialize();
+ auto le_audio_codec_capabilities = RunTestCase();
+ ASSERT_TRUE(le_audio_codec_capabilities.empty());
+}
+
+class UpdateCodecConfigurationsToMapTest
+ : public BluetoothLeAudioCodecsProviderTest {
+ public:
+ static std::vector<CodecConfigurationList>
+ CreateInvalidCodecConfigurations() {
+ std::vector<CodecConfigurationList> invalid_codec_configuration_test_cases;
+ invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
+ std::vector<CodecConfiguration>{CodecConfiguration(
+ std::nullopt, std::make_optional(CodecType::LC3), std::nullopt,
+ std::make_optional(16000), std::make_optional(7500),
+ std::make_optional(30), std::nullopt)}));
+
+ invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
+ std::vector<CodecConfiguration>{CodecConfiguration(
+ std::make_optional("LC3_16k_1"), std::nullopt, std::nullopt,
+ std::make_optional(16000), std::make_optional(7500),
+ std::make_optional(30), std::nullopt)}));
+
+ invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
+ std::vector<CodecConfiguration>{CodecConfiguration(
+ std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
+ std::nullopt, std::nullopt, std::make_optional(7500),
+ std::make_optional(30), std::nullopt)}));
+
+ invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
+ std::vector<CodecConfiguration>{CodecConfiguration(
+ std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
+ std::nullopt, std::make_optional(16000), std::nullopt,
+ std::make_optional(30), std::nullopt)}));
+
+ invalid_codec_configuration_test_cases.push_back(CodecConfigurationList(
+ std::vector<CodecConfiguration>{CodecConfiguration(
+ std::make_optional("LC3_16k_1"), std::make_optional(CodecType::LC3),
+ std::nullopt, std::make_optional(16000), std::make_optional(7500),
+ std::nullopt, std::nullopt)}));
+
+ invalid_codec_configuration_test_cases.push_back(
+ CodecConfigurationList(std::vector<CodecConfiguration>{}));
+
+ return invalid_codec_configuration_test_cases;
+ }
+};
+
+TEST_P(UpdateCodecConfigurationsToMapTest, InvalidCodecConfigurations) {
+ Initialize();
+ auto le_audio_codec_capabilities = RunTestCase();
+ ASSERT_TRUE(le_audio_codec_capabilities.empty());
+}
+
+class UpdateStrategyConfigurationsToMapTest
+ : public BluetoothLeAudioCodecsProviderTest {
+ public:
+ static std::vector<StrategyConfigurationList>
+ CreateInvalidStrategyConfigurations() {
+ std::vector<StrategyConfigurationList>
+ invalid_strategy_configuration_test_cases;
+ invalid_strategy_configuration_test_cases.push_back(
+ StrategyConfigurationList(
+ std::vector<StrategyConfiguration>{StrategyConfiguration(
+ std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+ std::make_optional(AudioLocation::STEREO),
+ std::make_optional(2), std::make_optional(2))}));
+
+ invalid_strategy_configuration_test_cases.push_back(
+ StrategyConfigurationList(
+ std::vector<StrategyConfiguration>{StrategyConfiguration(
+ std::make_optional("MONO_ONE_CIS_PER_DEVICE"),
+ std::make_optional(AudioLocation::STEREO),
+ std::make_optional(2), std::make_optional(2))}));
+
+ invalid_strategy_configuration_test_cases.push_back(
+ StrategyConfigurationList(
+ std::vector<StrategyConfiguration>{StrategyConfiguration(
+ std::nullopt, std::make_optional(AudioLocation::STEREO),
+ std::make_optional(2), std::make_optional(1))}));
+
+ invalid_strategy_configuration_test_cases.push_back(
+ StrategyConfigurationList(
+ std::vector<StrategyConfiguration>{StrategyConfiguration(
+ std::make_optional("STEREO_ONE_CIS_PER_DEVICE"), std::nullopt,
+ std::make_optional(2), std::make_optional(1))}));
+
+ invalid_strategy_configuration_test_cases.push_back(
+ StrategyConfigurationList(
+ std::vector<StrategyConfiguration>{StrategyConfiguration(
+ std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+ std::make_optional(AudioLocation::STEREO), std::nullopt,
+ std::make_optional(1))}));
+
+ invalid_strategy_configuration_test_cases.push_back(
+ StrategyConfigurationList(
+ std::vector<StrategyConfiguration>{StrategyConfiguration(
+ std::make_optional("STEREO_ONE_CIS_PER_DEVICE"),
+ std::make_optional(AudioLocation::STEREO),
+ std::make_optional(2), std::nullopt)}));
+
+ invalid_strategy_configuration_test_cases.push_back(
+ StrategyConfigurationList(std::vector<StrategyConfiguration>{}));
+
+ return invalid_strategy_configuration_test_cases;
+ }
+};
+
+TEST_P(UpdateStrategyConfigurationsToMapTest, InvalidStrategyConfigurations) {
+ Initialize();
+ auto le_audio_codec_capabilities = RunTestCase();
+ ASSERT_TRUE(le_audio_codec_capabilities.empty());
+}
+
+class ComposeLeAudioCodecCapabilitiesTest
+ : public BluetoothLeAudioCodecsProviderTest {
+ public:
+};
+
+TEST_P(ComposeLeAudioCodecCapabilitiesTest, CodecCapabilitiesNotEmpty) {
+ Initialize();
+ auto le_audio_codec_capabilities = RunTestCase();
+ ASSERT_TRUE(!le_audio_codec_capabilities.empty());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GetScenariosTest);
+INSTANTIATE_TEST_SUITE_P(
+ BluetoothLeAudioCodecsProviderTest, GetScenariosTest,
+ ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
+ GetScenariosTest::CreateInvalidScenarios(), kValidConfigurationList,
+ kValidCodecConfigurationList, kValidStrategyConfigurationList)));
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UpdateConfigurationsToMapTest);
+INSTANTIATE_TEST_SUITE_P(
+ BluetoothLeAudioCodecsProviderTest, UpdateConfigurationsToMapTest,
+ ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
+ kValidScenarioList,
+ UpdateConfigurationsToMapTest::CreateInvalidConfigurations(),
+ kValidCodecConfigurationList, kValidStrategyConfigurationList)));
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ UpdateCodecConfigurationsToMapTest);
+INSTANTIATE_TEST_SUITE_P(
+ BluetoothLeAudioCodecsProviderTest, UpdateCodecConfigurationsToMapTest,
+ ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
+ kValidScenarioList, kValidConfigurationList,
+ UpdateCodecConfigurationsToMapTest::CreateInvalidCodecConfigurations(),
+ kValidStrategyConfigurationList)));
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ UpdateStrategyConfigurationsToMapTest);
+INSTANTIATE_TEST_SUITE_P(
+ BluetoothLeAudioCodecsProviderTest, UpdateStrategyConfigurationsToMapTest,
+ ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
+ kValidScenarioList, kValidConfigurationList,
+ kValidCodecConfigurationList,
+ UpdateStrategyConfigurationsToMapTest::
+ CreateInvalidStrategyConfigurations())));
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(
+ ComposeLeAudioCodecCapabilitiesTest);
+INSTANTIATE_TEST_SUITE_P(
+ BluetoothLeAudioCodecsProviderTest, ComposeLeAudioCodecCapabilitiesTest,
+ ::testing::ValuesIn(BluetoothLeAudioCodecsProviderTest::CreateTestCases(
+ kValidScenarioList, kValidConfigurationList,
+ kValidCodecConfigurationList, kValidStrategyConfigurationList)));
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
diff --git a/bluetooth/hci/Android.bp b/bluetooth/hci/Android.bp
new file mode 100644
index 0000000..f0f6e8f
--- /dev/null
+++ b/bluetooth/hci/Android.bp
@@ -0,0 +1,46 @@
+package {
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_library_static {
+ name: "android.hardware.bluetooth.hci",
+ vendor_available: true,
+ host_supported: true,
+ defaults: ["hidl_defaults"],
+ srcs: [
+ "hci_packetizer.cc",
+ "h4_protocol.cc",
+ ],
+ export_include_dirs: ["."],
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+}
+
+cc_test {
+ name: "bluetooth-vendor-interface-hci-test",
+ host_supported: true,
+ defaults: ["hidl_defaults"],
+ srcs: [
+ "test/h4_protocol_unittest.cc",
+ ],
+ shared_libs: [
+ "libbase",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "android.hardware.bluetooth.async",
+ "android.hardware.bluetooth.hci",
+ "libgmock",
+ ],
+ sanitize: {
+ address: true,
+ cfi: true,
+ },
+ test_suites: ["general-tests"],
+}
diff --git a/bluetooth/hci/h4_protocol.cc b/bluetooth/hci/h4_protocol.cc
new file mode 100644
index 0000000..97ba7aa
--- /dev/null
+++ b/bluetooth/hci/h4_protocol.cc
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ */
+
+#include "h4_protocol.h"
+
+#define LOG_TAG "android.hardware.bluetooth.hci-h4"
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sys/uio.h>
+
+#include "log/log.h"
+
+namespace android::hardware::bluetooth::hci {
+
+H4Protocol::H4Protocol(int fd, PacketReadCallback cmd_cb,
+ PacketReadCallback acl_cb, PacketReadCallback sco_cb,
+ PacketReadCallback event_cb, PacketReadCallback iso_cb,
+ DisconnectCallback disconnect_cb)
+ : uart_fd_(fd),
+ cmd_cb_(std::move(cmd_cb)),
+ acl_cb_(std::move(acl_cb)),
+ sco_cb_(std::move(sco_cb)),
+ event_cb_(std::move(event_cb)),
+ iso_cb_(std::move(iso_cb)),
+ disconnect_cb_(std::move(disconnect_cb)) {}
+
+size_t H4Protocol::Send(PacketType type, const std::vector<uint8_t>& vector) {
+ return Send(type, vector.data(), vector.size());
+}
+
+size_t H4Protocol::Send(PacketType type, const uint8_t* data, size_t length) {
+ /* For HCI communication over USB dongle, multiple write results in
+ * response timeout as driver expect type + data at once to process
+ * the command, so using "writev"(for atomicity) here.
+ */
+ struct iovec iov[2];
+ ssize_t ret = 0;
+ iov[0].iov_base = &type;
+ iov[0].iov_len = sizeof(type);
+ iov[1].iov_base = (void*)data;
+ iov[1].iov_len = length;
+ while (1) {
+ ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, 2));
+ if (ret == -1) {
+ if (errno == EAGAIN) {
+ ALOGE("%s error writing to UART (%s)", __func__, strerror(errno));
+ continue;
+ }
+ } else if (ret == 0) {
+ // Nothing written :(
+ ALOGE("%s zero bytes written - something went wrong...", __func__);
+ break;
+ }
+ break;
+ }
+ return ret;
+}
+
+size_t H4Protocol::OnPacketReady(const std::vector<uint8_t>& packet) {
+ switch (hci_packet_type_) {
+ case PacketType::COMMAND:
+ cmd_cb_(packet);
+ break;
+ case PacketType::ACL_DATA:
+ acl_cb_(packet);
+ break;
+ case PacketType::SCO_DATA:
+ sco_cb_(packet);
+ break;
+ case PacketType::EVENT:
+ event_cb_(packet);
+ break;
+ case PacketType::ISO_DATA:
+ iso_cb_(packet);
+ break;
+ default: {
+ LOG_ALWAYS_FATAL("Bad packet type 0x%x",
+ static_cast<int>(hci_packet_type_));
+ }
+ }
+ return packet.size();
+}
+
+void H4Protocol::SendDataToPacketizer(uint8_t* buffer, size_t length) {
+ std::vector<uint8_t> input_buffer{buffer, buffer + length};
+ size_t buffer_offset = 0;
+ while (buffer_offset < input_buffer.size()) {
+ if (hci_packet_type_ == PacketType::UNKNOWN) {
+ hci_packet_type_ =
+ static_cast<PacketType>(input_buffer.data()[buffer_offset]);
+ buffer_offset += 1;
+ } else {
+ bool packet_ready = hci_packetizer_.OnDataReady(
+ hci_packet_type_, input_buffer, buffer_offset);
+ if (packet_ready) {
+ // Call packet callback and move offset.
+ buffer_offset += OnPacketReady(hci_packetizer_.GetPacket());
+ // Get ready for the next type byte.
+ hci_packet_type_ = PacketType::UNKNOWN;
+ } else {
+ // The data was consumed, but there wasn't a packet.
+ buffer_offset = input_buffer.size();
+ }
+ }
+ }
+}
+
+void H4Protocol::OnDataReady() {
+ if (disconnected_) {
+ return;
+ }
+ uint8_t buffer[kMaxPacketLength];
+ ssize_t bytes_read =
+ TEMP_FAILURE_RETRY(read(uart_fd_, buffer, kMaxPacketLength));
+ if (bytes_read == 0) {
+ ALOGI("No bytes read, calling the disconnect callback");
+ disconnected_ = true;
+ disconnect_cb_();
+ return;
+ }
+ if (bytes_read < 0) {
+ ALOGW("error reading from UART (%s)", strerror(errno));
+ return;
+ }
+ SendDataToPacketizer(buffer, bytes_read);
+}
+
+} // namespace android::hardware::bluetooth::hci
diff --git a/bluetooth/hci/h4_protocol.h b/bluetooth/hci/h4_protocol.h
new file mode 100644
index 0000000..5daee83
--- /dev/null
+++ b/bluetooth/hci/h4_protocol.h
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include "hci_internals.h"
+#include "hci_packetizer.h"
+
+namespace android::hardware::bluetooth::hci {
+
+using PacketReadCallback = std::function<void(const std::vector<uint8_t>&)>;
+using DisconnectCallback = std::function<void(void)>;
+
+class H4Protocol {
+ public:
+ H4Protocol(int fd, PacketReadCallback cmd_cb, PacketReadCallback acl_cb,
+ PacketReadCallback sco_cb, PacketReadCallback event_cb,
+ PacketReadCallback iso_cb, DisconnectCallback disconnect_cb);
+
+ size_t Send(PacketType type, const uint8_t* data, size_t length);
+ size_t Send(PacketType type, const std::vector<uint8_t>& data);
+
+ void OnDataReady();
+
+ protected:
+ size_t OnPacketReady(const std::vector<uint8_t>& packet);
+ void SendDataToPacketizer(uint8_t* buffer, size_t length);
+
+ private:
+ int uart_fd_;
+ bool disconnected_{false};
+
+ PacketReadCallback cmd_cb_;
+ PacketReadCallback acl_cb_;
+ PacketReadCallback sco_cb_;
+ PacketReadCallback event_cb_;
+ PacketReadCallback iso_cb_;
+ DisconnectCallback disconnect_cb_;
+
+ PacketType hci_packet_type_{PacketType::UNKNOWN};
+ HciPacketizer hci_packetizer_;
+
+ /**
+ * Question : Why read in single chunk rather than multiple reads?
+ * Answer: Using multiple reads does not work with some BT USB dongles.
+ * Reading in single shot gives expected response.
+ * ACL max length is 2 bytes, so using 64K as the buffer length.
+ */
+ static constexpr size_t kMaxPacketLength = 64 * 1024;
+};
+
+} // namespace android::hardware::bluetooth::hci
diff --git a/bluetooth/hci/hci_internals.h b/bluetooth/hci/hci_internals.h
new file mode 100644
index 0000000..71b6191
--- /dev/null
+++ b/bluetooth/hci/hci_internals.h
@@ -0,0 +1,55 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdlib>
+
+namespace android::hardware::bluetooth::hci {
+
+// HCI UART transport packet types (Volume 4, Part A, 2)
+enum class PacketType : uint8_t {
+ UNKNOWN = 0,
+ COMMAND = 1,
+ ACL_DATA = 2,
+ SCO_DATA = 3,
+ EVENT = 4,
+ ISO_DATA = 5,
+};
+
+// 2 bytes for opcode, 1 byte for parameter length (Volume 4, Part E, 5.4.1)
+static constexpr size_t kCommandHeaderSize = 3;
+static constexpr size_t kCommandLengthOffset = 2;
+
+// 2 bytes for handle, 2 bytes for data length (Volume 4, Part E, 5.4.2)
+static constexpr size_t kAclHeaderSize = 4;
+static constexpr size_t kAclLengthOffset = 2;
+
+// 2 bytes for handle, 1 byte for data length (Volume 4, Part E, 5.4.3)
+static constexpr size_t kScoHeaderSize = 3;
+static constexpr size_t kScoLengthOffset = 2;
+
+// 1 byte for event code, 1 byte for parameter length (Volume 4, Part E, 5.4.4)
+static constexpr size_t kEventHeaderSize = 2;
+static constexpr size_t kEventLengthOffset = 1;
+
+// 2 bytes for handle, 2 bytes for data length (Volume 4, Part E, 5.4.5)
+static constexpr size_t kIsoHeaderSize = 4;
+static constexpr size_t kIsoLengthOffset = 2;
+
+static constexpr size_t kMaxHeaderSize = kAclHeaderSize;
+
+} // namespace android::hardware::bluetooth::hci
diff --git a/bluetooth/hci/hci_packetizer.cc b/bluetooth/hci/hci_packetizer.cc
new file mode 100644
index 0000000..5b6c443
--- /dev/null
+++ b/bluetooth/hci/hci_packetizer.cc
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+#include "hci_packetizer.h"
+
+#define LOG_TAG "android.hardware.bluetooth.hci-packetizer"
+#include "log/log.h"
+
+namespace android::hardware::bluetooth::hci {
+
+namespace {
+
+const size_t header_size_for_type[] = {0,
+ kCommandHeaderSize,
+ kAclHeaderSize,
+ kScoHeaderSize,
+ kEventHeaderSize,
+ kIsoHeaderSize};
+const size_t packet_length_offset_for_type[] = {0,
+ kCommandLengthOffset,
+ kAclLengthOffset,
+ kScoLengthOffset,
+ kEventLengthOffset,
+ kIsoLengthOffset};
+
+size_t HciGetPacketLengthForType(PacketType type,
+ const std::vector<uint8_t>& header) {
+ size_t offset = packet_length_offset_for_type[static_cast<uint8_t>(type)];
+ if (type != PacketType::ACL_DATA && type != PacketType::ISO_DATA) {
+ return header[offset];
+ }
+ return (((header[offset + 1]) << 8) | header[offset]);
+}
+
+} // namespace
+
+const std::vector<uint8_t>& HciPacketizer::GetPacket() const { return packet_; }
+
+bool HciPacketizer::OnDataReady(PacketType packet_type,
+ const std::vector<uint8_t>& buffer,
+ size_t offset) {
+ bool packet_completed = false;
+ size_t bytes_available = buffer.size() - offset;
+ switch (state_) {
+ case HCI_HEADER: {
+ size_t header_size =
+ header_size_for_type[static_cast<size_t>(packet_type)];
+ if (bytes_remaining_ == 0) {
+ bytes_remaining_ = header_size;
+ packet_.clear();
+ }
+ size_t bytes_to_copy = std::min(bytes_remaining_, bytes_available);
+ packet_.insert(packet_.end(), buffer.begin() + offset,
+ buffer.begin() + offset + bytes_to_copy);
+ bytes_remaining_ -= bytes_to_copy;
+ bytes_available -= bytes_to_copy;
+ if (bytes_remaining_ == 0) {
+ bytes_remaining_ = HciGetPacketLengthForType(packet_type, packet_);
+ if (bytes_remaining_ > 0) {
+ state_ = HCI_PAYLOAD;
+ if (bytes_available > 0) {
+ packet_completed =
+ OnDataReady(packet_type, buffer, offset + bytes_to_copy);
+ }
+ } else {
+ packet_completed = true;
+ }
+ }
+ break;
+ }
+
+ case HCI_PAYLOAD: {
+ size_t bytes_to_copy = std::min(bytes_remaining_, bytes_available);
+ packet_.insert(packet_.end(), buffer.begin() + offset,
+ buffer.begin() + offset + bytes_to_copy);
+ bytes_remaining_ -= bytes_to_copy;
+ if (bytes_remaining_ == 0) {
+ state_ = HCI_HEADER;
+ packet_completed = true;
+ }
+ break;
+ }
+ }
+ return packet_completed;
+}
+
+} // namespace android::hardware::bluetooth::hci
diff --git a/bluetooth/hci/hci_packetizer.h b/bluetooth/hci/hci_packetizer.h
new file mode 100644
index 0000000..ba3e841
--- /dev/null
+++ b/bluetooth/hci/hci_packetizer.h
@@ -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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <vector>
+
+#include "hci_internals.h"
+
+namespace android::hardware::bluetooth::hci {
+
+class HciPacketizer {
+ public:
+ HciPacketizer() = default;
+ bool OnDataReady(PacketType packet_type, const std::vector<uint8_t>& data,
+ size_t offset);
+ const std::vector<uint8_t>& GetPacket() const;
+
+ protected:
+ enum State { HCI_HEADER, HCI_PAYLOAD };
+ State state_{HCI_HEADER};
+ std::vector<uint8_t> packet_;
+ size_t bytes_remaining_{0};
+};
+
+} // namespace android::hardware::bluetooth::hci
diff --git a/bluetooth/hci/test/h4_protocol_unittest.cc b/bluetooth/hci/test/h4_protocol_unittest.cc
new file mode 100644
index 0000000..d6f74fc
--- /dev/null
+++ b/bluetooth/hci/test/h4_protocol_unittest.cc
@@ -0,0 +1,441 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "bt_h4_unittest"
+
+#include "h4_protocol.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <cstdint>
+#include <cstring>
+#include <future>
+#include <vector>
+
+#include "async_fd_watcher.h"
+#include "log/log.h"
+
+using android::hardware::bluetooth::async::AsyncFdWatcher;
+using namespace android::hardware::bluetooth::hci;
+using ::testing::Eq;
+
+static char sample_data1[100] = "A point is that which has no part.";
+static char sample_data2[100] = "A line is breadthless length.";
+static char sample_data3[100] = "The ends of a line are points.";
+static char sample_data4[100] =
+ "A plane surface is a surface which lies evenly with the straight ...";
+static char acl_data[100] =
+ "A straight line is a line which lies evenly with the points on itself.";
+static char sco_data[100] =
+ "A surface is that which has length and breadth only.";
+static char event_data[100] = "The edges of a surface are lines.";
+static char iso_data[100] =
+ "A plane angle is the inclination to one another of two lines in a ...";
+
+MATCHER_P3(PacketMatches, header_, header_length, payload,
+ "Match header_length bytes of header and then the payload") {
+ size_t payload_length = strlen(payload);
+ if (header_length + payload_length != arg.size()) {
+ return false;
+ }
+
+ if (memcmp(header_, arg.data(), header_length) != 0) {
+ return false;
+ }
+
+ return memcmp(payload, arg.data() + header_length, payload_length) == 0;
+};
+
+ACTION_P(Notify, barrier) {
+ ALOGD("%s", __func__);
+ barrier->set_value();
+}
+
+class H4ProtocolTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ ALOGD("%s", __func__);
+
+ int sockfd[2];
+ socketpair(AF_LOCAL, SOCK_STREAM, 0, sockfd);
+ chip_uart_fd_ = sockfd[1];
+ stack_uart_fd_ = sockfd[0];
+ h4_hci_ = std::make_shared<H4Protocol>(
+ stack_uart_fd_, cmd_cb_.AsStdFunction(), acl_cb_.AsStdFunction(),
+ sco_cb_.AsStdFunction(), event_cb_.AsStdFunction(),
+ iso_cb_.AsStdFunction(), disconnect_cb_.AsStdFunction());
+ }
+
+ void TearDown() override {
+ close(stack_uart_fd_);
+ close(chip_uart_fd_);
+ }
+
+ virtual void CallDataReady() { h4_hci_->OnDataReady(); }
+
+ void SendAndReadUartOutbound(PacketType type, char* data) {
+ ALOGD("%s sending", __func__);
+ int data_length = strlen(data);
+ h4_hci_->Send(type, (uint8_t*)data, data_length);
+
+ int uart_length = data_length + 1; // + 1 for data type code
+ int i;
+
+ ALOGD("%s reading", __func__);
+ for (i = 0; i < uart_length; i++) {
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+ FD_SET(chip_uart_fd_, &read_fds);
+ TEMP_FAILURE_RETRY(
+ select(chip_uart_fd_ + 1, &read_fds, nullptr, nullptr, nullptr));
+
+ char byte;
+ TEMP_FAILURE_RETRY(read(chip_uart_fd_, &byte, 1));
+
+ EXPECT_EQ(i == 0 ? static_cast<uint8_t>(type) : data[i - 1], byte);
+ }
+
+ EXPECT_EQ(i, uart_length);
+ }
+
+ void ExpectInboundAclData(char* payload, std::promise<void>* promise) {
+ // h4 type[1] + handle[2] + size[2]
+ header_[0] = static_cast<uint8_t>(PacketType::ACL_DATA);
+ header_[1] = 19;
+ header_[2] = 92;
+ int length = strlen(payload);
+ header_[3] = length & 0xFF;
+ header_[4] = (length >> 8) & 0xFF;
+ ALOGD("(%d bytes) %s", length, payload);
+
+ EXPECT_CALL(acl_cb_,
+ Call(PacketMatches(header_ + 1, kAclHeaderSize, payload)))
+ .WillOnce(Notify(promise));
+ }
+
+ void WaitForTimeout(size_t timeout_ms, std::promise<void>* promise) {
+ auto future = promise->get_future();
+ auto status = future.wait_for(std::chrono::milliseconds(timeout_ms));
+ EXPECT_EQ(status, std::future_status::ready);
+ }
+
+ void WriteInboundAclData(char* payload) {
+ // Use the header_ computed in ExpectInboundAclData
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kAclHeaderSize + 1));
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
+ }
+
+ void ExpectInboundScoData(char* payload, std::promise<void>* promise) {
+ // h4 type[1] + handle[2] + size[1]
+ header_[0] = static_cast<uint8_t>(PacketType::SCO_DATA);
+ header_[1] = 20;
+ header_[2] = 17;
+ header_[3] = strlen(payload) & 0xFF;
+ EXPECT_CALL(sco_cb_,
+ Call(PacketMatches(header_ + 1, kScoHeaderSize, payload)))
+ .WillOnce(Notify(promise));
+ }
+
+ void WriteInboundScoData(char* payload) {
+ // Use the header_ computed in ExpectInboundScoData
+ ALOGD("%s writing", __func__);
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kScoHeaderSize + 1));
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
+ }
+
+ void ExpectInboundEvent(char* payload, std::promise<void>* promise) {
+ // h4 type[1] + event_code[1] + size[1]
+ header_[0] = static_cast<uint8_t>(PacketType::EVENT);
+ header_[1] = 9;
+ header_[2] = strlen(payload) & 0xFF;
+ EXPECT_CALL(event_cb_,
+ Call(PacketMatches(header_ + 1, kEventHeaderSize, payload)))
+ .WillOnce(Notify(promise));
+ }
+
+ void WriteInboundEvent(char* payload) {
+ // Use the header_ computed in ExpectInboundEvent
+ char preamble[3] = {static_cast<uint8_t>(PacketType::EVENT), 9, 0};
+ preamble[2] = strlen(payload) & 0xFF;
+ ALOGD("%s writing", __func__);
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kEventHeaderSize + 1));
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
+ }
+
+ void ExpectInboundIsoData(char* payload, std::promise<void>* promise) {
+ // h4 type[1] + handle[2] + size[1]
+ header_[0] = static_cast<uint8_t>(PacketType::ISO_DATA);
+ header_[1] = 19;
+ header_[2] = 92;
+ int length = strlen(payload);
+ header_[3] = length & 0xFF;
+ header_[4] = (length >> 8) & 0x3F;
+
+ EXPECT_CALL(iso_cb_,
+ Call(PacketMatches(header_ + 1, kIsoHeaderSize, payload)))
+ .WillOnce(Notify(promise));
+ }
+
+ void WriteInboundIsoData(char* payload) {
+ // Use the header_ computed in ExpectInboundIsoData
+ ALOGD("%s writing", __func__);
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kIsoHeaderSize + 1));
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
+ }
+
+ void WriteAndExpectManyInboundAclDataPackets(char* payload) {
+ size_t kNumPackets = 20;
+ // h4 type[1] + handle[2] + size[2]
+ char preamble[5] = {static_cast<uint8_t>(PacketType::ACL_DATA), 19, 92, 0,
+ 0};
+ int length = strlen(payload);
+ preamble[3] = length & 0xFF;
+ preamble[4] = (length >> 8) & 0xFF;
+
+ EXPECT_CALL(acl_cb_, Call(PacketMatches(preamble + 1, sizeof(preamble) - 1,
+ payload)))
+ .Times(kNumPackets);
+
+ for (size_t i = 0; i < kNumPackets; i++) {
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, preamble, sizeof(preamble)));
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
+ }
+
+ CallDataReady();
+ }
+
+ testing::MockFunction<void(const std::vector<uint8_t>&)> cmd_cb_;
+ testing::MockFunction<void(const std::vector<uint8_t>&)> event_cb_;
+ testing::MockFunction<void(const std::vector<uint8_t>&)> acl_cb_;
+ testing::MockFunction<void(const std::vector<uint8_t>&)> sco_cb_;
+ testing::MockFunction<void(const std::vector<uint8_t>&)> iso_cb_;
+ testing::MockFunction<void(void)> disconnect_cb_;
+ std::shared_ptr<H4Protocol> h4_hci_;
+ int chip_uart_fd_;
+ int stack_uart_fd_;
+
+ char header_[5];
+};
+
+// Test sending data sends correct data onto the UART
+TEST_F(H4ProtocolTest, TestSends) {
+ SendAndReadUartOutbound(PacketType::COMMAND, sample_data1);
+ SendAndReadUartOutbound(PacketType::ACL_DATA, sample_data2);
+ SendAndReadUartOutbound(PacketType::SCO_DATA, sample_data3);
+ SendAndReadUartOutbound(PacketType::ISO_DATA, sample_data4);
+}
+
+// Ensure we properly parse data coming from the UART
+TEST_F(H4ProtocolTest, TestReads) {
+ std::promise<void> acl_promise;
+ std::promise<void> sco_promise;
+ std::promise<void> event_promise;
+ std::promise<void> iso_promise;
+
+ ExpectInboundAclData(acl_data, &acl_promise);
+ WriteInboundAclData(acl_data);
+ CallDataReady();
+ ExpectInboundScoData(sco_data, &sco_promise);
+ WriteInboundScoData(sco_data);
+ CallDataReady();
+ ExpectInboundEvent(event_data, &event_promise);
+ WriteInboundEvent(event_data);
+ CallDataReady();
+ ExpectInboundIsoData(iso_data, &iso_promise);
+ WriteInboundIsoData(iso_data);
+ CallDataReady();
+
+ WaitForTimeout(100, &acl_promise);
+ WaitForTimeout(100, &sco_promise);
+ WaitForTimeout(100, &event_promise);
+ WaitForTimeout(100, &iso_promise);
+}
+
+TEST_F(H4ProtocolTest, TestMultiplePackets) {
+ WriteAndExpectManyInboundAclDataPackets(sco_data);
+}
+
+TEST_F(H4ProtocolTest, TestDisconnect) {
+ EXPECT_CALL(disconnect_cb_, Call());
+ close(chip_uart_fd_);
+ CallDataReady();
+}
+
+TEST_F(H4ProtocolTest, TestPartialWrites) {
+ size_t payload_len = strlen(acl_data);
+ const size_t kNumIntervals = payload_len + 1;
+ // h4 type[1] + handle[2] + size[2]
+ header_[0] = static_cast<uint8_t>(PacketType::ACL_DATA);
+ header_[1] = 19;
+ header_[2] = 92;
+ header_[3] = payload_len & 0xFF;
+ header_[4] = (payload_len >> 8) & 0xFF;
+
+ EXPECT_CALL(acl_cb_,
+ Call(PacketMatches(header_ + 1, sizeof(header_) - 1, acl_data)))
+ .Times(kNumIntervals);
+
+ for (size_t interval = 1; interval < kNumIntervals + 1; interval++) {
+ // Use the header_ data that expect already set up.
+ if (interval < kAclHeaderSize) {
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, interval));
+ CallDataReady();
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_ + interval,
+ kAclHeaderSize + 1 - interval));
+ CallDataReady();
+ } else {
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, header_, kAclHeaderSize + 1));
+ CallDataReady();
+ }
+
+ for (size_t bytes = 0; bytes + interval <= payload_len; bytes += interval) {
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, acl_data + bytes, interval));
+ CallDataReady();
+ }
+ size_t extra_bytes = payload_len % interval;
+ if (extra_bytes) {
+ TEMP_FAILURE_RETRY(write(
+ chip_uart_fd_, acl_data + payload_len - extra_bytes, extra_bytes));
+ CallDataReady();
+ }
+ }
+}
+
+class H4ProtocolAsyncTest : public H4ProtocolTest {
+ protected:
+ void SetUp() override {
+ H4ProtocolTest::SetUp();
+ fd_watcher_.WatchFdForNonBlockingReads(
+ stack_uart_fd_, [this](int) { h4_hci_->OnDataReady(); });
+ }
+
+ void TearDown() override { fd_watcher_.StopWatchingFileDescriptors(); }
+
+ void CallDataReady() override {
+ // The Async test can't call data ready.
+ FAIL();
+ }
+
+ void SendAndReadUartOutbound(PacketType type, char* data) {
+ ALOGD("%s sending", __func__);
+ int data_length = strlen(data);
+ h4_hci_->Send(type, (uint8_t*)data, data_length);
+
+ int uart_length = data_length + 1; // + 1 for data type code
+ int i;
+
+ ALOGD("%s reading", __func__);
+ for (i = 0; i < uart_length; i++) {
+ fd_set read_fds;
+ FD_ZERO(&read_fds);
+ FD_SET(chip_uart_fd_, &read_fds);
+ TEMP_FAILURE_RETRY(
+ select(chip_uart_fd_ + 1, &read_fds, nullptr, nullptr, nullptr));
+
+ char byte;
+ TEMP_FAILURE_RETRY(read(chip_uart_fd_, &byte, 1));
+
+ EXPECT_EQ(i == 0 ? static_cast<uint8_t>(type) : data[i - 1], byte);
+ }
+
+ EXPECT_EQ(i, uart_length);
+ }
+
+ void WriteAndExpectInboundAclData(char* payload) {
+ std::promise<void> promise;
+ ExpectInboundAclData(payload, &promise);
+ WriteInboundAclData(payload);
+ WaitForTimeout(100, &promise);
+ }
+
+ void WriteAndExpectInboundScoData(char* payload) {
+ std::promise<void> promise;
+ ExpectInboundScoData(payload, &promise);
+ WriteInboundScoData(payload);
+ WaitForTimeout(100, &promise);
+ }
+
+ void WriteAndExpectInboundEvent(char* payload) {
+ std::promise<void> promise;
+ ExpectInboundEvent(payload, &promise);
+ WriteInboundEvent(payload);
+ WaitForTimeout(100, &promise);
+ }
+
+ void WriteAndExpectInboundIsoData(char* payload) {
+ std::promise<void> promise;
+ ExpectInboundIsoData(payload, &promise);
+ WriteInboundIsoData(payload);
+ WaitForTimeout(100, &promise);
+ }
+
+ void WriteAndExpectManyInboundAclDataPackets(char* payload) {
+ const size_t kNumPackets = 20;
+ // h4 type[1] + handle[2] + size[2]
+ char preamble[5] = {static_cast<uint8_t>(PacketType::ACL_DATA), 19, 92, 0,
+ 0};
+ int length = strlen(payload);
+ preamble[3] = length & 0xFF;
+ preamble[4] = (length >> 8) & 0xFF;
+
+ EXPECT_CALL(acl_cb_, Call(PacketMatches(preamble + 1, sizeof(preamble) - 1,
+ payload)))
+ .Times(kNumPackets);
+
+ for (size_t i = 0; i < kNumPackets; i++) {
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, preamble, sizeof(preamble)));
+ TEMP_FAILURE_RETRY(write(chip_uart_fd_, payload, strlen(payload)));
+ }
+
+ WriteAndExpectInboundEvent(event_data);
+ }
+
+ AsyncFdWatcher fd_watcher_;
+};
+
+// Test sending data sends correct data onto the UART
+TEST_F(H4ProtocolAsyncTest, TestSends) {
+ SendAndReadUartOutbound(PacketType::COMMAND, sample_data1);
+ SendAndReadUartOutbound(PacketType::ACL_DATA, sample_data2);
+ SendAndReadUartOutbound(PacketType::SCO_DATA, sample_data3);
+ SendAndReadUartOutbound(PacketType::ISO_DATA, sample_data4);
+}
+
+// Ensure we properly parse data coming from the UART
+TEST_F(H4ProtocolAsyncTest, TestReads) {
+ WriteAndExpectInboundAclData(acl_data);
+ WriteAndExpectInboundScoData(sco_data);
+ WriteAndExpectInboundEvent(event_data);
+ WriteAndExpectInboundIsoData(iso_data);
+}
+
+TEST_F(H4ProtocolAsyncTest, TestMultiplePackets) {
+ WriteAndExpectManyInboundAclDataPackets(sco_data);
+}
+
+TEST_F(H4ProtocolAsyncTest, TestDisconnect) {
+ std::promise<void> promise;
+ EXPECT_CALL(disconnect_cb_, Call()).WillOnce(Notify(&promise));
+ close(chip_uart_fd_);
+
+ // Fail if it takes longer than 100 ms.
+ WaitForTimeout(100, &promise);
+}
diff --git a/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp b/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
index ab3c789..93c8376 100644
--- a/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
+++ b/boot/aidl/vts/functional/VtsHalBootAidlTargetTest.cpp
@@ -33,7 +33,7 @@
using std::unordered_set;
// The main test class for the Boot HIDL HAL.
-class BootHidlTest : public ::testing::TestWithParam<std::string> {
+class BootAidlTest : public ::testing::TestWithParam<std::string> {
public:
virtual void SetUp() override {
const auto instance_name = GetParam();
@@ -48,14 +48,14 @@
};
// validity check Boot::getNumberSlots().
-TEST_P(BootHidlTest, GetNumberSlots) {
+TEST_P(BootAidlTest, GetNumberSlots) {
int32_t slots{};
boot->getNumberSlots(&slots);
ASSERT_LE(2, slots);
}
// validity check Boot::getCurrentSlot().
-TEST_P(BootHidlTest, GetCurrentSlot) {
+TEST_P(BootAidlTest, GetCurrentSlot) {
int curSlot = -1;
boot->getCurrentSlot(&curSlot);
int slots = 0;
@@ -64,7 +64,7 @@
}
// validity check Boot::markBootSuccessful().
-TEST_P(BootHidlTest, MarkBootSuccessful) {
+TEST_P(BootAidlTest, MarkBootSuccessful) {
const auto result = boot->markBootSuccessful();
ASSERT_TRUE(result.isOk());
int curSlot = 0;
@@ -74,7 +74,7 @@
ASSERT_TRUE(ret);
}
-TEST_P(BootHidlTest, SetActiveBootSlot) {
+TEST_P(BootAidlTest, SetActiveBootSlot) {
int curSlot = -1;
boot->getCurrentSlot(&curSlot);
ASSERT_GE(curSlot, 0);
@@ -107,7 +107,7 @@
}
}
-TEST_P(BootHidlTest, SetSlotAsUnbootable) {
+TEST_P(BootAidlTest, SetSlotAsUnbootable) {
int curSlot = -1;
boot->getCurrentSlot(&curSlot);
ASSERT_GE(curSlot, 0);
@@ -139,7 +139,7 @@
}
// validity check Boot::isSlotBootable() on good and bad inputs.
-TEST_P(BootHidlTest, IsSlotBootable) {
+TEST_P(BootAidlTest, IsSlotBootable) {
for (int s = 0; s < 2; s++) {
bool bootable = false;
const auto res = boot->isSlotBootable(s, &bootable);
@@ -153,7 +153,7 @@
}
// validity check Boot::isSlotMarkedSuccessful() on good and bad inputs.
-TEST_P(BootHidlTest, IsSlotMarkedSuccessful) {
+TEST_P(BootAidlTest, IsSlotMarkedSuccessful) {
for (int32_t s = 0; s < 2; s++) {
bool isSuccess = false;
const auto res = boot->isSlotMarkedSuccessful(s, &isSuccess);
@@ -166,7 +166,7 @@
}
// validity check Boot::getSuffix() on good and bad inputs.
-TEST_P(BootHidlTest, GetSuffix) {
+TEST_P(BootAidlTest, GetSuffix) {
string suffixStr;
unordered_set<string> suffixes;
int numSlots = 0;
@@ -190,5 +190,6 @@
}
INSTANTIATE_TEST_SUITE_P(
- PerInstance, BootHidlTest,
+ PerInstance, BootAidlTest,
testing::ValuesIn(android::getAidlHalInstanceNames(IBootControl::descriptor)));
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BootAidlTest);
diff --git a/camera/README.md b/camera/README.md
index 8ce3352..25badfd 100644
--- a/camera/README.md
+++ b/camera/README.md
@@ -10,3 +10,8 @@
More complete information about the Android camera HAL and subsystem can be found at
[source.android.com](http://source.android.com/devices/camera/index.html).
+
+### AIDL Camera HAL Interfaces
+
+The AIDL Camera HAL interfaces can be found in the respective <interface>/aidl
+directories.
diff --git a/camera/device/aidl/Android.bp b/camera/device/aidl/Android.bp
index 365a5ff..c184677 100644
--- a/camera/device/aidl/Android.bp
+++ b/camera/device/aidl/Android.bp
@@ -15,9 +15,9 @@
imports: [
"android.hardware.common-V2",
"android.hardware.common.fmq-V1",
- "android.hardware.camera.common",
- "android.hardware.camera.metadata",
- "android.hardware.graphics.common",
+ "android.hardware.camera.common-V1",
+ "android.hardware.camera.metadata-V2",
+ "android.hardware.graphics.common-V4",
],
backend: {
cpp: {
@@ -36,7 +36,7 @@
"android.hardware.common.fmq-V1",
"android.hardware.camera.common-V1",
"android.hardware.camera.metadata-V1",
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
],
},
],
diff --git a/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/Stream.aidl b/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/Stream.aidl
index d2f295a..5057663 100644
--- a/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/Stream.aidl
+++ b/camera/device/aidl/aidl_api/android.hardware.camera.device/current/android/hardware/camera/device/Stream.aidl
@@ -48,4 +48,5 @@
android.hardware.camera.metadata.SensorPixelMode[] sensorPixelModesUsed;
android.hardware.camera.metadata.RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile;
android.hardware.camera.metadata.ScalerAvailableStreamUseCases useCase;
+ int colorSpace;
}
diff --git a/camera/device/aidl/android/hardware/camera/device/Stream.aidl b/camera/device/aidl/android/hardware/camera/device/Stream.aidl
index e35e4ff..457b1bc 100644
--- a/camera/device/aidl/android/hardware/camera/device/Stream.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/Stream.aidl
@@ -98,14 +98,18 @@
*
* For most formats, dataSpace defines the color space of the image data.
* In addition, for some formats, dataSpace indicates whether image- or
- * depth-based data is requested. See
- * android.hardware.graphics.common@1.0::types for details of formats and
- * valid dataSpace values for each format.
+ * depth-based data is requested. For others, it merely describes an encoding
+ * scheme. See android.hardware.graphics.common@1.0::types for details of formats
+ * and valid dataSpace values for each format.
*
* The HAL must use this dataSpace to configure the stream to the correct
* colorspace, or to select between color and depth outputs if
* supported. The dataspace values are set using the V0 dataspace
* definitions.
+ *
+ * The color space implied by dataSpace should be overridden by colorSpace if
+ * the device supports the REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES
+ * capability.
*/
android.hardware.graphics.common.Dataspace dataSpace;
@@ -222,4 +226,19 @@
* DEFAULT.
*/
android.hardware.camera.metadata.ScalerAvailableStreamUseCases useCase;
+
+ /**
+ * The color space of the stream.
+ *
+ * A client may not specify a color space. In this case, the value will be
+ * ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED, and the color space
+ * implied by dataSpace should be used instead.
+ *
+ * When specified, this field is the ultimate authority over the color space of the stream,
+ * regardless of dataSpace. The purpose of this field is to support specifying wide gamut
+ * color spaces for dataSpace values such as JFIF and HEIF.
+ *
+ * Possible values are the ordinals of the ColorSpace.Named enum in the public-facing API.
+ */
+ int colorSpace;
}
diff --git a/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl b/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl
index e487494..29fec68 100644
--- a/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl
+++ b/camera/device/aidl/android/hardware/camera/device/StreamBuffer.aidl
@@ -33,8 +33,8 @@
parcelable StreamBuffer {
/**
* The ID of the stream this buffer is associated with. -1 indicates an
- * invalid (empty) StreamBuffer, in which case buffer must also point to
- * null and bufferId must be 0.
+ * invalid (empty) StreamBuffer, in which case buffer must be empty
+ * and bufferId must be 0.
*/
int streamId;
@@ -48,7 +48,7 @@
* corresponding stream is removed from stream configuration or until camera
* device session is closed. After the first time a buffer is introduced to
* HAL, in the future camera service must refer to the same buffer using
- * only bufferId, and keep the buffer handle null.
+ * only bufferId, and keep the buffer handle empty.
*/
long bufferId;
@@ -59,10 +59,10 @@
* is not seen by the HAL before, this buffer handle is guaranteed to be a
* valid handle to a graphics buffer, with dimensions and format matching
* that of the stream. If the bufferId has been sent to the HAL before, this
- * buffer handle must be null and HAL must look up the actual buffer handle
+ * buffer handle must be empty and HAL must look up the actual buffer handle
* to use from its own bufferId to buffer handle map.
*
- * For StreamBuffers returned in a CaptureResult, this must be null, since
+ * For StreamBuffers returned in a CaptureResult, this must be empty, since
* the handle to the buffer is already known to the client (since the client
* sent it in the matching CaptureRequest), and the handle can be identified
* by the combination of frame number and stream ID.
@@ -81,11 +81,11 @@
* The acquire sync fence for this buffer. The HAL must wait on this fence
* fd before attempting to read from or write to this buffer.
*
- * In a buffer included in a CaptureRequest, the client may set this to null
+ * In a buffer included in a CaptureRequest, the client may leave this empty
* to indicate that no waiting is necessary for this buffer.
*
* When the HAL returns an input or output buffer to the framework with
- * processCaptureResult(), the acquireFence must be set to null. If the HAL
+ * processCaptureResult(), the acquireFence must be empty. If the HAL
* never waits on the acquireFence due to an error in filling or reading a
* buffer, when calling processCaptureResult() the HAL must set the
* releaseFence of the buffer to be the acquireFence passed to it by the
@@ -97,17 +97,17 @@
/**
* The release sync fence for this buffer. The HAL must set this to a valid
* fence fd when returning the input buffer or output buffers to the client
- * in a CaptureResult, or set it to null to indicate that no waiting is
+ * in a CaptureResult, or leave it empty to indicate that no waiting is
* required for this buffer.
*
- * The client must set this to be null for all buffers included in a
+ * The client must leave this empty for all buffers included in a
* processCaptureRequest call.
*
* After signaling the releaseFence for this buffer, the HAL
* must not make any further attempts to access this buffer as the
* ownership has been fully transferred back to the client.
*
- * If this is null, then the ownership of this buffer is transferred back
+ * If this is empty, then the ownership of the buffer is transferred back
* immediately upon the call of processCaptureResult.
*/
NativeHandle releaseFence;
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl
index 9bb55d2..ecbfc93 100644
--- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/CameraMetadataTag.aidl
@@ -92,6 +92,12 @@
ANDROID_CONTROL_ZOOM_RATIO_RANGE = 65582,
ANDROID_CONTROL_ZOOM_RATIO = 65583,
ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION = 65584,
+ ANDROID_CONTROL_SETTINGS_OVERRIDE = 65588,
+ ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES = 65589,
+ ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER = 65590,
+ ANDROID_CONTROL_AUTOFRAMING = 65591,
+ ANDROID_CONTROL_AUTOFRAMING_AVAILABLE = 65592,
+ ANDROID_CONTROL_AUTOFRAMING_STATE = 65593,
ANDROID_DEMOSAIC_MODE = 131072,
ANDROID_EDGE_MODE = 196608,
ANDROID_EDGE_STRENGTH = 196609,
@@ -171,6 +177,7 @@
ANDROID_REQUEST_CHARACTERISTIC_KEYS_NEEDING_PERMISSION = 786450,
ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP = 786451,
ANDROID_REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE = 786452,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP = 786453,
ANDROID_SCALER_CROP_REGION = 851968,
ANDROID_SCALER_AVAILABLE_FORMATS = 851969,
ANDROID_SCALER_AVAILABLE_JPEG_MIN_DURATIONS = 851970,
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAutoframing.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAutoframing.aidl
new file mode 100644
index 0000000..eeb7bcd
--- /dev/null
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAutoframing.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *//*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.camera.metadata;
+@Backing(type="int") @VintfStability
+enum ControlAutoframing {
+ ANDROID_CONTROL_AUTOFRAMING_OFF = 0,
+ ANDROID_CONTROL_AUTOFRAMING_ON = 1,
+ ANDROID_CONTROL_AUTOFRAMING_AUTO = 2,
+}
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAutoframingAvailable.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAutoframingAvailable.aidl
new file mode 100644
index 0000000..b075c32
--- /dev/null
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAutoframingAvailable.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ *//*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.camera.metadata;
+@Backing(type="int") @VintfStability
+enum ControlAutoframingAvailable {
+ ANDROID_CONTROL_AUTOFRAMING_AVAILABLE_FALSE = 0,
+ ANDROID_CONTROL_AUTOFRAMING_AVAILABLE_TRUE = 1,
+}
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAutoframingState.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAutoframingState.aidl
new file mode 100644
index 0000000..60df0d4
--- /dev/null
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlAutoframingState.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *//*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.camera.metadata;
+@Backing(type="int") @VintfStability
+enum ControlAutoframingState {
+ ANDROID_CONTROL_AUTOFRAMING_STATE_INACTIVE = 0,
+ ANDROID_CONTROL_AUTOFRAMING_STATE_FRAMING = 1,
+ ANDROID_CONTROL_AUTOFRAMING_STATE_CONVERGED = 2,
+}
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlSettingsOverride.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlSettingsOverride.aidl
new file mode 100644
index 0000000..ed5d46f
--- /dev/null
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/ControlSettingsOverride.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *//*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.camera.metadata;
+@Backing(type="int") @VintfStability
+enum ControlSettingsOverride {
+ ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF = 0,
+ ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM = 1,
+ ANDROID_CONTROL_SETTINGS_OVERRIDE_VENDOR_START = 16384,
+}
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/RequestAvailableCapabilities.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/RequestAvailableCapabilities.aidl
index 8dc2aa2..37b1dec 100644
--- a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/RequestAvailableCapabilities.aidl
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/RequestAvailableCapabilities.aidl
@@ -58,4 +58,5 @@
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING = 17,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT = 18,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE = 19,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES = 20,
}
diff --git a/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/RequestAvailableColorSpaceProfilesMap.aidl b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/RequestAvailableColorSpaceProfilesMap.aidl
new file mode 100644
index 0000000..0d59ab0
--- /dev/null
+++ b/camera/metadata/aidl/aidl_api/android.hardware.camera.metadata/current/android/hardware/camera/metadata/RequestAvailableColorSpaceProfilesMap.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ *//*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.camera.metadata;
+@Backing(type="long") @VintfStability
+enum RequestAvailableColorSpaceProfilesMap {
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED = -1,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB = 0,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_SRGB = 1,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_EXTENDED_SRGB = 2,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_EXTENDED_SRGB = 3,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT709 = 4,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020 = 5,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DCI_P3 = 6,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3 = 7,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_NTSC_1953 = 8,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SMPTE_C = 9,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ADOBE_RGB = 10,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_PRO_PHOTO_RGB = 11,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACES = 12,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACESCG = 13,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_XYZ = 14,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_LAB = 15,
+}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
index 48b1ee4..2e9bde9 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/CameraMetadataTag.aidl
@@ -450,6 +450,46 @@
*/
ANDROID_CONTROL_AVAILABLE_HIGH_SPEED_VIDEO_CONFIGURATIONS_MAXIMUM_RESOLUTION,
/**
+ * android.control.settingsOverride [dynamic, enum, public]
+ *
+ * <p>The desired CaptureRequest settings override with which certain keys are
+ * applied earlier so that they can take effect sooner.</p>
+ */
+ ANDROID_CONTROL_SETTINGS_OVERRIDE = 65588,
+ /**
+ * android.control.availableSettingsOverrides [static, int32[], public]
+ *
+ * <p>List of available settings overrides supported by the camera device that can
+ * be used to speed up certain controls.</p>
+ */
+ ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES,
+ /**
+ * android.control.settingsOverridingFrameNumber [dynamic, int32, system]
+ *
+ * <p>The frame number of the newer request overriding this capture.</p>
+ */
+ ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER,
+ /**
+ * android.control.autoframing [dynamic, enum, public]
+ *
+ * <p>Automatic crop, pan and zoom to keep objects in the center of the frame.</p>
+ */
+ ANDROID_CONTROL_AUTOFRAMING,
+ /**
+ * android.control.autoframingAvailable [static, enum, public]
+ *
+ * <p>Whether the camera device supports ANDROID_CONTROL_AUTOFRAMING.</p>
+ *
+ * @see ANDROID_CONTROL_AUTOFRAMING
+ */
+ ANDROID_CONTROL_AUTOFRAMING_AVAILABLE,
+ /**
+ * android.control.autoframingState [dynamic, enum, public]
+ *
+ * <p>Current state of auto-framing.</p>
+ */
+ ANDROID_CONTROL_AUTOFRAMING_STATE,
+ /**
* android.demosaic.mode [controls, enum, system]
*
* <p>Controls the quality of the demosaicing
@@ -1030,6 +1070,12 @@
*/
ANDROID_REQUEST_RECOMMENDED_TEN_BIT_DYNAMIC_RANGE_PROFILE,
/**
+ * android.request.availableColorSpaceProfilesMap [static, enum[], ndk_public]
+ *
+ * <p>A list of all possible color space profiles supported by a camera device.</p>
+ */
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP,
+ /**
* android.scaler.cropRegion [dynamic, int32[], public]
*
* <p>The desired region of the sensor to read out for this capture.</p>
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/ControlAutoframing.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/ControlAutoframing.aidl
new file mode 100644
index 0000000..0fef373
--- /dev/null
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/ControlAutoframing.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata;
+
+/**
+ * android.control.autoframing enumeration values
+ * @see ANDROID_CONTROL_AUTOFRAMING
+ */
+@VintfStability
+@Backing(type="int")
+enum ControlAutoframing {
+ ANDROID_CONTROL_AUTOFRAMING_OFF,
+ ANDROID_CONTROL_AUTOFRAMING_ON,
+ ANDROID_CONTROL_AUTOFRAMING_AUTO,
+}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/ControlAutoframingAvailable.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/ControlAutoframingAvailable.aidl
new file mode 100644
index 0000000..da0d348
--- /dev/null
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/ControlAutoframingAvailable.aidl
@@ -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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata;
+
+/**
+ * android.control.autoframingAvailable enumeration values
+ * @see ANDROID_CONTROL_AUTOFRAMING_AVAILABLE
+ */
+@VintfStability
+@Backing(type="int")
+enum ControlAutoframingAvailable {
+ ANDROID_CONTROL_AUTOFRAMING_AVAILABLE_FALSE,
+ ANDROID_CONTROL_AUTOFRAMING_AVAILABLE_TRUE,
+}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/ControlAutoframingState.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/ControlAutoframingState.aidl
new file mode 100644
index 0000000..13183a5
--- /dev/null
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/ControlAutoframingState.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata;
+
+/**
+ * android.control.autoframingState enumeration values
+ * @see ANDROID_CONTROL_AUTOFRAMING_STATE
+ */
+@VintfStability
+@Backing(type="int")
+enum ControlAutoframingState {
+ ANDROID_CONTROL_AUTOFRAMING_STATE_INACTIVE,
+ ANDROID_CONTROL_AUTOFRAMING_STATE_FRAMING,
+ ANDROID_CONTROL_AUTOFRAMING_STATE_CONVERGED,
+}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/ControlSettingsOverride.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/ControlSettingsOverride.aidl
new file mode 100644
index 0000000..d97f7c8
--- /dev/null
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/ControlSettingsOverride.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata;
+
+/**
+ * android.control.settingsOverride enumeration values
+ * @see ANDROID_CONTROL_SETTINGS_OVERRIDE
+ */
+@VintfStability
+@Backing(type="int")
+enum ControlSettingsOverride {
+ ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF,
+ ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM,
+ ANDROID_CONTROL_SETTINGS_OVERRIDE_VENDOR_START = 0x4000,
+}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/RequestAvailableCapabilities.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/RequestAvailableCapabilities.aidl
index f5c77eb..ebe0b4c 100644
--- a/camera/metadata/aidl/android/hardware/camera/metadata/RequestAvailableCapabilities.aidl
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/RequestAvailableCapabilities.aidl
@@ -49,4 +49,5 @@
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_REMOSAIC_REPROCESSING,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_DYNAMIC_RANGE_TEN_BIT,
ANDROID_REQUEST_AVAILABLE_CAPABILITIES_STREAM_USE_CASE,
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES,
}
diff --git a/camera/metadata/aidl/android/hardware/camera/metadata/RequestAvailableColorSpaceProfilesMap.aidl b/camera/metadata/aidl/android/hardware/camera/metadata/RequestAvailableColorSpaceProfilesMap.aidl
new file mode 100644
index 0000000..1423305
--- /dev/null
+++ b/camera/metadata/aidl/android/hardware/camera/metadata/RequestAvailableColorSpaceProfilesMap.aidl
@@ -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.
+ */
+
+/*
+ * Autogenerated from camera metadata definitions in
+ * /system/media/camera/docs/metadata_definitions.xml
+ * *** DO NOT EDIT BY HAND ***
+ */
+
+package android.hardware.camera.metadata;
+
+/**
+ * android.request.availableColorSpaceProfilesMap enumeration values
+ * @see ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP
+ */
+@VintfStability
+@Backing(type="long")
+enum RequestAvailableColorSpaceProfilesMap {
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED = -1L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SRGB = 0L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_SRGB = 1L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_EXTENDED_SRGB = 2L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_LINEAR_EXTENDED_SRGB = 3L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT709 = 4L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_BT2020 = 5L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DCI_P3 = 6L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_DISPLAY_P3 = 7L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_NTSC_1953 = 8L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_SMPTE_C = 9L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ADOBE_RGB = 10L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_PRO_PHOTO_RGB = 11L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACES = 12L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_ACESCG = 13L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_XYZ = 14L,
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_CIE_LAB = 15L,
+}
diff --git a/camera/provider/README.md b/camera/provider/README.md
index 0718fb1..7666a58 100644
--- a/camera/provider/README.md
+++ b/camera/provider/README.md
@@ -35,3 +35,9 @@
First HIDL version of the camara provider HAL callback interface, closely
matching the feature set and operation of the pre-HIDL camera HAL module
callbacks v2.4.
+
+### AIDL Camera HAL Default Implementation ###
+
+The default implementation can be found at
+$ANDROID_BUILD_TOP/hardware/google/camera/common/hal/aidl_service and
+$ANDROID_BUILD_TOP/hardware/google/camera/devices/EmulatedCamera
diff --git a/camera/provider/aidl/Android.bp b/camera/provider/aidl/Android.bp
index 87a94b2..d7e613e 100644
--- a/camera/provider/aidl/Android.bp
+++ b/camera/provider/aidl/Android.bp
@@ -14,9 +14,10 @@
"android/hardware/camera/provider/*.aidl",
],
imports: [
- "android.hardware.camera.device",
- "android.hardware.camera.common",
+ "android.hardware.camera.device-V2",
+ "android.hardware.camera.common-V1",
],
+ frozen: false,
stability: "vintf",
backend: {
java: {
diff --git a/camera/provider/aidl/vts/Android.bp b/camera/provider/aidl/vts/Android.bp
index 32da2fe..8429b21 100644
--- a/camera/provider/aidl/vts/Android.bp
+++ b/camera/provider/aidl/vts/Android.bp
@@ -59,9 +59,9 @@
static_libs: [
"android.hardware.camera.common@1.0-helper",
"android.hardware.camera.common-V1-ndk",
- "android.hardware.camera.device-V1-ndk",
- "android.hardware.camera.metadata-V1-ndk",
- "android.hardware.camera.provider-V1-ndk",
+ "android.hardware.camera.device-V2-ndk",
+ "android.hardware.camera.metadata-V2-ndk",
+ "android.hardware.camera.provider-V2-ndk",
"android.hidl.allocator@1.0",
"libgrallocusage",
"libhidlmemory",
diff --git a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
index 3fef089..747ea33 100644
--- a/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
+++ b/camera/provider/aidl/vts/VtsAidlHalCameraProvider_TargetTest.cpp
@@ -36,6 +36,7 @@
using ::aidl::android::hardware::camera::common::TorchModeStatus;
using ::aidl::android::hardware::camera::common::VendorTagSection;
using ::aidl::android::hardware::camera::device::ICameraDevice;
+using ::aidl::android::hardware::camera::metadata::RequestAvailableColorSpaceProfilesMap;
using ::aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
using ::aidl::android::hardware::camera::metadata::SensorPixelMode;
using ::aidl::android::hardware::camera::provider::CameraIdAndStreamCombination;
@@ -386,22 +387,6 @@
mTorchStatus = TorchModeStatus::NOT_AVAILABLE;
}
- // register a new callback; make sure it receives the
- // flash-on callback.
- std::shared_ptr<TorchProviderCb> cb2 = ndk::SharedRefBase::make<TorchProviderCb>(this);
- ret = mProvider->setCallback(cb2);
- ASSERT_TRUE(ret.isOk());
- ASSERT_NE(cb2, nullptr);
- {
- std::unique_lock<std::mutex> l(mTorchLock);
- while (TorchModeStatus::NOT_AVAILABLE == mTorchStatus) {
- auto timeout = std::chrono::system_clock::now() +
- std::chrono::seconds(kTorchTimeoutSec);
- ASSERT_NE(std::cv_status::timeout, mTorchCond.wait_until(l, timeout));
- }
- ASSERT_EQ(TorchModeStatus::AVAILABLE_ON, mTorchStatus);
- }
-
ret = device->setTorchMode(false);
ASSERT_TRUE(ret.isOk());
{
@@ -2037,6 +2022,71 @@
}
}
+TEST_P(CameraAidlTest, process8BitColorSpaceRequests) {
+ static int profiles[] = {
+ ColorSpaceNamed::BT709,
+ ColorSpaceNamed::DCI_P3,
+ ColorSpaceNamed::DISPLAY_P3,
+ ColorSpaceNamed::EXTENDED_SRGB,
+ ColorSpaceNamed::LINEAR_EXTENDED_SRGB,
+ ColorSpaceNamed::NTSC_1953,
+ ColorSpaceNamed::SMPTE_C,
+ ColorSpaceNamed::SRGB
+ };
+
+ for (int32_t i = 0; i < sizeof(profiles) / sizeof(profiles[0]); i++) {
+ processColorSpaceRequest(static_cast<RequestAvailableColorSpaceProfilesMap>(profiles[i]),
+ static_cast<RequestAvailableDynamicRangeProfilesMap>(
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD));
+ }
+}
+
+TEST_P(CameraAidlTest, process10BitColorSpaceRequests) {
+ static const camera_metadata_enum_android_request_available_dynamic_range_profiles_map
+ dynamicRangeProfiles[] = {
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM,
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO
+ };
+
+ // Process all dynamic range profiles with BT2020
+ for (int32_t i = 0; i < sizeof(dynamicRangeProfiles) / sizeof(dynamicRangeProfiles[0]); i++) {
+ processColorSpaceRequest(
+ static_cast<RequestAvailableColorSpaceProfilesMap>(ColorSpaceNamed::BT2020),
+ static_cast<RequestAvailableDynamicRangeProfilesMap>(dynamicRangeProfiles[i]));
+ }
+}
+
+TEST_P(CameraAidlTest, processZoomSettingsOverrideRequests) {
+ const int32_t kFrameCount = 5;
+ const int32_t kTestCases = 2;
+ const bool kOverrideSequence[kTestCases][kFrameCount] = {
+ // ZOOM, ZOOM, ZOOM, ZOOM, ZOOM;
+ { true, true, true, true, true },
+ // OFF, OFF, ZOOM, ZOOM, OFF;
+ { false, false, true, true, false } };
+ const bool kExpectedOverrideResults[kTestCases][kFrameCount] = {
+ // All resuls should be overridden except the last one. The last result's
+ // zoom doesn't have speed-up.
+ { true, true, true, true, false },
+ // Because we require at least 2 frames speed-up, request #1, #2 and #3
+ // will be overridden.
+ { true, true, true, false, false } };
+
+ for (int i = 0; i < kTestCases; i++) {
+ processZoomSettingsOverrideRequests(kFrameCount, kOverrideSequence[i],
+ kExpectedOverrideResults[i]);
+ }
+}
+
// Generate and verify a burst containing alternating sensor sensitivity values
TEST_P(CameraAidlTest, processCaptureRequestBurstISO) {
std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
diff --git a/camera/provider/aidl/vts/camera_aidl_test.cpp b/camera/provider/aidl/vts/camera_aidl_test.cpp
index 2c2f1b2..b9e30ab 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.cpp
+++ b/camera/provider/aidl/vts/camera_aidl_test.cpp
@@ -22,6 +22,7 @@
#include <HandleImporter.h>
#include <aidl/android/hardware/camera/device/ICameraDevice.h>
#include <aidl/android/hardware/camera/metadata/CameraMetadataTag.h>
+#include <aidl/android/hardware/camera/metadata/RequestAvailableColorSpaceProfilesMap.h>
#include <aidl/android/hardware/camera/metadata/RequestAvailableDynamicRangeProfilesMap.h>
#include <aidl/android/hardware/camera/metadata/SensorInfoColorFilterArrangement.h>
#include <aidl/android/hardware/camera/metadata/SensorPixelMode.h>
@@ -43,6 +44,7 @@
using ::aidl::android::hardware::camera::device::CameraMetadata;
using ::aidl::android::hardware::camera::device::ICameraDevice;
using ::aidl::android::hardware::camera::metadata::CameraMetadataTag;
+using ::aidl::android::hardware::camera::metadata::RequestAvailableColorSpaceProfilesMap;
using ::aidl::android::hardware::camera::metadata::RequestAvailableDynamicRangeProfilesMap;
using ::aidl::android::hardware::camera::metadata::SensorInfoColorFilterArrangement;
using ::aidl::android::hardware::camera::metadata::SensorPixelMode;
@@ -329,6 +331,69 @@
ASSERT_EQ(hasStreamUseCaseCap, supportMandatoryUseCases);
}
+void CameraAidlTest::verifySettingsOverrideCharacteristics(const camera_metadata_t* metadata) {
+ camera_metadata_ro_entry entry;
+ int retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES, &entry);
+ bool supportSettingsOverride = false;
+ if ((0 == retcode) && (entry.count > 0)) {
+ supportSettingsOverride = true;
+ bool hasOff = false;
+ for (size_t i = 0; i < entry.count; i++) {
+ if (entry.data.u8[i] == ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF) {
+ hasOff = true;
+ }
+ }
+ ASSERT_TRUE(hasOff);
+ }
+
+ // Check availableRequestKeys
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_REQUEST_KEYS, &entry);
+ bool hasSettingsOverrideRequestKey = false;
+ if ((0 == retcode) && (entry.count > 0)) {
+ hasSettingsOverrideRequestKey =
+ std::find(entry.data.i32, entry.data.i32 + entry.count,
+ ANDROID_CONTROL_SETTINGS_OVERRIDE) != entry.data.i32 + entry.count;
+ } else {
+ ADD_FAILURE() << "Get camera availableRequestKeys failed!";
+ }
+
+ // Check availableResultKeys
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_RESULT_KEYS, &entry);
+ bool hasSettingsOverrideResultKey = false;
+ bool hasOverridingFrameNumberKey = false;
+ if ((0 == retcode) && (entry.count > 0)) {
+ hasSettingsOverrideResultKey =
+ std::find(entry.data.i32, entry.data.i32 + entry.count,
+ ANDROID_CONTROL_SETTINGS_OVERRIDE) != entry.data.i32 + entry.count;
+ hasOverridingFrameNumberKey =
+ std::find(entry.data.i32, entry.data.i32 + entry.count,
+ ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER)
+ != entry.data.i32 + entry.count;
+ } else {
+ ADD_FAILURE() << "Get camera availableResultKeys failed!";
+ }
+
+ // Check availableCharacteristicKeys
+ retcode = find_camera_metadata_ro_entry(metadata,
+ ANDROID_REQUEST_AVAILABLE_CHARACTERISTICS_KEYS, &entry);
+ bool hasSettingsOverrideCharacteristicsKey= false;
+ if ((0 == retcode) && (entry.count > 0)) {
+ hasSettingsOverrideCharacteristicsKey = std::find(entry.data.i32,
+ entry.data.i32 + entry.count, ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES)
+ != entry.data.i32 + entry.count;
+ } else {
+ ADD_FAILURE() << "Get camera availableCharacteristicsKeys failed!";
+ }
+
+ ASSERT_EQ(supportSettingsOverride, hasSettingsOverrideRequestKey);
+ ASSERT_EQ(supportSettingsOverride, hasSettingsOverrideResultKey);
+ ASSERT_EQ(supportSettingsOverride, hasOverridingFrameNumberKey);
+ ASSERT_EQ(supportSettingsOverride, hasSettingsOverrideCharacteristicsKey);
+}
+
Status CameraAidlTest::isMonochromeCamera(const camera_metadata_t* staticMeta) {
Status ret = Status::OPERATION_NOT_SUPPORTED;
if (nullptr == staticMeta) {
@@ -604,6 +669,7 @@
verifyExtendedSceneModeCharacteristics(metadata);
verifyZoomCharacteristics(metadata);
verifyStreamUseCaseCharacteristics(metadata);
+ verifySettingsOverrideCharacteristics(metadata);
}
void CameraAidlTest::verifyExtendedSceneModeCharacteristics(const camera_metadata_t* metadata) {
@@ -1515,6 +1581,15 @@
ASSERT_EQ(zoomRatioEntry.count, 1);
ASSERT_EQ(zoomRatioEntry.data.f[0], 1.0f);
}
+
+ // Check settings override
+ camera_metadata_ro_entry settingsOverrideEntry;
+ int foundSettingsOverride = find_camera_metadata_ro_entry(metadata,
+ ANDROID_CONTROL_SETTINGS_OVERRIDE, &settingsOverrideEntry);
+ if (foundSettingsOverride == 0) {
+ ASSERT_EQ(settingsOverrideEntry.count, 1);
+ ASSERT_EQ(settingsOverrideEntry.data.u8[0], ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF);
+ }
}
void CameraAidlTest::openEmptyDeviceSession(const std::string& name,
@@ -2788,6 +2863,192 @@
}
}
+bool CameraAidlTest::reportsColorSpaces(const camera_metadata_t* staticMeta) {
+ camera_metadata_ro_entry capabilityEntry;
+ int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_REQUEST_AVAILABLE_CAPABILITIES,
+ &capabilityEntry);
+ if (rc == 0) {
+ for (uint32_t i = 0; i < capabilityEntry.count; i++) {
+ if (capabilityEntry.data.u8[i] ==
+ ANDROID_REQUEST_AVAILABLE_CAPABILITIES_COLOR_SPACE_PROFILES) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void CameraAidlTest::getColorSpaceProfiles(
+ const camera_metadata_t* staticMeta,
+ std::vector<RequestAvailableColorSpaceProfilesMap>* profiles) {
+ ASSERT_NE(nullptr, staticMeta);
+ ASSERT_NE(nullptr, profiles);
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(
+ staticMeta, ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP, &entry);
+ ASSERT_EQ(rc, 0);
+ ASSERT_TRUE(entry.count > 0);
+ ASSERT_EQ(entry.count % 3, 0);
+
+ for (uint32_t i = 0; i < entry.count; i += 3) {
+ ASSERT_NE(entry.data.i64[i],
+ ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED);
+ if (std::find(profiles->begin(), profiles->end(),
+ static_cast<RequestAvailableColorSpaceProfilesMap>(entry.data.i64[i]))
+ == profiles->end()) {
+ profiles->emplace_back(
+ static_cast<RequestAvailableColorSpaceProfilesMap>(entry.data.i64[i]));
+ }
+ }
+}
+
+bool CameraAidlTest::isColorSpaceCompatibleWithDynamicRangeAndPixelFormat(
+ const camera_metadata_t* staticMeta,
+ RequestAvailableColorSpaceProfilesMap colorSpace,
+ RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile,
+ aidl::android::hardware::graphics::common::PixelFormat pixelFormat) {
+ camera_metadata_ro_entry entry;
+ int rc = find_camera_metadata_ro_entry(
+ staticMeta, ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP, &entry);
+
+ if (rc == 0) {
+ for (uint32_t i = 0; i < entry.count; i += 3) {
+ RequestAvailableColorSpaceProfilesMap entryColorSpace =
+ static_cast<RequestAvailableColorSpaceProfilesMap>(entry.data.i64[i]);
+ int64_t dynamicRangeProfileI64 = static_cast<int64_t>(dynamicRangeProfile);
+ int32_t entryImageFormat = static_cast<int32_t>(entry.data.i64[i + 1]);
+ int32_t expectedImageFormat = halFormatToPublicFormat(pixelFormat);
+ if (entryColorSpace == colorSpace
+ && (entry.data.i64[i + 2] & dynamicRangeProfileI64) != 0
+ && entryImageFormat == expectedImageFormat) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+const char* CameraAidlTest::getColorSpaceProfileString(
+ RequestAvailableColorSpaceProfilesMap colorSpace) {
+ auto colorSpaceCast = static_cast<int>(colorSpace);
+ switch (colorSpaceCast) {
+ case ANDROID_REQUEST_AVAILABLE_COLOR_SPACE_PROFILES_MAP_UNSPECIFIED:
+ return "UNSPECIFIED";
+ case ColorSpaceNamed::SRGB:
+ return "SRGB";
+ case ColorSpaceNamed::LINEAR_SRGB:
+ return "LINEAR_SRGB";
+ case ColorSpaceNamed::EXTENDED_SRGB:
+ return "EXTENDED_SRGB";
+ case ColorSpaceNamed::LINEAR_EXTENDED_SRGB:
+ return "LINEAR_EXTENDED_SRGB";
+ case ColorSpaceNamed::BT709:
+ return "BT709";
+ case ColorSpaceNamed::BT2020:
+ return "BT2020";
+ case ColorSpaceNamed::DCI_P3:
+ return "DCI_P3";
+ case ColorSpaceNamed::DISPLAY_P3:
+ return "DISPLAY_P3";
+ case ColorSpaceNamed::NTSC_1953:
+ return "NTSC_1953";
+ case ColorSpaceNamed::SMPTE_C:
+ return "SMPTE_C";
+ case ColorSpaceNamed::ADOBE_RGB:
+ return "ADOBE_RGB";
+ case ColorSpaceNamed::PRO_PHOTO_RGB:
+ return "PRO_PHOTO_RGB";
+ case ColorSpaceNamed::ACES:
+ return "ACES";
+ case ColorSpaceNamed::ACESCG:
+ return "ACESCG";
+ case ColorSpaceNamed::CIE_XYZ:
+ return "CIE_XYZ";
+ case ColorSpaceNamed::CIE_LAB:
+ return "CIE_LAB";
+ default:
+ return "INVALID";
+ }
+
+ return "INVALID";
+}
+
+const char* CameraAidlTest::getDynamicRangeProfileString(
+ RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile) {
+ auto dynamicRangeProfileCast =
+ static_cast<camera_metadata_enum_android_request_available_dynamic_range_profiles_map>
+ (dynamicRangeProfile);
+ switch (dynamicRangeProfileCast) {
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD:
+ return "STANDARD";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HLG10:
+ return "HLG10";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10:
+ return "HDR10";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_HDR10_PLUS:
+ return "HDR10_PLUS";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF:
+ return "DOLBY_VISION_10B_HDR_REF";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_REF_PO:
+ return "DOLBY_VISION_10B_HDR_REF_P0";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM:
+ return "DOLBY_VISION_10B_HDR_OEM";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_10B_HDR_OEM_PO:
+ return "DOLBY_VISION_10B_HDR_OEM_P0";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF:
+ return "DOLBY_VISION_8B_HDR_REF";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_REF_PO:
+ return "DOLBY_VISION_8B_HDR_REF_P0";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM:
+ return "DOLBY_VISION_8B_HDR_OEM";
+ case ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_DOLBY_VISION_8B_HDR_OEM_PO:
+ return "DOLBY_VISION_8B_HDR_OEM_P0";
+ default:
+ return "INVALID";
+ }
+
+ return "INVALID";
+}
+
+int32_t CameraAidlTest::halFormatToPublicFormat(
+ aidl::android::hardware::graphics::common::PixelFormat pixelFormat) {
+ // This is an incomplete mapping of pixel format to image format and assumes dataspaces
+ // (see getDataspace)
+ switch (pixelFormat) {
+ case PixelFormat::BLOB:
+ return 0x100; // ImageFormat.JPEG
+ case PixelFormat::Y16:
+ return 0x44363159; // ImageFormat.DEPTH16
+ default:
+ return static_cast<int32_t>(pixelFormat);
+ }
+}
+
+bool CameraAidlTest::supportZoomSettingsOverride(const camera_metadata_t* staticMeta) {
+ camera_metadata_ro_entry availableOverridesEntry;
+ int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_CONTROL_AVAILABLE_SETTINGS_OVERRIDES,
+ &availableOverridesEntry);
+ if (rc == 0) {
+ for (size_t i = 0; i < availableOverridesEntry.count; i++) {
+ if (availableOverridesEntry.data.i32[i] == ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool CameraAidlTest::isPerFrameControl(const camera_metadata_t* staticMeta) {
+ camera_metadata_ro_entry syncLatencyEntry;
+ int rc = find_camera_metadata_ro_entry(staticMeta, ANDROID_SYNC_MAX_LATENCY,
+ &syncLatencyEntry);
+ if (rc == 0 && syncLatencyEntry.data.i32[0] == ANDROID_SYNC_MAX_LATENCY_PER_FRAME_CONTROL) {
+ return true;
+ }
+ return false;
+}
+
void CameraAidlTest::configurePreviewStream(
const std::string& name, const std::shared_ptr<ICameraProvider>& provider,
const AvailableStream* previewThreshold, std::shared_ptr<ICameraDeviceSession>* session,
@@ -2933,4 +3194,379 @@
for (auto& it : mInflightMap) {
it.second->resultQueue = resultQueue;
}
-}
\ No newline at end of file
+}
+
+void CameraAidlTest::processColorSpaceRequest(
+ RequestAvailableColorSpaceProfilesMap colorSpace,
+ RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile) {
+ std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+ int64_t bufferId = 1;
+ CameraMetadata settings;
+
+ for (const auto& name : cameraDeviceNames) {
+ std::string version, deviceId;
+ ASSERT_TRUE(matchDeviceName(name, mProviderType, &version, &deviceId));
+ CameraMetadata meta;
+ std::shared_ptr<ICameraDevice> device;
+ openEmptyDeviceSession(name, mProvider, &mSession, &meta, &device);
+ camera_metadata_t* staticMeta = reinterpret_cast<camera_metadata_t*>(meta.metadata.data());
+
+ // Device does not report color spaces, skip.
+ if (!reportsColorSpaces(staticMeta)) {
+ ndk::ScopedAStatus ret = mSession->close();
+ mSession = nullptr;
+ ASSERT_TRUE(ret.isOk());
+ ALOGV("Camera %s does not report color spaces", name.c_str());
+ continue;
+ }
+ std::vector<RequestAvailableColorSpaceProfilesMap> profileList;
+ getColorSpaceProfiles(staticMeta, &profileList);
+ ASSERT_FALSE(profileList.empty());
+
+ // Device does not support color space / dynamic range profile, skip
+ if (std::find(profileList.begin(), profileList.end(), colorSpace)
+ == profileList.end() || !isColorSpaceCompatibleWithDynamicRangeAndPixelFormat(
+ staticMeta, colorSpace, dynamicRangeProfile,
+ PixelFormat::IMPLEMENTATION_DEFINED)) {
+ ndk::ScopedAStatus ret = mSession->close();
+ mSession = nullptr;
+ ASSERT_TRUE(ret.isOk());
+ ALOGV("Camera %s does not support color space %s with dynamic range profile %s and "
+ "pixel format %d", name.c_str(), getColorSpaceProfileString(colorSpace),
+ getDynamicRangeProfileString(dynamicRangeProfile),
+ PixelFormat::IMPLEMENTATION_DEFINED);
+ continue;
+ }
+
+ ALOGV("Camera %s supports color space %s with dynamic range profile %s and pixel format %d",
+ name.c_str(), getColorSpaceProfileString(colorSpace),
+ getDynamicRangeProfileString(dynamicRangeProfile),
+ PixelFormat::IMPLEMENTATION_DEFINED);
+
+ // If an HDR dynamic range profile is reported in the color space profile list,
+ // the device must also have the dynamic range profiles map capability and contain
+ // the dynamic range profile in the map.
+ if (dynamicRangeProfile != static_cast<RequestAvailableDynamicRangeProfilesMap>(
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD)) {
+ ASSERT_TRUE(is10BitDynamicRangeCapable(staticMeta));
+
+ std::vector<RequestAvailableDynamicRangeProfilesMap> dynamicRangeProfiles;
+ get10BitDynamicRangeProfiles(staticMeta, &dynamicRangeProfiles);
+ ASSERT_FALSE(dynamicRangeProfiles.empty());
+ ASSERT_FALSE(std::find(dynamicRangeProfiles.begin(), dynamicRangeProfiles.end(),
+ dynamicRangeProfile) == dynamicRangeProfiles.end());
+ }
+
+ CameraMetadata req;
+ android::hardware::camera::common::V1_0::helper::CameraMetadata defaultSettings;
+ ndk::ScopedAStatus ret =
+ mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &req);
+ ASSERT_TRUE(ret.isOk());
+
+ const camera_metadata_t* metadata =
+ reinterpret_cast<const camera_metadata_t*>(req.metadata.data());
+ size_t expectedSize = req.metadata.size();
+ int result = validate_camera_metadata_structure(metadata, &expectedSize);
+ ASSERT_TRUE((result == 0) || (result == CAMERA_METADATA_VALIDATION_SHIFTED));
+
+ size_t entryCount = get_camera_metadata_entry_count(metadata);
+ ASSERT_GT(entryCount, 0u);
+ defaultSettings = metadata;
+
+ const camera_metadata_t* settingsBuffer = defaultSettings.getAndLock();
+ uint8_t* rawSettingsBuffer = (uint8_t*)settingsBuffer;
+ settings.metadata = std::vector(
+ rawSettingsBuffer, rawSettingsBuffer + get_camera_metadata_size(settingsBuffer));
+ overrideRotateAndCrop(&settings);
+
+ ret = mSession->close();
+ mSession = nullptr;
+ ASSERT_TRUE(ret.isOk());
+
+ std::vector<HalStream> halStreams;
+ bool supportsPartialResults = false;
+ bool useHalBufManager = false;
+ int32_t partialResultCount = 0;
+ Stream previewStream;
+ std::shared_ptr<DeviceCb> cb;
+
+ previewStream.usage =
+ static_cast<aidl::android::hardware::graphics::common::BufferUsage>(
+ GRALLOC1_CONSUMER_USAGE_HWCOMPOSER);
+ previewStream.dataSpace = getDataspace(PixelFormat::IMPLEMENTATION_DEFINED);
+ previewStream.colorSpace = static_cast<int32_t>(colorSpace);
+ configureStreams(name, mProvider, PixelFormat::IMPLEMENTATION_DEFINED, &mSession,
+ &previewStream, &halStreams, &supportsPartialResults,
+ &partialResultCount, &useHalBufManager, &cb, 0,
+ /*maxResolution*/ false, dynamicRangeProfile);
+ ASSERT_NE(mSession, nullptr);
+
+ ::aidl::android::hardware::common::fmq::MQDescriptor<
+ int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ descriptor;
+ auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
+ ASSERT_TRUE(resultQueueRet.isOk());
+
+ std::shared_ptr<ResultMetadataQueue> resultQueue =
+ std::make_shared<ResultMetadataQueue>(descriptor);
+ if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
+ ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
+ resultQueue = nullptr;
+ // Don't use the queue onwards.
+ }
+
+ mInflightMap.clear();
+ // Stream as long as needed to fill the Hal inflight queue
+ std::vector<CaptureRequest> requests(halStreams[0].maxBuffers);
+
+ for (int32_t frameNumber = 0; frameNumber < requests.size(); frameNumber++) {
+ std::shared_ptr<InFlightRequest> inflightReq = std::make_shared<InFlightRequest>(
+ static_cast<ssize_t>(halStreams.size()), false, supportsPartialResults,
+ partialResultCount, std::unordered_set<std::string>(), resultQueue);
+
+ CaptureRequest& request = requests[frameNumber];
+ std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
+ outputBuffers.resize(halStreams.size());
+
+ size_t k = 0;
+ inflightReq->mOutstandingBufferIds.resize(halStreams.size());
+ std::vector<buffer_handle_t> graphicBuffers;
+ graphicBuffers.reserve(halStreams.size());
+
+ for (const auto& halStream : halStreams) {
+ buffer_handle_t buffer_handle;
+ if (useHalBufManager) {
+ outputBuffers[k] = {halStream.id, 0,
+ NativeHandle(), BufferStatus::OK,
+ NativeHandle(), NativeHandle()};
+ } else {
+ auto usage = android_convertGralloc1To0Usage(
+ static_cast<uint64_t>(halStream.producerUsage),
+ static_cast<uint64_t>(halStream.consumerUsage));
+ allocateGraphicBuffer(previewStream.width, previewStream.height, usage,
+ halStream.overrideFormat, &buffer_handle);
+
+ inflightReq->mOutstandingBufferIds[halStream.id][bufferId] = buffer_handle;
+ graphicBuffers.push_back(buffer_handle);
+ outputBuffers[k] = {halStream.id, bufferId,
+ android::makeToAidl(buffer_handle), BufferStatus::OK, NativeHandle(),
+ NativeHandle()};
+ bufferId++;
+ }
+ k++;
+ }
+
+ request.inputBuffer = {
+ -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
+ request.frameNumber = frameNumber;
+ request.fmqSettingsSize = 0;
+ request.settings = settings;
+ request.inputWidth = 0;
+ request.inputHeight = 0;
+
+ {
+ std::unique_lock<std::mutex> l(mLock);
+ mInflightMap[frameNumber] = inflightReq;
+ }
+
+ }
+
+ int32_t numRequestProcessed = 0;
+ std::vector<BufferCache> cachesToRemove;
+ ndk::ScopedAStatus returnStatus =
+ mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
+ ASSERT_TRUE(returnStatus.isOk());
+ ASSERT_EQ(numRequestProcessed, requests.size());
+
+ returnStatus = mSession->repeatingRequestEnd(requests.size() - 1,
+ std::vector<int32_t> {halStreams[0].id});
+ ASSERT_TRUE(returnStatus.isOk());
+
+ for (int32_t frameNumber = 0; frameNumber < requests.size(); frameNumber++) {
+ const auto& inflightReq = mInflightMap[frameNumber];
+ std::unique_lock<std::mutex> l(mLock);
+ while (!inflightReq->errorCodeValid &&
+ ((0 < inflightReq->numBuffersLeft) || (!inflightReq->haveResultMetadata))) {
+ auto timeout = std::chrono::system_clock::now() +
+ std::chrono::seconds(kStreamBufferTimeoutSec);
+ ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
+ }
+
+ ASSERT_FALSE(inflightReq->errorCodeValid);
+ ASSERT_NE(inflightReq->resultOutputBuffers.size(), 0u);
+
+ if (dynamicRangeProfile != static_cast<RequestAvailableDynamicRangeProfilesMap>(
+ ANDROID_REQUEST_AVAILABLE_DYNAMIC_RANGE_PROFILES_MAP_STANDARD)) {
+ verify10BitMetadata(mHandleImporter, *inflightReq, dynamicRangeProfile);
+ }
+ }
+
+ if (useHalBufManager) {
+ std::vector<int32_t> streamIds(halStreams.size());
+ for (size_t i = 0; i < streamIds.size(); i++) {
+ streamIds[i] = halStreams[i].id;
+ }
+ mSession->signalStreamFlush(streamIds, /*streamConfigCounter*/ 0);
+ cb->waitForBuffersReturned();
+ }
+
+ ret = mSession->close();
+ mSession = nullptr;
+ ASSERT_TRUE(ret.isOk());
+ }
+}
+
+void CameraAidlTest::processZoomSettingsOverrideRequests(
+ int32_t frameCount, const bool *overrideSequence, const bool *expectedResults) {
+ std::vector<std::string> cameraDeviceNames = getCameraDeviceNames(mProvider);
+ AvailableStream previewThreshold = {kMaxPreviewWidth, kMaxPreviewHeight,
+ static_cast<int32_t>(PixelFormat::IMPLEMENTATION_DEFINED)};
+ int64_t bufferId = 1;
+ int32_t frameNumber = 1;
+ CameraMetadata settings;
+ ndk::ScopedAStatus ret;
+ for (const auto& name : cameraDeviceNames) {
+ CameraMetadata meta;
+ std::shared_ptr<ICameraDevice> device;
+ openEmptyDeviceSession(name, mProvider, &mSession /*out*/, &meta /*out*/,
+ &device /*out*/);
+ camera_metadata_t* staticMeta =
+ clone_camera_metadata(reinterpret_cast<camera_metadata_t*>(meta.metadata.data()));
+
+ ret = mSession->close();
+ mSession = nullptr;
+ ASSERT_TRUE(ret.isOk());
+
+ // Device does not support zoom settnigs override
+ if (!supportZoomSettingsOverride(staticMeta)) {
+ continue;
+ }
+
+ if (!isPerFrameControl(staticMeta)) {
+ continue;
+ }
+
+ bool supportsPartialResults = false;
+ bool useHalBufManager = false;
+ int32_t partialResultCount = 0;
+ Stream previewStream;
+ std::vector<HalStream> halStreams;
+ std::shared_ptr<DeviceCb> cb;
+ configurePreviewStream(name, mProvider, &previewThreshold, &mSession /*out*/,
+ &previewStream /*out*/, &halStreams /*out*/,
+ &supportsPartialResults /*out*/, &partialResultCount /*out*/,
+ &useHalBufManager /*out*/, &cb /*out*/);
+ ASSERT_NE(mSession, nullptr);
+
+ ::aidl::android::hardware::common::fmq::MQDescriptor<
+ int8_t, aidl::android::hardware::common::fmq::SynchronizedReadWrite>
+ descriptor;
+ auto resultQueueRet = mSession->getCaptureResultMetadataQueue(&descriptor);
+ ASSERT_TRUE(resultQueueRet.isOk());
+
+ std::shared_ptr<ResultMetadataQueue> resultQueue =
+ std::make_shared<ResultMetadataQueue>(descriptor);
+ if (!resultQueue->isValid() || resultQueue->availableToWrite() <= 0) {
+ ALOGE("%s: HAL returns empty result metadata fmq, not use it", __func__);
+ resultQueue = nullptr;
+ // Don't use the queue onwards.
+ }
+
+ ret = mSession->constructDefaultRequestSettings(RequestTemplate::PREVIEW, &settings);
+ ASSERT_TRUE(ret.isOk());
+
+ mInflightMap.clear();
+ ::android::hardware::camera::common::V1_0::helper::CameraMetadata requestMeta;
+ std::vector<CaptureRequest> requests(frameCount);
+ std::vector<buffer_handle_t> buffers(frameCount);
+ std::vector<std::shared_ptr<InFlightRequest>> inflightReqs(frameCount);
+ std::vector<CameraMetadata> requestSettings(frameCount);
+
+ for (int32_t i = 0; i < frameCount; i++) {
+ std::unique_lock<std::mutex> l(mLock);
+ CaptureRequest& request = requests[i];
+ std::vector<StreamBuffer>& outputBuffers = request.outputBuffers;
+ outputBuffers.resize(1);
+ StreamBuffer& outputBuffer = outputBuffers[0];
+
+ if (useHalBufManager) {
+ outputBuffer = {halStreams[0].id, 0,
+ NativeHandle(), BufferStatus::OK,
+ NativeHandle(), NativeHandle()};
+ } else {
+ allocateGraphicBuffer(previewStream.width, previewStream.height,
+ android_convertGralloc1To0Usage(
+ static_cast<uint64_t>(halStreams[0].producerUsage),
+ static_cast<uint64_t>(halStreams[0].consumerUsage)),
+ halStreams[0].overrideFormat, &buffers[i]);
+ outputBuffer = {halStreams[0].id, bufferId + i, ::android::makeToAidl(buffers[i]),
+ BufferStatus::OK, NativeHandle(), NativeHandle()};
+ }
+
+ // Set appropriate settings override tag
+ requestMeta.append(reinterpret_cast<camera_metadata_t*>(settings.metadata.data()));
+ int32_t settingsOverride = overrideSequence[i] ?
+ ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM : ANDROID_CONTROL_SETTINGS_OVERRIDE_OFF;
+ ASSERT_EQ(::android::OK, requestMeta.update(ANDROID_CONTROL_SETTINGS_OVERRIDE,
+ &settingsOverride, 1));
+ camera_metadata_t* metaBuffer = requestMeta.release();
+ uint8_t* rawMetaBuffer = reinterpret_cast<uint8_t*>(metaBuffer);
+ requestSettings[i].metadata = std::vector(
+ rawMetaBuffer, rawMetaBuffer + get_camera_metadata_size(metaBuffer));
+ overrideRotateAndCrop(&(requestSettings[i]));
+ request.frameNumber = frameNumber + i;
+ request.fmqSettingsSize = 0;
+ request.settings = requestSettings[i];
+ request.inputBuffer = {
+ -1, 0, NativeHandle(), BufferStatus::ERROR, NativeHandle(), NativeHandle()};
+
+ inflightReqs[i] = std::make_shared<InFlightRequest>(1, false, supportsPartialResults,
+ partialResultCount, resultQueue);
+ mInflightMap[frameNumber + i] = inflightReqs[i];
+ }
+
+ int32_t numRequestProcessed = 0;
+ std::vector<BufferCache> cachesToRemove;
+
+ ndk::ScopedAStatus returnStatus =
+ mSession->processCaptureRequest(requests, cachesToRemove, &numRequestProcessed);
+ ASSERT_TRUE(returnStatus.isOk());
+ ASSERT_EQ(numRequestProcessed, frameCount);
+
+ for (size_t i = 0; i < frameCount; i++) {
+ std::unique_lock<std::mutex> l(mLock);
+ while (!inflightReqs[i]->errorCodeValid && ((0 < inflightReqs[i]->numBuffersLeft) ||
+ (!inflightReqs[i]->haveResultMetadata))) {
+ auto timeout = std::chrono::system_clock::now() +
+ std::chrono::seconds(kStreamBufferTimeoutSec);
+ ASSERT_NE(std::cv_status::timeout, mResultCondition.wait_until(l, timeout));
+ }
+
+ ASSERT_FALSE(inflightReqs[i]->errorCodeValid);
+ ASSERT_NE(inflightReqs[i]->resultOutputBuffers.size(), 0u);
+ ASSERT_EQ(previewStream.id, inflightReqs[i]->resultOutputBuffers[0].buffer.streamId);
+ ASSERT_FALSE(inflightReqs[i]->collectedResult.isEmpty());
+ ASSERT_TRUE(inflightReqs[i]->collectedResult.exists(ANDROID_CONTROL_SETTINGS_OVERRIDE));
+ camera_metadata_entry_t overrideResult =
+ inflightReqs[i]->collectedResult.find(ANDROID_CONTROL_SETTINGS_OVERRIDE);
+ ASSERT_EQ(overrideResult.data.i32[0] == ANDROID_CONTROL_SETTINGS_OVERRIDE_ZOOM,
+ expectedResults[i]);
+ ASSERT_TRUE(inflightReqs[i]->collectedResult.exists(
+ ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER));
+ camera_metadata_entry_t frameNumberEntry = inflightReqs[i]->collectedResult.find(
+ ANDROID_CONTROL_SETTINGS_OVERRIDING_FRAME_NUMBER);
+ ALOGV("%s: i %zu, expcetedResults[i] %d, overrideResult is %d, frameNumber %d",
+ __FUNCTION__, i, expectedResults[i], overrideResult.data.i32[0],
+ frameNumberEntry.data.i32[0]);
+ if (expectedResults[i]) {
+ ASSERT_GT(frameNumberEntry.data.i32[0], inflightReqs[i]->frameNumber);
+ } else {
+ ASSERT_EQ(frameNumberEntry.data.i32[0], frameNumber + i);
+ }
+ }
+
+ ret = mSession->close();
+ mSession = nullptr;
+ ASSERT_TRUE(ret.isOk());
+ }
+}
diff --git a/camera/provider/aidl/vts/camera_aidl_test.h b/camera/provider/aidl/vts/camera_aidl_test.h
index d828cee..b6e398b 100644
--- a/camera/provider/aidl/vts/camera_aidl_test.h
+++ b/camera/provider/aidl/vts/camera_aidl_test.h
@@ -44,6 +44,8 @@
#include <aidl/android/hardware/camera/provider/ICameraProvider.h>
+#include <aidl/android/hardware/camera/metadata/RequestAvailableColorSpaceProfilesMap.h>
+
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
#include <gtest/gtest.h>
@@ -123,6 +125,26 @@
YUV_REPROCESS,
};
+ // Copied from ColorSpace.java (see Named)
+ enum ColorSpaceNamed {
+ SRGB,
+ LINEAR_SRGB,
+ EXTENDED_SRGB,
+ LINEAR_EXTENDED_SRGB,
+ BT709,
+ BT2020,
+ DCI_P3,
+ DISPLAY_P3,
+ NTSC_1953,
+ SMPTE_C,
+ ADOBE_RGB,
+ PRO_PHOTO_RGB,
+ ACES,
+ ACESCG,
+ CIE_XYZ,
+ CIE_LAB
+ };
+
struct AvailableZSLInputOutput {
int32_t inputFormat;
int32_t outputFormat;
@@ -230,6 +252,8 @@
static void verifyStreamUseCaseCharacteristics(const camera_metadata_t* metadata);
+ static void verifySettingsOverrideCharacteristics(const camera_metadata_t* metadata);
+
static void verifyStreamCombination(const std::shared_ptr<ICameraDevice>& device,
const StreamConfiguration& config, bool expectedStatus,
bool expectStreamCombQuery);
@@ -348,11 +372,46 @@
std::vector<aidl::android::hardware::camera::metadata::
RequestAvailableDynamicRangeProfilesMap>* profiles);
+ static bool reportsColorSpaces(const camera_metadata_t* staticMeta);
+
+ static void getColorSpaceProfiles(
+ const camera_metadata_t* staticMeta,
+ std::vector<aidl::android::hardware::camera::metadata::
+ RequestAvailableColorSpaceProfilesMap>* profiles);
+
+ static bool isColorSpaceCompatibleWithDynamicRangeAndPixelFormat(
+ const camera_metadata_t* staticMeta,
+ aidl::android::hardware::camera::metadata::
+ RequestAvailableColorSpaceProfilesMap colorSpace,
+ aidl::android::hardware::camera::metadata::
+ RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile,
+ aidl::android::hardware::graphics::common::PixelFormat pixelFormat);
+
+ static const char* getColorSpaceProfileString(aidl::android::hardware::camera::metadata::
+ RequestAvailableColorSpaceProfilesMap colorSpace);
+
+ static const char* getDynamicRangeProfileString(aidl::android::hardware::camera::metadata::
+ RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile);
+
+ static int32_t halFormatToPublicFormat(
+ aidl::android::hardware::graphics::common::PixelFormat pixelFormat);
+
// Used by switchToOffline where a new result queue is created for offline reqs
void updateInflightResultQueue(const std::shared_ptr<ResultMetadataQueue>& resultQueue);
static Size getMinSize(Size a, Size b);
+ void processColorSpaceRequest(aidl::android::hardware::camera::metadata::
+ RequestAvailableColorSpaceProfilesMap colorSpace,
+ aidl::android::hardware::camera::metadata::
+ RequestAvailableDynamicRangeProfilesMap dynamicRangeProfile);
+
+ void processZoomSettingsOverrideRequests(
+ int32_t frameCount, const bool *overrideSequence, const bool *expectedResults);
+
+ bool supportZoomSettingsOverride(const camera_metadata_t* staticMeta);
+ bool isPerFrameControl(const camera_metadata_t* staticMeta);
+
protected:
// In-flight queue for tracking completion of capture requests.
struct InFlightRequest {
diff --git a/cas/aidl/Android.bp b/cas/aidl/Android.bp
new file mode 100644
index 0000000..32f12b1
--- /dev/null
+++ b/cas/aidl/Android.bp
@@ -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.
+ */
+
+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.cas",
+ vendor_available: true,
+ srcs: ["android/hardware/cas/*.aidl"],
+ stability: "vintf",
+ imports: ["android.hardware.common-V2"],
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
new file mode 100644
index 0000000..7b8099f
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/AidlCasPluginDescriptor.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.cas;
+@VintfStability
+parcelable AidlCasPluginDescriptor {
+ int caSystemId;
+ String name;
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
new file mode 100644
index 0000000..dd355af
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/DestinationBuffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.cas;
+@VintfStability
+union DestinationBuffer {
+ android.hardware.cas.SharedBuffer nonsecureMemory;
+ android.hardware.common.NativeHandle secureMemory;
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
new file mode 100644
index 0000000..e169beb
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICas.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.cas;
+@VintfStability
+interface ICas {
+ void closeSession(in byte[] sessionId);
+ byte[] openSession(in android.hardware.cas.SessionIntent intent, in android.hardware.cas.ScramblingMode mode);
+ void processEcm(in byte[] sessionId, in byte[] ecm);
+ void processEmm(in byte[] emm);
+ void provision(in String provisionString);
+ void refreshEntitlements(in int refreshType, in byte[] refreshData);
+ void release();
+ void sendEvent(in int event, in int arg, in byte[] eventData);
+ void sendSessionEvent(in byte[] sessionId, in int event, in int arg, in byte[] eventData);
+ void setPrivateData(in byte[] pvtData);
+ void setSessionPrivateData(in byte[] sessionId, in byte[] pvtData);
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.aidl
new file mode 100644
index 0000000..ebc13ce
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ICasListener.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.cas;
+@VintfStability
+interface ICasListener {
+ void onEvent(in int event, in int arg, in byte[] data);
+ void onSessionEvent(in byte[] sessionId, in int event, in int arg, in byte[] data);
+ void onStatusUpdate(in android.hardware.cas.StatusEvent event, in int number);
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
new file mode 100644
index 0000000..9bf7903
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IDescrambler.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.cas;
+@VintfStability
+interface IDescrambler {
+ int descramble(in android.hardware.cas.ScramblingControl scramblingControl, in android.hardware.cas.SubSample[] subSamples, in android.hardware.cas.SharedBuffer srcBuffer, in long srcOffset, in android.hardware.cas.DestinationBuffer dstBuffer, in long dstOffset);
+ void release();
+ boolean requiresSecureDecoderComponent(in String mime);
+ void setMediaCasSession(in byte[] sessionId);
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
new file mode 100644
index 0000000..f5c8018
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/IMediaCasService.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.cas;
+@VintfStability
+interface IMediaCasService {
+ android.hardware.cas.IDescrambler createDescrambler(in int CA_system_id);
+ android.hardware.cas.ICas createPlugin(in int CA_system_id, in android.hardware.cas.ICasListener listener);
+ android.hardware.cas.AidlCasPluginDescriptor[] enumeratePlugins();
+ boolean isDescramblerSupported(in int CA_system_id);
+ boolean isSystemIdSupported(in int CA_system_id);
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingControl.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingControl.aidl
new file mode 100644
index 0000000..d71d4be
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingControl.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.cas;
+@Backing(type="int") @VintfStability
+enum ScramblingControl {
+ UNSCRAMBLED = 0,
+ RESERVED = 1,
+ EVENKEY = 2,
+ ODDKEY = 3,
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
new file mode 100644
index 0000000..e3923c7
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/ScramblingMode.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.cas;
+@Backing(type="int") @VintfStability
+enum ScramblingMode {
+ RESERVED = 0,
+ DVB_CSA1 = 1,
+ DVB_CSA2 = 2,
+ DVB_CSA3_STANDARD = 3,
+ DVB_CSA3_MINIMAL = 4,
+ DVB_CSA3_ENHANCE = 5,
+ DVB_CISSA_V1 = 6,
+ DVB_IDSA = 7,
+ MULTI2 = 8,
+ AES128 = 9,
+ AES_CBC = 10,
+ AES_ECB = 11,
+ AES_SCTE52 = 12,
+ TDES_ECB = 13,
+ TDES_SCTE52 = 14,
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SessionIntent.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SessionIntent.aidl
new file mode 100644
index 0000000..af95f80
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SessionIntent.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.cas;
+@Backing(type="int") @VintfStability
+enum SessionIntent {
+ LIVE = 0,
+ PLAYBACK = 1,
+ RECORD = 2,
+ TIMESHIFT = 3,
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.aidl
new file mode 100644
index 0000000..a18aa57
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SharedBuffer.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.cas;
+@VintfStability
+parcelable SharedBuffer {
+ android.hardware.common.Ashmem heapBase;
+ long offset;
+ long size;
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
new file mode 100644
index 0000000..3d3a8a0
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/Status.aidl
@@ -0,0 +1,59 @@
+/*
+ * 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.cas;
+@VintfStability
+parcelable Status {
+ const int OK = 0;
+ const int ERROR_CAS_NO_LICENSE = -1;
+ const int ERROR_CAS_LICENSE_EXPIRED = -2;
+ const int ERROR_CAS_SESSION_NOT_OPENED = -3;
+ const int ERROR_CAS_CANNOT_HANDLE = -4;
+ const int ERROR_CAS_INVALID_STATE = -5;
+ const int BAD_VALUE = -6;
+ const int ERROR_CAS_NOT_PROVISIONED = -7;
+ const int ERROR_CAS_RESOURCE_BUSY = -8;
+ const int ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = -9;
+ const int ERROR_CAS_TAMPER_DETECTED = -10;
+ const int ERROR_CAS_DEVICE_REVOKED = -11;
+ const int ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED = -12;
+ const int ERROR_CAS_DECRYPT = -13;
+ const int ERROR_CAS_UNKNOWN = -14;
+ const int ERROR_CAS_NEED_ACTIVATION = -15;
+ const int ERROR_CAS_NEED_PAIRING = -16;
+ const int ERROR_CAS_NO_CARD = -17;
+ const int ERROR_CAS_CARD_MUTE = -18;
+ const int ERROR_CAS_CARD_INVALID = -19;
+ const int ERROR_CAS_BLACKOUT = -20;
+ const int ERROR_CAS_REBOOTING = -21;
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
new file mode 100644
index 0000000..178cabc
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/StatusEvent.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.cas;
+@Backing(type="byte") @VintfStability
+enum StatusEvent {
+ PLUGIN_PHYSICAL_MODULE_CHANGED = 0,
+ PLUGIN_SESSION_NUMBER_CHANGED = 1,
+}
diff --git a/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
new file mode 100644
index 0000000..d9ee3b4
--- /dev/null
+++ b/cas/aidl/aidl_api/android.hardware.cas/current/android/hardware/cas/SubSample.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.cas;
+@VintfStability
+parcelable SubSample {
+ int numBytesOfClearData;
+ int numBytesOfEncryptedData;
+}
diff --git a/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl b/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
new file mode 100644
index 0000000..55b328a
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/AidlCasPluginDescriptor.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.cas;
+
+/**
+ * Describes a CAS plugin with its system ID and name.
+ */
+@VintfStability
+parcelable AidlCasPluginDescriptor {
+ int caSystemId;
+ String name;
+}
diff --git a/cas/aidl/android/hardware/cas/DestinationBuffer.aidl b/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
new file mode 100644
index 0000000..068f29d
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/DestinationBuffer.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.cas;
+
+import android.hardware.cas.SharedBuffer;
+import android.hardware.common.NativeHandle;
+
+@VintfStability
+union DestinationBuffer {
+ /**
+ * If type == SHARED_MEMORY, the descrambled data must be written
+ * to user-space non-secure shared memory.
+ */
+ SharedBuffer nonsecureMemory;
+
+ /**
+ * If type == NATIVE_HANDLE, the descrambled data must be written
+ * to secure memory referenced by the vendor's buffer allocator.
+ */
+ NativeHandle secureMemory;
+}
diff --git a/cas/aidl/android/hardware/cas/ICas.aidl b/cas/aidl/android/hardware/cas/ICas.aidl
new file mode 100644
index 0000000..4c938c7
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/ICas.aidl
@@ -0,0 +1,121 @@
+/*
+ * 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.cas;
+
+import android.hardware.cas.ScramblingMode;
+import android.hardware.cas.SessionIntent;
+
+/**
+ * ICas is the API to control the CAS. It is used to manage sessions, provision/refresh the cas
+ * system, and process the EMM/ECM messages. It also allows bi-directional, scheme-specific
+ * communications between the client and the cas system.
+ */
+@VintfStability
+interface ICas {
+ /**
+ * Close a session.
+ *
+ * @param sessionId The id of the session to be closed.
+ */
+ void closeSession(in byte[] sessionId);
+
+ /**
+ * Open a session to descramble one or more streams by specifying intention
+ * and scrambling mode.
+ *
+ * @param intent the intention of the session to be opened.
+ * @param mode the scrambling mode the session will use.
+ *
+ * @return sessionId The id of the newly opened session.
+ */
+ byte[] openSession(in SessionIntent intent, in ScramblingMode mode);
+
+ /**
+ * Process an ECM from the ECM stream for this session’s elementary stream.
+ *
+ * @param sessionId the id of the session which the ecm data applies to.
+ * @param ecm a byte array containing the ecm data.
+ */
+ void processEcm(in byte[] sessionId, in byte[] ecm);
+
+ /**
+ * Process an in-band EMM from the EMM stream.
+ *
+ * @param emm a byte array containing the emm data.
+ */
+ void processEmm(in byte[] emm);
+
+ /**
+ * Initiate a provisioning operation for a CA system.
+ *
+ * @param provisionString string containing information needed for the
+ * provisioning operation, the format of which is scheme and implementation
+ * specific.
+ */
+ void provision(in String provisionString);
+
+ /**
+ * Notify the CA system to refresh entitlement keys.
+ *
+ * @param refreshType the type of the refreshment.
+ * @param refreshData private data associated with the refreshment.
+ */
+ void refreshEntitlements(in int refreshType, in byte[] refreshData);
+
+ /**
+ * Release the descrambler instance.
+ */
+ void release();
+
+ /**
+ * Send an scheme-specific event to the CasPlugin.
+ *
+ * @param event an integer denoting a scheme-specific event to be sent.
+ * @param arg a scheme-specific integer argument for the event.
+ * @param data a byte array containing scheme-specific data for the event.
+ */
+ void sendEvent(in int event, in int arg, in byte[] eventData);
+
+ /**
+ * Send an scheme-specific session event to the CasPlugin.
+ *
+ * @param sessionId the id of an opened session.
+ * @param event an integer denoting a scheme-specific event to be sent.
+ * @param arg a scheme-specific integer argument for the event.
+ * @param data a byte array containing scheme-specific data for the event.
+ */
+ void sendSessionEvent(in byte[] sessionId, in int event, in int arg, in byte[] eventData);
+
+ /**
+ * Provide the CA private data from a CA_descriptor in the conditional
+ * access table to a CasPlugin.
+ *
+ * @param pvtData a byte array containing the private data, the format of
+ * which is scheme-specific and opaque to the framework.
+ */
+ void setPrivateData(in byte[] pvtData);
+
+ /**
+ * Provide the CA private data from a CA_descriptor in the program map
+ * table to a session.
+ *
+ * @param sessionId the id of the session which the private data applies to.
+ * @param pvtData a byte array containing the private data, the format of
+ * which is scheme-specific and opaque to the framework.
+ */
+ void setSessionPrivateData(in byte[] sessionId, in byte[] pvtData);
+}
diff --git a/cas/aidl/android/hardware/cas/ICasListener.aidl b/cas/aidl/android/hardware/cas/ICasListener.aidl
new file mode 100644
index 0000000..32d843f
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/ICasListener.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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.cas;
+
+import android.hardware.cas.StatusEvent;
+
+@VintfStability
+interface ICasListener {
+ /**
+ * Notify the listener of a scheme-specific event from the CA system.
+ *
+ * @param event an integer whose meaning is scheme-specific.
+ * @param arg an integer whose meaning is scheme-specific.
+ * @param data a byte array of data whose format and meaning are
+ * scheme-specific.
+ */
+ void onEvent(in int event, in int arg, in byte[] data);
+
+ /**
+ * Notify the listener of a scheme-specific session event from CA system.
+ *
+ * @param sessionId the id of an opened session.
+ * @param event an integer whose meaning is scheme-specific.
+ * @param arg an integer whose meaning is scheme-specific.
+ * @param data a byte array of data whose format and meaning are
+ * scheme-specific.
+ */
+ void onSessionEvent(in byte[] sessionId, in int event, in int arg, in byte[] data);
+
+ /**
+ * Notify the listener that the status of CAS system has changed.
+ *
+ * @param event the event type of status change.
+ * @param number value for status event.
+ * For PLUGIN_PHYSICAL_MODULE_CHANGED event:
+ * the positive number presents how many plugins are inserted;
+ * the negative number presents how many plugins are removed.
+ * Client must enumerate plugins after receive the event.
+ * For PLUGIN_SESSION_NUMBER_CHANGED event:
+ * the number presents how many sessions are supported
+ * in the plugin.
+ */
+ void onStatusUpdate(in StatusEvent event, in int number);
+}
diff --git a/cas/aidl/android/hardware/cas/IDescrambler.aidl b/cas/aidl/android/hardware/cas/IDescrambler.aidl
new file mode 100644
index 0000000..33fbe75
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/IDescrambler.aidl
@@ -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.cas;
+
+import android.hardware.cas.DestinationBuffer;
+import android.hardware.cas.ScramblingControl;
+import android.hardware.cas.SharedBuffer;
+import android.hardware.cas.SubSample;
+
+/**
+ * IDescrambler is the API to control the descrambling operations.
+ */
+@VintfStability
+interface IDescrambler {
+ /**
+ * Descramble the data in a source SharedBuffer, described by an array of
+ * SubSample structures.
+ *
+ * @param scramblingControl an enumeration indicating the key that the subsamples
+ * were scrambled with.
+ * @param subSamples an array of SubSample structures describing the number of
+ * clear and scrambled bytes within each subsample.
+ * @param srcBuffer the SharedBuffer containing the source scrambled data.
+ * @param srcOffset the position where the source scrambled data starts at.
+ * @param dstBuffer the DestinationBuffer to hold the descrambled data.
+ * @param dstOffset the position where the descrambled data should start at.
+ *
+ * @return bytesWritten Number of bytes that have been successfully written.
+ */
+ int descramble(in ScramblingControl scramblingControl, in SubSample[] subSamples,
+ in SharedBuffer srcBuffer, in long srcOffset, in DestinationBuffer dstBuffer,
+ in long dstOffset);
+
+ /**
+ * Release the descrambler instance.
+ */
+ void release();
+
+ /**
+ * Query if the scrambling scheme requires the use of a secure decoder
+ * to decode data of the given mime type.
+ *
+ * @param mime the mime type of the media data.
+ * @return whether the descrambler requires a secure decoder.
+ */
+ boolean requiresSecureDecoderComponent(in String mime);
+
+ /**
+ * Associate a MediaCas session with this MediaDescrambler instance.
+ *
+ * @param sessionId the id of the session to associate with this descrambler instance.
+ */
+ void setMediaCasSession(in byte[] sessionId);
+}
diff --git a/cas/aidl/android/hardware/cas/IMediaCasService.aidl b/cas/aidl/android/hardware/cas/IMediaCasService.aidl
new file mode 100644
index 0000000..8bc31f6
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/IMediaCasService.aidl
@@ -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.
+ */
+
+package android.hardware.cas;
+
+import android.hardware.cas.AidlCasPluginDescriptor;
+import android.hardware.cas.ICas;
+import android.hardware.cas.ICasListener;
+import android.hardware.cas.IDescrambler;
+
+/**
+ * IMediaCasService is the main entry point for interacting with a vendor's
+ * cas HAL to create cas and descrambler plugin instances. A cas plugin instance
+ * opens cas sessions which are used to obtain keys for a descrambler session,
+ * which can in turn be used to descramble protected video content.
+ */
+@VintfStability
+interface IMediaCasService {
+ /**
+ * Construct a new instance of a DescramblerPlugin given a CA_system_id.
+ *
+ * @param CA_system_id the id of the CA system.
+ * @return the newly created plugin interface.
+ */
+ IDescrambler createDescrambler(in int CA_system_id);
+
+ /**
+ * Construct a new instance of a CasPlugin given a CA_system_id.
+ *
+ * @param CA_system_id the id of the CA system.
+ * @param listener the event listener to receive events coming from the CasPlugin.
+ * @return the newly created CasPlugin interface.
+ */
+ ICas createPlugin(in int CA_system_id, in ICasListener listener);
+
+ /**
+ * List all available CA systems on the device.
+ *
+ * @return an array of descriptors for the available CA systems.
+ */
+ AidlCasPluginDescriptor[] enumeratePlugins();
+
+ /**
+ * Query if the descrambling scheme for a CA system is supported on this device.
+ *
+ * @param CA_system_id the id of the CA system.
+ * @return whether the specified descrambling scheme is supported on this device.
+ */
+ boolean isDescramblerSupported(in int CA_system_id);
+
+ /**
+ * Query if a certain CA system is supported on this device.
+ *
+ * @param CA_system_id the id of the CA system.
+ * @return whether the specified CA system is supported on this device.
+ */
+ boolean isSystemIdSupported(in int CA_system_id);
+}
diff --git a/cas/aidl/android/hardware/cas/ScramblingControl.aidl b/cas/aidl/android/hardware/cas/ScramblingControl.aidl
new file mode 100644
index 0000000..b36787c
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/ScramblingControl.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.cas;
+
+/**
+ * Enumerates the keys used to scramble the content.
+ */
+@VintfStability
+@Backing(type="int")
+enum ScramblingControl {
+ UNSCRAMBLED = 0,
+ RESERVED = 1,
+ EVENKEY = 2,
+ ODDKEY = 3,
+}
diff --git a/cas/aidl/android/hardware/cas/ScramblingMode.aidl b/cas/aidl/android/hardware/cas/ScramblingMode.aidl
new file mode 100644
index 0000000..9d73eba
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/ScramblingMode.aidl
@@ -0,0 +1,98 @@
+/*
+ * 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.cas;
+
+/**
+ * The Scrambling Mode.
+ */
+@VintfStability
+@Backing(type="int")
+enum ScramblingMode {
+ RESERVED = 0,
+
+ /**
+ * DVB (Digital Video Broadcasting) CSA1 (Common Scrambling Algorithm 1) is
+ * the default mode and shall be used when the scrambling descriptor
+ * is not present in the program map section. DVB scrambling mode is
+ * specified in ETSI EN 300 468 specification.
+ */
+ DVB_CSA1,
+
+ DVB_CSA2,
+
+ /**
+ * DVB-CSA3 in standard mode.
+ */
+ DVB_CSA3_STANDARD,
+
+ /**
+ * DVB-CSA3 in minimally enhanced mode.
+ */
+ DVB_CSA3_MINIMAL,
+
+ /**
+ * DVB-CSA3 in fully enhanced mode.
+ */
+ DVB_CSA3_ENHANCE,
+
+ /**
+ * DVB-CISSA version 1.
+ */
+ DVB_CISSA_V1,
+
+ /**
+ * ATIS-0800006 IIF Default Scrambling Algorithm (IDSA).
+ */
+ DVB_IDSA,
+
+ /**
+ * a symmetric key algorithm.
+ */
+ MULTI2,
+
+ /**
+ * Advanced Encryption System (AES) 128-bit Encryption mode.
+ */
+ AES128,
+
+ /**
+ * Advanced Encryption System (AES) Cipher Block Chaining (CBC) mode.
+ */
+ AES_CBC,
+
+ /**
+ * Advanced Encryption System (AES) Electronic Code Book (ECB) mode.
+ */
+ AES_ECB,
+
+ /**
+ * Advanced Encryption System (AES) Society of Cable Telecommunications
+ * Engineers (SCTE) 52 mode.
+ */
+ AES_SCTE52,
+
+ /**
+ * Triple Data Encryption Algorithm (TDES) Electronic Code Book (ECB) mode.
+ */
+ TDES_ECB,
+
+ /**
+ * Triple Data Encryption Algorithm (TDES) Society of Cable Telecommunications
+ * Engineers (SCTE) 52 mode.
+ */
+ TDES_SCTE52,
+}
diff --git a/cas/aidl/android/hardware/cas/SessionIntent.aidl b/cas/aidl/android/hardware/cas/SessionIntent.aidl
new file mode 100644
index 0000000..844deab
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/SessionIntent.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.cas;
+
+/**
+ * The intented usage for the session.
+ */
+@VintfStability
+@Backing(type="int")
+enum SessionIntent {
+ /**
+ * Live Stream.
+ */
+ LIVE,
+
+ /**
+ * Playback Recorded Stream.
+ */
+ PLAYBACK,
+
+ /**
+ * Record Live Stream.
+ */
+ RECORD,
+
+ /**
+ * View the content with Time Shift capability
+ */
+ TIMESHIFT,
+}
diff --git a/cas/aidl/android/hardware/cas/SharedBuffer.aidl b/cas/aidl/android/hardware/cas/SharedBuffer.aidl
new file mode 100644
index 0000000..8a94ff7
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/SharedBuffer.aidl
@@ -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.
+ */
+
+package android.hardware.cas;
+
+import android.hardware.common.Ashmem;
+
+/**
+ * SharedBuffer describes a shared buffer which is defined by a heapBase, an
+ * offset and a size. The offset is relative to the shared memory base for the
+ * memory region identified by heapBase.
+ */
+@VintfStability
+parcelable SharedBuffer {
+ /**
+ * Ashmem shared memory
+ */
+ Ashmem heapBase;
+
+ /**
+ * The offset from the shared memory base
+ */
+ long offset;
+
+ /**
+ * The size of the shared buffer in bytes
+ */
+ long size;
+}
diff --git a/cas/aidl/android/hardware/cas/Status.aidl b/cas/aidl/android/hardware/cas/Status.aidl
new file mode 100644
index 0000000..b2be34b
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/Status.aidl
@@ -0,0 +1,150 @@
+/*
+ * 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.cas;
+
+@VintfStability
+parcelable Status {
+ /**
+ * The CAS plugin must return OK when an operation completes without any
+ * errors.
+ */
+ const int OK = 0;
+
+ /**
+ * The CAS plugin must return ERROR_CAS_NO_LICENSE, when descrambling is
+ * attempted and no license keys have been provided.
+ */
+ const int ERROR_CAS_NO_LICENSE = -1;
+
+ /**
+ * ERROR_CAS_LICENSE_EXPIRED must be returned when an attempt is made
+ * to use a license and the keys in that license have expired.
+ */
+ const int ERROR_CAS_LICENSE_EXPIRED = -2;
+
+ /**
+ * The CAS plugin must return ERROR_CAS_SESSION_NOT_OPENED when an
+ * attempt is made to use a session that has not been opened.
+ */
+ const int ERROR_CAS_SESSION_NOT_OPENED = -3;
+
+ /**
+ * The CAS plugin must return ERROR_CAS_CANNOT_HANDLE when an unsupported
+ * data format or operation is attempted.
+ */
+ const int ERROR_CAS_CANNOT_HANDLE = -4;
+
+ /**
+ * ERROR_CAS_INVALID_STATE must be returned when the device is in a state
+ * where it is not able to perform descrambling.
+ */
+ const int ERROR_CAS_INVALID_STATE = -5;
+
+ /**
+ * The CAS plugin must return BAD_VALUE whenever an illegal parameter is
+ * passed to one of the interface functions.
+ */
+ const int BAD_VALUE = -6;
+
+ /**
+ * The CAS plugin must return ERROR_CAS_NOT_PROVISIONED when the device
+ * has not yet been provisioned.
+ */
+ const int ERROR_CAS_NOT_PROVISIONED = -7;
+
+ /**
+ * ERROR_CAS_RESOURCE_BUSY must be returned when resources, such as CAS
+ * sessions or secure buffers are not available to perform a requested
+ * operation because they are already in use.
+ */
+ const int ERROR_CAS_RESOURCE_BUSY = -8;
+
+ /**
+ * The CAS Plugin must return ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION
+ * when the output protection level enabled on the device is not
+ * sufficient to meet the requirements in the license policy. HDCP is an
+ * example of a form of output protection.
+ */
+ const int ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION = -9;
+
+ /**
+ * The CAS Plugin must return ERROR_CAS_TAMPER_DETECTED if an attempt to
+ * tamper with the CAS system is detected.
+ */
+ const int ERROR_CAS_TAMPER_DETECTED = -10;
+
+ /**
+ * The CAS Plugin must return ERROR_CAS_DEVICE_REVOKED if the response
+ * indicates that the device has been revoked. Device revocation means
+ * that the device is no longer permitted to play content.
+ */
+ const int ERROR_CAS_DEVICE_REVOKED = -11;
+
+ /**
+ * The CAS plugin must return ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED when
+ * descrambling is failing because the session is not initialized properly.
+ */
+ const int ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED = -12;
+
+ /**
+ * The CAS Plugin must return ERROR_CAS_DECRYPT if the DescramblerPlugin's
+ * descramble operation fails.
+ */
+ const int ERROR_CAS_DECRYPT = -13;
+
+ /**
+ * ERROR_CAS_UNKNOWN must be returned when a fatal failure occurs and no
+ * other defined error is appropriate.
+ */
+ const int ERROR_CAS_UNKNOWN = -14;
+
+ /**
+ * ERROR_CAS_NEED_ACTIVATION is used to trigger device activation process.
+ */
+ const int ERROR_CAS_NEED_ACTIVATION = -15;
+
+ /**
+ * ERROR_CAS_NEED_PAIRING is used to trigger pairing process.
+ */
+ const int ERROR_CAS_NEED_PAIRING = -16;
+
+ /**
+ * ERROR_CAS_NO_CARD is used to report no smart card for descrambling.
+ */
+ const int ERROR_CAS_NO_CARD = -17;
+
+ /**
+ * ERROR_CAS_CARD_MUTE is used to report smart card is muted for
+ * descrambling.
+ */
+ const int ERROR_CAS_CARD_MUTE = -18;
+
+ /**
+ * ERROR_CAS_CARD_INVALID is used to report smart card isn't valid.
+ */
+ const int ERROR_CAS_CARD_INVALID = -19;
+
+ /**
+ * ERROR_CAS_BLACKOUT is used to report geographical blackout.
+ */
+ const int ERROR_CAS_BLACKOUT = -20;
+
+ /**
+ * ERROR_CAS_REBOOTING is used to report CAS is during rebooting.
+ */
+ const int ERROR_CAS_REBOOTING = -21;
+}
diff --git a/cas/aidl/android/hardware/cas/StatusEvent.aidl b/cas/aidl/android/hardware/cas/StatusEvent.aidl
new file mode 100644
index 0000000..0f62634
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/StatusEvent.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.
+ */
+
+package android.hardware.cas;
+
+/**
+ * The Event Type for status change.
+ */
+@VintfStability
+@Backing(type="byte")
+enum StatusEvent {
+ /**
+ * The status of CAS plugin was changed due to physical module insertion or
+ * removal. Client must call enumeratePlugins to update plugins' status.
+ */
+ PLUGIN_PHYSICAL_MODULE_CHANGED,
+
+ /**
+ * The status of supported session number was changed due to physical module
+ * insertion or removal. Client must update session resource according to
+ * latest StatusMessage from the StatusEvent. The plugin supports unlimited
+ * session by default.
+ */
+ PLUGIN_SESSION_NUMBER_CHANGED,
+}
diff --git a/cas/aidl/android/hardware/cas/SubSample.aidl b/cas/aidl/android/hardware/cas/SubSample.aidl
new file mode 100644
index 0000000..c1353cb
--- /dev/null
+++ b/cas/aidl/android/hardware/cas/SubSample.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.cas;
+
+/**
+ * A subsample consists of some number of bytes of clear (unscrambled)
+ * data followed by a number of bytes of scrambled data.
+ */
+@VintfStability
+parcelable SubSample {
+ int numBytesOfClearData;
+ int numBytesOfEncryptedData;
+}
diff --git a/cas/aidl/default/Android.bp b/cas/aidl/default/Android.bp
new file mode 100755
index 0000000..3c16d57
--- /dev/null
+++ b/cas/aidl/default/Android.bp
@@ -0,0 +1,93 @@
+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: "libcasexampleimpl",
+ vendor_available: true,
+
+ srcs: [
+ "CasImpl.cpp",
+ "DescramblerImpl.cpp",
+ "MediaCasService.cpp",
+ "SharedLibrary.cpp",
+ "TypeConvert.cpp",
+ ],
+
+ shared_libs: [
+ "android.hardware.cas-V1-ndk",
+ "libbinder_ndk",
+ "liblog",
+ "libutils",
+ "libcutils",
+ ],
+ static_libs: [
+ "libaidlcommonsupport",
+ ],
+ header_libs: [
+ "libstagefright_foundation_headers",
+ "media_plugin_headers",
+ ],
+}
+
+cc_defaults {
+ name: "cas_service_example_defaults",
+ vendor: true,
+ relative_install_path: "hw",
+
+ srcs: ["service.cpp"],
+
+ static_libs: [
+ "libaidlcommonsupport",
+ "libcasexampleimpl",
+ ],
+ shared_libs: [
+ "android.hardware.cas-V1-ndk",
+ "libbinder_ndk",
+ "liblog",
+ "libutils",
+ "libcutils",
+ ],
+ header_libs: ["media_plugin_headers"],
+ vintf_fragments: ["android.hardware.cas-service.xml"],
+}
+
+cc_binary {
+ name: "android.hardware.cas-service.example",
+ defaults: ["cas_service_example_defaults"],
+ init_rc: ["cas-default.rc"],
+}
+
+cc_binary {
+ name: "android.hardware.cas-service.example-lazy",
+ defaults: ["cas_service_example_defaults"],
+ init_rc: ["cas-default-lazy.rc"],
+ cflags: ["-DLAZY_SERVICE"],
+}
+
+cc_fuzz {
+ name: "android.hardware.cas-service_fuzzer",
+ vendor: true,
+
+ defaults: ["service_fuzzer_defaults"],
+ srcs: ["fuzzer.cpp"],
+
+ shared_libs: [
+ "android.hardware.cas-V1-ndk",
+ "libcutils",
+ "liblog",
+ ],
+ static_libs: [
+ "libaidlcommonsupport",
+ "libcasexampleimpl",
+ ],
+ header_libs: ["media_plugin_headers"],
+ fuzz_config: {
+ componentid: 1344,
+ },
+}
diff --git a/cas/aidl/default/CasImpl.cpp b/cas/aidl/default/CasImpl.cpp
new file mode 100755
index 0000000..2d31b35
--- /dev/null
+++ b/cas/aidl/default/CasImpl.cpp
@@ -0,0 +1,242 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ icensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "android.hardware.cas-CasImpl"
+
+#include <media/cas/CasAPI.h>
+#include <utils/Log.h>
+
+#include "CasImpl.h"
+#include "TypeConvert.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+CasImpl::CasImpl(const shared_ptr<ICasListener>& listener) : mListener(listener) {
+ ALOGV("CTOR");
+}
+
+CasImpl::~CasImpl() {
+ ALOGV("DTOR");
+ release();
+}
+
+// static
+void CasImpl::OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size) {
+ if (appData == NULL) {
+ ALOGE("Invalid appData!");
+ return;
+ }
+ CasImpl* casImpl = static_cast<CasImpl*>(appData);
+ casImpl->onEvent(event, arg, data, size);
+}
+
+// static
+void CasImpl::CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size,
+ const CasSessionId* sessionId) {
+ if (appData == NULL) {
+ ALOGE("Invalid appData!");
+ return;
+ }
+ CasImpl* casImpl = static_cast<CasImpl*>(appData);
+ casImpl->onEvent(sessionId, event, arg, data, size);
+}
+
+// static
+void CasImpl::StatusUpdate(void* appData, int32_t event, int32_t arg) {
+ if (appData == NULL) {
+ ALOGE("Invalid appData!");
+ return;
+ }
+ CasImpl* casImpl = static_cast<CasImpl*>(appData);
+ casImpl->onStatusUpdate(event, arg);
+}
+
+void CasImpl::init(CasPlugin* plugin) {
+ shared_ptr<CasPlugin> holder(plugin);
+ atomic_store(&mPluginHolder, holder);
+}
+
+void CasImpl::onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size) {
+ if (mListener == NULL) {
+ return;
+ }
+
+ vector<uint8_t> eventData;
+ if (data != NULL) {
+ eventData.assign(data, data + size);
+ }
+
+ mListener->onEvent(event, arg, eventData);
+}
+
+void CasImpl::onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data,
+ size_t size) {
+ if (mListener == NULL) {
+ return;
+ }
+
+ vector<uint8_t> eventData;
+ if (data != NULL) {
+ eventData.assign(data, data + size);
+ }
+
+ if (sessionId != NULL) {
+ mListener->onSessionEvent(*sessionId, event, arg, eventData);
+ } else {
+ mListener->onEvent(event, arg, eventData);
+ }
+}
+
+void CasImpl::onStatusUpdate(int32_t event, int32_t arg) {
+ if (mListener == NULL) {
+ return;
+ }
+ mListener->onStatusUpdate(static_cast<StatusEvent>(event), arg);
+}
+
+ScopedAStatus CasImpl::setPluginStatusUpdateCallback() {
+ ALOGV("%s", __FUNCTION__);
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+ return toStatus(holder->setStatusCallback(&CasImpl::StatusUpdate));
+}
+
+ScopedAStatus CasImpl::setPrivateData(const vector<uint8_t>& pvtData) {
+ ALOGV("%s", __FUNCTION__);
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+ return toStatus(holder->setPrivateData(pvtData));
+}
+
+ScopedAStatus CasImpl::openSession(SessionIntent intent, ScramblingMode mode,
+ vector<uint8_t>* sessionId) {
+ ALOGV("%s", __FUNCTION__);
+
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ status_t err = INVALID_OPERATION;
+ if (holder.get() != nullptr) {
+ err = holder->openSession(static_cast<uint32_t>(intent), static_cast<uint32_t>(mode),
+ sessionId);
+ holder.reset();
+ }
+
+ return toStatus(err);
+}
+
+ScopedAStatus CasImpl::setSessionPrivateData(const vector<uint8_t>& sessionId,
+ const vector<uint8_t>& pvtData) {
+ ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+ return toStatus(holder->setSessionPrivateData(sessionId, pvtData));
+}
+
+ScopedAStatus CasImpl::closeSession(const vector<uint8_t>& sessionId) {
+ ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+ return toStatus(holder->closeSession(sessionId));
+}
+
+ScopedAStatus CasImpl::processEcm(const vector<uint8_t>& sessionId, const vector<uint8_t>& ecm) {
+ ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(sessionId).string());
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ return toStatus(holder->processEcm(sessionId, ecm));
+}
+
+ScopedAStatus CasImpl::processEmm(const vector<uint8_t>& emm) {
+ ALOGV("%s", __FUNCTION__);
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ return toStatus(holder->processEmm(emm));
+}
+
+ScopedAStatus CasImpl::sendEvent(int32_t event, int32_t arg, const vector<uint8_t>& eventData) {
+ ALOGV("%s", __FUNCTION__);
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ status_t err = holder->sendEvent(event, arg, eventData);
+ return toStatus(err);
+}
+
+ScopedAStatus CasImpl::sendSessionEvent(const vector<uint8_t>& sessionId, int32_t event,
+ int32_t arg, const vector<uint8_t>& eventData) {
+ ALOGV("%s", __FUNCTION__);
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ status_t err = holder->sendSessionEvent(sessionId, event, arg, eventData);
+ return toStatus(err);
+}
+
+ScopedAStatus CasImpl::provision(const string& provisionString) {
+ ALOGV("%s: provisionString=%s", __FUNCTION__, provisionString.c_str());
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ return toStatus(holder->provision(String8(provisionString.c_str())));
+}
+
+ScopedAStatus CasImpl::refreshEntitlements(int32_t refreshType,
+ const vector<uint8_t>& refreshData) {
+ ALOGV("%s", __FUNCTION__);
+ shared_ptr<CasPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ status_t err = holder->refreshEntitlements(refreshType, refreshData);
+ return toStatus(err);
+}
+
+ScopedAStatus CasImpl::release() {
+ ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get());
+
+ shared_ptr<CasPlugin> holder(nullptr);
+ atomic_store(&mPluginHolder, holder);
+
+ return ScopedAStatus::ok();
+}
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/CasImpl.h b/cas/aidl/default/CasImpl.h
new file mode 100755
index 0000000..84a8115
--- /dev/null
+++ b/cas/aidl/default/CasImpl.h
@@ -0,0 +1,93 @@
+/*
+ * 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/android/hardware/cas/BnCas.h>
+#include <aidl/android/hardware/cas/ICasListener.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+using namespace ::android;
+using namespace std;
+using ndk::ScopedAStatus;
+
+class CasImpl : public BnCas {
+ public:
+ CasImpl(const shared_ptr<ICasListener>& listener);
+ virtual ~CasImpl();
+
+ static void OnEvent(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size);
+
+ static void CallBackExt(void* appData, int32_t event, int32_t arg, uint8_t* data, size_t size,
+ const CasSessionId* sessionId);
+
+ static void StatusUpdate(void* appData, int32_t event, int32_t arg);
+
+ void init(CasPlugin* plugin);
+ void onEvent(int32_t event, int32_t arg, uint8_t* data, size_t size);
+
+ void onEvent(const CasSessionId* sessionId, int32_t event, int32_t arg, uint8_t* data,
+ size_t size);
+
+ void onStatusUpdate(int32_t event, int32_t arg);
+
+ // ICas inherits
+
+ ScopedAStatus setPluginStatusUpdateCallback();
+
+ virtual ScopedAStatus setPrivateData(const vector<uint8_t>& pvtData) override;
+
+ virtual ScopedAStatus openSession(SessionIntent intent, ScramblingMode mode,
+ vector<uint8_t>* sessionId) override;
+
+ virtual ScopedAStatus closeSession(const vector<uint8_t>& sessionId) override;
+
+ virtual ScopedAStatus setSessionPrivateData(const vector<uint8_t>& sessionId,
+ const vector<uint8_t>& pvtData) override;
+
+ virtual ScopedAStatus processEcm(const vector<uint8_t>& sessionId,
+ const vector<uint8_t>& ecm) override;
+
+ virtual ScopedAStatus processEmm(const vector<uint8_t>& emm) override;
+
+ virtual ScopedAStatus sendEvent(int32_t event, int32_t arg,
+ const vector<uint8_t>& eventData) override;
+
+ virtual ScopedAStatus sendSessionEvent(const vector<uint8_t>& sessionId, int32_t event,
+ int32_t arg, const vector<uint8_t>& eventData) override;
+
+ virtual ScopedAStatus provision(const string& provisionString) override;
+
+ virtual ScopedAStatus refreshEntitlements(int32_t refreshType,
+ const vector<uint8_t>& refreshData) override;
+
+ virtual ScopedAStatus release() override;
+
+ private:
+ struct PluginHolder;
+ shared_ptr<CasPlugin> mPluginHolder;
+ shared_ptr<ICasListener> mListener;
+
+ DISALLOW_EVIL_CONSTRUCTORS(CasImpl);
+};
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/DescramblerImpl.cpp b/cas/aidl/default/DescramblerImpl.cpp
new file mode 100755
index 0000000..a96fd46
--- /dev/null
+++ b/cas/aidl/default/DescramblerImpl.cpp
@@ -0,0 +1,193 @@
+/*
+ * 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 "android.hardware.cas-DescramblerImpl"
+
+#include <aidlcommonsupport/NativeHandle.h>
+#include <inttypes.h>
+#include <media/cas/DescramblerAPI.h>
+#include <media/hardware/CryptoAPI.h>
+#include <media/stagefright/foundation/AUtils.h>
+#include <sys/mman.h>
+#include <utils/Log.h>
+
+#include "DescramblerImpl.h"
+#include "TypeConvert.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+#define CHECK_SUBSAMPLE_DEF(type) \
+ static_assert(sizeof(SubSample) == sizeof(type::SubSample), "SubSample: size doesn't match"); \
+ static_assert(offsetof(SubSample, numBytesOfClearData) == \
+ offsetof(type::SubSample, mNumBytesOfClearData), \
+ "SubSample: numBytesOfClearData offset doesn't match"); \
+ static_assert(offsetof(SubSample, numBytesOfEncryptedData) == \
+ offsetof(type::SubSample, mNumBytesOfEncryptedData), \
+ "SubSample: numBytesOfEncryptedData offset doesn't match")
+
+CHECK_SUBSAMPLE_DEF(DescramblerPlugin);
+CHECK_SUBSAMPLE_DEF(CryptoPlugin);
+
+DescramblerImpl::DescramblerImpl(DescramblerPlugin* plugin) : mPluginHolder(plugin) {
+ ALOGV("CTOR: plugin=%p", mPluginHolder.get());
+}
+
+DescramblerImpl::~DescramblerImpl() {
+ ALOGV("DTOR: plugin=%p", mPluginHolder.get());
+ release();
+}
+
+ScopedAStatus DescramblerImpl::setMediaCasSession(const vector<uint8_t>& in_sessionId) {
+ ALOGV("%s: sessionId=%s", __FUNCTION__, sessionIdToString(in_sessionId).string());
+
+ shared_ptr<DescramblerPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ return toStatus(holder->setMediaCasSession(in_sessionId));
+}
+
+ScopedAStatus DescramblerImpl::requiresSecureDecoderComponent(const string& in_mime,
+ bool* _aidl_return) {
+ shared_ptr<DescramblerPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ *_aidl_return = false;
+ }
+
+ *_aidl_return = holder->requiresSecureDecoderComponent(String8(in_mime.c_str()));
+ return ScopedAStatus::ok();
+}
+
+static inline bool validateRangeForSize(int64_t offset, int64_t length, int64_t size) {
+ return isInRange<int64_t, uint64_t>(0, (uint64_t)size, offset, (uint64_t)length);
+}
+
+ScopedAStatus DescramblerImpl::descramble(ScramblingControl scramblingControl,
+ const vector<SubSample>& subSamples,
+ const SharedBuffer& srcBuffer, int64_t srcOffset,
+ const DestinationBuffer& dstBuffer, int64_t dstOffset,
+ int32_t* _aidl_return) {
+ ALOGV("%s", __FUNCTION__);
+
+ // heapbase's size is stored in int64_t, but mapMemory's mmap will map size in
+ // size_t. If size is over SIZE_MAX, mapMemory mapMemory could succeed but the
+ // mapped memory's actual size will be smaller than the reported size.
+ if (srcBuffer.heapBase.size > SIZE_MAX) {
+ ALOGE("Invalid memory size: %" PRIu64 "", srcBuffer.heapBase.size);
+ android_errorWriteLog(0x534e4554, "79376389");
+ return toStatus(BAD_VALUE);
+ }
+
+ void* srcPtr = mmap(NULL, srcBuffer.heapBase.size, PROT_READ | PROT_WRITE, MAP_SHARED,
+ srcBuffer.heapBase.fd.get(), 0);
+
+ // Validate if the offset and size in the SharedBuffer is consistent with the
+ // mapped heapbase, since the offset and size is controlled by client.
+ if (srcPtr == NULL) {
+ ALOGE("Failed to map src buffer.");
+ return toStatus(BAD_VALUE);
+ }
+ if (!validateRangeForSize(srcBuffer.offset, srcBuffer.size, srcBuffer.heapBase.size)) {
+ ALOGE("Invalid src buffer range: offset %" PRIu64 ", size %" PRIu64
+ ", srcMem"
+ "size %" PRIu64 "",
+ srcBuffer.offset, srcBuffer.size, srcBuffer.heapBase.size);
+ android_errorWriteLog(0x534e4554, "67962232");
+ return toStatus(BAD_VALUE);
+ }
+
+ // use 64-bit here to catch bad subsample size that might be overflowing.
+ uint64_t totalBytesInSubSamples = 0;
+ for (size_t i = 0; i < subSamples.size(); i++) {
+ uint32_t numBytesOfClearData = subSamples[i].numBytesOfClearData;
+ uint32_t numBytesOfEncryptedData = subSamples[i].numBytesOfEncryptedData;
+ totalBytesInSubSamples += (uint64_t)numBytesOfClearData + numBytesOfEncryptedData;
+ }
+ // Further validate if the specified srcOffset and requested total subsample size
+ // is consistent with the source shared buffer size.
+ if (!validateRangeForSize(srcOffset, totalBytesInSubSamples, srcBuffer.size)) {
+ ALOGE("Invalid srcOffset and subsample size: "
+ "srcOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64
+ ", srcBuffer"
+ "size %" PRIu64 "",
+ srcOffset, totalBytesInSubSamples, srcBuffer.size);
+ android_errorWriteLog(0x534e4554, "67962232");
+ return toStatus(BAD_VALUE);
+ }
+ srcPtr = (uint8_t*)srcPtr + srcBuffer.offset;
+
+ void* dstPtr = NULL;
+ if (dstBuffer.getTag() == DestinationBuffer::Tag::nonsecureMemory) {
+ // When using shared memory, src buffer is also used as dst,
+ // we don't map it again here.
+ dstPtr = srcPtr;
+
+ // In this case the dst and src would be the same buffer, need to validate
+ // dstOffset against the buffer size too.
+ if (!validateRangeForSize(dstOffset, totalBytesInSubSamples, srcBuffer.size)) {
+ ALOGE("Invalid dstOffset and subsample size: "
+ "dstOffset %" PRIu64 ", totalBytesInSubSamples %" PRIu64
+ ", srcBuffer"
+ "size %" PRIu64 "",
+ dstOffset, totalBytesInSubSamples, srcBuffer.size);
+ android_errorWriteLog(0x534e4554, "67962232");
+ return toStatus(BAD_VALUE);
+ }
+ } else {
+ native_handle_t* handle = makeFromAidl(dstBuffer.get<DestinationBuffer::secureMemory>());
+ dstPtr = static_cast<void*>(handle);
+ }
+
+ // Get a local copy of the shared_ptr for the plugin. Note that before
+ // calling the callback, this shared_ptr must be manually reset, since
+ // the client side could proceed as soon as the callback is called
+ // without waiting for this method to go out of scope.
+ shared_ptr<DescramblerPlugin> holder = atomic_load(&mPluginHolder);
+ if (holder.get() == nullptr) {
+ return toStatus(INVALID_OPERATION);
+ }
+
+ // Casting SubSample to DescramblerPlugin::SubSample, but need to ensure
+ // structs are actually identical
+
+ auto returnStatus =
+ holder->descramble(dstBuffer.getTag() != DestinationBuffer::Tag::nonsecureMemory,
+ (DescramblerPlugin::ScramblingControl)scramblingControl,
+ subSamples.size(), (DescramblerPlugin::SubSample*)subSamples.data(),
+ srcPtr, srcOffset, dstPtr, dstOffset, NULL);
+
+ holder.reset();
+ *_aidl_return = returnStatus;
+ return toStatus(returnStatus >= 0 ? OK : returnStatus);
+}
+
+ScopedAStatus DescramblerImpl::release() {
+ ALOGV("%s: plugin=%p", __FUNCTION__, mPluginHolder.get());
+
+ shared_ptr<DescramblerPlugin> holder(nullptr);
+ atomic_store(&mPluginHolder, holder);
+
+ return ScopedAStatus::ok();
+}
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/DescramblerImpl.h b/cas/aidl/default/DescramblerImpl.h
new file mode 100755
index 0000000..2efc1a0
--- /dev/null
+++ b/cas/aidl/default/DescramblerImpl.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.
+ */
+
+#include <aidl/android/hardware/cas/BnDescrambler.h>
+#include <media/stagefright/foundation/ABase.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+using namespace ::android;
+using namespace std;
+using ndk::ScopedAStatus;
+
+class DescramblerImpl : public BnDescrambler {
+ public:
+ DescramblerImpl(DescramblerPlugin* plugin);
+ virtual ~DescramblerImpl();
+
+ virtual ScopedAStatus setMediaCasSession(const vector<uint8_t>& in_sessionId) override;
+
+ virtual ScopedAStatus requiresSecureDecoderComponent(const string& in_mime,
+ bool* _aidl_return) override;
+
+ virtual ScopedAStatus descramble(ScramblingControl in_scramblingControl,
+ const vector<SubSample>& in_subSamples,
+ const SharedBuffer& in_srcBuffer, int64_t in_srcOffset,
+ const DestinationBuffer& in_dstBuffer, int64_t in_dstOffset,
+ int32_t* _aidl_return) override;
+
+ virtual ScopedAStatus release() override;
+
+ private:
+ shared_ptr<DescramblerPlugin> mPluginHolder;
+
+ DISALLOW_EVIL_CONSTRUCTORS(DescramblerImpl);
+};
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/FactoryLoader.h b/cas/aidl/default/FactoryLoader.h
new file mode 100755
index 0000000..f90b109
--- /dev/null
+++ b/cas/aidl/default/FactoryLoader.h
@@ -0,0 +1,219 @@
+/*
+ * 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 <dirent.h>
+#include <dlfcn.h>
+#include <media/cas/CasAPI.h>
+#include <utils/KeyedVector.h>
+#include <utils/Mutex.h>
+#include "SharedLibrary.h"
+
+using namespace std;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+using namespace ::android;
+
+template <class T>
+class FactoryLoader {
+ public:
+ FactoryLoader(const char* name) : mFactory(NULL), mCreateFactoryFuncName(name) {}
+
+ virtual ~FactoryLoader() { closeFactory(); }
+
+ bool findFactoryForScheme(int32_t CA_system_id, shared_ptr<SharedLibrary>* library = NULL,
+ T** factory = NULL);
+
+ bool enumeratePlugins(vector<AidlCasPluginDescriptor>* results);
+
+ private:
+ typedef T* (*CreateFactoryFunc)();
+
+ Mutex mMapLock;
+ T* mFactory;
+ const char* mCreateFactoryFuncName;
+ shared_ptr<SharedLibrary> mLibrary;
+ KeyedVector<int32_t, String8> mCASystemIdToLibraryPathMap;
+ KeyedVector<String8, shared_ptr<SharedLibrary>> mLibraryPathToOpenLibraryMap;
+
+ bool loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id,
+ shared_ptr<SharedLibrary>* library, T** factory);
+
+ bool queryPluginsFromPath(const String8& path, vector<AidlCasPluginDescriptor>* results);
+
+ bool openFactory(const String8& path);
+ void closeFactory();
+};
+
+template <class T>
+bool FactoryLoader<T>::findFactoryForScheme(int32_t CA_system_id,
+ shared_ptr<SharedLibrary>* library, T** factory) {
+ if (library != NULL) {
+ library->reset();
+ }
+ if (factory != NULL) {
+ *factory = NULL;
+ }
+
+ Mutex::Autolock autoLock(mMapLock);
+
+ // first check cache
+ ssize_t index = mCASystemIdToLibraryPathMap.indexOfKey(CA_system_id);
+ if (index >= 0) {
+ return loadFactoryForSchemeFromPath(mCASystemIdToLibraryPathMap[index], CA_system_id,
+ library, factory);
+ }
+
+ // no luck, have to search
+#ifdef __LP64__
+ String8 dirPath("/vendor/lib64/mediacas");
+#else
+ String8 dirPath("/vendor/lib/mediacas");
+#endif
+ DIR* pDir = opendir(dirPath.string());
+
+ if (pDir == NULL) {
+ ALOGE("Failed to open plugin directory %s", dirPath.string());
+ return false;
+ }
+
+ struct dirent* pEntry;
+ while ((pEntry = readdir(pDir))) {
+ String8 pluginPath = dirPath + "/" + pEntry->d_name;
+ if (pluginPath.getPathExtension() == ".so") {
+ if (loadFactoryForSchemeFromPath(pluginPath, CA_system_id, library, factory)) {
+ mCASystemIdToLibraryPathMap.add(CA_system_id, pluginPath);
+ closedir(pDir);
+
+ return true;
+ }
+ }
+ }
+
+ closedir(pDir);
+
+ ALOGE("Failed to find plugin");
+ return false;
+}
+
+template <class T>
+bool FactoryLoader<T>::enumeratePlugins(vector<AidlCasPluginDescriptor>* results) {
+ ALOGI("enumeratePlugins");
+
+ results->clear();
+
+#ifdef __LP64__
+ String8 dirPath("/vendor/lib64/mediacas");
+#else
+ String8 dirPath("/vendor/lib/mediacas");
+#endif
+ DIR* pDir = opendir(dirPath.string());
+
+ if (pDir == NULL) {
+ ALOGE("Failed to open plugin directory %s", dirPath.string());
+ return false;
+ }
+
+ Mutex::Autolock autoLock(mMapLock);
+
+ struct dirent* pEntry;
+ while ((pEntry = readdir(pDir))) {
+ String8 pluginPath = dirPath + "/" + pEntry->d_name;
+ if (pluginPath.getPathExtension() == ".so") {
+ queryPluginsFromPath(pluginPath, results);
+ }
+ }
+ return true;
+}
+
+template <class T>
+bool FactoryLoader<T>::loadFactoryForSchemeFromPath(const String8& path, int32_t CA_system_id,
+ shared_ptr<SharedLibrary>* library,
+ T** factory) {
+ closeFactory();
+
+ if (!openFactory(path) || !mFactory->isSystemIdSupported(CA_system_id)) {
+ closeFactory();
+ return false;
+ }
+
+ if (library != NULL) {
+ *library = mLibrary;
+ }
+ if (factory != NULL) {
+ *factory = mFactory;
+ }
+ return true;
+}
+
+template <class T>
+bool FactoryLoader<T>::queryPluginsFromPath(const String8& path,
+ vector<AidlCasPluginDescriptor>* results) {
+ closeFactory();
+
+ vector<CasPluginDescriptor> descriptors;
+ if (!openFactory(path) || mFactory->queryPlugins(&descriptors) != OK) {
+ closeFactory();
+ return false;
+ }
+
+ for (auto it = descriptors.begin(); it != descriptors.end(); it++) {
+ results->push_back(
+ AidlCasPluginDescriptor{.caSystemId = it->CA_system_id, .name = it->name.c_str()});
+ }
+ return true;
+}
+
+template <class T>
+bool FactoryLoader<T>::openFactory(const String8& path) {
+ // get strong pointer to open shared library
+ ssize_t index = mLibraryPathToOpenLibraryMap.indexOfKey(path);
+ if (index >= 0) {
+ mLibrary = mLibraryPathToOpenLibraryMap[index];
+ } else {
+ index = mLibraryPathToOpenLibraryMap.add(path, NULL);
+ }
+
+ if (!mLibrary.get()) {
+ mLibrary = ::ndk::SharedRefBase::make<SharedLibrary>(path);
+ if (!*mLibrary) {
+ return false;
+ }
+
+ mLibraryPathToOpenLibraryMap.replaceValueAt(index, mLibrary);
+ }
+
+ CreateFactoryFunc createFactory = (CreateFactoryFunc)mLibrary->lookup(mCreateFactoryFuncName);
+ if (createFactory == NULL || (mFactory = createFactory()) == NULL) {
+ return false;
+ }
+ return true;
+}
+
+template <class T>
+void FactoryLoader<T>::closeFactory() {
+ delete mFactory;
+ mFactory = NULL;
+ mLibrary.reset();
+}
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/MediaCasService.cpp b/cas/aidl/default/MediaCasService.cpp
new file mode 100755
index 0000000..8285613
--- /dev/null
+++ b/cas/aidl/default/MediaCasService.cpp
@@ -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.
+ */
+
+#define LOG_TAG "android.hardware.cas-MediaCasService"
+
+#include <media/cas/CasAPI.h>
+#include <media/cas/DescramblerAPI.h>
+#include <utils/Log.h>
+
+#include "CasImpl.h"
+#include "DescramblerImpl.h"
+#include "MediaCasService.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+MediaCasService::MediaCasService()
+ : mCasLoader("createCasFactory"), mDescramblerLoader("createDescramblerFactory") {}
+
+MediaCasService::~MediaCasService() {}
+
+ScopedAStatus MediaCasService::enumeratePlugins(
+ vector<AidlCasPluginDescriptor>* aidlCasPluginDescriptors) {
+ ALOGV("%s", __FUNCTION__);
+
+ mCasLoader.enumeratePlugins(aidlCasPluginDescriptors);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus MediaCasService::isSystemIdSupported(int32_t CA_system_id, bool* _aidl_return) {
+ ALOGV("isSystemIdSupported: CA_system_id=%d", CA_system_id);
+
+ *_aidl_return = mCasLoader.findFactoryForScheme(CA_system_id);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus MediaCasService::createPlugin(int32_t CA_system_id,
+ const shared_ptr<ICasListener>& listener,
+ shared_ptr<ICas>* _aidl_return) {
+ ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+ if (listener == NULL) ALOGV("%s: Listener is NULL", __FUNCTION__);
+
+ CasFactory* factory;
+ shared_ptr<SharedLibrary> library;
+ if (mCasLoader.findFactoryForScheme(CA_system_id, &library, &factory)) {
+ CasPlugin* plugin = NULL;
+ shared_ptr<CasImpl> casImpl = ::ndk::SharedRefBase::make<CasImpl>(listener);
+ if (factory->createPlugin(CA_system_id, casImpl.get(), &CasImpl::CallBackExt, &plugin) ==
+ OK &&
+ plugin != NULL) {
+ casImpl->init(plugin);
+ *_aidl_return = casImpl;
+ casImpl->setPluginStatusUpdateCallback();
+ }
+ }
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus MediaCasService::isDescramblerSupported(int32_t CA_system_id, bool* _aidl_return) {
+ ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+ *_aidl_return = mDescramblerLoader.findFactoryForScheme(CA_system_id);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus MediaCasService::createDescrambler(int32_t CA_system_id,
+ shared_ptr<IDescrambler>* _aidl_return) {
+ ALOGV("%s: CA_system_id=%d", __FUNCTION__, CA_system_id);
+
+ DescramblerFactory* factory;
+ shared_ptr<SharedLibrary> library;
+ if (mDescramblerLoader.findFactoryForScheme(CA_system_id, &library, &factory)) {
+ DescramblerPlugin* plugin = NULL;
+ if (factory->createPlugin(CA_system_id, &plugin) == OK && plugin != NULL) {
+ *_aidl_return = ::ndk::SharedRefBase::make<DescramblerImpl>(plugin);
+ }
+ }
+
+ return ScopedAStatus::ok();
+}
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/MediaCasService.h b/cas/aidl/default/MediaCasService.h
new file mode 100755
index 0000000..9662313
--- /dev/null
+++ b/cas/aidl/default/MediaCasService.h
@@ -0,0 +1,59 @@
+/*
+ * 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/android/hardware/cas/BnMediaCasService.h>
+#include <media/cas/DescramblerAPI.h>
+
+#include "FactoryLoader.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+using namespace ::android;
+using namespace std;
+using ndk::ScopedAStatus;
+
+class MediaCasService : public BnMediaCasService {
+ public:
+ MediaCasService();
+
+ virtual ScopedAStatus enumeratePlugins(
+ vector<AidlCasPluginDescriptor>* aidlCasPluginDescriptors) override;
+
+ virtual ScopedAStatus isSystemIdSupported(int32_t in_CA_system_id, bool* _aidl_return) override;
+
+ virtual ScopedAStatus createPlugin(int32_t in_CA_system_id,
+ const shared_ptr<ICasListener>& in_listener,
+ shared_ptr<ICas>* _aidl_return) override;
+
+ virtual ScopedAStatus isDescramblerSupported(int32_t in_CA_system_id,
+ bool* _aidl_return) override;
+
+ virtual ScopedAStatus createDescrambler(int32_t in_CA_system_id,
+ shared_ptr<IDescrambler>* _aidl_return) override;
+
+ private:
+ FactoryLoader<CasFactory> mCasLoader;
+ FactoryLoader<DescramblerFactory> mDescramblerLoader;
+
+ virtual ~MediaCasService();
+};
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/OWNERS b/cas/aidl/default/OWNERS
new file mode 100755
index 0000000..4c55752
--- /dev/null
+++ b/cas/aidl/default/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 1344
+quxiangfang@google.com
+hgchen@google.com
diff --git a/cas/aidl/default/SharedLibrary.cpp b/cas/aidl/default/SharedLibrary.cpp
new file mode 100755
index 0000000..e79f383
--- /dev/null
+++ b/cas/aidl/default/SharedLibrary.cpp
@@ -0,0 +1,61 @@
+/*
+ * 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 "android.hardware.cas-SharedLibrary"
+
+#include "SharedLibrary.h"
+#include <dlfcn.h>
+#include <utils/Log.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+SharedLibrary::SharedLibrary(const String8& path) {
+ mLibHandle = dlopen(path.string(), RTLD_NOW);
+}
+
+SharedLibrary::~SharedLibrary() {
+ if (mLibHandle != NULL) {
+ dlclose(mLibHandle);
+ mLibHandle = NULL;
+ }
+}
+
+bool SharedLibrary::operator!() const {
+ return mLibHandle == NULL;
+}
+
+void* SharedLibrary::lookup(const char* symbol) const {
+ if (!mLibHandle) {
+ return NULL;
+ }
+ // Clear last error before we load the symbol again,
+ // in case the caller didn't retrieve it.
+ (void)dlerror();
+ return dlsym(mLibHandle, symbol);
+}
+
+const char* SharedLibrary::lastError() const {
+ const char* error = dlerror();
+ return error ? error : "No errors or unknown error";
+}
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/SharedLibrary.h b/cas/aidl/default/SharedLibrary.h
new file mode 100755
index 0000000..d367866
--- /dev/null
+++ b/cas/aidl/default/SharedLibrary.h
@@ -0,0 +1,45 @@
+/*
+ * 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/binder_interface_utils.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <utils/String8.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+using namespace ::android;
+
+class SharedLibrary : public ndk::SharedRefBase {
+ public:
+ explicit SharedLibrary(const String8& path);
+ ~SharedLibrary();
+
+ bool operator!() const;
+ void* lookup(const char* symbol) const;
+ const char* lastError() const;
+
+ private:
+ void* mLibHandle;
+ DISALLOW_EVIL_CONSTRUCTORS(SharedLibrary);
+};
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/TypeConvert.cpp b/cas/aidl/default/TypeConvert.cpp
new file mode 100755
index 0000000..4f7005f
--- /dev/null
+++ b/cas/aidl/default/TypeConvert.cpp
@@ -0,0 +1,110 @@
+/*
+ * 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 "android.hardware.cas-TypeConvert"
+
+#include <aidl/android/hardware/cas/Status.h>
+#include <utils/Log.h>
+
+#include "TypeConvert.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+ScopedAStatus toStatus(status_t legacyStatus) {
+ int status;
+ switch (legacyStatus) {
+ case OK:
+ return ndk::ScopedAStatus::ok();
+ case ERROR_CAS_NO_LICENSE:
+ status = Status::ERROR_CAS_NO_LICENSE;
+ break;
+ case ERROR_CAS_LICENSE_EXPIRED:
+ status = Status::ERROR_CAS_LICENSE_EXPIRED;
+ break;
+ case ERROR_CAS_SESSION_NOT_OPENED:
+ status = Status::ERROR_CAS_SESSION_NOT_OPENED;
+ break;
+ case ERROR_CAS_CANNOT_HANDLE:
+ status = Status::ERROR_CAS_CANNOT_HANDLE;
+ break;
+ case ERROR_CAS_TAMPER_DETECTED:
+ status = Status::ERROR_CAS_INVALID_STATE;
+ break;
+ case BAD_VALUE:
+ status = Status::BAD_VALUE;
+ break;
+ case ERROR_CAS_NOT_PROVISIONED:
+ status = Status::ERROR_CAS_NOT_PROVISIONED;
+ break;
+ case ERROR_CAS_RESOURCE_BUSY:
+ status = Status::ERROR_CAS_RESOURCE_BUSY;
+ break;
+ case ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION:
+ status = Status::ERROR_CAS_INSUFFICIENT_OUTPUT_PROTECTION;
+ break;
+ case ERROR_CAS_DEVICE_REVOKED:
+ status = Status::ERROR_CAS_DEVICE_REVOKED;
+ break;
+ case ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED:
+ status = Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED;
+ break;
+ case ERROR_CAS_DECRYPT:
+ status = Status::ERROR_CAS_DECRYPT;
+ break;
+ case ERROR_CAS_NEED_ACTIVATION:
+ status = Status::ERROR_CAS_NEED_ACTIVATION;
+ break;
+ case ERROR_CAS_NEED_PAIRING:
+ status = Status::ERROR_CAS_NEED_PAIRING;
+ break;
+ case ERROR_CAS_NO_CARD:
+ status = Status::ERROR_CAS_NO_CARD;
+ break;
+ case ERROR_CAS_CARD_MUTE:
+ status = Status::ERROR_CAS_CARD_MUTE;
+ break;
+ case ERROR_CAS_CARD_INVALID:
+ status = Status::ERROR_CAS_CARD_INVALID;
+ break;
+ case ERROR_CAS_BLACKOUT:
+ status = Status::ERROR_CAS_BLACKOUT;
+ break;
+ default:
+ ALOGW("Unable to convert legacy status: %d, defaulting to UNKNOWN", legacyStatus);
+ status = Status::ERROR_CAS_UNKNOWN;
+ break;
+ }
+ return ScopedAStatus::fromServiceSpecificError(status);
+}
+
+String8 sessionIdToString(const std::vector<uint8_t>& sessionId) {
+ String8 result;
+ for (auto it = sessionId.begin(); it != sessionId.end(); it++) {
+ result.appendFormat("%02x ", *it);
+ }
+ if (result.isEmpty()) {
+ result.append("(null)");
+ }
+ return result;
+}
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/TypeConvert.h b/cas/aidl/default/TypeConvert.h
new file mode 100755
index 0000000..ebfa286
--- /dev/null
+++ b/cas/aidl/default/TypeConvert.h
@@ -0,0 +1,36 @@
+/*
+ * 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/binder_interface_utils.h>
+#include <media/stagefright/MediaErrors.h>
+#include <utils/String8.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace cas {
+
+using namespace ::android;
+using ndk::ScopedAStatus;
+
+ScopedAStatus toStatus(status_t legacyStatus);
+
+String8 sessionIdToString(const std::vector<uint8_t>& sessionId);
+
+} // namespace cas
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/cas/aidl/default/android.hardware.cas-service.xml b/cas/aidl/default/android.hardware.cas-service.xml
new file mode 100755
index 0000000..6389fe2
--- /dev/null
+++ b/cas/aidl/default/android.hardware.cas-service.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.cas</name>
+ <fqname>IMediaCasService/default</fqname>
+ </hal>
+</manifest>
diff --git a/cas/aidl/default/cas-default-lazy.rc b/cas/aidl/default/cas-default-lazy.rc
new file mode 100755
index 0000000..60b59ca
--- /dev/null
+++ b/cas/aidl/default/cas-default-lazy.rc
@@ -0,0 +1,9 @@
+service vendor.cas-default-lazy /vendor/bin/hw/android.hardware.cas-service.example-lazy
+ interface aidl android.hardware.cas.IMediaCasService/default
+ class hal
+ user media
+ group mediadrm drmrpc
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh
+ oneshot
+ disabled
diff --git a/cas/aidl/default/cas-default.rc b/cas/aidl/default/cas-default.rc
new file mode 100755
index 0000000..e00b9c5
--- /dev/null
+++ b/cas/aidl/default/cas-default.rc
@@ -0,0 +1,7 @@
+service vendor.cas-default /vendor/bin/hw/android.hardware.cas-service.example
+ interface aidl android.hardware.cas.IMediaCasService/default
+ class hal
+ user media
+ group mediadrm drmrpc
+ ioprio rt 4
+ task_profiles ProcessCapacityHigh
diff --git a/cas/aidl/default/fuzzer.cpp b/cas/aidl/default/fuzzer.cpp
new file mode 100755
index 0000000..db1369e
--- /dev/null
+++ b/cas/aidl/default/fuzzer.cpp
@@ -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.
+ */
+#include <MediaCasService.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using aidl::android::hardware::cas::MediaCasService;
+using android::fuzzService;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto mediaCasServiceAidl = SharedRefBase::make<MediaCasService>();
+
+ fuzzService(mediaCasServiceAidl->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
\ No newline at end of file
diff --git a/cas/aidl/default/service.cpp b/cas/aidl/default/service.cpp
new file mode 100755
index 0000000..bed2f01
--- /dev/null
+++ b/cas/aidl/default/service.cpp
@@ -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.
+ */
+
+#ifdef LAZY_SERVICE
+const bool kLazyService = true;
+#define LOG_TAG "android.hardware.cas-service.example-lazy"
+#else
+const bool kLazyService = false;
+#define LOG_TAG "android.hardware.cas-service.example"
+#endif
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+#include "MediaCasService.h"
+
+using aidl::android::hardware::cas::MediaCasService;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(8);
+
+ // Setup hwbinder service
+ std::shared_ptr<MediaCasService> service = ::ndk::SharedRefBase::make<MediaCasService>();
+
+ const std::string instance = std::string() + MediaCasService::descriptor + "/default";
+ binder_status_t status;
+
+ if (kLazyService) {
+ status = AServiceManager_registerLazyService(service->asBinder().get(), instance.c_str());
+ } else {
+ status = AServiceManager_addService(service->asBinder().get(), instance.c_str());
+ }
+ LOG_ALWAYS_FATAL_IF(status != STATUS_OK, "Error while registering cas service: %d", status);
+
+ ABinderProcess_joinThreadPool();
+ return 0;
+}
diff --git a/cas/aidl/vts/functional/Android.bp b/cas/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..295ae7c
--- /dev/null
+++ b/cas/aidl/vts/functional/Android.bp
@@ -0,0 +1,45 @@
+//
+// 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_test {
+ name: "VtsHalCasAidlTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalCasAidlTargetTest.cpp"],
+ static_libs: [
+ "android.hardware.cas-V1-ndk",
+ "android.hardware.common-V2-ndk",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ disable_framework: true,
+}
diff --git a/cas/aidl/vts/functional/OWNERS b/cas/aidl/vts/functional/OWNERS
new file mode 100644
index 0000000..4c55752
--- /dev/null
+++ b/cas/aidl/vts/functional/OWNERS
@@ -0,0 +1,3 @@
+# Bug component: 1344
+quxiangfang@google.com
+hgchen@google.com
diff --git a/cas/aidl/vts/functional/VtsHalCasAidlTargetTest.cpp b/cas/aidl/vts/functional/VtsHalCasAidlTargetTest.cpp
new file mode 100644
index 0000000..266b55d
--- /dev/null
+++ b/cas/aidl/vts/functional/VtsHalCasAidlTargetTest.cpp
@@ -0,0 +1,809 @@
+/*
+ * 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 "mediacas_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/cas/BnCasListener.h>
+#include <aidl/android/hardware/cas/IMediaCasService.h>
+#include <aidl/android/hardware/cas/Status.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <binder/ParcelFileDescriptor.h>
+#include <cutils/ashmem.h>
+#include <utils/Condition.h>
+#include <utils/Mutex.h>
+
+#define CLEAR_KEY_SYSTEM_ID 0xF6D8
+#define INVALID_SYSTEM_ID 0
+#define WAIT_TIMEOUT 3000000000
+
+#define PROVISION_STR \
+ "{ " \
+ " \"id\": 21140844, " \
+ " \"name\": \"Test Title\", " \
+ " \"lowercase_organization_name\": \"Android\", " \
+ " \"asset_key\": { " \
+ " \"encryption_key\": \"nezAr3CHFrmBR9R8Tedotw==\" " \
+ " }, " \
+ " \"cas_type\": 1, " \
+ " \"track_types\": [ ] " \
+ "} "
+
+using aidl::android::hardware::common::Ashmem;
+using android::Mutex;
+using namespace aidl::android::hardware::cas;
+using namespace ndk;
+using namespace std;
+using namespace testing;
+
+const uint8_t kEcmBinaryBuffer[] = {
+ 0x00, 0x00, 0x01, 0xf0, 0x00, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x46, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x27, 0x10, 0x02, 0x00,
+ 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0x0e, 0xe3, 0x91, 0xbc, 0xfd, 0x05, 0xb1, 0x60, 0x4f,
+ 0x17, 0x82, 0xa4, 0x86, 0x9b, 0x23, 0x56, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x27, 0x10, 0x02, 0x00, 0x01, 0x77, 0x01, 0x42, 0x95, 0x6c, 0xd7, 0x43, 0x62, 0xf8, 0x1c,
+ 0x62, 0x19, 0x05, 0xc7, 0x3a, 0x42, 0xcd, 0xfd, 0xd9, 0x13, 0x48,
+};
+
+const SubSample kSubSamples[] = {{162, 0}, {0, 184}, {0, 184}};
+
+const uint8_t kInBinaryBuffer[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
+ 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
+ 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
+ 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
+ 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
+ 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
+ 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
+ 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
+ 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
+ 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x6e, 0x45, 0x21,
+ 0x82, 0x38, 0xf0, 0x9d, 0x7d, 0x96, 0xe6, 0x94, 0xae, 0xe2, 0x87, 0x8f, 0x04, 0x49, 0xe5,
+ 0xf6, 0x8c, 0x8b, 0x9a, 0x10, 0x18, 0xba, 0x94, 0xe9, 0x22, 0x31, 0x04, 0x7e, 0x60, 0x5b,
+ 0xc4, 0x24, 0x00, 0x90, 0x62, 0x0d, 0xdc, 0x85, 0x74, 0x75, 0x78, 0xd0, 0x14, 0x08, 0xcb,
+ 0x02, 0x1d, 0x7d, 0x9d, 0x34, 0xe8, 0x81, 0xb9, 0xf7, 0x09, 0x28, 0x79, 0x29, 0x8d, 0xe3,
+ 0x14, 0xed, 0x5f, 0xca, 0xaf, 0xf4, 0x1c, 0x49, 0x15, 0xe1, 0x80, 0x29, 0x61, 0x76, 0x80,
+ 0x43, 0xf8, 0x58, 0x53, 0x40, 0xd7, 0x31, 0x6d, 0x61, 0x81, 0x41, 0xe9, 0x77, 0x9f, 0x9c,
+ 0xe1, 0x6d, 0xf2, 0xee, 0xd9, 0xc8, 0x67, 0xd2, 0x5f, 0x48, 0x73, 0xe3, 0x5c, 0xcd, 0xa7,
+ 0x45, 0x58, 0xbb, 0xdd, 0x28, 0x1d, 0x68, 0xfc, 0xb4, 0xc6, 0xf6, 0x92, 0xf6, 0x30, 0x03,
+ 0xaa, 0xe4, 0x32, 0xf6, 0x34, 0x51, 0x4b, 0x0f, 0x8c, 0xf9, 0xac, 0x98, 0x22, 0xfb, 0x49,
+ 0xc8, 0xbf, 0xca, 0x8c, 0x80, 0x86, 0x5d, 0xd7, 0xa4, 0x52, 0xb1, 0xd9, 0xa6, 0x04, 0x4e,
+ 0xb3, 0x2d, 0x1f, 0xb8, 0x35, 0xcc, 0x45, 0x6d, 0x9c, 0x20, 0xa7, 0xa4, 0x34, 0x59, 0x72,
+ 0xe3, 0xae, 0xba, 0x49, 0xde, 0xd1, 0xaa, 0xee, 0x3d, 0x77, 0xfc, 0x5d, 0xc6, 0x1f, 0x9d,
+ 0xac, 0xc2, 0x15, 0x66, 0xb8, 0xe1, 0x54, 0x4e, 0x74, 0x93, 0xdb, 0x9a, 0x24, 0x15, 0x6e,
+ 0x20, 0xa3, 0x67, 0x3e, 0x5a, 0x24, 0x41, 0x5e, 0xb0, 0xe6, 0x35, 0x87, 0x1b, 0xc8, 0x7a,
+ 0xf9, 0x77, 0x65, 0xe0, 0x01, 0xf2, 0x4c, 0xe4, 0x2b, 0xa9, 0x64, 0x96, 0x96, 0x0b, 0x46,
+ 0xca, 0xea, 0x79, 0x0e, 0x78, 0xa3, 0x5f, 0x43, 0xfc, 0x47, 0x6a, 0x12, 0xfa, 0xc4, 0x33,
+ 0x0e, 0x88, 0x1c, 0x19, 0x3a, 0x00, 0xc3, 0x4e, 0xb5, 0xd8, 0xfa, 0x8e, 0xf1, 0xbc, 0x3d,
+ 0xb2, 0x7e, 0x50, 0x8d, 0x67, 0xc3, 0x6b, 0xed, 0xe2, 0xea, 0xa6, 0x1f, 0x25, 0x24, 0x7c,
+ 0x94, 0x74, 0x50, 0x49, 0xe3, 0xc6, 0x58, 0x2e, 0xfd, 0x28, 0xb4, 0xc6, 0x73, 0xb1, 0x53,
+ 0x74, 0x27, 0x94, 0x5c, 0xdf, 0x69, 0xb7, 0xa1, 0xd7, 0xf5, 0xd3, 0x8a, 0x2c, 0x2d, 0xb4,
+ 0x5e, 0x8a, 0x16, 0x14, 0x54, 0x64, 0x6e, 0x00, 0x6b, 0x11, 0x59, 0x8a, 0x63, 0x38, 0x80,
+ 0x76, 0xc3, 0xd5, 0x59, 0xf7, 0x3f, 0xd2, 0xfa, 0xa5, 0xca, 0x82, 0xff, 0x4a, 0x62, 0xf0,
+ 0xe3, 0x42, 0xf9, 0x3b, 0x38, 0x27, 0x8a, 0x89, 0xaa, 0x50, 0x55, 0x4b, 0x29, 0xf1, 0x46,
+ 0x7c, 0x75, 0xef, 0x65, 0xaf, 0x9b, 0x0d, 0x6d, 0xda, 0x25, 0x94, 0x14, 0xc1, 0x1b, 0xf0,
+ 0xc5, 0x4c, 0x24, 0x0e, 0x65,
+};
+
+const uint8_t kOutRefBinaryBuffer[] = {
+ 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0, 0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0xc0, 0x1e, 0xdb,
+ 0x01, 0x40, 0x16, 0xec, 0x04, 0x40, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x0f, 0x03,
+ 0xc5, 0x8b, 0xb8, 0x00, 0x00, 0x00, 0x01, 0x68, 0xca, 0x8c, 0xb2, 0x00, 0x00, 0x01, 0x06,
+ 0x05, 0xff, 0xff, 0x70, 0xdc, 0x45, 0xe9, 0xbd, 0xe6, 0xd9, 0x48, 0xb7, 0x96, 0x2c, 0xd8,
+ 0x20, 0xd9, 0x23, 0xee, 0xef, 0x78, 0x32, 0x36, 0x34, 0x20, 0x2d, 0x20, 0x63, 0x6f, 0x72,
+ 0x65, 0x20, 0x31, 0x34, 0x32, 0x20, 0x2d, 0x20, 0x48, 0x2e, 0x32, 0x36, 0x34, 0x2f, 0x4d,
+ 0x50, 0x45, 0x47, 0x2d, 0x34, 0x20, 0x41, 0x56, 0x43, 0x20, 0x63, 0x6f, 0x64, 0x65, 0x63,
+ 0x20, 0x2d, 0x20, 0x43, 0x6f, 0x70, 0x79, 0x6c, 0x65, 0x66, 0x74, 0x20, 0x32, 0x30, 0x30,
+ 0x33, 0x2d, 0x32, 0x30, 0x31, 0x34, 0x20, 0x2d, 0x20, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f,
+ 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x6c, 0x61, 0x6e, 0x2e, 0x6f,
+ 0x72, 0x67, 0x2f, 0x78, 0x32, 0x36, 0x34, 0x2e, 0x68, 0x74, 0x6d, 0x6c, 0x20, 0x2d, 0x20,
+ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x20, 0x63, 0x61, 0x62, 0x61, 0x63, 0x3d,
+ 0x30, 0x20, 0x72, 0x65, 0x66, 0x3d, 0x32, 0x20, 0x64, 0x65, 0x62, 0x6c, 0x6f, 0x63, 0x6b,
+ 0x3d, 0x31, 0x3a, 0x30, 0x3a, 0x30, 0x20, 0x61, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x65, 0x3d,
+ 0x30, 0x78, 0x31, 0x3a, 0x30, 0x78, 0x31, 0x31, 0x31, 0x20, 0x6d, 0x65, 0x3d, 0x68, 0x65,
+ 0x78, 0x20, 0x73, 0x75, 0x62, 0x6d, 0x65, 0x3d, 0x37, 0x20, 0x70, 0x73, 0x79, 0x3d, 0x31,
+ 0x20, 0x70, 0x73, 0x79, 0x5f, 0x72, 0x64, 0x3d, 0x31, 0x2e, 0x30, 0x30, 0x3a, 0x30, 0x2e,
+ 0x30, 0x30, 0x20, 0x6d, 0x69, 0x78, 0x65, 0x64, 0x5f, 0x72, 0x65, 0x66, 0x3d, 0x31, 0x20,
+ 0x6d, 0x65, 0x5f, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x3d, 0x31, 0x36, 0x20, 0x63, 0x68, 0x72,
+ 0x6f, 0x6d, 0x61, 0x5f, 0x6d, 0x65, 0x3d, 0x31, 0x20, 0x74, 0x72, 0x65, 0x6c, 0x6c, 0x69,
+ 0x73, 0x3d, 0x31, 0x20, 0x38, 0x78, 0x38, 0x64, 0x63, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x71,
+ 0x6d, 0x3d, 0x30, 0x20, 0x64, 0x65, 0x61, 0x64, 0x7a, 0x6f, 0x6e, 0x65, 0x3d, 0x32, 0x31,
+ 0x2c, 0x31, 0x31, 0x20, 0x66, 0x61, 0x73, 0x74, 0x5f, 0x70, 0x73, 0x6b, 0x69, 0x70, 0x3d,
+ 0x31, 0x20, 0x63, 0x68, 0x72, 0x6f, 0x6d, 0x61, 0x5f, 0x71, 0x70, 0x5f, 0x6f, 0x66, 0x66,
+ 0x73, 0x65, 0x74, 0x3d, 0x2d, 0x32, 0x20, 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d,
+ 0x36, 0x30, 0x20, 0x6c, 0x6f, 0x6f, 0x6b, 0x61, 0x68, 0x65, 0x61, 0x64, 0x5f, 0x74, 0x68,
+ 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x35, 0x20, 0x73, 0x6c, 0x69, 0x63, 0x65, 0x64, 0x5f,
+ 0x74, 0x68, 0x72, 0x65, 0x61, 0x64, 0x73, 0x3d, 0x30, 0x20, 0x6e, 0x72, 0x3d, 0x30, 0x20,
+ 0x64, 0x65, 0x63, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x3d, 0x31, 0x20, 0x69, 0x6e, 0x74, 0x65,
+ 0x72, 0x6c, 0x61, 0x63, 0x65, 0x64, 0x3d, 0x30, 0x20, 0x62, 0x6c, 0x75, 0x72, 0x61, 0x79,
+ 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x3d, 0x30, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x74,
+ 0x72, 0x61, 0x69, 0x6e, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x74, 0x72, 0x61, 0x3d, 0x30, 0x20,
+ 0x62, 0x66, 0x72, 0x61, 0x6d, 0x65, 0x73, 0x3d, 0x30, 0x20, 0x77, 0x65, 0x69, 0x67, 0x68,
+ 0x74, 0x70, 0x3d, 0x30, 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x3d, 0x32, 0x35, 0x30,
+ 0x20, 0x6b, 0x65, 0x79, 0x69, 0x6e, 0x74, 0x5f, 0x6d, 0x69, 0x6e, 0x3d, 0x32, 0x35, 0x20,
+ 0x73, 0x63, 0x65, 0x6e, 0x65,
+};
+
+class MediaCasListener : public BnCasListener {
+ public:
+ virtual ScopedAStatus onEvent(int32_t event, int32_t arg,
+ const vector<uint8_t>& data) override {
+ Mutex::Autolock autoLock(mMsgLock);
+ mEvent = event;
+ mEventArg = arg;
+ mEventData = data;
+
+ mEventReceived = true;
+ mMsgCondition.signal();
+ return ScopedAStatus::ok();
+ }
+
+ virtual ScopedAStatus onSessionEvent(const vector<uint8_t>& sessionId, int32_t event,
+ int32_t arg, const vector<uint8_t>& data) override {
+ Mutex::Autolock autoLock(mMsgLock);
+ mSessionId = sessionId;
+ mEvent = event;
+ mEventArg = arg;
+ mEventData = data;
+
+ mEventReceived = true;
+ mMsgCondition.signal();
+ return ScopedAStatus::ok();
+ }
+
+ virtual ScopedAStatus onStatusUpdate(StatusEvent event, int32_t arg) override {
+ Mutex::Autolock autoLock(mMsgLock);
+ mStatusEvent = event;
+ mEventArg = arg;
+
+ mEventReceived = true;
+ mMsgCondition.signal();
+ return ScopedAStatus::ok();
+ }
+
+ void testEventEcho(shared_ptr<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
+ vector<uint8_t>& eventData);
+
+ void testSessionEventEcho(shared_ptr<ICas>& mediaCas, const vector<uint8_t>& sessionId,
+ int32_t& event, int32_t& eventArg, vector<uint8_t>& eventData);
+
+ void testStatusUpdate(shared_ptr<ICas>& mediaCas, vector<uint8_t>* sessionId,
+ SessionIntent intent, ScramblingMode mode);
+
+ private:
+ int32_t mEvent = -1;
+ int32_t mEventArg = -1;
+ StatusEvent mStatusEvent;
+ bool mEventReceived = false;
+ vector<uint8_t> mEventData;
+ vector<uint8_t> mSessionId;
+ Mutex mMsgLock;
+ android::Condition mMsgCondition;
+};
+
+void MediaCasListener::testEventEcho(shared_ptr<ICas>& mediaCas, int32_t& event, int32_t& eventArg,
+ vector<uint8_t>& eventData) {
+ mEventReceived = false;
+ auto returnStatus = mediaCas->sendEvent(event, eventArg, eventData);
+ EXPECT_TRUE(returnStatus.isOk());
+
+ Mutex::Autolock autoLock(mMsgLock);
+ while (!mEventReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ ADD_FAILURE() << "event not received within timeout";
+ return;
+ }
+ }
+
+ EXPECT_EQ(mEvent, event);
+ EXPECT_EQ(mEventArg, eventArg);
+ EXPECT_TRUE(mEventData == eventData);
+}
+
+void MediaCasListener::testSessionEventEcho(shared_ptr<ICas>& mediaCas,
+ const vector<uint8_t>& sessionId, int32_t& event,
+ int32_t& eventArg, vector<uint8_t>& eventData) {
+ mEventReceived = false;
+ EXPECT_TRUE(mediaCas->sendSessionEvent(sessionId, event, eventArg, eventData).isOk());
+
+ Mutex::Autolock autoLock(mMsgLock);
+ while (!mEventReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ ADD_FAILURE() << "event not received within timeout";
+ return;
+ }
+ }
+
+ EXPECT_TRUE(mSessionId == sessionId);
+ EXPECT_EQ(mEvent, event);
+ EXPECT_EQ(mEventArg, eventArg);
+ EXPECT_TRUE(mEventData == eventData);
+}
+
+void MediaCasListener::testStatusUpdate(shared_ptr<ICas>& mediaCas, vector<uint8_t>* sessionId,
+ SessionIntent intent, ScramblingMode mode) {
+ mEventReceived = false;
+ EXPECT_TRUE(mediaCas->openSession(intent, mode, sessionId).isOk());
+
+ Mutex::Autolock autoLock(mMsgLock);
+ while (!mEventReceived) {
+ if (-ETIMEDOUT == mMsgCondition.waitRelative(mMsgLock, WAIT_TIMEOUT)) {
+ ADD_FAILURE() << "event not received within timeout";
+ return;
+ }
+ }
+ EXPECT_EQ(mStatusEvent, static_cast<StatusEvent>(intent));
+ EXPECT_EQ(mEventArg, static_cast<int32_t>(mode));
+}
+
+class MediaCasAidlTest : public testing::TestWithParam<string> {
+ public:
+ virtual void SetUp() override {
+ if (AServiceManager_isDeclared(GetParam().c_str())) {
+ SpAIBinder binder(AServiceManager_waitForService(GetParam().c_str()));
+ mService = IMediaCasService::fromBinder(binder);
+ } else {
+ mService = nullptr;
+ }
+ ASSERT_NE(mService, nullptr);
+ }
+
+ shared_ptr<IMediaCasService> mService = nullptr;
+
+ protected:
+ static void description(const string& description) {
+ RecordProperty("description", description);
+ }
+
+ shared_ptr<ICas> mMediaCas;
+ shared_ptr<IDescrambler> mDescrambler;
+ shared_ptr<MediaCasListener> mCasListener;
+ typedef struct _OobInputTestParams {
+ const SubSample* subSamples;
+ int32_t numSubSamples;
+ int64_t imemSizeActual;
+ int64_t imemOffset;
+ int64_t imemSize;
+ int64_t srcOffset;
+ int64_t dstOffset;
+ } OobInputTestParams;
+
+ AssertionResult createCasPlugin(int32_t caSystemId);
+ AssertionResult openCasSession(vector<uint8_t>* sessionId, SessionIntent intent,
+ ScramblingMode mode);
+ AssertionResult descrambleTestInputBuffer(const shared_ptr<IDescrambler>& descrambler,
+ ScopedAStatus& descrambleStatus, uint8_t*& inMemory);
+ AssertionResult descrambleTestOobInput(const shared_ptr<IDescrambler>& descrambler,
+ ScopedAStatus& descrambleStatus,
+ const OobInputTestParams& params);
+};
+
+AssertionResult MediaCasAidlTest::createCasPlugin(int32_t caSystemId) {
+ bool isSystemIdSupported;
+ auto status = mService->isSystemIdSupported(caSystemId, &isSystemIdSupported);
+ bool skipDescrambler = false;
+ if (!status.isOk() || !isSystemIdSupported) {
+ return AssertionFailure();
+ }
+ bool isDescramblerSupported;
+ status = mService->isDescramblerSupported(caSystemId, &isDescramblerSupported);
+ if (!status.isOk() || !isDescramblerSupported) {
+ ALOGI("Skip Descrambler test since it's not required in cas.");
+ mDescrambler = nullptr;
+ skipDescrambler = true;
+ }
+
+ mCasListener = SharedRefBase::make<MediaCasListener>();
+ status = mService->createPlugin(caSystemId, mCasListener, &mMediaCas);
+ if (!status.isOk()) {
+ return AssertionFailure();
+ }
+ if (mMediaCas == nullptr) {
+ return AssertionFailure();
+ }
+
+ if (skipDescrambler) {
+ return AssertionSuccess();
+ }
+
+ status = mService->createDescrambler(caSystemId, &mDescrambler);
+ if (!status.isOk()) {
+ return AssertionFailure();
+ }
+
+ return AssertionResult(mDescrambler != nullptr);
+}
+
+AssertionResult MediaCasAidlTest::openCasSession(vector<uint8_t>* sessionId, SessionIntent intent,
+ ScramblingMode mode) {
+ return AssertionResult(mMediaCas->openSession(intent, mode, sessionId).isOk());
+}
+
+AssertionResult MediaCasAidlTest::descrambleTestInputBuffer(
+ const shared_ptr<IDescrambler>& descrambler, ScopedAStatus& descrambleStatus,
+ uint8_t*& sharedMemory) {
+ vector<SubSample> subSample(kSubSamples,
+ kSubSamples + (sizeof(kSubSamples) / sizeof(SubSample)));
+
+ int size = sizeof(kInBinaryBuffer);
+ auto fd = ashmem_create_region("vts-cas", size);
+ if (fd < 0) {
+ ALOGE("ashmem_create_region failed");
+ return AssertionFailure();
+ }
+
+ sharedMemory =
+ static_cast<uint8_t*>(mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
+ if (sharedMemory == reinterpret_cast<uint8_t*>(MAP_FAILED)) {
+ ALOGE("mmap failed");
+ return AssertionFailure();
+ }
+
+ memcpy(sharedMemory, kInBinaryBuffer, size);
+
+ auto dupFd = dup(fd);
+
+ SharedBuffer srcBuffer = {.heapBase.fd = ScopedFileDescriptor(std::move(fd)),
+ .heapBase.size = size,
+ .offset = 0,
+ .size = size};
+
+ SharedBuffer dupBuffer = {.heapBase.fd = ScopedFileDescriptor(dupFd),
+ .heapBase.size = size,
+ .offset = 0,
+ .size = size};
+
+ DestinationBuffer dstBuffer;
+ dstBuffer.set<DestinationBuffer::nonsecureMemory>(std::move(dupBuffer));
+
+ int32_t outBytes;
+ descrambleStatus = descrambler->descramble(ScramblingControl::EVENKEY /*2*/, subSample,
+ srcBuffer, 0, dstBuffer, 0, &outBytes);
+ if (!descrambleStatus.isOk()) {
+ ALOGI("descramble failed, status=%d, outBytes=%u, error=%s", descrambleStatus.getStatus(),
+ outBytes, descrambleStatus.getDescription().c_str());
+ }
+ return AssertionResult(descrambleStatus.isOk());
+}
+
+AssertionResult MediaCasAidlTest::descrambleTestOobInput(
+ const shared_ptr<IDescrambler>& descrambler, ScopedAStatus& descrambleStatus,
+ const OobInputTestParams& params) {
+ vector<SubSample> subSample(params.subSamples, params.subSamples + params.numSubSamples);
+
+ auto fd = ashmem_create_region("vts-cas", params.imemSizeActual);
+ if (fd < 0) {
+ ALOGE("ashmem_create_region failed");
+ return AssertionFailure();
+ }
+
+ auto dupFd = dup(fd);
+
+ SharedBuffer srcBuffer = {.heapBase.fd = ScopedFileDescriptor(std::move(fd)),
+ .heapBase.size = params.imemSizeActual,
+ .offset = params.imemOffset,
+ .size = params.imemSize};
+
+ SharedBuffer dupBuffer = {.heapBase.fd = ScopedFileDescriptor(dupFd),
+ .heapBase.size = params.imemSizeActual,
+ .offset = params.imemOffset,
+ .size = params.imemSize};
+
+ DestinationBuffer dstBuffer;
+ dstBuffer.set<DestinationBuffer::nonsecureMemory>(std::move(dupBuffer));
+
+ int32_t outBytes;
+ descrambleStatus =
+ descrambler->descramble(ScramblingControl::EVENKEY /*2*/, subSample, srcBuffer,
+ params.srcOffset, dstBuffer, params.dstOffset, &outBytes);
+ if (!descrambleStatus.isOk()) {
+ ALOGI("descramble failed, status=%d, outBytes=%u, error=%s", descrambleStatus.getStatus(),
+ outBytes, descrambleStatus.getDescription().c_str());
+ }
+ return AssertionResult(descrambleStatus.isOk());
+}
+
+TEST_P(MediaCasAidlTest, EnumeratePlugins) {
+ description("Test enumerate plugins");
+
+ vector<AidlCasPluginDescriptor> descriptors;
+ EXPECT_TRUE(mService->enumeratePlugins(&descriptors).isOk());
+
+ if (descriptors.size() == 0) {
+ ALOGW("[ WARN ] enumeratePlugins list empty");
+ return;
+ }
+
+ for (size_t i = 0; i < descriptors.size(); i++) {
+ int32_t caSystemId = descriptors[i].caSystemId;
+
+ ASSERT_TRUE(createCasPlugin(caSystemId));
+ }
+}
+
+TEST_P(MediaCasAidlTest, TestInvalidSystemIdFails) {
+ description("Test failure for invalid system ID");
+
+ bool isSystemIdSupported;
+ auto status = mService->isSystemIdSupported(INVALID_SYSTEM_ID, &isSystemIdSupported);
+
+ EXPECT_TRUE(status.isOk());
+ ASSERT_FALSE(isSystemIdSupported);
+
+ bool isDescramblerSupported;
+ status = mService->isDescramblerSupported(INVALID_SYSTEM_ID, &isDescramblerSupported);
+
+ EXPECT_TRUE(status.isOk());
+ ASSERT_FALSE(isDescramblerSupported);
+
+ shared_ptr<ICas> mediaCas;
+ shared_ptr<MediaCasListener> casListener = SharedRefBase::make<MediaCasListener>();
+ status = mService->createPlugin(INVALID_SYSTEM_ID, casListener, &mediaCas);
+ ASSERT_TRUE(status.isOk());
+ EXPECT_EQ(mediaCas, nullptr);
+
+ shared_ptr<IDescrambler> descrambler;
+ status = mService->createDescrambler(INVALID_SYSTEM_ID, &descrambler);
+ ASSERT_TRUE(status.isOk());
+ EXPECT_EQ(descrambler, nullptr);
+}
+
+TEST_P(MediaCasAidlTest, TestClearKeyPluginInstalled) {
+ description("Test if ClearKey plugin is installed");
+
+ vector<AidlCasPluginDescriptor> descriptors;
+ EXPECT_TRUE(mService->enumeratePlugins(&descriptors).isOk());
+
+ if (descriptors.size() == 0) {
+ ALOGW("[ WARN ] enumeratePlugins list empty");
+ }
+
+ for (size_t i = 0; i < descriptors.size(); i++) {
+ int32_t caSystemId = descriptors[i].caSystemId;
+ if (CLEAR_KEY_SYSTEM_ID == caSystemId) {
+ return;
+ }
+ }
+
+ ADD_FAILURE() << "ClearKey plugin not installed";
+}
+
+TEST_P(MediaCasAidlTest, TestClearKeySessionClosedAfterRelease) {
+ description("Test that all sessions are closed after a MediaCas object is released");
+
+ ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
+
+ EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
+
+ SessionIntent intent = SessionIntent::LIVE;
+ ScramblingMode mode = ScramblingMode::DVB_CSA1;
+
+ vector<uint8_t> sessionId;
+ ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
+
+ vector<uint8_t> streamSessionId;
+ ASSERT_TRUE(openCasSession(&streamSessionId, intent, mode));
+
+ EXPECT_TRUE(mMediaCas->release().isOk());
+
+ if (mDescrambler != nullptr) {
+ auto status = mDescrambler->setMediaCasSession(sessionId);
+ EXPECT_FALSE(status.isOk());
+ EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, status.getServiceSpecificError());
+
+ status = mDescrambler->setMediaCasSession(streamSessionId);
+ EXPECT_FALSE(status.isOk());
+ EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, status.getServiceSpecificError());
+ }
+}
+
+TEST_P(MediaCasAidlTest, TestClearKeyErrors) {
+ description("Test that invalid call sequences fail with expected error codes");
+
+ ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
+
+ /*
+ * Test MediaCas error codes
+ */
+ // Provision should fail with an invalid asset string
+ auto returnStatus = mMediaCas->provision("invalid asset string");
+ EXPECT_FALSE(returnStatus.isOk());
+ EXPECT_EQ(Status::ERROR_CAS_NO_LICENSE, returnStatus.getServiceSpecificError());
+
+ SessionIntent intent = SessionIntent::LIVE;
+ ScramblingMode mode = ScramblingMode::DVB_CSA1;
+
+ // Open a session, then close it so that it should become invalid
+ vector<uint8_t> invalidSessionId;
+ ASSERT_TRUE(openCasSession(&invalidSessionId, intent, mode));
+ EXPECT_TRUE(mMediaCas->closeSession(invalidSessionId).isOk());
+
+ // processEcm should fail with an invalid session id
+ vector<uint8_t> ecm(kEcmBinaryBuffer, kEcmBinaryBuffer + sizeof(kEcmBinaryBuffer));
+ returnStatus = mMediaCas->processEcm(invalidSessionId, ecm);
+ EXPECT_FALSE(returnStatus.isOk());
+ EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus.getServiceSpecificError());
+
+ vector<uint8_t> sessionId;
+ ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
+
+ // processEcm should fail without provisioning
+ returnStatus = mMediaCas->processEcm(sessionId, ecm);
+ EXPECT_FALSE(returnStatus.isOk());
+ EXPECT_EQ(Status::ERROR_CAS_NOT_PROVISIONED, returnStatus.getServiceSpecificError());
+
+ EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
+
+ // processEcm should fail with ecm with bad descriptor count
+ ecm[17] = 0x03; // change the descriptor count field to 3 (invalid)
+ returnStatus = mMediaCas->processEcm(sessionId, ecm);
+ EXPECT_FALSE(returnStatus.isOk());
+ EXPECT_EQ(Status::ERROR_CAS_UNKNOWN, returnStatus.getServiceSpecificError());
+
+ // processEcm should fail with ecm buffer that's too short
+ ecm.resize(8);
+ returnStatus = mMediaCas->processEcm(sessionId, ecm);
+ EXPECT_FALSE(returnStatus.isOk());
+ EXPECT_EQ(Status::BAD_VALUE, returnStatus.getServiceSpecificError());
+
+ if (mDescrambler != nullptr) {
+ /*
+ * Test MediaDescrambler error codes
+ */
+ // setMediaCasSession should fail with an invalid session id
+ returnStatus = mDescrambler->setMediaCasSession(invalidSessionId);
+ EXPECT_FALSE(returnStatus.isOk());
+ EXPECT_EQ(Status::ERROR_CAS_SESSION_NOT_OPENED, returnStatus.getServiceSpecificError());
+
+ // descramble should fail without a valid session
+ ScopedAStatus descrambleStatus = ScopedAStatus::ok();
+ uint8_t* sharedBuffer = nullptr;
+
+ ASSERT_FALSE(descrambleTestInputBuffer(mDescrambler, descrambleStatus, sharedBuffer));
+ EXPECT_EQ(Status::ERROR_CAS_DECRYPT_UNIT_NOT_INITIALIZED,
+ descrambleStatus.getServiceSpecificError());
+
+ // Now set a valid session, should still fail because no valid ecm is processed
+ EXPECT_TRUE(mDescrambler->setMediaCasSession(sessionId).isOk());
+ ASSERT_FALSE(descrambleTestInputBuffer(mDescrambler, descrambleStatus, sharedBuffer));
+ EXPECT_EQ(Status::ERROR_CAS_DECRYPT, descrambleStatus.getServiceSpecificError());
+
+ // Verify that requiresSecureDecoderComponent handles empty mime
+ bool requiresSecureDecoderComponent = true;
+ EXPECT_TRUE(
+ mDescrambler->requiresSecureDecoderComponent("", &requiresSecureDecoderComponent)
+ .isOk());
+ EXPECT_FALSE(requiresSecureDecoderComponent);
+
+ // Verify that requiresSecureDecoderComponent handles invalid mime
+ requiresSecureDecoderComponent = true;
+ EXPECT_TRUE(
+ mDescrambler->requiresSecureDecoderComponent("bad", &requiresSecureDecoderComponent)
+ .isOk());
+ EXPECT_FALSE(requiresSecureDecoderComponent);
+ }
+}
+
+TEST_P(MediaCasAidlTest, TestClearKeyApisWithSession) {
+ description("Test that valid call sequences with SessionEvent send and receive");
+
+ ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
+
+ EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
+
+ vector<uint8_t> pvtData;
+ pvtData.resize(256);
+ EXPECT_TRUE(mMediaCas->setPrivateData(pvtData).isOk());
+
+ SessionIntent intent = SessionIntent::LIVE;
+ ScramblingMode mode = ScramblingMode::DVB_CSA1;
+
+ vector<uint8_t> sessionId;
+ ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
+ EXPECT_TRUE(mMediaCas->setSessionPrivateData(sessionId, pvtData).isOk());
+
+ vector<uint8_t> streamSessionId;
+ ASSERT_TRUE(openCasSession(&streamSessionId, intent, mode));
+ EXPECT_TRUE(mMediaCas->setSessionPrivateData(streamSessionId, pvtData).isOk());
+
+ if (mDescrambler != nullptr) {
+ EXPECT_TRUE(mDescrambler->setMediaCasSession(sessionId).isOk());
+ EXPECT_TRUE(mDescrambler->setMediaCasSession(streamSessionId).isOk());
+ }
+
+ vector<uint8_t> nullPtrVector(0);
+ EXPECT_TRUE(mMediaCas->refreshEntitlements(3, nullPtrVector).isOk());
+
+ vector<uint8_t> refreshData{0, 1, 2, 3};
+ EXPECT_TRUE(mMediaCas->refreshEntitlements(10, refreshData).isOk());
+
+ int32_t eventID = 1;
+ int32_t eventArg = 2;
+ mCasListener->testEventEcho(mMediaCas, eventID, eventArg, nullPtrVector);
+ mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, nullPtrVector);
+
+ eventID = 3;
+ eventArg = 4;
+ vector<uint8_t> eventData{'e', 'v', 'e', 'n', 't', 'd', 'a', 't', 'a'};
+ mCasListener->testEventEcho(mMediaCas, eventID, eventArg, eventData);
+ mCasListener->testSessionEventEcho(mMediaCas, sessionId, eventID, eventArg, eventData);
+
+ mCasListener->testStatusUpdate(mMediaCas, &sessionId, intent, mode);
+
+ vector<uint8_t> clearKeyEmmData{'c', 'l', 'e', 'a', 'r', 'k', 'e', 'y', 'e', 'm', 'm'};
+ EXPECT_TRUE(mMediaCas->processEmm(clearKeyEmmData).isOk());
+
+ vector<uint8_t> ecm(kEcmBinaryBuffer, kEcmBinaryBuffer + sizeof(kEcmBinaryBuffer));
+ EXPECT_TRUE(mMediaCas->processEcm(sessionId, ecm).isOk());
+ EXPECT_TRUE(mMediaCas->processEcm(streamSessionId, ecm).isOk());
+
+ if (mDescrambler != nullptr) {
+ bool requiresSecureDecoderComponent = true;
+ EXPECT_TRUE(mDescrambler
+ ->requiresSecureDecoderComponent("video/avc",
+ &requiresSecureDecoderComponent)
+ .isOk());
+ EXPECT_FALSE(requiresSecureDecoderComponent);
+
+ ScopedAStatus descrambleStatus = ScopedAStatus::ok();
+ uint8_t* sharedBuffer = nullptr;
+
+ ASSERT_TRUE(descrambleTestInputBuffer(mDescrambler, descrambleStatus, sharedBuffer));
+
+ int compareResult =
+ memcmp(static_cast<const void*>(sharedBuffer),
+ static_cast<const void*>(kOutRefBinaryBuffer), sizeof(kOutRefBinaryBuffer));
+ EXPECT_EQ(0, compareResult);
+
+ EXPECT_TRUE(mDescrambler->release().isOk());
+ }
+
+ EXPECT_TRUE(mMediaCas->release().isOk());
+}
+
+TEST_P(MediaCasAidlTest, TestClearKeyOobFails) {
+ description("Test that oob descramble request fails with expected error");
+
+ ASSERT_TRUE(createCasPlugin(CLEAR_KEY_SYSTEM_ID));
+ EXPECT_TRUE(mMediaCas->provision(PROVISION_STR).isOk());
+
+ SessionIntent intent = SessionIntent::LIVE;
+ ScramblingMode mode = ScramblingMode::DVB_CSA1;
+
+ vector<uint8_t> sessionId;
+ ASSERT_TRUE(openCasSession(&sessionId, intent, mode));
+
+ if (mDescrambler != nullptr) {
+ EXPECT_TRUE(mDescrambler->setMediaCasSession(sessionId).isOk());
+ }
+
+ vector<uint8_t> ecm(kEcmBinaryBuffer, kEcmBinaryBuffer + sizeof(kEcmBinaryBuffer));
+ EXPECT_TRUE(mMediaCas->processEcm(sessionId, ecm).isOk());
+
+ if (mDescrambler != nullptr) {
+ ScopedAStatus descrambleStatus = ScopedAStatus::ok();
+
+ // test invalid src buffer offset
+ ASSERT_FALSE(
+ descrambleTestOobInput(mDescrambler, descrambleStatus,
+ {.subSamples = kSubSamples,
+ .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+ .imemSizeActual = sizeof(kInBinaryBuffer),
+ .imemOffset = 0xcccccc,
+ .imemSize = sizeof(kInBinaryBuffer),
+ .srcOffset = 0,
+ .dstOffset = 0}));
+ EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
+
+ // test invalid src buffer size
+ ASSERT_FALSE(
+ descrambleTestOobInput(mDescrambler, descrambleStatus,
+ {.subSamples = kSubSamples,
+ .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+ .imemSizeActual = sizeof(kInBinaryBuffer),
+ .imemOffset = 0,
+ .imemSize = 0xcccccc,
+ .srcOffset = 0,
+ .dstOffset = 0}));
+ EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
+
+ // test invalid src buffer size
+ ASSERT_FALSE(
+ descrambleTestOobInput(mDescrambler, descrambleStatus,
+ {.subSamples = kSubSamples,
+ .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+ .imemSizeActual = sizeof(kInBinaryBuffer),
+ .imemOffset = 1,
+ .imemSize = -1,
+ .srcOffset = 0,
+ .dstOffset = 0}));
+ EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
+
+ // test invalid srcOffset
+ ASSERT_FALSE(
+ descrambleTestOobInput(mDescrambler, descrambleStatus,
+ {.subSamples = kSubSamples,
+ .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+ .imemSizeActual = sizeof(kInBinaryBuffer),
+ .imemOffset = 0,
+ .imemSize = sizeof(kInBinaryBuffer),
+ .srcOffset = 0xcccccc,
+ .dstOffset = 0}));
+ EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
+
+ // test invalid dstOffset
+ ASSERT_FALSE(
+ descrambleTestOobInput(mDescrambler, descrambleStatus,
+ {.subSamples = kSubSamples,
+ .numSubSamples = sizeof(kSubSamples) / sizeof(SubSample),
+ .imemSizeActual = sizeof(kInBinaryBuffer),
+ .imemOffset = 0,
+ .imemSize = sizeof(kInBinaryBuffer),
+ .srcOffset = 0,
+ .dstOffset = 0xcccccc}));
+ EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
+
+ // test detection of oob subsample sizes
+ const SubSample invalidSubSamples1[] = {{162, 0}, {0, 184}, {0, 0xdddddd}};
+
+ ASSERT_FALSE(descrambleTestOobInput(
+ mDescrambler, descrambleStatus,
+ {.subSamples = invalidSubSamples1,
+ .numSubSamples = sizeof(invalidSubSamples1) / sizeof(SubSample),
+ .imemSizeActual = sizeof(kInBinaryBuffer),
+ .imemOffset = 0,
+ .imemSize = sizeof(kInBinaryBuffer),
+ .srcOffset = 0,
+ .dstOffset = 0}));
+ EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
+
+ // test detection of overflowing subsample sizes
+ const SubSample invalidSubSamples2[] = {{162, 0}, {0, 184}, {2, -1}};
+
+ ASSERT_FALSE(descrambleTestOobInput(
+ mDescrambler, descrambleStatus,
+ {.subSamples = invalidSubSamples2,
+ .numSubSamples = sizeof(invalidSubSamples2) / sizeof(SubSample),
+ .imemSizeActual = sizeof(kInBinaryBuffer),
+ .imemOffset = 0,
+ .imemSize = sizeof(kInBinaryBuffer),
+ .srcOffset = 0,
+ .dstOffset = 0}));
+ EXPECT_EQ(Status::BAD_VALUE, descrambleStatus.getServiceSpecificError());
+
+ EXPECT_TRUE(mDescrambler->release().isOk());
+ }
+ EXPECT_TRUE(mMediaCas->release().isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(MediaCasAidlTest);
+
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, MediaCasAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IMediaCasService::descriptor)),
+ android::PrintInstanceNameToString);
+
+// Start thread pool to receive callbacks from AIDL service.
+int main(int argc, char** argv) {
+ InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/common/aidl/Android.bp b/common/aidl/Android.bp
index 43f8c4d..7f6890c 100644
--- a/common/aidl/Android.bp
+++ b/common/aidl/Android.bp
@@ -37,6 +37,7 @@
min_sdk_version: "29",
},
},
+ frozen: true,
versions: [
"1",
"2",
diff --git a/common/fmq/aidl/Android.bp b/common/fmq/aidl/Android.bp
index a85597c..95fcc41 100644
--- a/common/fmq/aidl/Android.bp
+++ b/common/fmq/aidl/Android.bp
@@ -37,5 +37,6 @@
min_sdk_version: "29",
},
},
+ frozen: true,
versions: ["1"],
}
diff --git a/common/support/NativeHandle.cpp b/common/support/NativeHandle.cpp
index 321d7a8..126ef2e 100644
--- a/common/support/NativeHandle.cpp
+++ b/common/support/NativeHandle.cpp
@@ -22,6 +22,13 @@
using aidl::android::hardware::common::NativeHandle;
+/**
+ * Checks if a NativeHandle is null
+ */
+bool isAidlNativeHandleEmpty(const NativeHandle& handle) {
+ return handle.fds.empty() && handle.ints.empty();
+}
+
static native_handle_t* fromAidl(const NativeHandle& handle, bool doDup) {
native_handle_t* to = native_handle_create(handle.fds.size(), handle.ints.size());
if (!to) return nullptr;
diff --git a/common/support/include/aidlcommonsupport/NativeHandle.h b/common/support/include/aidlcommonsupport/NativeHandle.h
index 10eecba..b5ea1dd 100644
--- a/common/support/include/aidlcommonsupport/NativeHandle.h
+++ b/common/support/include/aidlcommonsupport/NativeHandle.h
@@ -22,6 +22,11 @@
namespace android {
/**
+ * Checks if a NativeHandle is empty.
+ */
+bool isAidlNativeHandleEmpty(const aidl::android::hardware::common::NativeHandle& handle);
+
+/**
* Creates a libcutils native handle from an AIDL native handle, but it does not
* dup internally, so it will contain the same FDs as the handle itself. The
* result should be deleted with native_handle_delete.
diff --git a/common/support/test.cpp b/common/support/test.cpp
index 2359277..9b79581 100644
--- a/common/support/test.cpp
+++ b/common/support/test.cpp
@@ -62,6 +62,7 @@
TEST(ConvertNativeHandle, MakeFromAidlEmpty) {
NativeHandle handle;
+ EXPECT_TRUE(isAidlNativeHandleEmpty(handle));
native_handle_t* to = makeFromAidl(handle);
checkEq(handle, to, false /*exceptFds*/);
// no native_handle_close b/c fds are owned by NativeHandle
@@ -70,6 +71,7 @@
TEST(ConvertNativeHandle, MakeFromAidl) {
NativeHandle handle = makeTestAidlHandle();
+ EXPECT_FALSE(isAidlNativeHandleEmpty(handle));
native_handle_t* to = makeFromAidl(handle);
checkEq(handle, to, false /*exceptFds*/);
// no native_handle_close b/c fds are owned by NativeHandle
@@ -106,6 +108,7 @@
TEST(ConvertNativeHandle, MakeToAidlEmpty) {
native_handle_t* handle = native_handle_create(0, 0);
NativeHandle to = makeToAidl(handle);
+ EXPECT_TRUE(isAidlNativeHandleEmpty(to));
checkEq(to, handle, false /*exceptFds*/);
// no native_handle_close b/c fds are owned by NativeHandle now
EXPECT_EQ(0, native_handle_delete(handle));
@@ -114,6 +117,7 @@
TEST(ConvertNativeHandle, MakeToAidl) {
native_handle_t* handle = makeTestLibcutilsHandle();
NativeHandle to = makeToAidl(handle);
+ EXPECT_FALSE(isAidlNativeHandleEmpty(to));
checkEq(to, handle, false /*exceptFds*/);
// no native_handle_close b/c fds are owned by NativeHandle now
EXPECT_EQ(0, native_handle_delete(handle));
@@ -122,6 +126,7 @@
TEST(ConvertNativeHandle, DupToAidlEmpty) {
native_handle_t* handle = native_handle_create(0, 0);
NativeHandle to = dupToAidl(handle);
+ EXPECT_TRUE(isAidlNativeHandleEmpty(to));
checkEq(to, handle, true /*exceptFds*/);
EXPECT_EQ(0, native_handle_close(handle));
EXPECT_EQ(0, native_handle_delete(handle));
@@ -130,6 +135,7 @@
TEST(ConvertNativeHandle, DupToAidl) {
native_handle_t* handle = makeTestLibcutilsHandle();
NativeHandle to = dupToAidl(handle);
+ EXPECT_FALSE(isAidlNativeHandleEmpty(to));
checkEq(to, handle, true /*exceptFds*/);
EXPECT_EQ(0, native_handle_close(handle));
EXPECT_EQ(0, native_handle_delete(handle));
diff --git a/compatibility_matrices/Android.bp b/compatibility_matrices/Android.bp
index 524242f..37c2820 100644
--- a/compatibility_matrices/Android.bp
+++ b/compatibility_matrices/Android.bp
@@ -28,8 +28,6 @@
"compatibility_matrix.3.xml",
],
kernel_configs: [
- "kernel_config_p_4.4",
- "kernel_config_p_4.9",
"kernel_config_p_4.14",
],
}
@@ -41,7 +39,6 @@
"compatibility_matrix.4.xml",
],
kernel_configs: [
- "kernel_config_q_4.9",
"kernel_config_q_4.14",
"kernel_config_q_4.19",
],
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index 6f0bd61..f8954a3 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -109,19 +109,19 @@
<name>android.hardware.automotive.vehicle</name>
<interface>
<name>IVehicle</name>
- <regex-instance>.*</regex-instance>
+ <instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.automotive.remoteaccess</name>
<interface>
<name>IRemoteAccess</name>
- <regex-instance>.*</regex-instance>
+ <instance>default</instance>
</interface>
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.biometrics.face</name>
- <version>2</version>
+ <version>3</version>
<interface>
<name>IFace</name>
<instance>default</instance>
@@ -129,7 +129,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.biometrics.fingerprint</name>
- <version>2</version>
+ <version>3</version>
<interface>
<name>IFingerprint</name>
<instance>default</instance>
@@ -145,6 +145,13 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.bluetooth</name>
+ <interface>
+ <name>IBluetoothHci</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.bluetooth.audio</name>
<version>2</version>
<interface>
@@ -166,17 +173,9 @@
<regex-instance>.*</regex-instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.camera.provider</name>
- <version>2.4-7</version>
- <interface>
- <name>ICameraProvider</name>
- <regex-instance>[^/]+/[0-9]+</regex-instance>
- </interface>
- </hal>
- <hal format="aidl" optional="true">
- <name>android.hardware.camera.provider</name>
- <version>1</version>
+ <version>1-2</version>
<interface>
<name>ICameraProvider</name>
<regex-instance>[^/]+/[0-9]+</regex-instance>
@@ -190,9 +189,16 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="aidl" optional="true">
+ <name>android.hardware.cas</name>
+ <interface>
+ <name>IMediaCasService</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.confirmationui</name>
- <version>1.0</version>
+ <version>1</version>
<interface>
<name>IConfirmationUI</name>
<instance>default</instance>
@@ -205,7 +211,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="aidl" optional="true">
+ <hal format="aidl" optional="true" updatable-via-apex="true">
<name>android.hardware.drm</name>
<version>1</version>
<interface>
@@ -238,7 +244,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.gnss</name>
- <version>2</version>
+ <version>3</version>
<interface>
<name>IGnss</name>
<instance>default</instance>
@@ -262,7 +268,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.graphics.allocator</name>
- <version>1</version>
+ <version>1-2</version>
<interface>
<name>IAllocator</name>
<instance>default</instance>
@@ -276,7 +282,7 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="hidl" optional="true">
<name>android.hardware.graphics.mapper</name>
<!-- New, non-Go devices should use 4.0, tested in vts_treble_vintf_vendor_test -->
<version>2.1</version>
@@ -305,7 +311,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.identity</name>
- <version>1-4</version>
+ <version>1-5</version>
<interface>
<name>IIdentityCredentialStore</name>
<instance>default</instance>
@@ -352,7 +358,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.security.keymint</name>
- <version>1-2</version>
+ <version>1-3</version>
<interface>
<name>IKeyMintDevice</name>
<instance>default</instance>
@@ -361,7 +367,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.security.keymint</name>
- <version>1-2</version>
+ <version>1-3</version>
<interface>
<name>IRemotelyProvisionedComponent</name>
<instance>default</instance>
@@ -385,16 +391,13 @@
<regex-instance>vendor[0-9]*_software</regex-instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.media.omx</name>
- <version>1.0</version>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.media.c2</name>
+ <version>1</version>
<interface>
- <name>IOmx</name>
- <instance>default</instance>
- </interface>
- <interface>
- <name>IOmxStore</name>
- <instance>default</instance>
+ <name>IComponentStore</name>
+ <regex-instance>default[0-9]*</regex-instance>
+ <regex-instance>vendor[0-9]*_software</regex-instance>
</interface>
</hal>
<hal format="aidl" optional="true">
@@ -405,14 +408,6 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.neuralnetworks</name>
- <version>1.0-3</version>
- <interface>
- <name>IDevice</name>
- <regex-instance>.*</regex-instance>
- </interface>
- </hal>
<hal format="aidl" optional="true">
<name>android.hardware.neuralnetworks</name>
<version>1-4</version>
@@ -453,7 +448,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.radio.config</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IRadioConfig</name>
<instance>default</instance>
@@ -461,7 +456,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.radio.data</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IRadioData</name>
<instance>slot1</instance>
@@ -471,7 +466,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.radio.messaging</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IRadioMessaging</name>
<instance>slot1</instance>
@@ -481,7 +476,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.radio.modem</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IRadioModem</name>
<instance>slot1</instance>
@@ -501,7 +496,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.radio.sim</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IRadioSim</name>
<instance>slot1</instance>
@@ -511,7 +506,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.radio.voice</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IRadioVoice</name>
<instance>slot1</instance>
@@ -519,6 +514,16 @@
<instance>slot3</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.radio.ims</name>
+ <version>1</version>
+ <interface>
+ <name>IRadioIms</name>
+ <instance>slot1</instance>
+ <instance>slot2</instance>
+ <instance>slot3</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.radio</name>
<version>1.2</version>
@@ -527,6 +532,14 @@
<instance>slot1</instance>
</interface>
</hal>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.radio.ims.media</name>
+ <version>1</version>
+ <interface>
+ <name>IImsMedia</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
<hal format="hidl" optional="true">
<name>android.hardware.renderscript</name>
<version>1.0</version>
@@ -553,6 +566,15 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.secure_element</name>
+ <version>1</version>
+ <interface>
+ <name>ISecureElement</name>
+ <regex-instance>eSE[1-9][0-9]*</regex-instance>
+ <regex-instance>SIM[1-9][0-9]*</regex-instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.security.secureclock</name>
<version>1</version>
<interface>
@@ -600,27 +622,25 @@
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="false">
+ <hal format="aidl" optional="false">
<name>android.hardware.thermal</name>
- <version>2.0</version>
+ <version>1</version>
<interface>
<name>IThermal</name>
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
+ <hal format="aidl" optional="true">
<name>android.hardware.tv.cec</name>
- <version>1.0-1</version>
<interface>
<name>IHdmiCec</name>
<instance>default</instance>
</interface>
</hal>
- <hal format="hidl" optional="true">
- <name>android.hardware.tv.input</name>
- <version>1.0</version>
+ <hal format="aidl" optional="true">
+ <name>android.hardware.tv.hdmi</name>
<interface>
- <name>ITvInput</name>
+ <name>IHdmi</name>
<instance>default</instance>
</interface>
</hal>
@@ -642,6 +662,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.usb</name>
+ <version>1-2</version>
<interface>
<name>IUsb</name>
<instance>default</instance>
@@ -728,6 +749,7 @@
</hal>
<hal format="aidl" optional="true">
<name>android.hardware.wifi.supplicant</name>
+ <version>2</version>
<interface>
<name>ISupplicant</name>
<instance>default</instance>
diff --git a/compatibility_matrices/exclude/fcm_exclude.cpp b/compatibility_matrices/exclude/fcm_exclude.cpp
index 6de9d03..cf1e138 100644
--- a/compatibility_matrices/exclude/fcm_exclude.cpp
+++ b/compatibility_matrices/exclude/fcm_exclude.cpp
@@ -61,6 +61,7 @@
"android.hardware.graphics.common",
"android.hardware.input.common",
"android.hardware.keymaster",
+ "android.hardware.media.bufferpool2",
"android.hardware.radio",
"android.hardware.uwb.fira_android",
@@ -68,6 +69,8 @@
// does not depend on this HAL, hence it is not declared in any manifests or matrices.
"android.hardware.fastboot@1.0",
"android.hardware.fastboot@1.1",
+ // Fastboot AIDL
+ "android.hardware.fastboot",
// Deprecated HALs.
// HIDL
diff --git a/confirmationui/OWNERS b/confirmationui/OWNERS
new file mode 100644
index 0000000..2bcdb0e
--- /dev/null
+++ b/confirmationui/OWNERS
@@ -0,0 +1,2 @@
+swillden@google.com
+subrahmanyaman@google.com
diff --git a/confirmationui/aidl/Android.bp b/confirmationui/aidl/Android.bp
new file mode 100644
index 0000000..5395101
--- /dev/null
+++ b/confirmationui/aidl/Android.bp
@@ -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.
+
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+aidl_interface {
+ name: "android.hardware.confirmationui",
+ vendor_available: true,
+ imports: [
+ "android.hardware.security.keymint-V3",
+ ],
+ srcs: ["android/hardware/confirmationui/*.aidl"],
+ stability: "vintf",
+ backend: {
+ java: {
+ platform_apis: true,
+ },
+ ndk: {
+ apps_enabled: false,
+ },
+ cpp: {
+ enabled: false,
+ },
+ },
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationResultCallback.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationResultCallback.aidl
new file mode 100644
index 0000000..6d6ec97
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationResultCallback.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.confirmationui;
+@VintfStability
+interface IConfirmationResultCallback {
+ void result(in int error, in byte[] formattedMessage, in byte[] confirmationToken);
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationUI.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationUI.aidl
new file mode 100644
index 0000000..c5c7aa7
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/IConfirmationUI.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.confirmationui;
+@VintfStability
+interface IConfirmationUI {
+ void abort();
+ void deliverSecureInputEvent(in android.hardware.security.keymint.HardwareAuthToken secureInputToken);
+ void promptUserConfirmation(in android.hardware.confirmationui.IConfirmationResultCallback resultCB, in byte[] promptText, in byte[] extraData, in @utf8InCpp String locale, in android.hardware.confirmationui.UIOption[] uiOptions);
+ const int OK = 0;
+ const int CANCELED = 1;
+ const int ABORTED = 2;
+ const int OPERATION_PENDING = 3;
+ const int IGNORED = 4;
+ const int SYSTEM_ERROR = 5;
+ const int UNIMPLEMENTED = 6;
+ const int UNEXPECTED = 7;
+ const int UI_ERROR = 65536;
+ const int UI_ERROR_MISSING_GLYPH = 65537;
+ const int UI_ERROR_MESSAGE_TOO_LONG = 65538;
+ const int UI_ERROR_MALFORMED_UTF8ENCODING = 65539;
+ const int TEST_KEY_BYTE = 165;
+ const int MAX_MESSAGE_SIZE = 6144;
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/TestModeCommands.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/TestModeCommands.aidl
new file mode 100644
index 0000000..b8629d1
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/TestModeCommands.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.confirmationui;
+@Backing(type="int") @VintfStability
+enum TestModeCommands {
+ OK_EVENT = 0,
+ CANCEL_EVENT = 1,
+}
diff --git a/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/UIOption.aidl b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/UIOption.aidl
new file mode 100644
index 0000000..ebecf9e
--- /dev/null
+++ b/confirmationui/aidl/aidl_api/android.hardware.confirmationui/current/android/hardware/confirmationui/UIOption.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.confirmationui;
+@Backing(type="int") @VintfStability
+enum UIOption {
+ ACCESSIBILITY_INVERTED = 0,
+ ACCESSIBILITY_MAGNIFIED = 1,
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl
new file mode 100644
index 0000000..2165fdd
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationResultCallback.aidl
@@ -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.
+ */
+
+package android.hardware.confirmationui;
+
+import android.hardware.confirmationui.IConfirmationUI;
+
+/**
+ * Callback interface passed to IConfirmationUI::promptUserConfirmation().
+ * Informs the caller about the result of the prompt operation.
+ */
+@VintfStability
+interface IConfirmationResultCallback {
+ /**
+ * This callback is called by the confirmation provider when it stops prompting the user.
+ * Iff the user has confirmed the prompted text, error is ErrorCode::OK and the
+ * parameters formattedMessage and confirmationToken hold the values needed to request
+ * a signature from keymaster.
+ * In all other cases formattedMessage and confirmationToken must be of length 0.
+ *
+ * @param error - OK: IFF the user has confirmed the prompt.
+ * - CANCELED: If the user has pressed the cancel button.
+ * - ABORTED: If IConfirmationUI::abort() was called.
+ * - SYSTEM_ERROR: If an unexpected System error occurred that prevented the TUI
+ * from being shut down gracefully.
+ *
+ * @param formattedMessage holds the prompt text and extra data.
+ * The message is CBOR (RFC 7049) encoded and has the following format:
+ * CBOR_MAP{ "prompt", <promptText>, "extra", <extraData> }
+ * The message is a CBOR encoded map (type 5) with the keys
+ * "prompt" and "extra". The keys are encoded as CBOR text string
+ * (type 3). The value <promptText> is encoded as CBOR text string
+ * (type 3), and the value <extraData> is encoded as CBOR byte string
+ * (type 2). The map must have exactly one key value pair for each of
+ * the keys "prompt" and "extra". Other keys are not allowed.
+ * The value of "prompt" is given by the proptText argument to
+ * IConfirmationUI::promptUserConfirmation and must not be modified
+ * by the implementation.
+ * The value of "extra" is given by the extraData argument to
+ * IConfirmationUI::promptUserConfirmation and must not be modified
+ * or interpreted by the implementation.
+ *
+ * @param confirmationToken a 32-byte HMAC-SHA256 value, computed over
+ * "confirmation token" || <formattedMessage>
+ * i.e. the literal UTF-8 encoded string "confirmation token", without
+ * the "", concatenated with the formatted message as returned in the
+ * formattedMessage argument. The HMAC is keyed with a 256-bit secret
+ * which is shared with Keymaster. In test mode the test key MUST be
+ * used (see types.hal TestModeCommands and
+ * IConfirmationUI::TEST_KEY_BYTE).
+ */
+ void result(in int error, in byte[] formattedMessage, in byte[] confirmationToken);
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/IConfirmationUI.aidl b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationUI.aidl
new file mode 100644
index 0000000..f071126
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/IConfirmationUI.aidl
@@ -0,0 +1,146 @@
+/*
+ * 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.confirmationui;
+
+import android.hardware.confirmationui.IConfirmationResultCallback;
+import android.hardware.confirmationui.UIOption;
+import android.hardware.security.keymint.HardwareAuthToken;
+
+@VintfStability
+interface IConfirmationUI {
+ // Possible Errors.
+ /**
+ * API call succeeded or the user gave approval (result callback).
+ */
+ const int OK = 0;
+ /**
+ * The user canceled the TUI (result callback).
+ */
+ const int CANCELED = 1;
+ /**
+ * IConfirmationUI::abort() was called. (result callback).
+ */
+ const int ABORTED = 2;
+ /**
+ * Cannot start another prompt.
+ */
+ const int OPERATION_PENDING = 3;
+ /**
+ * IConfirmationUI::deliverSecureInputEvent call was ignored.
+ */
+ const int IGNORED = 4;
+ /**
+ * An unexpected system error occurred.
+ */
+ const int SYSTEM_ERROR = 5;
+ /**
+ * Returned by an unimplemented API call.
+ */
+ const int UNIMPLEMENTED = 6;
+ /**
+ * This is returned when an error is diagnosed that should have been
+ * caught by earlier input sanitization. Should never be seen in production.
+ */
+ const int UNEXPECTED = 7;
+ /**
+ * General UI error.
+ */
+ const int UI_ERROR = 0x10000;
+ /**
+ * This is returned if there is no corresponding glyph for a character.
+ */
+ const int UI_ERROR_MISSING_GLYPH = 0x10001;
+ /**
+ * The implementation must return this error code on promptUserConfirmation if the
+ * resulting formatted message does not fit into MAX_MESSAGE_SIZE bytes. It is
+ * advised that the implementation formats the message upon receiving this API call to
+ * be able to diagnose this syndrome.
+ */
+ const int UI_ERROR_MESSAGE_TOO_LONG = 0x10002;
+ /**
+ * This is returned if the UTF8 encoding is malformed.
+ */
+ const int UI_ERROR_MALFORMED_UTF8ENCODING = 0x10003;
+
+ // Constants
+ /**
+ * The test key is 32byte word with all bytes set to TEST_KEY_BYTE.
+ */
+ const int TEST_KEY_BYTE = 0xA5;
+ /**
+ * This defines the maximum message size. This indirectly limits the size of the prompt text
+ * and the extra data that can be passed to the confirmation UI. The prompt text and extra data
+ * must fit in to this size including CBOR header information.
+ */
+ const int MAX_MESSAGE_SIZE = 0x1800;
+
+ /**
+ * Aborts a pending user prompt. This allows the framework to gracefully end a TUI dialog.
+ * If a TUI operation was pending the corresponding call back is informed with
+ * ErrorCode::Aborted.
+ */
+ void abort();
+
+ /**
+ * DeliverSecureInput is used by the framework to deliver a secure input event to the
+ * confirmation provider.
+ *
+ * VTS test mode:
+ * This function can be used to test certain code paths non-interactively.
+ * See TestModeCommands.aidl for details.
+ *
+ * @param secureInputToken An authentication token as generated by Android authentication
+ * providers.
+ */
+ void deliverSecureInputEvent(in HardwareAuthToken secureInputToken);
+
+ /**
+ * Asynchronously initiates a confirmation UI dialog prompting the user to confirm a given text.
+ * The TUI prompt must be implemented in such a way that a positive response indicates with
+ * high confidence that a user has seen the given prompt text even if the Android framework
+ * including the kernel was compromised.
+ *
+ * Service status return:
+ *
+ * OK IFF the dialog was successfully started. In this case, and only in this
+ * case, the implementation must, eventually, call the callback to
+ * indicate completion.
+ * OPERATION_PENDING is returned when the confirmation provider is currently
+ * in use.
+ * SYSTEM_ERROR an error occurred trying to communicate with the confirmation
+ * provider (e.g. trusted app).
+ * UI_ERROR the confirmation provider encountered an issue with displaying
+ * the prompt text to the user.
+ *
+ * @param resultCB Implementation of IResultCallback. Used by the implementation to report
+ * the result of the current pending user prompt.
+ *
+ * @param promptText UTF-8 encoded bytes which is to be presented to the user.
+ *
+ * @param extraData A binary blob that must be included in the formatted output message as is.
+ * It is opaque to the implementation. Implementations must neither interpret
+ * nor modify the content.
+ *
+ * @param locale String specifying the locale that must be used by the TUI dialog. The string
+ * is an IETF BCP 47 tag.
+ *
+ * @param uiOptions A set of uiOptions manipulating how the confirmation prompt is displayed.
+ * Refer to UIOption in types.hal for possible options.
+ */
+ void promptUserConfirmation(in IConfirmationResultCallback resultCB, in byte[] promptText,
+ in byte[] extraData, in @utf8InCpp String locale, in UIOption[] uiOptions);
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/TestModeCommands.aidl b/confirmationui/aidl/android/hardware/confirmationui/TestModeCommands.aidl
new file mode 100644
index 0000000..5b1d8fb
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/TestModeCommands.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.confirmationui;
+
+/**
+ * Test mode commands.
+ *
+ * IConfirmationUI::deliverSecureInputEvent can be used to test certain code paths.
+ * To that end, the caller passes an auth token that has an HMAC keyed with the test key
+ * (see IConfirmationUI::TEST_KEY_BYTE). Implementations first check the HMAC against test key.
+ * If the test key produces a matching HMAC, the implementation evaluates the challenge field
+ * of the auth token against the values defined in TestModeCommand.
+ * If the command indicates that a confirmation token is to be generated the test key MUST be used
+ * to generate this confirmation token.
+ *
+ * See command code for individual test command descriptions.
+ */
+@VintfStability
+@Backing(type="int")
+enum TestModeCommands {
+ /**
+ * Simulates the user pressing the OK button on the UI. If no operation is pending
+ * ResponseCode::Ignored must be returned. A pending operation is finalized successfully
+ * see IConfirmationResultCallback::result, however, the test key
+ * (see IConfirmationUI::TEST_KEY_BYTE) MUST be used to generate the confirmation token.
+ */
+ OK_EVENT = 0,
+ /**
+ * Simulates the user pressing the CANCEL button on the UI. If no operation is pending
+ * Result::Ignored must be returned. A pending operation is finalized as specified in
+ * IConfirmationResultCallback.hal.
+ */
+ CANCEL_EVENT = 1,
+}
diff --git a/confirmationui/aidl/android/hardware/confirmationui/UIOption.aidl b/confirmationui/aidl/android/hardware/confirmationui/UIOption.aidl
new file mode 100644
index 0000000..b242c53
--- /dev/null
+++ b/confirmationui/aidl/android/hardware/confirmationui/UIOption.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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.confirmationui;
+
+/**
+ * UI modification options.
+ */
+@VintfStability
+@Backing(type="int")
+enum UIOption {
+ /**
+ * Accessibility: Requests color inverted style.
+ */
+ ACCESSIBILITY_INVERTED = 0,
+ /**
+ * Accessibility: Requests magnified style.
+ */
+ ACCESSIBILITY_MAGNIFIED = 1,
+}
diff --git a/confirmationui/aidl/vts/functional/Android.bp b/confirmationui/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..3649c87
--- /dev/null
+++ b/confirmationui/aidl/vts/functional/Android.bp
@@ -0,0 +1,45 @@
+//
+// 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
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalConfirmationUITargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "keymint_use_latest_hal_aidl_ndk_shared",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "VtsHalConfirmationUITargetTest.cpp",
+ ],
+ static_libs: [
+ "android.hardware.confirmationui-V1-ndk",
+ "libcn-cbor",
+ "android.hardware.confirmationui-support-lib",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "libcrypto",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp b/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
new file mode 100644
index 0000000..61dae8b
--- /dev/null
+++ b/confirmationui/aidl/vts/functional/VtsHalConfirmationUITargetTest.cpp
@@ -0,0 +1,535 @@
+/*
+ * 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 "ConfirmationIOAidlHalTest"
+
+#include <algorithm>
+#include <condition_variable>
+#include <future>
+#include <iostream>
+#include <memory>
+#include <mutex>
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/confirmationui/BnConfirmationResultCallback.h>
+#include <aidl/android/hardware/confirmationui/IConfirmationUI.h>
+#include <aidl/android/hardware/confirmationui/TestModeCommands.h>
+#include <aidl/android/hardware/confirmationui/UIOption.h>
+#include <android-base/thread_annotations.h>
+#include <android/hardware/confirmationui/support/confirmationui_utils.h>
+#include <cutils/log.h>
+
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+
+#include <cn-cbor/cn-cbor.h>
+
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_status.h>
+
+static constexpr int TIMEOUT_PERIOD = 10;
+
+namespace aidl::android::hardware::confirmationui::test {
+using ::aidl::android::hardware::security::keymint::HardwareAuthenticatorType;
+using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
+using ::android::hardware::confirmationui::support::auth_token_key_t;
+using ::android::hardware::confirmationui::support::ByteBufferProxy;
+using ::android::hardware::confirmationui::support::HMac;
+using ::android::hardware::confirmationui::support::hmac_t;
+using ::android::hardware::confirmationui::support::hton;
+using ::android::hardware::confirmationui::support::NullOr;
+using std::shared_ptr;
+using std::string;
+using std::vector;
+
+namespace {
+const auth_token_key_t testKey(static_cast<uint8_t>(IConfirmationUI::TEST_KEY_BYTE));
+
+class HMacImplementation {
+ public:
+ static NullOr<hmac_t> hmac256(const auth_token_key_t& key,
+ std::initializer_list<ByteBufferProxy> buffers) {
+ HMAC_CTX hmacCtx;
+ HMAC_CTX_init(&hmacCtx);
+ if (!HMAC_Init_ex(&hmacCtx, key.data(), key.size(), EVP_sha256(), nullptr)) {
+ return {};
+ }
+ for (auto& buffer : buffers) {
+ if (!HMAC_Update(&hmacCtx, buffer.data(), buffer.size())) {
+ return {};
+ }
+ }
+ hmac_t result;
+ if (!HMAC_Final(&hmacCtx, result.data(), nullptr)) {
+ return {};
+ }
+ return result;
+ }
+};
+
+using HMacer = HMac<HMacImplementation>;
+
+template <typename... Data>
+vector<uint8_t> testHMAC(const Data&... data) {
+ auto hmac = HMacer::hmac256(testKey, data...);
+ if (!hmac.isOk()) {
+ ADD_FAILURE() << "Failed to compute test hmac. This is a self-test error.";
+ return {};
+ }
+ vector<uint8_t> result(hmac.value().size());
+ std::copy(hmac.value().data(), hmac.value().data() + hmac.value().size(), result.data());
+ return result;
+}
+
+template <typename T>
+auto toBytes(const T& v) -> const uint8_t (&)[sizeof(T)] {
+ return *reinterpret_cast<const uint8_t(*)[sizeof(T)]>(&v);
+}
+
+HardwareAuthToken makeTestToken(const TestModeCommands command, uint64_t timestamp = 0) {
+ HardwareAuthToken auth_token;
+ auth_token.challenge = static_cast<uint64_t>(command);
+ auth_token.userId = 0;
+ auth_token.authenticatorId = 0;
+ auth_token.authenticatorType = HardwareAuthenticatorType::NONE;
+ auth_token.timestamp = {static_cast<int64_t>(timestamp)};
+
+ // Canonical form of auth-token v0
+ // version (1 byte)
+ // challenge (8 bytes)
+ // user_id (8 bytes)
+ // authenticator_id (8 bytes)
+ // authenticator_type (4 bytes)
+ // timestamp (8 bytes)
+ // total 37 bytes
+ auth_token.mac = testHMAC("\0",
+ toBytes(auth_token.challenge), //
+ toBytes(auth_token.userId), //
+ toBytes(auth_token.authenticatorId), //
+ toBytes(hton(auth_token.authenticatorType)), //
+ toBytes(hton(auth_token.timestamp))); //
+
+ return auth_token;
+}
+
+#define DEBUG_CONFRIMATIONUI_UTILS_TEST
+
+#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
+std::ostream& hexdump(std::ostream& out, const uint8_t* data, size_t size) {
+ for (size_t i = 0; i < size; ++i) {
+ uint8_t byte = data[i];
+ out << std::hex << std::setw(2) << std::setfill('0') << (unsigned)byte;
+ switch (i & 0xf) {
+ case 0xf:
+ out << "\n";
+ break;
+ case 7:
+ out << " ";
+ break;
+ default:
+ out << " ";
+ break;
+ }
+ }
+ return out;
+}
+#endif
+
+constexpr char hex_value[256] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, // '0'..'9'
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'A'..'F'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 10, 11, 12, 13, 14, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 'a'..'f'
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+std::string hex2str(std::string a) {
+ std::string b;
+ size_t num = a.size() / 2;
+ b.resize(num);
+ for (size_t i = 0; i < num; i++) {
+ b[i] = (hex_value[a[i * 2] & 0xFF] << 4) + (hex_value[a[i * 2 + 1] & 0xFF]);
+ }
+ return b;
+}
+
+int getReturnCode(const ::ndk::ScopedAStatus& result) {
+ if (result.isOk()) return IConfirmationUI::OK;
+
+ if (result.getExceptionCode() == EX_SERVICE_SPECIFIC) {
+ return static_cast<int>(result.getServiceSpecificError());
+ }
+ return result.getStatus();
+}
+
+} // namespace
+
+class ConfirmationUIAidlTest : public ::testing::TestWithParam<std::string> {
+ public:
+ void TearDown() override { confirmator_->abort(); }
+ void SetUp() override {
+ std::string name = GetParam();
+ ASSERT_TRUE(AServiceManager_isDeclared(name.c_str())) << name;
+ ndk::SpAIBinder binder(AServiceManager_waitForService(name.c_str()));
+ ASSERT_NE(binder, nullptr);
+ confirmator_ = IConfirmationUI::fromBinder(binder);
+ ASSERT_NE(confirmator_, nullptr);
+ }
+
+ // 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() {
+ std::unique_lock<std::mutex> lock(mtx_);
+ auto now = std::chrono::system_clock::now();
+ std::cv_status status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+ return status;
+ }
+
+ protected:
+ shared_ptr<IConfirmationUI> confirmator_;
+
+ private:
+ // synchronization objects
+ std::mutex mtx_;
+ std::condition_variable cv_;
+};
+
+class ConfirmationTestCallback
+ : public ::aidl::android::hardware::confirmationui::BnConfirmationResultCallback {
+ public:
+ ConfirmationTestCallback(ConfirmationUIAidlTest& parent) : parent_(parent){};
+ virtual ~ConfirmationTestCallback() = default;
+
+ ::ndk::ScopedAStatus result(int32_t err, const vector<uint8_t>& msg,
+ const vector<uint8_t>& confToken) override {
+ error_ = err;
+ formattedMessage_ = msg;
+ confirmationToken_ = confToken;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+
+ bool verifyConfirmationToken() {
+ static constexpr char confirmationPrefix[] = "confirmation token";
+ EXPECT_EQ(32U, confirmationToken_.size());
+ return 32U == confirmationToken_.size() &&
+ !memcmp(confirmationToken_.data(),
+ testHMAC(confirmationPrefix, formattedMessage_).data(), 32);
+ }
+
+ int error_;
+ vector<uint8_t> formattedMessage_;
+ vector<uint8_t> confirmationToken_;
+
+ private:
+ ConfirmationUIAidlTest& parent_;
+};
+
+struct CnCborDeleter {
+ void operator()(cn_cbor* ptr) { cn_cbor_free(ptr); }
+};
+
+typedef std::unique_ptr<cn_cbor, CnCborDeleter> CnCborPtr;
+
+// Simulates the User taping Ok
+TEST_P(ConfirmationUIAidlTest, UserOkTest) {
+ static constexpr char test_prompt[] = "Me first, gimme gimme!";
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+ // Simulate the user taping ok.
+ ASSERT_TRUE(confirmator_->deliverSecureInputEvent(makeTestToken(TestModeCommands::OK_EVENT))
+ .isOk());
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::OK, conf_cb->error_);
+
+ ASSERT_TRUE(conf_cb->verifyConfirmationToken());
+
+ cn_cbor_errback cn_cbor_error;
+ auto parsed_message = CnCborPtr(cn_cbor_decode(
+ conf_cb->formattedMessage_.data(), conf_cb->formattedMessage_.size(), &cn_cbor_error));
+ // is parsable CBOR
+ ASSERT_TRUE(parsed_message.get());
+ // is a map
+ ASSERT_EQ(CN_CBOR_MAP, parsed_message->type);
+
+ // the message must have exactly 2 key value pairs.
+ // cn_cbor holds 2*<no_of_pairs> in the length field
+ ASSERT_EQ(4, parsed_message->length);
+ // map has key "prompt"
+ auto prompt = cn_cbor_mapget_string(parsed_message.get(), "prompt");
+ ASSERT_TRUE(prompt);
+ ASSERT_EQ(CN_CBOR_TEXT, prompt->type);
+ ASSERT_EQ(22, prompt->length);
+ ASSERT_EQ(0, memcmp(test_prompt, prompt->v.str, 22));
+ // map has key "extra"
+ auto extra_out = cn_cbor_mapget_string(parsed_message.get(), "extra");
+ ASSERT_TRUE(extra_out);
+ ASSERT_EQ(CN_CBOR_BYTES, extra_out->type);
+ ASSERT_EQ(3, extra_out->length);
+ ASSERT_EQ(0, memcmp(test_extra, extra_out->v.bytes, 3));
+}
+
+// Initiates a confirmation prompt with a message that is too long
+TEST_P(ConfirmationUIAidlTest, MessageTooLongTest) {
+ static constexpr uint8_t test_extra[IConfirmationUI::MAX_MESSAGE_SIZE] = {};
+ static constexpr char test_prompt[] = "D\'oh!";
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
+ auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+ ASSERT_EQ(IConfirmationUI::UI_ERROR_MESSAGE_TOO_LONG, getReturnCode(result));
+}
+
+// If the message gets very long some HAL implementations might fail even before the message
+// reaches the trusted app implementation. But the HAL must still diagnose the correct error.
+TEST_P(ConfirmationUIAidlTest, MessageWayTooLongTest) {
+ static constexpr uint8_t test_extra[(IConfirmationUI::MAX_MESSAGE_SIZE)*10] = {};
+ static constexpr char test_prompt[] = "D\'oh!";
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + sizeof(test_extra));
+ auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+ ASSERT_EQ(IConfirmationUI::UI_ERROR_MESSAGE_TOO_LONG, getReturnCode(result));
+}
+
+// Simulates the User tapping the Cancel
+TEST_P(ConfirmationUIAidlTest, UserCancelTest) {
+ static constexpr char test_prompt[] = "Me first, gimme gimme!";
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+ // Simulate the user taping ok.
+ ASSERT_TRUE(confirmator_->deliverSecureInputEvent(makeTestToken(TestModeCommands::CANCEL_EVENT))
+ .isOk());
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::CANCELED, conf_cb->error_);
+
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Simulates the framework cancelling an ongoing prompt
+TEST_P(ConfirmationUIAidlTest, AbortTest) {
+ static constexpr char test_prompt[] = "Me first, gimme gimme!";
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
+// the design guidelines.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest1) {
+ static constexpr char test_prompt[] =
+ "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
+ "WWWWWWWWWWWWWW";
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 100 'W' characters as required by
+// the design guidelines in magnified mode.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest1Magnified) {
+ static constexpr char test_prompt[] =
+ "WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW"
+ "WWWWWWWWWWWWWW";
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_
+ ->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+ {UIOption::ACCESSIBILITY_MAGNIFIED})
+ .isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
+// required by the design guidelines.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest2) {
+ static constexpr char test_prompt[] =
+ "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
+ "WWWWWWWWWWWW WWWWWWWWWWWW";
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {}).isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Tests if the confirmation dialog can successfully render 8 groups of 12 'W' characters as
+// required by the design guidelines in magnified mode.
+TEST_P(ConfirmationUIAidlTest, PortableMessageTest2Magnified) {
+ static constexpr char test_prompt[] =
+ "WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW WWWWWWWWWWWW "
+ "WWWWWWWWWWWW WWWWWWWWWWWW";
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ ASSERT_TRUE(confirmator_
+ ->promptUserConfirmation(conf_cb, prompt_text, extra, "en",
+ {UIOption::ACCESSIBILITY_MAGNIFIED})
+ .isOk());
+
+ confirmator_->abort();
+
+ // Wait for the callback.
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ ASSERT_EQ(IConfirmationUI::ABORTED, conf_cb->error_);
+ ASSERT_EQ(0U, conf_cb->confirmationToken_.size());
+ ASSERT_EQ(0U, conf_cb->formattedMessage_.size());
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string that ends in the middle of a multibyte character
+TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test1) {
+ static constexpr char test_prompt[] = {char(0xc0), 0};
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+ ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string with a 5-byte character.
+TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test2) {
+ static constexpr char test_prompt[] = {char(0xf8), char(0x82), char(0x82),
+ char(0x82), char(0x82), 0};
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+ ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
+}
+
+// Passing malformed UTF-8 to the confirmation UI
+// This test passes a string with a 2-byte character followed by a stray non UTF-8 character.
+TEST_P(ConfirmationUIAidlTest, MalformedUTF8Test3) {
+ static constexpr char test_prompt[] = {char(0xc0), char(0x82), char(0x83), 0};
+ static constexpr uint8_t test_extra[] = {0x1, 0x2, 0x3};
+ shared_ptr<ConfirmationTestCallback> conf_cb =
+ ::ndk::SharedRefBase::make<ConfirmationTestCallback>(*this);
+ vector<uint8_t> prompt_text(test_prompt, test_prompt + strlen(test_prompt));
+ vector<uint8_t> extra(test_extra, test_extra + 3);
+ auto result = confirmator_->promptUserConfirmation(conf_cb, prompt_text, extra, "en", {});
+ ASSERT_EQ(IConfirmationUI::UI_ERROR_MALFORMED_UTF8ENCODING, getReturnCode(result));
+}
+
+// Test the implementation of HMAC SHA 256 against a golden blob.
+TEST(ConfirmationUITestSelfTest, HMAC256SelfTest) {
+ const char key_str[32] = "keykeykeykeykeykeykeykeykeykeyk";
+ const uint8_t(&key)[32] = *reinterpret_cast<const uint8_t(*)[32]>(key_str);
+ auto expected = hex2str("2377fbcaa7fb3f6c20cfa1d9ebc60e9922cf58c909e25e300f3cb57f7805c886");
+ auto result = HMacer::hmac256(key, "value1", "value2", "value3");
+
+#ifdef DEBUG_CONFRIMATIONUI_UTILS_TEST
+ hexdump(std::cout, reinterpret_cast<const uint8_t*>(expected.data()), 32) << std::endl;
+ hexdump(std::cout, result.value().data(), 32) << std::endl;
+#endif
+
+ ByteBufferProxy expected_bytes(expected);
+ ASSERT_TRUE(result.isOk());
+ ASSERT_EQ(expected, result.value());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ConfirmationUIAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, ConfirmationUIAidlTest,
+ testing::ValuesIn(::android::getAidlHalInstanceNames(IConfirmationUI::descriptor)),
+ ::android::PrintInstanceNameToString);
+
+} // namespace aidl::android::hardware::confirmationui::test
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/current.txt b/current.txt
index afde7b1..146ded6 100644
--- a/current.txt
+++ b/current.txt
@@ -929,4 +929,7 @@
1bac6a7c8136dfb0414fe5639eec115aa2d12927e64a0642a43fb53225f099b2 android.hardware.wifi@1.6::IWifiStaIface
0a800e010e8eb6eecdfdc96f04fd2ae2f417a79a74a7c0eec3a9f539199bccd4 android.hardware.wifi@1.6::types
+# ABI preserving changes to HALs during Android U
+2aa559cda86c358c6429114ef6bc72c1b43281e98f9eb6b4df5e7073c8d05767 android.hardware.automotive.vehicle@2.0::types
+
# There will be no more HIDL HALs. Use AIDL instead.
diff --git a/fastboot/OWNERS b/fastboot/OWNERS
new file mode 100644
index 0000000..286b65f
--- /dev/null
+++ b/fastboot/OWNERS
@@ -0,0 +1,4 @@
+# Bug component: 1228891
+dvander@google.com
+elsk@google.com
+dhavale@google.com
diff --git a/fastboot/aidl/Android.bp b/fastboot/aidl/Android.bp
new file mode 100644
index 0000000..a5735ab
--- /dev/null
+++ b/fastboot/aidl/Android.bp
@@ -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.
+
+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.fastboot",
+ vendor_available: true,
+ recovery_available: true,
+ srcs: ["android/hardware/fastboot/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ enabled: false,
+ },
+ },
+}
diff --git a/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.aidl
new file mode 100644
index 0000000..b15d037
--- /dev/null
+++ b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/FileSystemType.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.fastboot;
+@Backing(type="byte") @VintfStability
+enum FileSystemType {
+ EXT4 = 0,
+ F2FS = 1,
+ RAW = 2,
+}
diff --git a/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl
new file mode 100644
index 0000000..445fcde
--- /dev/null
+++ b/fastboot/aidl/aidl_api/android.hardware.fastboot/current/android/hardware/fastboot/IFastboot.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.fastboot;
+@VintfStability
+interface IFastboot {
+ String doOemCommand(in String oemCmd);
+ void doOemSpecificErase();
+ int getBatteryVoltageFlashingThreshold();
+ boolean getOffModeChargeState();
+ android.hardware.fastboot.FileSystemType getPartitionType(in String partitionName);
+ String getVariant();
+ const int FAILURE_UNKNOWN = 1;
+}
diff --git a/fastboot/aidl/android/hardware/fastboot/FileSystemType.aidl b/fastboot/aidl/android/hardware/fastboot/FileSystemType.aidl
new file mode 100644
index 0000000..b4027ec
--- /dev/null
+++ b/fastboot/aidl/android/hardware/fastboot/FileSystemType.aidl
@@ -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.fastboot;
+
+@VintfStability
+@Backing(type="byte")
+enum FileSystemType {
+ /**
+ * Fourth extended file system.
+ */
+ EXT4,
+ /**
+ * Flash Friendly File System.
+ */
+ F2FS,
+ /**
+ * Raw file system.
+ */
+ RAW,
+}
diff --git a/fastboot/aidl/android/hardware/fastboot/IFastboot.aidl b/fastboot/aidl/android/hardware/fastboot/IFastboot.aidl
new file mode 100644
index 0000000..abdc215
--- /dev/null
+++ b/fastboot/aidl/android/hardware/fastboot/IFastboot.aidl
@@ -0,0 +1,94 @@
+/*
+ * 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.fastboot;
+
+import android.hardware.fastboot.FileSystemType;
+
+/**
+ * IFastboot interface implements vendor specific fastboot commands.
+ */
+@VintfStability
+interface IFastboot {
+ /**
+ * Status code for function.
+ * Operation failed due to unknown reason.
+ */
+ const int FAILURE_UNKNOWN = 1;
+ /**
+ * Executes a fastboot OEM command.
+ *
+ * @param oemCmd The oem command that is passed to the fastboot HAL.
+ * @return optional String if the operation is successful and output is expected
+ * for the command.
+ * @throws :
+ * - EX_ILLEGAL_ARGUMENT for bad arguments.
+ * - EX_UNSUPPORTED_OPERATION for unsupported commands.
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN for other errors.
+ */
+ String doOemCommand(in String oemCmd);
+
+ /**
+ * Executes an OEM specific erase after fastboot erase userdata.
+ *
+ * @throws :
+ * - EX_UNSUPPORTED_OPERATION if it is not supported.
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN for
+ * unknown error in oem specific command or other errors.
+ */
+ void doOemSpecificErase();
+
+ /**
+ * Returns the minimum battery voltage required for flashing in mV.
+ *
+ * @return Minimum batterery voltage (in mV) required for flashing to
+ * be successful.
+ * @throws :
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if error.
+ */
+ int getBatteryVoltageFlashingThreshold();
+
+ /**
+ * Returns whether off-mode-charging is enabled. If enabled, the device
+ * autoboots into a special mode when power is applied.
+ *
+ * @return Returns whether off-mode-charging is enabled.
+ * @throws :
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if error.
+ */
+ boolean getOffModeChargeState();
+
+ /**
+ * Returns the file system type of the partition. Implementation is only
+ * required for physical partitions that need to be wiped and reformatted.
+ * @param in partitionName Name of the partition.
+ * @return Returns the file system type of the partition. Type can be ext4,
+ * f2fs or raw.
+ * @throws :
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if the partition
+ * is invalid or does not require reformatting.
+ */
+ FileSystemType getPartitionType(in String partitionName);
+
+ /**
+ * Returns an OEM-defined string indicating the variant of the device, for
+ * example, US and ROW.
+ * @return Indicates the device variant.
+ * @throws :
+ * - EX_SERVICE_SPECIFIC with status FAILURE_UNKNOWN if error.
+ */
+ String getVariant();
+}
diff --git a/fastboot/aidl/default/Android.bp b/fastboot/aidl/default/Android.bp
new file mode 100644
index 0000000..0c96b33
--- /dev/null
+++ b/fastboot/aidl/default/Android.bp
@@ -0,0 +1,43 @@
+//
+// 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_binary {
+ name: "android.hardware.fastboot-service.example_recovery",
+ init_rc: ["android.hardware.fastboot-service.example_recovery.rc"],
+ vintf_fragments: ["android.hardware.fastboot-service.example.xml"],
+ recovery_available: true,
+ srcs: [
+ "Fastboot.cpp",
+ "main.cpp",
+ ],
+ relative_install_path: "hw",
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "liblog",
+ "libutils",
+ "libcutils",
+ "android.hardware.fastboot-V1-ndk",
+ ],
+}
diff --git a/fastboot/aidl/default/Fastboot.cpp b/fastboot/aidl/default/Fastboot.cpp
new file mode 100644
index 0000000..1ba73d3
--- /dev/null
+++ b/fastboot/aidl/default/Fastboot.cpp
@@ -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.
+ */
+
+#include "Fastboot.h"
+
+using ndk::ScopedAStatus;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace fastboot {
+
+ScopedAStatus Fastboot::getPartitionType(const std::string& in_partitionName,
+ FileSystemType* _aidl_return) {
+ if (in_partitionName.empty()) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "Invalid partition name");
+ }
+ *_aidl_return = FileSystemType::RAW;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::doOemCommand(const std::string& in_oemCmd, std::string* _aidl_return) {
+ *_aidl_return = "";
+ if (in_oemCmd.empty()) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, "Invalid command");
+ }
+ return ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_UNSUPPORTED_OPERATION, "Command not supported in default implementation");
+}
+
+ScopedAStatus Fastboot::getVariant(std::string* _aidl_return) {
+ *_aidl_return = "NA";
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::getOffModeChargeState(bool* _aidl_return) {
+ *_aidl_return = false;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::getBatteryVoltageFlashingThreshold(int32_t* _aidl_return) {
+ *_aidl_return = 0;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Fastboot::doOemSpecificErase() {
+ return ScopedAStatus::fromExceptionCodeWithMessage(
+ EX_UNSUPPORTED_OPERATION, "Command not supported in default implementation");
+}
+
+} // namespace fastboot
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/fastboot/aidl/default/Fastboot.h b/fastboot/aidl/default/Fastboot.h
new file mode 100644
index 0000000..48e2c38
--- /dev/null
+++ b/fastboot/aidl/default/Fastboot.h
@@ -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.
+ */
+
+#pragma once
+
+#include "aidl/android/hardware/fastboot/BnFastboot.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace fastboot {
+class Fastboot : public BnFastboot {
+ ::ndk::ScopedAStatus doOemCommand(const std::string& in_oemCmd,
+ std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus doOemSpecificErase() override;
+ ::ndk::ScopedAStatus getBatteryVoltageFlashingThreshold(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getOffModeChargeState(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getPartitionType(
+ const std::string& in_partitionName,
+ ::aidl::android::hardware::fastboot::FileSystemType* _aidl_return) override;
+ ::ndk::ScopedAStatus getVariant(std::string* _aidl_return) override;
+};
+
+} // namespace fastboot
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/fastboot/aidl/default/android.hardware.fastboot-service.example.xml b/fastboot/aidl/default/android.hardware.fastboot-service.example.xml
new file mode 100644
index 0000000..9490f98
--- /dev/null
+++ b/fastboot/aidl/default/android.hardware.fastboot-service.example.xml
@@ -0,0 +1,8 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.fastboot</name>
+ <version>1</version>
+ <fqname>IFastboot/default</fqname>
+ </hal>
+</manifest>
+
diff --git a/fastboot/aidl/default/android.hardware.fastboot-service.example_recovery.rc b/fastboot/aidl/default/android.hardware.fastboot-service.example_recovery.rc
new file mode 100644
index 0000000..5d4ee13
--- /dev/null
+++ b/fastboot/aidl/default/android.hardware.fastboot-service.example_recovery.rc
@@ -0,0 +1,6 @@
+service vendor.fastboot-default /system/bin/hw/android.hardware.fastboot-service.example_recovery
+ class hal
+ seclabel u:r:hal_fastboot_default:s0
+ user system
+ group system
+ interface aidl android.hardware.fastboot.IFastboot/default
diff --git a/fastboot/aidl/default/main.cpp b/fastboot/aidl/default/main.cpp
new file mode 100644
index 0000000..1b1b41d
--- /dev/null
+++ b/fastboot/aidl/default/main.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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include "Fastboot.h"
+
+using aidl::android::hardware::fastboot::Fastboot;
+using aidl::android::hardware::fastboot::IFastboot;
+
+int main(int, char* argv[]) {
+ android::base::InitLogging(argv, android::base::KernelLogger);
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ std::shared_ptr<IFastboot> service = ndk::SharedRefBase::make<Fastboot>();
+
+ const std::string instance = std::string(IFastboot::descriptor) + "/default";
+ auto status = AServiceManager_addService(service->asBinder().get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK) << "Failed to add service " << instance << " " << status;
+ LOG(INFO) << "IFastboot AIDL service running...";
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/fastboot/aidl/fastbootshim/Android.bp b/fastboot/aidl/fastbootshim/Android.bp
new file mode 100644
index 0000000..c843c12
--- /dev/null
+++ b/fastboot/aidl/fastbootshim/Android.bp
@@ -0,0 +1,61 @@
+// 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_defaults {
+ name: "libfastbootshim_defaults",
+ target: {
+ darwin: {
+ enabled: false,
+ },
+ },
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ static_libs: [
+ "android.hardware.fastboot-V1-ndk",
+ "android.hardware.fastboot@1.0",
+ "android.hardware.fastboot@1.1",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "libhidlbase",
+ "liblog",
+ "libutils",
+ ],
+}
+
+// Shim library that wraps a HIDL Fastboot object into an AIDL Fastboot object.
+cc_library_static {
+ name: "libfastbootshim",
+ defaults: ["libfastbootshim_defaults"],
+ recovery_available: true,
+ srcs: [
+ "fastbootshim.cpp",
+ ],
+ export_include_dirs: [
+ "include",
+ ],
+}
diff --git a/fastboot/aidl/fastbootshim/fastbootshim.cpp b/fastboot/aidl/fastbootshim/fastbootshim.cpp
new file mode 100644
index 0000000..4ab67f3
--- /dev/null
+++ b/fastboot/aidl/fastbootshim/fastbootshim.cpp
@@ -0,0 +1,123 @@
+/*
+ * 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 <fastbootshim.h>
+
+using ::android::sp;
+using ::android::hardware::hidl_string;
+using ::android::hardware::Void;
+using ::android::hardware::fastboot::V1_0::FileSystemType;
+using ::android::hardware::fastboot::V1_0::Result;
+using ::android::hardware::fastboot::V1_0::Status;
+
+using ndk::ScopedAStatus;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace fastboot {
+ScopedAStatus ResultToAStatus(Result result) {
+ switch (result.status) {
+ case Status::SUCCESS:
+ return ScopedAStatus::ok();
+ case Status::NOT_SUPPORTED:
+ return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ case Status::INVALID_ARGUMENT:
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ case Status::FAILURE_UNKNOWN:
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ BnFastboot::FAILURE_UNKNOWN, ("Error " + std::string(result.message)).c_str());
+ }
+ return ScopedAStatus::fromServiceSpecificErrorWithMessage(
+ BnFastboot::FAILURE_UNKNOWN,
+ ("Unrecognized status value " + toString(result.status)).c_str());
+}
+FastbootShim::FastbootShim(const sp<HidlFastboot>& service) : service_(service) {}
+
+ScopedAStatus FastbootShim::getPartitionType(const std::string& in_partitionName,
+ FileSystemType* _aidl_return) {
+ Result out_result = {Status::FAILURE_UNKNOWN, ""};
+ if (in_partitionName.empty()) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT,
+ "Invalid partition name");
+ }
+ const hidl_string partition = in_partitionName;
+ auto ret = service_->getPartitionType(partition, [&](auto type, auto& result) {
+ out_result = result;
+ if (out_result.status != Status::SUCCESS) return;
+ *_aidl_return = static_cast<aidl::android::hardware::fastboot::FileSystemType>(type);
+ });
+ return ResultToAStatus(out_result);
+}
+
+ScopedAStatus FastbootShim::doOemCommand(const std::string& in_oemCmd, std::string* _aidl_return) {
+ Result out_result = {Status::FAILURE_UNKNOWN, ""};
+ *_aidl_return = "";
+ if (in_oemCmd.empty()) {
+ return ScopedAStatus::fromExceptionCodeWithMessage(EX_ILLEGAL_ARGUMENT, "Invalid command");
+ }
+ const hidl_string oemCmdArgs = in_oemCmd;
+ auto ret = service_->doOemCommand(oemCmdArgs, [&](auto& result) {
+ out_result = result;
+ if (out_result.status != Status::SUCCESS) return;
+ *_aidl_return = std::string(result.message.c_str());
+ });
+ return ResultToAStatus(out_result);
+}
+
+ScopedAStatus FastbootShim::getVariant(std::string* _aidl_return) {
+ Result out_result = {Status::FAILURE_UNKNOWN, ""};
+ *_aidl_return = "";
+ auto ret = service_->getVariant([&](auto& variant, auto& result) {
+ out_result = result;
+ if (out_result.status != Status::SUCCESS) return;
+ *_aidl_return = std::string(variant.c_str());
+ });
+ return ResultToAStatus(out_result);
+}
+
+ScopedAStatus FastbootShim::getOffModeChargeState(bool* _aidl_return) {
+ Result out_result = {Status::FAILURE_UNKNOWN, ""};
+ *_aidl_return = false;
+ auto ret = service_->getOffModeChargeState([&](auto state, auto& result) {
+ out_result = result;
+ if (out_result.status != Status::SUCCESS) return;
+ *_aidl_return = state;
+ });
+ return ResultToAStatus(out_result);
+}
+
+ScopedAStatus FastbootShim::getBatteryVoltageFlashingThreshold(int32_t* _aidl_return) {
+ Result out_result = {Status::FAILURE_UNKNOWN, ""};
+ *_aidl_return = 0;
+ auto ret = service_->getBatteryVoltageFlashingThreshold([&](auto batteryVoltage, auto& result) {
+ out_result = result;
+ if (out_result.status != Status::SUCCESS) return;
+ *_aidl_return = batteryVoltage;
+ });
+ return ResultToAStatus(out_result);
+}
+
+ScopedAStatus FastbootShim::doOemSpecificErase() {
+ Result out_result = {Status::FAILURE_UNKNOWN, ""};
+ auto ret = service_->doOemSpecificErase([&](auto& result) { out_result = result; });
+ return ResultToAStatus(out_result);
+}
+
+} // namespace fastboot
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/fastboot/aidl/fastbootshim/include/fastbootshim.h b/fastboot/aidl/fastbootshim/include/fastbootshim.h
new file mode 100644
index 0000000..410a03e
--- /dev/null
+++ b/fastboot/aidl/fastbootshim/include/fastbootshim.h
@@ -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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/fastboot/BnFastboot.h>
+#include <android/hardware/fastboot/1.1/IFastboot.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace fastboot {
+// Shim that wraps HIDL IFastboot with AIDL BnFastboot
+class FastbootShim : public BnFastboot {
+ using HidlFastboot = ::android::hardware::fastboot::V1_1::IFastboot;
+
+ public:
+ explicit FastbootShim(const ::android::sp<HidlFastboot>& service);
+ ::ndk::ScopedAStatus doOemCommand(const std::string& in_oemCmd,
+ std::string* _aidl_return) override;
+ ::ndk::ScopedAStatus doOemSpecificErase() override;
+ ::ndk::ScopedAStatus getBatteryVoltageFlashingThreshold(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getOffModeChargeState(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus getPartitionType(
+ const std::string& in_partitionName,
+ ::aidl::android::hardware::fastboot::FileSystemType* _aidl_return) override;
+ ::ndk::ScopedAStatus getVariant(std::string* _aidl_return) override;
+
+ private:
+ ::android::sp<HidlFastboot> service_;
+};
+
+} // namespace fastboot
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/gatekeeper/1.0/vts/OWNERS b/gatekeeper/1.0/vts/OWNERS
index 738c710..ee2af97 100644
--- a/gatekeeper/1.0/vts/OWNERS
+++ b/gatekeeper/1.0/vts/OWNERS
@@ -1,3 +1,3 @@
-jdanis@google.com
+# Bug component: 1124862
swillden@google.com
guangzhu@google.com
diff --git a/gatekeeper/OWNERS b/gatekeeper/OWNERS
index d95b856..fddc2ff 100644
--- a/gatekeeper/OWNERS
+++ b/gatekeeper/OWNERS
@@ -1,2 +1,4 @@
+# Bug component: 1124862
swillden@google.com
guangzhu@google.com
+subrahmanyaman@google.com
diff --git a/gatekeeper/aidl/Android.bp b/gatekeeper/aidl/Android.bp
index 6b1bc7e..770e8ab 100644
--- a/gatekeeper/aidl/Android.bp
+++ b/gatekeeper/aidl/Android.bp
@@ -11,7 +11,7 @@
name: "android.hardware.gatekeeper",
vendor_available: true,
imports: [
- "android.hardware.security.keymint-V2",
+ "android.hardware.security.keymint-V3",
],
srcs: ["android/hardware/gatekeeper/*.aidl"],
stability: "vintf",
diff --git a/gnss/1.1/default/Android.bp b/gnss/1.1/default/Android.bp
index a73182e..300e8de 100644
--- a/gnss/1.1/default/Android.bp
+++ b/gnss/1.1/default/Android.bp
@@ -27,7 +27,7 @@
"android.hardware.gnss@2.0",
"android.hardware.gnss@1.1",
"android.hardware.gnss@1.0",
- "android.hardware.gnss-V2-ndk",
+ "android.hardware.gnss-V3-ndk",
],
static_libs: [
"android.hardware.gnss@common-default-lib",
diff --git a/gnss/1.1/vts/functional/Android.bp b/gnss/1.1/vts/functional/Android.bp
index f8fad94..2414cbc 100644
--- a/gnss/1.1/vts/functional/Android.bp
+++ b/gnss/1.1/vts/functional/Android.bp
@@ -36,7 +36,7 @@
"android.hardware.gnss@1.1",
"android.hardware.gnss@2.0",
"android.hardware.gnss@common-vts-lib",
- "android.hardware.gnss-V2-cpp",
+ "android.hardware.gnss-V3-cpp",
],
shared_libs: [
"android.hardware.gnss.measurement_corrections@1.0",
diff --git a/gnss/2.0/default/Android.bp b/gnss/2.0/default/Android.bp
index 769e8ae..83bc2cc 100644
--- a/gnss/2.0/default/Android.bp
+++ b/gnss/2.0/default/Android.bp
@@ -50,7 +50,7 @@
"android.hardware.gnss@2.0",
"android.hardware.gnss@1.1",
"android.hardware.gnss@1.0",
- "android.hardware.gnss-V2-ndk",
+ "android.hardware.gnss-V3-ndk",
],
static_libs: [
"android.hardware.gnss@common-default-lib",
diff --git a/gnss/2.0/vts/functional/Android.bp b/gnss/2.0/vts/functional/Android.bp
index 2042dd9..e8db886 100644
--- a/gnss/2.0/vts/functional/Android.bp
+++ b/gnss/2.0/vts/functional/Android.bp
@@ -39,7 +39,7 @@
"android.hardware.gnss@2.0",
"android.hardware.gnss@2.1",
"android.hardware.gnss@common-vts-lib",
- "android.hardware.gnss-V2-cpp",
+ "android.hardware.gnss-V3-cpp",
],
test_suites: [
"general-tests",
diff --git a/gnss/2.1/default/Android.bp b/gnss/2.1/default/Android.bp
index 2979f5c..4a4ce54 100644
--- a/gnss/2.1/default/Android.bp
+++ b/gnss/2.1/default/Android.bp
@@ -44,7 +44,7 @@
"android.hardware.gnss@1.0",
"android.hardware.gnss@1.1",
"android.hardware.gnss@2.0",
- "android.hardware.gnss-V2-ndk",
+ "android.hardware.gnss-V3-ndk",
],
static_libs: [
"android.hardware.gnss@common-default-lib",
diff --git a/gnss/2.1/vts/functional/Android.bp b/gnss/2.1/vts/functional/Android.bp
index d7b6eeb..76f9d07 100644
--- a/gnss/2.1/vts/functional/Android.bp
+++ b/gnss/2.1/vts/functional/Android.bp
@@ -40,7 +40,7 @@
"android.hardware.gnss@2.0",
"android.hardware.gnss@2.1",
"android.hardware.gnss@common-vts-lib",
- "android.hardware.gnss-V2-cpp",
+ "android.hardware.gnss-V3-cpp",
],
shared_libs: [
"libvintf",
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
index 31426f0..54e3b21 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/GnssData.aidl
@@ -39,6 +39,7 @@
android.hardware.gnss.GnssClock clock;
android.hardware.gnss.ElapsedRealtime elapsedRealtime;
android.hardware.gnss.GnssData.GnssAgc[] gnssAgcs = {};
+ boolean isFullTracking;
@VintfStability
parcelable GnssAgc {
double agcLevelDb;
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl
index 8930752..c782b6f 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IAGnssRil.aidl
@@ -39,6 +39,7 @@
void setRefLocation(in android.hardware.gnss.IAGnssRil.AGnssRefLocation agnssReflocation);
void setSetId(in android.hardware.gnss.IAGnssRil.SetIdType type, in @utf8InCpp String setid);
void updateNetworkState(in android.hardware.gnss.IAGnssRil.NetworkAttributes attributes);
+ void injectNiSuplMessageData(in byte[] msgData, in int slotIndex);
const int NETWORK_CAPABILITY_NOT_METERED = 1;
const int NETWORK_CAPABILITY_NOT_ROAMING = 2;
@Backing(type="int") @VintfStability
diff --git a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
index 48c88f5..0247182 100644
--- a/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/aidl_api/android.hardware.gnss/current/android/hardware/gnss/IGnssCallback.aidl
@@ -45,6 +45,7 @@
void gnssSetSystemInfoCb(in android.hardware.gnss.IGnssCallback.GnssSystemInfo info);
void gnssRequestTimeCb();
void gnssRequestLocationCb(in boolean independentFromGnss, in boolean isUserEmergency);
+ void gnssSetSignalTypeCapabilitiesCb(in android.hardware.gnss.GnssSignalType[] gnssSignalTypes);
const int CAPABILITY_SCHEDULING = 1;
const int CAPABILITY_MSB = 2;
const int CAPABILITY_MSA = 4;
@@ -60,6 +61,7 @@
const int CAPABILITY_CORRELATION_VECTOR = 4096;
const int CAPABILITY_SATELLITE_PVT = 8192;
const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 16384;
+ const int CAPABILITY_ACCUMULATED_DELTA_RANGE = 32768;
@Backing(type="int") @VintfStability
enum GnssStatusValue {
NONE = 0,
diff --git a/gnss/aidl/android/hardware/gnss/GnssData.aidl b/gnss/aidl/android/hardware/gnss/GnssData.aidl
index 075a039..492ba31 100644
--- a/gnss/aidl/android/hardware/gnss/GnssData.aidl
+++ b/gnss/aidl/android/hardware/gnss/GnssData.aidl
@@ -99,4 +99,15 @@
* weak to be acquired, the AGC value must still be reported.
*/
GnssAgc[] gnssAgcs = {};
+
+ /**
+ * True indicates that the GNSS chipset switches off duty cycling. In such mode, no clock
+ * discontinuities are expected and, when supported, carrier phase should be continuous in good
+ * signal conditions. All non-blocklisted, healthy constellations, satellites and frequency
+ * bands must be tracked and reported in this mode.
+ *
+ * False indicates that the GNSS chipset optimizes power via duty cycling, constellations and
+ * frequency limits, etc.
+ */
+ boolean isFullTracking;
}
diff --git a/gnss/aidl/android/hardware/gnss/IAGnssRil.aidl b/gnss/aidl/android/hardware/gnss/IAGnssRil.aidl
index 44847f0..5f2e261 100644
--- a/gnss/aidl/android/hardware/gnss/IAGnssRil.aidl
+++ b/gnss/aidl/android/hardware/gnss/IAGnssRil.aidl
@@ -164,4 +164,14 @@
*
*/
void updateNetworkState(in NetworkAttributes attributes);
+
+ /**
+ * Injects an SMS/WAP initiated SUPL message.
+ *
+ * @param msgData ASN.1 encoded SUPL INIT message. This is defined in
+ * UserPlane Location Protocol (Version 2.0.4).
+ * @param slotIndex Specifies the slot index (See
+ * android.telephony.SubscriptionManager#getSlotIndex()) of the SUPL connection.
+ */
+ void injectNiSuplMessageData(in byte[] msgData, in int slotIndex);
}
diff --git a/gnss/aidl/android/hardware/gnss/IGnss.aidl b/gnss/aidl/android/hardware/gnss/IGnss.aidl
index f0b583d..aaafe7f 100644
--- a/gnss/aidl/android/hardware/gnss/IGnss.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnss.aidl
@@ -104,7 +104,7 @@
*
* The framework calls this method to instruct the GPS engine to prepare for serving requests
* from the framework. The GNSS HAL implementation must respond to all GNSS requests from the
- * framework upon successful return from this method until cleanup() method is called to
+ * framework upon successful return from this method until close() method is called to
* close this interface.
*
* @param callback Callback interface for IGnss.
diff --git a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
index 8633bea..ff9feea 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssCallback.aidl
@@ -18,6 +18,7 @@
import android.hardware.gnss.GnssConstellationType;
import android.hardware.gnss.GnssLocation;
+import android.hardware.gnss.GnssSignalType;
import android.hardware.gnss.IGnssConfiguration;
import android.hardware.gnss.IGnssPsds;
@@ -81,6 +82,9 @@
/** Capability bit mask indicating that GNSS supports measurement corrections for driving */
const int CAPABILITY_MEASUREMENT_CORRECTIONS_FOR_DRIVING = 1 << 14;
+ /** Capability bit mask indicating that GNSS supports accumulated delta range */
+ const int CAPABILITY_ACCUMULATED_DELTA_RANGE = 1 << 15;
+
/**
* Callback to inform framework of the GNSS HAL implementation's capabilities.
*
@@ -308,4 +312,18 @@
* during-call to E911, or up to 5 minutes after end-of-call or text to E911).
*/
void gnssRequestLocationCb(in boolean independentFromGnss, in boolean isUserEmergency);
+
+ /**
+ * Callback to inform the framework of the list of GnssSignalTypes the GNSS HAL implementation
+ * supports.
+ *
+ * These capabilities are static at runtime, i.e., they represent the signal types the
+ * GNSS implementation supports without considering the temporary disabled signal types such as
+ * the blocklisted satellites/constellations or the constellations disabled by regional
+ * restrictions.
+ *
+ * @param gnssSignalTypes a list of GnssSignalTypes specifying the constellations, carrier
+ * frequencies, and the code types the GNSS HAL implementation supports.
+ */
+ void gnssSetSignalTypeCapabilitiesCb(in GnssSignalType[] gnssSignalTypes);
}
diff --git a/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl b/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl
index 8733754..4316407 100644
--- a/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl
+++ b/gnss/aidl/android/hardware/gnss/IGnssMeasurementInterface.aidl
@@ -78,6 +78,9 @@
* output rate of 1Hz (occasional intra-measurement time offsets in the range from 0-2000msec
* can be tolerated.)
*
+ * If setCallback() is invoked without a previous close(), the HAL must use the new callback
+ * and parameters to provide updates.
+ *
* @param callback Handle to GnssMeasurement callback interface.
* @param enableFullTracking If true, GNSS chipset must switch off duty cycling. In such mode
* no clock discontinuities are expected and, when supported, carrier phase should be
@@ -104,6 +107,9 @@
/**
* Initializes the interface and registers the callback routines with the HAL.
*
+ * If setCallbackWithOptions() is invoked without a previous close(), the HAL must use the new
+ * callback and options to provide updates.
+ *
* @param options See Options definition.
*/
void setCallbackWithOptions(in IGnssMeasurementCallback callback, in Options options);
diff --git a/gnss/aidl/default/AGnssRil.cpp b/gnss/aidl/default/AGnssRil.cpp
index 2aa1abc..81b4f2a 100644
--- a/gnss/aidl/default/AGnssRil.cpp
+++ b/gnss/aidl/default/AGnssRil.cpp
@@ -17,6 +17,7 @@
#define LOG_TAG "AGnssRilAidl"
#include "AGnssRil.h"
+#include <aidl/android/hardware/gnss/BnGnss.h>
#include <inttypes.h>
#include <log/log.h>
@@ -55,4 +56,15 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus AGnssRil::injectNiSuplMessageData(const std::vector<uint8_t>& msgData,
+ int slotIndex) {
+ ALOGD("AGnssRil::injectNiSuplMessageData: msgData:%d bytes slotIndex:%d",
+ static_cast<int>(msgData.size()), slotIndex);
+ if (msgData.size() > 0) {
+ return ndk::ScopedAStatus::ok();
+ } else {
+ return ndk::ScopedAStatus::fromServiceSpecificError(IGnss::ERROR_INVALID_ARGUMENT);
+ }
+}
+
} // namespace aidl::android::hardware::gnss
diff --git a/gnss/aidl/default/AGnssRil.h b/gnss/aidl/default/AGnssRil.h
index e205b69..76583ac 100644
--- a/gnss/aidl/default/AGnssRil.h
+++ b/gnss/aidl/default/AGnssRil.h
@@ -26,6 +26,8 @@
ndk::ScopedAStatus setRefLocation(const AGnssRefLocation& agnssReflocation) override;
ndk::ScopedAStatus setSetId(SetIdType type, const std::string& setid) override;
ndk::ScopedAStatus updateNetworkState(const NetworkAttributes& attributes) override;
+ ndk::ScopedAStatus injectNiSuplMessageData(const std::vector<uint8_t>& msgData,
+ int slotIndex) override;
private:
// Synchronization lock for sCallback
diff --git a/gnss/aidl/default/Android.bp b/gnss/aidl/default/Android.bp
index c8ae6b2..ca5a41f 100644
--- a/gnss/aidl/default/Android.bp
+++ b/gnss/aidl/default/Android.bp
@@ -50,7 +50,7 @@
"android.hardware.gnss.measurement_corrections@1.1",
"android.hardware.gnss.measurement_corrections@1.0",
"android.hardware.gnss.visibility_control@1.0",
- "android.hardware.gnss-V2-ndk",
+ "android.hardware.gnss-V3-ndk",
],
srcs: [
"AGnssRil.cpp",
diff --git a/gnss/aidl/default/Gnss.cpp b/gnss/aidl/default/Gnss.cpp
index cf2c90d..ec86d2e 100644
--- a/gnss/aidl/default/Gnss.cpp
+++ b/gnss/aidl/default/Gnss.cpp
@@ -60,7 +60,8 @@
IGnssCallback::CAPABILITY_SATELLITE_BLOCKLIST |
IGnssCallback::CAPABILITY_SATELLITE_PVT |
IGnssCallback::CAPABILITY_CORRELATION_VECTOR |
- IGnssCallback::CAPABILITY_ANTENNA_INFO);
+ IGnssCallback::CAPABILITY_ANTENNA_INFO |
+ IGnssCallback::CAPABILITY_ACCUMULATED_DELTA_RANGE);
auto status = sGnssCallback->gnssSetCapabilitiesCb(capabilities);
if (!status.isOk()) {
ALOGE("%s: Unable to invoke callback.gnssSetCapabilitiesCb", __func__);
@@ -68,13 +69,27 @@
IGnssCallback::GnssSystemInfo systemInfo = {
.yearOfHw = 2022,
- .name = "Google Mock GNSS Implementation AIDL v2",
+ .name = "Google, Cuttlefish, AIDL v3",
};
status = sGnssCallback->gnssSetSystemInfoCb(systemInfo);
if (!status.isOk()) {
ALOGE("%s: Unable to invoke callback.gnssSetSystemInfoCb", __func__);
}
-
+ GnssSignalType signalType1 = {
+ .constellation = GnssConstellationType::GPS,
+ .carrierFrequencyHz = 1.57542e+09,
+ .codeType = GnssSignalType::CODE_TYPE_C,
+ };
+ GnssSignalType signalType2 = {
+ .constellation = GnssConstellationType::GLONASS,
+ .carrierFrequencyHz = 1.5980625e+09,
+ .codeType = GnssSignalType::CODE_TYPE_C,
+ };
+ status = sGnssCallback->gnssSetSignalTypeCapabilitiesCb(
+ std::vector<GnssSignalType>({signalType1, signalType2}));
+ if (!status.isOk()) {
+ ALOGE("%s: Unable to invoke callback.gnssSetSignalTypeCapabilitiesCb", __func__);
+ }
return ScopedAStatus::ok();
}
diff --git a/gnss/aidl/default/GnssMeasurementInterface.cpp b/gnss/aidl/default/GnssMeasurementInterface.cpp
index 606de07..90056ce 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.cpp
+++ b/gnss/aidl/default/GnssMeasurementInterface.cpp
@@ -54,7 +54,7 @@
ALOGW("GnssMeasurement callback already set. Resetting the callback...");
stop();
}
- start(enableCorrVecOutputs);
+ start(enableCorrVecOutputs, enableFullTracking);
return ndk::ScopedAStatus::ok();
}
@@ -73,7 +73,7 @@
stop();
}
mIntervalMs = std::max(options.intervalMs, 1000);
- start(options.enableCorrVecOutputs);
+ start(options.enableCorrVecOutputs, options.enableFullTracking);
return ndk::ScopedAStatus::ok();
}
@@ -91,7 +91,8 @@
return ndk::ScopedAStatus::ok();
}
-void GnssMeasurementInterface::start(const bool enableCorrVecOutputs) {
+void GnssMeasurementInterface::start(const bool enableCorrVecOutputs,
+ const bool enableFullTracking) {
ALOGD("start");
if (mIsActive) {
@@ -103,7 +104,7 @@
mIsActive = true;
mThreadBlocker.reset();
- mThread = std::thread([this, enableCorrVecOutputs]() {
+ mThread = std::thread([this, enableCorrVecOutputs, enableFullTracking]() {
int intervalMs;
do {
if (!mIsActive) {
@@ -122,7 +123,8 @@
this->reportMeasurement(*measurement);
}
} else {
- auto measurement = Utils::getMockMeasurement(enableCorrVecOutputs);
+ auto measurement =
+ Utils::getMockMeasurement(enableCorrVecOutputs, enableFullTracking);
this->reportMeasurement(measurement);
}
intervalMs =
diff --git a/gnss/aidl/default/GnssMeasurementInterface.h b/gnss/aidl/default/GnssMeasurementInterface.h
index bb08027..d2737e5 100644
--- a/gnss/aidl/default/GnssMeasurementInterface.h
+++ b/gnss/aidl/default/GnssMeasurementInterface.h
@@ -41,7 +41,7 @@
void setLocationEnabled(const bool enabled);
private:
- void start(const bool enableCorrVecOutputs);
+ void start(const bool enableCorrVecOutputs, const bool enableFullTracking);
void stop();
void reportMeasurement(const GnssData&);
void waitForStoppingThreads();
diff --git a/gnss/aidl/default/gnss-default.xml b/gnss/aidl/default/gnss-default.xml
index 7449310..73b841e 100644
--- a/gnss/aidl/default/gnss-default.xml
+++ b/gnss/aidl/default/gnss-default.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.gnss</name>
- <version>2</version>
+ <version>3</version>
<interface>
<name>IGnss</name>
<instance>default</instance>
diff --git a/gnss/aidl/vts/Android.bp b/gnss/aidl/vts/Android.bp
index f02a41e..2a09a56 100644
--- a/gnss/aidl/vts/Android.bp
+++ b/gnss/aidl/vts/Android.bp
@@ -51,7 +51,7 @@
"libbinder",
],
static_libs: [
- "android.hardware.gnss-V2-cpp",
+ "android.hardware.gnss-V3-cpp",
"android.hardware.gnss@common-vts-lib",
],
test_suites: [
diff --git a/gnss/aidl/vts/GnssCallbackAidl.cpp b/gnss/aidl/vts/GnssCallbackAidl.cpp
index 2f6128b..d3be414 100644
--- a/gnss/aidl/vts/GnssCallbackAidl.cpp
+++ b/gnss/aidl/vts/GnssCallbackAidl.cpp
@@ -23,6 +23,7 @@
using android::hardware::gnss::GnssLocation;
using GnssSvInfo = android::hardware::gnss::IGnssCallback::GnssSvInfo;
using GnssSystemInfo = android::hardware::gnss::IGnssCallback::GnssSystemInfo;
+using GnssSignalType = android::hardware::gnss::GnssSignalType;
Status GnssCallbackAidl::gnssSetCapabilitiesCb(const int capabilities) {
ALOGI("Capabilities received %#08x", capabilities);
@@ -30,6 +31,20 @@
return Status::ok();
}
+Status GnssCallbackAidl::gnssSetSignalTypeCapabilitiesCb(
+ const std::vector<GnssSignalType>& signalTypes) {
+ ALOGI("SignalTypeCapabilities received");
+ std::ostringstream ss;
+ for (auto& signalType : signalTypes) {
+ ss << "[constellation=" << (int)signalType.constellation
+ << ", carrierFrequencyHz=" << signalType.carrierFrequencyHz
+ << ", codeType=" << signalType.codeType << "], ";
+ }
+ ALOGI("%s", ss.str().c_str());
+ signal_type_capabilities_cbq_.store(signalTypes);
+ return Status::ok();
+}
+
Status GnssCallbackAidl::gnssStatusCb(const GnssStatusValue /* status */) {
ALOGI("gnssStatusCb");
return Status::ok();
diff --git a/gnss/aidl/vts/GnssCallbackAidl.h b/gnss/aidl/vts/GnssCallbackAidl.h
index a9495ba..06526d3 100644
--- a/gnss/aidl/vts/GnssCallbackAidl.h
+++ b/gnss/aidl/vts/GnssCallbackAidl.h
@@ -25,6 +25,7 @@
public:
GnssCallbackAidl()
: capabilities_cbq_("capabilities"),
+ signal_type_capabilities_cbq_("signal_type_capabilities"),
info_cbq_("system_info"),
location_cbq_("location"),
sv_info_list_cbq_("sv_info"),
@@ -32,6 +33,8 @@
~GnssCallbackAidl(){};
android::binder::Status gnssSetCapabilitiesCb(const int capabilities) override;
+ android::binder::Status gnssSetSignalTypeCapabilitiesCb(
+ const std::vector<android::hardware::gnss::GnssSignalType>& signalTypes) override;
android::binder::Status gnssStatusCb(const GnssStatusValue status) override;
android::binder::Status gnssSvStatusCb(const std::vector<GnssSvInfo>& svInfoList) override;
android::binder::Status gnssLocationCb(
@@ -45,11 +48,15 @@
const bool isUserEmergency) override;
int last_capabilities_;
+ std::vector<android::hardware::gnss::GnssSignalType> last_signal_type_capabilities;
android::hardware::gnss::IGnssCallback::GnssSystemInfo last_info_;
android::hardware::gnss::GnssLocation last_location_;
android::hardware::gnss::common::GnssCallbackEventQueue<int> capabilities_cbq_;
android::hardware::gnss::common::GnssCallbackEventQueue<
+ std::vector<android::hardware::gnss::GnssSignalType>>
+ signal_type_capabilities_cbq_;
+ android::hardware::gnss::common::GnssCallbackEventQueue<
android::hardware::gnss::IGnssCallback::GnssSystemInfo>
info_cbq_;
android::hardware::gnss::common::GnssCallbackEventQueue<android::hardware::gnss::GnssLocation>
diff --git a/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp b/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp
index a553954..0d15b2a 100644
--- a/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp
+++ b/gnss/aidl/vts/GnssMeasurementCallbackAidl.cpp
@@ -24,9 +24,11 @@
android::binder::Status GnssMeasurementCallbackAidl::gnssMeasurementCb(const GnssData& gnssData) {
ALOGI("gnssMeasurementCb");
- ALOGV("elapsedRealtime: flags = 0x%X, timestampNs: %" PRId64 ", timeUncertaintyNs=%lf",
+ ALOGV("elapsedRealtime: flags = 0x%X, timestampNs: %" PRId64
+ ", timeUncertaintyNs=%lf"
+ " isFullTracking=%s",
gnssData.elapsedRealtime.flags, gnssData.elapsedRealtime.timestampNs,
- gnssData.elapsedRealtime.timeUncertaintyNs);
+ gnssData.elapsedRealtime.timeUncertaintyNs, gnssData.isFullTracking ? "true" : "false");
gnss_data_cbq_.store(gnssData);
return android::binder::Status::ok();
diff --git a/gnss/aidl/vts/gnss_hal_test.cpp b/gnss/aidl/vts/gnss_hal_test.cpp
index 0e1218e..7578585 100644
--- a/gnss/aidl/vts/gnss_hal_test.cpp
+++ b/gnss/aidl/vts/gnss_hal_test.cpp
@@ -105,6 +105,26 @@
EXPECT_TRUE(aidl_gnss_cb_->info_cbq_.retrieve(aidl_gnss_cb_->last_info_, TIMEOUT_SEC));
EXPECT_EQ(aidl_gnss_cb_->info_cbq_.calledCount(), 1);
}
+
+ /*
+ * SignalTypeCapabilities callback should trigger.
+ */
+ if (aidl_gnss_hal_->getInterfaceVersion() >= 3) {
+ EXPECT_TRUE(aidl_gnss_cb_->signal_type_capabilities_cbq_.retrieve(
+ aidl_gnss_cb_->last_signal_type_capabilities, TIMEOUT_SEC));
+ EXPECT_EQ(aidl_gnss_cb_->signal_type_capabilities_cbq_.calledCount(), 1);
+ }
+}
+
+void GnssHalTest::TearDown() {
+ GnssHalTestTemplate<IGnss_V2_1>::TearDown();
+ if (aidl_gnss_hal_ != nullptr) {
+ aidl_gnss_hal_->close();
+ aidl_gnss_hal_ = nullptr;
+ }
+
+ // Set to nullptr to destruct the callback event queues and warn of any unprocessed events.
+ aidl_gnss_cb_ = nullptr;
}
void GnssHalTest::CheckLocation(const GnssLocation& location, bool check_speed) {
@@ -457,6 +477,28 @@
}
}
+void GnssHalTest::checkGnssDataFields(const sp<GnssMeasurementCallbackAidl>& callback,
+ const int numMeasurementEvents, const int timeoutSeconds,
+ const bool isFullTracking) {
+ for (int i = 0; i < numMeasurementEvents; i++) {
+ GnssData lastGnssData;
+ ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastGnssData, timeoutSeconds));
+ EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ ASSERT_TRUE(lastGnssData.measurements.size() > 0);
+
+ // Validity check GnssData fields
+ checkGnssMeasurementClockFields(lastGnssData);
+ if (aidl_gnss_hal_->getInterfaceVersion() >= 3) {
+ if (isFullTracking) {
+ EXPECT_EQ(lastGnssData.isFullTracking, isFullTracking);
+ }
+ }
+ for (const auto& measurement : lastGnssData.measurements) {
+ checkGnssMeasurementFields(measurement, lastGnssData);
+ }
+ }
+}
+
void GnssHalTest::assertMeanAndStdev(int intervalMs, std::vector<int>& deltasMs) {
double mean = computeMean(deltasMs);
double stdev = computeStdev(mean, deltasMs);
diff --git a/gnss/aidl/vts/gnss_hal_test.h b/gnss/aidl/vts/gnss_hal_test.h
index 645fc82..470294c 100644
--- a/gnss/aidl/vts/gnss_hal_test.h
+++ b/gnss/aidl/vts/gnss_hal_test.h
@@ -64,6 +64,7 @@
virtual void SetUp() override;
virtual void SetUpGnssCallback() override;
+ virtual void TearDown() override;
void CheckLocation(const android::hardware::gnss::GnssLocation& location,
const bool check_speed);
@@ -100,6 +101,9 @@
void collectMeasurementIntervals(const sp<GnssMeasurementCallbackAidl>& callback,
const int numMeasurementEvents, const int timeoutSeconds,
std::vector<int>& deltaMs);
+ void checkGnssDataFields(const sp<GnssMeasurementCallbackAidl>& callback,
+ const int numMeasurementEvents, const int timeoutSeconds,
+ const bool isFullTracking);
void assertMeanAndStdev(int intervalMillis, std::vector<int>& deltasMillis);
sp<IGnssAidl> aidl_gnss_hal_;
diff --git a/gnss/aidl/vts/gnss_hal_test_cases.cpp b/gnss/aidl/vts/gnss_hal_test_cases.cpp
index 3696233..48027b6 100644
--- a/gnss/aidl/vts/gnss_hal_test_cases.cpp
+++ b/gnss/aidl/vts/gnss_hal_test_cases.cpp
@@ -173,6 +173,7 @@
* GnssCapabilities:
* 1. Verifies that GNSS hardware supports measurement capabilities.
* 2. Verifies that GNSS hardware supports Scheduling capabilities.
+ * 3. Verifies that GNSS hardware supports non-empty signal type capabilities.
*/
TEST_P(GnssHalTest, GnssCapabilites) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
@@ -182,6 +183,10 @@
EXPECT_TRUE(aidl_gnss_cb_->last_capabilities_ & IGnssCallback::CAPABILITY_MEASUREMENTS);
}
EXPECT_TRUE(aidl_gnss_cb_->last_capabilities_ & IGnssCallback::CAPABILITY_SCHEDULING);
+ if (aidl_gnss_hal_->getInterfaceVersion() <= 2) {
+ return;
+ }
+ EXPECT_FALSE(aidl_gnss_cb_->last_signal_type_capabilities.empty());
}
/*
@@ -1077,6 +1082,7 @@
* 2. Sets AGnssRilCallback.
* 3. Update network state to connected and then disconnected.
* 4. Sets reference location.
+ * 5. Injects empty NI message data and verifies that it returns an error.
*/
TEST_P(GnssHalTest, TestAGnssRilExtension) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
@@ -1120,6 +1126,9 @@
status = iAGnssRil->setRefLocation(agnssReflocation);
ASSERT_TRUE(status.isOk());
+
+ status = iAGnssRil->injectNiSuplMessageData(std::vector<uint8_t>(), 0);
+ ASSERT_FALSE(status.isOk());
}
/*
@@ -1462,7 +1471,7 @@
/*
* TestGnssMeasurementIntervals:
* 1. start measurement with interval
- * 2. verify that the received measurement intervals have expected mean and stdev
+ * 2. verify that the received measurement intervals have expected mean and stddev
*/
TEST_P(GnssHalTest, TestGnssMeasurementIntervals_LocationOnAfterMeasurement) {
if (aidl_gnss_hal_->getInterfaceVersion() <= 1) {
@@ -1494,3 +1503,136 @@
assertMeanAndStdev(locationIntervalMs, deltas);
}
}
+
+/*
+ * TestGnssMeasurementSetCallback:
+ * This test ensures setCallback() can be called consecutively without close().
+ * 1. Start measurement with 20s interval and wait for 1 measurement.
+ * 2. Start measurement with 1s interval and wait for 5 measurements.
+ * Verify the measurements were received at 1Hz.
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementSetCallback) {
+ if (aidl_gnss_hal_->getInterfaceVersion() <= 2) {
+ return;
+ }
+ const int kFirstGnssMeasurementTimeoutSeconds = 10;
+ sp<IGnssMeasurementInterface> iGnssMeasurement;
+ auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(iGnssMeasurement != nullptr);
+
+ ALOGD("TestGnssMeasurementSetCallback");
+ auto callback = sp<GnssMeasurementCallbackAidl>::make();
+ std::vector<int> deltas;
+
+ // setCallback at 20s interval and wait for 1 measurement
+ startMeasurementWithInterval(20000, iGnssMeasurement, callback);
+ collectMeasurementIntervals(callback, /* numEvents= */ 1, kFirstGnssMeasurementTimeoutSeconds,
+ deltas);
+
+ // setCallback at 1s interval and wait for 5 measurements
+ callback->gnss_data_cbq_.reset();
+ startMeasurementWithInterval(1000, iGnssMeasurement, callback);
+ collectMeasurementIntervals(callback, /* numEvents= */ 5, kFirstGnssMeasurementTimeoutSeconds,
+ deltas);
+
+ // verify the measurements were received at 1Hz
+ assertMeanAndStdev(1000, deltas);
+
+ status = iGnssMeasurement->close();
+ ASSERT_TRUE(status.isOk());
+}
+
+/*
+ * TestGnssMeasurementIsFullTracking
+ * 1. Start measurement with enableFullTracking=true. Verify the received measurements have
+ * isFullTracking=true.
+ * 2. Start measurement with enableFullTracking = false. Verify the received measurements have
+ * isFullTracking=false.
+ * 3. Do step 1 again.
+ */
+TEST_P(GnssHalTest, TestGnssMeasurementIsFullTracking) {
+ // GnssData.isFullTracking is added in the interface version 3
+ if (aidl_gnss_hal_->getInterfaceVersion() <= 2) {
+ return;
+ }
+ const int kFirstGnssMeasurementTimeoutSeconds = 10;
+ const int kNumMeasurementEvents = 5;
+ std::vector<bool> isFullTrackingList({true, false, true});
+
+ sp<IGnssMeasurementInterface> iGnssMeasurement;
+ auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(iGnssMeasurement != nullptr);
+
+ ALOGD("TestGnssMeasurementIsFullTracking");
+ auto callback = sp<GnssMeasurementCallbackAidl>::make();
+ IGnssMeasurementInterface::Options options;
+ options.intervalMs = 1000;
+
+ for (auto isFullTracking : isFullTrackingList) {
+ options.enableFullTracking = isFullTracking;
+
+ callback->gnss_data_cbq_.reset();
+ auto status = iGnssMeasurement->setCallbackWithOptions(callback, options);
+ checkGnssDataFields(callback, kNumMeasurementEvents, kFirstGnssMeasurementTimeoutSeconds,
+ isFullTracking);
+ }
+
+ status = iGnssMeasurement->close();
+ ASSERT_TRUE(status.isOk());
+}
+
+/*
+ * TestAccumulatedDeltaRange:
+ * 1. Gets the GnssMeasurementExtension and verifies that it returns a non-null extension.
+ * 2. Start measurement with 1s interval and wait for up to 15 measurements.
+ * 3. Verify at least one measurement has a valid AccumulatedDeltaRange state.
+ */
+TEST_P(GnssHalTest, TestAccumulatedDeltaRange) {
+ if (aidl_gnss_hal_->getInterfaceVersion() <= 2) {
+ return;
+ }
+ if ((aidl_gnss_cb_->last_capabilities_ & IGnssCallback::CAPABILITY_ACCUMULATED_DELTA_RANGE) ==
+ 0) {
+ return;
+ }
+
+ ALOGD("TestAccumulatedDeltaRange");
+
+ auto callback = sp<GnssMeasurementCallbackAidl>::make();
+ sp<IGnssMeasurementInterface> iGnssMeasurement;
+ auto status = aidl_gnss_hal_->getExtensionGnssMeasurement(&iGnssMeasurement);
+ ASSERT_TRUE(status.isOk());
+ ASSERT_TRUE(iGnssMeasurement != nullptr);
+
+ IGnssMeasurementInterface::Options options;
+ options.intervalMs = 1000;
+ options.enableFullTracking = true;
+ status = iGnssMeasurement->setCallbackWithOptions(callback, options);
+ ASSERT_TRUE(status.isOk());
+
+ bool accumulatedDeltaRangeFound = false;
+ const int kNumMeasurementEvents = 15;
+
+ // setCallback at 1s interval and wait for 15 measurements
+ for (int i = 0; i < kNumMeasurementEvents; i++) {
+ GnssData lastGnssData;
+ ASSERT_TRUE(callback->gnss_data_cbq_.retrieve(lastGnssData, 10));
+ EXPECT_EQ(callback->gnss_data_cbq_.calledCount(), i + 1);
+ ASSERT_TRUE(lastGnssData.measurements.size() > 0);
+
+ // Validity check GnssData fields
+ checkGnssMeasurementClockFields(lastGnssData);
+ for (const auto& measurement : lastGnssData.measurements) {
+ if ((measurement.accumulatedDeltaRangeState & measurement.ADR_STATE_VALID) > 0) {
+ accumulatedDeltaRangeFound = true;
+ break;
+ }
+ }
+ if (accumulatedDeltaRangeFound) break;
+ }
+ ASSERT_TRUE(accumulatedDeltaRangeFound);
+ status = iGnssMeasurement->close();
+ ASSERT_TRUE(status.isOk());
+}
\ No newline at end of file
diff --git a/gnss/common/utils/default/Android.bp b/gnss/common/utils/default/Android.bp
index b896f04..4cf17a6 100644
--- a/gnss/common/utils/default/Android.bp
+++ b/gnss/common/utils/default/Android.bp
@@ -57,6 +57,6 @@
"android.hardware.gnss@2.1",
"android.hardware.gnss.measurement_corrections@1.1",
"android.hardware.gnss.measurement_corrections@1.0",
- "android.hardware.gnss-V2-ndk",
+ "android.hardware.gnss-V3-ndk",
],
}
diff --git a/gnss/common/utils/default/Utils.cpp b/gnss/common/utils/default/Utils.cpp
index 4de49f3..2aed29b 100644
--- a/gnss/common/utils/default/Utils.cpp
+++ b/gnss/common/utils/default/Utils.cpp
@@ -147,7 +147,7 @@
return gnssData;
}
-GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs) {
+GnssData Utils::getMockMeasurement(const bool enableCorrVecOutputs, const bool enableFullTracking) {
aidl::android::hardware::gnss::GnssSignalType signalType = {
.constellation = GnssConstellationType::GLONASS,
.carrierFrequencyHz = 1.59975e+09,
@@ -170,7 +170,7 @@
.agcLevelDb = 2.3,
.pseudorangeRateMps = -484.13739013671875,
.pseudorangeRateUncertaintyMps = 1.0379999876022339,
- .accumulatedDeltaRangeState = GnssMeasurement::ADR_STATE_UNKNOWN,
+ .accumulatedDeltaRangeState = GnssMeasurement::ADR_STATE_VALID,
.accumulatedDeltaRangeM = 1.52,
.accumulatedDeltaRangeUncertaintyM = 2.43,
.multipathIndicator = aidl::android::hardware::gnss::GnssMultipathIndicator::UNKNOWN,
@@ -258,7 +258,8 @@
GnssData gnssData = {.measurements = {measurement},
.clock = clock,
.elapsedRealtime = timestamp,
- .gnssAgcs = std::vector({gnssAgc1, gnssAgc2})};
+ .gnssAgcs = std::vector({gnssAgc1, gnssAgc2}),
+ .isFullTracking = enableFullTracking};
return gnssData;
}
diff --git a/gnss/common/utils/default/include/Utils.h b/gnss/common/utils/default/include/Utils.h
index ad8f539..9be4a19 100644
--- a/gnss/common/utils/default/include/Utils.h
+++ b/gnss/common/utils/default/include/Utils.h
@@ -32,7 +32,7 @@
struct Utils {
static aidl::android::hardware::gnss::GnssData getMockMeasurement(
- const bool enableCorrVecOutputs);
+ const bool enableCorrVecOutputs, const bool enableFullTracking);
static V2_0::IGnssMeasurementCallback::GnssData getMockMeasurementV2_0();
static V2_1::IGnssMeasurementCallback::GnssData getMockMeasurementV2_1();
diff --git a/gnss/common/utils/vts/Android.bp b/gnss/common/utils/vts/Android.bp
index f92e609..b5325b2 100644
--- a/gnss/common/utils/vts/Android.bp
+++ b/gnss/common/utils/vts/Android.bp
@@ -44,7 +44,7 @@
"android.hardware.gnss@2.1",
"android.hardware.gnss.measurement_corrections@1.0",
"android.hardware.gnss.measurement_corrections@1.1",
- "android.hardware.gnss-V2-cpp",
+ "android.hardware.gnss-V3-cpp",
],
static_libs: [
"libgtest",
diff --git a/graphics/Android.bp b/graphics/Android.bp
index b48844d..4898dbe 100644
--- a/graphics/Android.bp
+++ b/graphics/Android.bp
@@ -19,41 +19,41 @@
cc_defaults {
name: "android.hardware.graphics.allocator-ndk_static",
static_libs: [
- "android.hardware.graphics.allocator-V1-ndk",
+ "android.hardware.graphics.allocator-V2-ndk",
],
}
cc_defaults {
name: "android.hardware.graphics.allocator-ndk_shared",
shared_libs: [
- "android.hardware.graphics.allocator-V1-ndk",
+ "android.hardware.graphics.allocator-V2-ndk",
],
}
cc_defaults {
name: "android.hardware.graphics.common-ndk_static",
static_libs: [
- "android.hardware.graphics.common-V3-ndk",
+ "android.hardware.graphics.common-V4-ndk",
],
}
cc_defaults {
name: "android.hardware.graphics.common-ndk_shared",
shared_libs: [
- "android.hardware.graphics.common-V3-ndk",
+ "android.hardware.graphics.common-V4-ndk",
],
}
cc_defaults {
name: "android.hardware.graphics.composer3-ndk_static",
static_libs: [
- "android.hardware.graphics.composer3-V1-ndk",
+ "android.hardware.graphics.composer3-V2-ndk",
],
}
cc_defaults {
name: "android.hardware.graphics.composer3-ndk_shared",
shared_libs: [
- "android.hardware.graphics.composer3-V1-ndk",
+ "android.hardware.graphics.composer3-V2-ndk",
],
}
diff --git a/graphics/OWNERS b/graphics/OWNERS
index 75ceb23..1cb6015 100644
--- a/graphics/OWNERS
+++ b/graphics/OWNERS
@@ -6,4 +6,5 @@
chrisforbes@google.com
jreck@google.com
lpy@google.com
+scroggo@google.com
sumir@google.com
\ No newline at end of file
diff --git a/graphics/allocator/2.0/default/OWNERS b/graphics/allocator/2.0/default/OWNERS
deleted file mode 100644
index c9f24d0..0000000
--- a/graphics/allocator/2.0/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
diff --git a/graphics/allocator/2.0/utils/OWNERS b/graphics/allocator/2.0/utils/OWNERS
deleted file mode 100644
index c9f24d0..0000000
--- a/graphics/allocator/2.0/utils/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
diff --git a/graphics/allocator/aidl/Android.bp b/graphics/allocator/aidl/Android.bp
index 272ab48..67c7fb5 100644
--- a/graphics/allocator/aidl/Android.bp
+++ b/graphics/allocator/aidl/Android.bp
@@ -14,9 +14,11 @@
enabled: true,
support_system_process: true,
},
+ vndk_use_version: "2",
srcs: ["android/hardware/graphics/allocator/*.aidl"],
imports: [
"android.hardware.common-V2",
+ "android.hardware.graphics.common-V4",
],
stability: "vintf",
backend: {
@@ -37,6 +39,7 @@
min_sdk_version: "29",
},
},
+ frozen: false,
versions_with_info: [
{
version: "1",
diff --git a/graphics/allocator/aidl/aidl_api/android.hardware.graphics.allocator/current/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl b/graphics/allocator/aidl/aidl_api/android.hardware.graphics.allocator/current/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
new file mode 100644
index 0000000..980e246
--- /dev/null
+++ b/graphics/allocator/aidl/aidl_api/android.hardware.graphics.allocator/current/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
@@ -0,0 +1,44 @@
+/*
+ * 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.graphics.allocator;
+@VintfStability
+parcelable BufferDescriptorInfo {
+ byte[128] name;
+ int width;
+ int height;
+ int layerCount;
+ android.hardware.graphics.common.PixelFormat format = android.hardware.graphics.common.PixelFormat.UNSPECIFIED;
+ android.hardware.graphics.common.BufferUsage usage = android.hardware.graphics.common.BufferUsage.CPU_READ_NEVER;
+ long reservedSize;
+}
diff --git a/graphics/allocator/aidl/aidl_api/android.hardware.graphics.allocator/current/android/hardware/graphics/allocator/IAllocator.aidl b/graphics/allocator/aidl/aidl_api/android.hardware.graphics.allocator/current/android/hardware/graphics/allocator/IAllocator.aidl
index fe0b0a2..48bef16 100644
--- a/graphics/allocator/aidl/aidl_api/android.hardware.graphics.allocator/current/android/hardware/graphics/allocator/IAllocator.aidl
+++ b/graphics/allocator/aidl/aidl_api/android.hardware.graphics.allocator/current/android/hardware/graphics/allocator/IAllocator.aidl
@@ -34,5 +34,11 @@
package android.hardware.graphics.allocator;
@VintfStability
interface IAllocator {
+ /**
+ * @deprecated As of android.hardware.graphics.allocator-V2, this is deprecated & replaced with allocate2
+ */
android.hardware.graphics.allocator.AllocationResult allocate(in byte[] descriptor, in int count);
+ android.hardware.graphics.allocator.AllocationResult allocate2(in android.hardware.graphics.allocator.BufferDescriptorInfo descriptor, in int count);
+ boolean isSupported(in android.hardware.graphics.allocator.BufferDescriptorInfo descriptor);
+ String getIMapperLibrarySuffix();
}
diff --git a/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl b/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
new file mode 100644
index 0000000..ffc50b8
--- /dev/null
+++ b/graphics/allocator/aidl/android/hardware/graphics/allocator/BufferDescriptorInfo.aidl
@@ -0,0 +1,65 @@
+/*
+ * 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.graphics.allocator;
+
+import android.hardware.graphics.common.BufferUsage;
+import android.hardware.graphics.common.PixelFormat;
+
+@VintfStability
+parcelable BufferDescriptorInfo {
+ /**
+ * The name of the buffer in ASCII. Useful for debugging/tracing.
+ */
+ byte[128] name;
+
+ /**
+ * The width specifies how many columns of pixels must be in the
+ * allocated buffer, but does not necessarily represent the offset in
+ * columns between the same column in adjacent rows. The rows may be
+ * padded.
+ */
+ int width;
+
+ /**
+ * The height specifies how many rows of pixels must be in the
+ * allocated buffer.
+ */
+ int height;
+
+ /**
+ * The number of image layers that must be in the allocated buffer.
+ */
+ int layerCount;
+
+ /**
+ * Buffer pixel format. See PixelFormat.aidl in graphics/common for
+ * valid values
+ */
+ PixelFormat format = PixelFormat.UNSPECIFIED;
+
+ /**
+ * Buffer usage mask; valid flags can be found in the definition of
+ * BufferUsage.aidl in graphics/common
+ */
+ BufferUsage usage = BufferUsage.CPU_READ_NEVER;
+
+ /**
+ * The size in bytes of the reserved region associated with the buffer.
+ * See getReservedRegion for more information.
+ */
+ long reservedSize;
+}
diff --git a/graphics/allocator/aidl/android/hardware/graphics/allocator/IAllocator.aidl b/graphics/allocator/aidl/android/hardware/graphics/allocator/IAllocator.aidl
index 92dfd4f..71cebd6 100644
--- a/graphics/allocator/aidl/android/hardware/graphics/allocator/IAllocator.aidl
+++ b/graphics/allocator/aidl/android/hardware/graphics/allocator/IAllocator.aidl
@@ -17,6 +17,7 @@
package android.hardware.graphics.allocator;
import android.hardware.graphics.allocator.AllocationResult;
+import android.hardware.graphics.allocator.BufferDescriptorInfo;
@VintfStability
interface IAllocator {
@@ -31,6 +32,43 @@
* @param count The number of buffers to allocate.
* @return An AllocationResult containing the result of the allocation
* @throws AllocationError on failure
+ * @deprecated As of android.hardware.graphics.allocator-V2, this is deprecated & replaced with
+ * allocate2
*/
AllocationResult allocate(in byte[] descriptor, in int count);
+
+ /**
+ * Allocates buffers with the properties specified by the descriptor.
+ *
+ * Allocations should be optimized for usage bits provided in the
+ * descriptor.
+ *
+ * @param descriptor Properties of the buffers to allocate. This must be
+ * obtained from IMapper::createDescriptor().
+ * @param count The number of buffers to allocate.
+ * @return An AllocationResult containing the result of the allocation
+ * @throws AllocationError on failure
+ */
+ AllocationResult allocate2(in BufferDescriptorInfo descriptor, in int count);
+
+ /**
+ * Test whether the given BufferDescriptorInfo is allocatable.
+ *
+ * If this function returns true, it means that a buffer with the given
+ * description can be allocated on this implementation, unless resource
+ * exhaustion occurs. If this function returns false, it means that the
+ * allocation of the given description will never succeed.
+ *
+ * @param description the description of the buffer
+ * @return supported whether the description is supported
+ */
+ boolean isSupported(in BufferDescriptorInfo descriptor);
+
+ /**
+ * Retrieve the library suffix to load for the IMapper SP-HAL. This library must implement the
+ * IMapper stable-C interface (android/hardware/graphics/mapper/IMapper.h).
+ *
+ * The library that will attempt to be loaded is "/vendor/lib[64]/hw/mapper.<imapper_suffix>.so"
+ */
+ String getIMapperLibrarySuffix();
}
diff --git a/graphics/allocator/aidl/vts/Android.bp b/graphics/allocator/aidl/vts/Android.bp
index a38af14..630ab2a 100644
--- a/graphics/allocator/aidl/vts/Android.bp
+++ b/graphics/allocator/aidl/vts/Android.bp
@@ -55,6 +55,7 @@
],
header_libs: [
"libhwui_internal_headers",
+ "libimapper_stablec",
],
cflags: [
"-Wall",
diff --git a/graphics/allocator/aidl/vts/VtsHalGraphicsAllocatorAidl_TargetTest.cpp b/graphics/allocator/aidl/vts/VtsHalGraphicsAllocatorAidl_TargetTest.cpp
index 59af5cf..09f1c15 100644
--- a/graphics/allocator/aidl/vts/VtsHalGraphicsAllocatorAidl_TargetTest.cpp
+++ b/graphics/allocator/aidl/vts/VtsHalGraphicsAllocatorAidl_TargetTest.cpp
@@ -25,7 +25,10 @@
#include <aidl/android/hardware/graphics/common/PixelFormat.h>
#include <aidlcommonsupport/NativeHandle.h>
#include <android/binder_manager.h>
+#include <android/dlext.h>
#include <android/hardware/graphics/mapper/4.0/IMapper.h>
+#include <android/hardware/graphics/mapper/IMapper.h>
+#include <dlfcn.h>
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
@@ -33,6 +36,7 @@
#include <renderthread/EglManager.h>
#include <utils/GLUtils.h>
#include <vndk/hardware_buffer.h>
+#include <vndksupport/linker.h>
#include <initializer_list>
#include <optional>
#include <string>
@@ -42,60 +46,70 @@
using namespace aidl::android::hardware::graphics::common;
using namespace android;
using namespace android::hardware;
-using namespace android::hardware::graphics::mapper::V4_0;
+using IMapper4 = android::hardware::graphics::mapper::V4_0::IMapper;
+using Error = android::hardware::graphics::mapper::V4_0::Error;
+using android::hardware::graphics::mapper::V4_0::BufferDescriptor;
using android::uirenderer::AutoEglImage;
using android::uirenderer::AutoGLFramebuffer;
using android::uirenderer::AutoSkiaGlTexture;
using android::uirenderer::renderthread::EglManager;
-static constexpr uint64_t pack(const std::initializer_list<BufferUsage>& usages) {
- uint64_t ret = 0;
- for (const auto u : usages) {
- ret |= static_cast<uint64_t>(u);
- }
- return ret;
+typedef AIMapper_Error (*AIMapper_loadIMapperFn)(AIMapper* _Nullable* _Nonnull outImplementation);
+
+inline BufferUsage operator|(BufferUsage lhs, BufferUsage rhs) {
+ using T = std::underlying_type_t<BufferUsage>;
+ return static_cast<BufferUsage>(static_cast<T>(lhs) | static_cast<T>(rhs));
}
-static constexpr hardware::graphics::common::V1_2::PixelFormat cast(PixelFormat format) {
- return static_cast<hardware::graphics::common::V1_2::PixelFormat>(format);
+inline BufferUsage& operator|=(BufferUsage& lhs, BufferUsage rhs) {
+ lhs = lhs | rhs;
+ return lhs;
}
+static IMapper4::BufferDescriptorInfo convert(const BufferDescriptorInfo& info) {
+ return IMapper4::BufferDescriptorInfo{
+ .name{reinterpret_cast<const char*>(info.name.data())},
+ .width = static_cast<uint32_t>(info.width),
+ .height = static_cast<uint32_t>(info.height),
+ .layerCount = static_cast<uint32_t>(info.layerCount),
+ .format = static_cast<hardware::graphics::common::V1_2::PixelFormat>(info.format),
+ .usage = static_cast<uint64_t>(info.usage),
+ .reservedSize = 0,
+ };
+}
+
+class GraphicsTestsBase;
+
class BufferHandle {
- sp<IMapper> mMapper;
+ GraphicsTestsBase& mTestBase;
native_handle_t* mRawHandle;
bool mImported = false;
uint32_t mStride;
- const IMapper::BufferDescriptorInfo mInfo;
+ const BufferDescriptorInfo mInfo;
BufferHandle(const BufferHandle&) = delete;
void operator=(const BufferHandle&) = delete;
public:
- BufferHandle(const sp<IMapper> mapper, native_handle_t* handle, bool imported, uint32_t stride,
- const IMapper::BufferDescriptorInfo& info)
- : mMapper(mapper), mRawHandle(handle), mImported(imported), mStride(stride), mInfo(info) {}
+ BufferHandle(GraphicsTestsBase& testBase, native_handle_t* handle, bool imported,
+ uint32_t stride, const BufferDescriptorInfo& info)
+ : mTestBase(testBase),
+ mRawHandle(handle),
+ mImported(imported),
+ mStride(stride),
+ mInfo(info) {}
- ~BufferHandle() {
- if (mRawHandle == nullptr) return;
-
- if (mImported) {
- Error error = mMapper->freeBuffer(mRawHandle);
- EXPECT_EQ(Error::NONE, error) << "failed to free buffer " << mRawHandle;
- } else {
- native_handle_close(mRawHandle);
- native_handle_delete(mRawHandle);
- }
- }
+ ~BufferHandle();
uint32_t stride() const { return mStride; }
AHardwareBuffer_Desc describe() const {
return {
- .width = mInfo.width,
- .height = mInfo.height,
- .layers = mInfo.layerCount,
+ .width = static_cast<uint32_t>(mInfo.width),
+ .height = static_cast<uint32_t>(mInfo.height),
+ .layers = static_cast<uint32_t>(mInfo.layerCount),
.format = static_cast<uint32_t>(mInfo.format),
- .usage = mInfo.usage,
+ .usage = static_cast<uint64_t>(mInfo.usage),
.stride = stride(),
.rfu0 = 0,
.rfu1 = 0,
@@ -114,25 +128,43 @@
class GraphicsTestsBase {
private:
+ friend class BufferHandle;
+ int32_t mIAllocatorVersion = 1;
std::shared_ptr<IAllocator> mAllocator;
- sp<IMapper> mMapper;
+ sp<IMapper4> mMapper4;
+ AIMapper* mAIMapper = nullptr;
protected:
- void Initialize(std::string allocatorService, std::string mapperService) {
+ void Initialize(std::string allocatorService) {
mAllocator = IAllocator::fromBinder(
ndk::SpAIBinder(AServiceManager_checkService(allocatorService.c_str())));
- mMapper = IMapper::getService(mapperService);
+ ASSERT_TRUE(mAllocator->getInterfaceVersion(&mIAllocatorVersion).isOk());
+ if (mIAllocatorVersion >= 2) {
+ std::string mapperSuffix;
+ auto status = mAllocator->getIMapperLibrarySuffix(&mapperSuffix);
+ ASSERT_TRUE(status.isOk());
+ std::string lib_name = "mapper." + mapperSuffix + ".so";
+ void* so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
+ ASSERT_NE(nullptr, so) << "Failed to load " << lib_name;
+ auto loadIMapper = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper");
+ ASSERT_NE(nullptr, loadIMapper) << "AIMapper_locaIMapper missing from " << lib_name;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, loadIMapper(&mAIMapper));
+ ASSERT_NE(mAIMapper, nullptr);
+ } else {
+ // Don't have IMapper 5, fall back to IMapper 4
+ mMapper4 = IMapper4::getService();
+ ASSERT_NE(nullptr, mMapper4.get()) << "failed to get mapper service";
+ ASSERT_FALSE(mMapper4->isRemote()) << "mapper is not in passthrough mode";
+ }
ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
- ASSERT_NE(nullptr, mMapper.get()) << "failed to get mapper service";
- ASSERT_FALSE(mMapper->isRemote()) << "mapper is not in passthrough mode";
}
- public:
- BufferDescriptor createDescriptor(const IMapper::BufferDescriptorInfo& descriptorInfo) {
+ private:
+ BufferDescriptor createDescriptor(const BufferDescriptorInfo& descriptorInfo) {
BufferDescriptor descriptor;
- mMapper->createDescriptor(
- descriptorInfo, [&](const auto& tmpError, const auto& tmpDescriptor) {
+ mMapper4->createDescriptor(
+ convert(descriptorInfo), [&](const auto& tmpError, const auto& tmpDescriptor) {
ASSERT_EQ(Error::NONE, tmpError) << "failed to create descriptor";
descriptor = tmpDescriptor;
});
@@ -140,14 +172,22 @@
return descriptor;
}
- std::unique_ptr<BufferHandle> allocate(const IMapper::BufferDescriptorInfo& descriptorInfo) {
- auto descriptor = createDescriptor(descriptorInfo);
- if (::testing::Test::HasFatalFailure()) {
- return nullptr;
- }
-
+ public:
+ std::unique_ptr<BufferHandle> allocate(const BufferDescriptorInfo& descriptorInfo) {
AllocationResult result;
- auto status = mAllocator->allocate(descriptor, 1, &result);
+ ::ndk::ScopedAStatus status;
+ if (mIAllocatorVersion >= 2) {
+ status = mAllocator->allocate2(descriptorInfo, 1, &result);
+ } else {
+ auto descriptor = createDescriptor(descriptorInfo);
+ if (::testing::Test::HasFatalFailure()) {
+ return nullptr;
+ }
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ status = mAllocator->allocate(descriptor, 1, &result);
+#pragma clang diagnostic pop // deprecation
+ }
if (!status.isOk()) {
status_t error = status.getExceptionCode();
if (error == EX_SERVICE_SPECIFIC) {
@@ -158,28 +198,48 @@
}
return nullptr;
} else {
- return std::make_unique<BufferHandle>(mMapper, dupFromAidl(result.buffers[0]), false,
+ return std::make_unique<BufferHandle>(*this, dupFromAidl(result.buffers[0]), false,
result.stride, descriptorInfo);
}
}
- bool isSupported(const IMapper::BufferDescriptorInfo& descriptorInfo) {
+ bool isSupported(const BufferDescriptorInfo& descriptorInfo) {
bool ret = false;
- EXPECT_TRUE(mMapper->isSupported(descriptorInfo,
- [&](auto error, bool supported) {
- ASSERT_EQ(Error::NONE, error);
- ret = supported;
- })
- .isOk());
+ if (mIAllocatorVersion >= 2) {
+ EXPECT_TRUE(mAllocator->isSupported(descriptorInfo, &ret).isOk());
+ } else {
+ EXPECT_TRUE(mMapper4->isSupported(convert(descriptorInfo),
+ [&](auto error, bool supported) {
+ ASSERT_EQ(Error::NONE, error);
+ ret = supported;
+ })
+ .isOk());
+ }
return ret;
}
};
-class GraphicsAllocatorAidlTests
- : public GraphicsTestsBase,
- public ::testing::TestWithParam<std::tuple<std::string, std::string>> {
+BufferHandle::~BufferHandle() {
+ if (mRawHandle == nullptr) return;
+
+ if (mImported) {
+ if (mTestBase.mAIMapper) {
+ AIMapper_Error error = mTestBase.mAIMapper->v5.freeBuffer(mRawHandle);
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, error);
+ } else {
+ Error error = mTestBase.mMapper4->freeBuffer(mRawHandle);
+ EXPECT_EQ(Error::NONE, error) << "failed to free buffer " << mRawHandle;
+ }
+ } else {
+ native_handle_close(mRawHandle);
+ native_handle_delete(mRawHandle);
+ }
+}
+
+class GraphicsAllocatorAidlTests : public GraphicsTestsBase,
+ public ::testing::TestWithParam<std::string> {
public:
- void SetUp() override { Initialize(std::get<0>(GetParam()), std::get<1>(GetParam())); }
+ void SetUp() override { Initialize(GetParam()); }
void TearDown() override {}
};
@@ -191,22 +251,22 @@
class GraphicsFrontBufferTests
: public GraphicsTestsBase,
- public ::testing::TestWithParam<std::tuple<std::string, std::string, FlushMethod>> {
+ public ::testing::TestWithParam<std::tuple<std::string, FlushMethod>> {
private:
EglManager eglManager;
std::function<void(EglManager&)> flush;
public:
void SetUp() override {
- Initialize(std::get<0>(GetParam()), std::get<1>(GetParam()));
- flush = std::get<2>(GetParam()).func;
+ Initialize(std::get<0>(GetParam()));
+ flush = std::get<1>(GetParam()).func;
eglManager.initialize();
}
void TearDown() override { eglManager.destroy(); }
void fillWithGpu(AHardwareBuffer* buffer, float red, float green, float blue, float alpha) {
- const EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(buffer);
+ EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(buffer);
AutoEglImage eglImage(eglManager.eglDisplay(), clientBuffer);
AutoSkiaGlTexture glTexture;
AutoGLFramebuffer glFbo;
@@ -235,26 +295,14 @@
}
};
-TEST_P(GraphicsAllocatorAidlTests, CreateDescriptorBasic) {
- ASSERT_NO_FATAL_FAILURE(createDescriptor({
- .name = "CPU_8888",
- .width = 64,
- .height = 64,
- .layerCount = 1,
- .format = cast(PixelFormat::RGBA_8888),
- .usage = pack({BufferUsage::CPU_WRITE_OFTEN, BufferUsage::CPU_READ_OFTEN}),
- .reservedSize = 0,
- }));
-}
-
TEST_P(GraphicsAllocatorAidlTests, CanAllocate) {
auto buffer = allocate({
- .name = "CPU_8888",
+ .name = {"CPU_8888"},
.width = 64,
.height = 64,
.layerCount = 1,
- .format = cast(PixelFormat::RGBA_8888),
- .usage = pack({BufferUsage::CPU_WRITE_OFTEN, BufferUsage::CPU_READ_OFTEN}),
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
.reservedSize = 0,
});
ASSERT_NE(nullptr, buffer.get());
@@ -262,14 +310,14 @@
}
TEST_P(GraphicsFrontBufferTests, FrontBufferGpuToCpu) {
- IMapper::BufferDescriptorInfo info{
- .name = "CPU_8888",
+ BufferDescriptorInfo info{
+ .name = {"CPU_8888"},
.width = 64,
.height = 64,
.layerCount = 1,
- .format = cast(PixelFormat::RGBA_8888),
- .usage = pack({BufferUsage::GPU_RENDER_TARGET, BufferUsage::CPU_READ_OFTEN,
- BufferUsage::FRONT_BUFFER}),
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::GPU_RENDER_TARGET | BufferUsage::CPU_READ_OFTEN |
+ BufferUsage::FRONT_BUFFER,
.reservedSize = 0,
};
const bool supported = isSupported(info);
@@ -304,14 +352,14 @@
}
TEST_P(GraphicsFrontBufferTests, FrontBufferGpuToGpu) {
- IMapper::BufferDescriptorInfo info{
- .name = "CPU_8888",
+ BufferDescriptorInfo info{
+ .name = {"CPU_8888"},
.width = 64,
.height = 64,
.layerCount = 1,
- .format = cast(PixelFormat::RGBA_8888),
- .usage = pack({BufferUsage::GPU_RENDER_TARGET, BufferUsage::GPU_TEXTURE,
- BufferUsage::FRONT_BUFFER}),
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::GPU_RENDER_TARGET | BufferUsage::GPU_TEXTURE |
+ BufferUsage::FRONT_BUFFER,
.reservedSize = 0,
};
const bool supported = isSupported(info);
@@ -344,11 +392,9 @@
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsAllocatorAidlTests);
-INSTANTIATE_TEST_CASE_P(
- PerInstance, GraphicsAllocatorAidlTests,
- testing::Combine(testing::ValuesIn(getAidlHalInstanceNames(IAllocator::descriptor)),
- testing::ValuesIn(getAllHalInstanceNames(IMapper::descriptor))),
- PrintInstanceTupleNameToString<>);
+INSTANTIATE_TEST_CASE_P(PerInstance, GraphicsAllocatorAidlTests,
+ testing::ValuesIn(getAidlHalInstanceNames(IAllocator::descriptor)),
+ PrintInstanceNameToString);
const auto FlushMethodsValues = testing::Values(
FlushMethod{"glFinish", [](EglManager&) { glFinish(); }},
@@ -362,7 +408,7 @@
}},
FlushMethod{"eglClientWaitSync", [](EglManager& eglManager) {
EGLDisplay display = eglManager.eglDisplay();
- EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, NULL);
+ EGLSyncKHR fence = eglCreateSyncKHR(display, EGL_SYNC_FENCE_KHR, nullptr);
eglClientWaitSyncKHR(display, fence, EGL_SYNC_FLUSH_COMMANDS_BIT_KHR,
EGL_FOREVER_KHR);
eglDestroySyncKHR(display, fence);
@@ -371,9 +417,8 @@
INSTANTIATE_TEST_CASE_P(
PerInstance, GraphicsFrontBufferTests,
testing::Combine(testing::ValuesIn(getAidlHalInstanceNames(IAllocator::descriptor)),
- testing::ValuesIn(getAllHalInstanceNames(IMapper::descriptor)),
FlushMethodsValues),
[](auto info) -> std::string {
- std::string name = std::to_string(info.index) + "/" + std::get<2>(info.param).name;
+ std::string name = std::to_string(info.index) + "/" + std::get<1>(info.param).name;
return Sanitize(name);
- });
+ });
\ No newline at end of file
diff --git a/graphics/common/OWNERS b/graphics/common/OWNERS
deleted file mode 100644
index 94999ea..0000000
--- a/graphics/common/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 1075130
-adyabr@google.com
-alecmouri@google.com
-jreck@google.com
-scroggo@google.com
diff --git a/graphics/common/aidl/Android.bp b/graphics/common/aidl/Android.bp
index 40a575d..84bc1af 100644
--- a/graphics/common/aidl/Android.bp
+++ b/graphics/common/aidl/Android.bp
@@ -15,7 +15,7 @@
enabled: true,
support_system_process: true,
},
- vndk_use_version: "3",
+ vndk_use_version: "4",
srcs: [
"android/hardware/graphics/common/*.aidl",
],
@@ -40,6 +40,7 @@
min_sdk_version: "29",
},
},
+ frozen: false,
versions_with_info: [
{
version: "1",
diff --git a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Hdr.aidl b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Hdr.aidl
index 7bae45e..128ef49 100644
--- a/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Hdr.aidl
+++ b/graphics/common/aidl/aidl_api/android.hardware.graphics.common/current/android/hardware/graphics/common/Hdr.aidl
@@ -39,4 +39,5 @@
HDR10 = 2,
HLG = 3,
HDR10_PLUS = 4,
+ DOLBY_VISION_4K30 = 5,
}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/Hdr.aidl b/graphics/common/aidl/android/hardware/graphics/common/Hdr.aidl
index f543780..407b54f 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/Hdr.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/Hdr.aidl
@@ -39,4 +39,8 @@
* Device supports HDR10+
*/
HDR10_PLUS = 4,
+ /**
+ * If present, indicates that device supports Dolby Vision only up to 4k30hz graphics mode
+ */
+ DOLBY_VISION_4K30 = 5,
}
diff --git a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
index 8126143..4bca795 100644
--- a/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
+++ b/graphics/common/aidl/android/hardware/graphics/common/StandardMetadataType.aidl
@@ -22,9 +22,9 @@
* This is an enum that defines the common types of gralloc 4 buffer metadata. The comments for
* each enum include a description of the metadata that is associated with the type.
*
- * IMapper@4.x must support getting the following standard buffer metadata types, with the exception
- * of SMPTE 2094-10 metadata. IMapper@4.x may support setting these standard buffer metadata types
- * as well.
+ * IMapper@4.x & later must support getting the following standard buffer metadata types, with the
+ * exception of SMPTE 2094-10 and SMPTE 2094-40 metadata. IMapper@4.x & later may support setting
+ * these standard buffer metadata types as well.
*
* When encoding these StandardMetadataTypes into a byte stream, the associated MetadataType is
* is first encoded followed by the StandardMetadataType value. The MetadataType is encoded by
diff --git a/graphics/composer/2.1/default/OWNERS b/graphics/composer/2.1/default/OWNERS
deleted file mode 100644
index 331c80d..0000000
--- a/graphics/composer/2.1/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# 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
deleted file mode 100644
index 83c4f5f..0000000
--- a/graphics/composer/2.1/utils/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-adyabr@google.com
-alecmouri@google.com
-lpy@google.com
diff --git a/graphics/composer/2.1/vts/OWNERS b/graphics/composer/2.1/vts/OWNERS
deleted file mode 100644
index a643bbd..0000000
--- a/graphics/composer/2.1/vts/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-# Graphics team
-adyabr@google.com
-alecmouri@google.com
-lpy@google.com
-
-# VTS team
-yim@google.com
-zhuoyao@google.com
diff --git a/graphics/composer/2.1/vts/functional/OWNERS b/graphics/composer/2.1/vts/functional/OWNERS
deleted file mode 100644
index 3d970d1..0000000
--- a/graphics/composer/2.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# 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
deleted file mode 100644
index e8f584d..0000000
--- a/graphics/composer/2.2/default/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# 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
deleted file mode 100644
index 331c80d..0000000
--- a/graphics/composer/2.2/utils/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-adyabr@google.com
-alecmouri@google.com
-lpy@google.com
diff --git a/graphics/composer/2.2/vts/functional/OWNERS b/graphics/composer/2.2/vts/functional/OWNERS
deleted file mode 100644
index a4eb0ca..0000000
--- a/graphics/composer/2.2/vts/functional/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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
deleted file mode 100644
index 331c80d..0000000
--- a/graphics/composer/2.3/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# 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
deleted file mode 100644
index 331c80d..0000000
--- a/graphics/composer/2.3/utils/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-adyabr@google.com
-alecmouri@google.com
-lpy@google.com
diff --git a/graphics/composer/2.3/vts/functional/OWNERS b/graphics/composer/2.3/vts/functional/OWNERS
deleted file mode 100644
index a4eb0ca..0000000
--- a/graphics/composer/2.3/vts/functional/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# 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
deleted file mode 100644
index 331c80d..0000000
--- a/graphics/composer/2.4/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# 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
deleted file mode 100644
index 331c80d..0000000
--- a/graphics/composer/2.4/utils/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-adyabr@google.com
-alecmouri@google.com
-lpy@google.com
diff --git a/graphics/composer/2.4/vts/functional/OWNERS b/graphics/composer/2.4/vts/functional/OWNERS
deleted file mode 100644
index a4eb0ca..0000000
--- a/graphics/composer/2.4/vts/functional/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Bug component: 25423
-# Graphics team
-adyabr@google.com
-alecmouri@google.com
-lpy@google.com
-sumir@google.com
diff --git a/graphics/composer/aidl/Android.bp b/graphics/composer/aidl/Android.bp
index a5ca0a0..1e08221 100644
--- a/graphics/composer/aidl/Android.bp
+++ b/graphics/composer/aidl/Android.bp
@@ -31,12 +31,14 @@
enabled: true,
support_system_process: true,
},
+ frozen: false,
+ vndk_use_version: "1",
srcs: [
"android/hardware/graphics/composer3/*.aidl",
],
stability: "vintf",
imports: [
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
"android.hardware.common-V2",
],
backend: {
@@ -57,7 +59,7 @@
{
version: "1",
imports: [
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
"android.hardware.common-V2",
],
},
diff --git a/graphics/composer/aidl/OWNERS b/graphics/composer/aidl/OWNERS
deleted file mode 100644
index 9028d9d..0000000
--- a/graphics/composer/aidl/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Bug component: 1075131
-
-# Graphics team
-adyabr@google.com
-alecmouri@google.com
-sumir@google.com
\ No newline at end of file
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
index 6eba887..0e2d72b 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -42,4 +42,5 @@
AUTO_LOW_LATENCY_MODE = 5,
SUSPEND = 6,
DISPLAY_IDLE_TIMER = 7,
+ MULTI_THREADED_PRESENT = 8,
}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
index b49f239..a7e6535 100644
--- a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -75,6 +75,7 @@
void setReadbackBuffer(long display, in android.hardware.common.NativeHandle buffer, in @nullable ParcelFileDescriptor releaseFence);
void setVsyncEnabled(long display, boolean enabled);
void setIdleTimerEnabled(long display, int timeoutMs);
+ android.hardware.graphics.composer3.OverlayProperties getOverlaySupport();
const int EX_BAD_CONFIG = 1;
const int EX_BAD_DISPLAY = 2;
const int EX_BAD_LAYER = 3;
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OverlayProperties.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OverlayProperties.aidl
new file mode 100644
index 0000000..4d8fcac
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/OverlayProperties.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.graphics.composer3;
+@VintfStability
+parcelable OverlayProperties {
+ android.hardware.graphics.composer3.SupportedBufferCombinations[] combinations;
+}
diff --git a/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/SupportedBufferCombinations.aidl b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/SupportedBufferCombinations.aidl
new file mode 100644
index 0000000..1828be1
--- /dev/null
+++ b/graphics/composer/aidl/aidl_api/android.hardware.graphics.composer3/current/android/hardware/graphics/composer3/SupportedBufferCombinations.aidl
@@ -0,0 +1,39 @@
+/**
+ * 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.graphics.composer3;
+@VintfStability
+parcelable SupportedBufferCombinations {
+ android.hardware.graphics.common.PixelFormat[] pixelFormats;
+ android.hardware.graphics.common.Dataspace[] dataspaces;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
index f4b2984..7154d74 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/DisplayCapability.aidl
@@ -80,4 +80,20 @@
* IComposerCallback.onVsyncIdle.
*/
DISPLAY_IDLE_TIMER = 7,
+ /**
+ * Indicates that both the composer HAL implementation and the given display
+ * support calling executeCommands concurrently from separate threads.
+ * executeCommands for a particular display will never run concurrently to
+ * any other executeCommands for the same display. In addition, the
+ * CommandResultPayload must only reference displays included in the
+ * DisplayCommands passed to executeCommands. Displays referenced from
+ * separate threads must have minimal interference with one another. If a
+ * HWC-managed display has this capability, SurfaceFlinger can run
+ * executeCommands for this display concurrently with other displays with the
+ * same capability.
+ * @see IComposerClient.executeCommands
+ * @see DisplayCommand.presentDisplay
+ * @see DisplayCommand.validateDisplay
+ */
+ MULTI_THREADED_PRESENT = 8,
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
index a4ea64f..88bb3a4 100644
--- a/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/IComposerClient.aidl
@@ -32,6 +32,7 @@
import android.hardware.graphics.composer3.FormatColorComponent;
import android.hardware.graphics.composer3.HdrCapabilities;
import android.hardware.graphics.composer3.IComposerCallback;
+import android.hardware.graphics.composer3.OverlayProperties;
import android.hardware.graphics.composer3.PerFrameMetadataKey;
import android.hardware.graphics.composer3.PowerMode;
import android.hardware.graphics.composer3.ReadbackBufferAttributes;
@@ -814,4 +815,14 @@
*
*/
void setIdleTimerEnabled(long display, int timeoutMs);
+
+ /**
+ * Hardware overlays is a technique to composite different buffers directly to the screen
+ * while bypassing GPU composition.
+ *
+ * This function returns what the device's overlays support.
+ *
+ * @return the overlay properties of the device.
+ */
+ OverlayProperties getOverlaySupport();
}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/OverlayProperties.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/OverlayProperties.aidl
new file mode 100644
index 0000000..d3bd7d3
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/OverlayProperties.aidl
@@ -0,0 +1,29 @@
+/**
+ * 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.graphics.composer3;
+
+import android.hardware.graphics.composer3.SupportedBufferCombinations;
+
+@VintfStability
+parcelable OverlayProperties {
+ // Array of all valid pixelformat and dataspace combinations.
+ // If all supported formats work with all supported dataspaces,
+ // then this list may only have 1 entry.
+ // If some dataspaces, e.g. scRGB, only work with specific formats,
+ // then this list may contain more than 1 entry.
+ SupportedBufferCombinations[] combinations;
+}
diff --git a/graphics/composer/aidl/android/hardware/graphics/composer3/SupportedBufferCombinations.aidl b/graphics/composer/aidl/android/hardware/graphics/composer3/SupportedBufferCombinations.aidl
new file mode 100644
index 0000000..41f8817
--- /dev/null
+++ b/graphics/composer/aidl/android/hardware/graphics/composer3/SupportedBufferCombinations.aidl
@@ -0,0 +1,25 @@
+/**
+ * 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.graphics.composer3;
+
+@VintfStability
+parcelable SupportedBufferCombinations {
+ // List of pixelformats and dataspaces that can be used together.
+ // All pixelformats and dataspaces stored inside are valid combinations.
+ android.hardware.graphics.common.PixelFormat[] pixelFormats;
+ android.hardware.graphics.common.Dataspace[] dataspaces;
+}
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
index 27dce76..76ba24b 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientReader.h
@@ -19,8 +19,8 @@
#include <algorithm>
#include <limits>
#include <memory>
+#include <optional>
#include <unordered_map>
-#include <unordered_set>
#include <vector>
#include <inttypes.h>
@@ -41,8 +41,15 @@
class ComposerClientReader {
public:
+ explicit ComposerClientReader(std::optional<int64_t> display = {}) : mDisplay(display) {}
+
~ComposerClientReader() { resetData(); }
+ ComposerClientReader(ComposerClientReader&&) = default;
+
+ ComposerClientReader(const ComposerClientReader&) = delete;
+ ComposerClientReader& operator=(const ComposerClientReader&) = delete;
+
// Parse and execute commands from the command queue. The commands are
// actually return values from the server and will be saved in ReturnData.
void parse(std::vector<CommandResultPayload>&& results) {
@@ -85,6 +92,7 @@
void hasChanges(int64_t display, uint32_t* outNumChangedCompositionTypes,
uint32_t* outNumLayerRequestMasks) const {
+ LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay);
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
*outNumChangedCompositionTypes = 0;
@@ -100,6 +108,7 @@
// Get and clear saved changed composition types.
std::vector<ChangedCompositionLayer> takeChangedCompositionTypes(int64_t display) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay);
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
return {};
@@ -111,6 +120,7 @@
// Get and clear saved display requests.
DisplayRequest takeDisplayRequests(int64_t display) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay);
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
return {};
@@ -122,6 +132,7 @@
// Get and clear saved release fences.
std::vector<ReleaseFences::Layer> takeReleaseFences(int64_t display) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay);
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
return {};
@@ -133,6 +144,7 @@
// Get and clear saved present fence.
ndk::ScopedFileDescriptor takePresentFence(int64_t display) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay);
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
return {};
@@ -144,6 +156,7 @@
// Get what stage succeeded during PresentOrValidate: Present or Validate
std::optional<PresentOrValidate::Result> takePresentOrValidateStage(int64_t display) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay);
auto found = mReturnData.find(display);
if (found == mReturnData.end()) {
return std::nullopt;
@@ -154,6 +167,7 @@
// Get the client target properties requested by hardware composer.
ClientTargetPropertyWithBrightness takeClientTargetProperty(int64_t display) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && display != *mDisplay);
auto found = mReturnData.find(display);
// If not found, return the default values.
@@ -177,32 +191,38 @@
void parseSetError(CommandError&& error) { mErrors.emplace_back(error); }
void parseSetChangedCompositionTypes(ChangedCompositionTypes&& changedCompositionTypes) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && changedCompositionTypes.display != *mDisplay);
auto& data = mReturnData[changedCompositionTypes.display];
data.changedLayers = std::move(changedCompositionTypes.layers);
}
void parseSetDisplayRequests(DisplayRequest&& displayRequest) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && displayRequest.display != *mDisplay);
auto& data = mReturnData[displayRequest.display];
data.displayRequests = std::move(displayRequest);
}
void parseSetPresentFence(PresentFence&& presentFence) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && presentFence.display != *mDisplay);
auto& data = mReturnData[presentFence.display];
data.presentFence = std::move(presentFence.fence);
}
void parseSetReleaseFences(ReleaseFences&& releaseFences) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && releaseFences.display != *mDisplay);
auto& data = mReturnData[releaseFences.display];
data.releasedLayers = std::move(releaseFences.layers);
}
void parseSetPresentOrValidateDisplayResult(const PresentOrValidate&& presentOrValidate) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && presentOrValidate.display != *mDisplay);
auto& data = mReturnData[presentOrValidate.display];
data.presentOrValidateState = std::move(presentOrValidate.result);
}
void parseSetClientTargetProperty(
const ClientTargetPropertyWithBrightness&& clientTargetProperty) {
+ LOG_ALWAYS_FATAL_IF(mDisplay && clientTargetProperty.display != *mDisplay);
auto& data = mReturnData[clientTargetProperty.display];
data.clientTargetProperty = std::move(clientTargetProperty);
}
@@ -222,6 +242,7 @@
std::vector<CommandError> mErrors;
std::unordered_map<int64_t, ReturnData> mReturnData;
+ const std::optional<int64_t> mDisplay;
};
} // namespace aidl::android::hardware::graphics::composer3
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
index 775ae9f..0c8742f 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerClientWriter.h
@@ -19,8 +19,6 @@
#include <algorithm>
#include <limits>
#include <memory>
-#include <unordered_map>
-#include <unordered_set>
#include <vector>
#include <inttypes.h>
@@ -63,10 +61,15 @@
public:
static constexpr std::optional<ClockMonotonicTimestamp> kNoTimestamp = std::nullopt;
- ComposerClientWriter() { reset(); }
+ explicit ComposerClientWriter(int64_t display) : mDisplay(display) { reset(); }
~ComposerClientWriter() { reset(); }
+ ComposerClientWriter(ComposerClientWriter&&) = default;
+
+ ComposerClientWriter(const ComposerClientWriter&) = delete;
+ ComposerClientWriter& operator=(const ComposerClientWriter&) = delete;
+
void reset() {
mDisplayCommand.reset();
mLayerCommand.reset();
@@ -229,6 +232,7 @@
std::optional<DisplayCommand> mDisplayCommand;
std::optional<LayerCommand> mLayerCommand;
std::vector<DisplayCommand> mCommands;
+ const int64_t mDisplay;
Buffer getBuffer(uint32_t slot, const native_handle_t* bufferHandle, int fence) {
Buffer bufferCommand;
@@ -254,6 +258,7 @@
DisplayCommand& getDisplayCommand(int64_t display) {
if (!mDisplayCommand.has_value() || mDisplayCommand->display != display) {
+ LOG_ALWAYS_FATAL_IF(display != mDisplay);
flushLayerCommand();
flushDisplayCommand();
mDisplayCommand.emplace();
diff --git a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerServiceWriter.h b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerServiceWriter.h
index 34cda6a..b50b84b 100644
--- a/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerServiceWriter.h
+++ b/graphics/composer/aidl/include/android/hardware/graphics/composer3/ComposerServiceWriter.h
@@ -18,6 +18,7 @@
#include <aidl/android/hardware/graphics/composer3/CommandResultPayload.h>
#include <aidl/android/hardware/graphics/composer3/IComposerClient.h>
+#include <android-base/logging.h>
#include <inttypes.h>
#include <string.h>
@@ -26,8 +27,6 @@
#include <memory>
#include <vector>
-#include "Util.h"
-
namespace aidl::android::hardware::graphics::composer3::impl {
class ComposerServiceWriter {
diff --git a/graphics/composer/aidl/vts/OWNERS b/graphics/composer/aidl/vts/OWNERS
deleted file mode 100644
index d95d98d..0000000
--- a/graphics/composer/aidl/vts/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-# Bug component: 199413815
-
-# Graphics team
-adyabr@google.com
-alecmouri@google.com
-ramindani@google.com
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.cpp b/graphics/composer/aidl/vts/VtsComposerClient.cpp
index 5bc7296..34cc802 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.cpp
+++ b/graphics/composer/aidl/vts/VtsComposerClient.cpp
@@ -338,6 +338,11 @@
outDisplayOrientation};
}
+std::pair<ScopedAStatus, composer3::OverlayProperties> VtsComposerClient::getOverlaySupport() {
+ OverlayProperties properties;
+ return {mComposerClient->getOverlaySupport(&properties), properties};
+}
+
ScopedAStatus VtsComposerClient::setIdleTimerEnabled(int64_t display, int32_t timeoutMs) {
return mComposerClient->setIdleTimerEnabled(display, timeoutMs);
}
diff --git a/graphics/composer/aidl/vts/VtsComposerClient.h b/graphics/composer/aidl/vts/VtsComposerClient.h
index 3625c8c..1883336 100644
--- a/graphics/composer/aidl/vts/VtsComposerClient.h
+++ b/graphics/composer/aidl/vts/VtsComposerClient.h
@@ -35,6 +35,7 @@
#include <string>
#include <thread>
#include <unordered_map>
+#include <unordered_set>
#include "GraphicsComposerCallback.h"
using aidl::android::hardware::graphics::common::Dataspace;
@@ -172,6 +173,8 @@
std::pair<ScopedAStatus, std::vector<VtsDisplay>> getDisplays();
+ std::pair<ScopedAStatus, OverlayProperties> getOverlaySupport();
+
private:
ScopedAStatus updateDisplayProperties(VtsDisplay* vtsDisplay, int32_t config);
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
index 46dde09..6fa3392 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_ReadbackTest.cpp
@@ -53,6 +53,7 @@
const auto& [status, displays] = mComposerClient->getDisplays();
ASSERT_TRUE(status.isOk());
mDisplays = displays;
+ mWriter.reset(new ComposerClientWriter(getPrimaryDisplayId()));
setTestColorModes();
@@ -200,15 +201,15 @@
void writeLayers(const std::vector<std::shared_ptr<TestLayer>>& layers) {
for (const auto& layer : layers) {
- layer->write(mWriter);
+ layer->write(*mWriter);
}
execute();
}
void execute() {
- const auto& commands = mWriter.getPendingCommands();
+ const auto& commands = mWriter->getPendingCommands();
if (commands.empty()) {
- mWriter.reset();
+ mWriter->reset();
return;
}
@@ -216,7 +217,7 @@
ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
mReader.parse(std::move(results));
- mWriter.reset();
+ mWriter->reset();
}
bool getHasReadbackBuffer() {
@@ -236,7 +237,7 @@
std::vector<VtsDisplay> mDisplays;
// use the slot count usually set by SF
std::vector<ColorMode> mTestColorModes;
- ComposerClientWriter mWriter;
+ std::unique_ptr<ComposerClientWriter> mWriter;
ComposerClientReader mReader;
std::unique_ptr<TestRenderEngine> mTestRenderEngine;
common::PixelFormat mPixelFormat;
@@ -297,7 +298,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
// if hwc cannot handle and asks for composition change,
// just succeed the test
@@ -306,7 +307,7 @@
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -349,14 +350,14 @@
getDisplayHeight(), common::PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+ layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
std::vector<std::shared_ptr<TestLayer>> layers = {layer};
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
@@ -365,7 +366,7 @@
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -395,7 +396,7 @@
layer->setColor(BLUE);
layer->setDisplayFrame(coloredSquare);
layer->setZOrder(10);
- layer->write(mWriter);
+ layer->write(*mWriter);
// This following buffer call should have no effect
const auto usage = static_cast<uint32_t>(common::BufferUsage::CPU_WRITE_OFTEN) |
@@ -403,8 +404,8 @@
const auto& [graphicBufferStatus, graphicBuffer] = allocateBuffer(usage);
ASSERT_TRUE(graphicBufferStatus);
const auto& buffer = graphicBuffer->handle;
- mWriter.setLayerBuffer(getPrimaryDisplayId(), layer->getLayer(), /*slot*/ 0, buffer,
- /*acquireFence*/ -1);
+ mWriter->setLayerBuffer(getPrimaryDisplayId(), layer->getLayer(), /*slot*/ 0, buffer,
+ /*acquireFence*/ -1);
// expected color for each pixel
std::vector<Color> expectedColors(
@@ -415,7 +416,7 @@
getDisplayHeight(), mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
@@ -423,7 +424,7 @@
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -533,7 +534,7 @@
getDisplayHeight(), PixelFormat::RGBA_FP16);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+ layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
std::vector<std::shared_ptr<TestLayer>> layers = {layer};
@@ -542,7 +543,7 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
auto changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
@@ -572,17 +573,17 @@
int32_t clientFence;
const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence);
ASSERT_EQ(::android::OK, unlockStatus);
- mWriter.setClientTarget(getPrimaryDisplayId(), /*slot*/ 0, buffer, clientFence,
- clientDataspace, std::vector<common::Rect>(1, damage));
- layer->setToClientComposition(mWriter);
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->setClientTarget(getPrimaryDisplayId(), /*slot*/ 0, buffer, clientFence,
+ clientDataspace, std::vector<common::Rect>(1, damage));
+ layer->setToClientComposition(*mWriter);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
ASSERT_TRUE(changedCompositionTypes.empty());
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -631,9 +632,9 @@
deviceLayer->setDisplayFrame({0, 0, static_cast<int32_t>(deviceLayer->getWidth()),
static_cast<int32_t>(deviceLayer->getHeight())});
deviceLayer->setZOrder(10);
- deviceLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+ deviceLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
ASSERT_NO_FATAL_FAILURE(deviceLayer->setBuffer(deviceColors));
- deviceLayer->write(mWriter);
+ deviceLayer->write(*mWriter);
PixelFormat clientFormat = PixelFormat::RGBA_8888;
auto clientUsage = static_cast<uint32_t>(
@@ -651,8 +652,8 @@
getDisplayHeight()};
clientLayer->setDisplayFrame(clientFrame);
clientLayer->setZOrder(0);
- clientLayer->write(mWriter);
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ clientLayer->write(*mWriter);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
auto changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
@@ -678,16 +679,16 @@
int32_t clientFence;
const auto unlockStatus = graphicBuffer->unlockAsync(&clientFence);
ASSERT_EQ(::android::OK, unlockStatus);
- mWriter.setClientTarget(getPrimaryDisplayId(), /*slot*/ 0, buffer, clientFence,
- clientDataspace, std::vector<common::Rect>(1, clientFrame));
- clientLayer->setToClientComposition(mWriter);
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->setClientTarget(getPrimaryDisplayId(), /*slot*/ 0, buffer, clientFence,
+ clientDataspace, std::vector<common::Rect>(1, clientFrame));
+ clientLayer->setToClientComposition(*mWriter);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
changedCompositionTypes = mReader.takeChangedCompositionTypes(getPrimaryDisplayId());
ASSERT_TRUE(changedCompositionTypes.empty());
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
@@ -718,7 +719,7 @@
getDisplayHeight(), PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+ layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
ASSERT_NO_FATAL_FAILURE(layer->setBuffer(expectedColors));
std::vector<std::shared_ptr<TestLayer>> layers = {layer};
@@ -729,14 +730,14 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -757,11 +758,11 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -798,7 +799,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
@@ -806,7 +807,7 @@
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -846,7 +847,7 @@
getDisplayHeight(), PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+ layer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
layer->setSourceCrop({0, static_cast<float>(getDisplayHeight() / 2),
static_cast<float>(getDisplayWidth()),
static_cast<float>(getDisplayHeight())});
@@ -862,14 +863,14 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
@@ -920,13 +921,13 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
return;
}
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -942,11 +943,11 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
ASSERT_TRUE(mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty());
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -980,7 +981,7 @@
// Preconditions to successfully run are knowing the max brightness and successfully applying
// the max brightness
ASSERT_GT(maxBrightnessNits, 0.f);
- mWriter.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 1.f, maxBrightnessNits);
+ mWriter->setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 1.f, maxBrightnessNits);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1030,7 +1031,7 @@
writeLayers(layers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED()
@@ -1038,7 +1039,7 @@
<< toString(mode);
continue;
}
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1088,7 +1089,7 @@
getDisplayHeight(), PixelFormat::RGBA_8888);
layer->setDisplayFrame({0, 0, getDisplayWidth(), getDisplayHeight()});
layer->setZOrder(10);
- layer->setDataspace(Dataspace::UNKNOWN, mWriter);
+ layer->setDataspace(Dataspace::UNKNOWN, *mWriter);
ASSERT_NO_FATAL_FAILURE(layer->setBuffer(topLayerPixelColors));
layer->setBlendMode(blendMode);
@@ -1165,14 +1166,14 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1210,14 +1211,14 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
@@ -1250,14 +1251,14 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
@@ -1323,7 +1324,7 @@
getDisplayHeight(), mPixelFormat, mDataspace);
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
mLayer->setTransform(Transform::FLIP_H);
- mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+ mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
std::vector<Color> expectedColors(
static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
@@ -1334,14 +1335,14 @@
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1369,7 +1370,7 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
mLayer->setTransform(Transform::FLIP_V);
- mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+ mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
std::vector<Color> expectedColors(
static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
@@ -1380,14 +1381,14 @@
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
@@ -1414,7 +1415,7 @@
ASSERT_NO_FATAL_FAILURE(readbackBuffer.setReadbackBuffer());
mLayer->setTransform(Transform::ROT_180);
- mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), mWriter);
+ mLayer->setDataspace(ReadbackHelper::getDataspaceForColorMode(mode), *mWriter);
std::vector<Color> expectedColors(
static_cast<size_t>(getDisplayWidth() * getDisplayHeight()));
@@ -1426,14 +1427,14 @@
writeLayers(mLayers);
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ mWriter->validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED();
return;
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ mWriter->presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
ASSERT_NO_FATAL_FAILURE(readbackBuffer.checkReadbackBuffer(expectedColors));
diff --git a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
index 93b646f..fa66812 100644
--- a/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
+++ b/graphics/composer/aidl/vts/VtsHalGraphicsComposer3_TargetTest.cpp
@@ -13,6 +13,7 @@
* 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/graphics/common/BlendMode.h>
@@ -32,9 +33,11 @@
#include <ui/GraphicBuffer.h>
#include <ui/PixelFormat.h>
#include <algorithm>
+#include <iterator>
#include <numeric>
#include <string>
#include <thread>
+#include <unordered_map>
#include "GraphicsComposerCallback.h"
#include "VtsComposerClient.h"
@@ -808,6 +811,18 @@
EXPECT_TRUE(status.isOk());
}
+// TODO(b/250036572): disable this due to no implementation and revup on cuttlefish
+TEST_P(GraphicsComposerAidlTest, DISABLED_GetOverlaySupport) {
+ const auto& [status, _] = mComposerClient->getOverlaySupport();
+ if (!status.isOk() && status.getExceptionCode() == EX_SERVICE_SPECIFIC &&
+ status.getServiceSpecificError() == IComposerClient::EX_UNSUPPORTED) {
+ GTEST_SUCCEED() << "getOverlaySupport is not supported";
+ return;
+ }
+
+ ASSERT_TRUE(status.isOk());
+}
+
TEST_P(GraphicsComposerAidlTest, GetDisplayPhysicalOrientation_BadDisplay) {
const auto& [status, _] = mComposerClient->getDisplayPhysicalOrientation(getInvalidDisplayId());
@@ -1065,17 +1080,23 @@
}
void execute() {
- const auto& commands = mWriter.getPendingCommands();
- if (commands.empty()) {
- mWriter.reset();
- return;
+ std::vector<CommandResultPayload> payloads;
+ for (auto& [_, writer] : mWriters) {
+ const auto& commands = writer.getPendingCommands();
+ if (commands.empty()) {
+ writer.reset();
+ continue;
+ }
+
+ auto [status, results] = mComposerClient->executeCommands(commands);
+ ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
+ writer.reset();
+
+ payloads.reserve(payloads.size() + results.size());
+ payloads.insert(payloads.end(), std::make_move_iterator(results.begin()),
+ std::make_move_iterator(results.end()));
}
-
- auto [status, results] = mComposerClient->executeCommands(commands);
- ASSERT_TRUE(status.isOk()) << "executeCommands failed " << status.getDescription();
-
- mReader.parse(std::move(results));
- mWriter.reset();
+ mReader.parse(std::move(payloads));
}
static inline auto toTimePoint(nsecs_t time) {
@@ -1139,6 +1160,7 @@
const auto& [status, layer] =
mComposerClient->createLayer(display.getDisplayId(), kBufferSlotCount);
EXPECT_TRUE(status.isOk());
+ auto& writer = getWriter(display.getDisplayId());
{
const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
ASSERT_NE(nullptr, buffer);
@@ -1147,15 +1169,15 @@
configureLayer(display, layer, Composition::DEVICE, display.getFrameRect(),
display.getCrop());
- mWriter.setLayerBuffer(display.getDisplayId(), layer, /*slot*/ 0, buffer->handle,
- /*acquireFence*/ -1);
- mWriter.setLayerDataspace(display.getDisplayId(), layer, common::Dataspace::UNKNOWN);
+ writer.setLayerBuffer(display.getDisplayId(), layer, /*slot*/ 0, buffer->handle,
+ /*acquireFence*/ -1);
+ writer.setLayerDataspace(display.getDisplayId(), layer, common::Dataspace::UNKNOWN);
- mWriter.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp);
+ writer.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(display.getDisplayId());
+ writer.presentDisplay(display.getDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -1164,15 +1186,15 @@
const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
ASSERT_NE(nullptr, buffer->handle);
- mWriter.setLayerBuffer(display.getDisplayId(), layer, /*slot*/ 0, buffer->handle,
- /*acquireFence*/ -1);
- mWriter.setLayerSurfaceDamage(display.getDisplayId(), layer,
- std::vector<Rect>(1, {0, 0, 10, 10}));
- mWriter.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp);
+ writer.setLayerBuffer(display.getDisplayId(), layer, /*slot*/ 0, buffer->handle,
+ /*acquireFence*/ -1);
+ writer.setLayerSurfaceDamage(display.getDisplayId(), layer,
+ std::vector<Rect>(1, {0, 0, 10, 10}));
+ writer.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(display.getDisplayId());
+ writer.presentDisplay(display.getDisplayId());
execute();
}
@@ -1181,11 +1203,12 @@
sp<::android::Fence> presentAndGetFence(
std::optional<ClockMonotonicTimestamp> expectedPresentTime) {
- mWriter.validateDisplay(getPrimaryDisplayId(), expectedPresentTime);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.validateDisplay(getPrimaryDisplayId(), expectedPresentTime);
execute();
EXPECT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ writer.presentDisplay(getPrimaryDisplayId());
execute();
EXPECT_TRUE(mReader.takeErrors().empty());
@@ -1217,7 +1240,8 @@
FRect cropRect{0, 0, (float)getPrimaryDisplay().getDisplayWidth(),
(float)getPrimaryDisplay().getDisplayHeight()};
configureLayer(getPrimaryDisplay(), layer, Composition::DEVICE, displayFrame, cropRect);
- mWriter.setLayerDataspace(getPrimaryDisplayId(), layer, common::Dataspace::UNKNOWN);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerDataspace(getPrimaryDisplayId(), layer, common::Dataspace::UNKNOWN);
return layer;
}
@@ -1317,8 +1341,9 @@
ASSERT_NE(nullptr, buffer2);
const auto layer = createOnScreenLayer();
- mWriter.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer1->handle,
- /*acquireFence*/ -1);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer1->handle,
+ /*acquireFence*/ -1);
const sp<::android::Fence> presentFence1 =
presentAndGetFence(ComposerClientWriter::kNoTimestamp);
presentFence1->waitForever(LOG_TAG);
@@ -1328,8 +1353,8 @@
expectedPresentTime += *framesDelay * vsyncPeriod;
}
- mWriter.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer2->handle,
- /*acquireFence*/ -1);
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer2->handle,
+ /*acquireFence*/ -1);
const auto setExpectedPresentTime = [&]() -> std::optional<ClockMonotonicTimestamp> {
if (!framesDelay.has_value()) {
return ComposerClientWriter::kNoTimestamp;
@@ -1350,17 +1375,18 @@
void configureLayer(const VtsDisplay& display, int64_t layer, Composition composition,
const Rect& displayFrame, const FRect& cropRect) {
- mWriter.setLayerCompositionType(display.getDisplayId(), layer, composition);
- mWriter.setLayerDisplayFrame(display.getDisplayId(), layer, displayFrame);
- mWriter.setLayerPlaneAlpha(display.getDisplayId(), layer, /*alpha*/ 1);
- mWriter.setLayerSourceCrop(display.getDisplayId(), layer, cropRect);
- mWriter.setLayerTransform(display.getDisplayId(), layer, static_cast<Transform>(0));
- mWriter.setLayerVisibleRegion(display.getDisplayId(), layer,
- std::vector<Rect>(1, displayFrame));
- mWriter.setLayerZOrder(display.getDisplayId(), layer, /*z*/ 10);
- mWriter.setLayerBlendMode(display.getDisplayId(), layer, BlendMode::NONE);
- mWriter.setLayerSurfaceDamage(display.getDisplayId(), layer,
- std::vector<Rect>(1, displayFrame));
+ auto& writer = getWriter(display.getDisplayId());
+ writer.setLayerCompositionType(display.getDisplayId(), layer, composition);
+ writer.setLayerDisplayFrame(display.getDisplayId(), layer, displayFrame);
+ writer.setLayerPlaneAlpha(display.getDisplayId(), layer, /*alpha*/ 1);
+ writer.setLayerSourceCrop(display.getDisplayId(), layer, cropRect);
+ writer.setLayerTransform(display.getDisplayId(), layer, static_cast<Transform>(0));
+ writer.setLayerVisibleRegion(display.getDisplayId(), layer,
+ std::vector<Rect>(1, displayFrame));
+ writer.setLayerZOrder(display.getDisplayId(), layer, /*z*/ 10);
+ writer.setLayerBlendMode(display.getDisplayId(), layer, BlendMode::NONE);
+ writer.setLayerSurfaceDamage(display.getDisplayId(), layer,
+ std::vector<Rect>(1, displayFrame));
}
// clang-format off
const std::array<float, 16> kIdentity = {{
@@ -1371,12 +1397,20 @@
}};
// clang-format on
- ComposerClientWriter mWriter;
+ ComposerClientWriter& getWriter(int64_t display) {
+ auto [it, _] = mWriters.try_emplace(display, display);
+ return it->second;
+ }
+
ComposerClientReader mReader;
+
+ private:
+ std::unordered_map<int64_t, ComposerClientWriter> mWriters;
};
TEST_P(GraphicsComposerAidlCommandTest, SetColorTransform) {
- mWriter.setColorTransform(getPrimaryDisplayId(), kIdentity.data());
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setColorTransform(getPrimaryDisplayId(), kIdentity.data());
execute();
}
@@ -1384,7 +1418,8 @@
const auto& [status, layer] =
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(status.isOk());
- mWriter.setLayerColorTransform(getPrimaryDisplayId(), layer, kIdentity.data());
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerColorTransform(getPrimaryDisplayId(), layer, kIdentity.data());
execute();
const auto errors = mReader.takeErrors();
@@ -1400,8 +1435,9 @@
ASSERT_TRUE(status.isOk());
bool brightnessSupport = std::find(capabilities.begin(), capabilities.end(),
DisplayCapability::BRIGHTNESS) != capabilities.end();
+ auto& writer = getWriter(getPrimaryDisplayId());
if (!brightnessSupport) {
- mWriter.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 0.5f, -1.f);
+ writer.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 0.5f, -1.f);
execute();
const auto errors = mReader.takeErrors();
EXPECT_EQ(1, errors.size());
@@ -1410,23 +1446,23 @@
return;
}
- mWriter.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 0.0f, -1.f);
+ writer.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 0.0f, -1.f);
execute();
EXPECT_TRUE(mReader.takeErrors().empty());
- mWriter.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 0.5f, -1.f);
+ writer.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 0.5f, -1.f);
execute();
EXPECT_TRUE(mReader.takeErrors().empty());
- mWriter.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 1.0f, -1.f);
+ writer.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 1.0f, -1.f);
execute();
EXPECT_TRUE(mReader.takeErrors().empty());
- mWriter.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ -1.0f, -1.f);
+ writer.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ -1.0f, -1.f);
execute();
EXPECT_TRUE(mReader.takeErrors().empty());
- mWriter.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 2.0f, -1.f);
+ writer.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ 2.0f, -1.f);
execute();
{
const auto errors = mReader.takeErrors();
@@ -1434,7 +1470,7 @@
EXPECT_EQ(IComposerClient::EX_BAD_PARAMETER, errors[0].errorCode);
}
- mWriter.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ -2.0f, -1.f);
+ writer.setDisplayBrightness(getPrimaryDisplayId(), /*brightness*/ -2.0f, -1.f);
execute();
{
const auto errors = mReader.takeErrors();
@@ -1447,8 +1483,9 @@
EXPECT_TRUE(mComposerClient->setClientTargetSlotCount(getPrimaryDisplayId(), kBufferSlotCount)
.isOk());
- mWriter.setClientTarget(getPrimaryDisplayId(), /*slot*/ 0, nullptr, /*acquireFence*/ -1,
- Dataspace::UNKNOWN, std::vector<Rect>());
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setClientTarget(getPrimaryDisplayId(), /*slot*/ 0, nullptr, /*acquireFence*/ -1,
+ Dataspace::UNKNOWN, std::vector<Rect>());
execute();
}
@@ -1468,24 +1505,28 @@
const auto buffer = allocate(::android::PIXEL_FORMAT_RGBA_8888);
const auto handle = buffer->handle;
- mWriter.setOutputBuffer(display.display, /*slot*/ 0, handle, /*releaseFence*/ -1);
+ auto& writer = getWriter(display.display);
+ writer.setOutputBuffer(display.display, /*slot*/ 0, handle, /*releaseFence*/ -1);
execute();
}
TEST_P(GraphicsComposerAidlCommandTest, ValidDisplay) {
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
}
TEST_P(GraphicsComposerAidlCommandTest, AcceptDisplayChanges) {
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
- mWriter.acceptDisplayChanges(getPrimaryDisplayId());
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ writer.acceptDisplayChanges(getPrimaryDisplayId());
execute();
}
TEST_P(GraphicsComposerAidlCommandTest, PresentDisplay) {
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
- mWriter.presentDisplay(getPrimaryDisplayId());
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ writer.presentDisplay(getPrimaryDisplayId());
execute();
}
@@ -1506,6 +1547,7 @@
const auto& [renderIntentsStatus, renderIntents] =
mComposerClient->getRenderIntents(getPrimaryDisplayId(), ColorMode::NATIVE);
EXPECT_TRUE(renderIntentsStatus.isOk());
+ auto& writer = getWriter(getPrimaryDisplayId());
for (auto intent : renderIntents) {
EXPECT_TRUE(mComposerClient->setColorMode(getPrimaryDisplayId(), ColorMode::NATIVE, intent)
.isOk());
@@ -1523,10 +1565,10 @@
FRect cropRect{0, 0, (float)getPrimaryDisplay().getDisplayWidth(),
(float)getPrimaryDisplay().getDisplayHeight()};
configureLayer(getPrimaryDisplay(), layer, Composition::CURSOR, displayFrame, cropRect);
- mWriter.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle,
- /*acquireFence*/ -1);
- mWriter.setLayerDataspace(getPrimaryDisplayId(), layer, Dataspace::UNKNOWN);
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle,
+ /*acquireFence*/ -1);
+ writer.setLayerDataspace(getPrimaryDisplayId(), layer, Dataspace::UNKNOWN);
+ writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (!mReader.takeChangedCompositionTypes(getPrimaryDisplayId()).empty()) {
GTEST_SUCCEED() << "Composition change requested, skipping test";
@@ -1534,18 +1576,18 @@
}
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.presentDisplay(getPrimaryDisplayId());
+ writer.presentDisplay(getPrimaryDisplayId());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
const auto buffer2 = allocate(::android::PIXEL_FORMAT_RGBA_8888);
const auto handle2 = buffer2->handle;
ASSERT_NE(nullptr, handle2);
- mWriter.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle2,
- /*acquireFence*/ -1);
- mWriter.setLayerSurfaceDamage(getPrimaryDisplayId(), layer,
- std::vector<Rect>(1, {0, 0, 10, 10}));
- mWriter.presentDisplay(getPrimaryDisplayId());
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle2,
+ /*acquireFence*/ -1);
+ writer.setLayerSurfaceDamage(getPrimaryDisplayId(), layer,
+ std::vector<Rect>(1, {0, 0, 10, 10}));
+ writer.presentDisplay(getPrimaryDisplayId());
execute();
}
}
@@ -1559,15 +1601,16 @@
const auto handle = buffer->handle;
ASSERT_NE(nullptr, handle);
- mWriter.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle, /*acquireFence*/ -1);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle, /*acquireFence*/ -1);
Rect displayFrame{0, 0, getPrimaryDisplay().getDisplayWidth(),
getPrimaryDisplay().getDisplayHeight()};
FRect cropRect{0, 0, (float)getPrimaryDisplay().getDisplayWidth(),
(float)getPrimaryDisplay().getDisplayHeight()};
configureLayer(getPrimaryDisplay(), layer, Composition::CURSOR, displayFrame, cropRect);
- mWriter.setLayerDataspace(getPrimaryDisplayId(), layer, Dataspace::UNKNOWN);
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ writer.setLayerDataspace(getPrimaryDisplayId(), layer, Dataspace::UNKNOWN);
+ writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
@@ -1575,15 +1618,15 @@
GTEST_SUCCEED() << "Composition change requested, skipping test";
return;
}
- mWriter.presentDisplay(getPrimaryDisplayId());
+ writer.presentDisplay(getPrimaryDisplayId());
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerCursorPosition(getPrimaryDisplayId(), layer, /*x*/ 1, /*y*/ 1);
+ writer.setLayerCursorPosition(getPrimaryDisplayId(), layer, /*x*/ 1, /*y*/ 1);
execute();
- mWriter.setLayerCursorPosition(getPrimaryDisplayId(), layer, /*x*/ 0, /*y*/ 0);
- mWriter.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
- mWriter.presentDisplay(getPrimaryDisplayId());
+ writer.setLayerCursorPosition(getPrimaryDisplayId(), layer, /*x*/ 0, /*y*/ 0);
+ writer.validateDisplay(getPrimaryDisplayId(), ComposerClientWriter::kNoTimestamp);
+ writer.presentDisplay(getPrimaryDisplayId());
execute();
}
@@ -1595,7 +1638,8 @@
const auto& [layerStatus, layer] =
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle, /*acquireFence*/ -1);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, handle, /*acquireFence*/ -1);
execute();
}
@@ -1607,15 +1651,16 @@
Rect empty{0, 0, 0, 0};
Rect unit{0, 0, 1, 1};
- mWriter.setLayerSurfaceDamage(getPrimaryDisplayId(), layer, std::vector<Rect>(1, empty));
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerSurfaceDamage(getPrimaryDisplayId(), layer, std::vector<Rect>(1, empty));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerSurfaceDamage(getPrimaryDisplayId(), layer, std::vector<Rect>(1, unit));
+ writer.setLayerSurfaceDamage(getPrimaryDisplayId(), layer, std::vector<Rect>(1, unit));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerSurfaceDamage(getPrimaryDisplayId(), layer, std::vector<Rect>());
+ writer.setLayerSurfaceDamage(getPrimaryDisplayId(), layer, std::vector<Rect>());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -1628,15 +1673,16 @@
Rect empty{0, 0, 0, 0};
Rect unit{0, 0, 1, 1};
- mWriter.setLayerBlockingRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, empty));
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerBlockingRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, empty));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerBlockingRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, unit));
+ writer.setLayerBlockingRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, unit));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerBlockingRegion(getPrimaryDisplayId(), layer, std::vector<Rect>());
+ writer.setLayerBlockingRegion(getPrimaryDisplayId(), layer, std::vector<Rect>());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -1646,15 +1692,16 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerBlendMode(getPrimaryDisplayId(), layer, BlendMode::NONE);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerBlendMode(getPrimaryDisplayId(), layer, BlendMode::NONE);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerBlendMode(getPrimaryDisplayId(), layer, BlendMode::PREMULTIPLIED);
+ writer.setLayerBlendMode(getPrimaryDisplayId(), layer, BlendMode::PREMULTIPLIED);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerBlendMode(getPrimaryDisplayId(), layer, BlendMode::COVERAGE);
+ writer.setLayerBlendMode(getPrimaryDisplayId(), layer, BlendMode::COVERAGE);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -1664,11 +1711,12 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerColor(getPrimaryDisplayId(), layer, Color{1.0f, 1.0f, 1.0f, 1.0f});
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerColor(getPrimaryDisplayId(), layer, Color{1.0f, 1.0f, 1.0f, 1.0f});
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerColor(getPrimaryDisplayId(), layer, Color{0.0f, 0.0f, 0.0f, 0.0f});
+ writer.setLayerColor(getPrimaryDisplayId(), layer, Color{0.0f, 0.0f, 0.0f, 0.0f});
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -1678,19 +1726,20 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerCompositionType(getPrimaryDisplayId(), layer, Composition::CLIENT);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerCompositionType(getPrimaryDisplayId(), layer, Composition::CLIENT);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerCompositionType(getPrimaryDisplayId(), layer, Composition::DEVICE);
+ writer.setLayerCompositionType(getPrimaryDisplayId(), layer, Composition::DEVICE);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerCompositionType(getPrimaryDisplayId(), layer, Composition::SOLID_COLOR);
+ writer.setLayerCompositionType(getPrimaryDisplayId(), layer, Composition::SOLID_COLOR);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerCompositionType(getPrimaryDisplayId(), layer, Composition::CURSOR);
+ writer.setLayerCompositionType(getPrimaryDisplayId(), layer, Composition::CURSOR);
execute();
}
@@ -1721,9 +1770,10 @@
configureLayer(display, layer, Composition::DISPLAY_DECORATION, display.getFrameRect(),
display.getCrop());
- mWriter.setLayerBuffer(display.getDisplayId(), layer, /*slot*/ 0, decorBuffer->handle,
- /*acquireFence*/ -1);
- mWriter.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp);
+ auto& writer = getWriter(display.getDisplayId());
+ writer.setLayerBuffer(display.getDisplayId(), layer, /*slot*/ 0, decorBuffer->handle,
+ /*acquireFence*/ -1);
+ writer.validateDisplay(display.getDisplayId(), ComposerClientWriter::kNoTimestamp);
execute();
if (support) {
ASSERT_TRUE(mReader.takeErrors().empty());
@@ -1740,7 +1790,8 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerDataspace(getPrimaryDisplayId(), layer, Dataspace::UNKNOWN);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerDataspace(getPrimaryDisplayId(), layer, Dataspace::UNKNOWN);
execute();
}
@@ -1749,7 +1800,8 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerDisplayFrame(getPrimaryDisplayId(), layer, Rect{0, 0, 1, 1});
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerDisplayFrame(getPrimaryDisplayId(), layer, Rect{0, 0, 1, 1});
execute();
}
@@ -1758,11 +1810,12 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerPlaneAlpha(getPrimaryDisplayId(), layer, /*alpha*/ 0.0f);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerPlaneAlpha(getPrimaryDisplayId(), layer, /*alpha*/ 0.0f);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerPlaneAlpha(getPrimaryDisplayId(), layer, /*alpha*/ 1.0f);
+ writer.setLayerPlaneAlpha(getPrimaryDisplayId(), layer, /*alpha*/ 1.0f);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -1781,7 +1834,8 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerSidebandStream(getPrimaryDisplayId(), layer, handle);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerSidebandStream(getPrimaryDisplayId(), layer, handle);
execute();
}
@@ -1790,7 +1844,8 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerSourceCrop(getPrimaryDisplayId(), layer, FRect{0.0f, 0.0f, 1.0f, 1.0f});
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerSourceCrop(getPrimaryDisplayId(), layer, FRect{0.0f, 0.0f, 1.0f, 1.0f});
execute();
}
@@ -1799,39 +1854,40 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerTransform(getPrimaryDisplayId(), layer, static_cast<Transform>(0));
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerTransform(getPrimaryDisplayId(), layer, static_cast<Transform>(0));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerTransform(getPrimaryDisplayId(), layer, Transform::FLIP_H);
+ writer.setLayerTransform(getPrimaryDisplayId(), layer, Transform::FLIP_H);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerTransform(getPrimaryDisplayId(), layer, Transform::FLIP_V);
+ writer.setLayerTransform(getPrimaryDisplayId(), layer, Transform::FLIP_V);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerTransform(getPrimaryDisplayId(), layer, Transform::ROT_90);
+ writer.setLayerTransform(getPrimaryDisplayId(), layer, Transform::ROT_90);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerTransform(getPrimaryDisplayId(), layer, Transform::ROT_180);
+ writer.setLayerTransform(getPrimaryDisplayId(), layer, Transform::ROT_180);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerTransform(getPrimaryDisplayId(), layer, Transform::ROT_270);
+ writer.setLayerTransform(getPrimaryDisplayId(), layer, Transform::ROT_270);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerTransform(getPrimaryDisplayId(), layer,
- static_cast<Transform>(static_cast<int>(Transform::FLIP_H) |
- static_cast<int>(Transform::ROT_90)));
+ writer.setLayerTransform(getPrimaryDisplayId(), layer,
+ static_cast<Transform>(static_cast<int>(Transform::FLIP_H) |
+ static_cast<int>(Transform::ROT_90)));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerTransform(getPrimaryDisplayId(), layer,
- static_cast<Transform>(static_cast<int>(Transform::FLIP_V) |
- static_cast<int>(Transform::ROT_90)));
+ writer.setLayerTransform(getPrimaryDisplayId(), layer,
+ static_cast<Transform>(static_cast<int>(Transform::FLIP_V) |
+ static_cast<int>(Transform::ROT_90)));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -1844,15 +1900,16 @@
Rect empty{0, 0, 0, 0};
Rect unit{0, 0, 1, 1};
- mWriter.setLayerVisibleRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, empty));
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerVisibleRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, empty));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerVisibleRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, unit));
+ writer.setLayerVisibleRegion(getPrimaryDisplayId(), layer, std::vector<Rect>(1, unit));
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerVisibleRegion(getPrimaryDisplayId(), layer, std::vector<Rect>());
+ writer.setLayerVisibleRegion(getPrimaryDisplayId(), layer, std::vector<Rect>());
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -1862,11 +1919,12 @@
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
EXPECT_TRUE(layerStatus.isOk());
- mWriter.setLayerZOrder(getPrimaryDisplayId(), layer, /*z*/ 10);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerZOrder(getPrimaryDisplayId(), layer, /*z*/ 10);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerZOrder(getPrimaryDisplayId(), layer, /*z*/ 0);
+ writer.setLayerZOrder(getPrimaryDisplayId(), layer, /*z*/ 0);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
}
@@ -1888,6 +1946,7 @@
* white (D65) 0.3127 0.3290
*/
+ auto& writer = getWriter(getPrimaryDisplayId());
std::vector<PerFrameMetadata> aidlMetadata;
aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_X, 0.680f});
aidlMetadata.push_back({PerFrameMetadataKey::DISPLAY_RED_PRIMARY_Y, 0.320f});
@@ -1901,7 +1960,7 @@
aidlMetadata.push_back({PerFrameMetadataKey::MIN_LUMINANCE, 0.1f});
aidlMetadata.push_back({PerFrameMetadataKey::MAX_CONTENT_LIGHT_LEVEL, 78.0});
aidlMetadata.push_back({PerFrameMetadataKey::MAX_FRAME_AVERAGE_LIGHT_LEVEL, 62.0});
- mWriter.setLayerPerFrameMetadata(getPrimaryDisplayId(), layer, aidlMetadata);
+ writer.setLayerPerFrameMetadata(getPrimaryDisplayId(), layer, aidlMetadata);
execute();
const auto errors = mReader.takeErrors();
@@ -1918,19 +1977,20 @@
const auto& [layerStatus, layer] =
mComposerClient->createLayer(getPrimaryDisplayId(), kBufferSlotCount);
- mWriter.setLayerBrightness(getPrimaryDisplayId(), layer, 0.2f);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerBrightness(getPrimaryDisplayId(), layer, 0.2f);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerBrightness(getPrimaryDisplayId(), layer, 1.f);
+ writer.setLayerBrightness(getPrimaryDisplayId(), layer, 1.f);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerBrightness(getPrimaryDisplayId(), layer, 0.f);
+ writer.setLayerBrightness(getPrimaryDisplayId(), layer, 0.f);
execute();
ASSERT_TRUE(mReader.takeErrors().empty());
- mWriter.setLayerBrightness(getPrimaryDisplayId(), layer, -1.f);
+ writer.setLayerBrightness(getPrimaryDisplayId(), layer, -1.f);
execute();
{
const auto errors = mReader.takeErrors();
@@ -1938,7 +1998,7 @@
EXPECT_EQ(IComposerClient::EX_BAD_PARAMETER, errors[0].errorCode);
}
- mWriter.setLayerBrightness(getPrimaryDisplayId(), layer, std::nanf(""));
+ writer.setLayerBrightness(getPrimaryDisplayId(), layer, std::nanf(""));
execute();
{
const auto errors = mReader.takeErrors();
@@ -2103,8 +2163,9 @@
ASSERT_NE(nullptr, buffer->handle);
const auto layer = createOnScreenLayer();
- mWriter.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer->handle,
- /*acquireFence*/ -1);
+ auto& writer = getWriter(getPrimaryDisplayId());
+ writer.setLayerBuffer(getPrimaryDisplayId(), layer, /*slot*/ 0, buffer->handle,
+ /*acquireFence*/ -1);
int32_t vsyncIdleCount = mComposerClient->getVsyncIdleCount();
auto earlyVsyncIdleTime = systemTime() + std::chrono::nanoseconds(2s).count();
EXPECT_TRUE(
@@ -2157,6 +2218,20 @@
}
}
+TEST_P(GraphicsComposerAidlCommandTest, MultiThreadedPresent) {
+ std::vector<VtsDisplay*> displays;
+ for (auto& display : mDisplays) {
+ if (hasDisplayCapability(display.getDisplayId(),
+ DisplayCapability::MULTI_THREADED_PRESENT)) {
+ displays.push_back(&display);
+ }
+ }
+ if (displays.size() <= 1u) {
+ return;
+ }
+ // TODO(b/251842321): Try to present on multiple threads.
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsComposerAidlCommandTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, GraphicsComposerAidlCommandTest,
diff --git a/graphics/mapper/2.0/default/OWNERS b/graphics/mapper/2.0/default/OWNERS
deleted file mode 100644
index c9f24d0..0000000
--- a/graphics/mapper/2.0/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
diff --git a/graphics/mapper/2.0/utils/OWNERS b/graphics/mapper/2.0/utils/OWNERS
deleted file mode 100644
index c9f24d0..0000000
--- a/graphics/mapper/2.0/utils/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
diff --git a/graphics/mapper/2.0/vts/OWNERS b/graphics/mapper/2.0/vts/OWNERS
deleted file mode 100644
index 62e3f2a..0000000
--- a/graphics/mapper/2.0/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 25423
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
-sumir@google.com
diff --git a/graphics/mapper/2.1/default/OWNERS b/graphics/mapper/2.1/default/OWNERS
deleted file mode 100644
index c9f24d0..0000000
--- a/graphics/mapper/2.1/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
diff --git a/graphics/mapper/2.1/utils/OWNERS b/graphics/mapper/2.1/utils/OWNERS
deleted file mode 100644
index c9f24d0..0000000
--- a/graphics/mapper/2.1/utils/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
diff --git a/graphics/mapper/2.1/vts/OWNERS b/graphics/mapper/2.1/vts/OWNERS
deleted file mode 100644
index 43c018a..0000000
--- a/graphics/mapper/2.1/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 25423
-include ../../2.0/vts/OWNERS
diff --git a/graphics/mapper/3.0/utils/OWNERS b/graphics/mapper/3.0/utils/OWNERS
deleted file mode 100644
index c9f24d0..0000000
--- a/graphics/mapper/3.0/utils/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
diff --git a/graphics/mapper/3.0/vts/OWNERS b/graphics/mapper/3.0/vts/OWNERS
deleted file mode 100644
index 43c018a..0000000
--- a/graphics/mapper/3.0/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 25423
-include ../../2.0/vts/OWNERS
diff --git a/graphics/mapper/4.0/utils/OWNERS b/graphics/mapper/4.0/utils/OWNERS
deleted file mode 100644
index c9f24d0..0000000
--- a/graphics/mapper/4.0/utils/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-# Graphics team
-chrisforbes@google.com
-jreck@google.com
-lpy@google.com
diff --git a/graphics/mapper/4.0/utils/vts/Android.bp b/graphics/mapper/4.0/utils/vts/Android.bp
index 55e721e..51e871b 100644
--- a/graphics/mapper/4.0/utils/vts/Android.bp
+++ b/graphics/mapper/4.0/utils/vts/Android.bp
@@ -47,7 +47,7 @@
],
export_static_lib_headers: [
"android.hardware.graphics.allocator@4.0",
- "android.hardware.graphics.common-V3-ndk",
+ "android.hardware.graphics.common-V4-ndk",
"android.hardware.graphics.mapper@4.0",
],
export_include_dirs: ["include"],
diff --git a/graphics/mapper/4.0/vts/OWNERS b/graphics/mapper/4.0/vts/OWNERS
deleted file mode 100644
index 43c018a..0000000
--- a/graphics/mapper/4.0/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 25423
-include ../../2.0/vts/OWNERS
diff --git a/graphics/mapper/stable-c/Android.bp b/graphics/mapper/stable-c/Android.bp
new file mode 100644
index 0000000..c03f67e
--- /dev/null
+++ b/graphics/mapper/stable-c/Android.bp
@@ -0,0 +1,104 @@
+/**
+ * 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_library_headers {
+ name: "libimapper_stablec",
+ export_include_dirs: ["include"],
+ vendor_available: true,
+ header_libs: [
+ "libarect_headers",
+ ],
+ export_header_lib_headers: [
+ "libarect_headers",
+ ],
+}
+
+cc_library_headers {
+ name: "libimapper_providerutils",
+ vendor_available: true,
+ export_include_dirs: ["implutils/include"],
+ header_libs: [
+ "libbase_headers",
+ "libimapper_stablec",
+ ],
+ export_header_lib_headers: [
+ "libbase_headers",
+ "libimapper_stablec",
+ ],
+}
+
+cc_test {
+ name: "libimapper_providerutils_tests",
+ defaults: [
+ "android.hardware.graphics.allocator-ndk_shared",
+ "android.hardware.graphics.common-ndk_shared",
+ ],
+ header_libs: [
+ "libimapper_providerutils",
+ ],
+ srcs: [
+ "implutils/impltests.cpp",
+ ],
+ visibility: [":__subpackages__"],
+ cpp_std: "experimental",
+}
+
+cc_test {
+ name: "VtsHalGraphicsMapperStableC_TargetTest",
+ cpp_std: "experimental",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ "android.hardware.graphics.allocator-ndk_shared",
+ "android.hardware.graphics.common-ndk_shared",
+ ],
+ srcs: [
+ "vts/VtsHalGraphicsMapperStableC_TargetTest.cpp",
+ ],
+
+ shared_libs: [
+ "libbinder_ndk",
+ "libbase",
+ "libsync",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "libaidlcommonsupport",
+ "libgralloctypes",
+ "libgtest",
+ ],
+ header_libs: [
+ "libimapper_stablec",
+ "libimapper_providerutils",
+ ],
+ cflags: [
+ "-Wall",
+ "-Werror",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/graphics/mapper/stable-c/implutils/impltests.cpp b/graphics/mapper/stable-c/implutils/impltests.cpp
new file mode 100644
index 0000000..9c5d70b
--- /dev/null
+++ b/graphics/mapper/stable-c/implutils/impltests.cpp
@@ -0,0 +1,314 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
+#include <android/hardware/graphics/mapper/utils/IMapperProvider.h>
+#include <vector>
+
+using namespace ::android::hardware::graphics::mapper;
+using namespace ::aidl::android::hardware::graphics::common;
+
+// These tests are primarily interested in hitting all the different *types* that can be
+// serialized/deserialized than in exhaustively testing all the StandardMetadataTypes.
+// Exhaustive testing of the actual metadata types is relegated for IMapper's VTS suite
+// where meaning & correctness of values are more narrowly defined (eg, read-only values)
+
+TEST(Metadata, setGetBufferId) {
+ using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
+
+ std::vector<char> buffer;
+ buffer.resize(12, 0);
+ *reinterpret_cast<int64_t*>(buffer.data()) = 42;
+
+ EXPECT_EQ(8, BufferId::encode(18, buffer.data(), 0));
+ EXPECT_EQ(42, *reinterpret_cast<int64_t*>(buffer.data()));
+ EXPECT_EQ(8, BufferId::encode(18, buffer.data(), buffer.size()));
+ EXPECT_EQ(18, *reinterpret_cast<int64_t*>(buffer.data()));
+ EXPECT_FALSE(BufferId::decode(buffer.data(), 0));
+ auto read = BufferId::decode(buffer.data(), buffer.size());
+ EXPECT_TRUE(read.has_value());
+ EXPECT_EQ(18, read.value_or(0));
+}
+
+TEST(Metadata, setGetDataspace) {
+ using DataspaceValue = StandardMetadata<StandardMetadataType::DATASPACE>::value;
+ using intType = std::underlying_type_t<Dataspace>;
+ std::vector<char> buffer;
+ buffer.resize(12, 0);
+
+ EXPECT_EQ(4, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), 0));
+ EXPECT_EQ(0, *reinterpret_cast<intType*>(buffer.data()));
+ EXPECT_EQ(4, DataspaceValue::encode(Dataspace::BT2020, buffer.data(), buffer.size()));
+ EXPECT_EQ(static_cast<intType>(Dataspace::BT2020), *reinterpret_cast<intType*>(buffer.data()));
+ EXPECT_FALSE(DataspaceValue::decode(buffer.data(), 0));
+ auto read = DataspaceValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(Dataspace::BT2020, *read);
+}
+
+TEST(Metadata, setGetValidName) {
+ using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
+
+ std::vector<char> buffer;
+ buffer.resize(100, 'a');
+ buffer[buffer.size() - 1] = '\0';
+
+ // len("Hello") + sizeof(int64)
+ constexpr int expectedSize = 5 + sizeof(int64_t);
+ EXPECT_EQ(expectedSize, NameValue::encode("Hello", buffer.data(), buffer.size()));
+ EXPECT_EQ(5, *reinterpret_cast<int64_t*>(buffer.data()));
+ // Verify didn't write past the end of the desired size
+ EXPECT_EQ('a', buffer[expectedSize]);
+
+ auto readValue = NameValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(readValue.has_value());
+ EXPECT_EQ(5, readValue->length());
+ EXPECT_EQ("Hello", *readValue);
+}
+
+TEST(Metadata, setGetInvalidName) {
+ using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
+
+ std::vector<char> buffer;
+ buffer.resize(12, 'a');
+ buffer[buffer.size() - 1] = '\0';
+
+ // len("This is a long string") + sizeof(int64)
+ constexpr int expectedSize = 21 + sizeof(int64_t);
+ EXPECT_EQ(expectedSize,
+ NameValue::encode("This is a long string", buffer.data(), buffer.size()));
+ EXPECT_EQ(21, *reinterpret_cast<int64_t*>(buffer.data()));
+ // Verify didn't write the too-long string
+ EXPECT_EQ('a', buffer[9]);
+ EXPECT_EQ('\0', buffer[buffer.size() - 1]);
+
+ auto readValue = NameValue::decode(buffer.data(), buffer.size());
+ EXPECT_FALSE(readValue.has_value());
+ readValue = NameValue::decode(buffer.data(), 0);
+ ASSERT_FALSE(readValue.has_value());
+}
+
+TEST(Metadata, wouldOverflowName) {
+ using NameValue = StandardMetadata<StandardMetadataType::NAME>::value;
+ std::vector<char> buffer(100, 0);
+
+ // int_max + sizeof(int64) overflows int32
+ std::string_view bad_string{"badbeef", std::numeric_limits<int32_t>::max()};
+ EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
+ NameValue::encode(bad_string, buffer.data(), buffer.size()));
+
+ // check barely overflows
+ bad_string = std::string_view{"badbeef", std::numeric_limits<int32_t>::max() - 7};
+ EXPECT_EQ(-AIMAPPER_ERROR_BAD_VALUE,
+ NameValue::encode(bad_string, buffer.data(), buffer.size()));
+}
+
+TEST(Metadata, setGetCompression) {
+ using CompressionValue = StandardMetadata<StandardMetadataType::COMPRESSION>::value;
+ ExtendableType myCompression{"bestest_compression_ever", 42};
+ std::vector<char> buffer(100, '\0');
+ const int expectedSize = myCompression.name.length() + sizeof(int64_t) + sizeof(int64_t);
+ EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), 0));
+ EXPECT_EQ(0, buffer[0]);
+ EXPECT_EQ(expectedSize, CompressionValue::encode(myCompression, buffer.data(), buffer.size()));
+ EXPECT_EQ(myCompression.name.length(), *reinterpret_cast<int64_t*>(buffer.data()));
+ EXPECT_FALSE(CompressionValue::decode(buffer.data(), 0).has_value());
+ auto read = CompressionValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(myCompression, read.value());
+}
+
+TEST(Metadata, setGetPlaneLayout) {
+ using PlaneLayoutValue = StandardMetadata<StandardMetadataType::PLANE_LAYOUTS>::value;
+ PlaneLayout myPlaneLayout;
+ myPlaneLayout.offsetInBytes = 10;
+ myPlaneLayout.sampleIncrementInBits = 11;
+ myPlaneLayout.strideInBytes = 12;
+ myPlaneLayout.widthInSamples = 13;
+ myPlaneLayout.heightInSamples = 14;
+ myPlaneLayout.totalSizeInBytes = 15;
+ myPlaneLayout.horizontalSubsampling = 16;
+ myPlaneLayout.verticalSubsampling = 17;
+
+ myPlaneLayout.components.resize(3);
+ for (int i = 0; i < myPlaneLayout.components.size(); i++) {
+ auto& it = myPlaneLayout.components[i];
+ it.type = ExtendableType{"Plane ID", 40 + i};
+ it.offsetInBits = 20 + i;
+ it.sizeInBits = 30 + i;
+ }
+
+ std::vector<PlaneLayout> layouts{myPlaneLayout, PlaneLayout{}};
+
+ std::vector<char> buffer(5000, '\0');
+ constexpr int componentSize = 8 + (4 * sizeof(int64_t));
+ constexpr int firstLayoutSize = (8 + 1) * sizeof(int64_t) + (3 * componentSize);
+ constexpr int secondLayoutSize = (8 + 1) * sizeof(int64_t);
+ constexpr int expectedSize = firstLayoutSize + secondLayoutSize + sizeof(int64_t);
+ EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), 0));
+ EXPECT_EQ(0, buffer[0]);
+ EXPECT_EQ(expectedSize, PlaneLayoutValue::encode(layouts, buffer.data(), buffer.size()));
+ EXPECT_EQ(3, reinterpret_cast<int64_t*>(buffer.data())[1]);
+ EXPECT_EQ(8, reinterpret_cast<int64_t*>(buffer.data())[2]);
+ EXPECT_EQ(40, reinterpret_cast<int64_t*>(buffer.data())[4]);
+ EXPECT_EQ(31, reinterpret_cast<int64_t*>(buffer.data())[11]);
+ EXPECT_EQ(22, reinterpret_cast<int64_t*>(buffer.data())[15]);
+ EXPECT_EQ(10, reinterpret_cast<int64_t*>(buffer.data())[17]);
+ EXPECT_EQ(11, reinterpret_cast<int64_t*>(buffer.data())[18]);
+ EXPECT_FALSE(PlaneLayoutValue::decode(buffer.data(), 0).has_value());
+ auto read = PlaneLayoutValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(layouts, *read);
+}
+
+TEST(Metadata, setGetRects) {
+ using RectsValue = StandardMetadata<StandardMetadataType::CROP>::value;
+ std::vector<uint8_t> buffer(500, 0);
+ std::vector<Rect> cropRects{2};
+ cropRects[0] = Rect{10, 11, 12, 13};
+ cropRects[1] = Rect{20, 21, 22, 23};
+
+ constexpr int expectedSize = sizeof(int64_t) + (8 * sizeof(int32_t));
+ EXPECT_EQ(expectedSize, RectsValue::encode(cropRects, buffer.data(), buffer.size()));
+ EXPECT_EQ(2, reinterpret_cast<int64_t*>(buffer.data())[0]);
+ EXPECT_EQ(10, reinterpret_cast<int32_t*>(buffer.data())[2]);
+ auto read = RectsValue::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ EXPECT_EQ(cropRects.size(), read->size());
+ EXPECT_EQ(cropRects, *read);
+}
+
+TEST(Metadata, setGetSmpte2086) {
+ using Smpte2086Value = StandardMetadata<StandardMetadataType::SMPTE2086>::value;
+ Smpte2086 source;
+ source.minLuminance = 12.335f;
+ source.maxLuminance = 452.889f;
+ source.whitePoint = XyColor{-6.f, -9.f};
+ source.primaryRed = XyColor{.1f, .2f};
+ source.primaryGreen = XyColor{.3f, .4f};
+ source.primaryBlue = XyColor{.5f, .6f};
+
+ constexpr int expectedSize = 10 * sizeof(float);
+ std::vector<uint8_t> buffer(500, 0);
+ EXPECT_EQ(expectedSize, Smpte2086Value::encode(source, buffer.data(), buffer.size()));
+ auto read = Smpte2086Value::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ ASSERT_TRUE(read->has_value());
+ EXPECT_EQ(source, read->value());
+
+ // A valid encoding of a nullopt
+ read = Smpte2086Value::decode(nullptr, 0);
+ ASSERT_TRUE(read.has_value());
+ EXPECT_FALSE(read->has_value());
+}
+
+TEST(Metadata, setGetCta861_3) {
+ using Cta861_3Value = StandardMetadata<StandardMetadataType::CTA861_3>::value;
+ Cta861_3 source;
+ source.maxFrameAverageLightLevel = 244.55f;
+ source.maxContentLightLevel = 202.202f;
+
+ constexpr int expectedSize = 2 * sizeof(float);
+ std::vector<uint8_t> buffer(500, 0);
+ EXPECT_EQ(expectedSize, Cta861_3Value::encode(source, buffer.data(), buffer.size()));
+ auto read = Cta861_3Value::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ ASSERT_TRUE(read->has_value());
+ EXPECT_EQ(source, read->value());
+
+ // A valid encoding of a nullopt
+ read = Cta861_3Value::decode(nullptr, 0);
+ ASSERT_TRUE(read.has_value());
+ EXPECT_FALSE(read->has_value());
+}
+
+TEST(Metadata, setGetSmpte2094_10) {
+ using SMPTE2094_10Value = StandardMetadata<StandardMetadataType::SMPTE2094_10>::value;
+
+ std::vector<uint8_t> buffer(500, 0);
+ EXPECT_EQ(0, SMPTE2094_10Value::encode(std::nullopt, buffer.data(), buffer.size()));
+ auto read = SMPTE2094_10Value::decode(buffer.data(), 0);
+ ASSERT_TRUE(read.has_value());
+ EXPECT_FALSE(read->has_value());
+
+ const std::vector<uint8_t> emptyBuffer;
+ EXPECT_EQ(sizeof(int64_t),
+ SMPTE2094_10Value::encode(emptyBuffer, buffer.data(), buffer.size()));
+ read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ ASSERT_TRUE(read->has_value());
+ EXPECT_EQ(0, read->value().size());
+
+ const std::vector<uint8_t> simpleBuffer{0, 1, 2, 3, 4, 5};
+ EXPECT_EQ(sizeof(int64_t) + 6,
+ SMPTE2094_10Value::encode(simpleBuffer, buffer.data(), buffer.size()));
+ read = SMPTE2094_10Value::decode(buffer.data(), buffer.size());
+ ASSERT_TRUE(read.has_value());
+ ASSERT_TRUE(read->has_value());
+ EXPECT_EQ(6, read->value().size());
+ EXPECT_EQ(simpleBuffer, read->value());
+}
+
+TEST(MetadataProvider, bufferId) {
+ using BufferId = StandardMetadata<StandardMetadataType::BUFFER_ID>::value;
+ std::vector<uint8_t> buffer(500, 0);
+ int result = provideStandardMetadata(StandardMetadataType::BUFFER_ID, buffer.data(),
+ buffer.size(), []<StandardMetadataType T>(auto&& provide) {
+ if constexpr (T == StandardMetadataType::BUFFER_ID) {
+ return provide(42);
+ }
+ return 0;
+ });
+
+ EXPECT_EQ(8, result);
+ auto read = BufferId::decode(buffer.data(), buffer.size());
+ EXPECT_EQ(42, read.value_or(0));
+}
+
+TEST(MetadataProvider, allJumpsWork) {
+ const auto& values = ndk::internal::enum_values<StandardMetadataType>;
+ auto get = [](StandardMetadataType type) -> int {
+ return provideStandardMetadata(type, nullptr, 0, []<StandardMetadataType T>(auto&&) {
+ return static_cast<int>(T) + 100;
+ });
+ };
+
+ for (auto& type : values) {
+ const int expected = type == StandardMetadataType::INVALID ? -AIMAPPER_ERROR_UNSUPPORTED
+ : static_cast<int>(type) + 100;
+ EXPECT_EQ(expected, get(type));
+ }
+}
+
+TEST(MetadataProvider, invalid) {
+ int result = provideStandardMetadata(StandardMetadataType::INVALID, nullptr, 0,
+ []<StandardMetadataType T>(auto&&) { return 10; });
+
+ EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, result);
+}
+
+TEST(MetadataProvider, outOfBounds) {
+ int result = provideStandardMetadata(static_cast<StandardMetadataType>(-1), nullptr, 0,
+ []<StandardMetadataType T>(auto&&) { return 10; });
+ EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, result) << "-1 should have resulted in UNSUPPORTED";
+
+ result = provideStandardMetadata(static_cast<StandardMetadataType>(100), nullptr, 0,
+ []<StandardMetadataType T>(auto&&) { return 10; });
+ EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, result)
+ << "100 (out of range) should have resulted in UNSUPPORTED";
+}
diff --git a/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h
new file mode 100644
index 0000000..7861af8
--- /dev/null
+++ b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h
@@ -0,0 +1,576 @@
+/*
+ * 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/graphics/common/BlendMode.h>
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <aidl/android/hardware/graphics/common/Cta861_3.h>
+#include <aidl/android/hardware/graphics/common/Dataspace.h>
+#include <aidl/android/hardware/graphics/common/ExtendableType.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <aidl/android/hardware/graphics/common/PlaneLayout.h>
+#include <aidl/android/hardware/graphics/common/PlaneLayoutComponent.h>
+#include <aidl/android/hardware/graphics/common/Rect.h>
+#include <aidl/android/hardware/graphics/common/Smpte2086.h>
+#include <aidl/android/hardware/graphics/common/StandardMetadataType.h>
+#include <aidl/android/hardware/graphics/common/XyColor.h>
+#include <android/hardware/graphics/mapper/IMapper.h>
+
+#include <cinttypes>
+#include <string_view>
+#include <type_traits>
+#include <vector>
+
+namespace android::hardware::graphics::mapper {
+
+using ::aidl::android::hardware::graphics::common::BlendMode;
+using ::aidl::android::hardware::graphics::common::BufferUsage;
+using ::aidl::android::hardware::graphics::common::Cta861_3;
+using ::aidl::android::hardware::graphics::common::Dataspace;
+using ::aidl::android::hardware::graphics::common::ExtendableType;
+using ::aidl::android::hardware::graphics::common::PixelFormat;
+using ::aidl::android::hardware::graphics::common::PlaneLayout;
+using ::aidl::android::hardware::graphics::common::PlaneLayoutComponent;
+using ::aidl::android::hardware::graphics::common::Rect;
+using ::aidl::android::hardware::graphics::common::Smpte2086;
+using ::aidl::android::hardware::graphics::common::StandardMetadataType;
+using ::aidl::android::hardware::graphics::common::XyColor;
+
+class MetadataWriter {
+ private:
+ uint8_t* _Nonnull mDest;
+ size_t mSizeRemaining = 0;
+ int32_t mDesiredSize = 0;
+
+ void* _Nullable reserve(size_t sizeToWrite) {
+ if (mDesiredSize < 0) {
+ // Error state
+ return nullptr;
+ }
+ if (__builtin_add_overflow(mDesiredSize, sizeToWrite, &mDesiredSize)) {
+ // Overflowed, abort writing any further data
+ mDesiredSize = -AIMAPPER_ERROR_BAD_VALUE;
+ mSizeRemaining = 0;
+ return nullptr;
+ }
+ if (sizeToWrite > mSizeRemaining) {
+ mSizeRemaining = 0;
+ return nullptr;
+ } else {
+ mSizeRemaining -= sizeToWrite;
+ uint8_t* whereToWrite = mDest;
+ mDest += sizeToWrite;
+ return whereToWrite;
+ }
+ }
+
+ public:
+ explicit MetadataWriter(void* _Nullable destBuffer, size_t destBufferSize)
+ : mDest(reinterpret_cast<uint8_t*>(destBuffer)), mSizeRemaining(destBufferSize) {}
+
+ int32_t desiredSize() const { return mDesiredSize; }
+
+ template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
+ MetadataWriter& write(T value) {
+ auto sizeToWrite = sizeof(T);
+ if (void* dest = reserve(sizeToWrite)) {
+ memcpy(dest, &value, sizeToWrite);
+ }
+ return *this;
+ }
+
+ MetadataWriter& write(float value) {
+ auto sizeToWrite = sizeof(float);
+ if (void* dest = reserve(sizeToWrite)) {
+ memcpy(dest, &value, sizeToWrite);
+ }
+ return *this;
+ }
+
+ MetadataWriter& write(const std::string_view& value) {
+ auto sizeToWrite = value.length();
+ write<int64_t>(sizeToWrite);
+ if (void* dest = reserve(sizeToWrite)) {
+ memcpy(dest, value.data(), sizeToWrite);
+ }
+ return *this;
+ }
+
+ MetadataWriter& write(const std::vector<uint8_t>& value) {
+ auto sizeToWrite = value.size();
+ write<int64_t>(sizeToWrite);
+ if (void* dest = reserve(sizeToWrite)) {
+ memcpy(dest, value.data(), sizeToWrite);
+ }
+ return *this;
+ }
+
+ MetadataWriter& write(const ExtendableType& value) {
+ return write(value.name).write(value.value);
+ }
+
+ MetadataWriter& write(const XyColor& value) { return write(value.x).write(value.y); }
+};
+
+class MetadataReader {
+ private:
+ const uint8_t* _Nonnull mSrc;
+ size_t mSizeRemaining = 0;
+ bool mOk = true;
+
+ const void* _Nullable advance(size_t size) {
+ if (mOk && mSizeRemaining >= size) {
+ const void* buf = mSrc;
+ mSrc += size;
+ mSizeRemaining -= size;
+ return buf;
+ }
+ mOk = false;
+ return nullptr;
+ }
+
+ public:
+ explicit MetadataReader(const void* _Nonnull metadata, size_t metadataSize)
+ : mSrc(reinterpret_cast<const uint8_t*>(metadata)), mSizeRemaining(metadataSize) {}
+
+ [[nodiscard]] size_t remaining() const { return mSizeRemaining; }
+ [[nodiscard]] bool ok() const { return mOk; }
+
+ template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
+ MetadataReader& read(T& dest) {
+ if (const void* src = advance(sizeof(T))) {
+ memcpy(&dest, src, sizeof(T));
+ }
+ return *this;
+ }
+
+ MetadataReader& read(float& dest) {
+ if (const void* src = advance(sizeof(float))) {
+ memcpy(&dest, src, sizeof(float));
+ }
+ return *this;
+ }
+
+ MetadataReader& read(std::string& dest) {
+ dest = readString();
+ return *this;
+ }
+
+ MetadataReader& read(ExtendableType& dest) {
+ dest.name = readString();
+ read(dest.value);
+ return *this;
+ }
+
+ MetadataReader& read(XyColor& dest) {
+ read(dest.x);
+ read(dest.y);
+ return *this;
+ }
+
+ template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
+ [[nodiscard]] std::optional<T> readInt() {
+ auto sizeToRead = sizeof(T);
+ if (const void* src = advance(sizeof(T))) {
+ T ret;
+ memcpy(&ret, src, sizeToRead);
+ return ret;
+ }
+ return std::nullopt;
+ }
+
+ [[nodiscard]] std::string_view readString() {
+ auto lengthOpt = readInt<int64_t>();
+ if (!lengthOpt) {
+ return std::string_view{};
+ }
+ size_t length = lengthOpt.value();
+ if (const void* src = advance(length)) {
+ return std::string_view{reinterpret_cast<const char*>(src), length};
+ }
+ return std::string_view{};
+ }
+
+ [[nodiscard]] std::optional<ExtendableType> readExtendable() {
+ ExtendableType ret;
+ ret.name = readString();
+ auto value = readInt<int64_t>();
+ if (value) {
+ ret.value = value.value();
+ return ret;
+ } else {
+ return std::nullopt;
+ }
+ }
+
+ [[nodiscard]] std::vector<uint8_t> readBuffer() {
+ std::vector<uint8_t> ret;
+ size_t length = readInt<int64_t>().value_or(0);
+ if (const void* src = advance(length)) {
+ ret.resize(length);
+ memcpy(ret.data(), src, length);
+ }
+ return ret;
+ }
+};
+
+template <typename T, class Enable = void>
+struct MetadataValue {};
+
+template <typename T>
+struct MetadataValue<T, std::enable_if_t<std::is_integral_v<T>>> {
+ [[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
+ size_t destBufferSize) {
+ return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
+ }
+
+ [[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
+ size_t metadataSize) {
+ return MetadataReader{metadata, metadataSize}.readInt<T>();
+ }
+};
+
+template <typename T>
+struct MetadataValue<T, std::enable_if_t<std::is_enum_v<T>>> {
+ [[nodiscard]] static int32_t encode(T value, void* _Nullable destBuffer,
+ size_t destBufferSize) {
+ return MetadataWriter{destBuffer, destBufferSize}
+ .write(static_cast<std::underlying_type_t<T>>(value))
+ .desiredSize();
+ }
+
+ [[nodiscard]] static std::optional<T> decode(const void* _Nonnull metadata,
+ size_t metadataSize) {
+ std::underlying_type_t<T> temp;
+ return MetadataReader{metadata, metadataSize}.read(temp).ok()
+ ? std::optional<T>(static_cast<T>(temp))
+ : std::nullopt;
+ }
+};
+
+template <>
+struct MetadataValue<std::string> {
+ [[nodiscard]] static int32_t encode(const std::string_view& value, void* _Nullable destBuffer,
+ size_t destBufferSize) {
+ return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
+ }
+
+ [[nodiscard]] static std::optional<std::string> decode(const void* _Nonnull metadata,
+ size_t metadataSize) {
+ auto reader = MetadataReader{metadata, metadataSize};
+ auto result = reader.readString();
+ return reader.ok() ? std::optional<std::string>{result} : std::nullopt;
+ }
+};
+
+template <>
+struct MetadataValue<ExtendableType> {
+ static_assert(sizeof(int64_t) == sizeof(ExtendableType::value));
+
+ [[nodiscard]] static int32_t encode(const ExtendableType& value, void* _Nullable destBuffer,
+ size_t destBufferSize) {
+ return MetadataWriter{destBuffer, destBufferSize}.write(value).desiredSize();
+ }
+
+ [[nodiscard]] static std::optional<ExtendableType> decode(const void* _Nonnull metadata,
+ size_t metadataSize) {
+ return MetadataReader{metadata, metadataSize}.readExtendable();
+ }
+};
+
+template <>
+struct MetadataValue<std::vector<PlaneLayout>> {
+ [[nodiscard]] static int32_t encode(const std::vector<PlaneLayout>& values,
+ void* _Nullable destBuffer, size_t destBufferSize) {
+ MetadataWriter writer{destBuffer, destBufferSize};
+ writer.write<int64_t>(values.size());
+ for (const auto& value : values) {
+ writer.write<int64_t>(value.components.size());
+ for (const auto& component : value.components) {
+ writer.write(component.type)
+ .write<int64_t>(component.offsetInBits)
+ .write<int64_t>(component.sizeInBits);
+ }
+ writer.write<int64_t>(value.offsetInBytes)
+ .write<int64_t>(value.sampleIncrementInBits)
+ .write<int64_t>(value.strideInBytes)
+ .write<int64_t>(value.widthInSamples)
+ .write<int64_t>(value.heightInSamples)
+ .write<int64_t>(value.totalSizeInBytes)
+ .write<int64_t>(value.horizontalSubsampling)
+ .write<int64_t>(value.verticalSubsampling);
+ }
+ return writer.desiredSize();
+ }
+
+ using DecodeResult = std::optional<std::vector<PlaneLayout>>;
+ [[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
+ std::vector<PlaneLayout> values;
+ MetadataReader reader{metadata, metadataSize};
+ auto numPlanes = reader.readInt<int64_t>().value_or(0);
+ values.reserve(numPlanes);
+ for (int i = 0; i < numPlanes && reader.ok(); i++) {
+ PlaneLayout& value = values.emplace_back();
+ auto numPlaneComponents = reader.readInt<int64_t>().value_or(0);
+ value.components.reserve(numPlaneComponents);
+ for (int i = 0; i < numPlaneComponents && reader.ok(); i++) {
+ PlaneLayoutComponent& component = value.components.emplace_back();
+ reader.read(component.type)
+ .read<int64_t>(component.offsetInBits)
+ .read<int64_t>(component.sizeInBits);
+ }
+ reader.read<int64_t>(value.offsetInBytes)
+ .read<int64_t>(value.sampleIncrementInBits)
+ .read<int64_t>(value.strideInBytes)
+ .read<int64_t>(value.widthInSamples)
+ .read<int64_t>(value.heightInSamples)
+ .read<int64_t>(value.totalSizeInBytes)
+ .read<int64_t>(value.horizontalSubsampling)
+ .read<int64_t>(value.verticalSubsampling);
+ }
+ return reader.ok() ? DecodeResult{std::move(values)} : std::nullopt;
+ }
+};
+
+template <>
+struct MetadataValue<std::vector<Rect>> {
+ [[nodiscard]] static int32_t encode(const std::vector<Rect>& value, void* _Nullable destBuffer,
+ size_t destBufferSize) {
+ MetadataWriter writer{destBuffer, destBufferSize};
+ writer.write<int64_t>(value.size());
+ for (auto& rect : value) {
+ writer.write<int32_t>(rect.left)
+ .write<int32_t>(rect.top)
+ .write<int32_t>(rect.right)
+ .write<int32_t>(rect.bottom);
+ }
+ return writer.desiredSize();
+ }
+
+ using DecodeResult = std::optional<std::vector<Rect>>;
+ [[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
+ MetadataReader reader{metadata, metadataSize};
+ std::vector<Rect> value;
+ auto numRects = reader.readInt<int64_t>().value_or(0);
+ value.reserve(numRects);
+ for (int i = 0; i < numRects && reader.ok(); i++) {
+ Rect& rect = value.emplace_back();
+ reader.read<int32_t>(rect.left)
+ .read<int32_t>(rect.top)
+ .read<int32_t>(rect.right)
+ .read<int32_t>(rect.bottom);
+ }
+ return reader.ok() ? DecodeResult{std::move(value)} : std::nullopt;
+ }
+};
+
+template <>
+struct MetadataValue<std::optional<Smpte2086>> {
+ [[nodiscard]] static int32_t encode(const std::optional<Smpte2086>& optValue,
+ void* _Nullable destBuffer, size_t destBufferSize) {
+ if (optValue.has_value()) {
+ const auto& value = *optValue;
+ return MetadataWriter{destBuffer, destBufferSize}
+ .write(value.primaryRed)
+ .write(value.primaryGreen)
+ .write(value.primaryBlue)
+ .write(value.whitePoint)
+ .write(value.maxLuminance)
+ .write(value.minLuminance)
+ .desiredSize();
+ } else {
+ return 0;
+ }
+ }
+
+ // Double optional because the value type itself is an optional<>
+ using DecodeResult = std::optional<std::optional<Smpte2086>>;
+ [[nodiscard]] static DecodeResult decode(const void* _Nullable metadata, size_t metadataSize) {
+ std::optional<Smpte2086> optValue{std::nullopt};
+ if (metadataSize > 0) {
+ Smpte2086 value;
+ MetadataReader reader{metadata, metadataSize};
+ reader.read(value.primaryRed)
+ .read(value.primaryGreen)
+ .read(value.primaryBlue)
+ .read(value.whitePoint)
+ .read(value.maxLuminance)
+ .read(value.minLuminance);
+ if (reader.ok()) {
+ optValue = std::move(value);
+ } else {
+ return std::nullopt;
+ }
+ }
+ return DecodeResult{std::move(optValue)};
+ }
+};
+
+template <>
+struct MetadataValue<std::optional<Cta861_3>> {
+ [[nodiscard]] static int32_t encode(const std::optional<Cta861_3>& optValue,
+ void* _Nullable destBuffer, size_t destBufferSize) {
+ if (optValue.has_value()) {
+ const auto& value = *optValue;
+ return MetadataWriter{destBuffer, destBufferSize}
+ .write(value.maxContentLightLevel)
+ .write(value.maxFrameAverageLightLevel)
+ .desiredSize();
+ } else {
+ return 0;
+ }
+ }
+
+ // Double optional because the value type itself is an optional<>
+ using DecodeResult = std::optional<std::optional<Cta861_3>>;
+ [[nodiscard]] static DecodeResult decode(const void* _Nullable metadata, size_t metadataSize) {
+ std::optional<Cta861_3> optValue{std::nullopt};
+ if (metadataSize > 0) {
+ MetadataReader reader{metadata, metadataSize};
+ Cta861_3 value;
+ reader.read(value.maxContentLightLevel).read(value.maxFrameAverageLightLevel);
+ if (reader.ok()) {
+ optValue = std::move(value);
+ } else {
+ return std::nullopt;
+ }
+ }
+ return DecodeResult{std::move(optValue)};
+ }
+};
+
+template <>
+struct MetadataValue<std::optional<std::vector<uint8_t>>> {
+ [[nodiscard]] static int32_t encode(const std::optional<std::vector<uint8_t>>& value,
+ void* _Nullable destBuffer, size_t destBufferSize) {
+ if (!value.has_value()) {
+ return 0;
+ }
+ return MetadataWriter{destBuffer, destBufferSize}.write(*value).desiredSize();
+ }
+
+ using DecodeResult = std::optional<std::optional<std::vector<uint8_t>>>;
+ [[nodiscard]] static DecodeResult decode(const void* _Nonnull metadata, size_t metadataSize) {
+ std::optional<std::vector<uint8_t>> optValue;
+ if (metadataSize > 0) {
+ MetadataReader reader{metadata, metadataSize};
+ auto value = reader.readBuffer();
+ if (reader.ok()) {
+ optValue = std::move(value);
+ } else {
+ return std::nullopt;
+ }
+ }
+ return DecodeResult{std::move(optValue)};
+ }
+};
+
+template <StandardMetadataType>
+struct StandardMetadata {};
+
+#define DEFINE_TYPE(name, typeArg) \
+ template <> \
+ struct StandardMetadata<StandardMetadataType::name> { \
+ using value_type = typeArg; \
+ using value = MetadataValue<value_type>; \
+ static_assert( \
+ StandardMetadataType::name == \
+ ndk::internal::enum_values<StandardMetadataType>[static_cast<size_t>( \
+ StandardMetadataType::name)], \
+ "StandardMetadataType must have equivalent value to index"); \
+ }
+
+DEFINE_TYPE(BUFFER_ID, uint64_t);
+DEFINE_TYPE(NAME, std::string);
+DEFINE_TYPE(WIDTH, uint64_t);
+DEFINE_TYPE(HEIGHT, uint64_t);
+DEFINE_TYPE(LAYER_COUNT, uint64_t);
+DEFINE_TYPE(PIXEL_FORMAT_REQUESTED, PixelFormat);
+DEFINE_TYPE(PIXEL_FORMAT_FOURCC, uint32_t);
+DEFINE_TYPE(PIXEL_FORMAT_MODIFIER, uint64_t);
+DEFINE_TYPE(USAGE, BufferUsage);
+DEFINE_TYPE(ALLOCATION_SIZE, uint64_t);
+DEFINE_TYPE(PROTECTED_CONTENT, uint64_t);
+DEFINE_TYPE(COMPRESSION, ExtendableType);
+DEFINE_TYPE(INTERLACED, ExtendableType);
+DEFINE_TYPE(CHROMA_SITING, ExtendableType);
+DEFINE_TYPE(PLANE_LAYOUTS, std::vector<PlaneLayout>);
+DEFINE_TYPE(CROP, std::vector<Rect>);
+DEFINE_TYPE(DATASPACE, Dataspace);
+DEFINE_TYPE(BLEND_MODE, BlendMode);
+DEFINE_TYPE(SMPTE2086, std::optional<Smpte2086>);
+DEFINE_TYPE(CTA861_3, std::optional<Cta861_3>);
+DEFINE_TYPE(SMPTE2094_10, std::optional<std::vector<uint8_t>>);
+DEFINE_TYPE(SMPTE2094_40, std::optional<std::vector<uint8_t>>);
+
+#undef DEFINE_TYPE
+
+template <typename F, std::size_t... I>
+void invokeWithStandardMetadata(F&& f, StandardMetadataType type, std::index_sequence<I...>) {
+ // Setup the jump table, mapping from each type to a springboard that invokes the template
+ // function with the appropriate concrete type
+ using F_PTR = decltype(&f);
+ using THUNK = void (*)(F_PTR);
+ static constexpr auto jump = std::array<THUNK, sizeof...(I)>{[](F_PTR fp) {
+ constexpr StandardMetadataType type = ndk::internal::enum_values<StandardMetadataType>[I];
+ if constexpr (type != StandardMetadataType::INVALID) {
+ (*fp)(StandardMetadata<type>{});
+ }
+ }...};
+
+ auto index = static_cast<size_t>(type);
+ if (index >= 0 && index < jump.size()) {
+ jump[index](&f);
+ }
+}
+
+template <typename F, typename StandardMetadataSequence = std::make_index_sequence<
+ ndk::internal::enum_values<StandardMetadataType>.size()>>
+int32_t provideStandardMetadata(StandardMetadataType type, void* _Nullable destBuffer,
+ size_t destBufferSize, F&& f) {
+ int32_t retVal = -AIMAPPER_ERROR_UNSUPPORTED;
+ invokeWithStandardMetadata(
+ [&]<StandardMetadataType T>(StandardMetadata<T>) {
+ retVal = f.template operator()<T>(
+ [&](const typename StandardMetadata<T>::value_type& value) -> int32_t {
+ return StandardMetadata<T>::value::encode(value, destBuffer,
+ destBufferSize);
+ });
+ },
+ type, StandardMetadataSequence{});
+ return retVal;
+}
+
+template <typename F, typename StandardMetadataSequence = std::make_index_sequence<
+ ndk::internal::enum_values<StandardMetadataType>.size()>>
+AIMapper_Error applyStandardMetadata(StandardMetadataType type, const void* _Nonnull metadata,
+ size_t metadataSize, F&& f) {
+ AIMapper_Error retVal = AIMAPPER_ERROR_UNSUPPORTED;
+ invokeWithStandardMetadata(
+ [&]<StandardMetadataType T>(StandardMetadata<T>) {
+ auto value = StandardMetadata<T>::value::decode(metadata, metadataSize);
+ if (value.has_value()) {
+ retVal = f.template operator()<T>(std::move(*value));
+ } else {
+ retVal = AIMAPPER_ERROR_BAD_VALUE;
+ }
+ },
+ type, StandardMetadataSequence{});
+ return retVal;
+}
+
+} // namespace android::hardware::graphics::mapper
\ No newline at end of file
diff --git a/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperProvider.h b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperProvider.h
new file mode 100644
index 0000000..957fdc9
--- /dev/null
+++ b/graphics/mapper/stable-c/implutils/include/android/hardware/graphics/mapper/utils/IMapperProvider.h
@@ -0,0 +1,222 @@
+/*
+ * 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 <android-base/unique_fd.h>
+#include <android/hardware/graphics/mapper/IMapper.h>
+#include <log/log.h>
+
+#include <mutex>
+#include <optional>
+#include <type_traits>
+
+/**
+ * Helper utilities for providing an IMapper-StableC implementation.
+ */
+
+namespace vendor::mapper {
+
+/**
+ * Extend from this interface to provide Version 5 of the IMapper interface
+ */
+struct IMapperV5Impl {
+ static const auto version = AIMAPPER_VERSION_5;
+ virtual ~IMapperV5Impl() = default;
+
+ virtual AIMapper_Error importBuffer(const native_handle_t* _Nonnull handle,
+ buffer_handle_t _Nullable* _Nonnull outBufferHandle) = 0;
+
+ virtual AIMapper_Error freeBuffer(buffer_handle_t _Nonnull buffer) = 0;
+
+ virtual AIMapper_Error getTransportSize(buffer_handle_t _Nonnull buffer,
+ uint32_t* _Nonnull outNumFds,
+ uint32_t* _Nonnull outNumInts) = 0;
+
+ virtual AIMapper_Error lock(buffer_handle_t _Nonnull buffer, uint64_t cpuUsage,
+ ARect accessRegion, int acquireFence,
+ void* _Nullable* _Nonnull outData) = 0;
+
+ virtual AIMapper_Error unlock(buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence) = 0;
+
+ virtual AIMapper_Error flushLockedBuffer(buffer_handle_t _Nonnull buffer) = 0;
+
+ virtual AIMapper_Error rereadLockedBuffer(buffer_handle_t _Nonnull buffer) = 0;
+
+ virtual int32_t getMetadata(buffer_handle_t _Nonnull buffer, AIMapper_MetadataType metadataType,
+ void* _Nullable destBuffer, size_t destBufferSize) = 0;
+
+ virtual int32_t getStandardMetadata(buffer_handle_t _Nonnull buffer,
+ int64_t standardMetadataType, void* _Nullable destBuffer,
+ size_t destBufferSize) = 0;
+
+ virtual AIMapper_Error setMetadata(buffer_handle_t _Nonnull buffer,
+ AIMapper_MetadataType metadataType,
+ const void* _Nonnull metadata, size_t metadataSize) = 0;
+
+ virtual AIMapper_Error setStandardMetadata(buffer_handle_t _Nonnull buffer,
+ int64_t standardMetadataType,
+ const void* _Nonnull metadata,
+ size_t metadataSize) = 0;
+
+ virtual AIMapper_Error listSupportedMetadataTypes(
+ const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList,
+ size_t* _Nonnull outNumberOfDescriptions) = 0;
+
+ virtual AIMapper_Error dumpBuffer(buffer_handle_t _Nonnull bufferHandle,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
+ void* _Null_unspecified context) = 0;
+
+ virtual AIMapper_Error dumpAllBuffers(
+ AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
+ void* _Null_unspecified context) = 0;
+
+ virtual AIMapper_Error getReservedRegion(buffer_handle_t _Nonnull buffer,
+ void* _Nullable* _Nonnull outReservedRegion,
+ uint64_t* _Nonnull outReservedSize) = 0;
+};
+
+namespace provider {
+#ifndef __cpp_inline_variables
+#error "Only C++17 & newer is supported; inline variables is missing"
+#endif
+
+inline void* _Nullable sIMapperInstance = nullptr;
+} // namespace provider
+
+template <typename IMPL>
+class IMapperProvider {
+ private:
+ static_assert(IMPL::version >= AIMAPPER_VERSION_5, "Must be at least AIMAPPER_VERSION_5");
+ static_assert(std::is_final_v<IMPL>, "Implementation must be final");
+ static_assert(std::is_constructible_v<IMPL>, "Implementation must have a no-args constructor");
+
+ std::once_flag mLoadOnceFlag;
+ std::optional<IMPL> mImpl;
+ AIMapper mMapper = {};
+
+ static IMPL& impl() {
+ return *reinterpret_cast<IMapperProvider<IMPL>*>(provider::sIMapperInstance)->mImpl;
+ }
+
+ void bindV5() {
+ mMapper.v5 = {
+ .importBuffer = [](const native_handle_t* _Nonnull handle,
+ buffer_handle_t _Nullable* _Nonnull outBufferHandle)
+ -> AIMapper_Error { return impl().importBuffer(handle, outBufferHandle); },
+
+ .freeBuffer = [](buffer_handle_t _Nonnull buffer) -> AIMapper_Error {
+ return impl().freeBuffer(buffer);
+ },
+
+ .getTransportSize = [](buffer_handle_t _Nonnull buffer,
+ uint32_t* _Nonnull outNumFds,
+ uint32_t* _Nonnull outNumInts) -> AIMapper_Error {
+ return impl().getTransportSize(buffer, outNumFds, outNumInts);
+ },
+
+ .lock = [](buffer_handle_t _Nonnull buffer, uint64_t cpuUsage, ARect accessRegion,
+ int acquireFence, void* _Nullable* _Nonnull outData) -> AIMapper_Error {
+ return impl().lock(buffer, cpuUsage, accessRegion, acquireFence, outData);
+ },
+
+ .unlock = [](buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence)
+ -> AIMapper_Error { return impl().unlock(buffer, releaseFence); },
+
+ .flushLockedBuffer = [](buffer_handle_t _Nonnull buffer) -> AIMapper_Error {
+ return impl().flushLockedBuffer(buffer);
+ },
+
+ .rereadLockedBuffer = [](buffer_handle_t _Nonnull buffer) -> AIMapper_Error {
+ return impl().rereadLockedBuffer(buffer);
+ },
+
+ .getMetadata = [](buffer_handle_t _Nonnull buffer,
+ AIMapper_MetadataType metadataType, void* _Nullable destBuffer,
+ size_t destBufferSize) -> int32_t {
+ return impl().getMetadata(buffer, metadataType, destBuffer, destBufferSize);
+ },
+
+ .getStandardMetadata = [](buffer_handle_t _Nonnull buffer,
+ int64_t standardMetadataType, void* _Nullable destBuffer,
+ size_t destBufferSize) -> int32_t {
+ return impl().getStandardMetadata(buffer, standardMetadataType, destBuffer,
+ destBufferSize);
+ },
+
+ .setMetadata = [](buffer_handle_t _Nonnull buffer,
+ AIMapper_MetadataType metadataType, const void* _Nonnull metadata,
+ size_t metadataSize) -> AIMapper_Error {
+ return impl().setMetadata(buffer, metadataType, metadata, metadataSize);
+ },
+
+ .setStandardMetadata =
+ [](buffer_handle_t _Nonnull buffer, int64_t standardMetadataType,
+ const void* _Nonnull metadata, size_t metadataSize) -> AIMapper_Error {
+ return impl().setStandardMetadata(buffer, standardMetadataType, metadata,
+ metadataSize);
+ },
+
+ .listSupportedMetadataTypes =
+ [](const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList,
+ size_t* _Nonnull outNumberOfDescriptions) -> AIMapper_Error {
+ return impl().listSupportedMetadataTypes(outDescriptionList,
+ outNumberOfDescriptions);
+ },
+
+ .dumpBuffer = [](buffer_handle_t _Nonnull bufferHandle,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
+ void* _Null_unspecified context) -> AIMapper_Error {
+ return impl().dumpBuffer(bufferHandle, dumpBufferCallback, context);
+ },
+
+ .dumpAllBuffers =
+ [](AIMapper_BeginDumpBufferCallback _Nonnull beginDumpBufferCallback,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
+ void* _Null_unspecified context) {
+ return impl().dumpAllBuffers(beginDumpBufferCallback,
+ dumpBufferCallback, context);
+ },
+
+ .getReservedRegion = [](buffer_handle_t _Nonnull buffer,
+ void* _Nullable* _Nonnull outReservedRegion,
+ uint64_t* _Nonnull outReservedSize) -> AIMapper_Error {
+ return impl().getReservedRegion(buffer, outReservedRegion, outReservedSize);
+ },
+ };
+ }
+
+ public:
+ explicit IMapperProvider() = default;
+
+ AIMapper_Error load(AIMapper* _Nullable* _Nonnull outImplementation) {
+ std::call_once(mLoadOnceFlag, [this] {
+ LOG_ALWAYS_FATAL_IF(provider::sIMapperInstance != nullptr,
+ "AIMapper implementation already loaded!");
+ provider::sIMapperInstance = this;
+ mImpl.emplace();
+ mMapper.version = IMPL::version;
+ if (IMPL::version >= AIMAPPER_VERSION_5) {
+ bindV5();
+ }
+ });
+ *outImplementation = &mMapper;
+ return AIMAPPER_ERROR_NONE;
+ }
+};
+
+} // namespace vendor::mapper
diff --git a/graphics/mapper/stable-c/include/android/hardware/graphics/mapper/IMapper.h b/graphics/mapper/stable-c/include/android/hardware/graphics/mapper/IMapper.h
new file mode 100644
index 0000000..0f6d146
--- /dev/null
+++ b/graphics/mapper/stable-c/include/android/hardware/graphics/mapper/IMapper.h
@@ -0,0 +1,691 @@
+/*
+ * 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.
+ */
+
+/**
+ * IMapper Stable-C HAL interface
+ *
+ * This file represents the sphal interface between libui & the IMapper HAL implementation.
+ * A vendor implementation of this interface is retrieved by looking up the vendor imapper
+ * implementation library via the IAllocator AIDL interface.
+ *
+ * This interface is not intended for general use.
+ */
+
+#pragma once
+
+#include <sys/cdefs.h>
+#include <cinttypes>
+#include <cstddef>
+#include <type_traits>
+
+#include <android/rect.h>
+#include <cutils/native_handle.h>
+
+__BEGIN_DECLS
+
+/**
+ * AIMapper versioning
+ *
+ * IMapper versions 0-1 are pre-treble
+ * IMapper versions 2-4 are HIDL
+ * C-style AIMapper API starts at 5
+ */
+enum AIMapper_Version : uint32_t {
+ AIMAPPER_VERSION_5 = 5,
+};
+
+/**
+ * Possible AIMapper errors
+ * Values are the same as IMapper 4.0's Error type for simplicity
+ */
+enum AIMapper_Error : int32_t {
+ /**
+ * No error.
+ */
+ AIMAPPER_ERROR_NONE = 0,
+ /**
+ * Invalid BufferDescriptor.
+ */
+ AIMAPPER_ERROR_BAD_DESCRIPTOR = 1,
+ /**
+ * Invalid buffer handle.
+ */
+ AIMAPPER_ERROR_BAD_BUFFER = 2,
+ /**
+ * Invalid HardwareBufferDescription.
+ */
+ AIMAPPER_ERROR_BAD_VALUE = 3,
+ /**
+ * Resource unavailable.
+ */
+ AIMAPPER_ERROR_NO_RESOURCES = 5,
+ /**
+ * Permanent failure.
+ */
+ AIMAPPER_ERROR_UNSUPPORTED = 7,
+};
+
+/**
+ * MetadataType represents the different types of buffer metadata that could be
+ * associated with a buffer. It is used by IMapper to help get and set buffer metadata
+ * on the buffer's native handle.
+ *
+ * Standard buffer metadata will have the name field set to
+ * "android.hardware.graphics.common.StandardMetadataType" and will contain values
+ * from StandardMetadataType.aidl.
+ *
+ * Vendor-provided metadata should be prefixed with a "vendor.mycompanyname.*" namespace. It is
+ * recommended that the metadata follows the pattern of StandardMetadaType.aidl. That is, an
+ * aidl-defined enum with @VendorStability on it and the naming then matching that type such
+ * as "vendor.mycompanyname.graphics.common.MetadataType" with the value field then set to the
+ * aidl's enum value.
+ *
+ * Each company should create their own enum & namespace. The name
+ * field prevents values from different companies from colliding.
+ */
+typedef struct AIMapper_MetadataType {
+ const char* _Nonnull name;
+ int64_t value;
+} AIMapper_MetadataType;
+
+typedef struct AIMapper_MetadataTypeDescription {
+ /**
+ * The `name` of the metadataType must be valid for the lifetime of the process
+ */
+ AIMapper_MetadataType metadataType;
+ /**
+ * description should contain a string representation of the MetadataType.
+ *
+ * For example: "MyExampleMetadataType is a 64-bit timestamp in nanoseconds
+ * that indicates when a buffer is decoded. It is set by the media HAL after
+ * a buffer is decoded. It is used by the display HAL for hardware
+ * synchronization".
+ *
+ * This field is required for any non-StandardMetadataTypes. For StandardMetadataTypes this
+ * field may be null. The lifetime of this pointer must be valid for the duration of the
+ * process (that is, a static const char*).
+ */
+ const char* _Nullable description;
+ /**
+ * isGettable represents if the MetadataType can be get.
+ */
+ bool isGettable;
+ /**
+ * isSettable represents if the MetadataType can be set.
+ */
+ bool isSettable;
+
+ /** Reserved for future use; must be zero-initialized currently */
+ uint8_t reserved[32];
+} AIMapper_MetadataTypeDescription;
+
+/**
+ * Callback that is passed to dumpBuffer.
+ *
+ * @param context The caller-provided void* that was passed to dumpBuffer.
+ * @param metadataType The type of the metadata passed to the callback
+ * @param value A pointer to the value of the metadata. The lifetime of this pointer is only
+ * valid for the duration of the call
+ * @param valueSize The size of the value buffer.
+ */
+typedef void (*AIMapper_DumpBufferCallback)(void* _Null_unspecified context,
+ AIMapper_MetadataType metadataType,
+ const void* _Nonnull value, size_t valueSize);
+
+/**
+ * Callback that is passed to dumpAllBuffers.
+ *
+ * Indicates that a buffer is about to be dumped. Will be followed by N calls to
+ * AIMapper_DumpBufferCallback for all the metadata for this buffer.
+ *
+ * @param context The caller-provided void* that was passed to dumpAllBuffers.
+ */
+typedef void (*AIMapper_BeginDumpBufferCallback)(void* _Null_unspecified context);
+
+/**
+ * Implementation of AIMAPPER_VERSION_5
+ * All functions must not be null & must provide a valid implementation.
+ */
+typedef struct AIMapperV5 {
+ /**
+ * Imports a raw buffer handle to create an imported buffer handle for use
+ * with the rest of the mapper or with other in-process libraries.
+ *
+ * A buffer handle is considered raw when it is cloned (e.g., with
+ * `native_handle_clone()`) from another buffer handle locally, or when it
+ * is received from another HAL server/client or another process. A raw
+ * buffer handle must not be used to access the underlying graphic
+ * buffer. It must be imported to create an imported handle first.
+ *
+ * This function must at least validate the raw handle before creating the
+ * imported handle. It must also support importing the same raw handle
+ * multiple times to create multiple imported handles. The imported handle
+ * must be considered valid everywhere in the process, including in
+ * another instance of the mapper.
+ *
+ * Because of passthrough HALs, a raw buffer handle received from a HAL
+ * may actually have been imported in the process. importBuffer() must treat
+ * such a handle as if it is raw and must not return `BAD_BUFFER`. The
+ * returned handle is independent from the input handle as usual, and
+ * freeBuffer() must be called on it when it is no longer needed.
+ *
+ * @param handle Raw buffer handle to import.
+ * @param outBufferHandle The resulting imported buffer handle.
+ * @return Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the raw handle is invalid.
+ * - `NO_RESOURCES` if the raw handle cannot be imported due to
+ * unavailability of resources.
+ */
+ AIMapper_Error (*_Nonnull importBuffer)(const native_handle_t* _Nonnull handle,
+ buffer_handle_t _Nullable* _Nonnull outBufferHandle);
+
+ /**
+ * Frees a buffer handle. Buffer handles returned by importBuffer() must be
+ * freed with this function when no longer needed.
+ *
+ * This function must free up all resources allocated by importBuffer() for
+ * the imported handle. For example, if the imported handle was created
+ * with `native_handle_create()`, this function must call
+ * `native_handle_close()` and `native_handle_delete()`.
+ *
+ * @param buffer Imported buffer handle.
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the buffer is invalid.
+ */
+ AIMapper_Error (*_Nonnull freeBuffer)(buffer_handle_t _Nonnull buffer);
+
+ /**
+ * Calculates the transport size of a buffer. An imported buffer handle is a
+ * raw buffer handle with the process-local runtime data appended. This
+ * function, for example, allows a caller to omit the process-local runtime
+ * data at the tail when serializing the imported buffer handle.
+ *
+ * Note that a client might or might not omit the process-local runtime data
+ * when sending an imported buffer handle. The mapper must support both
+ * cases on the receiving end.
+ *
+ * @param buffer Buffer to get the transport size from.
+ * @param outNumFds The number of file descriptors needed for transport.
+ * @param outNumInts The number of integers needed for transport.
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the buffer is invalid.
+ */
+ AIMapper_Error (*_Nonnull getTransportSize)(buffer_handle_t _Nonnull buffer,
+ uint32_t* _Nonnull outNumFds,
+ uint32_t* _Nonnull outNumInts);
+
+ /**
+ * Locks the given buffer for the specified CPU usage.
+ *
+ * Locking the same buffer simultaneously from multiple threads is
+ * permitted, but if any of the threads attempt to lock the buffer for
+ * writing, the behavior is undefined, except that it must not cause
+ * process termination or block the client indefinitely. Leaving the
+ * buffer content in an indeterminate state or returning an error are both
+ * acceptable.
+ *
+ * 1D buffers (width = size in bytes, height = 1, pixel_format = BLOB) must
+ * "lock in place". The buffers must be directly accessible via mapping.
+ *
+ * The client must not modify the content of the buffer outside of
+ * @p accessRegion, and the device need not guarantee that content outside
+ * of @p accessRegion is valid for reading. The result of reading or writing
+ * outside of @p accessRegion is undefined, except that it must not cause
+ * process termination.
+ *
+ * An accessRegion of all-zeros means the entire buffer. That is, it is
+ * equivalent to '(0,0)-(buffer width, buffer height)'.
+ *
+ * This function can lock both single-planar and multi-planar formats. The caller
+ * should use get() to get information about the buffer they are locking.
+ * get() can be used to get information about the planes, offsets, stride,
+ * etc.
+ *
+ * This function must also work on buffers with
+ * `AHARDWAREBUFFER_FORMAT_Y8Cb8Cr8_*` if supported by the device, as well
+ * as with any other formats requested by multimedia codecs when they are
+ * configured with a flexible-YUV-compatible color format.
+ *
+ * On success, @p data must be filled with a pointer to the locked buffer
+ * memory. This address will represent the top-left corner of the entire
+ * buffer, even if @p accessRegion does not begin at the top-left corner.
+ *
+ * The locked buffer must adhere to the format requested at allocation time
+ * in the BufferDescriptorInfo.
+ *
+ * @param buffer Buffer to lock.
+ * @param cpuUsage CPU usage flags to request. See BufferUsage.aidl for possible values.
+ * @param accessRegion Portion of the buffer that the client intends to
+ * access.
+ * @param acquireFence Handle containing a file descriptor referring to a
+ * sync fence object, which will be signaled when it is safe for the
+ * mapper to lock the buffer. @p acquireFence may be an empty fence (-1) if
+ * it is already safe to lock. Ownership is passed to the callee and it is the
+ * implementations responsibility to ensure it is closed even when an error
+ * occurs.
+ * @param outData CPU-accessible pointer to the buffer data.
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the buffer is invalid or is incompatible with this
+ * function.
+ * - `BAD_VALUE` if @p cpuUsage is 0, contains non-CPU usage flags, or
+ * is incompatible with the buffer. Also if the @p accessRegion is
+ * outside the bounds of the buffer or the accessRegion is invalid.
+ * - `NO_RESOURCES` if the buffer cannot be locked at this time. Note
+ * that locking may succeed at a later time.
+ * @return data CPU-accessible pointer to the buffer data.
+ */
+ AIMapper_Error (*_Nonnull lock)(buffer_handle_t _Nonnull buffer, uint64_t cpuUsage,
+ ARect accessRegion, int acquireFence,
+ void* _Nullable* _Nonnull outData);
+
+ /**
+ * Unlocks a buffer to indicate all CPU accesses to the buffer have
+ * completed.
+ *
+ * @param buffer Buffer to unlock.
+ * @param releaseFence Handle containing a file descriptor referring to a
+ * sync fence object. The sync fence object will be signaled when the
+ * mapper has completed any pending work. @p releaseFence may be an
+ * empty fence (-1).
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the buffer is invalid or not locked.
+ */
+ AIMapper_Error (*_Nonnull unlock)(buffer_handle_t _Nonnull buffer, int* _Nonnull releaseFence);
+
+ /**
+ * Flushes the contents of a locked buffer.
+ *
+ * This function flushes the CPUs caches for the range of all the buffer's
+ * planes and metadata. This should behave similarly to unlock() except the
+ * buffer should remain mapped to the CPU.
+ *
+ * The client is still responsible for calling unlock() when it is done
+ * with all CPU accesses to the buffer.
+ *
+ * If non-CPU blocks are simultaneously writing the buffer, the locked
+ * copy should still be flushed but what happens is undefined except that
+ * it should not cause any crashes.
+ *
+ * @param buffer Buffer to flush.
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the buffer is invalid or not locked.
+ */
+ AIMapper_Error (*_Nonnull flushLockedBuffer)(buffer_handle_t _Nonnull buffer);
+
+ /**
+ * Rereads the contents of a locked buffer.
+ *
+ * This should fetch the most recent copy of the locked buffer.
+ *
+ * It may reread locked copies of the buffer in other processes.
+ *
+ * The client is still responsible for calling unlock() when it is done
+ * with all CPU accesses to the buffer.
+ *
+ * @param buffer Buffer to reread.
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the buffer is invalid or not locked.
+ * - `NO_RESOURCES` if the buffer cannot be reread at this time. Note
+ * that rereading may succeed at a later time.
+ */
+ AIMapper_Error (*_Nonnull rereadLockedBuffer)(buffer_handle_t _Nonnull buffer);
+
+ /**
+ * Description for get(...), set(...) and getFromBufferDescriptorInfo(...)
+ *
+ * ------------ Overview -----------------------------------
+ * Gralloc 4 adds support for getting and setting buffer metadata on a buffer.
+ *
+ * To get buffer metadata, the client passes in a buffer handle and a token that
+ * represents the type of buffer metadata they would like to get. IMapper returns
+ * a byte stream that contains the buffer metadata. To set the buffer metadata, the
+ * client passes in a buffer handle and a token that represents the type of buffer
+ * metadata they would like to set and a byte stream that contains the buffer metadata
+ * they are setting.
+ *
+ * Buffer metadata is global for a buffer. When the metadata is set on the buffer
+ * in a process, the updated metadata should be available to all other processes.
+ * Please see "Storing and Propagating Metadata" below for more details.
+ *
+ * The getter and setter functions have been optimized for easy vendor extension.
+ * They do not require a formal extension to add support for getting and setting
+ * vendor defined buffer metadata. See "Buffer Metadata Token" and
+ * "Buffer Metadata Stream" below for more details.
+ *
+ * ------------ Storing and Propagating Metadata -----------
+ * Buffer metadata must be global. Any changes to the metadata must be propagated
+ * to all other processes immediately. Vendors may chose how they would like support
+ * this functionality.
+ *
+ * We recommend supporting this functionality by allocating an extra page of shared
+ * memory and storing it in the buffer's native_handle_t. The buffer metadata can
+ * be stored in the extra page of shared memory. Set operations are automatically
+ * propagated to all other processes.
+ *
+ * ------------ Buffer Metadata Synchronization ------------
+ * There are no explicit buffer metadata synchronization primitives. Many devices
+ * before gralloc 4 already support getting and setting of global buffer metadata
+ * with no explicit synchronization primitives. Adding synchronization primitives
+ * would just add unnecessary complexity.
+ *
+ * The general rule is if a process has permission to write to a buffer, they
+ * have permission to write to the buffer's writable metadata. If a process has permission
+ * to read from a buffer, they have permission to read the buffer's metadata.
+ *
+ * There is one exception to this rule. Fences CANNOT be used to protect a buffer's
+ * metadata. A process should finish writing to a buffer's metadata before
+ * sending the buffer to another process that will read or write to the buffer.
+ * This exception is needed because sometimes userspace needs to read the
+ * buffer's metadata before the buffer's contents are ready.
+ *
+ * As a simple example: an app renders to a buffer and then displays the buffer.
+ * In this example when the app renders to the buffer, both the buffer and its
+ * metadata need to be updated. The app's process queues up its work on the GPU
+ * and gets back an acquire fence. The app's process must update the buffer's
+ * metadata before enqueuing the buffer to SurfaceFlinger. The app process CANNOT
+ * update the buffer's metadata after enqueuing the buffer. When HardwareComposer
+ * receives the buffer, it is immediately safe to read the buffer's metadata
+ * and use it to program the display driver. To read the buffer's contents,
+ * display driver must still wait on the acquire fence.
+ *
+ * ------------ Buffer Metadata Token ----------------------
+ * In order to allow arbitrary vendor defined metadata, the token used to access
+ * metadata is defined defined as a struct that has a string representing
+ * the enum type and an int that represents the enum value. The string protects
+ * different enum values from colliding.
+ *
+ * The token struct (MetadataType) is defined as a C struct since it
+ * is passed into a C function. The standard buffer metadata types are NOT
+ * defined as a C enum but instead as an AIDL enum to allow for broader usage across
+ * other HALs and libraries. By putting the enum in the
+ * stable AIDL (hardware/interfaces/graphics/common/aidl/android/hardware/
+ * graphics/common/StandardMetadataType.aidl), vendors will be able to optionally
+ * choose to support future standard buffer metadata types without upgrading
+ * IMapper versions. For more information see the description of "struct MetadataType".
+ *
+ * ------------ Buffer Metadata Stream ---------------------
+ * The buffer metadata is get and set as a void* buffer. By getting
+ * and setting buffer metadata as a generic buffer, vendors can use the standard
+ * getters and setter functions defined here. Vendors do NOT need to add their own
+ * getters and setter functions for each new type of buffer metadata.
+ *
+ * Converting buffer metadata into a byte stream can be non-trivial. For the standard
+ * buffer metadata types defined in StandardMetadataType.aidl, there are also
+ * support functions that will encode the buffer metadata into a byte stream
+ * and decode the buffer metadata from a byte stream. We STRONGLY recommend using
+ * these support functions. The framework will use them when getting and setting
+ * metadata. The support functions are defined in
+ * frameworks/native/libs/gralloc/types/include/gralloctypes/Gralloc4.h.
+ */
+
+ /**
+ * Gets the buffer metadata for a given MetadataType.
+ *
+ * Buffer metadata can be changed after allocation so clients should avoid "caching"
+ * the buffer metadata. For example, if the video resolution changes and the buffers
+ * are not reallocated, several buffer metadata values may change without warning.
+ * Clients should not expect the values to be constant. They should requery them every
+ * frame. The only exception is buffer metadata that is determined at allocation
+ * time. For StandardMetadataType values, only BUFFER_ID, NAME, WIDTH,
+ * HEIGHT, LAYER_COUNT, PIXEL_FORMAT_REQUESTED and USAGE are safe to cache because
+ * they are determined at allocation time.
+ *
+ * @param buffer Buffer containing desired metadata
+ * @param metadataType MetadataType for the metadata value being queried
+ * @param destBuffer Pointer to a buffer in which to store the result of the get() call; if
+ * null, the computed output size or error must still be returned.
+ * @param destBufferSize How large the destBuffer buffer is. If destBuffer is null this must be
+ * 0.
+ * @return The number of bytes written to `destBuffer` or which would have been written
+ * if `destBufferSize` was large enough.
+ * A negative value indicates an error, which may be
+ * - `BAD_BUFFER` if the raw handle is invalid.
+ * - `UNSUPPORTED` when metadataType is unknown/unsupported.
+ * IMapper must support getting all StandardMetadataType.aidl values defined
+ * at the time the device first launches.
+ */
+ int32_t (*_Nonnull getMetadata)(buffer_handle_t _Nonnull buffer,
+ AIMapper_MetadataType metadataType, void* _Nullable destBuffer,
+ size_t destBufferSize);
+
+ /**
+ * Gets the buffer metadata for a StandardMetadataType.
+ *
+ * This is equivalent to `getMetadata` when passed an AIMapper_MetadataType with name
+ * set to "android.hardware.graphics.common.StandardMetadataType"
+ *
+ * Buffer metadata can be changed after allocation so clients should avoid "caching"
+ * the buffer metadata. For example, if the video resolution changes and the buffers
+ * are not reallocated, several buffer metadata values may change without warning.
+ * Clients should not expect the values to be constant. They should requery them every
+ * frame. The only exception is buffer metadata that is determined at allocation
+ * time. For StandardMetadataType values, only BUFFER_ID, NAME, WIDTH,
+ * HEIGHT, LAYER_COUNT, PIXEL_FORMAT_REQUESTED and USAGE are safe to cache because
+ * they are determined at allocation time.
+ *
+ * @param buffer Buffer containing desired metadata
+ * @param standardMetadataType StandardMetadataType for the metadata value being queried
+ * @param destBuffer Pointer to a buffer in which to store the result of the get() call; if
+ * null, the computed output size or error must still be returned.
+ * @param destBufferSize How large the destBuffer buffer is. If destBuffer is null this must be
+ * 0.
+ * @return The number of bytes written to `destBuffer` or which would have been written
+ * if `destBufferSize` was large enough.
+ * A negative value indicates an error, which may be
+ * - `BAD_BUFFER` if the raw handle is invalid.
+ * - `UNSUPPORTED` when metadataType is unknown/unsupported.
+ * IMapper must support getting all StandardMetadataType.aidl values defined
+ * at the time the device first launches.
+ */
+ int32_t (*_Nonnull getStandardMetadata)(buffer_handle_t _Nonnull buffer,
+ int64_t standardMetadataType,
+ void* _Nullable destBuffer, size_t destBufferSize);
+
+ /**
+ * Sets the global value for a given MetadataType.
+ *
+ * Metadata fields are not required to be settable. This function can
+ * return Error::UNSUPPORTED whenever it doesn't support setting a
+ * particular Metadata field.
+ *
+ * The framework will attempt to set the following StandardMetadataType
+ * values: DATASPACE, SMPTE2086, CTA861_3, and BLEND_MODE.
+ * We require everyone to support setting those fields. Framework will also attempt to set
+ * SMPTE2094_40 and SMPTE2094_10 if available, and it is required to support setting those
+ * if it is possible to get them. If a device's Composer implementation supports a field,
+ * it should be supported here. Over time these metadata fields will be moved out of
+ * Composer/BufferQueue/etc. and into the buffer's Metadata fields.
+ *
+ * @param buffer Buffer receiving desired metadata
+ * @param metadataType MetadataType for the metadata value being set
+ * @param metadata Pointer to a buffer of bytes representing the value associated with
+ * @param metadataSize The size of the metadata buffer
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the raw handle is invalid.
+ * - `BAD_VALUE` when the field is constant and can never be set (such as
+ * BUFFER_ID, NAME, WIDTH, HEIGHT, LAYER_COUNT, PIXEL_FORMAT_REQUESTED and
+ * USAGE)
+ * - `NO_RESOURCES` if the set cannot be fulfilled due to unavailability of
+ * resources.
+ * - `UNSUPPORTED` when metadataType is unknown/unsupported or setting
+ * it is unsupported. Unsupported should also be returned if the metadata
+ * is malformed.
+ */
+ AIMapper_Error (*_Nonnull setMetadata)(buffer_handle_t _Nonnull buffer,
+ AIMapper_MetadataType metadataType,
+ const void* _Nonnull metadata, size_t metadataSize);
+
+ /**
+ * Sets the global value for a given MetadataType.
+ *
+ * This is equivalent to `setMetadata` when passed an AIMapper_MetadataType with name
+ * set to "android.hardware.graphics.common.StandardMetadataType"
+ *
+ * Metadata fields are not required to be settable. This function can
+ * return Error::UNSUPPORTED whenever it doesn't support setting a
+ * particular Metadata field.
+ *
+ * The framework will attempt to set the following StandardMetadataType
+ * values: DATASPACE, SMPTE2086, CTA861_3, and BLEND_MODE.
+ * We require everyone to support setting those fields. Framework will also attempt to set
+ * SMPTE2094_40 and SMPTE2094_10 if available, and it is required to support setting those
+ * if it is possible to get them. If a device's Composer implementation supports a field,
+ * it should be supported here. Over time these metadata fields will be moved out of
+ * Composer/BufferQueue/etc. and into the buffer's Metadata fields.
+ *
+ * @param buffer Buffer receiving desired metadata
+ * @param standardMetadataType StandardMetadataType for the metadata value being set
+ * @param metadata Pointer to a buffer of bytes representing the value associated with
+ * @param metadataSize The size of the metadata buffer
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the raw handle is invalid.
+ * - `BAD_VALUE` when the field is constant and can never be set (such as
+ * BUFFER_ID, NAME, WIDTH, HEIGHT, LAYER_COUNT, PIXEL_FORMAT_REQUESTED and
+ * USAGE)
+ * - `NO_RESOURCES` if the set cannot be fulfilled due to unavailability of
+ * resources.
+ * - `UNSUPPORTED` when metadataType is unknown/unsupported or setting
+ * it is unsupported. Unsupported should also be returned if the metadata
+ * is malformed.
+ */
+ AIMapper_Error (*_Nonnull setStandardMetadata)(buffer_handle_t _Nonnull buffer,
+ int64_t standardMetadataType,
+ const void* _Nonnull metadata,
+ size_t metadataSize);
+
+ /**
+ * Lists all the MetadataTypes supported by IMapper as well as a description
+ * of each supported MetadataType. For StandardMetadataTypes, the description
+ * string can be left empty.
+ *
+ * This list is expected to be static & thus the returned array must be valid for the
+ * lifetime of the process.
+ *
+ * @param outDescriptionList The list of descriptions
+ * @param outNumberOfDescriptions How many descriptions are in `outDescriptionList`
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `UNSUPPORTED` if there's any error
+ */
+ AIMapper_Error (*_Nonnull listSupportedMetadataTypes)(
+ const AIMapper_MetadataTypeDescription* _Nullable* _Nonnull outDescriptionList,
+ size_t* _Nonnull outNumberOfDescriptions);
+
+ /**
+ * Dumps a buffer's metadata.
+ *
+ * @param buffer The buffer to dump the metadata for
+ * @param dumpBufferCallback Callback that will be invoked for each of the metadata fields
+ * @param context A caller-provided context to be passed to the dumpBufferCallback
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the raw handle is invalid.
+ * - `NO_RESOURCES` if the get cannot be fulfilled due to unavailability of
+ * resources.
+ */
+ AIMapper_Error (*_Nonnull dumpBuffer)(buffer_handle_t _Nonnull buffer,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
+ void* _Null_unspecified context);
+
+ /**
+ * Dump the metadata for all imported buffers in the current process
+ *
+ * The HAL implementation should invoke beginDumpCallback before dumping a buffer's metadata,
+ * followed by N calls to dumpBufferCallback for that buffer's metadata fields. The call
+ * sequence should follow this pseudocode:
+ *
+ * for (auto buffer : gListOfImportedBuffers) {
+ * beginDumpCallback(context);
+ * for (auto metadata : buffer->allMetadata()) {
+ * dumpBufferCallback(context, metadata...);
+ * }
+ * }
+ *
+ * @param beginDumpCallback Signals that a buffer is about to be dumped
+ * @param dumpBufferCallback Callback that will be invoked for each of the metadata fields
+ * @param context A caller-provided context to be passed to beginDumpCallback and
+ * dumpBufferCallback
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the raw handle is invalid.
+ * - `NO_RESOURCES` if the get cannot be fulfilled due to unavailability of
+ * resources.
+ */
+ AIMapper_Error (*_Nonnull dumpAllBuffers)(
+ AIMapper_BeginDumpBufferCallback _Nonnull beginDumpCallback,
+ AIMapper_DumpBufferCallback _Nonnull dumpBufferCallback,
+ void* _Null_unspecified context);
+
+ /**
+ * Returns the region of shared memory associated with the buffer that is
+ * reserved for client use.
+ *
+ * The shared memory may be allocated from any shared memory allocator.
+ * The shared memory must be CPU-accessible and virtually contiguous. The
+ * starting address must be word-aligned.
+ *
+ * This function may only be called after importBuffer() has been called by the
+ * client. The reserved region must remain accessible until freeBuffer() has
+ * been called. After freeBuffer() has been called, the client must not access
+ * the reserved region.
+ *
+ * This reserved memory may be used in future versions of Android to
+ * help clients implement backwards compatible features without requiring
+ * IAllocator/IMapper updates.
+ *
+ * @param buffer Imported buffer handle.
+ * @param outReservedRegion CPU-accessible pointer to the reserved region
+ * @param outReservedSize the size of the reservedRegion that was requested
+ * in the BufferDescriptorInfo.
+ * @return error Error status of the call, which may be
+ * - `NONE` upon success.
+ * - `BAD_BUFFER` if the buffer is invalid.
+ */
+ AIMapper_Error (*_Nonnull getReservedRegion)(buffer_handle_t _Nonnull buffer,
+ void* _Nullable* _Nonnull outReservedRegion,
+ uint64_t* _Nonnull outReservedSize);
+
+} AIMapperV5;
+
+/**
+ * Return value for AIMapper_loadIMapper
+ *
+ * Note: This struct's size is not fixed and callers must never store it by-value as a result.
+ * Only fields up to those covered by `version` are allowed to be accessed.
+ */
+typedef struct AIMapper {
+ alignas(alignof(max_align_t)) AIMapper_Version version;
+ AIMapperV5 v5;
+} AIMapper;
+
+/**
+ * Loads the vendor-provided implementation of AIMapper
+ * @return Error status of the call.
+ * - `NONE` upon success
+ * - `UNSUPPORTED` if no implementation is available
+ */
+AIMapper_Error AIMapper_loadIMapper(AIMapper* _Nullable* _Nonnull outImplementation);
+
+__END_DECLS
\ No newline at end of file
diff --git a/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
new file mode 100644
index 0000000..326346c
--- /dev/null
+++ b/graphics/mapper/stable-c/vts/VtsHalGraphicsMapperStableC_TargetTest.cpp
@@ -0,0 +1,1763 @@
+/*
+ * 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "VtsHalGraphicsMapperStableC_TargetTest"
+
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/graphics/allocator/AllocationError.h>
+#include <aidl/android/hardware/graphics/allocator/AllocationResult.h>
+#include <aidl/android/hardware/graphics/allocator/IAllocator.h>
+#include <aidl/android/hardware/graphics/common/BufferUsage.h>
+#include <aidl/android/hardware/graphics/common/PixelFormat.h>
+#include <aidlcommonsupport/NativeHandle.h>
+#include <android/binder_enums.h>
+#include <android/binder_manager.h>
+#include <android/dlext.h>
+#include <android/hardware/graphics/mapper/IMapper.h>
+#include <android/hardware/graphics/mapper/utils/IMapperMetadataTypes.h>
+#include <gralloctypes/Gralloc4.h>
+#include <hidl/GtestPrinter.h>
+#include <system/graphics.h>
+
+#include <dlfcn.h>
+#include <drm/drm_fourcc.h>
+#include <gtest/gtest.h>
+#include <vndksupport/linker.h>
+#include <initializer_list>
+#include <optional>
+#include <string>
+#include <tuple>
+#include <vector>
+
+using namespace aidl::android::hardware::graphics::allocator;
+using namespace aidl::android::hardware::graphics::common;
+using namespace android;
+using namespace android::hardware;
+using namespace ::android::hardware::graphics::mapper;
+
+typedef AIMapper_Error (*AIMapper_loadIMapperFn)(AIMapper* _Nullable* _Nonnull outImplementation);
+
+inline constexpr BufferUsage operator|(BufferUsage lhs, BufferUsage rhs) {
+ using T = std::underlying_type_t<BufferUsage>;
+ return static_cast<BufferUsage>(static_cast<T>(lhs) | static_cast<T>(rhs));
+}
+
+inline BufferUsage& operator|=(BufferUsage& lhs, BufferUsage rhs) {
+ lhs = lhs | rhs;
+ return lhs;
+}
+
+struct YCbCr {
+ android_ycbcr yCbCr;
+ int64_t horizontalSubSampling;
+ int64_t verticalSubSampling;
+};
+
+constexpr const char* STANDARD_METADATA_NAME =
+ "android.hardware.graphics.common.StandardMetadataType";
+
+static bool isStandardMetadata(AIMapper_MetadataType metadataType) {
+ return strcmp(STANDARD_METADATA_NAME, metadataType.name) == 0;
+}
+
+static std::string toString(const std::vector<StandardMetadataType> types) {
+ std::stringstream buf;
+ buf << "[";
+ for (auto type : types) {
+ buf << toString(type) << ", ";
+ }
+ buf.seekp(-2, buf.cur);
+ buf << "]";
+ return buf.str();
+}
+
+class BufferHandle {
+ AIMapper* mIMapper;
+ buffer_handle_t mHandle = nullptr;
+
+ public:
+ explicit BufferHandle(AIMapper* mapper, native_handle_t* rawHandle) : mIMapper(mapper) {
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mIMapper->v5.importBuffer(rawHandle, &mHandle));
+ }
+
+ explicit BufferHandle(BufferHandle&& other) { *this = std::move(other); }
+
+ BufferHandle& operator=(BufferHandle&& other) noexcept {
+ reset();
+ mIMapper = other.mIMapper;
+ mHandle = other.mHandle;
+ other.mHandle = nullptr;
+ return *this;
+ }
+
+ ~BufferHandle() { reset(); }
+
+ constexpr explicit operator bool() const noexcept { return mHandle != nullptr; }
+
+ buffer_handle_t operator*() const noexcept { return mHandle; }
+
+ void reset() {
+ if (mHandle != nullptr) {
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mIMapper->v5.freeBuffer(mHandle));
+ mHandle = nullptr;
+ }
+ }
+};
+
+class BufferAllocation {
+ AIMapper* mIMapper;
+ native_handle_t* mRawHandle;
+ uint32_t mStride;
+ const BufferDescriptorInfo mInfo;
+
+ public:
+ BufferAllocation(const BufferAllocation&) = delete;
+ void operator=(const BufferAllocation&) = delete;
+
+ BufferAllocation(AIMapper* mapper, native_handle_t* handle, uint32_t stride,
+ const BufferDescriptorInfo& info)
+ : mIMapper(mapper), mRawHandle(handle), mStride(stride), mInfo(info) {}
+
+ ~BufferAllocation() {
+ if (mRawHandle == nullptr) return;
+
+ native_handle_close(mRawHandle);
+ native_handle_delete(mRawHandle);
+ }
+
+ uint32_t stride() const { return mStride; }
+ const BufferDescriptorInfo& info() const { return mInfo; }
+
+ BufferHandle import() { return BufferHandle{mIMapper, mRawHandle}; }
+
+ const native_handle_t* rawHandle() const { return mRawHandle; }
+};
+
+class GraphicsTestsBase {
+ private:
+ friend class BufferAllocation;
+ int32_t mIAllocatorVersion = 1;
+ std::shared_ptr<IAllocator> mAllocator;
+ AIMapper* mIMapper = nullptr;
+ AIMapper_loadIMapperFn mIMapperLoader;
+
+ protected:
+ void Initialize(std::shared_ptr<IAllocator> allocator) {
+ mAllocator = allocator;
+ ASSERT_NE(nullptr, mAllocator.get()) << "failed to get allocator service";
+ ASSERT_TRUE(mAllocator->getInterfaceVersion(&mIAllocatorVersion).isOk());
+ ASSERT_GE(mIAllocatorVersion, 2);
+ std::string mapperSuffix;
+ auto status = mAllocator->getIMapperLibrarySuffix(&mapperSuffix);
+ ASSERT_TRUE(status.isOk()) << "Failed to get IMapper library suffix";
+ std::string lib_name = "mapper." + mapperSuffix + ".so";
+ void* so = android_load_sphal_library(lib_name.c_str(), RTLD_LOCAL | RTLD_NOW);
+ ASSERT_NE(nullptr, so) << "Failed to load " << lib_name;
+ mIMapperLoader = (AIMapper_loadIMapperFn)dlsym(so, "AIMapper_loadIMapper");
+ ASSERT_NE(nullptr, mIMapperLoader) << "AIMapper_locaIMapper missing from " << lib_name;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mIMapperLoader(&mIMapper));
+ ASSERT_NE(mIMapper, nullptr);
+ }
+
+ public:
+ AIMapper_loadIMapperFn getIMapperLoader() const { return mIMapperLoader; }
+
+ std::unique_ptr<BufferAllocation> allocate(const BufferDescriptorInfo& descriptorInfo) {
+ AllocationResult result;
+ ::ndk::ScopedAStatus status = mAllocator->allocate2(descriptorInfo, 1, &result);
+ if (!status.isOk()) {
+ status_t error = status.getExceptionCode();
+ if (error == EX_SERVICE_SPECIFIC) {
+ error = status.getServiceSpecificError();
+ EXPECT_NE(OK, error) << "Failed to set error properly";
+ } else {
+ EXPECT_EQ(OK, error) << "Allocation transport failure";
+ }
+ return nullptr;
+ } else {
+ return std::make_unique<BufferAllocation>(mIMapper, dupFromAidl(result.buffers[0]),
+ result.stride, descriptorInfo);
+ }
+ }
+
+ std::unique_ptr<BufferAllocation> allocateGeneric() {
+ return allocate({
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ });
+ }
+
+ bool isSupported(const BufferDescriptorInfo& descriptorInfo) {
+ bool ret = false;
+ EXPECT_TRUE(mAllocator->isSupported(descriptorInfo, &ret).isOk());
+ return ret;
+ }
+
+ AIMapper* mapper() const { return mIMapper; }
+
+ template <StandardMetadataType T>
+ auto getStandardMetadata(buffer_handle_t bufferHandle)
+ -> decltype(StandardMetadata<T>::value::decode(nullptr, 0)) {
+ using Value = typename StandardMetadata<T>::value;
+ std::vector<uint8_t> buffer;
+ // Initial guess
+ buffer.resize(512);
+ int32_t sizeRequired = mapper()->v5.getStandardMetadata(
+ bufferHandle, static_cast<int64_t>(T), buffer.data(), buffer.size());
+ if (sizeRequired < 0) {
+ EXPECT_EQ(-AIMAPPER_ERROR_UNSUPPORTED, sizeRequired)
+ << "Received something other than UNSUPPORTED from valid getStandardMetadata "
+ "call";
+ return std::nullopt;
+ }
+ if (sizeRequired > buffer.size()) {
+ buffer.resize(sizeRequired);
+ sizeRequired = mapper()->v5.getStandardMetadata(bufferHandle, static_cast<int64_t>(T),
+ buffer.data(), buffer.size());
+ }
+ if (sizeRequired < 0 || sizeRequired >= buffer.size()) {
+ ADD_FAILURE() << "getStandardMetadata failed, received " << sizeRequired
+ << " with buffer size " << buffer.size();
+ // Generate a fail type
+ return std::nullopt;
+ }
+ return Value::decode(buffer.data(), sizeRequired);
+ }
+
+ template <StandardMetadataType T>
+ AIMapper_Error setStandardMetadata(buffer_handle_t bufferHandle,
+ const typename StandardMetadata<T>::value_type& value) {
+ using Value = typename StandardMetadata<T>::value;
+ int32_t sizeRequired = Value::encode(value, nullptr, 0);
+ if (sizeRequired < 0) {
+ EXPECT_GE(sizeRequired, 0) << "Failed to calculate required size";
+ return static_cast<AIMapper_Error>(-sizeRequired);
+ }
+ std::vector<uint8_t> buffer;
+ buffer.resize(sizeRequired);
+ sizeRequired = Value::encode(value, buffer.data(), buffer.size());
+ if (sizeRequired < 0 || sizeRequired > buffer.size()) {
+ ADD_FAILURE() << "Failed to encode with calculated size " << sizeRequired
+ << "; buffer size" << buffer.size();
+ return static_cast<AIMapper_Error>(-sizeRequired);
+ }
+ return mapper()->v5.setStandardMetadata(bufferHandle, static_cast<int64_t>(T),
+ buffer.data(), sizeRequired);
+ }
+
+ void verifyRGBA8888PlaneLayouts(const std::vector<PlaneLayout>& planeLayouts) {
+ ASSERT_EQ(1, planeLayouts.size());
+
+ const auto& planeLayout = planeLayouts.front();
+
+ ASSERT_EQ(4, planeLayout.components.size());
+
+ int64_t offsetInBitsR = -1;
+ int64_t offsetInBitsG = -1;
+ int64_t offsetInBitsB = -1;
+ int64_t offsetInBitsA = -1;
+
+ for (const auto& component : planeLayout.components) {
+ if (!gralloc4::isStandardPlaneLayoutComponentType(component.type)) {
+ continue;
+ }
+ EXPECT_EQ(8, component.sizeInBits);
+ if (component.type.value == gralloc4::PlaneLayoutComponentType_R.value) {
+ offsetInBitsR = component.offsetInBits;
+ }
+ if (component.type.value == gralloc4::PlaneLayoutComponentType_G.value) {
+ offsetInBitsG = component.offsetInBits;
+ }
+ if (component.type.value == gralloc4::PlaneLayoutComponentType_B.value) {
+ offsetInBitsB = component.offsetInBits;
+ }
+ if (component.type.value == gralloc4::PlaneLayoutComponentType_A.value) {
+ offsetInBitsA = component.offsetInBits;
+ }
+ }
+
+ EXPECT_EQ(0, offsetInBitsR);
+ EXPECT_EQ(8, offsetInBitsG);
+ EXPECT_EQ(16, offsetInBitsB);
+ EXPECT_EQ(24, offsetInBitsA);
+
+ EXPECT_EQ(0, planeLayout.offsetInBytes);
+ EXPECT_EQ(32, planeLayout.sampleIncrementInBits);
+ // Skip testing stride because any stride is valid
+ EXPECT_LE(planeLayout.widthInSamples * planeLayout.heightInSamples * 4,
+ planeLayout.totalSizeInBytes);
+ EXPECT_EQ(1, planeLayout.horizontalSubsampling);
+ EXPECT_EQ(1, planeLayout.verticalSubsampling);
+ }
+
+ void fillRGBA8888(uint8_t* data, uint32_t height, size_t strideInBytes, size_t widthInBytes) {
+ for (uint32_t y = 0; y < height; y++) {
+ memset(data, y, widthInBytes);
+ data += strideInBytes;
+ }
+ }
+
+ void verifyRGBA8888(const buffer_handle_t bufferHandle, const uint8_t* data, uint32_t height,
+ size_t strideInBytes, size_t widthInBytes) {
+ auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
+ ASSERT_TRUE(decodeResult.has_value());
+ const auto& planeLayouts = *decodeResult;
+ ASSERT_TRUE(planeLayouts.size() > 0);
+
+ verifyRGBA8888PlaneLayouts(planeLayouts);
+
+ for (uint32_t y = 0; y < height; y++) {
+ for (size_t i = 0; i < widthInBytes; i++) {
+ EXPECT_EQ(static_cast<uint8_t>(y), data[i]);
+ }
+ data += strideInBytes;
+ }
+ }
+
+ void traverseYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
+ int64_t hSubsampling, int64_t vSubsampling,
+ std::function<void(uint8_t*, uint8_t)> traverseFuncion) {
+ auto yData = static_cast<uint8_t*>(yCbCr.y);
+ auto cbData = static_cast<uint8_t*>(yCbCr.cb);
+ auto crData = static_cast<uint8_t*>(yCbCr.cr);
+ auto yStride = yCbCr.ystride;
+ auto cStride = yCbCr.cstride;
+ auto chromaStep = yCbCr.chroma_step;
+
+ for (uint32_t y = 0; y < height; y++) {
+ for (uint32_t x = 0; x < width; x++) {
+ auto val = static_cast<uint8_t>(height * y + x);
+
+ traverseFuncion(yData + yStride * y + x, val);
+
+ if (y % vSubsampling == 0 && x % hSubsampling == 0) {
+ uint32_t subSampleX = x / hSubsampling;
+ uint32_t subSampleY = y / vSubsampling;
+ const auto subSampleOffset = cStride * subSampleY + chromaStep * subSampleX;
+ const auto subSampleVal =
+ static_cast<uint8_t>(height * subSampleY + subSampleX);
+
+ traverseFuncion(cbData + subSampleOffset, subSampleVal);
+ traverseFuncion(crData + subSampleOffset, subSampleVal + 1);
+ }
+ }
+ }
+ }
+
+ void fillYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
+ int64_t hSubsampling, int64_t vSubsampling) {
+ traverseYCbCrData(yCbCr, width, height, hSubsampling, vSubsampling,
+ [](auto address, auto fillingData) { *address = fillingData; });
+ }
+
+ void verifyYCbCrData(const android_ycbcr& yCbCr, int32_t width, int32_t height,
+ int64_t hSubsampling, int64_t vSubsampling) {
+ traverseYCbCrData(
+ yCbCr, width, height, hSubsampling, vSubsampling,
+ [](auto address, auto expectedData) { EXPECT_EQ(*address, expectedData); });
+ }
+
+ constexpr uint64_t bitsToBytes(int64_t bits) { return bits / 8; }
+ constexpr uint64_t bytesToBits(int64_t bytes) { return bytes * 8; }
+
+ void getAndroidYCbCr(buffer_handle_t bufferHandle, uint8_t* data, android_ycbcr* outYCbCr,
+ int64_t* hSubsampling, int64_t* vSubsampling) {
+ auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
+ ASSERT_TRUE(decodeResult.has_value());
+ const auto& planeLayouts = *decodeResult;
+ ASSERT_TRUE(planeLayouts.size() > 0);
+
+ outYCbCr->y = nullptr;
+ outYCbCr->cb = nullptr;
+ outYCbCr->cr = nullptr;
+ outYCbCr->ystride = 0;
+ outYCbCr->cstride = 0;
+ outYCbCr->chroma_step = 0;
+
+ for (const auto& planeLayout : planeLayouts) {
+ for (const auto& planeLayoutComponent : planeLayout.components) {
+ if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
+ continue;
+ }
+ ASSERT_EQ(0, planeLayoutComponent.offsetInBits % 8);
+
+ uint8_t* tmpData = data + planeLayout.offsetInBytes +
+ bitsToBytes(planeLayoutComponent.offsetInBits);
+ uint64_t sampleIncrementInBytes;
+
+ auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
+ switch (type) {
+ case PlaneLayoutComponentType::Y:
+ ASSERT_EQ(nullptr, outYCbCr->y);
+ ASSERT_EQ(8, planeLayoutComponent.sizeInBits);
+ ASSERT_EQ(8, planeLayout.sampleIncrementInBits);
+ outYCbCr->y = tmpData;
+ outYCbCr->ystride = planeLayout.strideInBytes;
+ break;
+
+ case PlaneLayoutComponentType::CB:
+ case PlaneLayoutComponentType::CR:
+ ASSERT_EQ(0, planeLayout.sampleIncrementInBits % 8);
+
+ sampleIncrementInBytes = planeLayout.sampleIncrementInBits / 8;
+ ASSERT_TRUE(sampleIncrementInBytes == 1 || sampleIncrementInBytes == 2);
+
+ if (outYCbCr->cstride == 0 && outYCbCr->chroma_step == 0) {
+ outYCbCr->cstride = planeLayout.strideInBytes;
+ outYCbCr->chroma_step = sampleIncrementInBytes;
+ } else {
+ ASSERT_EQ(outYCbCr->cstride, planeLayout.strideInBytes);
+ ASSERT_EQ(outYCbCr->chroma_step, sampleIncrementInBytes);
+ }
+
+ if (*hSubsampling == 0 && *vSubsampling == 0) {
+ *hSubsampling = planeLayout.horizontalSubsampling;
+ *vSubsampling = planeLayout.verticalSubsampling;
+ } else {
+ ASSERT_EQ(*hSubsampling, planeLayout.horizontalSubsampling);
+ ASSERT_EQ(*vSubsampling, planeLayout.verticalSubsampling);
+ }
+
+ if (type == PlaneLayoutComponentType::CB) {
+ ASSERT_EQ(nullptr, outYCbCr->cb);
+ outYCbCr->cb = tmpData;
+ } else {
+ ASSERT_EQ(nullptr, outYCbCr->cr);
+ outYCbCr->cr = tmpData;
+ }
+ break;
+ default:
+ break;
+ };
+ }
+ }
+
+ ASSERT_NE(nullptr, outYCbCr->y);
+ ASSERT_NE(nullptr, outYCbCr->cb);
+ ASSERT_NE(nullptr, outYCbCr->cr);
+ }
+
+ YCbCr getAndroidYCbCr_P010(const native_handle_t* bufferHandle, uint8_t* data) {
+ YCbCr yCbCr_P010;
+ auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(bufferHandle);
+ if (!decodeResult.has_value()) {
+ ADD_FAILURE() << "failed to get plane layout";
+ return YCbCr{};
+ }
+ const auto& planeLayouts = *decodeResult;
+ EXPECT_EQ(2, planeLayouts.size());
+ EXPECT_EQ(1, planeLayouts[0].components.size());
+ EXPECT_EQ(2, planeLayouts[1].components.size());
+
+ yCbCr_P010.yCbCr.y = nullptr;
+ yCbCr_P010.yCbCr.cb = nullptr;
+ yCbCr_P010.yCbCr.cr = nullptr;
+ yCbCr_P010.yCbCr.ystride = 0;
+ yCbCr_P010.yCbCr.cstride = 0;
+ yCbCr_P010.yCbCr.chroma_step = 0;
+ int64_t cb_offset = 0;
+ int64_t cr_offset = 0;
+
+ for (const auto& planeLayout : planeLayouts) {
+ for (const auto& planeLayoutComponent : planeLayout.components) {
+ if (!gralloc4::isStandardPlaneLayoutComponentType(planeLayoutComponent.type)) {
+ continue;
+ }
+
+ uint8_t* tmpData = data + planeLayout.offsetInBytes +
+ bitsToBytes(planeLayoutComponent.offsetInBits);
+ uint64_t sampleIncrementInBytes = 0;
+ auto type = static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value);
+ switch (type) {
+ case PlaneLayoutComponentType::Y:
+ // For specs refer:
+ // https://docs.microsoft.com/en-us/windows/win32/medfound/10-bit-and-16-bit-yuv-video-formats
+ EXPECT_EQ(6, planeLayoutComponent.offsetInBits);
+ EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.y);
+ EXPECT_EQ(10, planeLayoutComponent.sizeInBits);
+ EXPECT_EQ(16, planeLayout.sampleIncrementInBits);
+
+ yCbCr_P010.yCbCr.y = tmpData;
+ yCbCr_P010.yCbCr.ystride = planeLayout.strideInBytes;
+ break;
+
+ case PlaneLayoutComponentType::CB:
+ case PlaneLayoutComponentType::CR:
+ sampleIncrementInBytes = bitsToBytes(planeLayout.sampleIncrementInBits);
+ EXPECT_EQ(4, sampleIncrementInBytes);
+
+ if (yCbCr_P010.yCbCr.cstride == 0 && yCbCr_P010.yCbCr.chroma_step == 0) {
+ yCbCr_P010.yCbCr.cstride = planeLayout.strideInBytes;
+ yCbCr_P010.yCbCr.chroma_step = sampleIncrementInBytes;
+ } else {
+ EXPECT_EQ(yCbCr_P010.yCbCr.cstride, planeLayout.strideInBytes);
+ EXPECT_EQ(yCbCr_P010.yCbCr.chroma_step, sampleIncrementInBytes);
+ }
+
+ if (yCbCr_P010.horizontalSubSampling == 0 &&
+ yCbCr_P010.verticalSubSampling == 0) {
+ yCbCr_P010.horizontalSubSampling = planeLayout.horizontalSubsampling;
+ yCbCr_P010.verticalSubSampling = planeLayout.verticalSubsampling;
+ } else {
+ EXPECT_EQ(yCbCr_P010.horizontalSubSampling,
+ planeLayout.horizontalSubsampling);
+ EXPECT_EQ(yCbCr_P010.verticalSubSampling,
+ planeLayout.verticalSubsampling);
+ }
+
+ if (type == PlaneLayoutComponentType::CB) {
+ EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cb);
+ yCbCr_P010.yCbCr.cb = tmpData;
+ cb_offset = planeLayoutComponent.offsetInBits;
+ } else {
+ EXPECT_EQ(nullptr, yCbCr_P010.yCbCr.cr);
+ yCbCr_P010.yCbCr.cr = tmpData;
+ cr_offset = planeLayoutComponent.offsetInBits;
+ }
+ break;
+ default:
+ break;
+ };
+ }
+ }
+
+ EXPECT_EQ(cb_offset + bytesToBits(2), cr_offset);
+ EXPECT_NE(nullptr, yCbCr_P010.yCbCr.y);
+ EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cb);
+ EXPECT_NE(nullptr, yCbCr_P010.yCbCr.cr);
+ return yCbCr_P010;
+ }
+};
+
+class GraphicsMapperStableCTests
+ : public GraphicsTestsBase,
+ public ::testing::TestWithParam<std::tuple<std::string, std::shared_ptr<IAllocator>>> {
+ public:
+ void SetUp() override { Initialize(std::get<1>(GetParam())); }
+
+ void TearDown() override {}
+};
+
+TEST_P(GraphicsMapperStableCTests, AllV5CallbacksDefined) {
+ ASSERT_GE(mapper()->version, AIMAPPER_VERSION_5);
+
+ EXPECT_TRUE(mapper()->v5.importBuffer);
+ EXPECT_TRUE(mapper()->v5.freeBuffer);
+ EXPECT_TRUE(mapper()->v5.getTransportSize);
+ EXPECT_TRUE(mapper()->v5.lock);
+ EXPECT_TRUE(mapper()->v5.unlock);
+ EXPECT_TRUE(mapper()->v5.flushLockedBuffer);
+ EXPECT_TRUE(mapper()->v5.rereadLockedBuffer);
+ EXPECT_TRUE(mapper()->v5.getMetadata);
+ EXPECT_TRUE(mapper()->v5.getStandardMetadata);
+ EXPECT_TRUE(mapper()->v5.setMetadata);
+ EXPECT_TRUE(mapper()->v5.setStandardMetadata);
+ EXPECT_TRUE(mapper()->v5.listSupportedMetadataTypes);
+ EXPECT_TRUE(mapper()->v5.dumpBuffer);
+ EXPECT_TRUE(mapper()->v5.getReservedRegion);
+}
+
+TEST_P(GraphicsMapperStableCTests, DualLoadIsIdentical) {
+ ASSERT_GE(mapper()->version, AIMAPPER_VERSION_5);
+ AIMapper* secondMapper;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, getIMapperLoader()(&secondMapper));
+
+ EXPECT_EQ(secondMapper->v5.importBuffer, mapper()->v5.importBuffer);
+ EXPECT_EQ(secondMapper->v5.freeBuffer, mapper()->v5.freeBuffer);
+ EXPECT_EQ(secondMapper->v5.getTransportSize, mapper()->v5.getTransportSize);
+ EXPECT_EQ(secondMapper->v5.lock, mapper()->v5.lock);
+ EXPECT_EQ(secondMapper->v5.unlock, mapper()->v5.unlock);
+ EXPECT_EQ(secondMapper->v5.flushLockedBuffer, mapper()->v5.flushLockedBuffer);
+ EXPECT_EQ(secondMapper->v5.rereadLockedBuffer, mapper()->v5.rereadLockedBuffer);
+ EXPECT_EQ(secondMapper->v5.getMetadata, mapper()->v5.getMetadata);
+ EXPECT_EQ(secondMapper->v5.getStandardMetadata, mapper()->v5.getStandardMetadata);
+ EXPECT_EQ(secondMapper->v5.setMetadata, mapper()->v5.setMetadata);
+ EXPECT_EQ(secondMapper->v5.setStandardMetadata, mapper()->v5.setStandardMetadata);
+ EXPECT_EQ(secondMapper->v5.listSupportedMetadataTypes, mapper()->v5.listSupportedMetadataTypes);
+ EXPECT_EQ(secondMapper->v5.dumpBuffer, mapper()->v5.dumpBuffer);
+ EXPECT_EQ(secondMapper->v5.getReservedRegion, mapper()->v5.getReservedRegion);
+}
+
+TEST_P(GraphicsMapperStableCTests, CanAllocate) {
+ auto buffer = allocate({
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ });
+ ASSERT_NE(nullptr, buffer.get());
+ EXPECT_GE(buffer->stride(), 64);
+}
+
+TEST_P(GraphicsMapperStableCTests, ImportFreeBuffer) {
+ auto buffer = allocate({
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ });
+ ASSERT_NE(nullptr, buffer.get());
+ EXPECT_GE(buffer->stride(), 64);
+
+ {
+ auto import1 = buffer->import();
+ auto import2 = buffer->import();
+ EXPECT_TRUE(import1);
+ EXPECT_TRUE(import2);
+ EXPECT_NE(*import1, *import2);
+ }
+}
+
+/**
+ * Test IMapper::importBuffer and IMapper::freeBuffer cross mapper instances.
+ */
+TEST_P(GraphicsMapperStableCTests, ImportFreeBufferSingleton) {
+ auto buffer = allocate({
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ });
+ ASSERT_NE(nullptr, buffer.get());
+ EXPECT_GE(buffer->stride(), 64);
+
+ buffer_handle_t bufferHandle = nullptr;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.importBuffer(buffer->rawHandle(), &bufferHandle));
+ ASSERT_NE(nullptr, bufferHandle);
+
+ AIMapper* secondMapper;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, getIMapperLoader()(&secondMapper));
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, secondMapper->v5.freeBuffer(bufferHandle));
+}
+
+/**
+ * Test IMapper::importBuffer with invalid buffers.
+ */
+TEST_P(GraphicsMapperStableCTests, ImportBufferNegative) {
+ native_handle_t* invalidHandle = nullptr;
+ buffer_handle_t bufferHandle = nullptr;
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.importBuffer(invalidHandle, &bufferHandle))
+ << "importBuffer with nullptr did not fail with BAD_BUFFER";
+
+ invalidHandle = native_handle_create(0, 0);
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.importBuffer(invalidHandle, &bufferHandle))
+ << "importBuffer with invalid handle did not fail with BAD_BUFFER";
+ native_handle_delete(invalidHandle);
+}
+
+/**
+ * Test IMapper::freeBuffer with invalid buffers.
+ */
+TEST_P(GraphicsMapperStableCTests, FreeBufferNegative) {
+ native_handle_t* bufferHandle = nullptr;
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.freeBuffer(bufferHandle))
+ << "freeBuffer with nullptr did not fail with BAD_BUFFER";
+
+ bufferHandle = native_handle_create(0, 0);
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.freeBuffer(bufferHandle))
+ << "freeBuffer with invalid handle did not fail with BAD_BUFFER";
+ native_handle_delete(bufferHandle);
+
+ auto buffer = allocateGeneric();
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.freeBuffer(buffer->rawHandle()))
+ << "freeBuffer with un-imported handle did not fail with BAD_BUFFER";
+}
+
+/**
+ * Test IMapper::lock and IMapper::unlock.
+ */
+TEST_P(GraphicsMapperStableCTests, LockUnlockBasic) {
+ constexpr auto usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN;
+ auto buffer = allocate({
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = usage,
+ .reservedSize = 0,
+ });
+ ASSERT_NE(nullptr, buffer.get());
+
+ // lock buffer for writing
+ const auto& info = buffer->info();
+ const auto stride = buffer->stride();
+ const ARect region{0, 0, info.width, info.height};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.lock(*handle, static_cast<int64_t>(usage), region, -1, (void**)&data));
+
+ // RGBA_8888
+ fillRGBA8888(data, info.height, stride * 4, info.width * 4);
+
+ int releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+
+ // lock again for reading
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(usage), region,
+ releaseFence, (void**)&data));
+ releaseFence = -1;
+
+ ASSERT_NO_FATAL_FAILURE(verifyRGBA8888(*handle, data, info.height, stride * 4, info.width * 4));
+
+ releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ }
+}
+
+/**
+ * Test multiple operations associated with different color formats
+ */
+TEST_P(GraphicsMapperStableCTests, Lock_YCRCB_420_SP) {
+ BufferDescriptorInfo info{
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::YCRCB_420_SP,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ };
+ auto buffer = allocate(info);
+ if (!buffer) {
+ ASSERT_FALSE(isSupported(info));
+ GTEST_SUCCEED() << "YCRCB_420_SP format is unsupported";
+ return;
+ }
+
+ // lock buffer for writing
+ const ARect region{0, 0, info.width, info.height};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, -1, (void**)&data));
+
+ android_ycbcr yCbCr;
+ int64_t hSubsampling = 0;
+ int64_t vSubsampling = 0;
+ ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+ constexpr uint32_t kCbCrSubSampleFactor = 2;
+ ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
+ ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
+
+ auto cbData = static_cast<uint8_t*>(yCbCr.cb);
+ auto crData = static_cast<uint8_t*>(yCbCr.cr);
+ ASSERT_EQ(crData + 1, cbData);
+ ASSERT_EQ(2, yCbCr.chroma_step);
+
+ fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+ int releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+
+ // lock again for reading
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, releaseFence, (void**)&data));
+ releaseFence = -1;
+
+ ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+ verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+ releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, YV12SubsampleMetadata) {
+ BufferDescriptorInfo info{
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::YV12,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ };
+ auto buffer = allocate(info);
+ ASSERT_NE(nullptr, buffer.get());
+
+ // lock buffer for writing
+ const ARect region{0, 0, info.width, info.height};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, -1, (void**)&data));
+
+ auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*handle);
+ ASSERT_TRUE(decodeResult.has_value());
+ const auto& planeLayouts = *decodeResult;
+
+ ASSERT_EQ(3, planeLayouts.size());
+
+ auto yPlane = planeLayouts[0];
+ auto crPlane = planeLayouts[1];
+ auto cbPlane = planeLayouts[2];
+
+ constexpr uint32_t kCbCrSubSampleFactor = 2;
+ EXPECT_EQ(kCbCrSubSampleFactor, crPlane.horizontalSubsampling);
+ EXPECT_EQ(kCbCrSubSampleFactor, crPlane.verticalSubsampling);
+
+ EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.horizontalSubsampling);
+ EXPECT_EQ(kCbCrSubSampleFactor, cbPlane.verticalSubsampling);
+
+ const long chromaSampleWidth = info.width / kCbCrSubSampleFactor;
+ const long chromaSampleHeight = info.height / kCbCrSubSampleFactor;
+
+ EXPECT_EQ(info.width, yPlane.widthInSamples);
+ EXPECT_EQ(info.height, yPlane.heightInSamples);
+
+ EXPECT_EQ(chromaSampleWidth, crPlane.widthInSamples);
+ EXPECT_EQ(chromaSampleHeight, crPlane.heightInSamples);
+
+ EXPECT_EQ(chromaSampleWidth, cbPlane.widthInSamples);
+ EXPECT_EQ(chromaSampleHeight, cbPlane.heightInSamples);
+
+ EXPECT_LE(crPlane.widthInSamples, crPlane.strideInBytes);
+ EXPECT_LE(cbPlane.widthInSamples, cbPlane.strideInBytes);
+
+ int releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, Lock_YV12) {
+ BufferDescriptorInfo info{
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::YV12,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ };
+ auto buffer = allocate(info);
+ ASSERT_NE(nullptr, buffer.get());
+
+ // lock buffer for writing
+ const ARect region{0, 0, info.width, info.height};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, -1, (void**)&data));
+
+ android_ycbcr yCbCr;
+ int64_t hSubsampling = 0;
+ int64_t vSubsampling = 0;
+ ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+ constexpr uint32_t kCbCrSubSampleFactor = 2;
+ ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
+ ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
+
+ auto cbData = static_cast<uint8_t*>(yCbCr.cb);
+ auto crData = static_cast<uint8_t*>(yCbCr.cr);
+ ASSERT_EQ(crData + yCbCr.cstride * info.height / vSubsampling, cbData);
+ ASSERT_EQ(1, yCbCr.chroma_step);
+
+ fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+ int releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+
+ // lock again for reading
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, releaseFence, (void**)&data));
+ releaseFence = -1;
+
+ ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+ verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, Lock_YCBCR_420_888) {
+ BufferDescriptorInfo info{
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::YCBCR_420_888,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ };
+ auto buffer = allocate(info);
+ ASSERT_NE(nullptr, buffer.get());
+
+ // lock buffer for writing
+ const ARect region{0, 0, info.width, info.height};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, -1, (void**)&data));
+
+ android_ycbcr yCbCr;
+ int64_t hSubsampling = 0;
+ int64_t vSubsampling = 0;
+ ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+ constexpr uint32_t kCbCrSubSampleFactor = 2;
+ ASSERT_EQ(kCbCrSubSampleFactor, hSubsampling);
+ ASSERT_EQ(kCbCrSubSampleFactor, vSubsampling);
+
+ fillYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+ int releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+
+ // lock again for reading
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, releaseFence, (void**)&data));
+ releaseFence = -1;
+
+ ASSERT_NO_FATAL_FAILURE(getAndroidYCbCr(*handle, data, &yCbCr, &hSubsampling, &vSubsampling));
+
+ verifyYCbCrData(yCbCr, info.width, info.height, hSubsampling, vSubsampling);
+
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, Lock_RAW10) {
+ BufferDescriptorInfo info{
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RAW10,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ };
+ auto buffer = allocate(info);
+ if (!buffer) {
+ ASSERT_FALSE(isSupported(info));
+ GTEST_SUCCEED() << "RAW10 format is unsupported";
+ return;
+ }
+
+ // lock buffer for writing
+ const ARect region{0, 0, info.width, info.height};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, -1, (void**)&data));
+
+ auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*handle);
+ ASSERT_TRUE(decodeResult.has_value());
+ const auto& planeLayouts = *decodeResult;
+
+ ASSERT_EQ(1, planeLayouts.size());
+ auto planeLayout = planeLayouts[0];
+
+ EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
+ EXPECT_EQ(1, planeLayout.horizontalSubsampling);
+ EXPECT_EQ(1, planeLayout.verticalSubsampling);
+
+ ASSERT_EQ(1, planeLayout.components.size());
+ auto planeLayoutComponent = planeLayout.components[0];
+
+ EXPECT_EQ(PlaneLayoutComponentType::RAW,
+ static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
+ EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
+ EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
+
+ int releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, Lock_RAW12) {
+ BufferDescriptorInfo info{
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RAW12,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ };
+ auto buffer = allocate(info);
+ if (!buffer) {
+ ASSERT_FALSE(isSupported(info));
+ GTEST_SUCCEED() << "RAW12 format is unsupported";
+ return;
+ }
+
+ // lock buffer for writing
+ const ARect region{0, 0, info.width, info.height};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, -1, (void**)&data));
+
+ auto decodeResult = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*handle);
+ ASSERT_TRUE(decodeResult.has_value());
+ const auto& planeLayouts = *decodeResult;
+
+ ASSERT_EQ(1, planeLayouts.size());
+ auto planeLayout = planeLayouts[0];
+
+ EXPECT_EQ(0, planeLayout.sampleIncrementInBits);
+ EXPECT_EQ(1, planeLayout.horizontalSubsampling);
+ EXPECT_EQ(1, planeLayout.verticalSubsampling);
+
+ ASSERT_EQ(1, planeLayout.components.size());
+ auto planeLayoutComponent = planeLayout.components[0];
+
+ EXPECT_EQ(PlaneLayoutComponentType::RAW,
+ static_cast<PlaneLayoutComponentType>(planeLayoutComponent.type.value));
+ EXPECT_EQ(0, planeLayoutComponent.offsetInBits % 8);
+ EXPECT_EQ(-1, planeLayoutComponent.sizeInBits);
+
+ int releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, Lock_YCBCR_P010) {
+ BufferDescriptorInfo info{
+ .name = {"VTS_TEMP"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::YCBCR_P010,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ };
+ auto buffer = allocate(info);
+ if (!buffer) {
+ ASSERT_FALSE(isSupported(info));
+ GTEST_SUCCEED() << "YCBCR_P010 format is unsupported";
+ return;
+ }
+
+ // lock buffer for writing
+ const ARect region{0, 0, info.width, info.height};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, -1, (void**)&data));
+
+ YCbCr yCbCr;
+ ASSERT_NO_FATAL_FAILURE(yCbCr = getAndroidYCbCr_P010(*handle, data));
+
+ constexpr uint32_t kCbCrSubSampleFactor = 2;
+ ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.horizontalSubSampling);
+ ASSERT_EQ(kCbCrSubSampleFactor, yCbCr.verticalSubSampling);
+
+ ASSERT_EQ(0, info.height % 2);
+
+ // fill the data
+ fillYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
+ yCbCr.verticalSubSampling);
+ // verify the YCbCr data
+ verifyYCbCrData(yCbCr.yCbCr, info.width, info.height, yCbCr.horizontalSubSampling,
+ yCbCr.verticalSubSampling);
+
+ int releaseFence = -1;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, LockBadAccessRegion) {
+ auto buffer = allocateGeneric();
+ ASSERT_NE(nullptr, buffer);
+ const auto& info = buffer->info();
+
+ // lock buffer for writing
+ const ARect region{0, 0, info.width * 2, info.height * 2};
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_VALUE, mapper()->v5.lock(*handle, static_cast<int64_t>(info.usage),
+ region, -1, (void**)&data));
+}
+
+TEST_P(GraphicsMapperStableCTests, UnlockNegative) {
+ native_handle_t* invalidHandle = nullptr;
+ int releaseFence = -1;
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(invalidHandle, &releaseFence))
+ << "unlock with nullptr did not fail with BAD_BUFFER";
+
+ invalidHandle = native_handle_create(0, 0);
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(invalidHandle, &releaseFence))
+ << "unlock with invalid handle did not fail with BAD_BUFFER";
+ native_handle_delete(invalidHandle);
+
+ auto buffer = allocateGeneric();
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(buffer->rawHandle(), &releaseFence))
+ << "unlock with un-imported handle did not fail with BAD_BUFFER";
+}
+
+TEST_P(GraphicsMapperStableCTests, UnlockNotImported) {
+ int releaseFence = -1;
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(buffer->rawHandle(), &releaseFence))
+ << "unlock with un-imported handle did not fail with BAD_BUFFER";
+}
+
+TEST_P(GraphicsMapperStableCTests, UnlockNotLocked) {
+ int releaseFence = -1;
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(*bufferHandle, &releaseFence))
+ << "unlock with unlocked handle did not fail with BAD_BUFFER";
+}
+
+TEST_P(GraphicsMapperStableCTests, LockUnlockNested) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ const ARect region{0, 0, buffer->info().width, buffer->info().height};
+ auto usage = static_cast<int64_t>(buffer->info().usage);
+ auto handle = buffer->import();
+ uint8_t* data = nullptr;
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, usage, region, -1, (void**)&data));
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.lock(*handle, usage, region, -1, (void**)&data))
+ << "Second lock failed";
+ int releaseFence = -1;
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ releaseFence = -1;
+ }
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*handle, &releaseFence))
+ << "Second unlock failed";
+ if (releaseFence != -1) {
+ close(releaseFence);
+ releaseFence = -1;
+ }
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.unlock(*handle, &releaseFence))
+ << "Third, unmatched, unlock should have failed with BAD_BUFFER";
+}
+
+TEST_P(GraphicsMapperStableCTests, FlushRereadBasic) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ const auto& info = buffer->info();
+ const auto stride = buffer->stride();
+ const ARect region{0, 0, buffer->info().width, buffer->info().height};
+
+ auto writeHandle = buffer->import();
+ auto readHandle = buffer->import();
+ ASSERT_TRUE(writeHandle && readHandle);
+
+ // lock buffer for writing
+
+ uint8_t* writeData;
+ EXPECT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.lock(*writeHandle, static_cast<uint64_t>(BufferUsage::CPU_WRITE_OFTEN),
+ region, -1, (void**)&writeData));
+
+ uint8_t* readData;
+ EXPECT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.lock(*readHandle, static_cast<uint64_t>(BufferUsage::CPU_READ_OFTEN),
+ region, -1, (void**)&readData));
+
+ fillRGBA8888(writeData, info.height, stride * 4, info.width * 4);
+
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.flushLockedBuffer(*writeHandle));
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.rereadLockedBuffer(*readHandle));
+
+ ASSERT_NO_FATAL_FAILURE(
+ verifyRGBA8888(*readHandle, readData, info.height, stride * 4, info.width * 4));
+
+ int releaseFence = -1;
+
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*readHandle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ releaseFence = -1;
+ }
+
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, mapper()->v5.unlock(*writeHandle, &releaseFence));
+ if (releaseFence != -1) {
+ close(releaseFence);
+ releaseFence = -1;
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, FlushLockedBufferBadBuffer) {
+ // Amazingly this is enough to make the compiler happy even though flushLockedBuffer
+ // is _Nonnull :shrug:
+ buffer_handle_t badBuffer = nullptr;
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.flushLockedBuffer(badBuffer));
+}
+
+TEST_P(GraphicsMapperStableCTests, RereadLockedBufferBadBuffer) {
+ buffer_handle_t badBuffer = nullptr;
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, mapper()->v5.rereadLockedBuffer(badBuffer));
+}
+
+TEST_P(GraphicsMapperStableCTests, GetBufferId) {
+ auto buffer = allocateGeneric();
+ auto bufferHandle = buffer->import();
+ auto bufferId = getStandardMetadata<StandardMetadataType::BUFFER_ID>(*bufferHandle);
+ ASSERT_TRUE(bufferId.has_value());
+
+ auto buffer2 = allocateGeneric();
+ auto bufferHandle2 = buffer2->import();
+ auto bufferId2 = getStandardMetadata<StandardMetadataType::BUFFER_ID>(*bufferHandle2);
+ ASSERT_TRUE(bufferId2.has_value());
+
+ EXPECT_NE(*bufferId, *bufferId2);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetName) {
+ auto buffer = allocate({
+ .name = {"Hello, World!"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ });
+ auto bufferHandle = buffer->import();
+ auto name = getStandardMetadata<StandardMetadataType::NAME>(*bufferHandle);
+ ASSERT_TRUE(name.has_value());
+ EXPECT_EQ(*name, "Hello, World!");
+}
+
+TEST_P(GraphicsMapperStableCTests, GetWidthHeight) {
+ auto buffer = allocate({
+ .name = {"Hello, World!"},
+ .width = 64,
+ .height = 128,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ });
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::WIDTH>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(*value, 64);
+ value = getStandardMetadata<StandardMetadataType::HEIGHT>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(*value, 128);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetLayerCount) {
+ auto buffer = allocateGeneric();
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::LAYER_COUNT>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(*value, buffer->info().layerCount);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetPixelFormatRequested) {
+ auto buffer = allocateGeneric();
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_REQUESTED>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(*value, buffer->info().format);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetPixelFormatFourCC) {
+ auto buffer = allocate({
+ .name = {"Hello, World!"},
+ .width = 64,
+ .height = 128,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ });
+ {
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(*value, DRM_FORMAT_ABGR8888);
+ }
+
+ buffer = allocate({
+ .name = {"yv12"},
+ .width = 64,
+ .height = 128,
+ .layerCount = 1,
+ .format = PixelFormat::YV12,
+ .usage = BufferUsage::CPU_WRITE_OFTEN | BufferUsage::CPU_READ_OFTEN,
+ .reservedSize = 0,
+ });
+ {
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_FOURCC>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(*value, DRM_FORMAT_YVU420);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, GetPixelFormatModifier) {
+ auto buffer = allocateGeneric();
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::PIXEL_FORMAT_MODIFIER>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ // Only the upper 8-bits are defined and is just the vendor ID, the lower 56 bits are
+ // then vendor specific. So there's not anything useful to assert here beyond just that
+ // we successfully queried a value
+}
+
+TEST_P(GraphicsMapperStableCTests, GetUsage) {
+ auto buffer = allocateGeneric();
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::USAGE>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(buffer->info().usage, *value);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetAllocationSize) {
+ auto buffer = allocateGeneric();
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::ALLOCATION_SIZE>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ const auto estimatedSize = buffer->stride() * buffer->info().height * 4;
+ // This buffer has CPU usage, so we expect at least stride * height * 4 since it should be
+ // generally linear uncompressed.
+ EXPECT_GE(*value, estimatedSize)
+ << "Expected allocation size to be at least stride * height * 4bpp";
+ // Might need refining, but hopefully this a generous-enough upper-bound?
+ EXPECT_LT(*value, estimatedSize * 2)
+ << "Expected allocation size to less than double stride * height * 4bpp";
+}
+
+TEST_P(GraphicsMapperStableCTests, GetProtectedContent) {
+ const BufferDescriptorInfo info{
+ .name = {"prot8888"},
+ .width = 64,
+ .height = 64,
+ .layerCount = 1,
+ .format = PixelFormat::RGBA_8888,
+ .usage = BufferUsage::PROTECTED | BufferUsage::COMPOSER_OVERLAY,
+ .reservedSize = 0,
+ };
+ auto buffer = allocate(info);
+ if (!buffer) {
+ ASSERT_FALSE(isSupported(info))
+ << "Allocation of trivial sized buffer failed, so isSupported() must be false";
+ GTEST_SUCCEED() << "PROTECTED RGBA_8888 is unsupported";
+ return;
+ }
+ auto bufferHandle = buffer->import();
+ auto value = getStandardMetadata<StandardMetadataType::PROTECTED_CONTENT>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(*value, 1);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetCompression) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::COMPRESSION>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(gralloc4::Compression_None.name, value->name);
+ EXPECT_EQ(gralloc4::Compression_None.value, value->value);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetInterlaced) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::INTERLACED>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(gralloc4::Interlaced_None.name, value->name);
+ EXPECT_EQ(gralloc4::Interlaced_None.value, value->value);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetChromaSiting) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::CHROMA_SITING>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(gralloc4::ChromaSiting_None.name, value->name);
+ EXPECT_EQ(gralloc4::ChromaSiting_None.value, value->value);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetPlaneLayouts) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::PLANE_LAYOUTS>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ ASSERT_NO_FATAL_FAILURE(verifyRGBA8888PlaneLayouts(*value));
+}
+
+TEST_P(GraphicsMapperStableCTests, GetCrop) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::CROP>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(1, value->size());
+ const Rect expected{0, 0, buffer->info().width, buffer->info().height};
+ EXPECT_EQ(expected, value->at(0));
+}
+
+TEST_P(GraphicsMapperStableCTests, GetSetDataspace) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::DATASPACE>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(Dataspace::UNKNOWN, *value);
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, setStandardMetadata<StandardMetadataType::DATASPACE>(
+ *bufferHandle, Dataspace::DISPLAY_P3));
+ value = getStandardMetadata<StandardMetadataType::DATASPACE>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(Dataspace::DISPLAY_P3, *value);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetSetBlendMode) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::BLEND_MODE>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(BlendMode::INVALID, *value);
+ EXPECT_EQ(AIMAPPER_ERROR_NONE, setStandardMetadata<StandardMetadataType::BLEND_MODE>(
+ *bufferHandle, BlendMode::COVERAGE));
+ value = getStandardMetadata<StandardMetadataType::BLEND_MODE>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(BlendMode::COVERAGE, *value);
+}
+
+TEST_P(GraphicsMapperStableCTests, GetSetSmpte2086) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_FALSE(value->has_value());
+
+ // TODO: Maybe use something resembling real values, but validation isn't supposed to happen
+ // here anyway so :shrug:
+ const Smpte2086 awesomeHdr{
+ XyColor{1.f, 1.f}, XyColor{2.f, 2.f}, XyColor{3.f, 3.f},
+ XyColor{400.f, 1000.f}, 100000.0f, 0.0001f,
+ };
+ EXPECT_EQ(AIMAPPER_ERROR_NONE,
+ setStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle, awesomeHdr));
+ value = getStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ ASSERT_TRUE(value->has_value());
+ EXPECT_EQ(awesomeHdr, *value);
+
+ EXPECT_EQ(AIMAPPER_ERROR_NONE,
+ setStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle, std::nullopt));
+ value = getStandardMetadata<StandardMetadataType::SMPTE2086>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_FALSE(value->has_value());
+}
+
+TEST_P(GraphicsMapperStableCTests, GetCta861_3) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_FALSE(value->has_value());
+
+ const Cta861_3 genericHlgish{1000.f, 140.f};
+ EXPECT_EQ(AIMAPPER_ERROR_NONE,
+ setStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle, genericHlgish));
+ value = getStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ ASSERT_TRUE(value->has_value());
+ EXPECT_EQ(genericHlgish, *value);
+
+ EXPECT_EQ(AIMAPPER_ERROR_NONE,
+ setStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle, std::nullopt));
+ value = getStandardMetadata<StandardMetadataType::CTA861_3>(*bufferHandle);
+ ASSERT_TRUE(value.has_value());
+ EXPECT_FALSE(value->has_value());
+}
+
+TEST_P(GraphicsMapperStableCTests, GetSmpte2094_10) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_10>(*bufferHandle);
+ if (value.has_value()) {
+ EXPECT_FALSE(value->has_value());
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, GetSmpte2094_40) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ auto value = getStandardMetadata<StandardMetadataType::SMPTE2094_40>(*bufferHandle);
+ if (value.has_value()) {
+ EXPECT_FALSE(value->has_value());
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, SupportsRequiredGettersSetters) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ const AIMapper_MetadataTypeDescription* descriptions = nullptr;
+ size_t descriptionCount = 0;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
+ std::vector<StandardMetadataType> requiredGetters = {
+ StandardMetadataType::BUFFER_ID,
+ StandardMetadataType::NAME,
+ StandardMetadataType::WIDTH,
+ StandardMetadataType::HEIGHT,
+ StandardMetadataType::LAYER_COUNT,
+ StandardMetadataType::PIXEL_FORMAT_REQUESTED,
+ StandardMetadataType::PIXEL_FORMAT_FOURCC,
+ StandardMetadataType::PIXEL_FORMAT_MODIFIER,
+ StandardMetadataType::USAGE,
+ StandardMetadataType::ALLOCATION_SIZE,
+ StandardMetadataType::PROTECTED_CONTENT,
+ StandardMetadataType::COMPRESSION,
+ StandardMetadataType::INTERLACED,
+ StandardMetadataType::CHROMA_SITING,
+ StandardMetadataType::PLANE_LAYOUTS,
+ StandardMetadataType::CROP,
+ StandardMetadataType::DATASPACE,
+ StandardMetadataType::BLEND_MODE,
+ StandardMetadataType::SMPTE2086,
+ StandardMetadataType::CTA861_3,
+ };
+
+ std::vector<StandardMetadataType> requiredSetters = {
+ StandardMetadataType::DATASPACE,
+ StandardMetadataType::BLEND_MODE,
+ StandardMetadataType::SMPTE2086,
+ StandardMetadataType::CTA861_3,
+ };
+
+ for (int i = 0; i < descriptionCount; i++) {
+ const auto& it = descriptions[i];
+ if (isStandardMetadata(it.metadataType)) {
+ EXPECT_GT(it.metadataType.value, static_cast<int64_t>(StandardMetadataType::INVALID));
+ EXPECT_LT(it.metadataType.value,
+ ndk::internal::enum_values<StandardMetadataType>.size());
+
+ if (it.isGettable) {
+ std::erase(requiredGetters,
+ static_cast<StandardMetadataType>(it.metadataType.value));
+ }
+ if (it.isSettable) {
+ std::erase(requiredSetters,
+ static_cast<StandardMetadataType>(it.metadataType.value));
+ }
+ } else {
+ EXPECT_NE(nullptr, it.description) << "Non-standard metadata must have a description";
+ int len = strlen(it.description);
+ EXPECT_GE(len, 0) << "Non-standard metadata must have a description";
+ }
+ }
+
+ EXPECT_EQ(0, requiredGetters.size()) << "Missing required getters" << toString(requiredGetters);
+ EXPECT_EQ(0, requiredSetters.size()) << "Missing required setters" << toString(requiredSetters);
+}
+
+/*
+ * Test that verifies that if the optional StandardMetadataTypes have getters, they have
+ * the required setters as well
+ */
+TEST_P(GraphicsMapperStableCTests, CheckRequiredSettersIfHasGetters) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ const AIMapper_MetadataTypeDescription* descriptions = nullptr;
+ size_t descriptionCount = 0;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
+
+ for (int i = 0; i < descriptionCount; i++) {
+ const auto& it = descriptions[i];
+ if (isStandardMetadata(it.metadataType)) {
+ const auto type = static_cast<StandardMetadataType>(it.metadataType.value);
+ switch (type) {
+ case StandardMetadataType::SMPTE2094_10:
+ case StandardMetadataType::SMPTE2094_40:
+ if (it.isGettable) {
+ EXPECT_TRUE(it.isSettable)
+ << "Type " << toString(type) << " must be settable if gettable";
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, ListSupportedWorks) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+ const AIMapper_MetadataTypeDescription* descriptions = nullptr;
+ size_t descriptionCount = 0;
+ ASSERT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.listSupportedMetadataTypes(&descriptions, &descriptionCount));
+
+ std::vector<uint8_t> metadataBuffer;
+ auto get = [&](AIMapper_MetadataType metadataType) -> int32_t {
+ int32_t size = mapper()->v5.getMetadata(*bufferHandle, metadataType, nullptr, 0);
+ if (size >= 0) {
+ metadataBuffer.resize(size);
+ size = mapper()->v5.getMetadata(*bufferHandle, metadataType, metadataBuffer.data(),
+ metadataBuffer.size());
+ EXPECT_EQ(size, metadataBuffer.size());
+ }
+ return size;
+ };
+
+ for (int i = 0; i < descriptionCount; i++) {
+ const auto& it = descriptions[i];
+ if (!isStandardMetadata(it.metadataType)) {
+ continue;
+ }
+ if (!it.isGettable) {
+ EXPECT_FALSE(it.isSettable)
+ << "StandardMetadata that isn't gettable must not be settable";
+ continue;
+ }
+ EXPECT_GE(get(it.metadataType), 0)
+ << "Get failed for claimed supported getter of "
+ << toString(static_cast<StandardMetadataType>(it.metadataType.value));
+ if (it.isSettable) {
+ EXPECT_EQ(AIMAPPER_ERROR_NONE,
+ mapper()->v5.setMetadata(*bufferHandle, it.metadataType,
+ metadataBuffer.data(), metadataBuffer.size()))
+ << "Failed to set metadata for "
+ << toString(static_cast<StandardMetadataType>(it.metadataType.value));
+ }
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, GetMetadataBadValue) {
+ auto get = [this](StandardMetadataType type) -> AIMapper_Error {
+ // This is a _Nonnull parameter, but this is enough obfuscation to fool the linter
+ buffer_handle_t buffer = nullptr;
+ int32_t ret =
+ mapper()->v5.getStandardMetadata(buffer, static_cast<int64_t>(type), nullptr, 0);
+ return (ret < 0) ? (AIMapper_Error)-ret : AIMAPPER_ERROR_NONE;
+ };
+
+ for (auto type : ndk::enum_range<StandardMetadataType>()) {
+ if (type == StandardMetadataType::INVALID) {
+ continue;
+ }
+ EXPECT_EQ(AIMAPPER_ERROR_BAD_BUFFER, get(type)) << "Wrong error for " << toString(type);
+ }
+}
+
+TEST_P(GraphicsMapperStableCTests, GetUnsupportedMetadata) {
+ auto buffer = allocateGeneric();
+ ASSERT_TRUE(buffer);
+ auto bufferHandle = buffer->import();
+ ASSERT_TRUE(bufferHandle);
+
+ int result = mapper()->v5.getMetadata(*bufferHandle, {"Fake", 1}, nullptr, 0);
+ EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
+
+ result = mapper()->v5.getStandardMetadata(
+ *bufferHandle, static_cast<int64_t>(StandardMetadataType::INVALID), nullptr, 0);
+ EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
+
+ constexpr int64_t unknownStandardType = ndk::internal::enum_values<StandardMetadataType>.size();
+ result = mapper()->v5.getStandardMetadata(*bufferHandle, unknownStandardType, nullptr, 0);
+ EXPECT_EQ(AIMAPPER_ERROR_UNSUPPORTED, -result);
+}
+
+std::vector<std::tuple<std::string, std::shared_ptr<IAllocator>>> getIAllocatorsAtLeastVersion(
+ int32_t minVersion) {
+ auto instanceNames = getAidlHalInstanceNames(IAllocator::descriptor);
+ std::vector<std::tuple<std::string, std::shared_ptr<IAllocator>>> filteredInstances;
+ filteredInstances.reserve(instanceNames.size());
+ for (const auto& name : instanceNames) {
+ auto allocator =
+ IAllocator::fromBinder(ndk::SpAIBinder(AServiceManager_checkService(name.c_str())));
+ int32_t version = 0;
+ if (allocator->getInterfaceVersion(&version).isOk()) {
+ if (version >= minVersion) {
+ filteredInstances.emplace_back(name, std::move(allocator));
+ }
+ }
+ }
+ return filteredInstances;
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(GraphicsMapperStableCTests);
+INSTANTIATE_TEST_CASE_P(PerInstance, GraphicsMapperStableCTests,
+ testing::ValuesIn(getIAllocatorsAtLeastVersion(2)),
+ [](auto info) -> std::string {
+ std::string name =
+ std::to_string(info.index) + "/" + std::get<0>(info.param);
+ return Sanitize(name);
+ });
\ No newline at end of file
diff --git a/identity/aidl/Android.bp b/identity/aidl/Android.bp
index 57451ed..2090473 100644
--- a/identity/aidl/Android.bp
+++ b/identity/aidl/Android.bp
@@ -14,10 +14,11 @@
"android/hardware/identity/*.aidl",
],
imports: [
- "android.hardware.keymaster",
- "android.hardware.security.keymint",
+ "android.hardware.keymaster-V3",
+ "android.hardware.security.rkp-V3",
],
stability: "vintf",
+ frozen: true,
backend: {
java: {
platform_apis: true,
@@ -31,28 +32,28 @@
version: "1",
imports: [
"android.hardware.keymaster-V3",
- "android.hardware.security.keymint-V1",
+ "android.hardware.security.rkp-V1",
],
},
{
version: "2",
imports: [
"android.hardware.keymaster-V3",
- "android.hardware.security.keymint-V1",
+ "android.hardware.security.rkp-V1",
],
},
{
version: "3",
imports: [
"android.hardware.keymaster-V3",
- "android.hardware.security.keymint-V1",
+ "android.hardware.security.rkp-V1",
],
},
{
version: "4",
imports: [
"android.hardware.keymaster-V3",
- "android.hardware.security.keymint-V2",
+ "android.hardware.security.rkp-V3",
],
},
diff --git a/identity/aidl/default/Android.bp b/identity/aidl/default/Android.bp
index a57875a..7bc3c8d 100644
--- a/identity/aidl/default/Android.bp
+++ b/identity/aidl/default/Android.bp
@@ -45,6 +45,7 @@
"libpuresoftkeymasterdevice",
"android.hardware.identity-support-lib",
"android.hardware.keymaster-V3-ndk",
+ "android.hardware.security.rkp-V3-ndk",
],
}
@@ -112,6 +113,7 @@
"android.hardware.keymaster-V3-ndk",
"android.hardware.identity-libeic-hal-common",
"android.hardware.identity-libeic-library",
+ "android.hardware.security.rkp-V3-ndk",
],
srcs: [
"service.cpp",
diff --git a/identity/aidl/default/EicOpsImpl.cc b/identity/aidl/default/EicOpsImpl.cc
index b6d324f..803df64 100644
--- a/identity/aidl/default/EicOpsImpl.cc
+++ b/identity/aidl/default/EicOpsImpl.cc
@@ -489,7 +489,7 @@
}
bool eicOpsEcdh(const uint8_t publicKey[EIC_P256_PUB_KEY_SIZE],
- const uint8_t privateKey[EIC_P256_PUB_KEY_SIZE],
+ const uint8_t privateKey[EIC_P256_PRIV_KEY_SIZE],
uint8_t sharedSecret[EIC_P256_COORDINATE_SIZE]) {
vector<uint8_t> pubKeyVec(EIC_P256_PUB_KEY_SIZE + 1);
pubKeyVec[0] = 0x04;
diff --git a/identity/aidl/default/android.hardware.identity_credential.xml b/identity/aidl/default/android.hardware.identity_credential.xml
index 20b2710..a49ddca 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="202201" />
+ <feature name="android.hardware.identity_credential" version="202301" />
</permissions>
diff --git a/identity/aidl/vts/Android.bp b/identity/aidl/vts/Android.bp
index dd29819..5e303bb 100644
--- a/identity/aidl/vts/Android.bp
+++ b/identity/aidl/vts/Android.bp
@@ -39,6 +39,8 @@
"libcrypto",
],
static_libs: [
+ "android.hardware.security.rkp-V3-cpp",
+ "android.hardware.security.rkp-V3-ndk",
"android.hardware.security.secureclock-V1-ndk",
"libcppbor_external",
"libcppcose_rkp",
@@ -59,3 +61,16 @@
],
require_root: true,
}
+
+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/IdentityCredentialImplementedTest.xml b/identity/aidl/vts/IdentityCredentialImplementedTest.xml
new file mode 100644
index 0000000..4276ae6
--- /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/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..4936f8c
--- /dev/null
+++ b/identity/aidl/vts/src/com/android/tests/security/identity/IdentityCredentialImplementedTest.java
@@ -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 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;
+
+// This is a host-test which executes shell commands on the device. It would be
+// nicer to have this be a Device test (like CTS) but this is currently not
+// possible, see https://source.android.com/docs/core/tests/vts
+
+@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 14 VSR (vendor API level 34), Identity Credential is required at feature
+ // version 202301 or later.
+ @RequiresDevice
+ @Test
+ public void testIdentityCredentialIsImplemented() throws Exception {
+ int vendorApiLevel = getVendorApiLevel();
+ assumeTrue(vendorApiLevel >= 34);
+
+ final String minimumFeatureVersionNeeded = "202301";
+
+ 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/input/common/aidl/Android.bp b/input/common/aidl/Android.bp
index 390d8b5..95a14b2 100644
--- a/input/common/aidl/Android.bp
+++ b/input/common/aidl/Android.bp
@@ -9,6 +9,7 @@
aidl_interface {
name: "android.hardware.input.common",
+ host_supported: true,
vendor_available: true,
srcs: ["android/hardware/input/common/*.aidl"],
stability: "vintf",
diff --git a/input/processor/aidl/Android.bp b/input/processor/aidl/Android.bp
index 354816e..773bb49 100644
--- a/input/processor/aidl/Android.bp
+++ b/input/processor/aidl/Android.bp
@@ -9,6 +9,7 @@
aidl_interface {
name: "android.hardware.input.processor",
+ host_supported: true,
vendor_available: true,
srcs: ["android/hardware/input/processor/*.aidl"],
imports: [
diff --git a/ir/aidl/default/Android.bp b/ir/aidl/default/Android.bp
index a4fb439..a8096c2 100644
--- a/ir/aidl/default/Android.bp
+++ b/ir/aidl/default/Android.bp
@@ -36,6 +36,7 @@
"liblog",
"libutils",
"android.hardware.ir-V1-ndk",
+ "libhardware"
],
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
index 56def64..d27f282 100644
--- a/ir/aidl/default/android.hardware.ir-service.example.rc
+++ b/ir/aidl/default/android.hardware.ir-service.example.rc
@@ -1,4 +1,4 @@
service vendor.ir-default /vendor/bin/hw/android.hardware.ir-service.example
class hal
- user nobody
- group nobody
+ user system
+ group system
diff --git a/ir/aidl/default/main.cpp b/ir/aidl/default/main.cpp
index 7c4a816..92376fc 100644
--- a/ir/aidl/default/main.cpp
+++ b/ir/aidl/default/main.cpp
@@ -15,49 +15,77 @@
*/
#include <aidl/android/hardware/ir/BnConsumerIr.h>
+#include <aidl/android/hardware/ir/ConsumerIrFreqRange.h>
#include <android-base/logging.h>
#include <android/binder_interface_utils.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <hardware/consumerir.h>
#include <numeric>
+#include <log/log.h>
+
+using ::aidl::android::hardware::ir::ConsumerIrFreqRange;
+
namespace aidl::android::hardware::ir {
-const std::vector<ConsumerIrFreqRange> kSupportedFreqs = {
- {2000, 4000},
- {10000, 30000},
-};
-
class ConsumerIr : public BnConsumerIr {
+ public:
+ ConsumerIr();
+ private:
::ndk::ScopedAStatus getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) override;
::ndk::ScopedAStatus transmit(int32_t in_carrierFreqHz,
const std::vector<int32_t>& in_pattern) override;
+ consumerir_device_t *mDevice = nullptr;
};
-::ndk::ScopedAStatus ConsumerIr::getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) {
- *_aidl_return = kSupportedFreqs;
- return ::ndk::ScopedAStatus::ok();
+ConsumerIr::ConsumerIr() {
+ const hw_module_t *hw_module = NULL;
+
+ int ret = hw_get_module(CONSUMERIR_HARDWARE_MODULE_ID, &hw_module);
+ if (ret != 0) {
+ ALOGE("hw_get_module %s failed: %d", CONSUMERIR_HARDWARE_MODULE_ID, ret);
+ return;
+ }
+ ret = hw_module->methods->open(hw_module, CONSUMERIR_TRANSMITTER, (hw_device_t **) &mDevice);
+ if (ret < 0) {
+ // note - may want to make this a fatal error - otherwise the service will crash when it's used
+ ALOGE("Can't open consumer IR transmitter, error: %d", ret);
+ // in case it's modified
+ mDevice = nullptr;
+ }
}
-bool isSupportedFreq(int32_t freq) {
- for (const auto& range : kSupportedFreqs) {
- if (freq >= range.minHz && freq <= range.maxHz) return true;
+::ndk::ScopedAStatus ConsumerIr::getCarrierFreqs(std::vector<ConsumerIrFreqRange>* _aidl_return) {
+ int32_t len = mDevice->get_num_carrier_freqs(mDevice);
+ if (len < 0) {
+ (*_aidl_return).clear();
+ return ::ndk::ScopedAStatus::ok();
}
- return false;
+
+ consumerir_freq_range_t *rangeAr = new consumerir_freq_range_t[len];
+ bool success = (mDevice->get_carrier_freqs(mDevice, len, rangeAr) >= 0);
+ if (!success) {
+ (*_aidl_return).clear();
+ return ::ndk::ScopedAStatus::ok();
+ }
+
+ (*_aidl_return).resize(len);
+ for (int32_t i = 0; i < len; i++) {
+ (*_aidl_return)[i].minHz = static_cast<uint32_t>(rangeAr[i].min);
+ (*_aidl_return)[i].maxHz = static_cast<uint32_t>(rangeAr[i].max);
+ }
+ return ::ndk::ScopedAStatus::ok();
}
::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));
+ if (in_carrierFreqHz > 0) {
+ mDevice->transmit(mDevice, in_carrierFreqHz, in_pattern.data(), in_pattern.size());
return ::ndk::ScopedAStatus::ok();
} else {
- // unsupported operation
return ::ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
- return ::ndk::ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::ir
diff --git a/keymaster/3.0/default/OWNERS b/keymaster/3.0/default/OWNERS
deleted file mode 100644
index 335660d..0000000
--- a/keymaster/3.0/default/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-jdanis@google.com
-swillden@google.com
diff --git a/keymaster/3.0/vts/OWNERS b/keymaster/3.0/vts/OWNERS
deleted file mode 100644
index 846bb84..0000000
--- a/keymaster/3.0/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-drysdale@google.com
-jdanis@google.com
-swillden@google.com
-yim@google.com
-yuexima@google.com
diff --git a/keymaster/3.0/vts/functional/OWNERS b/keymaster/3.0/vts/functional/OWNERS
deleted file mode 100644
index 2ef9086..0000000
--- a/keymaster/3.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 189335
-swillden@google.com
diff --git a/keymaster/4.0/default/OWNERS b/keymaster/4.0/default/OWNERS
deleted file mode 100644
index 335660d..0000000
--- a/keymaster/4.0/default/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-jdanis@google.com
-swillden@google.com
diff --git a/keymaster/4.0/support/OWNERS b/keymaster/4.0/support/OWNERS
deleted file mode 100644
index a9efe66..0000000
--- a/keymaster/4.0/support/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-jdanis@google.com
-swillden@google.com
-jbires@google.com
diff --git a/keymaster/4.0/vts/OWNERS b/keymaster/4.0/vts/OWNERS
deleted file mode 100644
index 0d6fa6c..0000000
--- a/keymaster/4.0/vts/OWNERS
+++ /dev/null
@@ -1,6 +0,0 @@
-drysdale@google.com
-jbires@google.com
-jdanis@google.com
-swillden@google.com
-yim@google.com
-yuexima@google.com
diff --git a/keymaster/4.0/vts/functional/OWNERS b/keymaster/4.0/vts/functional/OWNERS
deleted file mode 100644
index 2ef9086..0000000
--- a/keymaster/4.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 189335
-swillden@google.com
diff --git a/keymaster/4.1/default/OWNERS b/keymaster/4.1/default/OWNERS
deleted file mode 100644
index 2b2ad2a..0000000
--- a/keymaster/4.1/default/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-swillden@google.com
-zeuthen@google.com
\ No newline at end of file
diff --git a/keymaster/4.1/support/OWNERS b/keymaster/4.1/support/OWNERS
deleted file mode 100644
index 2b2ad2a..0000000
--- a/keymaster/4.1/support/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-jbires@google.com
-jdanis@google.com
-swillden@google.com
-zeuthen@google.com
\ No newline at end of file
diff --git a/keymaster/4.1/vts/OWNERS b/keymaster/4.1/vts/OWNERS
deleted file mode 100644
index 24ed042..0000000
--- a/keymaster/4.1/vts/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-drysdale@google.com
-jbires@google.com
-jdanis@google.com
-swillden@google.com
-zeuthen@google.com
\ No newline at end of file
diff --git a/keymaster/4.1/vts/functional/OWNERS b/keymaster/4.1/vts/functional/OWNERS
deleted file mode 100644
index 2ef9086..0000000
--- a/keymaster/4.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 189335
-swillden@google.com
diff --git a/keymaster/OWNERS b/keymaster/OWNERS
new file mode 100644
index 0000000..ac8bd83
--- /dev/null
+++ b/keymaster/OWNERS
@@ -0,0 +1,14 @@
+# Bug component: 1084733
+
+# Please assign all bugs related to /hardware/interfaces/keymaster to the team alias:
+#
+# android-hardware-security@google.com
+#
+# This will get them auto-assigned to the on-call triage engineer, ensuring quickest response.
+
+drysdale@google.com
+eranm@google.com
+hasinitg@google.com
+jbires@google.com
+swillden@google.com
+zeuthen@google.com
diff --git a/keymaster/aidl/Android.bp b/keymaster/aidl/Android.bp
index 0fb6e4c..a3800c1 100644
--- a/keymaster/aidl/Android.bp
+++ b/keymaster/aidl/Android.bp
@@ -19,9 +19,18 @@
platform_apis: true,
},
},
- versions: [
- "1",
- "2",
- "3",
+ versions_with_info: [
+ {
+ version: "1",
+ imports: [],
+ },
+ {
+ version: "2",
+ imports: [],
+ },
+ {
+ version: "3",
+ imports: [],
+ },
],
}
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthToken.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthToken.aidl
index 4f21cba..6e84e98 100644
--- a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthToken.aidl
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthToken.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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 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
@@ -16,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.keymaster;
+/* @hide */
@VintfStability
parcelable HardwareAuthToken {
long challenge;
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthenticatorType.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthenticatorType.aidl
index 924567f..0a40549 100644
--- a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthenticatorType.aidl
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/HardwareAuthenticatorType.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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 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
@@ -16,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.keymaster;
+/* @hide */
@Backing(type="int") @VintfStability
enum HardwareAuthenticatorType {
NONE = 0,
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/SecurityLevel.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/SecurityLevel.aidl
index 127c1bf..d32ef68 100644
--- a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/SecurityLevel.aidl
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/SecurityLevel.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
@@ -16,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.keymaster;
+/* @hide */
@Backing(type="int") @VintfStability
enum SecurityLevel {
SOFTWARE = 0,
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/Timestamp.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/Timestamp.aidl
index 45fa1ae..5b7b37a 100644
--- a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/Timestamp.aidl
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/Timestamp.aidl
@@ -1,14 +1,30 @@
+/*
+ * 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 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
@@ -16,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.keymaster;
+/* @hide */
@VintfStability
parcelable Timestamp {
long milliSeconds;
diff --git a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/VerificationToken.aidl b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/VerificationToken.aidl
index b116dac..10fa5e1 100644
--- a/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/VerificationToken.aidl
+++ b/keymaster/aidl/aidl_api/android.hardware.keymaster/current/android/hardware/keymaster/VerificationToken.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
@@ -16,6 +32,7 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.keymaster;
+/* @hide */
@VintfStability
parcelable VerificationToken {
long challenge;
diff --git a/keymaster/aidl/android/hardware/keymaster/HardwareAuthToken.aidl b/keymaster/aidl/android/hardware/keymaster/HardwareAuthToken.aidl
index 99b036a..427c192 100644
--- a/keymaster/aidl/android/hardware/keymaster/HardwareAuthToken.aidl
+++ b/keymaster/aidl/android/hardware/keymaster/HardwareAuthToken.aidl
@@ -16,8 +16,8 @@
package android.hardware.keymaster;
-import android.hardware.keymaster.Timestamp;
import android.hardware.keymaster.HardwareAuthenticatorType;
+import android.hardware.keymaster.Timestamp;
/**
* HardwareAuthToken is used to prove successful user authentication, to unlock the use of a key.
@@ -27,10 +27,10 @@
* begin(), update(), and finish() to prove that authentication occurred. See those methods for
* more details. It is up to the caller to determine which of the generated auth tokens is
* appropriate for a given key operation.
+ * @hide
*/
@VintfStability
parcelable HardwareAuthToken {
-
/**
* challenge is a value that's used to enable authentication tokens to authorize specific
* events. The primary use case for challenge is to authorize an IKeymasterDevice cryptographic
@@ -49,7 +49,7 @@
* but is created in an authentication application in the secure environment, such as the
* Fingerprint application.
*/
- long authenticatorId; // Secure authenticator ID.
+ long authenticatorId; // Secure authenticator ID.
/**
* authenticatorType describes the type of authentication that took place, e.g. password or
diff --git a/keymaster/aidl/android/hardware/keymaster/HardwareAuthenticatorType.aidl b/keymaster/aidl/android/hardware/keymaster/HardwareAuthenticatorType.aidl
index 3141858..7a303a7 100644
--- a/keymaster/aidl/android/hardware/keymaster/HardwareAuthenticatorType.aidl
+++ b/keymaster/aidl/android/hardware/keymaster/HardwareAuthenticatorType.aidl
@@ -20,6 +20,7 @@
* Hardware authentication type, used by HardwareAuthTokens to specify the mechanism used to
* authentiate the user, and in KeyCharacteristics to specify the allowable mechanisms for
* authenticating to activate a key.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl b/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
index 00578a4..0b84392 100644
--- a/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
+++ b/keymaster/aidl/android/hardware/keymaster/SecurityLevel.aidl
@@ -18,6 +18,7 @@
/**
* Device security levels.
+ * @hide
*/
@VintfStability
@Backing(type="int")
diff --git a/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl b/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl
index 19ea944..0b0c36f 100644
--- a/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl
+++ b/keymaster/aidl/android/hardware/keymaster/Timestamp.aidl
@@ -16,14 +16,13 @@
package android.hardware.keymaster;
-
/**
* Time in milliseconds since some arbitrary point in time. Time must be monotonically increasing,
* and a secure environment's notion of "current time" must not repeat until the Android device
* reboots, or until at least 50 million years have elapsed (note that this requirement is satisfied
* by setting the clock to zero during each boot, and then counting time accurately).
+ * @hide
*/
-
@VintfStability
parcelable Timestamp {
long milliSeconds;
diff --git a/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl b/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl
index 5efd937..ceee941 100644
--- a/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl
+++ b/keymaster/aidl/android/hardware/keymaster/VerificationToken.aidl
@@ -24,6 +24,7 @@
*
* This version of the parcelable currently don't use the parametersVerified field since it's not
* needed for time-based verification. This can be added in a later version, if needed.
+ * @hide
*/
@VintfStability
parcelable VerificationToken {
@@ -39,7 +40,6 @@
*/
Timestamp timestamp;
-
/**
* SecurityLevel of the secure environment that generated the token.
*/
diff --git a/media/bufferpool/aidl/Android.bp b/media/bufferpool/aidl/Android.bp
new file mode 100644
index 0000000..68ac489
--- /dev/null
+++ b/media/bufferpool/aidl/Android.bp
@@ -0,0 +1,44 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // 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.media.bufferpool2",
+ vendor_available: true,
+ srcs: ["android/hardware/media/bufferpool2/*.aidl"],
+ imports: [
+ "android.hardware.common-V2",
+ "android.hardware.common.fmq-V1",
+ ],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: true,
+ },
+ },
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/Buffer.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/Buffer.aidl
new file mode 100644
index 0000000..4ea0bba
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/Buffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.bufferpool2;
+@VintfStability
+parcelable Buffer {
+ int id;
+ android.hardware.common.NativeHandle buffer;
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl
new file mode 100644
index 0000000..181286c
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferInvalidationMessage.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.media.bufferpool2;
+@FixedSize @VintfStability
+parcelable BufferInvalidationMessage {
+ int messageId;
+ int fromBufferId;
+ int toBufferId;
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatus.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatus.aidl
new file mode 100644
index 0000000..13174ff
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatus.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.media.bufferpool2;
+@Backing(type="int") @VintfStability
+enum BufferStatus {
+ NOT_USED = 0,
+ USED = 1,
+ TRANSFER_TO = 2,
+ TRANSFER_FROM = 3,
+ TRANSFER_TIMEOUT = 4,
+ TRANSFER_LOST = 5,
+ TRANSFER_FETCH = 6,
+ TRANSFER_OK = 7,
+ TRANSFER_ERROR = 8,
+ INVALIDATION_ACK = 9,
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatusMessage.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatusMessage.aidl
new file mode 100644
index 0000000..7e79a36
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/BufferStatusMessage.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.media.bufferpool2;
+@FixedSize @VintfStability
+parcelable BufferStatusMessage {
+ long transactionId;
+ int bufferId;
+ android.hardware.media.bufferpool2.BufferStatus status;
+ long connectionId;
+ long targetConnectionId;
+ long timestampUs;
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IAccessor.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IAccessor.aidl
new file mode 100644
index 0000000..4053797
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IAccessor.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.media.bufferpool2;
+@VintfStability
+interface IAccessor {
+ android.hardware.media.bufferpool2.IAccessor.ConnectionInfo connect(in android.hardware.media.bufferpool2.IObserver observer);
+ @VintfStability
+ parcelable ConnectionInfo {
+ android.hardware.media.bufferpool2.IConnection connection;
+ long connectionId;
+ int msgId;
+ android.hardware.common.fmq.MQDescriptor<android.hardware.media.bufferpool2.BufferStatusMessage,android.hardware.common.fmq.SynchronizedReadWrite> toFmqDesc;
+ android.hardware.common.fmq.MQDescriptor<android.hardware.media.bufferpool2.BufferInvalidationMessage,android.hardware.common.fmq.UnsynchronizedWrite> fromFmqDesc;
+ }
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IClientManager.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IClientManager.aidl
new file mode 100644
index 0000000..54896d4
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IClientManager.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.media.bufferpool2;
+@VintfStability
+interface IClientManager {
+ long registerSender(in android.hardware.media.bufferpool2.IAccessor bufferPool);
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IConnection.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IConnection.aidl
new file mode 100644
index 0000000..300fcba
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IConnection.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.media.bufferpool2;
+@VintfStability
+interface IConnection {
+ android.hardware.media.bufferpool2.IConnection.FetchResult[] fetch(in android.hardware.media.bufferpool2.IConnection.FetchInfo[] fetchInfos);
+ parcelable FetchInfo {
+ long transactionId;
+ int bufferId;
+ }
+ union FetchResult {
+ android.hardware.media.bufferpool2.Buffer buffer;
+ android.hardware.media.bufferpool2.ResultStatus failure;
+ }
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IObserver.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IObserver.aidl
new file mode 100644
index 0000000..2d8cffe
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/IObserver.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.media.bufferpool2;
+@VintfStability
+interface IObserver {
+ oneway void onMessage(in long connectionId, in int msgId);
+}
diff --git a/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/ResultStatus.aidl b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/ResultStatus.aidl
new file mode 100644
index 0000000..7370998
--- /dev/null
+++ b/media/bufferpool/aidl/aidl_api/android.hardware.media.bufferpool2/current/android/hardware/media/bufferpool2/ResultStatus.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.media.bufferpool2;
+@VintfStability
+parcelable ResultStatus {
+ int resultStatus;
+ const int OK = 0;
+ const int NO_MEMORY = 1;
+ const int ALREADY_EXISTS = 2;
+ const int NOT_FOUND = 3;
+ const int CRITICAL_ERROR = 4;
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/Buffer.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/Buffer.aidl
new file mode 100644
index 0000000..976f674
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/Buffer.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.media.bufferpool2;
+
+import android.hardware.common.NativeHandle;
+
+/**
+ * Generic buffer for fast recycling for media/stagefright.
+ *
+ * During media pipeline buffer references are created, shared and
+ * destroyed frequently. The underlying buffers are allocated on demand
+ * by a buffer pool, and are recycled to the buffer pool when they are
+ * no longer referenced by the clients.
+ *
+ * E.g. ion or gralloc buffer
+ */
+@VintfStability
+parcelable Buffer {
+ int id;
+ NativeHandle buffer;
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferInvalidationMessage.aidl
new file mode 100644
index 0000000..ad03cd5
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferInvalidationMessage.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.
+ */
+
+package android.hardware.media.bufferpool2;
+
+/*
+ * Buffer pool sends a buffer invalidation message to clients in order to
+ * ensure fast reclamation of the buffers. Buffer pool implementation on
+ * clients must release the invalidated buffers right away after finishing
+ * the use of buffers upon receiving a buffer invalidation message.
+ * Users cannot delay or control timing of the handling/reception of
+ * invalidation messages. Buffer pool implementation must guarantee timely
+ * handling of invalidation messages.
+ */
+@VintfStability
+@FixedSize
+parcelable BufferInvalidationMessage {
+ int messageId;
+ /**
+ * Buffers from fromBufferId to toBufferId must be invalidated.
+ * fromBufferId is inclusive, but toBufferId is not inclusive.
+ * If fromBufferId > toBufferID, wrap happens. In that case
+ * the wrap is based on UINT32_MAX.
+ */
+ int fromBufferId;
+ int toBufferId;
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatus.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatus.aidl
new file mode 100644
index 0000000..b63aee2
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatus.aidl
@@ -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.media.bufferpool2;
+
+/**
+ * Buffer ownership status for the specified client.
+ * Buffer transfer status for the specified buffer transafer transaction.
+ * BufferStatus is posted along with BufferStatusMessage from a client to
+ * the buffer pool for synchronization after status change.
+ */
+@VintfStability
+@Backing(type="int")
+enum BufferStatus {
+ /**
+ * No longer used by the specified client.
+ */
+ NOT_USED = 0,
+ /**
+ * Buffer is acquired by the specified client.
+ */
+ USED = 1,
+ /**
+ * Buffer is sent by the specified client.
+ */
+ TRANSFER_TO = 2,
+ /**
+ * Buffer transfer is acked by the receiver client.
+ */
+ TRANSFER_FROM = 3,
+ /**
+ * Buffer transfer is timed out by receiver client.
+ */
+ TRANSFER_TIMEOUT = 4,
+ /**
+ * Buffer transfer is not acked by the receiver.
+ */
+ TRANSFER_LOST = 5,
+ /**
+ * Buffer fetch request from the client.
+ */
+ TRANSFER_FETCH = 6,
+ /**
+ * Buffer transaction succeeded.
+ */
+ TRANSFER_OK = 7,
+ /**
+ * Buffer transaction failure.
+ */
+ TRANSFER_ERROR = 8,
+ /**
+ * Buffer invalidation ack.
+ */
+ INVALIDATION_ACK = 9,
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatusMessage.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatusMessage.aidl
new file mode 100644
index 0000000..e3fd8f0
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/BufferStatusMessage.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.media.bufferpool2;
+
+import android.hardware.media.bufferpool2.BufferStatus;
+
+/**
+ * Buffer ownership status change message. This message is
+ * sent via fmq to the buffer pool from client processes.
+ */
+@VintfStability
+@FixedSize
+parcelable BufferStatusMessage {
+ /**
+ * Transaction Id = (SenderId : sender local transaction Id)
+ * Transaction Id is created from sender and posted via fmq within
+ * TRANSFER_TO message.
+ */
+ long transactionId;
+ int bufferId;
+ BufferStatus status;
+ /**
+ * Used by the buffer pool, not by client.
+ */
+ long connectionId;
+ /**
+ * Valid only when TRANSFER_TO is posted.
+ */
+ long targetConnectionId;
+ /**
+ * Used by the buffer pool, not by client.
+ * Monotonic timestamp in Us since fixed point in time as decided
+ * by the sender of the message
+ */
+ long timestampUs;
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/IAccessor.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IAccessor.aidl
new file mode 100644
index 0000000..0fa5961
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IAccessor.aidl
@@ -0,0 +1,106 @@
+/*
+ * 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.media.bufferpool2;
+
+import android.hardware.common.fmq.MQDescriptor;
+import android.hardware.common.fmq.SynchronizedReadWrite;
+import android.hardware.common.fmq.UnsynchronizedWrite;
+
+
+import android.hardware.media.bufferpool2.BufferInvalidationMessage;
+import android.hardware.media.bufferpool2.BufferStatusMessage;
+import android.hardware.media.bufferpool2.IConnection;
+import android.hardware.media.bufferpool2.IObserver;
+
+/**
+ * IAccessor creates IConnection which is used from IClientManager in order to
+ * use functionality of the specified buffer pool.
+ */
+@VintfStability
+interface IAccessor {
+ @VintfStability
+ /**
+ * Connection information between the bufferpool process and the receiver
+ * process. The information is used from the receiver process in order to
+ * receive buffers from the bufferpool process.
+ */
+ parcelable ConnectionInfo {
+ /**
+ * The interface to get shared buffers from the bufferpool.
+ */
+ IConnection connection;
+ /**
+ * The identifier for a (sender/receiver) pair during buffer transfer.
+ * This is system wide unique.
+ */
+ long connectionId;
+ /**
+ * Id of the most recent message from bufferpool. This is monotonic.
+ */
+ int msgId;
+ /**
+ * The FMQ descriptor for sending buffer status messages back to bufferpool
+ */
+ MQDescriptor<BufferStatusMessage, SynchronizedReadWrite> toFmqDesc;
+ /**
+ * The FMQ descriptor for receiving buffer invalidation messages from bufferpool
+ */
+ MQDescriptor<BufferInvalidationMessage, UnsynchronizedWrite> fromFmqDesc;
+ }
+
+ /**
+ * Registers a new client and creates IConnection to the buffer pool for
+ * the client. IConnection and FMQ are used by IClientManager in order to
+ * communicate with the buffer pool. Via FMQ IClientManager sends
+ * BufferStatusMessage(s) to the buffer pool.
+ *
+ * FMQ is used to send buffer ownership status changes to a buffer pool
+ * from a buffer pool client. A buffer pool synchronizes FMQ messages when
+ * there is an aidl request from the clients. Every client has its own
+ * connection and FMQ to communicate with the buffer pool. So sending an
+ * FMQ message on behalf of other clients is not possible.
+ *
+ * FMQ messages are sent when a buffer is acquired or released. Also, FMQ
+ * messages are sent when a buffer is transferred from a client to another
+ * client. FMQ has its own ID from a buffer pool. A client is specified
+ * with the ID.
+ *
+ * To transfer a buffer, a sender must send an FMQ message. The message
+ * must include a receiver's ID and a transaction ID. A receiver must send
+ * the transaction ID to fetch a buffer from a buffer pool. Since the
+ * sender already registered the receiver via an FMQ message, The buffer
+ * pool must verify the receiver with the transaction ID. In order to
+ * prevent faking a receiver, a connection to a buffer pool from client is
+ * made and kept private. Also part of transaction ID is a sender ID in
+ * order to prevent fake transactions from other clients. This must be
+ * verified with an FMQ message from a buffer pool.
+ *
+ * @param observer The buffer pool event observer from the client.
+ * Observer is provided to ensure FMQ messages are processed even when
+ * client processes are idle. Buffer invalidation caused by
+ * reconfiguration does not call observer. Buffer invalidation caused
+ * by termination of pipeline call observer in order to ensure
+ * invalidation is done after pipeline completion.
+ * @return ConnectionInfo The information regarding the established
+ * connection
+ * @@throws ServiceSpecificException with one of the following values:
+ * ResultStatus::NO_MEMORY - Memory allocation failure occurred.
+ * ResultStatus::ALREADY_EXISTS - A connection was already made.
+ * ResultStatus::CRITICAL_ERROR - Other errors.
+ */
+ ConnectionInfo connect(in IObserver observer);
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/IClientManager.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IClientManager.aidl
new file mode 100644
index 0000000..bf36e25
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IClientManager.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.media.bufferpool2;
+
+import android.hardware.media.bufferpool2.IAccessor;
+
+/**
+ * IClientManager manages IConnection(s) inside a process. A locally
+ * created IConnection represents a communication node(receiver) with the
+ * specified buffer pool(IAccessor).
+ * IConnection(s) are not exposed to other processes(IClientManager).
+ * IClientManager instance must be unique within a process.
+ */
+@VintfStability
+interface IClientManager {
+ /**
+ * Sets up a buffer receiving communication node for the specified
+ * buffer pool. A manager must create a IConnection to the buffer
+ * pool if it does not already have a connection.
+ *
+ * @param bufferPool a buffer pool which is specified with the IAccessor.
+ * The specified buffer pool is the owner of received buffers.
+ * @return the Id of the communication node to the buffer pool.
+ * This id is used in FMQ to notify IAccessor that a buffer has been
+ * sent to that connection during transfers.
+ * @throws ServiceSpecificException with one of the following values:
+ * ResultStatus::NO_MEMORY - Memory allocation failure occurred.
+ * ResultStatus::ALREADY_EXISTS - A sender was registered already.
+ * ResultStatus::CRITICAL_ERROR - Other errors.
+ */
+ long registerSender(in IAccessor bufferPool);
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/IConnection.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IConnection.aidl
new file mode 100644
index 0000000..d869f47
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IConnection.aidl
@@ -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.media.bufferpool2;
+
+import android.hardware.media.bufferpool2.Buffer;
+import android.hardware.media.bufferpool2.ResultStatus;
+
+/**
+ * A connection to a buffer pool which handles requests from a buffer pool
+ * client. The connection must be made in order to receive buffers from
+ * other buffer pool clients.
+ */
+@VintfStability
+interface IConnection {
+
+ parcelable FetchInfo {
+ /**
+ * Unique transaction id for buffer transferring.
+ */
+ long transactionId;
+ /**
+ * Id of the buffer to be fetched.
+ */
+ int bufferId;
+ }
+
+ union FetchResult {
+ /**
+ * The fetched buffer on successful fetch.
+ */
+ Buffer buffer;
+ /**
+ * The reason of the request failure. Possible values are below.
+ *
+ * ResultStatus::NOT_FOUND - A buffer was not found due to invalidation.
+ * ResultStatus::CRITICAL_ERROR - Other errors.
+ */
+ ResultStatus failure;
+ }
+
+ /**
+ * Retrieves buffers using an array of FetchInfo.
+ * Each element of FetchInfo array contains a bufferId and a transactionId
+ * for each buffer to fetch. The method must be called from receiving side of buffers
+ * during transferring only when the specified buffer is neither cached nor used.
+ *
+ * The method could have partial failures, in the case other successfully fetched buffers
+ * will be in returned result along with the failures. The order of the returned result
+ * will be the same with the fetchInfos.
+ *
+ * @param fetchInfos information of buffers to fetch
+ * @return Requested buffers.
+ * If there are failures, reasons of failures are also included.
+ * @throws ServiceSpecificException with one of the following values:
+ * ResultStatus::NO_MEMORY - Memory allocation failure occurred.
+ * ResultStatus::CRITICAL_ERROR - Other errors.
+ */
+ FetchResult[] fetch(in FetchInfo[] fetchInfos);
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/IObserver.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IObserver.aidl
new file mode 100644
index 0000000..07d1c3e
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/IObserver.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.media.bufferpool2;
+
+/**
+ * IObserver listens on notifications from the buffer pool. On receiving
+ * notifications, FMQ messages from the specific buffer pool which are already
+ * in the FMQ are processed.
+ */
+@VintfStability
+interface IObserver {
+ /**
+ * The specific buffer pool sent a message to the client. Calling this
+ * method from the buffer pool enforces a buffer pool client process the
+ * message.
+ *
+ * @param connectionId the connection Id of the specific buffer pool client
+ * @param msgId Id of the most recent message
+ */
+ oneway void onMessage(in long connectionId, in int msgId);
+}
diff --git a/media/bufferpool/aidl/android/hardware/media/bufferpool2/ResultStatus.aidl b/media/bufferpool/aidl/android/hardware/media/bufferpool2/ResultStatus.aidl
new file mode 100644
index 0000000..162f9a7
--- /dev/null
+++ b/media/bufferpool/aidl/android/hardware/media/bufferpool2/ResultStatus.aidl
@@ -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.media.bufferpool2;
+
+@VintfStability
+parcelable ResultStatus {
+ const int OK = 0;
+ const int NO_MEMORY = 1;
+ const int ALREADY_EXISTS = 2;
+ const int NOT_FOUND = 3;
+ const int CRITICAL_ERROR = 4;
+
+ int resultStatus;
+}
diff --git a/media/c2/aidl/Android.bp b/media/c2/aidl/Android.bp
new file mode 100644
index 0000000..10867c0
--- /dev/null
+++ b/media/c2/aidl/Android.bp
@@ -0,0 +1,29 @@
+// This is the expected build file, but it may not be right in all cases
+
+aidl_interface {
+ name: "android.hardware.media.c2",
+ vendor_available: true,
+ srcs: ["android/hardware/media/c2/*.aidl"],
+ include_dirs: [
+ "frameworks/native/aidl/gui",
+ ],
+ imports: [
+ "android.hardware.common-V2",
+ "android.hardware.media.bufferpool2-V1",
+ ],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ enabled: false,
+ },
+ ndk: {
+ enabled: true,
+ additional_shared_libraries: [
+ "libnativewindow",
+ ],
+ },
+ },
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl
new file mode 100644
index 0000000..460ff97
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/BaseBlock.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+union BaseBlock {
+ android.hardware.common.NativeHandle nativeBlock;
+ android.hardware.media.bufferpool2.BufferStatusMessage pooledBlock;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.aidl
new file mode 100644
index 0000000..7b3005e
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Block.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.media.c2;
+@VintfStability
+parcelable Block {
+ int index;
+ android.hardware.media.c2.Params meta;
+ android.hardware.common.NativeHandle fence;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl
new file mode 100644
index 0000000..b632932
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Buffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Buffer {
+ android.hardware.media.c2.Params info;
+ android.hardware.media.c2.Block[] blocks;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl
new file mode 100644
index 0000000..d0e4cbf
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldDescriptor.aidl
@@ -0,0 +1,62 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldDescriptor {
+ android.hardware.media.c2.FieldId fieldId;
+ android.hardware.media.c2.FieldDescriptor.Type type;
+ int structIndex;
+ int extent;
+ String name;
+ android.hardware.media.c2.FieldDescriptor.NamedValue[] namedValues;
+ @Backing(type="int") @VintfStability
+ enum Type {
+ NO_INIT = 0,
+ INT32 = 1,
+ UINT32 = 2,
+ CNTR32 = 3,
+ INT64 = 4,
+ UINT64 = 5,
+ CNTR64 = 6,
+ FLOAT = 7,
+ STRING = 256,
+ BLOB = 257,
+ STRUCT = 131072,
+ }
+ @VintfStability
+ parcelable NamedValue {
+ String name;
+ long value;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl
new file mode 100644
index 0000000..935b85d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldId.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldId {
+ int offset;
+ int sizeBytes;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl
new file mode 100644
index 0000000..69060be
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValues.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.media.c2;
+@VintfStability
+union FieldSupportedValues {
+ boolean empty;
+ android.hardware.media.c2.ValueRange range;
+ long[] values;
+ long[] flags;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
new file mode 100644
index 0000000..22f7c84
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.c2;
+@VintfStability
+parcelable FieldSupportedValuesQuery {
+ android.hardware.media.c2.ParamField field;
+ android.hardware.media.c2.FieldSupportedValuesQuery.Type type;
+ @Backing(type="int") @VintfStability
+ enum Type {
+ POSSIBLE = 0,
+ CURRENT = 1,
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
new file mode 100644
index 0000000..187e3eb
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable FieldSupportedValuesQueryResult {
+ android.hardware.media.c2.Status status;
+ android.hardware.media.c2.FieldSupportedValues values;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.aidl
new file mode 100644
index 0000000..e73b05e
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/FrameData.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.media.c2;
+@VintfStability
+parcelable FrameData {
+ int flags;
+ android.hardware.media.c2.WorkOrdinal ordinal;
+ android.hardware.media.c2.Buffer[] buffers;
+ android.hardware.media.c2.Params configUpdate;
+ android.hardware.media.c2.InfoBuffer[] infoBuffers;
+ const int DROP_FRAME = 1;
+ const int END_OF_STREAM = 2;
+ const int DISCARD_FRAME = 4;
+ const int FLAG_INCOMPLETE = 8;
+ const int CODEC_CONFIG = -2147483648;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
new file mode 100644
index 0000000..7ed09af
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponent.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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.media.c2;
+@VintfStability
+interface IComponent {
+ android.hardware.common.NativeHandle configureVideoTunnel(in int avSyncHwId);
+ android.hardware.media.c2.IComponent.BlockPool createBlockPool(in int allocatorId);
+ void destroyBlockPool(in long blockPoolId);
+ void drain(in boolean withEos);
+ android.hardware.media.c2.WorkBundle flush();
+ android.hardware.media.c2.IComponentInterface getInterface();
+ void queue(in android.hardware.media.c2.WorkBundle workBundle);
+ void release();
+ void reset();
+ void setOutputSurface(in long blockPoolId, in android.view.Surface surface, in android.hardware.media.c2.SurfaceSyncObj syncObject);
+ void start();
+ void stop();
+ parcelable BlockPool {
+ long blockPoolId;
+ android.hardware.media.c2.IConfigurable configurable;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.aidl
new file mode 100644
index 0000000..2350dae
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentInterface.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.media.c2;
+@VintfStability
+interface IComponentInterface {
+ android.hardware.media.c2.IConfigurable getConfigurable();
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl
new file mode 100644
index 0000000..f6f2a63
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentListener.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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.media.c2;
+@VintfStability
+interface IComponentListener {
+ oneway void onError(in android.hardware.media.c2.Status status, in int errorCode);
+ oneway void onFramesRendered(in android.hardware.media.c2.IComponentListener.RenderedFrame[] renderedFrames);
+ oneway void onInputBuffersReleased(in android.hardware.media.c2.IComponentListener.InputBuffer[] inputBuffers);
+ oneway void onTripped(in android.hardware.media.c2.SettingResult[] settingResults);
+ oneway void onWorkDone(in android.hardware.media.c2.WorkBundle workBundle);
+ @VintfStability
+ parcelable InputBuffer {
+ long frameIndex;
+ int arrayIndex;
+ }
+ @VintfStability
+ parcelable RenderedFrame {
+ long bufferQueueId;
+ int slotId;
+ long timestampNs;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl
new file mode 100644
index 0000000..35532be
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IComponentStore.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.c2;
+@VintfStability
+interface IComponentStore {
+ void copyBuffer(in android.hardware.media.c2.Buffer src, in android.hardware.media.c2.Buffer dst);
+ android.hardware.media.c2.IComponent createComponent(in String name, in android.hardware.media.c2.IComponentListener listener, in android.hardware.media.bufferpool2.IClientManager pool);
+ android.hardware.media.c2.IComponentInterface createInterface(in String name);
+ android.hardware.media.c2.IConfigurable getConfigurable();
+ android.hardware.media.bufferpool2.IClientManager getPoolClientManager();
+ android.hardware.media.c2.StructDescriptor[] getStructDescriptors(in int[] indices);
+ android.hardware.media.c2.IComponentStore.ComponentTraits[] listComponents();
+ @VintfStability
+ parcelable ComponentTraits {
+ String name;
+ android.hardware.media.c2.IComponentStore.ComponentTraits.Domain domain;
+ android.hardware.media.c2.IComponentStore.ComponentTraits.Kind kind;
+ int rank;
+ String mediaType;
+ String[] aliases;
+ @Backing(type="int") @VintfStability
+ enum Kind {
+ OTHER = 0,
+ DECODER = 1,
+ ENCODER = 2,
+ }
+ @Backing(type="int") @VintfStability
+ enum Domain {
+ OTHER = 0,
+ VIDEO = 1,
+ AUDIO = 2,
+ IMAGE = 3,
+ }
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl
new file mode 100644
index 0000000..32f5abd
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/IConfigurable.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.media.c2;
+@VintfStability
+interface IConfigurable {
+ android.hardware.media.c2.IConfigurable.ConfigResult config(in android.hardware.media.c2.Params inParams, in boolean mayBlock);
+ int getId();
+ String getName();
+ android.hardware.media.c2.Params query(in int[] indices, in boolean mayBlock);
+ android.hardware.media.c2.ParamDescriptor[] querySupportedParams(in int start, in int count);
+ android.hardware.media.c2.FieldSupportedValuesQueryResult[] querySupportedValues(in android.hardware.media.c2.FieldSupportedValuesQuery[] inFields, in boolean mayBlock);
+ @VintfStability
+ parcelable ConfigResult {
+ android.hardware.media.c2.Params params;
+ android.hardware.media.c2.SettingResult[] failures;
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl
new file mode 100644
index 0000000..94cd77d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/InfoBuffer.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable InfoBuffer {
+ int index;
+ android.hardware.media.c2.Buffer buffer;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl
new file mode 100644
index 0000000..04c869c
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamDescriptor.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable ParamDescriptor {
+ int index;
+ int attrib;
+ String name;
+ int[] dependencies;
+ const int ATTRIBUTE_REQUIRED = 1;
+ const int ATTRIBUTE_PERSISTENT = 2;
+ const int ATTRIBUTE_STRICT = 4;
+ const int ATTRIBUTE_READ_ONLY = 8;
+ const int ATTRIBUTE_HIDDEN = 16;
+ const int ATTRIBUTE_INTERNAL = 32;
+ const int ATTRIBUTE_CONST = 64;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl
new file mode 100644
index 0000000..13d2522
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamField.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable ParamField {
+ int index;
+ android.hardware.media.c2.FieldId fieldId;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl
new file mode 100644
index 0000000..5a2821c
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ParamFieldValues.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable ParamFieldValues {
+ android.hardware.media.c2.ParamField paramOrField;
+ android.hardware.media.c2.FieldSupportedValues[] values;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.aidl
new file mode 100644
index 0000000..7d363c0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Params.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.media.c2;
+@VintfStability
+parcelable Params {
+ byte[] params;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl
new file mode 100644
index 0000000..f9e6a93
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SettingResult.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable SettingResult {
+ android.hardware.media.c2.SettingResult.Failure failure;
+ android.hardware.media.c2.ParamFieldValues field;
+ android.hardware.media.c2.ParamFieldValues[] conflicts;
+ @Backing(type="int") @VintfStability
+ enum Failure {
+ BAD_TYPE = 0,
+ BAD_PORT = 1,
+ BAD_INDEX = 2,
+ READ_ONLY = 3,
+ MISMATCH = 4,
+ BAD_VALUE = 5,
+ CONFLICT = 6,
+ UNSUPPORTED = 7,
+ INFO_BAD_VALUE = 8,
+ INFO_CONFLICT = 9,
+ }
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl
new file mode 100644
index 0000000..ad07677
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Status.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.media.c2;
+@VintfStability
+parcelable Status {
+ int status;
+ const int OK = 0;
+ const int BAD_VALUE = -22;
+ const int BAD_INDEX = -75;
+ const int CANNOT_DO = -2147483646;
+ const int DUPLICATE = -17;
+ const int NOT_FOUND = -2;
+ const int BAD_STATE = -38;
+ const int BLOCKING = -9930;
+ const int NO_MEMORY = -12;
+ const int REFUSED = -1;
+ const int TIMED_OUT = -110;
+ const int OMITTED = -74;
+ const int CORRUPTED = -2147483648;
+ const int NO_INIT = -19;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl
new file mode 100644
index 0000000..58268e0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/StructDescriptor.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable StructDescriptor {
+ int type;
+ android.hardware.media.c2.FieldDescriptor[] fields;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SurfaceSyncObj.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SurfaceSyncObj.aidl
new file mode 100644
index 0000000..1c9bf8d
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/SurfaceSyncObj.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable SurfaceSyncObj {
+ android.hardware.common.NativeHandle syncMemory;
+ long bqId;
+ int generationId;
+ long consumerUsage;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl
new file mode 100644
index 0000000..db71ce0
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/ValueRange.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.c2;
+@VintfStability
+parcelable ValueRange {
+ long min;
+ long max;
+ long step;
+ long num;
+ long denom;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl
new file mode 100644
index 0000000..a534348
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Work.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.media.c2;
+@VintfStability
+parcelable Work {
+ byte[] chainInfo;
+ android.hardware.media.c2.FrameData input;
+ android.hardware.media.c2.Worklet[] worklets;
+ int workletsProcessed;
+ android.hardware.media.c2.Status result;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl
new file mode 100644
index 0000000..84708a8
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkBundle.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable WorkBundle {
+ android.hardware.media.c2.Work[] works;
+ android.hardware.media.c2.BaseBlock[] baseBlocks;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.aidl
new file mode 100644
index 0000000..2833df3
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/WorkOrdinal.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.media.c2;
+@VintfStability
+parcelable WorkOrdinal {
+ long timestampUs;
+ long frameIndex;
+ long customOrdinal;
+}
diff --git a/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl
new file mode 100644
index 0000000..a79abf2
--- /dev/null
+++ b/media/c2/aidl/aidl_api/android.hardware.media.c2/current/android/hardware/media/c2/Worklet.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.media.c2;
+@VintfStability
+parcelable Worklet {
+ int componentId;
+ byte[] tunings;
+ android.hardware.media.c2.SettingResult[] failures;
+ android.hardware.media.c2.FrameData output;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl b/media/c2/aidl/android/hardware/media/c2/BaseBlock.aidl
new file mode 100644
index 0000000..8b8b8e0
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/BaseBlock.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.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.common.NativeHandle;
+
+/**
+ * Storage type for `BaseBlock`.
+ *
+ * A `BaseBlock` is a representation of a codec memory block. Coded data,
+ * decoded data, codec-specific data, and other codec-related data are all sent
+ * in the form of BaseBlocks.
+ */
+@VintfStability
+union BaseBlock {
+ /**
+ * #nativeBlock is the opaque representation of a buffer.
+ */
+ NativeHandle nativeBlock;
+ /**
+ * #pooledBlock is a reference to a buffer handled by a BufferPool.
+ */
+ android.hardware.media.bufferpool2.BufferStatusMessage pooledBlock;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Block.aidl b/media/c2/aidl/android/hardware/media/c2/Block.aidl
new file mode 100644
index 0000000..34aa7b1
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Block.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.common.NativeHandle;
+import android.hardware.media.c2.Params;
+
+/**
+ * Reference to a @ref BaseBlock within a @ref WorkBundle.
+ *
+ * `Block` contains additional attributes that `BaseBlock` does not. These
+ * attributes may differ among `Block` objects that refer to the same
+ * `BaseBlock` in the same `WorkBundle`.
+ */
+@VintfStability
+parcelable Block {
+ /**
+ * Identity of a `BaseBlock` within a `WorkBundle`. This is an index into
+ * #WorkBundle.baseBlocks.
+ */
+ int index;
+ /**
+ * Metadata associated with this `Block`.
+ */
+ Params meta;
+ /**
+ * Fence for synchronizing `Block` access.
+ */
+ NativeHandle fence;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Buffer.aidl b/media/c2/aidl/android/hardware/media/c2/Buffer.aidl
new file mode 100644
index 0000000..d2dcf2d
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Buffer.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.Block;
+import android.hardware.media.c2.Params;
+
+/**
+ * A codec buffer, which is a collection of @ref Block objects and metadata.
+ *
+ * This is a part of @ref FrameData.
+ */
+@VintfStability
+parcelable Buffer {
+ /**
+ * Metadata associated with the buffer.
+ */
+ Params info;
+ /**
+ * Blocks contained in the buffer.
+ */
+ Block[] blocks;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
new file mode 100644
index 0000000..a2774ec
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldDescriptor.aidl
@@ -0,0 +1,103 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FieldId;
+
+/**
+ * Description of a field inside a C2Param structure.
+ */
+@VintfStability
+parcelable FieldDescriptor {
+ /**
+ * Possible types of the field.
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum Type {
+ NO_INIT = 0,
+ INT32,
+ UINT32,
+ CNTR32,
+ INT64,
+ UINT64,
+ CNTR64,
+ FLOAT,
+ /**
+ * Fixed-size string (POD).
+ */
+ STRING = 0x100,
+ /**
+ * A blob has no sub-elements and can be thought of as an array of
+ * bytes. However, bytes cannot be individually addressed by clients.
+ */
+ BLOB,
+ /**
+ * The field is a structure that may contain other fields.
+ */
+ STRUCT = 0x20000,
+ }
+ /**
+ * Named value type. This is used for defining an enum value for a numeric
+ * type.
+ */
+ @VintfStability
+ parcelable NamedValue {
+ /**
+ * Name of the enum value. This must be unique for each enum value in
+ * the same field.
+ */
+ String name;
+ /**
+ * Underlying value of the enum value. Multiple enum names may have the
+ * same underlying value.
+ */
+ long value;
+ }
+ /**
+ * Location of the field in the C2Param structure
+ */
+ FieldId fieldId;
+ /**
+ * Type of the field.
+ */
+ Type type;
+ /**
+ * If #type is #Type.STRUCT, #structIndex is the C2Param structure index;
+ * otherwise, #structIndex is not used.
+ */
+ int structIndex;
+ /**
+ * Extent of the field.
+ * - For a non-array field, #extent is 1.
+ * - For a fixed-length array field, #extent is the length. An array field
+ * of length 1 is indistinguishable from a non-array field.
+ * - For a variable-length array field, #extent is 0. This can only occur as
+ * the last member of a C2Param structure.
+ */
+ int extent;
+ /**
+ * Name of the field. This must be unique for each field in the same
+ * structure.
+ */
+ String name;
+ /**
+ * List of enum values. This is not used when #type is not one of the
+ * numeric types.
+ */
+ NamedValue[] namedValues;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldId.aidl b/media/c2/aidl/android/hardware/media/c2/FieldId.aidl
new file mode 100644
index 0000000..68bf058
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldId.aidl
@@ -0,0 +1,35 @@
+/*
+ * 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.media.c2;
+
+/**
+ * Identifying information of a field relative to a known C2Param structure.
+ *
+ * Within a given C2Param structure, each field is uniquely identified by @ref
+ * FieldId.
+ */
+@VintfStability
+parcelable FieldId {
+ /**
+ * Offset of the field in bytes.
+ */
+ int offset;
+ /**
+ * Size of the field in bytes.
+ */
+ int sizeBytes;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
new file mode 100644
index 0000000..6c2033b
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValues.aidl
@@ -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 android.hardware.media.c2;
+
+import android.hardware.media.c2.ValueRange;
+
+/*
+ * Description of supported values for a field of C2Param.
+ *
+ * This can be a continuous range or a discrete set of values.
+ *
+ * The intended type of values must be made clear in the context where
+ * `FieldSupportedValues` is used.
+ */
+@VintfStability
+union FieldSupportedValues {
+ /**
+ * No supported values
+ */
+ boolean empty;
+ /**
+ * Numeric range, described in a #ValueRange structure
+ */
+ ValueRange range;
+ /**
+ * List of values
+ */
+ long[] values;
+ /**
+ * List of flags that can be OR-ed.
+ *
+ * The list contains { min-mask, flag1, flag2... }. Basically, the first
+ * value is the required set of flags to be set, and the rest of the values are flags that can
+ * be set independently. FLAGS is only supported for integral types. Supported flags should
+ * not overlap, as it can make validation non-deterministic. The standard validation method
+ * is that starting from the original value, if each flag is removed when fully present (the
+ * min-mask must be fully present), we shall arrive at 0.
+ */
+ long[] flags;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.aidl
new file mode 100644
index 0000000..bdaaef6
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQuery.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.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.media.c2.ParamField;
+
+/**
+ * Query information for supported values of a field. This is used as input to
+ * IConfigurable::querySupportedValues().
+ */
+@VintfStability
+parcelable FieldSupportedValuesQuery {
+ @VintfStability
+ @Backing(type="int")
+ enum Type {
+ /**
+ * Query all possible values regardless of other settings.
+ */
+ POSSIBLE = 0,
+ /**
+ * Query currently possible values given dependent settings.
+ */
+ CURRENT,
+ }
+ /**
+ * Identity of the field to query.
+ */
+ ParamField field;
+ /**
+ * Type of the query. See #Type for more information.
+ */
+ Type type;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
new file mode 100644
index 0000000..b5c28c6
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FieldSupportedValuesQueryResult.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.media.c2.FieldSupportedValues;
+import android.hardware.media.c2.Status;
+
+/**
+ * This structure is used to hold the result from
+ * IConfigurable::querySupportedValues().
+ */
+@VintfStability
+parcelable FieldSupportedValuesQueryResult {
+ /**
+ * Result of the query. Possible values are
+ * - `Status::OK`: The query was successful.
+ * - `Status::BAD_STATE`: The query was requested when the `IConfigurable` instance
+ * was in a bad state.
+ * - `Status::BAD_INDEX`: The requested field was not recognized.
+ * - `Status::TIMED_OUT`: The query could not be completed in a timely manner.
+ * - `Status::BLOCKING`: The query must block, but the parameter `mayBlock` in the
+ * call to `querySupportedValues()` was `false`.
+ * - `Status::CORRUPTED`: Some unknown error occurred.
+ */
+ Status status;
+ /**
+ * Supported values. This is meaningful only when #status is `OK`.
+ */
+ FieldSupportedValues values;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/FrameData.aidl b/media/c2/aidl/android/hardware/media/c2/FrameData.aidl
new file mode 100644
index 0000000..15c1b6d
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/FrameData.aidl
@@ -0,0 +1,97 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.Buffer;
+import android.hardware.media.c2.InfoBuffer;
+import android.hardware.media.c2.Params;
+import android.hardware.media.c2.WorkOrdinal;
+
+/**
+ * Data for an input frame or an output frame.
+ *
+ * This structure represents a @e frame with its metadata. A @e frame consists
+ * of an ordered set of buffers, configuration changes, and info buffers along
+ * with some non-configuration metadata.
+ *
+ * @note `FrameData` is the HIDL counterpart of `C2FrameData` in the Codec 2.0
+ * standard.
+ */
+@VintfStability
+parcelable FrameData {
+ /** List of frame flags */
+ /**
+ * For input frames: no output frame shall be generated when processing
+ * this frame, but metadata must still be processed.
+ *
+ * For output frames: this frame must be discarded but metadata is still
+ * valid.
+ */
+ const int DROP_FRAME = (1 << 0);
+ /**
+ * This frame is the last frame of the current stream. Further frames
+ * are part of a new stream.
+ */
+ const int END_OF_STREAM = (1 << 1);
+ /**
+ * This frame must be discarded with its metadata.
+ *
+ * This flag is only set by components, e.g. as a response to the flush
+ * command.
+ */
+ const int DISCARD_FRAME = (1 << 2);
+ /**
+ * This frame is not the last frame produced for the input.
+ *
+ * This flag is normally set by the component - e.g. when an input frame
+ * results in multiple output frames, this flag is set on all but the
+ * last output frame.
+ *
+ * Also, when components are chained, this flag should be propagated
+ * down the work chain. That is, if set on an earlier frame of a
+ * work-chain, it should be propagated to all later frames in that
+ * chain. Additionally, components down the chain could set this flag
+ * even if not set earlier, e.g. if multiple output frames are generated
+ * at that component for the input frame.
+ */
+ const int FLAG_INCOMPLETE = (1 << 3);
+ /**
+ * This frame contains only codec-specific configuration data, and no
+ * actual access unit.
+ */
+ const int CODEC_CONFIG = (1 << 31);
+ /**
+ * Frame flags, as described above.
+ */
+ int flags;
+ /**
+ * @ref WorkOrdinal of the frame.
+ */
+ WorkOrdinal ordinal;
+ /**
+ * List of frame buffers.
+ */
+ Buffer[] buffers;
+ /**
+ * List of configuration updates.
+ */
+ Params configUpdate;
+ /**
+ * List of info buffers.
+ */
+ InfoBuffer[] infoBuffers;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IComponent.aidl b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
new file mode 100644
index 0000000..b3390c3
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IComponent.aidl
@@ -0,0 +1,304 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.common.NativeHandle;
+import android.view.Surface;
+
+import android.hardware.media.c2.IComponentInterface;
+import android.hardware.media.c2.IConfigurable;
+import android.hardware.media.c2.WorkBundle;
+import android.hardware.media.c2.SurfaceSyncObj;
+
+/**
+ * Interface for an AIDL Codec2 component.
+ * Components have two states: stopped and running. The running state has three
+ * sub-states: executing, tripped and error.
+ *
+ * All methods in `IComponent` must not block. If a method call cannot be
+ * completed in a timely manner, it must throw `Status::TIMED_OUT`.
+ */
+@VintfStability
+interface IComponent {
+ /**
+ * The reference object from framwork to HAL C2BlockPool.
+ *
+ * The object will be returned when C2BlockPool is created by a framework
+ * request. The object also can be destroyed using blockPoolId.
+ * Using configurable framework can query/config the object in HAL(IComponent).
+ */
+ parcelable BlockPool {
+ long blockPoolId;
+ IConfigurable configurable;
+ }
+ /**
+ * Configures a component for a tunneled playback mode.
+ *
+ * A successful call to this method puts the component in the *tunneled*
+ * mode. In this mode, the output `Worklet`s returned in
+ * IComponentListener::onWorkDone() may not contain any buffers. The output
+ * buffers are passed directly to the consumer end of a buffer queue whose
+ * producer side is configured with the returned @p sidebandStream passed
+ * to IGraphicBufferProducer::setSidebandStream().
+ *
+ * The component is initially in the non-tunneled mode by default. The
+ * tunneled mode can be toggled on only before the component starts
+ * processing. Once the component is put into the tunneled mode, it shall
+ * stay in the tunneled mode until and only until reset() is called.
+ *
+ * @param avSyncHwId A resource ID for hardware sync. The generator of sync
+ * IDs must ensure that this number is unique among all services at any
+ * given time. For example, if both the audio HAL and the tuner HAL
+ * support this feature, sync IDs from the audio HAL must not clash
+ * with sync IDs from the tuner HAL.
+ * @return Codec-allocated sideband stream NativeHandle. This can
+ * be passed to IGraphicBufferProducer::setSidebandStream() to
+ * establish a direct channel to the consumer.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::OMITTED` - The component does not support video tunneling.
+ * - `Status::BAD_STATE` - The component is already running.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ NativeHandle configureVideoTunnel(in int avSyncHwId);
+
+ /**
+ * Creates a local `C2BlockPool` backed by the given allocator and returns
+ * its id.
+ *
+ * The returned @p blockPoolId is the only way the client can refer to a
+ * `C2BlockPool` object in the component. The id can be passed to
+ * setOutputSurface() or used in some C2Param objects later.
+ *
+ * The created `C2BlockPool` object can be destroyed by calling
+ * destroyBlockPool(), reset() or release(). reset() and release() must
+ * destroy all `C2BlockPool` objects that have been created.
+ *
+ * @param allocatorId Id of a `C2Allocator`.
+ * @param out configurable Configuration interface for the created pool. This
+ * must not be null.
+ * @return Created block pool information. This could be used to config/query and
+ * also be used in setOutputSurface() if the allocator
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Not enough memory to create the pool.
+ * - `Status::BAD_VALUE` - @p allocatorId is not recognized.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ BlockPool createBlockPool(in int allocatorId);
+
+ /**
+ * Destroys a local block pool previously created by createBlockPool().
+ *
+ * @param blockPoolId Id of a `C2BlockPool` that was previously returned by
+ * createBlockPool().
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NOT_FOUND` - The supplied blockPoolId is not valid.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void destroyBlockPool(in long blockPoolId);
+
+ /**
+ * Drains the component, and optionally downstream components. This is a
+ * signalling method; as such it does not wait for any work completion.
+ *
+ * The last `Work` item is marked as "drain-till-here", so the component is
+ * notified not to wait for further `Work` before it processes what is
+ * already queued. This method can also be used to set the end-of-stream
+ * flag after `Work` has been queued. Client can continue to queue further
+ * `Work` immediately after this method returns.
+ *
+ * This method must be supported in running (including tripped) states.
+ *
+ * `Work` that is completed must be returned via
+ * IComponentListener::onWorkDone().
+ *
+ * @param withEos Whether to drain the component with marking end-of-stream.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void drain(in boolean withEos);
+
+ /**
+ * Discards and abandons any pending `Work` items for the component.
+ *
+ * This method must be supported in running (including tripped) states.
+ *
+ * `Work` that could be immediately abandoned/discarded must be returned in
+ * @p flushedWorkBundle. The order in which queued `Work` items are
+ * discarded can be arbitrary.
+ *
+ * `Work` that could not be abandoned or discarded immediately must be
+ * marked to be discarded at the earliest opportunity, and must be returned
+ * via IComponentListener::onWorkDone(). This must be completed within
+ * 500ms.
+ *
+ * @return `WorkBundle` object containing flushed `Work` items.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ WorkBundle flush();
+
+ /**
+ * Returns the @ref IComponentInterface instance associated to this
+ * component.
+ *
+ * An @ref IConfigurable instance for the component can be obtained by calling
+ * IComponentInterface::getConfigurable() on the returned @p intf.
+ *
+ * @return `IComponentInterface` instance. This must not be null.
+ */
+ IComponentInterface getInterface();
+
+ /**
+ * Queues up work for the component.
+ *
+ * This method must be supported in running (including tripped) states.
+ *
+ * It is acceptable for this method to return `OK` and return an error value
+ * using the IComponentListener::onWorkDone() callback.
+ *
+ * @param workBundle `WorkBundle` object containing a list of `Work` objects
+ * to queue to the component.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_INDEX` - Some component id in some `Worklet` is not valid.
+ * - `Status::CANNOT_DO` - The components are not tunneled but some `Work` object
+ * contains tunneling information.
+ * - `Status::NO_MEMORY` - Not enough memory to queue @p workBundle.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void queue(in WorkBundle workBundle);
+
+ /**
+ * Releases the component.
+ *
+ * This method must be supported in stopped state.
+ *
+ * This method destroys the component. Upon return, if @p status is `OK` or
+ * `DUPLICATE`, all resources must have been released.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_STATE` - The component is running.
+ * - `Status::DUPLICATE` - The component is already released.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void release();
+
+ /**
+ * Resets the component.
+ *
+ * This method must be supported in all (including tripped) states other
+ * than released.
+ *
+ * This method must be supported during any other blocking call.
+ *
+ * This method must return within 500ms.
+ *
+ * When this call returns, if @p status is `OK`, all `Work` items must
+ * have been abandoned, and all resources (including `C2BlockPool` objects
+ * previously created by createBlockPool()) must have been released.
+ *
+ * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+ * expected as a response to this call. For all other return values, the
+ * component must be in the stopped state.
+ *
+ * This brings settings back to their default, "guaranteeing" no tripped
+ * state.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_STATE` - Component is in released state.
+ * - `Status::DUPLICATE` - When called during another reset call from another
+ * thread.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void reset();
+
+ /**
+ * Starts using a surface for output with a synchronization object
+ *
+ * This method must not block.
+ *
+ * @param blockPoolId Id of the `C2BlockPool` to be associated with the
+ * output surface.
+ * @param surface Output surface.
+ * @param syncObject synchronization object for buffer allocation between
+ * Framework and Component.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::CANNOT_DO` - The component does not support an output surface.
+ * - `Status::REFUSED` - The output surface cannot be accessed.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void setOutputSurface(in long blockPoolId, in Surface surface,
+ in SurfaceSyncObj syncObject);
+
+ /**
+ * Starts the component.
+ *
+ * This method must be supported in stopped state as well as tripped state.
+ *
+ * If the return value is `OK`, the component must be in the running state.
+ * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+ * expected as a response to this call. Otherwise, the component must be in
+ * the stopped state.
+ *
+ * If a component is in the tripped state and start() is called while the
+ * component configuration still results in a trip, start() must succeed and
+ * a new onTripped() callback must be used to communicate the configuration
+ * conflict that results in the new trip.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_STATE` - Component is not in stopped or tripped state.
+ * - `Status::DUPLICATE` - When called during another start call from another
+ * thread.
+ * - `Status::NO_MEMORY` - Not enough memory to start the component.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void start();
+
+ /**
+ * Stops the component.
+ *
+ * This method must be supported in running (including tripped) state.
+ *
+ * This method must return within 500ms.
+ *
+ * Upon this call, all pending `Work` must be abandoned.
+ *
+ * If the return value is `BAD_STATE` or `DUPLICATE`, no state change is
+ * expected as a response to this call. For all other return values, the
+ * component must be in the stopped state.
+ *
+ * This does not alter any settings and tunings that may have resulted in a
+ * tripped state.
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BAD_STATE` - Component is not in running state.
+ * - `Status::DUPLICATE` - When called during another stop call from another
+ * thread.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void stop();
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentInterface.aidl
new file mode 100644
index 0000000..9db81e6
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentInterface.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.
+ */
+
+package android.hardware.media.c2;
+
+import android.hardware.media.c2.IConfigurable;
+
+/**
+ * Component interface object. This object contains all of the configurations of
+ * a potential or actual component. It can be created and used independently of
+ * an actual Codec2 component to query supported parameters for various
+ * component settings, and configurations for a potential component.
+ *
+ * An actual component exposes this interface via IComponent::getInterface().
+ */
+@VintfStability
+interface IComponentInterface {
+ /**
+ * Returns the @ref IConfigurable instance associated to this component
+ * interface.
+ *
+ * @return `IConfigurable` instance. This must not be null.
+ */
+ IConfigurable getConfigurable();
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
new file mode 100644
index 0000000..75500b7
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentListener.aidl
@@ -0,0 +1,131 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.SettingResult;
+import android.hardware.media.c2.Status;
+import android.hardware.media.c2.WorkBundle;
+
+/**
+ * Callback interface for handling notifications from @ref IComponent.
+ */
+@VintfStability
+oneway interface IComponentListener {
+ /**
+ * Identifying information for an input buffer previously queued to the
+ * component via IComponent::queue().
+ */
+ @VintfStability
+ parcelable InputBuffer {
+ /**
+ * This value comes from `Work::input.ordinal.frameIndex` in a `Work`
+ * object that was previously queued.
+ */
+ long frameIndex;
+ /**
+ * This value is an index into `Work::input.buffers` (which is an array)
+ * in a `Work` object that was previously queued.
+ */
+ int arrayIndex;
+ }
+ /**
+ * Information about rendering of a frame to a `Surface`.
+ */
+ @VintfStability
+ parcelable RenderedFrame {
+ /**
+ * Id of the `BufferQueue` containing the rendered buffer.
+ *
+ * This value must have been obtained by an earlier call to
+ * IGraphicBufferProducer::getUniqueId().
+ */
+ long bufferQueueId;
+ /**
+ * Id of the slot of the rendered buffer.
+ *
+ * This value must have been obtained by an earlier call to
+ * IGraphicBufferProducer::dequeueBuffer() or
+ * IGraphicBufferProducer::attachBuffer().
+ */
+ int slotId;
+ /**
+ * Timestamp the rendering happened.
+ *
+ * The reference point for the timestamp is determined by the
+ * `BufferQueue` that performed the rendering.
+ */
+ long timestampNs;
+ }
+ /**
+ * Notify the listener of an error.
+ *
+ * @param status Error type. @p status may be `OK`, which means that an
+ * error has occurred, but the error type does not fit into the type
+ * `Status`. In this case, additional information is provided by
+ * @p errorCode.
+ * @param errorCode Additional error information. The framework may not
+ * recognize the meaning of this value.
+ */
+ void onError(in Status status, in int errorCode);
+
+ /**
+ * Notify the listener that frames have been rendered.
+ *
+ * @param renderedFrames List of @ref RenderedFrame objects.
+ */
+ void onFramesRendered(in RenderedFrame[] renderedFrames);
+
+ /**
+ * Notify the listener that some input buffers are no longer needed by the
+ * component, and hence can be released or reused by the client.
+ *
+ * Input buffers that are contained in a `Work` object returned by an
+ * earlier onWorkDone() call are assumed released, so they must not appear
+ * in any onInputBuffersReleased() calls. That means
+ * onInputBuffersReleased() must only report input buffers that are released
+ * before the output in the same `Work` item is produced. However, it is
+ * possible for an input buffer to be returned by onWorkDone() after it has
+ * been reported by onInputBuffersReleased().
+ *
+ * @note onWorkDone() and onInputBuffersReleased() both notify the client
+ * that input buffers are no longer needed. However, in order to minimize
+ * IPC calls, onInputBuffersReleased() should be called only when
+ * onWorkDone() cannot be called, e.g., the component needs more input
+ * before an output can be produced.
+ *
+ * @param inputBuffers List of `InputBuffer` objects, identifying input
+ * buffers that are no longer needed by the component.
+ */
+ void onInputBuffersReleased(in InputBuffer[] inputBuffers);
+
+ /**
+ * Notify the listener that the component is tripped.
+ *
+ * @param settingResults List of failures.
+ */
+ void onTripped(in SettingResult[] settingResults);
+
+ /**
+ * Notify the listener that some `Work` items have been completed.
+ *
+ * All the input buffers in the returned `Work` objects must not be used by
+ * the component after onWorkDone() is called.
+ *
+ * @param workBundle List of completed `Work` objects.
+ */
+ void onWorkDone(in WorkBundle workBundle);
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl b/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
new file mode 100644
index 0000000..1435a7e
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IComponentStore.aidl
@@ -0,0 +1,185 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.Buffer;
+import android.hardware.media.c2.IComponent;
+import android.hardware.media.c2.IComponentInterface;
+import android.hardware.media.c2.IComponentListener;
+import android.hardware.media.c2.IConfigurable;
+import android.hardware.media.c2.StructDescriptor;
+
+/**
+ * Entry point for Codec2 HAL.
+ *
+ * All methods in `IComponentStore` must not block. If a method call cannot be
+ * completed in a timely manner, it must throw `Status::TIMED_OUT`. The only
+ * exceptions are getPoolClientManager() and getConfigurable(), which must
+ * always return immediately.
+ *
+ * @note This is an extension of version 1.1 of `IComponentStore`. The purpose
+ * of the extension is to add support for blocking output buffer allocator.
+ */
+@VintfStability
+interface IComponentStore {
+ /**
+ * Component traits.
+ */
+ @VintfStability
+ parcelable ComponentTraits {
+ @VintfStability
+ @Backing(type="int")
+ enum Kind {
+ OTHER = 0,
+ DECODER,
+ ENCODER,
+ }
+ @VintfStability
+ @Backing(type="int")
+ enum Domain {
+ OTHER = 0,
+ VIDEO,
+ AUDIO,
+ IMAGE,
+ }
+ /**
+ * Name of the component. This must be unique for each component.
+ *
+ * This name is use to identify the component to create in
+ * createComponent() and createComponentInterface().
+ */
+ String name;
+ /**
+ * Component domain.
+ */
+ Domain domain;
+ /**
+ * Component kind.
+ */
+ Kind kind;
+ /**
+ * Rank used by `MediaCodecList` to determine component ordering. Lower
+ * value means higher priority.
+ */
+ int rank;
+ /**
+ * MIME type.
+ */
+ String mediaType;
+ /**
+ * Aliases for component name for backward compatibility.
+ *
+ * Multiple components can have the same alias (but not the same
+ * component name) as long as their media types differ.
+ */
+ String[] aliases;
+ }
+
+ /**
+ * Copies the contents of @p src into @p dst without changing the format of
+ * @p dst.
+ *
+ * @param src Source buffer.
+ * @param dst Destination buffer.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::CANNOT_DO` - @p src and @p dst are not compatible.
+ * - `Status::REFUSED` - No permission to copy.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ void copyBuffer(in Buffer src, in Buffer dst);
+
+ /**
+ * Creates a component by name.
+ *
+ * @param name Name of the component to create. This must match one of the
+ * names returned by listComponents().
+ * @param listener Callback receiver.
+ * @param pool `IClientManager` object of the BufferPool in the client
+ * process. This may be null if the client does not own a BufferPool.
+ * @return The created component.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NOT_FOUND` - There is no component with the given name.
+ * - `Status::NO_MEMORY` - Not enough memory to create the component.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ *
+ * @sa IComponentListener.
+ */
+ IComponent createComponent(in String name, in IComponentListener listener,
+ in android.hardware.media.bufferpool2.IClientManager pool);
+
+ /**
+ * Creates a component interface by name.
+ *
+ * @param name Name of the component interface to create. This should match
+ * one of the names returned by listComponents().
+ * @return The created component interface.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NOT_FOUND` - There is no component interface with the given name.
+ * - `Status::NO_MEMORY` - Not enough memory to create the component interface.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ IComponentInterface createInterface(in String name);
+
+ /**
+ * Returns the @ref IConfigurable instance associated to this component
+ * store.
+ *
+ * @return `IConfigurable` instance. This must not be null.
+ */
+ IConfigurable getConfigurable();
+
+ /**
+ * Returns the `IClientManager` object for the component's BufferPool.
+ *
+ * @return If the component store supports receiving buffers via
+ * BufferPool API, @p pool must be a valid `IClientManager` instance.
+ * Otherwise, @p pool must be null.
+ */
+ android.hardware.media.bufferpool2.IClientManager getPoolClientManager();
+
+ /**
+ * Returns a list of `StructDescriptor` objects for a set of requested
+ * C2Param structure indices that this store is aware of.
+ *
+ * This operation must be performed at best effort, e.g. the component
+ * store must simply ignore all struct indices that it is not aware of.
+ *
+ * @param indices Indices of C2Param structures to describe.
+ * @return List of `StructDescriptor` objects.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NOT_FOUND` - Some indices were not known.
+ * - `Status::NO_MEMORY` - Not enough memory to complete this method.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ StructDescriptor[] getStructDescriptors(in int[] indices);
+
+ /**
+ * Returns the list of components supported by this component store.
+ *
+ * @return traits List of component traits for all components supported by
+ * this store (in no particular order).
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Not enough memory to complete this method.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ ComponentTraits[] listComponents();
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl b/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
new file mode 100644
index 0000000..7fdb825
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/IConfigurable.aidl
@@ -0,0 +1,213 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FieldSupportedValuesQuery;
+import android.hardware.media.c2.FieldSupportedValuesQueryResult;
+import android.hardware.media.c2.ParamDescriptor;
+import android.hardware.media.c2.Params;
+import android.hardware.media.c2.SettingResult;
+
+/**
+ * Generic configuration interface presented by all configurable Codec2 objects.
+ *
+ * This interface must be supported in all states of the owning object, and must
+ * not change the state of the owning object.
+ */
+@VintfStability
+interface IConfigurable {
+ /**
+ * Return parcelable for config() interface.
+ *
+ * This includes the successful config settings along with the failure reasons of
+ * the specified setting.
+ */
+ @VintfStability
+ parcelable ConfigResult {
+ Params params;
+ SettingResult[] failures;
+ }
+
+ /**
+ * Sets a set of parameters for the object.
+ *
+ * Tuning is performed at best effort: the object must update all supported
+ * configurations at best effort and skip unsupported parameters. Any errors
+ * are communicated in the return value along with the failures.
+ *
+ * A non-strict parameter update with an unsupported value shall cause an
+ * update to the closest supported value. A strict parameter update with an
+ * unsupported value shall be skipped and a failure shall be returned.
+ *
+ * If @p mayBlock is false, this method must not block. An update that
+ * requires blocking shall be skipped and a failure shall be returned.
+ *
+ * If @p mayBlock is true, an update may block, but the whole method call
+ * has to complete in a timely manner, or `Status::TIMED_OUT` is thrown.
+ *
+ * The final values for all parameters set are propagated back to the caller
+ * in @p params.
+ *
+ * \par For IComponent
+ *
+ * When the object type is @ref IComponent, this method must be supported in
+ * any state except released.
+ *
+ * The blocking behavior of this method differs among states:
+ * - In the stopped state, this must be non-blocking. @p mayBlock is
+ * ignored. (The method operates as if @p mayBlock was false.)
+ * - In any of the running states, this method may block momentarily if
+ * @p mayBlock is true. However, if the call cannot be completed in a
+ * timely manner, `Status::TIMED_OUT` is thrown.
+ *
+ * @note Parameter tuning @e does depend on the order of the tuning
+ * parameters, e.g., some parameter update may enable some subsequent
+ * parameter update.
+ *
+ * @param inParams Requested parameter updates.
+ * @param mayBlock Whether this call may block or not.
+ * @return result of config. Params in the result should be in same order
+ * with @p inParams.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Some supported parameters could not be updated
+ * successfully because they contained unsupported values.
+ * These are returned in @p failures.
+ * - `Status::BLOCKING` - Setting some parameters requires blocking, but
+ * @p mayBlock is false.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ ConfigResult config(in Params inParams, in boolean mayBlock);
+
+ /**
+ * Returns the id of the object. This must be unique among all objects of
+ * the same type hosted by the same store.
+ *
+ * @return Id of the object.
+ */
+ int getId();
+
+ /**
+ * Returns the name of the object.
+ *
+ * This must match the name that was supplied during the creation of the
+ * object.
+ *
+ * @return Name of the object.
+ */
+ String getName();
+
+ /**
+ * Queries a set of parameters from the object.
+ *
+ * Querying is performed at best effort: the object must query all supported
+ * parameters and skip unsupported ones (which may include parameters that
+ * could not be allocated).
+ *
+ * If @p mayBlock is true, a query may block, but the whole method call
+ * has to complete in a timely manner, or `Status::TIMED_OUT` is thrown.
+ *
+ * If @p mayBlock is false, this method must not block(All parameter queries
+ * that require blocking must be skipped). Otherwise, this
+ * method is allowed to block for a certain period of time before completing
+ * the operation. If the operation is not completed in a timely manner,
+ * `Status::TIMED_OUT` is thrown.
+ *
+ * @note Since unsupported parameters will be skipped, the returned results
+ * does not have every settings from @p indices, but the result will preserve
+ * the original order from @p indices though unsupported settings are skipped.
+ *
+ * \par For IComponent
+ *
+ * When the object type is @ref IComponent, this method must be supported in
+ * any state except released. This call must not change the state nor the
+ * internal configuration of the component.
+ *
+ * The blocking behavior of this method differs among states:
+ * - In the stopped state, this must be non-blocking. @p mayBlock is
+ * ignored. (The method operates as if @p mayBlock was false.)
+ * - In any of the running states, this method may block momentarily if
+ * @p mayBlock is true. However, if the call cannot be completed in a
+ * timely manner, `Status::status` is thrown.
+ *
+ * @param indices List of C2Param structure indices to query.
+ * @param mayBlock Whether this call may block or not.
+ * @return Flattened representation of std::vector<C2Param> object.
+ * Unsupported settings are skipped in the results. The order in @p indices
+ * still be preserved except skipped settings.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Could not allocate memory for a supported parameter.
+ * - `Status::BLOCKING` - Querying some parameters requires blocking, but
+ * @p mayBlock is false.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ Params query(in int[] indices, in boolean mayBlock);
+
+ /**
+ * Returns a list of supported parameters within a selected range of C2Param
+ * structure indices.
+ *
+ * @param start The first index of the selected range.
+ * @param count The length of the selected range.
+ * @return List of supported parameters in the selected range. This
+ * list may have fewer than @p count elements if some indices in the
+ * range are not supported.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::NO_MEMORY` - Not enough memory to complete this method.
+ *
+ */
+ ParamDescriptor[] querySupportedParams(in int start, in int count);
+
+ /**
+ * Retrieves the supported values for the queried fields.
+ *
+ * The object must process all fields queried even if some queries fail.
+ *
+ * If @p mayBlock is false, this method must not block. Otherwise, this
+ * method is allowed to block for a certain period of time before completing
+ * the operation. If the operation cannot be completed in a timely manner,
+ * `Status::TIMED_OUT` is thrown.
+ *
+ * \par For IComponent
+ *
+ * When the object type is @ref IComponent, this method must be supported in
+ * any state except released.
+ *
+ * The blocking behavior of this method differs among states:
+ * - In the stopped state, this must be non-blocking. @p mayBlock is
+ * ignored. (The method operates as if @p mayBlock was false.)
+ * - In any of the running states, this method may block momentarily if
+ * @p mayBlock is true. However, if the call cannot be completed in a
+ * timely manner, `Status::TIMED_OUT` is thrown.
+ *
+ * @param inFields List of field queries.
+ * @param mayBlock Whether this call may block or not.
+ * @return List of supported values and results for the
+ * supplied queries.
+ * @throws ServiceSpecificException with one of the following values:
+ * - `Status::BLOCKING` - Querying some parameters requires blocking, but
+ * @p mayBlock is false.
+ * - `Status::NO_MEMORY` - Not enough memory to complete this method.
+ * - `Status::BLOCKING` - Querying some fields requires blocking, but @p mayblock
+ * is false.
+ * - `Status::TIMED_OUT` - The operation cannot be finished in a timely manner.
+ * - `Status::CORRUPTED` - Some unknown error occurred.
+ */
+ FieldSupportedValuesQueryResult[] querySupportedValues(
+ in FieldSupportedValuesQuery[] inFields, in boolean mayBlock);
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl b/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
new file mode 100644
index 0000000..207c4d0
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/InfoBuffer.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.Buffer;
+
+/**
+ * An extension of @ref Buffer that also contains a C2Param structure index.
+ *
+ * This is a part of @ref FrameData.
+ */
+@VintfStability
+parcelable InfoBuffer {
+ /**
+ * A C2Param structure index.
+ */
+ int index;
+ /**
+ * Associated @ref Buffer object.
+ */
+ Buffer buffer;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
new file mode 100644
index 0000000..84c6acc
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/ParamDescriptor.aidl
@@ -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.media.c2;
+
+/**
+ * Usage description of a C2Param structure.
+ *
+ * @ref ParamDescriptor is returned by IConfigurable::querySupportedParams().
+ */
+@VintfStability
+parcelable ParamDescriptor {
+ /** The list of bit flags for attrib */
+ /**
+ * The parameter is required to be specified.
+ */
+ const int ATTRIBUTE_REQUIRED = 1 << 0;
+ /**
+ * The parameter retains its value.
+ */
+ const int ATTRIBUTE_PERSISTENT = 1 << 1;
+ /**
+ * The parameter is strict.
+ */
+ const int ATTRIBUTE_STRICT = 1 << 2;
+ /**
+ * The parameter is publicly read-only.
+ */
+ const int ATTRIBUTE_READ_ONLY = 1 << 3;
+ /**
+ * The parameter must not be visible to clients.
+ */
+ const int ATTRIBUTE_HIDDEN = 1 << 4;
+ /**
+ * The parameter must not be used by framework (other than testing).
+ */
+ const int ATTRIBUTE_INTERNAL = 1 << 5;
+ /**
+ * The parameter is publicly constant (hence read-only).
+ */
+ const int ATTRIBUTE_CONST = 1 << 6;
+
+ /**
+ * Index of the C2Param structure being described.
+ */
+ int index;
+ /**
+ * bit flag for attribute defined in the above.
+ */
+ int attrib;
+ /**
+ * Name of the structure. This must be unique for each structure.
+ */
+ String name;
+ /**
+ * Indices of other C2Param structures that this C2Param structure depends
+ * on.
+ */
+ int[] dependencies;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/ParamField.aidl b/media/c2/aidl/android/hardware/media/c2/ParamField.aidl
new file mode 100644
index 0000000..64a46bb
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/ParamField.aidl
@@ -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.media.c2;
+
+import android.hardware.media.c2.FieldId;
+
+/**
+ * Reference to a field in a C2Param structure.
+ */
+@VintfStability
+parcelable ParamField {
+ /**
+ * Index of the C2Param structure.
+ */
+ int index;
+ /**
+ * Identifier of the field inside the C2Param structure.
+ */
+ FieldId fieldId;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl b/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
new file mode 100644
index 0000000..7b74c0e
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/ParamFieldValues.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FieldSupportedValues;
+import android.hardware.media.c2.ParamField;
+
+/**
+ * Supported values for a field.
+ *
+ * This is a pair of the field specifier together with an optional supported
+ * values object. This structure is used when reporting parameter configuration
+ * failures and conflicts.
+ */
+@VintfStability
+parcelable ParamFieldValues {
+ /**
+ * Reference to a field or a C2Param structure.
+ */
+ ParamField paramOrField;
+ /**
+ * Optional supported values for the field if #paramOrField specifies an
+ * actual field that is numeric (non struct, blob or string). Supported
+ * values for arrays (including string and blobs) describe the supported
+ * values for each element (character for string, and bytes for blobs). It
+ * is optional for read-only strings and blobs.
+ */
+ FieldSupportedValues[] values;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Params.aidl b/media/c2/aidl/android/hardware/media/c2/Params.aidl
new file mode 100644
index 0000000..53b512c
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Params.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.media.c2;
+
+/**
+ * Flattened representation of std::vector<C2Param> object.
+ *
+ * The `Params` type is an array of bytes made up by concatenating a list of
+ * C2Param objects. The start index (offset into @ref Params) of each C2Param
+ * object in the list is divisible by 8. Up to 7 padding bytes may be added
+ * after each C2Param object to achieve this 64-bit alignment.
+ *
+ * Each C2Param object has the following layout:
+ * - 4 bytes: C2Param structure index (of type @ref ParamIndex) identifying the
+ * type of the C2Param object.
+ * - 4 bytes: size of the C2Param object (unsigned 4-byte integer).
+ * - (size - 8) bytes: data of the C2Param object.
+ */
+@VintfStability
+parcelable Params {
+ byte[] params;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl b/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
new file mode 100644
index 0000000..c2b9574
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/SettingResult.aidl
@@ -0,0 +1,99 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.ParamFieldValues;
+
+/**
+ * Information describing the reason the parameter settings may fail, or may be
+ * overridden.
+ */
+@VintfStability
+parcelable SettingResult {
+ /**
+ * Failure code
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum Failure {
+ /**
+ * Parameter is not supported.
+ */
+ BAD_TYPE,
+ /**
+ * Parameter is not supported on the specific port.
+ */
+ BAD_PORT,
+ /**
+ * Parameter is not supported on the specific stream.
+ */
+ BAD_INDEX,
+ /**
+ * Parameter is read-only and cannot be set.
+ */
+ READ_ONLY,
+ /**
+ * Parameter mismatches input data.
+ */
+ MISMATCH,
+ /**
+ * Strict parameter does not accept value for the field at all.
+ */
+ BAD_VALUE,
+ /**
+ * Strict parameter field value is in conflict with an/other
+ * setting(s).
+ */
+ CONFLICT,
+ /**
+ * Parameter field is out of range due to other settings. (This failure
+ * mode can only be used for strict calculated parameters.)
+ */
+ UNSUPPORTED,
+ /**
+ * Field does not access the requested parameter value at all. It has
+ * been corrected to the closest supported value. This failure mode is
+ * provided to give guidance as to what are the currently supported
+ * values for this field (which may be a subset of the at-all-potential
+ * values).
+ */
+ INFO_BAD_VALUE,
+ /**
+ * Requested parameter value is in conflict with an/other setting(s)
+ * and has been corrected to the closest supported value. This failure
+ * mode is given to provide guidance as to what are the currently
+ * supported values as well as to optionally provide suggestion to the
+ * client as to how to enable the requested parameter value.
+ */
+ INFO_CONFLICT,
+ }
+ Failure failure;
+ /**
+ * Failing (or corrected) field or parameter and optionally, currently
+ * supported values for the field. Values must only be set for field
+ * failures other than `BAD_VALUE`, and only if they are different from the
+ * globally supported values (e.g. due to restrictions by another parameter
+ * or input data).
+ */
+ ParamFieldValues field;
+ /**
+ * Conflicting parameters or fields with (optional) suggested values for any
+ * conflicting fields to avoid the conflict. Values must only be set for
+ * `CONFLICT`, `UNSUPPORTED` or `INFO_CONFLICT` failure code.
+ */
+ ParamFieldValues[] conflicts;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Status.aidl b/media/c2/aidl/android/hardware/media/c2/Status.aidl
new file mode 100644
index 0000000..58a2404
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Status.aidl
@@ -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.
+ */
+
+package android.hardware.media.c2;
+
+/**
+ * Common return values for Codec2 operations.
+ */
+@VintfStability
+parcelable Status {
+ /**
+ * Operation completed successfully.
+ */
+ const int OK = 0;
+ /**
+ * Argument has invalid value (user error).
+ */
+ const int BAD_VALUE = -22;
+ /**
+ * Argument uses invalid index (user error).
+ */
+ const int BAD_INDEX = -75;
+ /**
+ * Argument/Index is valid but not possible.
+ */
+ const int CANNOT_DO = -2147483646;
+ /**
+ * Object already exists.
+ */
+ const int DUPLICATE = -17;
+ /**
+ * Object not found.
+ */
+ const int NOT_FOUND = -2;
+ /**
+ * Operation is not permitted in the current state.
+ */
+ const int BAD_STATE = -38;
+ /**
+ * Operation would block but blocking is not permitted.
+ */
+ const int BLOCKING = -9930;
+ /**
+ * Not enough memory to complete operation.
+ */
+ const int NO_MEMORY = -12;
+ /**
+ * Missing permission to complete operation.
+ */
+ const int REFUSED = -1;
+ /**
+ * Operation did not complete within timeout.
+ */
+ const int TIMED_OUT = -110;
+ /**
+ * Operation is not implemented/supported (optional only).
+ */
+ const int OMITTED = -74;
+ /**
+ * Some unexpected error prevented the operation.
+ */
+ const int CORRUPTED = -2147483648;
+ /**
+ * Status has not been initialized.
+ */
+ const int NO_INIT = -19;
+
+ int status;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl b/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
new file mode 100644
index 0000000..00359041
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/StructDescriptor.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FieldDescriptor;
+
+/**
+ * Description of a C2Param structure. It consists of an index and a list of
+ * `FieldDescriptor`s.
+ */
+@VintfStability
+parcelable StructDescriptor {
+ /**
+ * Index of the structure.
+ *
+ * Actually C2Param::CoreIndex
+ * Core index is the underlying parameter type for a parameter. It is used to describe the
+ * layout of the parameter structure regardless of the component or parameter kind/scope.
+ *
+ * It is used to identify and distinguish global parameters, and also parameters on a given
+ * port or stream. They must be unique for the set of global parameters, as well as for the
+ * set of parameters on each port or each stream, but the same core index can be used for
+ * parameters on different streams or ports, as well as for global parameters and port/stream
+ * parameters.
+ */
+ int type;
+ /**
+ * List of fields in the structure.
+ *
+ * Fields are ordered by their offsets. A field that is a structure is
+ * ordered before its members.
+ */
+ FieldDescriptor[] fields;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl b/media/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl
new file mode 100644
index 0000000..d20e102
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/SurfaceSyncObj.aidl
@@ -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 android.hardware.media.c2;
+
+import android.hardware.common.NativeHandle;
+/**
+ * Surface(BufferQueue/IGBP) synchronization object regarding # of dequeued
+ * output buffers. This keeps # of dequeued buffers from Surface less than
+ * configured max # of dequeued buffers all the time.
+ */
+@VintfStability
+parcelable SurfaceSyncObj {
+ /**
+ * ASharedMemory for synchronization data. Layout is below
+ *
+ * |lock(futex) 4bytes|
+ * |conditional_variable(futex) 4bytes|
+ * |# of max dequeable buffer 4bytes|
+ * |# of dequeued buffer 4bytes|
+ * |Status of the surface 4bytes|
+ * INIT = 0, Configuring surface is not finished.
+ * ACTIVE = 1, Surface is ready to allocate(dequeue).
+ * SWITCHING = 2, Switching to the new surface. It is blocked
+ * to allocate(dequeue) a buffer until switching
+ * completes.
+ */
+ NativeHandle syncMemory;
+ /**
+ * BufferQueue id.
+ */
+ long bqId;
+ /**
+ * Generation id.
+ */
+ int generationId;
+ /**
+ * Consumer usage flags. See +ndk
+ * libnativewindow#AHardwareBuffer_UsageFlags for possible values.
+ */
+ long consumerUsage;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl b/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
new file mode 100644
index 0000000..9abcb7d
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/ValueRange.aidl
@@ -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.
+ */
+
+package android.hardware.media.c2;
+
+/**
+ * Description of a set of values.
+ *
+ * If the `step` member is 0, and `num` and `denom` are both 1, the `Range`
+ * structure represents a closed interval bounded by `min` and `max`.
+ *
+ * Otherwise, the #ValueRange structure represents a finite sequence of numbers
+ * produced from the following recurrence relation:
+ *
+ * @code
+ * v[0] = min
+ * v[i] = v[i - 1] * num / denom + step ; i >= 1
+ * @endcode
+ *
+ * Both the ratio `num / denom` and the value `step` must be positive. The
+ * last number in the sequence described by this #Range structure is the
+ * largest number in the sequence that is smaller than or equal to `max`.
+ *
+ * @note
+ * The division in the formula may truncate the result if the data type of
+ * these values is an integral type.
+ */
+@VintfStability
+parcelable ValueRange {
+ /**
+ * Lower end of the range (inclusive).
+ */
+ long min;
+ /**
+ * Upper end of the range (inclusive).
+ */
+ long max;
+ /**
+ * The non-homogeneous term in the recurrence relation.
+ */
+ long step;
+ /**
+ * The numerator of the scale coefficient in the recurrence relation.
+ */
+ long num;
+ /**
+ * The denominator of the scale coefficient in the recurrence relation.
+ */
+ long denom;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Work.aidl b/media/c2/aidl/android/hardware/media/c2/Work.aidl
new file mode 100644
index 0000000..4b8d696
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Work.aidl
@@ -0,0 +1,83 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.FrameData;
+import android.hardware.media.c2.Status;
+import android.hardware.media.c2.Worklet;
+
+/**
+ * A collection of input data to and output data from the component.
+ *
+ * A `Work` object holds information about a single work item. It is created by
+ * the client and passed to the component via IComponent::queue(). The component
+ * has two ways of returning a `Work` object to the client:
+ * 1. If the queued `Work` object has been successfully processed,
+ * IComponentListener::onWorkDone() shall be called to notify the listener,
+ * and the output shall be included in the returned `Work` object.
+ * 2. If the client calls IComponent::flush(), a `Work` object that has not
+ * been processed shall be returned.
+ *
+ * `Work` is a part of @ref WorkBundle.
+ */
+@VintfStability
+parcelable Work {
+ /**
+ * Additional work chain info not part of this work.
+ */
+ byte[] chainInfo;
+ /**
+ * @ref FrameData for the input.
+ */
+ FrameData input;
+ /**
+ * The chain of `Worklet`s.
+ *
+ * The length of #worklets is 1 when tunneling is not enabled.
+ *
+ * If #worklets has more than a single element, the tunnels between
+ * successive components of the work chain must have been successfully
+ * pre-registered at the time that the `Work` is submitted. Allocating the
+ * output buffers in the `Worklet`s is the responsibility of each component
+ * in the chain.
+ *
+ * Upon `Work` submission, #worklets must be an appropriately sized vector
+ * containing `Worklet`s with @ref Worklet.hasOutput set to `false`. After a
+ * successful processing, all but the final `Worklet` in the returned
+ * #worklets must have @ref Worklet.hasOutput set to `false`.
+ */
+ Worklet[] worklets;
+ /**
+ * The number of `Worklet`s successfully processed in this chain.
+ *
+ * This must be initialized to 0 by the client when the `Work` is submitted,
+ * and it must contain the number of `Worklet`s that were successfully
+ * processed when the `Work` is returned to the client.
+ *
+ * #workletsProcessed cannot exceed the length of #worklets. If
+ * #workletsProcessed is smaller than the length of #worklets, #result
+ * cannot be `OK`.
+ */
+ int workletsProcessed;
+ /**
+ * The final outcome of the `Work` (corresponding to #workletsProcessed).
+ *
+ * The value of @ref Status.OK implies that all `Worklet`s have been
+ * successfully processed.
+ */
+ Status result;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl b/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
new file mode 100644
index 0000000..2125fda
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/WorkBundle.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.media.c2;
+
+import android.hardware.media.c2.BaseBlock;
+import android.hardware.media.c2.Work;
+
+/**
+ * List of `Work` objects.
+ *
+ * `WorkBundle` is used in IComponent::queue(), IComponent::flush() and
+ * IComponentListener::onWorkDone(). A `WorkBundle` object consists of a list of
+ * `Work` objects and a list of `BaseBlock` objects. Bundling multiple `Work`
+ * objects together provides two benefits:
+ * 1. Batching of `Work` objects can reduce the number of IPC calls.
+ * 2. If multiple `Work` objects contain `Block`s that refer to the same
+ * `BaseBlock`, the number of `BaseBlock`s that is sent between processes
+ * is also reduced.
+ *
+ * @note `WorkBundle` is the AIDL counterpart of the vector of `C2Work` in the
+ * Codec 2.0 standard. The presence of #baseBlocks helps with minimizing the
+ * data transferred over an IPC.
+ */
+@VintfStability
+parcelable WorkBundle {
+ /**
+ * A list of Work items.
+ */
+ Work[] works;
+ /**
+ * A list of blocks indexed by elements of #works.
+ */
+ BaseBlock[] baseBlocks;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl b/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
new file mode 100644
index 0000000..5708a90
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/WorkOrdinal.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.media.c2;
+
+/**
+ * Ordering information of @ref FrameData objects. Each member is used for
+ * comparing urgency: a smaller difference from a reference value indicates that
+ * the associated Work object is more urgent. The reference value for each
+ * member is initialized the first time it is communicated between the client
+ * and the codec, and it may be updated to later values that are communicated.
+ *
+ * Each member of `WorkOrdinal` is stored as an unsigned integer, but the actual
+ * order it represents is derived by subtracting the reference value, then
+ * interpreting the result as a signed number with the same storage size (using
+ * two's complement).
+ *
+ * @note `WorkOrdinal` is the HIDL counterpart of `C2WorkOrdinalStruct` in the
+ * Codec 2.0 standard.
+ */
+@VintfStability
+parcelable WorkOrdinal {
+ /**
+ * Timestamp in microseconds.
+ */
+ long timestampUs;
+ /**
+ * Frame index.
+ */
+ long frameIndex;
+ /**
+ * Component specific frame ordinal.
+ */
+ long customOrdinal;
+}
diff --git a/media/c2/aidl/android/hardware/media/c2/Worklet.aidl b/media/c2/aidl/android/hardware/media/c2/Worklet.aidl
new file mode 100644
index 0000000..6b3ceac
--- /dev/null
+++ b/media/c2/aidl/android/hardware/media/c2/Worklet.aidl
@@ -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 android.hardware.media.c2;
+
+import android.hardware.media.c2.FrameData;
+import android.hardware.media.c2.SettingResult;
+
+/**
+ * In/out structure containing some instructions for and results from output
+ * processing.
+ *
+ * This is a part of @ref Work. One `Worklet` corresponds to one output
+ * @ref FrameData. The client must construct an original `Worklet` object inside
+ * a @ref Work object for each expected output before calling
+ * IComponent::queue().
+ */
+@VintfStability
+parcelable Worklet {
+ /**
+ * Component id. (Input)
+ *
+ * This is used only when tunneling is enabled.
+ *
+ * When used, this must match the return value from IConfigurable::getId().
+ */
+ int componentId;
+ /**
+ * List of C2Param objects describing tunings to be applied before
+ * processing this `Worklet`. (Input)
+ */
+ byte[] tunings;
+ /**
+ * List of failures. (Output)
+ */
+ SettingResult[] failures;
+ /**
+ * Output frame data. (Output)
+ */
+ FrameData output;
+}
diff --git a/memtrack/aidl/Android.bp b/memtrack/aidl/Android.bp
index 79effcb..0d1c241 100644
--- a/memtrack/aidl/Android.bp
+++ b/memtrack/aidl/Android.bp
@@ -39,5 +39,6 @@
},
},
},
+ frozen: true,
versions: ["1"],
}
diff --git a/neuralnetworks/1.0/vts/functional/Android.bp b/neuralnetworks/1.0/vts/functional/Android.bp
index a41f37f..8048e62 100644
--- a/neuralnetworks/1.0/vts/functional/Android.bp
+++ b/neuralnetworks/1.0/vts/functional/Android.bp
@@ -27,7 +27,6 @@
name: "neuralnetworks_vts_functional_defaults",
defaults: [
"VtsHalTargetTestDefaults",
- "neuralnetworks_float16",
],
}
diff --git a/neuralnetworks/aidl/Android.bp b/neuralnetworks/aidl/Android.bp
index db1188d..be86879 100644
--- a/neuralnetworks/aidl/Android.bp
+++ b/neuralnetworks/aidl/Android.bp
@@ -17,7 +17,7 @@
stability: "vintf",
imports: [
"android.hardware.common-V2",
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
],
backend: {
java: {
@@ -40,28 +40,28 @@
version: "1",
imports: [
"android.hardware.common-V2",
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
],
},
{
version: "2",
imports: [
"android.hardware.common-V2",
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
],
},
{
version: "3",
imports: [
"android.hardware.common-V2",
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
],
},
{
version: "4",
imports: [
"android.hardware.common-V2",
- "android.hardware.graphics.common-V3",
+ "android.hardware.graphics.common-V4",
],
},
diff --git a/oemlock/aidl/default/OemLock.cpp b/oemlock/aidl/default/OemLock.cpp
index 646b532..234a8a9 100644
--- a/oemlock/aidl/default/OemLock.cpp
+++ b/oemlock/aidl/default/OemLock.cpp
@@ -24,29 +24,31 @@
// Methods from ::android::hardware::oemlock::IOemLock follow.
::ndk::ScopedAStatus OemLock::getName(std::string *out_name) {
- (void)out_name;
+ *out_name = "SomeCoolName";
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus OemLock::setOemUnlockAllowedByCarrier(bool in_allowed, const std::vector<uint8_t> &in_signature, OemLockSecureStatus *_aidl_return) {
- (void)in_allowed;
+ // Default impl doesn't care about a valid vendor signature
(void)in_signature;
- (void)_aidl_return;
+
+ mAllowedByCarrier = in_allowed;
+ *_aidl_return = OemLockSecureStatus::OK;
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus OemLock::isOemUnlockAllowedByCarrier(bool *out_allowed) {
- (void)out_allowed;
+ *out_allowed = mAllowedByCarrier;
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus OemLock::setOemUnlockAllowedByDevice(bool in_allowed) {
- (void)in_allowed;
+ mAllowedByDevice = in_allowed;
return ::ndk::ScopedAStatus::ok();
}
::ndk::ScopedAStatus OemLock::isOemUnlockAllowedByDevice(bool *out_allowed) {
- (void)out_allowed;
+ *out_allowed = mAllowedByDevice;
return ::ndk::ScopedAStatus::ok();
}
diff --git a/oemlock/aidl/default/OemLock.h b/oemlock/aidl/default/OemLock.h
index b0df414..9dff21a 100644
--- a/oemlock/aidl/default/OemLock.h
+++ b/oemlock/aidl/default/OemLock.h
@@ -36,6 +36,10 @@
::ndk::ScopedAStatus isOemUnlockAllowedByDevice(bool* out_allowed) override;
::ndk::ScopedAStatus setOemUnlockAllowedByCarrier(bool in_allowed, const std::vector<uint8_t>& in_signature, OemLockSecureStatus* _aidl_return) override;
::ndk::ScopedAStatus setOemUnlockAllowedByDevice(bool in_allowed) override;
+
+ private:
+ bool mAllowedByCarrier = false;
+ bool mAllowedByDevice = false;
};
} // namespace oemlock
diff --git a/power/TEST_MAPPING b/power/TEST_MAPPING
new file mode 100644
index 0000000..c0963f9
--- /dev/null
+++ b/power/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalPowerTargetTest"
+ }
+ ]
+}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
index 928668c..e6809da 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/IPowerHintSession.aidl
@@ -40,4 +40,5 @@
oneway void resume();
oneway void close();
oneway void sendHint(android.hardware.power.SessionHint hint);
+ void setThreads(in int[] threadIds);
}
diff --git a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl
index b19c77b..9c1f381 100644
--- a/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl
+++ b/power/aidl/aidl_api/android.hardware.power/current/android/hardware/power/SessionHint.aidl
@@ -38,4 +38,5 @@
CPU_LOAD_DOWN = 1,
CPU_LOAD_RESET = 2,
CPU_LOAD_RESUME = 3,
+ POWER_EFFICIENCY = 4,
}
diff --git a/power/aidl/android/hardware/power/IPowerHintSession.aidl b/power/aidl/android/hardware/power/IPowerHintSession.aidl
index 4ca9c54..7db0ea1 100644
--- a/power/aidl/android/hardware/power/IPowerHintSession.aidl
+++ b/power/aidl/android/hardware/power/IPowerHintSession.aidl
@@ -20,7 +20,7 @@
import android.hardware.power.WorkDuration;
@VintfStability
-oneway interface IPowerHintSession {
+interface IPowerHintSession {
/**
* Updates the desired duration of a previously-created thread group.
*
@@ -29,7 +29,7 @@
*
* @param targetDurationNanos the new desired duration in nanoseconds
*/
- void updateTargetWorkDuration(long targetDurationNanos);
+ oneway void updateTargetWorkDuration(long targetDurationNanos);
/**
* Reports the actual duration of a thread group.
@@ -41,22 +41,22 @@
* @param actualDurationMicros how long the thread group took to complete its
* last task in nanoseconds
*/
- void reportActualWorkDuration(in WorkDuration[] durations);
+ oneway void reportActualWorkDuration(in WorkDuration[] durations);
/**
* Pause the session when the application is not allowed to send hint in framework.
*/
- void pause();
+ oneway void pause();
/**
* Resume the session when the application is allowed to send hint in framework.
*/
- void resume();
+ oneway void resume();
/**
* Close the session to release resources.
*/
- void close();
+ oneway void close();
/**
* Gives information to the PowerHintSession about upcoming or unexpected
@@ -64,5 +64,21 @@
*
* @param hint The hint to provide to the PowerHintSession
*/
- void sendHint(SessionHint hint);
+ oneway void sendHint(SessionHint hint);
+
+ /**
+ * Sets a list of threads to the power hint session. This operation will replace
+ * the current list of threads with the given list of threads. If there's already
+ * boost for the replaced threads, a reset must be performed for the replaced
+ * threads. Note that this is not an oneway method.
+ *
+ * @param threadIds The list of threads to be associated
+ * with this session.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, getMessage() must be populated with the human-readable
+ * error message. If the list of thread ids is empty, EX_ILLEGAL_ARGUMENT
+ * must be thrown.
+ */
+ void setThreads(in int[] threadIds);
}
diff --git a/power/aidl/android/hardware/power/SessionHint.aidl b/power/aidl/android/hardware/power/SessionHint.aidl
index 6a95035..a172e12 100644
--- a/power/aidl/android/hardware/power/SessionHint.aidl
+++ b/power/aidl/android/hardware/power/SessionHint.aidl
@@ -25,22 +25,31 @@
* This hint must be sent before reporting the actual duration to the session.
*/
CPU_LOAD_UP = 0,
+
/**
* This hint indicates a decrease in CPU workload intensity. It means that
* this hint session can reduce CPU resources and still meet the target duration.
*/
CPU_LOAD_DOWN = 1,
- /*
+
+ /**
* This hint indicates an upcoming CPU workload that is completely changed and
* unknown. It means that the hint session should reset CPU resources to a known
* baseline to prepare for an arbitrary load, and must wake up if inactive.
*/
CPU_LOAD_RESET = 2,
- /*
+
+ /**
* This hint indicates that the most recent CPU workload is resuming after a
* period of inactivity. It means that the hint session should allocate similar
* CPU resources to what was used previously, and must wake up if inactive.
*/
CPU_LOAD_RESUME = 3,
+ /**
+ * This hint indicates that this power hint session should be applied with a
+ * power-efficient-first scheduling strategy. This means the work of this
+ * power hint session is noncritical despite its CPU intensity.
+ */
+ POWER_EFFICIENCY = 4,
}
diff --git a/power/aidl/default/Android.bp b/power/aidl/default/Android.bp
index d1257f3..da91ee6 100644
--- a/power/aidl/default/Android.bp
+++ b/power/aidl/default/Android.bp
@@ -35,6 +35,7 @@
srcs: [
"main.cpp",
"Power.cpp",
+ "PowerHintSession.cpp",
],
}
diff --git a/power/aidl/default/Power.cpp b/power/aidl/default/Power.cpp
index 7f08f44..8fe370c 100644
--- a/power/aidl/default/Power.cpp
+++ b/power/aidl/default/Power.cpp
@@ -15,6 +15,7 @@
*/
#include "Power.h"
+#include "PowerHintSession.h"
#include <android-base/logging.h>
@@ -25,42 +26,53 @@
namespace impl {
namespace example {
+using namespace std::chrono_literals;
+
+using ndk::ScopedAStatus;
+
const std::vector<Boost> BOOST_RANGE{ndk::enum_range<Boost>().begin(),
ndk::enum_range<Boost>().end()};
const std::vector<Mode> MODE_RANGE{ndk::enum_range<Mode>().begin(), ndk::enum_range<Mode>().end()};
-ndk::ScopedAStatus Power::setMode(Mode type, bool enabled) {
+ScopedAStatus Power::setMode(Mode type, bool enabled) {
LOG(VERBOSE) << "Power setMode: " << static_cast<int32_t>(type) << " to: " << enabled;
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Power::isModeSupported(Mode type, bool* _aidl_return) {
+ScopedAStatus Power::isModeSupported(Mode type, bool* _aidl_return) {
LOG(INFO) << "Power isModeSupported: " << static_cast<int32_t>(type);
*_aidl_return = type >= MODE_RANGE.front() && type <= MODE_RANGE.back();
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) {
+ScopedAStatus Power::setBoost(Boost type, int32_t durationMs) {
LOG(VERBOSE) << "Power setBoost: " << static_cast<int32_t>(type)
<< ", duration: " << durationMs;
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Power::isBoostSupported(Boost type, bool* _aidl_return) {
+ScopedAStatus Power::isBoostSupported(Boost type, bool* _aidl_return) {
LOG(INFO) << "Power isBoostSupported: " << static_cast<int32_t>(type);
*_aidl_return = type >= BOOST_RANGE.front() && type <= BOOST_RANGE.back();
- return ndk::ScopedAStatus::ok();
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Power::createHintSession(int32_t, int32_t, const std::vector<int32_t>&, int64_t,
- std::shared_ptr<IPowerHintSession>* _aidl_return) {
- *_aidl_return = nullptr;
- return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ScopedAStatus Power::createHintSession(int32_t, int32_t, const std::vector<int32_t>& tids, int64_t,
+ std::shared_ptr<IPowerHintSession>* _aidl_return) {
+ if (tids.size() == 0) {
+ *_aidl_return = nullptr;
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ std::shared_ptr<IPowerHintSession> powerHintSession =
+ ndk::SharedRefBase::make<PowerHintSession>();
+ mPowerHintSessions.push_back(powerHintSession);
+ *_aidl_return = powerHintSession;
+ return ScopedAStatus::ok();
}
-ndk::ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) {
- *outNanoseconds = -1;
- return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
+ScopedAStatus Power::getHintSessionPreferredRate(int64_t* outNanoseconds) {
+ *outNanoseconds = std::chrono::nanoseconds(1ms).count();
+ return ScopedAStatus::ok();
}
} // namespace example
diff --git a/power/aidl/default/Power.h b/power/aidl/default/Power.h
index ef6439d..7f8405e 100644
--- a/power/aidl/default/Power.h
+++ b/power/aidl/default/Power.h
@@ -26,6 +26,7 @@
namespace example {
class Power : public BnPower {
+ public:
ndk::ScopedAStatus setMode(Mode type, bool enabled) override;
ndk::ScopedAStatus isModeSupported(Mode type, bool* _aidl_return) override;
ndk::ScopedAStatus setBoost(Boost type, int32_t durationMs) override;
@@ -35,6 +36,9 @@
int64_t durationNanos,
std::shared_ptr<IPowerHintSession>* _aidl_return) override;
ndk::ScopedAStatus getHintSessionPreferredRate(int64_t* outNanoseconds) override;
+
+ private:
+ std::vector<std::shared_ptr<IPowerHintSession>> mPowerHintSessions;
};
} // namespace example
diff --git a/power/aidl/default/PowerHintSession.cpp b/power/aidl/default/PowerHintSession.cpp
new file mode 100644
index 0000000..f395800
--- /dev/null
+++ b/power/aidl/default/PowerHintSession.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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 "PowerHintSession.h"
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::power::impl::example {
+
+using ndk::ScopedAStatus;
+
+PowerHintSession::PowerHintSession() {}
+
+ScopedAStatus PowerHintSession::updateTargetWorkDuration(int64_t targetDurationNanos) {
+ LOG(VERBOSE) << __func__ << "target duration in nanoseconds: " << targetDurationNanos;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::reportActualWorkDuration(
+ const std::vector<WorkDuration>& /* durations */) {
+ LOG(VERBOSE) << __func__;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::pause() {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::resume() {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::close() {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::sendHint(SessionHint /* hint */) {
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus PowerHintSession::setThreads(const std::vector<int32_t>& threadIds) {
+ if (threadIds.size() == 0) {
+ LOG(ERROR) << "Error: threadIds.size() shouldn't be " << threadIds.size();
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ return ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/default/PowerHintSession.h b/power/aidl/default/PowerHintSession.h
new file mode 100644
index 0000000..1d74716
--- /dev/null
+++ b/power/aidl/default/PowerHintSession.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/power/BnPowerHintSession.h>
+#include <aidl/android/hardware/power/SessionHint.h>
+#include <aidl/android/hardware/power/WorkDuration.h>
+
+namespace aidl::android::hardware::power::impl::example {
+
+class PowerHintSession : public BnPowerHintSession {
+ public:
+ explicit PowerHintSession();
+ ndk::ScopedAStatus updateTargetWorkDuration(int64_t targetDurationNanos) override;
+ ndk::ScopedAStatus reportActualWorkDuration(
+ const std::vector<WorkDuration>& durations) override;
+ ndk::ScopedAStatus pause() override;
+ ndk::ScopedAStatus resume() override;
+ ndk::ScopedAStatus close() override;
+ ndk::ScopedAStatus sendHint(SessionHint hint) override;
+ ndk::ScopedAStatus setThreads(const std::vector<int32_t>& threadIds) override;
+};
+
+} // namespace aidl::android::hardware::power::impl::example
diff --git a/power/aidl/vts/Android.bp b/power/aidl/vts/Android.bp
index d5cc2b6..56c98bd 100644
--- a/power/aidl/vts/Android.bp
+++ b/power/aidl/vts/Android.bp
@@ -35,6 +35,7 @@
"android.hardware.power-V4-ndk",
],
test_suites: [
+ "general-tests",
"vts",
],
}
diff --git a/power/aidl/vts/VtsHalPowerTargetTest.cpp b/power/aidl/vts/VtsHalPowerTargetTest.cpp
index dcf075f..5f5ce56 100644
--- a/power/aidl/vts/VtsHalPowerTargetTest.cpp
+++ b/power/aidl/vts/VtsHalPowerTargetTest.cpp
@@ -92,6 +92,18 @@
DurationWrapper(1000000000L, 4L),
};
+// DEVICEs launching with Android 11 MUST meet the requirements for the
+// target-level=5 compatibility_matrix file.
+const uint64_t kCompatibilityMatrix5ApiLevel = 30;
+
+// DEVICEs launching with Android 13 MUST meet the requirements for the
+// target-level=7 compatibility_matrix file.
+const uint64_t kCompatibilityMatrix7ApiLevel = 33;
+
+// DEVICEs launching with Android 14 MUST meet the requirements for the
+// target-level=8 compatibility_matrix file.
+const uint64_t kCompatibilityMatrix8ApiLevel = 34;
+
inline bool isUnknownOrUnsupported(const ndk::ScopedAStatus& status) {
return status.getStatus() == STATUS_UNKNOWN_TRANSACTION ||
status.getExceptionCode() == EX_UNSUPPORTED_OPERATION;
@@ -103,9 +115,13 @@
AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
ASSERT_NE(binder, nullptr);
power = IPower::fromBinder(ndk::SpAIBinder(binder));
+
+ mApiLevel = GetUintProperty<uint64_t>("ro.vendor.api_level", 0);
+ ASSERT_NE(mApiLevel, 0);
}
std::shared_ptr<IPower> power;
+ uint64_t mApiLevel;
};
TEST_P(PowerAidl, setMode) {
@@ -161,11 +177,11 @@
TEST_P(PowerAidl, getHintSessionPreferredRate) {
int64_t rate = -1;
auto status = power->getHintSessionPreferredRate(&rate);
- if (!status.isOk()) {
+ if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
EXPECT_TRUE(isUnknownOrUnsupported(status));
- return;
+ GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
}
-
+ ASSERT_TRUE(status.isOk());
// At least 1ms rate limit from HAL
ASSERT_GE(rate, 1000000);
}
@@ -173,10 +189,11 @@
TEST_P(PowerAidl, createAndCloseHintSession) {
std::shared_ptr<IPowerHintSession> session;
auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
- if (!status.isOk()) {
+ if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
EXPECT_TRUE(isUnknownOrUnsupported(status));
- return;
+ GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
}
+ ASSERT_TRUE(status.isOk());
ASSERT_NE(nullptr, session);
ASSERT_TRUE(session->pause().isOk());
ASSERT_TRUE(session->resume().isOk());
@@ -188,9 +205,14 @@
TEST_P(PowerAidl, createHintSessionFailed) {
std::shared_ptr<IPowerHintSession> session;
auto status = power->createHintSession(getpid(), getuid(), kEmptyTids, 16666666L, &session);
+
+ // Regardless of whether V2 and beyond is supported, the status is always not STATUS_OK.
ASSERT_FALSE(status.isOk());
- if (isUnknownOrUnsupported(status)) {
- return;
+
+ // If device not launching with Android 13 and beyond, check whether it's supported,
+ // if not, skip the test.
+ if (mApiLevel < kCompatibilityMatrix7ApiLevel && isUnknownOrUnsupported(status)) {
+ GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
}
ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
}
@@ -198,10 +220,11 @@
TEST_P(PowerAidl, updateAndReportDurations) {
std::shared_ptr<IPowerHintSession> session;
auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
- if (!status.isOk()) {
+ if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
EXPECT_TRUE(isUnknownOrUnsupported(status));
- return;
+ GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
}
+ ASSERT_TRUE(status.isOk());
ASSERT_NE(nullptr, session);
ASSERT_TRUE(session->updateTargetWorkDuration(16666667LL).isOk());
@@ -223,17 +246,37 @@
}
}
+TEST_P(PowerAidl, setThreads) {
+ std::shared_ptr<IPowerHintSession> session;
+ auto status = power->createHintSession(getpid(), getuid(), kSelfTids, 16666666L, &session);
+ if (mApiLevel < kCompatibilityMatrix7ApiLevel && !status.isOk()) {
+ EXPECT_TRUE(isUnknownOrUnsupported(status));
+ GTEST_SKIP() << "DEVICE not launching with Android 13 and beyond.";
+ }
+ ASSERT_TRUE(status.isOk());
+
+ if (mApiLevel < kCompatibilityMatrix8ApiLevel) {
+ GTEST_SKIP() << "DEVICE not launching with Android 14 and beyond.";
+ }
+
+ status = session->setThreads(kEmptyTids);
+ ASSERT_FALSE(status.isOk());
+ ASSERT_EQ(EX_ILLEGAL_ARGUMENT, status.getExceptionCode());
+
+ status = session->setThreads(kSelfTids);
+ ASSERT_TRUE(status.isOk());
+}
+
// FIXED_PERFORMANCE mode is required for all devices which ship on Android 11
// or later
TEST_P(PowerAidl, hasFixedPerformance) {
- auto apiLevel = GetUintProperty<uint64_t>("ro.vendor.api_level", 0);
- ASSERT_NE(apiLevel, 0);
-
- if (apiLevel >= 30) {
- bool supported;
- ASSERT_TRUE(power->isModeSupported(Mode::FIXED_PERFORMANCE, &supported).isOk());
- ASSERT_TRUE(supported);
+ if (mApiLevel < kCompatibilityMatrix5ApiLevel) {
+ GTEST_SKIP() << "FIXED_PERFORMANCE mode is only required for all devices launching Android "
+ "11 or later.";
}
+ bool supported;
+ ASSERT_TRUE(power->isModeSupported(Mode::FIXED_PERFORMANCE, &supported).isOk());
+ ASSERT_TRUE(supported);
}
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(PowerAidl);
diff --git a/power/stats/aidl/OWNERS b/power/stats/aidl/OWNERS
index b290b49..e0d66d7 100644
--- a/power/stats/aidl/OWNERS
+++ b/power/stats/aidl/OWNERS
@@ -1,3 +1,4 @@
-bsschwar@google.com
+darrenhsu@google.com
+joaodias@google.com
krossmo@google.com
-tstrudel@google.com
+vincentwang@google.com
diff --git a/radio/aidl/Android.bp b/radio/aidl/Android.bp
index 613f31b..9dbe09a 100644
--- a/radio/aidl/Android.bp
+++ b/radio/aidl/Android.bp
@@ -36,7 +36,7 @@
host_supported: true,
srcs: ["android/hardware/radio/config/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -60,7 +60,7 @@
host_supported: true,
srcs: ["android/hardware/radio/data/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -84,7 +84,7 @@
host_supported: true,
srcs: ["android/hardware/radio/messaging/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -108,7 +108,7 @@
host_supported: true,
srcs: ["android/hardware/radio/modem/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -132,7 +132,7 @@
host_supported: true,
srcs: ["android/hardware/radio/network/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -157,8 +157,8 @@
srcs: ["android/hardware/radio/sim/*.aidl"],
stability: "vintf",
imports: [
- "android.hardware.radio-V1",
- "android.hardware.radio.config",
+ "android.hardware.radio-V2",
+ "android.hardware.radio.config-V2",
],
backend: {
cpp: {
@@ -186,7 +186,7 @@
host_supported: true,
srcs: ["android/hardware/radio/voice/*.aidl"],
stability: "vintf",
- imports: ["android.hardware.radio-V1"],
+ imports: ["android.hardware.radio-V2"],
backend: {
cpp: {
enabled: true,
@@ -203,3 +203,38 @@
],
}
+
+aidl_interface {
+ name: "android.hardware.radio.ims.media",
+ vendor_available: true,
+ srcs: ["android/hardware/radio/ims/media/*.aidl"],
+ stability: "vintf",
+ imports: [
+ "android.hardware.radio-V2",
+ "android.hardware.radio.data-V2",
+ ],
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+}
+
+aidl_interface {
+ name: "android.hardware.radio.ims",
+ vendor_available: true,
+ srcs: ["android/hardware/radio/ims/*.aidl"],
+ stability: "vintf",
+ imports: ["android.hardware.radio-V2"],
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl
new file mode 100644
index 0000000..fad767c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.radio.config;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum MultipleEnabledProfilesMode {
+ NONE = 0,
+ MEP_A1 = 1,
+ MEP_A2 = 2,
+ MEP_B = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
index be4c080..da894cd 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.config/current/android/hardware/radio/config/SimSlotStatus.aidl
@@ -38,4 +38,5 @@
String atr;
String eid;
android.hardware.radio.config.SimPortInfo[] portInfo;
+ android.hardware.radio.config.MultipleEnabledProfilesMode supportedMepMode;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl
index 62f6204..a0792c3 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.data/current/android/hardware/radio/data/NrQos.aidl
@@ -37,8 +37,12 @@
int fiveQi;
android.hardware.radio.data.QosBandwidth downlink;
android.hardware.radio.data.QosBandwidth uplink;
+ /**
+ * @deprecated use qosFlowIdentifier.
+ */
byte qfi;
char averagingWindowMs;
+ int qosFlowIdentifier;
const byte FLOW_ID_RANGE_MIN = 1;
const byte FLOW_ID_RANGE_MAX = 63;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.aidl
new file mode 100644
index 0000000..5179169
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrMode.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.ims.media;
+@Backing(type="int") @VintfStability
+enum AmrMode {
+ AMR_MODE_0 = 1 << 0,
+ AMR_MODE_1 = 1 << 1,
+ AMR_MODE_2 = 1 << 2,
+ AMR_MODE_3 = 1 << 3,
+ AMR_MODE_4 = 1 << 4,
+ AMR_MODE_5 = 1 << 5,
+ AMR_MODE_6 = 1 << 6,
+ AMR_MODE_7 = 1 << 7,
+ AMR_MODE_8 = 1 << 8,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.aidl
new file mode 100644
index 0000000..36edb7f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AmrParams.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.radio.ims.media;
+@VintfStability
+parcelable AmrParams {
+ android.hardware.radio.ims.media.AmrMode amrMode;
+ boolean octetAligned;
+ int maxRedundancyMillis;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AnbrBitrate.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AnbrBitrate.aidl
new file mode 100644
index 0000000..711ac19
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/AnbrBitrate.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.radio.ims.media;
+@VintfStability
+parcelable AnbrBitrate {
+ int uplinkBps;
+ int downlinkBps;
+ const int INVALID_ANBR_BITRATE = -1;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CallQuality.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CallQuality.aidl
new file mode 100644
index 0000000..fff6e1c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CallQuality.aidl
@@ -0,0 +1,58 @@
+/*
+ * 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.radio.ims.media;
+@VintfStability
+parcelable CallQuality {
+ int downlinkCallQualityLevel;
+ int uplinkCallQualityLevel;
+ int callDuration;
+ int numRtpPacketsTransmitted;
+ int numRtpPacketsReceived;
+ int numRtpPacketsTransmittedLost;
+ int numRtpPacketsNotReceived;
+ int averageRelativeJitter;
+ int maxRelativeJitter;
+ int averageRoundTripTime;
+ int codecType;
+ boolean rtpInactivityDetected;
+ boolean rxSilenceDetected;
+ boolean txSilenceDetected;
+ int numVoiceFrames;
+ int numNoDataFrames;
+ int numDroppedRtpPackets;
+ long minPlayoutDelayMillis;
+ long maxPlayoutDelayMillis;
+ int numRtpSidPacketsReceived;
+ int numRtpDuplicatePackets;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.aidl
new file mode 100644
index 0000000..3da2dbd
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecParams.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.ims.media;
+@VintfStability
+parcelable CodecParams {
+ android.hardware.radio.ims.media.CodecType codecType;
+ byte rxPayloadTypeNumber;
+ byte txPayloadTypeNumber;
+ byte samplingRateKHz;
+ boolean dtxEnabled;
+ android.hardware.radio.ims.media.CodecSpecificParams codecSpecificParams;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecSpecificParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecSpecificParams.aidl
new file mode 100644
index 0000000..08e3f0f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecSpecificParams.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.ims.media;
+@VintfStability
+union CodecSpecificParams {
+ android.hardware.radio.ims.media.AmrParams amr;
+ android.hardware.radio.ims.media.EvsParams evs;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.aidl
new file mode 100644
index 0000000..56d2800
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/CodecType.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.radio.ims.media;
+@Backing(type="int") @VintfStability
+enum CodecType {
+ AMR = 1,
+ AMR_WB = 2,
+ EVS = 4,
+ PCMA = 8,
+ PCMU = 16,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/DtmfParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/DtmfParams.aidl
new file mode 100644
index 0000000..5523fd8
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/DtmfParams.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.radio.ims.media;
+@VintfStability
+parcelable DtmfParams {
+ byte rxPayloadTypeNumber;
+ byte txPayloadTypeNumber;
+ byte samplingRateKHz;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsBandwidth.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsBandwidth.aidl
new file mode 100644
index 0000000..eb31175
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsBandwidth.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.radio.ims.media;
+@Backing(type="int") @VintfStability
+enum EvsBandwidth {
+ NONE = 0,
+ NARROW_BAND = 1,
+ WIDE_BAND = 2,
+ SUPER_WIDE_BAND = 4,
+ FULL_BAND = 8,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.aidl
new file mode 100644
index 0000000..a067357
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsMode.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.radio.ims.media;
+@Backing(type="int") @VintfStability
+enum EvsMode {
+ EVS_MODE_0 = 1 << 0,
+ EVS_MODE_1 = 1 << 1,
+ EVS_MODE_2 = 1 << 2,
+ EVS_MODE_3 = 1 << 3,
+ EVS_MODE_4 = 1 << 4,
+ EVS_MODE_5 = 1 << 5,
+ EVS_MODE_6 = 1 << 6,
+ EVS_MODE_7 = 1 << 7,
+ EVS_MODE_8 = 1 << 8,
+ EVS_MODE_9 = 1 << 9,
+ EVS_MODE_10 = 1 << 10,
+ EVS_MODE_11 = 1 << 11,
+ EVS_MODE_12 = 1 << 12,
+ EVS_MODE_13 = 1 << 13,
+ EVS_MODE_14 = 1 << 14,
+ EVS_MODE_15 = 1 << 15,
+ EVS_MODE_16 = 1 << 16,
+ EVS_MODE_17 = 1 << 17,
+ EVS_MODE_18 = 1 << 18,
+ EVS_MODE_19 = 1 << 19,
+ EVS_MODE_20 = 1 << 20,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.aidl
new file mode 100644
index 0000000..735eb08
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/EvsParams.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.ims.media;
+@VintfStability
+parcelable EvsParams {
+ android.hardware.radio.ims.media.EvsBandwidth bandwidth;
+ android.hardware.radio.ims.media.EvsMode evsMode;
+ byte channelAwareMode;
+ boolean useHeaderFullOnly;
+ boolean useEvsModeSwitch;
+ byte codecModeRequest;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMedia.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMedia.aidl
new file mode 100644
index 0000000..30793e5
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMedia.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.radio.ims.media;
+@VintfStability
+interface IImsMedia {
+ oneway void setListener(in android.hardware.radio.ims.media.IImsMediaListener mediaListener);
+ oneway void openSession(int sessionId, in android.hardware.radio.ims.media.LocalEndPoint localEndPoint, in android.hardware.radio.ims.media.RtpConfig config);
+ oneway void closeSession(int sessionId);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaListener.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaListener.aidl
new file mode 100644
index 0000000..40f7107
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaListener.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.radio.ims.media;
+@VintfStability
+interface IImsMediaListener {
+ oneway void onOpenSessionSuccess(int sessionId, android.hardware.radio.ims.media.IImsMediaSession session);
+ oneway void onOpenSessionFailure(int sessionId, android.hardware.radio.ims.media.RtpError error);
+ oneway void onSessionClosed(int sessionId);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.aidl
new file mode 100644
index 0000000..ea9f3a4
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSession.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.radio.ims.media;
+@VintfStability
+interface IImsMediaSession {
+ oneway void setListener(in android.hardware.radio.ims.media.IImsMediaSessionListener sessionListener);
+ oneway void modifySession(in android.hardware.radio.ims.media.RtpConfig config);
+ oneway void sendDtmf(char dtmfDigit, int duration);
+ oneway void startDtmf(char dtmfDigit);
+ oneway void stopDtmf();
+ oneway void sendHeaderExtension(in List<android.hardware.radio.ims.media.RtpHeaderExtension> extensions);
+ oneway void setMediaQualityThreshold(in android.hardware.radio.ims.media.MediaQualityThreshold threshold);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
new file mode 100644
index 0000000..f03b29e
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/IImsMediaSessionListener.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.ims.media;
+@VintfStability
+interface IImsMediaSessionListener {
+ oneway void onModifySessionResponse(in android.hardware.radio.ims.media.RtpConfig config, android.hardware.radio.ims.media.RtpError error);
+ oneway void onFirstMediaPacketReceived(in android.hardware.radio.ims.media.RtpConfig config);
+ oneway void onHeaderExtensionReceived(in List<android.hardware.radio.ims.media.RtpHeaderExtension> extensions);
+ oneway void notifyMediaInactivity(android.hardware.radio.ims.media.MediaProtocolType packetType);
+ oneway void notifyPacketLoss(int packetLossPercentage);
+ oneway void notifyJitter(int jitter);
+ oneway void triggerAnbrQuery(in android.hardware.radio.ims.media.RtpConfig config);
+ oneway void onDtmfReceived(char dtmfDigit);
+ oneway void onCallQualityChanged(in android.hardware.radio.ims.media.CallQuality callQuality);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/LocalEndPoint.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/LocalEndPoint.aidl
new file mode 100644
index 0000000..6ec5156
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/LocalEndPoint.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.radio.ims.media;
+@VintfStability
+parcelable LocalEndPoint {
+ ParcelFileDescriptor rtpFd;
+ ParcelFileDescriptor rtcpFd;
+ int modemId;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaDirection.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaDirection.aidl
new file mode 100644
index 0000000..d90b2a4
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaDirection.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.radio.ims.media;
+@Backing(type="int") @VintfStability
+enum MediaDirection {
+ NO_FLOW = 0,
+ SEND_ONLY = 1,
+ RECEIVE_ONLY = 2,
+ SEND_RECEIVE = 3,
+ INACTIVE = 4,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaProtocolType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaProtocolType.aidl
new file mode 100644
index 0000000..1a290d4
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaProtocolType.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.ims.media;
+@Backing(type="int") @VintfStability
+enum MediaProtocolType {
+ RTP = 0,
+ RTCP = 1,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityThreshold.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityThreshold.aidl
new file mode 100644
index 0000000..a448bac
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/MediaQualityThreshold.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.ims.media;
+@VintfStability
+parcelable MediaQualityThreshold {
+ int rtpInactivityTimerMillis;
+ int rtcpInactivityTimerMillis;
+ int rtpPacketLossDurationMillis;
+ int rtpPacketLossRate;
+ int jitterDurationMillis;
+ int rtpJitterMillis;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpConfig.aidl
new file mode 100644
index 0000000..6a76d85
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpConfig.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.radio.ims.media;
+@VintfStability
+parcelable RtcpConfig {
+ String canonicalName;
+ int transmitPort;
+ int transmitIntervalSec;
+ int rtcpXrBlocks;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
new file mode 100644
index 0000000..2eefe6f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtcpXrReportBlockType.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.radio.ims.media;
+@Backing(type="int") @VintfStability
+enum RtcpXrReportBlockType {
+ RTCPXR_NONE = 0,
+ RTCPXR_LOSS_RLE_REPORT_BLOCK = 1,
+ RTCPXR_DUPLICATE_RLE_REPORT_BLOCK = 2,
+ RTCPXR_PACKET_RECEIPT_TIMES_REPORT_BLOCK = 4,
+ RTCPXR_RECEIVER_REFERENCE_TIME_REPORT_BLOCK = 8,
+ RTCPXR_DLRR_REPORT_BLOCK = 16,
+ RTCPXR_STATISTICS_SUMMARY_REPORT_BLOCK = 32,
+ RTCPXR_VOIP_METRICS_REPORT_BLOCK = 64,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpAddress.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpAddress.aidl
new file mode 100644
index 0000000..35357d1
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpAddress.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.ims.media;
+@VintfStability
+parcelable RtpAddress {
+ String ipAddress;
+ int portNumber;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.aidl
new file mode 100644
index 0000000..ad8b86c
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpConfig.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.ims.media;
+@VintfStability
+parcelable RtpConfig {
+ android.hardware.radio.ims.media.MediaDirection direction;
+ android.hardware.radio.AccessNetwork accessNetwork;
+ android.hardware.radio.ims.media.RtpAddress remoteAddress;
+ android.hardware.radio.ims.media.RtpSessionParams sessionParams;
+ android.hardware.radio.ims.media.RtcpConfig rtcpConfig;
+ android.hardware.radio.ims.media.AnbrBitrate anbrBitrateParams;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpError.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpError.aidl
new file mode 100644
index 0000000..41b0aeb
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpError.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.radio.ims.media;
+@Backing(type="int") @VintfStability
+enum RtpError {
+ NONE = 0,
+ INVALID_PARAM = 1,
+ NOT_READY = 2,
+ NO_MEMORY = 3,
+ NO_RESOURCES = 4,
+ PORT_UNAVAILABLE = 5,
+ NOT_SUPPORTED = 6,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpHeaderExtension.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpHeaderExtension.aidl
new file mode 100644
index 0000000..83b8a31
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpHeaderExtension.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.ims.media;
+@VintfStability
+parcelable RtpHeaderExtension {
+ int localId;
+ byte[] data;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionParams.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionParams.aidl
new file mode 100644
index 0000000..13a7487
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims.media/current/android/hardware/radio/ims/media/RtpSessionParams.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.radio.ims.media;
+@VintfStability
+parcelable RtpSessionParams {
+ byte pTimeMillis;
+ int maxPtimeMillis;
+ byte dscp;
+ android.hardware.radio.ims.media.DtmfParams dtmfParams;
+ android.hardware.radio.ims.media.CodecParams codecParams;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl
new file mode 100644
index 0000000..030479f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ConnectionFailureInfo.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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.radio.ims;
+@JavaDerive(toString=true) @VintfStability
+parcelable ConnectionFailureInfo {
+ android.hardware.radio.ims.ConnectionFailureInfo.ConnectionFailureReason failureReason;
+ int causeCode;
+ int waitTimeMillis;
+ @Backing(type="int") @VintfStability
+ enum ConnectionFailureReason {
+ REASON_ACCESS_DENIED = 1,
+ REASON_NAS_FAILURE = 2,
+ REASON_RACH_FAILURE = 3,
+ REASON_RLC_FAILURE = 4,
+ REASON_RRC_REJECT = 5,
+ REASON_RRC_TIMEOUT = 6,
+ REASON_NO_SERVICE = 7,
+ REASON_PDN_NOT_AVAILABLE = 8,
+ REASON_RF_BUSY = 9,
+ REASON_UNSPECIFIED = 65535,
+ }
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/EpsFallbackReason.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/EpsFallbackReason.aidl
new file mode 100644
index 0000000..ebea903
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/EpsFallbackReason.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.radio.ims;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum EpsFallbackReason {
+ NO_NETWORK_TRIGGER = 1,
+ NO_NETWORK_RESPONSE = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioIms.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioIms.aidl
new file mode 100644
index 0000000..4df8709
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioIms.aidl
@@ -0,0 +1,45 @@
+/*
+ * 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.radio.ims;
+@VintfStability
+interface IRadioIms {
+ oneway void setSrvccCallInfo(int serial, in android.hardware.radio.ims.SrvccCall[] srvccCalls);
+ oneway void updateImsRegistrationInfo(int serial, in android.hardware.radio.ims.ImsRegistration imsRegistration);
+ oneway void startImsTraffic(int serial, int token, android.hardware.radio.ims.ImsTrafficType imsTrafficType, android.hardware.radio.AccessNetwork accessNetworkType, android.hardware.radio.ims.ImsCall.Direction trafficDirection);
+ oneway void stopImsTraffic(int serial, int token);
+ oneway void triggerEpsFallback(int serial, in android.hardware.radio.ims.EpsFallbackReason reason);
+ oneway void setResponseFunctions(in android.hardware.radio.ims.IRadioImsResponse radioImsResponse, in android.hardware.radio.ims.IRadioImsIndication radioImsIndication);
+ oneway void sendAnbrQuery(int serial, android.hardware.radio.ims.ImsStreamType mediaType, android.hardware.radio.ims.ImsStreamDirection direction, int bitsPerSecond);
+ oneway void updateImsCallStatus(int serial, in android.hardware.radio.ims.ImsCall[] imsCalls);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsIndication.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsIndication.aidl
new file mode 100644
index 0000000..ef6b4cc
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsIndication.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.radio.ims;
+@VintfStability
+interface IRadioImsIndication {
+ oneway void onConnectionSetupFailure(in android.hardware.radio.RadioIndicationType type, int token, in android.hardware.radio.ims.ConnectionFailureInfo info);
+ oneway void notifyAnbr(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.ims.ImsStreamType mediaType, in android.hardware.radio.ims.ImsStreamDirection direction, int bitsPerSecond);
+ oneway void triggerImsDeregistration(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.ims.ImsDeregistrationReason reason);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsResponse.aidl
new file mode 100644
index 0000000..053ba46
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/IRadioImsResponse.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.ims;
+@VintfStability
+interface IRadioImsResponse {
+ oneway void setSrvccCallInfoResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void updateImsRegistrationInfoResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void startImsTrafficResponse(in android.hardware.radio.RadioResponseInfo info, in @nullable android.hardware.radio.ims.ConnectionFailureInfo failureInfo);
+ oneway void stopImsTrafficResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void triggerEpsFallbackResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void sendAnbrQueryResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void updateImsCallStatusResponse(in android.hardware.radio.RadioResponseInfo info);
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl
new file mode 100644
index 0000000..e48653b
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsCall.aidl
@@ -0,0 +1,64 @@
+/*
+ * 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.radio.ims;
+@JavaDerive(toString=true) @VintfStability
+parcelable ImsCall {
+ int index;
+ android.hardware.radio.ims.ImsCall.CallType callType;
+ android.hardware.radio.AccessNetwork accessNetwork;
+ android.hardware.radio.ims.ImsCall.CallState callState;
+ android.hardware.radio.ims.ImsCall.Direction direction;
+ boolean isHeldByRemote;
+ @Backing(type="int")
+ enum CallType {
+ NORMAL = 0,
+ EMERGENCY = 1,
+ }
+ @Backing(type="int")
+ enum CallState {
+ ACTIVE = 0,
+ HOLDING = 1,
+ DIALING = 2,
+ ALERTING = 3,
+ INCOMING = 4,
+ WAITING = 5,
+ DISCONNECTING = 6,
+ DISCONNECTED = 7,
+ }
+ @Backing(type="int")
+ enum Direction {
+ INCOMING = 0,
+ OUTGOING = 1,
+ }
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.aidl
new file mode 100644
index 0000000..b04e559
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsDeregistrationReason.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.radio.ims;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum ImsDeregistrationReason {
+ REASON_SIM_REMOVED = 1,
+ REASON_SIM_REFRESH = 2,
+ REASON_ALLOWED_NETWORK_TYPES_CHANGED = 3,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl
new file mode 100644
index 0000000..1c4c12a
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistration.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.radio.ims;
+@JavaDerive(toString=true) @VintfStability
+parcelable ImsRegistration {
+ android.hardware.radio.ims.ImsRegistrationState regState;
+ android.hardware.radio.AccessNetwork accessNetworkType;
+ android.hardware.radio.ims.SuggestedAction suggestedAction;
+ int capabilities;
+ const int IMS_MMTEL_CAPABILITY_NONE = 0;
+ const int IMS_MMTEL_CAPABILITY_VOICE = 1;
+ const int IMS_MMTEL_CAPABILITY_VIDEO = 2;
+ const int IMS_MMTEL_CAPABILITY_SMS = 4;
+ const int IMS_RCS_CAPABILITIES = 8;
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistrationState.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistrationState.aidl
new file mode 100644
index 0000000..664f561
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsRegistrationState.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.radio.ims;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum ImsRegistrationState {
+ NOT_REGISTERED = 0,
+ REGISTERED = 1,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamDirection.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamDirection.aidl
new file mode 100644
index 0000000..cf2e4f1
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamDirection.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.radio.ims;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum ImsStreamDirection {
+ UPLINK = 1,
+ DOWNLINK = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamType.aidl
new file mode 100644
index 0000000..10c477f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsStreamType.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.radio.ims;
+@Backing(type="int") @VintfStability
+enum ImsStreamType {
+ AUDIO = 1,
+ VIDEO = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsTrafficType.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsTrafficType.aidl
new file mode 100644
index 0000000..f7654b4
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/ImsTrafficType.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.ims;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum ImsTrafficType {
+ EMERGENCY = 0,
+ EMERGENCY_SMS = 1,
+ VOICE = 2,
+ VIDEO = 3,
+ SMS = 4,
+ REGISTRATION = 5,
+ UT_XCAP = 6,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl
new file mode 100644
index 0000000..a8b7cfc
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SrvccCall.aidl
@@ -0,0 +1,64 @@
+/*
+ * 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.radio.ims;
+@JavaDerive(toString=true) @VintfStability
+parcelable SrvccCall {
+ int index;
+ android.hardware.radio.ims.SrvccCall.CallType callType;
+ int callState;
+ android.hardware.radio.ims.SrvccCall.CallSubState callSubstate;
+ android.hardware.radio.ims.SrvccCall.ToneType ringbackToneType;
+ boolean isMpty;
+ boolean isMT;
+ String number;
+ int numPresentation;
+ String name;
+ int namePresentation;
+ @Backing(type="int") @VintfStability
+ enum CallType {
+ NORMAL = 0,
+ EMERGENCY = 1,
+ }
+ @Backing(type="int") @VintfStability
+ enum CallSubState {
+ NONE = 0,
+ PREALERTING = 1,
+ }
+ @Backing(type="int") @VintfStability
+ enum ToneType {
+ NONE = 0,
+ LOCAL = 1,
+ NETWORK = 2,
+ }
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.aidl
new file mode 100644
index 0000000..da19774
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.ims/current/android/hardware/radio/ims/SuggestedAction.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.radio.ims;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum SuggestedAction {
+ NONE = 0,
+ TRIGGER_PLMN_BLOCK = 1,
+ TRIGGER_PLMN_BLOCK_WITH_TIMEOUT = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl
index 41eff51..74dc39d 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModem.aidl
@@ -41,9 +41,18 @@
oneway void getModemActivityInfo(in int serial);
oneway void getModemStackStatus(in int serial);
oneway void getRadioCapability(in int serial);
+ /**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ */
oneway void nvReadItem(in int serial, in android.hardware.radio.modem.NvItem itemId);
oneway void nvResetConfig(in int serial, in android.hardware.radio.modem.ResetNvType resetType);
+ /**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ */
oneway void nvWriteCdmaPrl(in int serial, in byte[] prl);
+ /**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ */
oneway void nvWriteItem(in int serial, in android.hardware.radio.modem.NvWriteItem item);
oneway void requestShutdown(in int serial);
oneway void responseAcknowledgement();
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl
index dcaff45..af8bbe1 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/IRadioModemResponse.aidl
@@ -42,9 +42,18 @@
oneway void getModemActivityInfoResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.modem.ActivityStatsInfo activityInfo);
oneway void getModemStackStatusResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isEnabled);
oneway void getRadioCapabilityResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.modem.RadioCapability rc);
+ /**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ */
oneway void nvReadItemResponse(in android.hardware.radio.RadioResponseInfo info, in String result);
oneway void nvResetConfigResponse(in android.hardware.radio.RadioResponseInfo info);
+ /**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ */
oneway void nvWriteCdmaPrlResponse(in android.hardware.radio.RadioResponseInfo info);
+ /**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ */
oneway void nvWriteItemResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void requestShutdownResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void sendDeviceStateResponse(in android.hardware.radio.RadioResponseInfo info);
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
index 3e27643..b80d7ac 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvItem.aidl
@@ -32,6 +32,9 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.radio.modem;
+/**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ */
@Backing(type="int") @JavaDerive(toString=true) @VintfStability
enum NvItem {
CDMA_MEID = 1,
diff --git a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
index 17b7de0..6a786bc 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.modem/current/android/hardware/radio/modem/NvWriteItem.aidl
@@ -32,6 +32,9 @@
// later when a module using the interface is updated, e.g., Mainline modules.
package android.hardware.radio.modem;
+/**
+ * @deprecated NV APIs are deprecated starting from Android U.
+ */
@JavaDerive(toString=true) @VintfStability
parcelable NvWriteItem {
android.hardware.radio.modem.NvItem itemId;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
index af17b43..7d99a53 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EmergencyRegResult.aidl
@@ -37,6 +37,7 @@
android.hardware.radio.AccessNetwork accessNetwork;
android.hardware.radio.network.RegState regState;
android.hardware.radio.network.Domain emcDomain;
+ boolean isVopsSupported;
boolean isEmcBearerSupported;
byte nwProvidedEmc;
byte nwProvidedEmf;
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
index dfbf881..93df3a4 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/EutranRegistrationInfo.aidl
@@ -36,4 +36,13 @@
parcelable EutranRegistrationInfo {
android.hardware.radio.network.LteVopsInfo lteVopsInfo;
android.hardware.radio.network.NrIndicators nrIndicators;
+ android.hardware.radio.network.EutranRegistrationInfo.AttachResultType lteAttachResultType;
+ int extraInfo;
+ const int EXTRA_CSFB_NOT_PREFERRED = 1;
+ const int EXTRA_SMS_ONLY = 2;
+ enum AttachResultType {
+ NONE = 0,
+ EPS_ONLY = 1,
+ COMBINED = 2,
+ }
}
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 832738f..5aed024 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
@@ -41,6 +41,9 @@
oneway void getCdmaRoamingPreference(in int serial);
oneway void getCellInfoList(in int serial);
oneway void getDataRegistrationState(in int serial);
+ /**
+ * @deprecated Deprecated starting from Android U.
+ */
oneway void getImsRegistrationState(in int serial);
oneway void getNetworkSelectionMode(in int serial);
oneway void getOperator(in int serial);
@@ -72,6 +75,11 @@
oneway void getUsageSetting(in int serial);
oneway void setEmergencyMode(int serial, in android.hardware.radio.network.EmergencyMode emcModeType);
oneway void triggerEmergencyNetworkScan(int serial, in android.hardware.radio.network.EmergencyNetworkScanTrigger request);
- oneway void cancelEmergencyNetworkScan(in int serial);
+ oneway void cancelEmergencyNetworkScan(int serial, boolean resetScan);
oneway void exitEmergencyMode(in int serial);
+ oneway void setNullCipherAndIntegrityEnabled(in int serial, in boolean enabled);
+ oneway void isN1ModeEnabled(in int serial);
+ oneway void setN1ModeEnabled(in int serial, boolean enable);
+ oneway void setLocationPrivacySetting(in int serial, in boolean shareLocation);
+ oneway void getLocationPrivacySetting(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 0f017ea..229f3e2 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
@@ -49,4 +49,5 @@
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);
oneway void emergencyNetworkScanResult(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.EmergencyRegResult result);
+ oneway void onNetworkInitiatedLocationResult(in android.hardware.radio.RadioIndicationType type, in android.hardware.radio.network.LocationResponseType locationResponseType);
}
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 24d587e..ccdfde6 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
@@ -42,6 +42,9 @@
oneway void getCdmaRoamingPreferenceResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CdmaRoamingType type);
oneway void getCellInfoListResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.CellInfo[] cellInfo);
oneway void getDataRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in android.hardware.radio.network.RegStateResult dataRegResponse);
+ /**
+ * @deprecated Deprecated starting from Android U.
+ */
oneway void getImsRegistrationStateResponse(in android.hardware.radio.RadioResponseInfo info, in boolean isRegistered, in android.hardware.radio.RadioTechnologyFamily ratFamily);
oneway void getNetworkSelectionModeResponse(in android.hardware.radio.RadioResponseInfo info, in boolean manual);
oneway void getOperatorResponse(in android.hardware.radio.RadioResponseInfo info, in String longName, in String shortName, in String numeric);
@@ -73,4 +76,9 @@
oneway void triggerEmergencyNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void exitEmergencyModeResponse(in android.hardware.radio.RadioResponseInfo info);
oneway void cancelEmergencyNetworkScanResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void setNullCipherAndIntegrityEnabledResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void isN1ModeEnabledResponse(in android.hardware.radio.RadioResponseInfo info, boolean isEnabled);
+ oneway void setN1ModeEnabledResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void setLocationPrivacySettingResponse(in android.hardware.radio.RadioResponseInfo info);
+ oneway void getLocationPrivacySettingResponse(in android.hardware.radio.RadioResponseInfo info, boolean shareLocation);
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LocationResponseType.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LocationResponseType.aidl
new file mode 100644
index 0000000..e89a40f
--- /dev/null
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/LocationResponseType.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.radio.network;
+@Backing(type="int") @JavaDerive(toString=true) @VintfStability
+enum LocationResponseType {
+ REJECTED = 0,
+ ACCEPTED_NO_LOCATION_PROVIDED = 1,
+ ACCEPTED_LOCATION_PROVIDED = 2,
+}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
index e6e7999..711c9ac 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.network/current/android/hardware/radio/network/RegState.aidl
@@ -44,4 +44,5 @@
NOT_REG_MT_SEARCHING_OP_EM = 12,
REG_DENIED_EM = 13,
UNKNOWN_EM = 14,
+ REG_EM = 20,
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
index 2201345..2f2e07b 100644
--- a/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio.sim/current/android/hardware/radio/sim/SimApdu.aidl
@@ -41,4 +41,5 @@
int p2;
int p3;
String data;
+ boolean isEs10;
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl
index ecc2a9b..afc4f4e 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioAccessFamily.aidl
@@ -53,6 +53,9 @@
GSM = 65536,
TD_SCDMA = 131072,
IWLAN = 262144,
+ /**
+ * @deprecated use LTE instead.
+ */
LTE_CA = 524288,
NR = 1048576,
}
diff --git a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl
index 9dad0a4..7060469 100644
--- a/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl
+++ b/radio/aidl/aidl_api/android.hardware.radio/current/android/hardware/radio/RadioTechnology.aidl
@@ -53,6 +53,9 @@
GSM = 16,
TD_SCDMA = 17,
IWLAN = 18,
+ /**
+ * @deprecated use LTE instead and indicate carrier aggregation through multiple physical channel configurations in IRadioNetwork::currentPhysicalChannelConfigs.
+ */
LTE_CA = 19,
NR = 20,
}
diff --git a/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl b/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
index 6cd0a95..edf33ba 100644
--- a/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
+++ b/radio/aidl/android/hardware/radio/RadioAccessFamily.aidl
@@ -41,6 +41,7 @@
GSM = 1 << RadioTechnology.GSM,
TD_SCDMA = 1 << RadioTechnology.TD_SCDMA,
IWLAN = 1 << RadioTechnology.IWLAN,
+ /** @deprecated use LTE instead. */
LTE_CA = 1 << RadioTechnology.LTE_CA,
/**
* 5G NR. This is only use in 5G Standalone mode.
diff --git a/radio/aidl/android/hardware/radio/RadioError.aidl b/radio/aidl/android/hardware/radio/RadioError.aidl
index ae58a0e..61d5a77 100644
--- a/radio/aidl/android/hardware/radio/RadioError.aidl
+++ b/radio/aidl/android/hardware/radio/RadioError.aidl
@@ -41,6 +41,9 @@
* Operation requires SIM PUK2 to be entered
*/
SIM_PUK2 = 5,
+ /**
+ * Optional API
+ */
REQUEST_NOT_SUPPORTED = 6,
CANCELLED = 7,
/**
diff --git a/radio/aidl/android/hardware/radio/RadioTechnology.aidl b/radio/aidl/android/hardware/radio/RadioTechnology.aidl
index 917cb16..4b51152 100644
--- a/radio/aidl/android/hardware/radio/RadioTechnology.aidl
+++ b/radio/aidl/android/hardware/radio/RadioTechnology.aidl
@@ -45,6 +45,10 @@
GSM,
TD_SCDMA,
IWLAN,
+ /**
+ * @deprecated use LTE instead and indicate carrier aggregation through multiple
+ * physical channel configurations in IRadioNetwork::currentPhysicalChannelConfigs.
+ */
LTE_CA,
/**
* 5G NR. This is only used in 5G Standalone mode.
diff --git a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
index 929f02d..0d36bbd 100644
--- a/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
+++ b/radio/aidl/android/hardware/radio/config/IRadioConfigResponse.aidl
@@ -54,7 +54,6 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void getNumOfLiveModemsResponse(
in android.hardware.radio.RadioResponseInfo info, in byte numOfLiveModems);
@@ -93,7 +92,6 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_ARGUMENTS
*/
void setNumOfLiveModemsResponse(in android.hardware.radio.RadioResponseInfo info);
diff --git a/radio/aidl/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl b/radio/aidl/android/hardware/radio/config/MultipleEnabledProfilesMode.aidl
new file mode 100644
index 0000000..b18ea0e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/config/MultipleEnabledProfilesMode.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.
+ */
+
+package android.hardware.radio.config;
+
+/**
+ * Multiple Enabled Profiles(MEP) mode is the jointly supported MEP mode. As per section 3.4.1.1 of
+ * GSMA spec SGP.22 v3.0,there are 3 supported MEP modes: MEP-A1, MEP-A2 and MEP-B.
+ * If there is no jointly supported MEP mode, supported MEP mode is set to NONE.
+ */
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum MultipleEnabledProfilesMode {
+ /**
+ * If there is no jointly supported MEP mode, set supported MEP mode to NONE.
+ */
+ NONE,
+ /**
+ * In case of MEP-A1, the ISD-R is selected on eSIM port 0 only and profiles are selected on
+ * eSIM ports 1 and higher, with the eSIM port being assigned by the LPA or platform.
+ */
+ MEP_A1,
+ /**
+ * In case of MEP-A2, the ISD-R is selected on eSIM port 0 only and profiles are selected on
+ * eSIM ports 1 and higher, with the eSIM port being assigned by the eUICC.
+ */
+ MEP_A2,
+ /**
+ * In case of MEP-B, profiles are selected on eSIM ports 0 and higher, with the ISD-R being
+ * selectable on any of these eSIM ports.
+ */
+ MEP_B,
+}
diff --git a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
index 748660f..73f2954 100644
--- a/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
+++ b/radio/aidl/android/hardware/radio/config/SimSlotStatus.aidl
@@ -16,6 +16,7 @@
package android.hardware.radio.config;
+import android.hardware.radio.config.MultipleEnabledProfilesMode;
import android.hardware.radio.config.SimPortInfo;
@VintfStability
@@ -52,4 +53,8 @@
* active port in the slot mapping.
*/
SimPortInfo[] portInfo;
+ /**
+ * Jointly supported Multiple Enabled Profiles(MEP) mode as per SGP.22 V3.0
+ */
+ MultipleEnabledProfilesMode supportedMepMode;
}
diff --git a/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl b/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl
index 88b6c1b..06c83c1 100644
--- a/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl
+++ b/radio/aidl/android/hardware/radio/data/IRadioDataResponse.aidl
@@ -44,7 +44,6 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
* RadioError:NO_RESOURCES- Indicates that no pdu session ids are available
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void allocatePduSessionIdResponse(in RadioResponseInfo info, in int id);
@@ -57,7 +56,6 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
* RadioError:NO_RESOURCES
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_CALL_ID
*/
void cancelHandoverResponse(in RadioResponseInfo info);
@@ -66,7 +64,6 @@
* @param info Response info struct containing response type, serial no. and error
*
* Valid errors returned:
- * RadioError:REQUEST_NOT_SUPPORTED may be returned when HAL 1.2 or higher is supported.
* RadioError:NONE indicates success. Any other error will remove the network from the list.
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INVALID_CALL_ID
@@ -112,7 +109,6 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
* RadioError:NO_RESOURCES
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void releasePduSessionIdResponse(in RadioResponseInfo info);
@@ -131,7 +127,6 @@
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void setDataAllowedResponse(in RadioResponseInfo info);
@@ -146,7 +141,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SIM_ABSENT
*/
void setDataProfileResponse(in RadioResponseInfo info);
@@ -159,7 +153,6 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:MODEM_ERR
* RadioError:INVALID_ARGUMENTS
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void setDataThrottlingResponse(in RadioResponseInfo info);
@@ -176,7 +169,6 @@
* RadioError:MODEM_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:NOT_PROVISIONED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -208,7 +200,6 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
* RadioError:NO_RESOURCES
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_CALL_ID
*/
void startHandoverResponse(in RadioResponseInfo info);
diff --git a/radio/aidl/android/hardware/radio/data/NrQos.aidl b/radio/aidl/android/hardware/radio/data/NrQos.aidl
index af8ab83..28b4a7f 100644
--- a/radio/aidl/android/hardware/radio/data/NrQos.aidl
+++ b/radio/aidl/android/hardware/radio/data/NrQos.aidl
@@ -36,9 +36,13 @@
QosBandwidth downlink;
QosBandwidth uplink;
/**
- * QOS flow identifier of the QOS flow description in the range
- * (FLOW_ID_RANGE_MIN, FLOW_ID_RANGE_MAX)
+ * @deprecated use qosFlowIdentifier.
*/
byte qfi;
char averagingWindowMs;
+ /**
+ * QOS flow identifier of the QOS flow description in the range
+ * (FLOW_ID_RANGE_MIN, FLOW_ID_RANGE_MAX).
+ **/
+ int qosFlowIdentifier;
}
diff --git a/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl b/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl
new file mode 100644
index 0000000..70faa1e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/ConnectionFailureInfo.aidl
@@ -0,0 +1,61 @@
+/*
+ * 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.radio.ims;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable ConnectionFailureInfo {
+
+ @VintfStability
+ @Backing(type="int")
+ enum ConnectionFailureReason {
+ /** Access class check failed */
+ REASON_ACCESS_DENIED = 1,
+ /** 3GPP Non-access stratum failure */
+ REASON_NAS_FAILURE = 2,
+ /** Random access failure */
+ REASON_RACH_FAILURE = 3,
+ /** Radio link failure */
+ REASON_RLC_FAILURE = 4,
+ /** Radio connection establishment rejected by network */
+ REASON_RRC_REJECT = 5,
+ /** Radio connection establishment timed out */
+ REASON_RRC_TIMEOUT = 6,
+ /** Device currently not in service */
+ REASON_NO_SERVICE = 7,
+ /** The PDN is no more active */
+ REASON_PDN_NOT_AVAILABLE = 8,
+ /** Radio resource is busy with another subscription */
+ REASON_RF_BUSY = 9,
+ REASON_UNSPECIFIED = 0xFFFF,
+ }
+
+ /**
+ * Values are REASON_* constants
+ */
+ ConnectionFailureReason failureReason;
+
+ /**
+ * Failure cause code from network or modem specific to the failure
+ */
+ int causeCode;
+
+ /**
+ * Retry wait time provided by network in milliseconds
+ */
+ int waitTimeMillis;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/EpsFallbackReason.aidl b/radio/aidl/android/hardware/radio/ims/EpsFallbackReason.aidl
new file mode 100644
index 0000000..670638b
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/EpsFallbackReason.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.radio.ims;
+
+@VintfStability
+@JavaDerive(toString=true)
+@Backing(type="int")
+enum EpsFallbackReason {
+ /**
+ * If VoNR is not supported and EPS fallback is not triggered by network then UE initiated EPS
+ * fallback would be triggered by IMS stack with this reason. The modem shall locally release
+ * the 5G NR SA RRC connection and acquire the LTE network and perform a tracking area update
+ * procedure. After the EPS fallback procedure is completed, the call setup for voice will
+ * be established.
+ */
+ NO_NETWORK_TRIGGER = 1,
+
+ /**
+ * If the UE doesn't receive any response for SIP INVITE within a certain time in 5G NR SA,
+ * UE initiated EPS fallback will be triggered with this reason. The modem shall reset its data
+ * buffer of IMS PDUs to prevent the ghost call. After the EPS fallback procedure is completed,
+ * the VoLTE call will be established.
+ */
+ NO_NETWORK_RESPONSE = 2,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/IRadioIms.aidl b/radio/aidl/android/hardware/radio/ims/IRadioIms.aidl
new file mode 100644
index 0000000..bd661a7
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/IRadioIms.aidl
@@ -0,0 +1,152 @@
+/*
+ * 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.radio.ims;
+
+import android.hardware.radio.AccessNetwork;
+import android.hardware.radio.ims.EpsFallbackReason;
+import android.hardware.radio.ims.IRadioImsIndication;
+import android.hardware.radio.ims.IRadioImsResponse;
+import android.hardware.radio.ims.ImsCall;
+import android.hardware.radio.ims.ImsRegistration;
+import android.hardware.radio.ims.ImsStreamDirection;
+import android.hardware.radio.ims.ImsStreamType;
+import android.hardware.radio.ims.ImsTrafficType;
+import android.hardware.radio.ims.SrvccCall;
+
+/**
+ * This interface is used by IMS telephony layer to talk to cellular radio.
+ * All the functions have minimum one parameter:
+ * serial: which corresponds to serial no. of request. Serial numbers must only be memorized for the
+ * duration of a method call. If clients provide colliding serials (including passing the same
+ * serial to different methods), multiple responses (one for each method call) must still be served.
+ * setResponseFunctions must work with IRadioImsResponse and IRadioImsIndication.
+ */
+@VintfStability
+oneway interface IRadioIms {
+ /**
+ * Provides a list of SRVCC call information to radio.
+ *
+ * @param serial Serial number of request
+ * @param srvccCalls the list of calls
+ *
+ * Response function is IRadioImsResponse.setSrvccCallInfoResponse()
+ */
+ void setSrvccCallInfo(int serial, in SrvccCall[] srvccCalls);
+
+ /**
+ * Update the IMS registration information to the radio.
+ *
+ * This information shall be used by radio to implement following carrier requirements:
+ * 1) Graceful IMS PDN disconnection on cellular when NAS is about to perform detach
+ * eg. SIM removal or SIM refresh
+ * 2) Block PLMN or RAT based on the IMS registration failure reason
+ *
+ * @param serial Serial number of request
+ * @param imsRegistration IMS registration information
+ *
+ * Response function is IRadioImsResponse.updateImsRegistrationInfoResponse()
+ */
+ void updateImsRegistrationInfo(int serial, in ImsRegistration imsRegistration);
+
+ /**
+ * IMS stack notifies the NAS and RRC layers of the radio that the upcoming IMS traffic is
+ * for the service mentioned in the ImsTrafficType. If this API is not
+ * explicitly invoked and IMS module sends traffic on IMS PDN then the radio
+ * shall treat type as background data traffic type.
+ * This API shall be used by modem
+ * 1. To set the appropriate establishment cause in RRC connection request.
+ * 2. To prioritize RF resources in case of DSDS. The service priority is
+ * EMERGENCY > EMERGENCY SMS > VOICE > VIDEO > SMS > REGISTRATION > Ut/XCAP. The RF
+ * shall be prioritized to the subscription which handles higher priority service.
+ * When both subscriptions are handling the same type of service then RF shall be
+ * prioritized to the voice preferred sub.
+ * 3. To evaluate the overall access barring in the case of ACB, ACB-Skp/SCM and UAC.
+ * The response {@link IRadioImsResponse#startImsTrafficResponse()} with success shall
+ * be sent by modem upon access class is allowed and RF resource is allotted. Otherwise
+ * the same API shall be invoked with appropriate {@link ConnectionFailureInfo}. Further
+ * if RRC connection setup fails then {@link IRadioImsIndication#onConnectionSetupFailure()}
+ * shall be invoked by modem with appropriate {@link ConnectionFailureInfo}.
+ *
+ * @param serial Serial number of request
+ * @param token A nonce to identify the request
+ * @param imsTrafficType IMS traffic type like registration, voice, and video
+ * @param accessNetworkType The type of the radio access network used
+ * @param trafficDirection Indicates whether traffic is originated by mobile originated or
+ * mobile terminated use case eg. MO/MT call/SMS etc
+ *
+ * Response function is IRadioImsResponse.startImsTrafficResponse()
+ */
+ void startImsTraffic(int serial, int token,
+ ImsTrafficType imsTrafficType, AccessNetwork accessNetworkType,
+ ImsCall.Direction trafficDirection);
+
+ /**
+ * Indicates IMS traffic has been stopped.
+ * For all IMS traffic, notified with startImsTraffic, IMS service shall notify
+ * stopImsTraffic when it completes the traffic specified by the token.
+ *
+ * @param serial Serial number of request
+ * @param token The token assigned by startImsTraffic()
+ *
+ * Response function is IRadioImsResponse.stopImsTrafficResponse()
+ */
+ void stopImsTraffic(int serial, int token);
+
+ /**
+ * Triggers the UE initiated EPS fallback when a MO voice call failed to establish on 5G NR
+ * network and network didn't initiate a fallback.
+ *
+ * @param serial Serial number of request
+ * @param reason Specifies the reason that causes EPS fallback
+ *
+ * Response function is IRadioImsResponse.triggerEpsFallbackResponse()
+ */
+ void triggerEpsFallback(int serial, in EpsFallbackReason reason);
+
+ /**
+ * Set response functions for IMS radio requests and indications.
+ *
+ * @param radioImsResponse Object containing response functions
+ * @param radioImsIndication Object containing radio indications
+ */
+ void setResponseFunctions(in IRadioImsResponse radioImsResponse,
+ in IRadioImsIndication radioImsIndication);
+
+ /**
+ * Access Network Bitrate Recommendation Query (ANBRQ), see 3GPP TS 26.114.
+ * This API triggers radio to send ANBRQ message
+ * to the access network to query the desired bitrate.
+ *
+ * @param serial Serial number of request
+ * @param mediaType Media type is used to identify media stream such as audio or video
+ * @param direction Direction of this packet stream (e.g. uplink or downlink)
+ * @param bitsPerSecond The bit rate requested by the opponent UE
+ *
+ * Response function is IRadioImsResponse.sendAnbrQueryResponse()
+ */
+ void sendAnbrQuery(int serial, ImsStreamType mediaType, ImsStreamDirection direction, int bitsPerSecond);
+
+ /**
+ * Provides a list of IMS call information to radio.
+ *
+ * @param serial Serial number of request
+ * @param imsCalls The list of IMS calls
+ *
+ * Response function is IRadioImsResponse.updateImsCallStatusResponse()
+ */
+ void updateImsCallStatus(int serial, in ImsCall[] imsCalls);
+}
diff --git a/radio/aidl/android/hardware/radio/ims/IRadioImsIndication.aidl b/radio/aidl/android/hardware/radio/ims/IRadioImsIndication.aidl
new file mode 100644
index 0000000..d123d07
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/IRadioImsIndication.aidl
@@ -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.
+ */
+
+package android.hardware.radio.ims;
+
+import android.hardware.radio.RadioIndicationType;
+import android.hardware.radio.ims.ConnectionFailureInfo;
+import android.hardware.radio.ims.ImsDeregistrationReason;
+import android.hardware.radio.ims.ImsStreamDirection;
+import android.hardware.radio.ims.ImsStreamType;
+
+/**
+ * Interface declaring unsolicited radio indications for ims APIs.
+ */
+@VintfStability
+oneway interface IRadioImsIndication {
+ /**
+ * Fired by radio when any IMS traffic is not sent to network due to any failure
+ * on cellular networks. IMS service shall call stopImsTraffic when receiving
+ * this indication.
+ *
+ * @param type Type of radio indication
+ * @param token The token of startImsTraffic() associated with this indication
+ * @param info Connection failure information
+ */
+ void onConnectionSetupFailure(
+ in RadioIndicationType type, int token, in ConnectionFailureInfo info);
+
+ /**
+ * Access Network Bitrate Recommendation (ANBR), see 3GPP TS 26.114.
+ * Notifies the bit rate received from the network via ANBR message
+ *
+ * @param type Type of radio indication
+ * @param mediaType Media type is used to identify media stream such as audio or video
+ * @param direction Direction of this packet stream (e.g. uplink or downlink)
+ * @param bitsPerSecond The recommended bit rate for the UE
+ * for a specific logical channel and a specific direction by NW
+ */
+ void notifyAnbr(in RadioIndicationType type, in ImsStreamType mediaType,
+ in ImsStreamDirection direction, int bitsPerSecond);
+
+ /**
+ * Requests IMS stack to perform graceful IMS deregistration before radio performing
+ * network detach in the events of SIM remove, refresh or and so on. The radio waits for
+ * the IMS deregistration, which will be notified by telephony via
+ * {@link IRadioIms#updateImsRegistrationInfo()}, or a certain timeout interval to start
+ * the network detach procedure.
+ *
+ * @param type Type of radio indication
+ * @param reason the reason why the deregistration is triggered
+ */
+ void triggerImsDeregistration(in RadioIndicationType type, in ImsDeregistrationReason reason);
+}
diff --git a/radio/aidl/android/hardware/radio/ims/IRadioImsResponse.aidl b/radio/aidl/android/hardware/radio/ims/IRadioImsResponse.aidl
new file mode 100644
index 0000000..241c342
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/IRadioImsResponse.aidl
@@ -0,0 +1,141 @@
+/*
+ * 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.radio.ims;
+
+import android.hardware.radio.RadioResponseInfo;
+import android.hardware.radio.ims.ConnectionFailureInfo;
+
+/**
+ * Interface declaring response functions to solicited radio requests for ims APIs.
+ */
+@VintfStability
+oneway interface IRadioImsResponse {
+
+ /**
+ * @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:NO_MEMORY
+ * RadioError:SYSTEM_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_RESOURCES
+ */
+ void setSrvccCallInfoResponse(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_STATE
+ * RadioError:NO_MEMORY
+ * RadioError:SYSTEM_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_RESOURCES
+ */
+ void updateImsRegistrationInfoResponse(in RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param failureInfo Information about failure in detail
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INVALID_STATE
+ * RadioError:NO_MEMORY
+ * RadioError:SYSTEM_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_RESOURCES
+ */
+ void startImsTrafficResponse(in RadioResponseInfo info,
+ in @nullable ConnectionFailureInfo failureInfo);
+
+ /**
+ * @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:NO_MEMORY
+ * RadioError:SYSTEM_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_RESOURCES
+ */
+ void stopImsTrafficResponse(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_STATE
+ * RadioError:NO_MEMORY
+ * RadioError:SYSTEM_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_RESOURCES
+ */
+ void triggerEpsFallbackResponse(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_STATE
+ * RadioError:NO_MEMORY
+ * RadioError:SYSTEM_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_RESOURCES
+ */
+ void sendAnbrQueryResponse(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_STATE
+ * RadioError:NO_MEMORY
+ * RadioError:SYSTEM_ERR
+ * RadioError:MODEM_ERR
+ * RadioError:INTERNAL_ERR
+ * RadioError:INVALID_ARGUMENTS
+ * RadioError:NO_RESOURCES
+ */
+ void updateImsCallStatusResponse(in RadioResponseInfo info);
+}
diff --git a/radio/aidl/android/hardware/radio/ims/ImsCall.aidl b/radio/aidl/android/hardware/radio/ims/ImsCall.aidl
new file mode 100644
index 0000000..b71682f
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/ImsCall.aidl
@@ -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.
+ */
+
+package android.hardware.radio.ims;
+
+import android.hardware.radio.AccessNetwork;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable ImsCall {
+
+ @Backing(type="int")
+ enum CallType {
+ NORMAL,
+ EMERGENCY,
+ }
+
+ @Backing(type="int")
+ enum CallState {
+ ACTIVE,
+ HOLDING,
+ DIALING, /* Outgoing only */
+ ALERTING, /* Outgoing only */
+ INCOMING, /* Incoming only */
+ WAITING, /* Incoming only */
+ DISCONNECTING,
+ DISCONNECTED,
+ }
+
+ @Backing(type="int")
+ enum Direction {
+ INCOMING,
+ OUTGOING,
+ }
+
+ /** Call index */
+ int index;
+
+ /** The type of the call */
+ CallType callType;
+
+ /** The access network where the call is in progress */
+ AccessNetwork accessNetwork;
+
+ /** The state of the call */
+ CallState callState;
+
+ /** The direction of the call */
+ Direction direction;
+
+ /** True if the call is put on HOLD by the other party */
+ boolean isHeldByRemote;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl b/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.aidl
new file mode 100644
index 0000000..eac8db4
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/ImsDeregistrationReason.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.
+ */
+
+package android.hardware.radio.ims;
+
+@VintfStability
+@JavaDerive(toString=true)
+@Backing(type="int")
+enum ImsDeregistrationReason {
+ /**
+ * Radio shall send this reason to IMS stack to perform graceful de-registration
+ * due to SIM card is removed.
+ */
+ REASON_SIM_REMOVED = 1,
+ /**
+ * Radio shall send this reason to IMS stack to perform graceful de-registration
+ * due to SIM refresh that needs a NAS detach and re-attach.
+ */
+ REASON_SIM_REFRESH = 2,
+ /**
+ * Radio shall send this reason to IMS stack to perform graceful de-registration
+ * due to allowed network types bitmask changed that results in NAS detach.
+ */
+ REASON_ALLOWED_NETWORK_TYPES_CHANGED = 3,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl b/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl
new file mode 100644
index 0000000..662f9e9
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/ImsRegistration.aidl
@@ -0,0 +1,53 @@
+/*
+ * 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.radio.ims;
+
+import android.hardware.radio.AccessNetwork;
+import android.hardware.radio.ims.ImsRegistrationState;
+import android.hardware.radio.ims.SuggestedAction;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable ImsRegistration {
+ /** Default value */
+ const int IMS_MMTEL_CAPABILITY_NONE = 0;
+ /** IMS voice */
+ const int IMS_MMTEL_CAPABILITY_VOICE = 1 << 0;
+ /** IMS video */
+ const int IMS_MMTEL_CAPABILITY_VIDEO = 1 << 1;
+ /** IMS SMS */
+ const int IMS_MMTEL_CAPABILITY_SMS = 1 << 2;
+ /** IMS RCS */
+ const int IMS_RCS_CAPABILITIES = 1 << 3;
+
+ /** Indicates the current IMS registration state. */
+ ImsRegistrationState regState;
+
+ /**
+ * Indicates the type of the radio access network where IMS is registered.
+ */
+ AccessNetwork accessNetworkType;
+
+ /** Indicates the expected action for the radio to do. */
+ SuggestedAction suggestedAction;
+
+ /**
+ * Values are bitwise ORs of IMS_MMTEL_CAPABILITY_* constants and IMS_RCS_CAPABILITIES.
+ * IMS capability such as VOICE, VIDEO, SMS and RCS.
+ */
+ int capabilities;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/ImsRegistrationState.aidl b/radio/aidl/android/hardware/radio/ims/ImsRegistrationState.aidl
new file mode 100644
index 0000000..fd5c0fa
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/ImsRegistrationState.aidl
@@ -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.radio.ims;
+
+@VintfStability
+@JavaDerive(toString=true)
+@Backing(type="int")
+enum ImsRegistrationState {
+ /** IMS is not registered */
+ NOT_REGISTERED,
+
+ /** IMS is successfully registered */
+ REGISTERED,
+}
\ No newline at end of file
diff --git a/radio/aidl/android/hardware/radio/ims/ImsStreamDirection.aidl b/radio/aidl/android/hardware/radio/ims/ImsStreamDirection.aidl
new file mode 100644
index 0000000..c0cea32
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/ImsStreamDirection.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.radio.ims;
+
+@VintfStability
+@JavaDerive(toString=true)
+@Backing(type="int")
+enum ImsStreamDirection {
+ /** DIRECTION_UPLINK - From UE to Network **/
+ UPLINK = 1,
+ /** DIRECTION_DOWNLINK - From Network to UE **/
+ DOWNLINK = 2,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/ImsStreamType.aidl b/radio/aidl/android/hardware/radio/ims/ImsStreamType.aidl
new file mode 100644
index 0000000..c12a0c1
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/ImsStreamType.aidl
@@ -0,0 +1,26 @@
+/*
+ * 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.radio.ims;
+
+@VintfStability
+@Backing(type="int")
+enum ImsStreamType {
+ /** Media Stream Type - Audio **/
+ AUDIO = 1,
+ /** Media Stream Type - Video **/
+ VIDEO = 2,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/ImsTrafficType.aidl b/radio/aidl/android/hardware/radio/ims/ImsTrafficType.aidl
new file mode 100644
index 0000000..5a824c0
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/ImsTrafficType.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.radio.ims;
+
+@VintfStability
+@JavaDerive(toString=true)
+@Backing(type="int")
+enum ImsTrafficType {
+ /** Emergency call */
+ EMERGENCY,
+
+ /** Emergency SMS */
+ EMERGENCY_SMS,
+
+ /** Voice call */
+ VOICE,
+
+ /** Video call */
+ VIDEO,
+
+ /** SMS over IMS */
+ SMS,
+
+ /** IMS registration and subscription for reg event package (signaling) */
+ REGISTRATION,
+
+ /** Ut/XCAP (XML Configuration Access Protocol) */
+ UT_XCAP
+}
\ No newline at end of file
diff --git a/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl b/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl
new file mode 100644
index 0000000..38e6cdb
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/SrvccCall.aidl
@@ -0,0 +1,78 @@
+/*
+ * 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.radio.ims;
+
+@VintfStability
+@JavaDerive(toString=true)
+parcelable SrvccCall {
+
+ @VintfStability
+ @Backing(type="int")
+ enum CallType {
+ NORMAL,
+ EMERGENCY,
+ }
+
+ @VintfStability
+ @Backing(type="int")
+ enum CallSubState {
+ NONE,
+ /** Pre-alerting state. Applicable for MT calls only */
+ PREALERTING,
+ }
+
+ @VintfStability
+ @Backing(type="int")
+ enum ToneType {
+ NONE,
+ LOCAL,
+ NETWORK,
+ }
+
+ /** Connection index */
+ int index;
+
+ /** The type of the call */
+ CallType callType;
+
+ /** Values are android.hardware.radio.voice.Call.STATE_* constants */
+ int callState;
+
+ /** The substate of the call */
+ CallSubState callSubstate;
+
+ /** The type of the ringback tone */
+ ToneType ringbackToneType;
+
+ /** true if is mpty call */
+ boolean isMpty;
+
+ /** true if call is mobile terminated */
+ boolean isMT;
+
+ /** Remote party nummber */
+ String number;
+
+ /** Values are android.hardware.radio.voice.Call.PRESENTATION_* constants */
+ int numPresentation;
+
+ /** Remote party name */
+ String name;
+
+ /** Values are android.hardware.radio.voice.Call.PRESENTATION_* constants */
+ int namePresentation;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl b/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl
new file mode 100644
index 0000000..2d12ed6
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/SuggestedAction.aidl
@@ -0,0 +1,37 @@
+/*
+ * 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.radio.ims;
+
+@VintfStability
+@JavaDerive(toString=true)
+@Backing(type="int")
+enum SuggestedAction {
+ /** Default value */
+ NONE,
+ /**
+ * Indicates that the IMS registration is failed with fatal error such as 403 or 404
+ * on all P-CSCF addresses. The radio shall block the current PLMN or disable
+ * the RAT as per the carrier requirements.
+ */
+ TRIGGER_PLMN_BLOCK,
+ /**
+ * Indicates that the IMS registration on current PLMN failed multiple times.
+ * The radio shall block the current PLMN or disable the RAT during EPS or 5GS mobility
+ * management timer value as per the carrier requirements.
+ */
+ TRIGGER_PLMN_BLOCK_WITH_TIMEOUT,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl b/radio/aidl/android/hardware/radio/ims/media/AmrMode.aidl
new file mode 100644
index 0000000..66d8ef0
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/AmrMode.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.radio.ims.media;
+
+/** AMR codec mode to represent the bit rate. See 3ggp Specs 26.976 & 26.071 */
+@VintfStability
+@Backing(type="int")
+enum AmrMode {
+ /** 4.75 kbps for AMR / 6.6 kbps for AMR-WB */
+ AMR_MODE_0 = 1 << 0,
+ /** 5.15 kbps for AMR / 8.855 kbps for AMR-WB */
+ AMR_MODE_1 = 1 << 1,
+ /** 5.9 kbps for AMR / 12.65 kbps for AMR-WB */
+ AMR_MODE_2 = 1 << 2,
+ /** 6.7 kbps for AMR / 14.25 kbps for AMR-WB */
+ AMR_MODE_3 = 1 << 3,
+ /** 7.4 kbps for AMR / 15.85 kbps for AMR-WB */
+ AMR_MODE_4 = 1 << 4,
+ /** 7.95 kbps for AMR / 18.25 kbps for AMR-WB */
+ AMR_MODE_5 = 1 << 5,
+ /** 10.2 kbps for AMR / 19.85 kbps for AMR-WB */
+ AMR_MODE_6 = 1 << 6,
+ /** 12.2 kbps for AMR / 23.05 kbps for AMR-WB */
+ AMR_MODE_7 = 1 << 7,
+ /** Silence frame for AMR / 23.85 kbps for AMR-WB */
+ AMR_MODE_8 = 1 << 8,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl b/radio/aidl/android/hardware/radio/ims/media/AmrParams.aidl
new file mode 100644
index 0000000..4ed3a24
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/AmrParams.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.radio.ims.media;
+
+import android.hardware.radio.ims.media.AmrMode;
+
+@VintfStability
+parcelable AmrParams {
+ /** mode-set: AMR codec mode to represent the bit rate */
+ AmrMode amrMode;
+ /**
+ * octet-align: If it's set to true then all fields in the AMR/AMR-WB header
+ * shall be aligned to octet boundaries by adding padding bits.
+ */
+ boolean octetAligned;
+ /**
+ * max-red: It’s the maximum duration in milliseconds that elapses between the
+ * primary (first) transmission of a frame and any redundant transmission that
+ * the sender will use. This parameter allows a receiver to have a bounded delay
+ * when redundancy is used. Allowed values are between 0 (no redundancy will be
+ * used) and 65535. If the parameter is omitted, no limitation on the use of
+ * redundancy is present. See RFC 4867
+ */
+ int maxRedundancyMillis;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/AnbrBitrate.aidl b/radio/aidl/android/hardware/radio/ims/media/AnbrBitrate.aidl
new file mode 100644
index 0000000..61239d0
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/AnbrBitrate.aidl
@@ -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.radio.ims.media;
+
+@VintfStability
+parcelable AnbrBitrate {
+ /** default value to represent NOT_SET */
+ const int INVALID_ANBR_BITRATE = -1;
+
+ /** Received bitrate in seconds for Uplink from NW or peer UE for ANBR */
+ int uplinkBps;
+ /** Received bitrate in secondsfor Downlink from NW or peer UE for ANBR */
+ int downlinkBps;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/CallQuality.aidl b/radio/aidl/android/hardware/radio/ims/media/CallQuality.aidl
new file mode 100644
index 0000000..a8f7b16
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/CallQuality.aidl
@@ -0,0 +1,84 @@
+/*
+ * 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.radio.ims.media;
+
+@VintfStability
+parcelable CallQuality {
+ /**
+ * downlink CallQualityLevel for a given ongoing call
+ * this value corresponds to the CALL_QUALITY_* constants in {@link CallQuality}
+ */
+ int downlinkCallQualityLevel;
+ /**
+ * uplink CallQualityLevel for a given ongoing call
+ * this value corresponds to the CALL_QUALITY_* constants in {@link CallQuality}
+ */
+ int uplinkCallQualityLevel;
+ /** the call duration in milliseconds */
+ int callDuration;
+ /** RTP packets sent to network */
+ int numRtpPacketsTransmitted;
+ /** RTP packets received from network */
+ int numRtpPacketsReceived;
+ /** RTP packets which were lost in network and never transmitted */
+ int numRtpPacketsTransmittedLost;
+ /** RTP packets which were lost in network and never received */
+ int numRtpPacketsNotReceived;
+ /** average relative jitter in milliseconds */
+ int averageRelativeJitter;
+ /** maximum relative jitter in milliseconds */
+ int maxRelativeJitter;
+ /** average round trip delay in milliseconds */
+ int averageRoundTripTime;
+ /**
+ * the codec type. This value corresponds to the AUDIO_QUALITY_* constants in
+ * {@link ImsStreamMediaProfile}
+ */
+ int codecType;
+ /** True if no incoming RTP is received for a continuous duration of 4 seconds */
+ boolean rtpInactivityDetected;
+ /**
+ * True if only silence RTP packets are received for 20 seconds
+ * immediately after call is connected
+ */
+ boolean rxSilenceDetected;
+ /**
+ * True if only silence RTP packets are sent for 20 seconds
+ * immediately after call is connected
+ */
+ boolean txSilenceDetected;
+ /** the number of Voice frames sent by jitter buffer to audio */
+ int numVoiceFrames;
+ /** the number of no-data frames sent by jitter buffer to audio */
+ int numNoDataFrames;
+ /** the number of RTP voice packets dropped by jitter buffer */
+ int numDroppedRtpPackets;
+ /** the minimum playout delay in the reporting interval in milliseconds */
+ long minPlayoutDelayMillis;
+ /** the maximum playout delay in the reporting interval in milliseconds */
+ long maxPlayoutDelayMillis;
+ /**
+ * the total number of RTP SID (Silence Insertion Descriptor) packets
+ * received by this device for an ongoing call
+ */
+ int numRtpSidPacketsReceived;
+ /**
+ * the total number of RTP duplicate packets received by this device
+ * for an ongoing call
+ */
+ int numRtpDuplicatePackets;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl b/radio/aidl/android/hardware/radio/ims/media/CodecParams.aidl
new file mode 100644
index 0000000..0aa5505
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/CodecParams.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.radio.ims.media;
+
+import android.hardware.radio.ims.media.CodecSpecificParams;
+import android.hardware.radio.ims.media.CodecType;
+
+@VintfStability
+parcelable CodecParams {
+ /** Negotiated codec type */
+ CodecType codecType;
+ /**
+ * Static or dynamic payload type number negotiated through the SDP for
+ * the incoming RTP packets. This value shall be matched with the PT value
+ * of the incoming RTP header. Values 0 to 127, see RFC 3551 section 6
+ */
+ byte rxPayloadTypeNumber;
+ /**
+ * Static or dynamic payload type number negotiated through the SDP for
+ * the outgoing RTP packets. This value shall be set to the PT value
+ * of the outgoing RTP header. Values 0 to 127, see RFC 3551 section 6
+ */
+ byte txPayloadTypeNumber;
+ /** Sampling rate in kHz*/
+ byte samplingRateKHz;
+ /** dtx: Whether discontinuous transmission is enabled or not */
+ boolean dtxEnabled;
+ /** Codec specific parameters */
+ CodecSpecificParams codecSpecificParams;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/CodecSpecificParams.aidl b/radio/aidl/android/hardware/radio/ims/media/CodecSpecificParams.aidl
new file mode 100644
index 0000000..4410c81
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/CodecSpecificParams.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.radio.ims.media;
+
+import android.hardware.radio.ims.media.AmrParams;
+import android.hardware.radio.ims.media.EvsParams;
+
+@VintfStability
+union CodecSpecificParams {
+ AmrParams amr;
+ EvsParams evs;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl b/radio/aidl/android/hardware/radio/ims/media/CodecType.aidl
new file mode 100644
index 0000000..31218e3
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/CodecType.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.radio.ims.media;
+
+@VintfStability
+@Backing(type="int")
+enum CodecType {
+ /** Adaptive Multi-Rate */
+ AMR = 1 << 0,
+ /** Adaptive Multi-Rate Wide Band */
+ AMR_WB = 1 << 1,
+ /** Enhanced Voice Services */
+ EVS = 1 << 2,
+ /** G.711 A-law i.e. Pulse Code Modulation using A-law */
+ PCMA = 1 << 3,
+ /** G.711 μ-law i.e. Pulse Code Modulation using μ-law */
+ PCMU = 1 << 4,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/DtmfParams.aidl b/radio/aidl/android/hardware/radio/ims/media/DtmfParams.aidl
new file mode 100644
index 0000000..a7dcb0d
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/DtmfParams.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.radio.ims.media;
+
+@VintfStability
+parcelable DtmfParams {
+ /**
+ * Dynamic payload type number to be used for DTMF RTP packets received.
+ * The values is in the range from 96 to 127 chosen during the session
+ * establishment. The PT value of the RTP header of all DTMF packets shall be
+ * set with this value.
+ */
+ byte rxPayloadTypeNumber;
+
+ /**
+ * Dynamic payload type number to be used for DTMF RTP packets sent.
+ * The values is in the range from 96 to 127 chosen during the session
+ * establishment. The PT value of the RTP header of all DTMF packets shall be set
+ * with this value.
+ */
+ byte txPayloadTypeNumber;
+
+ /** Sampling rate in kHz */
+ byte samplingRateKHz;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/EvsBandwidth.aidl b/radio/aidl/android/hardware/radio/ims/media/EvsBandwidth.aidl
new file mode 100644
index 0000000..8278514
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/EvsBandwidth.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.radio.ims.media;
+/** EVS Speech codec bandwidths, See 3gpp spec 26.441 Table 1 */
+@VintfStability
+@Backing(type="int")
+enum EvsBandwidth {
+ NONE = 0,
+ NARROW_BAND = 1 << 0,
+ WIDE_BAND = 1 << 1,
+ SUPER_WIDE_BAND = 1 << 2,
+ FULL_BAND = 1 << 3,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl b/radio/aidl/android/hardware/radio/ims/media/EvsMode.aidl
new file mode 100644
index 0000000..95bd6c7
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/EvsMode.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.radio.ims.media;
+
+/** EVS codec mode to represent the bit rate. See 3ggp Spec 26.952 Table 5.1 */
+@VintfStability
+@Backing(type="int")
+enum EvsMode {
+ /** 6.6 kbps for EVS AMR-WB IO */
+ EVS_MODE_0 = 1 << 0,
+ /** 8.855 kbps for AMR-WB IO */
+ EVS_MODE_1 = 1 << 1,
+ /** 12.65 kbps for AMR-WB IO */
+ EVS_MODE_2 = 1 << 2,
+ /** 14.25 kbps for AMR-WB IO */
+ EVS_MODE_3 = 1 << 3,
+ /** 15.85 kbps for AMR-WB IO */
+ EVS_MODE_4 = 1 << 4,
+ /** 18.25 kbps for AMR-WB IO */
+ EVS_MODE_5 = 1 << 5,
+ /** 19.85 kbps for AMR-WB IO */
+ EVS_MODE_6 = 1 << 6,
+ /** 23.05 kbps for AMR-WB IO */
+ EVS_MODE_7 = 1 << 7,
+ /** 23.85 kbps for AMR-WB IO */
+ EVS_MODE_8 = 1 << 8,
+ /** 5.9 kbps for EVS primary */
+ EVS_MODE_9 = 1 << 9,
+ /** 7.2 kbps for EVS primary */
+ EVS_MODE_10 = 1 << 10,
+ /** 8.0 kbps for EVS primary */
+ EVS_MODE_11 = 1 << 11,
+ /** 9.6 kbps for EVS primary */
+ EVS_MODE_12 = 1 << 12,
+ /** 13.2 kbps for EVS primary */
+ EVS_MODE_13 = 1 << 13,
+ /** 16.4 kbps for EVS primary */
+ EVS_MODE_14 = 1 << 14,
+ /** 24.4 kbps for EVS primary */
+ EVS_MODE_15 = 1 << 15,
+ /** 32.0 kbps for EVS primary */
+ EVS_MODE_16 = 1 << 16,
+ /** 48.0 kbps for EVS primary */
+ EVS_MODE_17 = 1 << 17,
+ /** 64.0 kbps for EVS primary */
+ EVS_MODE_18 = 1 << 18,
+ /** 96.0 kbps for EVS primary */
+ EVS_MODE_19 = 1 << 19,
+ /** 128.0 kbps for EVS primary */
+ EVS_MODE_20 = 1 << 20,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl b/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl
new file mode 100644
index 0000000..d138c83
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/EvsParams.aidl
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ims.media;
+
+import android.hardware.radio.ims.media.EvsBandwidth;
+import android.hardware.radio.ims.media.EvsMode;
+
+@VintfStability
+parcelable EvsParams {
+ /** EVS codec bandwidth */
+ EvsBandwidth bandwidth;
+
+ /** mode-set: EVS codec mode to represent the bit rate */
+ EvsMode evsMode;
+ /**
+ * ch-aw-recv: Channel aware mode for the receive direction. Permissible values
+ * are -1, 0, 2, 3, 5, and 7. If -1, channel-aware mode is disabled in the
+ * session for the receive direction. If 0 or not present, partial redundancy
+ * (channel-aware mode) is not used at the start of the session for the receive
+ * direction. If positive (2, 3, 5, or 7), partial redundancy (channel-aware
+ * mode) is used at the start of the session for the receive direction using the
+ * value as the offset, See 3GPP TS 26.445 section 4.4.5
+ */
+ byte channelAwareMode;
+ /**
+ * hf-only: Header full only is used for the outgoing and incoming packets.
+ * If it's true then the session shall support header full format only else the
+ * session could support both header full format and compact format.
+ */
+ boolean useHeaderFullOnly;
+ /**
+ * evs-mode-switch: Used for switching between EVS Primary mode and EVS AMR-WB IO mode,
+ * If this value is true, the codec operates in AMR-WB IO mode
+ */
+ boolean useEvsModeSwitch;
+ /**
+ * cmr: Codec mode request is used to request the speech codec encoder of the
+ * other party to set the frame type index of speech mode via RTP header, See
+ * 3GPP TS 26.445 section A.3. Allowed values are -1, 0 and 1.
+ */
+ byte codecModeRequest;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMedia.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMedia.aidl
new file mode 100644
index 0000000..ecf1370
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMedia.aidl
@@ -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 android.hardware.radio.ims.media;
+
+import android.hardware.radio.ims.media.IImsMediaListener;
+import android.hardware.radio.ims.media.LocalEndPoint;
+import android.hardware.radio.ims.media.RtpConfig;
+import android.hardware.radio.ims.media.RtpError;
+
+/**
+ * This interface is used by IMS media framework to talk to RTP stack located in another processor.
+ */
+@VintfStability
+oneway interface IImsMedia {
+
+ /**
+ * Set the listener functions for receiving notifications from the RTP stack.
+ *
+ * @param mediaListener Object containing listener methods
+ */
+ void setListener(in IImsMediaListener mediaListener);
+
+ /**
+ * Opens a RTP session for the local end point with the associated initial remote configuration
+ * if there is a valid RtpConfig passed. It starts the media flow if the media direction in the
+ * RtpConfig is set to any value other than NO_MEDIA_FLOW. If the open session is successful
+ * then the implementation shall return a new IImsMediaSession binder connection for this
+ * session using IImsMediaListener#onOpenSessionSuccess() API. If the open session is failed
+ * then the implementation shall return the error using IImsMediaListener#onOpenSessionFailure()
+ *
+ * @param sessionId unique identifier of the session
+ * @param localEndPoint provides IP address, port and logical modem id for local RTP endpoint
+ * @param config provides remote end point info and codec details. This could be null initially
+ * and the application may update this later using modifySession() API.
+ */
+ void openSession(int sessionId, in LocalEndPoint localEndPoint, in RtpConfig config);
+
+ /**
+ * Close the RTP session including cleanup of all the resources associated with the session.
+ * This shall also close the session specific binder connection opened as part of openSession().
+ *
+ * @param sessionId identifier for the rtp session that needs to be closed
+ */
+ void closeSession(int sessionId);
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaListener.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaListener.aidl
new file mode 100644
index 0000000..228acb7
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaListener.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.ims.media;
+
+import android.hardware.radio.ims.media.IImsMediaSession;
+import android.hardware.radio.ims.media.RtpError;
+
+/**
+ * Interface declaring listener functions for unsolicited IMS media notifications.
+ */
+@VintfStability
+oneway interface IImsMediaListener {
+ /**
+ * Fired when a IImsMedia#openSession() API is successful.
+ *
+ * @param sessionId identifier of the session
+ * @param session new IImsMediaSession binder connection to be used for the session
+ * specific operations
+ */
+ void onOpenSessionSuccess(int sessionId, IImsMediaSession session);
+
+ /**
+ * Fired when IImsMedia#openSession() API failed to create a new session.
+ *
+ * @param sessionId identifier of the session
+ * @param error one of the following RTP error code
+ * RtpError :INVALID_PARAM
+ * RtpError :INTERNAL_ERR
+ * RtpError :NO_MEMORY
+ * RtpError :NO_RESOURCES
+ * RtpError :PORT_UNAVAILABLE
+ */
+ void onOpenSessionFailure(int sessionId, RtpError error);
+
+ /**
+ * Fired when IImsMedia#closeSession() API handled.
+ *
+ * @param sessionId identifier of the session
+ */
+ void onSessionClosed(int sessionId);
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
new file mode 100644
index 0000000..a8d2161
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSession.aidl
@@ -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.
+ */
+
+package android.hardware.radio.ims.media;
+
+import android.hardware.radio.ims.media.IImsMediaSessionListener;
+import android.hardware.radio.ims.media.MediaProtocolType;
+import android.hardware.radio.ims.media.MediaQualityThreshold;
+import android.hardware.radio.ims.media.RtpConfig;
+import android.hardware.radio.ims.media.RtpError;
+import android.hardware.radio.ims.media.RtpHeaderExtension;
+
+/**
+ * Session specific interface used by IMS media framework to talk to the vendor RTP stack.
+ */
+@VintfStability
+oneway interface IImsMediaSession {
+ /**
+ * Set the listener functions to receive IMS media session specific notifications.
+ *
+ * @param sessionListener Object containing notification methods
+ */
+ void setListener(in IImsMediaSessionListener sessionListener);
+
+ /**
+ * Modifies the configuration of the RTP session. It can be used to pause/resume
+ * the media stream by changing the value of the MediaDirection.
+ *
+ * @param config provides remote end point info and codec details
+ */
+ void modifySession(in RtpConfig config);
+
+ /**
+ * Send DTMF digit until the duration expires.
+ *
+ * @param dtmfDigit single char having one of 12 values: 0-9, *, #
+ * @param duration of the key press in milliseconds.
+ */
+ void sendDtmf(char dtmfDigit, int duration);
+
+ /**
+ * Start sending DTMF digit until the stopDtmf() API is received.
+ * If the implementation is currently sending a DTMF tone for which
+ * stopDtmf() is not received yet, then that digit must be stopped first
+ *
+ * @param dtmfDigit single char having one of 12 values: 0-9, *, #
+ */
+ void startDtmf(char dtmfDigit);
+
+ /**
+ * Stop sending the last DTMF digit started by startDtmf().
+ * stopDtmf() without preceding startDtmf() must be ignored.
+ */
+ void stopDtmf();
+
+ /**
+ * Send RTP header extension to the other party in the next RTP packet.
+ *
+ * @param extensions data to be transmitted via RTP header extension
+ */
+ void sendHeaderExtension(in List<RtpHeaderExtension> extensions);
+
+ /**
+ * Sets the media quality threshold parameters of the session to get
+ * media quality notifications.
+ *
+ * @param threshold media quality thresholds for various quality parameters
+ */
+ void setMediaQualityThreshold(in MediaQualityThreshold threshold);
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
new file mode 100644
index 0000000..d40da64
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/IImsMediaSessionListener.aidl
@@ -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.
+ */
+
+package android.hardware.radio.ims.media;
+
+import android.hardware.radio.ims.media.CallQuality;
+import android.hardware.radio.ims.media.MediaProtocolType;
+import android.hardware.radio.ims.media.RtpConfig;
+import android.hardware.radio.ims.media.RtpError;
+import android.hardware.radio.ims.media.RtpHeaderExtension;
+
+/**
+ * Interface declaring listener functions for unsolicited IMS media notifications per session.
+ */
+@VintfStability
+oneway interface IImsMediaSessionListener {
+ /**
+ * Notifies the result of IImsMediaSession#modifySession() API.
+ *
+ * @param config The RTP config passed in IImsMediaSession#modifySession() API
+ * @param error RtpError.NONE in case of success else one of the following
+ * RtpError :INVALID_PARAM
+ * RtpError :INTERNAL_ERR
+ * RtpError :NO_MEMORY
+ * RtpError :NO_RESOURCES
+ */
+ void onModifySessionResponse(in RtpConfig config, RtpError error);
+
+ /**
+ * Indicates when the first Rtp media packet is received by the UE during ring
+ * back, call hold or early media scenarios. This is sent only if the packet is
+ * received on the active remote configuration.
+ *
+ * In case of early media scenarios, the implementation shall play the RTP
+ * packets from the most recently added config.
+ *
+ * @param config The remote config where the media is received
+ */
+ void onFirstMediaPacketReceived(in RtpConfig config);
+
+ /**
+ * RTP header extension received from the other party
+ *
+ * @param extensions content of the received RTP header extension
+ */
+ void onHeaderExtensionReceived(in List<RtpHeaderExtension> extensions);
+
+ /**
+ * Notifies media inactivity observed as per thresholds set by
+ * setMediaQualityThreshold() API
+ *
+ * @param packetType either RTP or RTCP
+ */
+ void notifyMediaInactivity(MediaProtocolType packetType);
+
+ /**
+ * Notifies RTP packet loss observed as per thresholds set by
+ * setMediaQualityThreshold() API
+ *
+ * @param packetLossPercentage percentage of packet loss calculated over the duration
+ */
+ void notifyPacketLoss(int packetLossPercentage);
+
+ /**
+ * Notifies RTP jitter observed as per thresholds set by
+ * IImsMediaSession#setMediaQualityThreshold() API
+ *
+ * @param jitter jitter of the RTP packets in milliseconds calculated over the duration
+ */
+ void notifyJitter(int jitter);
+
+ /**
+ * The modem RTP stack fires this API to query whether the desired bitrate mentioned
+ * in the RtpConfig is currently available on the NW or not using ANBRQ message.
+ * See 3GPP TS 26.114.
+ *
+ * @param config containing desired bitrate and direction
+ */
+ void triggerAnbrQuery(in RtpConfig config);
+
+ /**
+ * Notifies the received DTMF digit from the other party
+ *
+ * @param dtmfDigit single char having one of 12 values: 0-9, *, #
+ */
+ void onDtmfReceived(char dtmfDigit);
+
+ /**
+ * Notifies when a change to call quality has occurred
+ *
+ * @param CallQuality The call quality statistics of ongoing call since last report
+ */
+ void onCallQualityChanged(in CallQuality callQuality);
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/LocalEndPoint.aidl b/radio/aidl/android/hardware/radio/ims/media/LocalEndPoint.aidl
new file mode 100644
index 0000000..2bd48c6
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/LocalEndPoint.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.radio.ims.media;
+
+import android.os.ParcelFileDescriptor;
+
+@VintfStability
+parcelable LocalEndPoint {
+ /** Socket file descriptor for RTP traffic */
+ ParcelFileDescriptor rtpFd;
+ /** Socket file descriptor for RTCP traffic */
+ ParcelFileDescriptor rtcpFd;
+ /** The logical modem ID, returned by IRadioConfig.getPhoneCapability() */
+ int modemId;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/MediaDirection.aidl b/radio/aidl/android/hardware/radio/ims/media/MediaDirection.aidl
new file mode 100644
index 0000000..9f04d8e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/MediaDirection.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.radio.ims.media;
+
+@VintfStability
+@Backing(type="int")
+enum MediaDirection {
+ /**
+ * No RTP/RTCP flow in either direction. The implementation
+ * may release the audio resource. Eg. SRVCC.
+ */
+ NO_FLOW = 0,
+ /** Device sends outgoing RTP and drops incoming RTP */
+ SEND_ONLY = 1,
+ /** Device receives the downlink RTP and does not transmit any uplink RTP */
+ RECEIVE_ONLY = 2,
+ /** Device sends and receive RTP in both directions */
+ SEND_RECEIVE = 3,
+ /** No RTP flow however RTCP continues to flow. Eg. HOLD */
+ INACTIVE = 4,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/MediaProtocolType.aidl b/radio/aidl/android/hardware/radio/ims/media/MediaProtocolType.aidl
new file mode 100644
index 0000000..325c6fa
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/MediaProtocolType.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.radio.ims.media;
+
+@VintfStability
+@Backing(type="int")
+enum MediaProtocolType {
+ /** Real Time Protocol, see RFC 3550 */
+ RTP = 0,
+ /** Real Time Control Protocol, see RFC 3550 */
+ RTCP = 1,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/MediaQualityThreshold.aidl b/radio/aidl/android/hardware/radio/ims/media/MediaQualityThreshold.aidl
new file mode 100644
index 0000000..946bd5c
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/MediaQualityThreshold.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.radio.ims.media;
+
+@VintfStability
+parcelable MediaQualityThreshold {
+ /** Timer in milliseconds for monitoring RTP inactivity */
+ int rtpInactivityTimerMillis;
+ /** Timer in milliseconds for monitoring RTCP inactivity */
+ int rtcpInactivityTimerMillis;
+ /** Duration in milliseconds for monitoring the RTP packet loss rate */
+ int rtpPacketLossDurationMillis;
+ /**
+ * Packet loss rate in percentage of (total number of packets lost) /
+ * (total number of packets expected) during rtpPacketLossDurationMs
+ */
+ int rtpPacketLossRate;
+ /** Duration in milliseconds for monitoring the jitter for RTP traffic */
+ int jitterDurationMillis;
+ /** RTP jitter threshold in milliseconds */
+ int rtpJitterMillis;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtcpConfig.aidl b/radio/aidl/android/hardware/radio/ims/media/RtcpConfig.aidl
new file mode 100644
index 0000000..98bbfc6
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/RtcpConfig.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.radio.ims.media;
+
+@VintfStability
+parcelable RtcpConfig {
+ /** Canonical name that will be sent to all session participants */
+ String canonicalName;
+ /** Port for sending outgoing RTCP packets */
+ int transmitPort;
+ /** Transmit interval in seconds. Value 0 indicates that RTCP reports should not be reported */
+ int transmitIntervalSec;
+ /** Bitmask of RTCP-XR blocks to enable as in RtcpXrReportBlockType */
+ int rtcpXrBlocks;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl b/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.aidl
new file mode 100644
index 0000000..7f6839a
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/RtcpXrReportBlockType.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.ims.media;
+
+/** RTP Control Protocol Extended Reports (RTCP XR) Blocks, See RFC 3611 section 4 */
+
+@VintfStability
+@Backing(type="int")
+enum RtcpXrReportBlockType {
+ /** Disable RTCP XR */
+ RTCPXR_NONE = 0,
+ /** Loss RLE Report Block */
+ RTCPXR_LOSS_RLE_REPORT_BLOCK = 1 << 0,
+ /** Duplicate RLE Report Block */
+ RTCPXR_DUPLICATE_RLE_REPORT_BLOCK = 1 << 1,
+ /** Packet Receipt Times Report Block */
+ RTCPXR_PACKET_RECEIPT_TIMES_REPORT_BLOCK = 1 << 2,
+ /** Receiver Reference Time Report Block */
+ RTCPXR_RECEIVER_REFERENCE_TIME_REPORT_BLOCK = 1 << 3,
+ /** DLRR Report Block */
+ RTCPXR_DLRR_REPORT_BLOCK = 1 << 4,
+ /** Statistics Summary Report Block */
+ RTCPXR_STATISTICS_SUMMARY_REPORT_BLOCK = 1 << 5,
+ /** VoIP Metrics Report Block */
+ RTCPXR_VOIP_METRICS_REPORT_BLOCK = 1 << 6,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpAddress.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpAddress.aidl
new file mode 100644
index 0000000..2db73a3
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpAddress.aidl
@@ -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.
+ */
+
+package android.hardware.radio.ims.media;
+
+@VintfStability
+parcelable RtpAddress {
+ /** Point to point IP address */
+ String ipAddress;
+ /** UDP port number used for the RTP traffic */
+ int portNumber;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpConfig.aidl
new file mode 100644
index 0000000..d0d849e
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpConfig.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.
+ */
+
+package android.hardware.radio.ims.media;
+
+import android.hardware.radio.AccessNetwork;
+import android.hardware.radio.ims.media.AnbrBitrate;
+import android.hardware.radio.ims.media.MediaDirection;
+import android.hardware.radio.ims.media.RtcpConfig;
+import android.hardware.radio.ims.media.RtpAddress;
+import android.hardware.radio.ims.media.RtpSessionParams;
+
+@VintfStability
+parcelable RtpConfig {
+ /** Media flow direction */
+ MediaDirection direction;
+ /** Radio Access Network */
+ AccessNetwork accessNetwork;
+ /** IP address and port number of the other party for RTP media */
+ RtpAddress remoteAddress;
+ /** Negotiated session parameters */
+ RtpSessionParams sessionParams;
+ /** RTCP configuration */
+ RtcpConfig rtcpConfig;
+ /**
+ * ANBR Bitrate parameters. This is set to valid only when its triggered,
+ * otherwise it shall be set to NULL.
+ *
+ * This would be used in the following two cases
+ * - IImsMediaSession#modifySession(RtpConfig) - When RAN wants to change the bit
+ * rate via ANBR MAC layer signaling, ImsStack would set the values and direction
+ * and pass it in the modifySession(). The underlying RTP stack shall adapt to
+ * the changed bitrate.
+ *
+ * - IImsMediaSessionListener#triggerAnbrQuery(RtpConfig) - When the vendor RTP
+ * stack receives a request for bitrate increase from the peer terminal via CMR,
+ * RTCP-APP or TMMBR, it triggers ANBRQ by setting the desired bitrate and the
+ * direction of the stream.
+ */
+ AnbrBitrate anbrBitrateParams;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpError.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpError.aidl
new file mode 100644
index 0000000..11a3468
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpError.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.radio.ims.media;
+
+@VintfStability
+@Backing(type="int")
+enum RtpError {
+ /** Success */
+ NONE = 0,
+ /** Invalid parameters passed in the request */
+ INVALID_PARAM = 1,
+ /** The RTP stack is not ready to handle the request */
+ NOT_READY = 2,
+ /** Unable to handle the request due to memory allocation failure */
+ NO_MEMORY = 3,
+ /** Unable to handle the request due to no sufficient resources such as audio, codec */
+ NO_RESOURCES = 4,
+ /** The requested port number is not available */
+ PORT_UNAVAILABLE = 5,
+ /** The request is not supported by the implementation */
+ NOT_SUPPORTED = 6,
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpHeaderExtension.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpHeaderExtension.aidl
new file mode 100644
index 0000000..76b13dc
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpHeaderExtension.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.radio.ims.media;
+
+/** RTP Header Extensions, see RFC 8285 */
+@VintfStability
+parcelable RtpHeaderExtension {
+ /** Local identifier */
+ int localId;
+ /** Extension data bytes */
+ byte[] data;
+}
diff --git a/radio/aidl/android/hardware/radio/ims/media/RtpSessionParams.aidl b/radio/aidl/android/hardware/radio/ims/media/RtpSessionParams.aidl
new file mode 100644
index 0000000..f93c52c
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/ims/media/RtpSessionParams.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.ims.media;
+
+import android.hardware.radio.ims.media.CodecParams;
+import android.hardware.radio.ims.media.DtmfParams;
+
+@VintfStability
+parcelable RtpSessionParams {
+ /**
+ * ptime: Recommended length of time in milliseconds represented by the media
+ * in each packet, see RFC 4566
+ */
+ byte pTimeMillis;
+ /**
+ * maxptime: Maximum amount of media that can be encapsulated in each packet
+ * represented in milliseconds, see RFC 4566
+ */
+ int maxPtimeMillis;
+ /** dscp: Differentiated Services Field Code Point value, see RFC 2474 */
+ byte dscp;
+ /** DTMF payload and clock rate */
+ DtmfParams dtmfParams;
+ /** Negotiated codec parameters */
+ CodecParams codecParams;
+}
diff --git a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
index 492755f..8cbc869 100644
--- a/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
+++ b/radio/aidl/android/hardware/radio/messaging/IRadioMessagingResponse.aidl
@@ -36,7 +36,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void acknowledgeIncomingGsmSmsWithPduResponse(in RadioResponseInfo info);
@@ -56,7 +55,6 @@
* RadioError:NETWORK_NOT_READY
* RadioError:INVALID_MODEM_STATE
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -73,7 +71,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void acknowledgeLastIncomingGsmSmsResponse(in RadioResponseInfo info);
@@ -98,7 +95,6 @@
* RadioError:MODEM_ERR
* RadioError:NO_SUCH_ENTRY
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -122,7 +118,6 @@
* RadioError:NO_SUCH_ENTRY
* RadioError:INTERNAL_ERR
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
@@ -145,7 +140,6 @@
* RadioError:MODEM_ERR
* RadioError:NO_RESOURCES
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
@@ -168,7 +162,6 @@
* RadioError:MODEM_ERR
* RadioError:NO_RESOURCES
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
@@ -191,7 +184,6 @@
* RadioError:MODEM_ERR
* RadioError:INVALID_MODEM_STATE
* RadioError:NOT_PROVISIONED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -212,7 +204,6 @@
* RadioError:MODEM_ERR
* RadioError:INVALID_STATE
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
@@ -240,7 +231,6 @@
* RadioError:MODEM_ERR
* RadioError:NETWORK_ERR
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NETWORK_NOT_READY
* RadioError:OPERATION_NOT_ALLOWED
@@ -275,7 +265,6 @@
* RadioError:INVALID_SMSC_ADDRESS
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:ENCODING_ERR
* RadioError:NO_RESOURCES
@@ -308,7 +297,6 @@
* RadioError:ENCODING_ERR
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NETWORK_NOT_READY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -336,7 +324,6 @@
* RadioError:MODEM_ERR
* RadioError:NETWORK_ERR
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NETWORK_NOT_READY
* RadioError:OPERATION_NOT_ALLOWED
@@ -368,7 +355,6 @@
* RadioError:MODEM_ERR
* RadioError:NETWORK_ERR
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NETWORK_NOT_READY
* RadioError:OPERATION_NOT_ALLOWED
@@ -393,7 +379,6 @@
* RadioError:SYSTEM_ERR
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -414,7 +399,6 @@
* RadioError:SYSTEM_ERR
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
@@ -434,7 +418,6 @@
* RadioError:SYSTEM_ERR
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -455,7 +438,6 @@
* RadioError:SYSTEM_ERR
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
@@ -476,7 +458,6 @@
* RadioError:MODEM_ERR
* RadioError:NO_RESOURCES
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -502,7 +483,6 @@
* RadioError:INVALID_MODEM_STATE
* RadioError:INVALID_SMSC_ADDRESS
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -531,7 +511,6 @@
* RadioError:INVALID_SMSC_ADDRESS
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
* RadioError:SIM_ABSENT
diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
index ba0ddb9..a5d98d3 100644
--- a/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModem.aidl
@@ -117,6 +117,8 @@
* @param itemId NvItem
*
* Response function is IRadioModemResponse.nvReadItemResponse()
+ *
+ * @deprecated NV APIs are deprecated starting from Android U.
*/
void nvReadItem(in int serial, in NvItem itemId);
@@ -128,6 +130,8 @@
* @param resetType ResetNvType
*
* Response function is IRadioModemResponse.nvResetConfigResponse()
+ *
+ * Note: This will be deprecated in favor of a rebootModem API in Android U.
*/
void nvResetConfig(in int serial, in ResetNvType resetType);
@@ -139,6 +143,8 @@
* @param prl PRL as a byte array
*
* Response function is IRadioModemResponse.nvWriteCdmaPrlResponse()
+ *
+ * @deprecated NV APIs are deprecated starting from Android U.
*/
void nvWriteCdmaPrl(in int serial, in byte[] prl);
@@ -150,6 +156,8 @@
* @param item NvWriteItem
*
* Response function is IRadioModemResponse.nvWriteItemResponse()
+ *
+ * @deprecated NV APIs are deprecated starting from Android U.
*/
void nvWriteItem(in int serial, in NvWriteItem item);
diff --git a/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl b/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
index b17cac4..eca3192 100644
--- a/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
+++ b/radio/aidl/android/hardware/radio/modem/IRadioModemResponse.aidl
@@ -61,7 +61,6 @@
* RadioError:SYSTEM_ERR
* RadioError:MODEM_ERR
* RadioError:NOT_PROVISIONED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -88,7 +87,6 @@
* RadioError:NOT_PROVISIONED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void getDeviceIdentityResponse(in RadioResponseInfo info, in String imei, in String imeisv,
in String esn, in String meid);
@@ -100,7 +98,6 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void getHardwareConfigResponse(in RadioResponseInfo info, in HardwareConfig[] config);
@@ -118,7 +115,6 @@
* RadioError:NOT_PROVISIONED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void getModemActivityInfoResponse(in RadioResponseInfo info, in ActivityStatsInfo activityInfo);
@@ -141,7 +137,6 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:INVALID_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INTERNAL_ERR
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
@@ -156,7 +151,8 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
+ *
+ * @deprecated NV APIs are deprecated starting from Android U.
*/
void nvReadItemResponse(in RadioResponseInfo info, in String result);
@@ -166,7 +162,8 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
+ *
+ * Note: This will be deprecated in favor of a rebootModemResponse API in Android U.
*/
void nvResetConfigResponse(in RadioResponseInfo info);
@@ -176,7 +173,8 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
+ *
+ * @deprecated NV APIs are deprecated starting from Android U.
*/
void nvWriteCdmaPrlResponse(in RadioResponseInfo info);
@@ -186,7 +184,8 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
+ *
+ * @deprecated NV APIs are deprecated starting from Android U.
*/
void nvWriteItemResponse(in RadioResponseInfo info);
@@ -200,7 +199,6 @@
* RadioError:NO_MEMORY
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -216,7 +214,6 @@
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
* RadioError:INVALID_ARGUMENTS
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -237,7 +234,6 @@
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
* RadioError:INVALID_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
diff --git a/radio/aidl/android/hardware/radio/modem/NvItem.aidl b/radio/aidl/android/hardware/radio/modem/NvItem.aidl
index 649b0d2..310b1ad 100644
--- a/radio/aidl/android/hardware/radio/modem/NvItem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/NvItem.aidl
@@ -16,6 +16,7 @@
package android.hardware.radio.modem;
+/** @deprecated NV APIs are deprecated starting from Android U. */
@VintfStability
@Backing(type="int")
@JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl b/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
index 47fb490..6472f23 100644
--- a/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
+++ b/radio/aidl/android/hardware/radio/modem/NvWriteItem.aidl
@@ -18,6 +18,7 @@
import android.hardware.radio.modem.NvItem;
+/** @deprecated NV APIs are deprecated starting from Android U. */
@VintfStability
@JavaDerive(toString=true)
parcelable NvWriteItem {
diff --git a/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
index 16487f8..6476fe8 100644
--- a/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
+++ b/radio/aidl/android/hardware/radio/modem/ResetNvType.aidl
@@ -16,6 +16,7 @@
package android.hardware.radio.modem;
+/** Note: This will be deprecated along with nvResetConfig in Android U. */
@VintfStability
@Backing(type="int")
@JavaDerive(toString=true)
diff --git a/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl b/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
index ec70e17..2215149 100644
--- a/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/EmergencyRegResult.aidl
@@ -38,6 +38,11 @@
Domain emcDomain;
/**
+ * This indicates whether the network supports voice over PS network.
+ */
+ boolean isVopsSupported;
+
+ /**
* This indicates if camped network support VoLTE emergency bearers.
* This should only be set if the UE is in LTE mode.
*/
diff --git a/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl b/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
index c9563ac..b986944 100644
--- a/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
+++ b/radio/aidl/android/hardware/radio/network/EutranRegistrationInfo.aidl
@@ -22,6 +22,21 @@
@VintfStability
@JavaDerive(toString=true)
parcelable EutranRegistrationInfo {
+ enum AttachResultType {
+ /** Default value. */
+ NONE,
+ /** LTE is attached with eps only. */
+ EPS_ONLY,
+ /** LTE combined EPS and IMSI attach. */
+ COMBINED,
+ }
+
+ /** LTE combined attach with CSFB not preferred */
+ const int EXTRA_CSFB_NOT_PREFERRED = 1 << 0;
+
+ /** LTE combined attach for SMS only */
+ const int EXTRA_SMS_ONLY = 1 << 1;
+
/**
* Network capabilities for voice over PS services. This info is valid only on LTE network and
* must be present when device is camped on LTE. VopsInfo must be empty when device is camped
@@ -33,4 +48,13 @@
* be empty.
*/
NrIndicators nrIndicators;
+
+ /**
+ * The type of network attachment. This info is valid only on LTE network and must be present
+ * when device has attached to the network.
+ */
+ AttachResultType lteAttachResultType;
+
+ /** Values are bitwise ORs of EXTRA_* constants */
+ int extraInfo;
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
index 0ac8b0e..70427f8 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetwork.aidl
@@ -18,6 +18,8 @@
import android.hardware.radio.AccessNetwork;
import android.hardware.radio.network.CdmaRoamingType;
+import android.hardware.radio.network.EmergencyMode;
+import android.hardware.radio.network.EmergencyNetworkScanTrigger;
import android.hardware.radio.network.IRadioNetworkIndication;
import android.hardware.radio.network.IRadioNetworkResponse;
import android.hardware.radio.network.IndicationFilter;
@@ -27,8 +29,6 @@
import android.hardware.radio.network.RadioBandMode;
import android.hardware.radio.network.SignalThresholdInfo;
import android.hardware.radio.network.UsageSetting;
-import android.hardware.radio.network.EmergencyNetworkScanTrigger;
-import android.hardware.radio.network.EmergencyMode;
/**
* This interface is used by telephony and telecom to talk to cellular radio for network APIs.
@@ -112,6 +112,8 @@
* @param serial Serial number of request.
*
* Response function is IRadioNetworkResponse.getImsRegistrationStateResponse()
+ *
+ * @deprecated Deprecated starting from Android U.
*/
void getImsRegistrationState(in int serial);
@@ -449,27 +451,30 @@
*
* Response function is IRadioEmergencyResponse.setEmergencyModeResponse()
*/
- void setEmergencyMode(int serial, in EmergencyMode emcModeType );
+ void setEmergencyMode(int serial, in EmergencyMode emcModeType);
/**
* Triggers an Emergency network scan.
*
* @param serial Serial number of the request.
- * @param request Defines the radio target networks/preferred network/
- * Max Scan Time and type of service to be scanned.
+ * @param request Contains the preferred networks and type of service to be scanned.
+ * See {@link EmergencyNetworkScanTrigger}.
*
* Response function is IRadioEmergencyResponse.triggerEmergencyNetworkScanResponse()
*/
- void triggerEmergencyNetworkScan( int serial, in EmergencyNetworkScanTrigger request);
+ void triggerEmergencyNetworkScan(int serial, in EmergencyNetworkScanTrigger request);
/**
* Cancels ongoing Emergency network scan
*
* @param serial Serial number of the request.
+ * @param resetScan Indicates how the next {@link #triggerEmergencyNetworkScan} should work.
+ * If {@code true}, then the modem shall start the new scan from the beginning,
+ * otherwise the modem shall resume from the last search.
*
* Response function is IRadioEmergencyResponse.cancelEmergencyNetworkScan()
*/
- void cancelEmergencyNetworkScan(in int serial);
+ void cancelEmergencyNetworkScan(int serial, boolean resetScan);
/**
* Exits ongoing Emergency Mode
@@ -479,4 +484,80 @@
* Response function is IRadioEmergencyResponse.exitEmergencyModeResponse()
*/
void exitEmergencyMode(in int serial);
+
+ /**
+ * Set if null encryption and integrity modes are enabled. If the value of enabled is false
+ * the modem must not allow any network communications with null ciphering or null integrity
+ * modes.
+ *
+ * In the case when enabled is false, integrity protection for user data is optional, but
+ * ciphering for user data is required. In case of an emergency call, the modem must bypass
+ * this setting.
+ *
+ * Null ciphering and integrity modes include (but are not limited to):
+ * 2G: A5/0
+ * 3G: UEA0 and UIA0
+ * 4G: EEA0 and EIA0
+ * 5G: NEA0 and NIA0
+ *
+ *
+ * @param serial Serial number of the request.
+ * @param enabled To allow null encryption/integrity, set to true.
+ * Otherwise, false.
+ *
+ * Response callback is IRadioResponse.setNullCipherAndIntegrityEnabledResponse()
+ */
+ void setNullCipherAndIntegrityEnabled(in int serial, in boolean enabled);
+
+ /**
+ * Checks whether N1 mode (access to 5G core network) is enabled or not.
+ *
+ * @param serial Serial number of request.
+ *
+ * Response function is IRadioNetworkResponse.isN1ModeEnabledResponse()
+ */
+ void isN1ModeEnabled(in int serial);
+
+ /**
+ * Enables or disables N1 mode (access to 5G core network) in accordance with
+ * 3GPP TS 24.501 4.9.
+ *
+ * Note: The default value of N1 mode shall be based on the modem's internal configuration
+ * as per device or carrier. This API may be invoked on demand first to disable N1 mode and
+ * later to re-enable for certain use case. This setting shall not be persisted by modem.
+ * This setting shall not interfere with the allowed network type bitmap set using
+ * {@link IRadioNetwork#setAllowedNetworkTypesBitmap()} API.
+ *
+ * @param serial Serial number of request.
+ * @param enable {@code true} to enable N1 mode, {@code false} to disable N1 mode.
+ *
+ * Response function is IRadioNetworkResponse.setN1ModeEnabledResponse()
+ */
+ void setN1ModeEnabled(in int serial, boolean enable);
+
+ /**
+ * This API updates the current user setting of sharing the location data. This value must be
+ * used by radio before honoring a network initiated location request for non emergency use
+ * cases. The radio shall ignore this setting during emergency call, emergency SMS or emergency
+ * call back modes and continue to provide the location information to the network initiated
+ * location requests.
+ *
+ * @param serial Serial number of request.
+ * @param shareLocation Whether to share location data to the network or not. true means the
+ * radio is allowed to provide location data for any network initiated locations
+ * request. false means the radio must not share location data for any network initiated
+ * location requests for non-emergency use cases.
+ *
+ * Response function is IRadioNetworkResponse.setLocationPrivacySettingResponse()
+ */
+ void setLocationPrivacySetting(in int serial, in boolean shareLocation);
+
+ /**
+ * Request the current setting of sharing the location data.
+ *
+ * @param serial Serial number of request.
+ *
+ * Response function is IRadioNetworkResponse.getLocationPrivacySettingResponse()
+ */
+ void getLocationPrivacySetting(in int serial);
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
index 47d932d..2891496 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkIndication.aidl
@@ -21,13 +21,14 @@
import android.hardware.radio.network.BarringInfo;
import android.hardware.radio.network.CellIdentity;
import android.hardware.radio.network.CellInfo;
+import android.hardware.radio.network.EmergencyRegResult;
import android.hardware.radio.network.LinkCapacityEstimate;
+import android.hardware.radio.network.LocationResponseType;
import android.hardware.radio.network.NetworkScanResult;
import android.hardware.radio.network.PhoneRestrictedState;
import android.hardware.radio.network.PhysicalChannelConfig;
import android.hardware.radio.network.SignalStrength;
import android.hardware.radio.network.SuppSvcNotification;
-import android.hardware.radio.network.EmergencyRegResult;
/**
* Interface declaring unsolicited radio indications for network APIs.
@@ -199,4 +200,13 @@
* @param result the result of the Emergency Network Scan
*/
void emergencyNetworkScanResult(in RadioIndicationType type, in EmergencyRegResult result);
+
+ /**
+ * Reports the result of the network initiated location request.
+ *
+ * @param type Type of radio indication
+ * @param locationResponseType result of the network initiated location request.
+ */
+ void onNetworkInitiatedLocationResult(
+ in RadioIndicationType type, in LocationResponseType locationResponseType);
}
diff --git a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
index 243e949..3fa6521 100644
--- a/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
+++ b/radio/aidl/android/hardware/radio/network/IRadioNetworkResponse.aidl
@@ -23,13 +23,13 @@
import android.hardware.radio.network.CdmaRoamingType;
import android.hardware.radio.network.CellIdentity;
import android.hardware.radio.network.CellInfo;
+import android.hardware.radio.network.EmergencyRegResult;
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;
-import android.hardware.radio.network.EmergencyRegResult;
/**
* Interface declaring response functions to solicited radio requests for network APIs.
@@ -57,7 +57,6 @@
* RadioError:INTERNAL_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
*/
void getAllowedNetworkTypesBitmapResponse(in RadioResponseInfo info, in int networkTypeBitmap);
@@ -74,7 +73,6 @@
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -93,7 +91,6 @@
* RadioError:INTERNAL_ERR
* RadioError:NO_MEMORY
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:CANCELLED
* RadioError:NO_RESOURCES
* RadioError:INTERNAL_ERR
@@ -126,7 +123,6 @@
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
@@ -170,7 +166,8 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
+ *
+ * @deprecated Deprecated starting from Android U.
*/
void getImsRegistrationStateResponse(
in RadioResponseInfo info, in boolean isRegistered, in RadioTechnologyFamily ratFamily);
@@ -187,7 +184,6 @@
* RadioError:SYSTEM_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -205,7 +201,6 @@
* RadioError:NO_MEMORY
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -247,7 +242,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void getVoiceRadioTechnologyResponse(in RadioResponseInfo info, in RadioTechnology rat);
@@ -272,7 +266,6 @@
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void isNrDualConnectivityEnabledResponse(in RadioResponseInfo info, in boolean isEnabled);
@@ -287,7 +280,6 @@
* RadioError:INTERNAL_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
*/
void setAllowedNetworkTypesBitmapResponse(in RadioResponseInfo info);
@@ -304,7 +296,6 @@
* RadioError:SYSTEM_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -325,7 +316,6 @@
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
* RadioError:FDN_CHECK_FAILURE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -342,7 +332,6 @@
* RadioError:SYSTEM_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -362,7 +351,6 @@
* RadioError:INVALID_ARGUMENTS
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void setCellInfoListRateResponse(in RadioResponseInfo info);
@@ -400,7 +388,6 @@
* RadioError:SYSTEM_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
@@ -420,7 +407,6 @@
* RadioError:SYSTEM_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*
@@ -443,7 +429,6 @@
* RadioError:SYSTEM_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*
@@ -459,7 +444,6 @@
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_STATE
*/
void setNrDualConnectivityStateResponse(in RadioResponseInfo info);
@@ -486,7 +470,6 @@
* RadioError:SYSTEM_ERR
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
@@ -543,7 +526,6 @@
* RadioError:INVALID_ARGUMENTS
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SIM_ABSENT
*/
void supplyNetworkDepersonalizationResponse(in RadioResponseInfo info, in int remainingRetries);
@@ -575,11 +557,15 @@
oneway void getUsageSettingResponse(in RadioResponseInfo info, in UsageSetting usageSetting);
/**
+ * Response of setEmergencyMode.
+ * This is an optional API.
+ *
* @param info Response info struct containing response type, serial no. and error.
* @param regState the current registration state of the modem.
*
* Valid errors returned:
* RadioError:NONE
+ * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:MODEM_ERR
* RadioError:INVALID_ARGUMENTS
@@ -587,10 +573,14 @@
void setEmergencyModeResponse(in RadioResponseInfo info, in EmergencyRegResult regState);
/**
- * @param info Response info struct containing response type, serial no. and error
+ * Response of triggerEmergencyNetworkScan.
+ * This is an optional API.
+ *
+ * @param info Response info struct containing response type, serial no. and error.
*
* Valid errors returned:
* RadioError:NONE
+ * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:MODEM_ERR
* RadioError:INVALID_ARGUMENTS
@@ -598,16 +588,34 @@
void triggerEmergencyNetworkScanResponse(in RadioResponseInfo info);
/**
- * @param info Response info struct containing response type, serial no. and error
+ * Response of exitEmergencyMode.
+ * This is an optional API.
+ *
+ * @param info Response info struct containing response type, serial no. and error.
*
* Valid errors returned:
* RadioError:NONE
+ * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:MODEM_ERR
*/
void exitEmergencyModeResponse(in RadioResponseInfo info);
/**
+ * Response of cancelEmergencyNetworkScan.
+ * This is an optional API.
+ *
+ * @param info Response info struct containing response type, serial no. and error.
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:MODEM_ERR
+ */
+ void cancelEmergencyNetworkScanResponse(in RadioResponseInfo info);
+
+ /**
* @param info Response info struct containing response type, serial no. and error
*
* Valid errors returned:
@@ -615,5 +623,57 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:MODEM_ERR
*/
- void cancelEmergencyNetworkScanResponse(in RadioResponseInfo info);
+ void setNullCipherAndIntegrityEnabledResponse(in RadioResponseInfo info);
+
+ /**
+ * Response of isN1ModeEnabled.
+ * This is an optional API.
+ *
+ * @param info Response info struct containing response type, serial no. and error.
+ * @param isEnabled Indicates whether N1 mode is enabled or not.
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:REQUEST_NOT_SUPPORTED
+ */
+ void isN1ModeEnabledResponse(in RadioResponseInfo info, boolean isEnabled);
+
+ /**
+ * Response of setN1ModeEnabled.
+ * This is an optional API.
+ *
+ * @param info Response info struct containing response type, serial no. and error.
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ * RadioError:REQUEST_NOT_SUPPORTED
+ * RadioError:INVALID_STATE
+ */
+ void setN1ModeEnabledResponse(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:INTERNAL_ERR
+ */
+ void setLocationPrivacySettingResponse(in RadioResponseInfo info);
+
+ /**
+ * @param info Response info struct containing response type, serial no. and error
+ * @param shareLocation Indicates whether the location sharing is allowed or not, True if
+ * allowed else false.
+ *
+ * Valid errors returned:
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
+ * RadioError:INTERNAL_ERR
+ */
+ void getLocationPrivacySettingResponse(in RadioResponseInfo info, boolean shareLocation);
}
diff --git a/radio/aidl/android/hardware/radio/network/LocationResponseType.aidl b/radio/aidl/android/hardware/radio/network/LocationResponseType.aidl
new file mode 100644
index 0000000..0c502d0
--- /dev/null
+++ b/radio/aidl/android/hardware/radio/network/LocationResponseType.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.
+ */
+
+package android.hardware.radio.network;
+
+@VintfStability
+@Backing(type="int")
+@JavaDerive(toString=true)
+enum LocationResponseType {
+ /**
+ * Network initiated Location request rejected by modem because the user has not given
+ * permission for this use case
+ */
+ REJECTED = 0,
+ /**
+ * Network initiated Location request is accepted by modem however no location information has
+ * been shared to network due to a failure
+ */
+ ACCEPTED_NO_LOCATION_PROVIDED = 1,
+ /**
+ * Network initiated Location request is accepted and location information is provided to the
+ * network by modem
+ */
+ ACCEPTED_LOCATION_PROVIDED = 2,
+}
diff --git a/radio/aidl/android/hardware/radio/network/RegState.aidl b/radio/aidl/android/hardware/radio/network/RegState.aidl
index 3f13783..bdba4c4 100644
--- a/radio/aidl/android/hardware/radio/network/RegState.aidl
+++ b/radio/aidl/android/hardware/radio/network/RegState.aidl
@@ -65,4 +65,10 @@
* Same as UNKNOWN but indicates that emergency calls are enabled
*/
UNKNOWN_EM = 14,
+ /**
+ * Emergency attached in EPS or in 5GS.
+ * Reference: 3GPP TS 24.301 9.9.3.11 EPS attach type.
+ * Reference: 3GPP TS 24.501 9.11.3.6 5GS registration result.
+ */
+ REG_EM = 20,
}
diff --git a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
index 3d96b8c..f1d2972 100644
--- a/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
+++ b/radio/aidl/android/hardware/radio/network/RegStateResult.aidl
@@ -33,9 +33,9 @@
*/
RegState regState;
/**
- * Indicates the radio technology (except LTE_CA, which is no longer a valid value), which
- * must not be UNKNOWN if regState is REG_HOME, REG_ROAMING, NOT_REG_MT_NOT_SEARCHING_OP_EM,
- * NOT_REG_MT_SEARCHING_OP_EM, REG_DENIED_EM, or UNKNOWN_EM.
+ * Indicates the radio technology, which must not be UNKNOWN if regState is REG_HOME,
+ * REG_ROAMING, NOT_REG_MT_NOT_SEARCHING_OP_EM, NOT_REG_MT_SEARCHING_OP_EM, REG_DENIED_EM,
+ * or UNKNOWN_EM.
* When the device is on carrier aggregation, vendor RIL service must properly report multiple
* PhysicalChannelConfig elements through IRadioNetwork::currentPhysicalChannelConfigs.
*/
diff --git a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
index 750a29a..b3df504 100644
--- a/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
+++ b/radio/aidl/android/hardware/radio/sim/IRadioSimResponse.aidl
@@ -65,7 +65,6 @@
* RadioError:CANCELLED
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_SIM_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SIM_PUK2
*/
void changeIccPin2ForAppResponse(in RadioResponseInfo info, in int remainingRetries);
@@ -84,7 +83,6 @@
* RadioError:CANCELLED
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_SIM_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void changeIccPinForAppResponse(in RadioResponseInfo info, in int remainingRetries);
@@ -108,7 +106,6 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void getAllowedCarriersResponse(in RadioResponseInfo info, in CarrierRestrictions carriers,
in SimLockMultiSimPolicy multiSimPolicy);
@@ -133,7 +130,6 @@
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
* RadioError:NOT_PROVISIONED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
@@ -153,7 +149,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SIM_ABSENT
*/
void getCdmaSubscriptionSourceResponse(
@@ -176,7 +171,6 @@
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
* RadioError:FDN_CHECK_FAILURE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -191,7 +185,6 @@
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INTERNAL_ERR
* RadioError:NO_RESOURCES
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void getIccCardStatusResponse(in RadioResponseInfo info, in CardStatus cardStatus);
@@ -208,7 +201,6 @@
* RadioError:CANCELLED
* RadioError:INVALID_SIM_STATE
* RadioError:SIM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void getImsiForAppResponse(in RadioResponseInfo info, in String imsi);
@@ -219,13 +211,10 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_SIM_STATE
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
- * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
- * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
*/
void getSimPhonebookCapacityResponse(in RadioResponseInfo info, in PhonebookCapacity capacity);
@@ -235,13 +224,10 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_SIM_STATE
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
- * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
- * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
*/
void getSimPhonebookRecordsResponse(in RadioResponseInfo info);
@@ -255,7 +241,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void iccCloseLogicalChannelResponse(in RadioResponseInfo info);
@@ -274,7 +259,6 @@
* RadioError:CANCELLED
* RadioError:INVALID_SIM_STATE
* RadioError:SIM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void iccIoForAppResponse(in RadioResponseInfo info, in IccIoResult iccIo);
@@ -296,7 +280,6 @@
* RadioError:SIM_ERR
* RadioError:INVALID_SIM_STATE
* RadioError:MISSING_RESOURCE
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void iccOpenLogicalChannelResponse(
in RadioResponseInfo info, in int channelId, in byte[] selectResponse);
@@ -312,7 +295,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void iccTransmitApduBasicChannelResponse(in RadioResponseInfo info, in IccIoResult result);
@@ -327,7 +309,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void iccTransmitApduLogicalChannelResponse(in RadioResponseInfo info, in IccIoResult result);
@@ -341,7 +322,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void reportStkServiceIsRunningResponse(in RadioResponseInfo info);
@@ -359,7 +339,6 @@
* RadioError:INVALID_MODEM_STATE
* RadioError:SIM_ERR
* RadioError:INVALID_ARGUMENTS
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void requestIccSimAuthenticationResponse(in RadioResponseInfo info, in IccIoResult result);
@@ -379,7 +358,6 @@
* RadioError:CANCELLED
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SIM_ABSENT
*/
void sendEnvelopeResponse(in RadioResponseInfo info, in String commandResponse);
@@ -397,7 +375,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SIM_ABSENT
*/
void sendEnvelopeWithStatusResponse(in RadioResponseInfo info, in IccIoResult iccIo);
@@ -415,7 +392,6 @@
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SIM_ABSENT
*/
void sendTerminalResponseToSimResponse(in RadioResponseInfo info);
@@ -427,7 +403,6 @@
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
* RadioError:INVALID_ARGUMENTS
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void setAllowedCarriersResponse(in RadioResponseInfo info);
@@ -435,12 +410,11 @@
* @param info Response info struct containing response type, serial no. and error
*
* Valid errors returned:
- * RadioError:RIL_E_SUCCESS
- * RadioError:RIL_E_RADIO_NOT_AVAILABLE
+ * RadioError:NONE
+ * RadioError:RADIO_NOT_AVAILABLE
* RadioError:SIM_ABSENT
- * RadioError:RIL_E_REQUEST_NOT_SUPPORTED
* RadioError:INVALID_ARGUMENTS
- * RadioError:MODEM_INTERNAL_FAILURE
+ * RadioError:INTERNAL_FAILURE
*/
void setCarrierInfoForImsiEncryptionResponse(in RadioResponseInfo info);
@@ -456,7 +430,6 @@
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void setCdmaSubscriptionSourceResponse(in RadioResponseInfo info);
@@ -477,7 +450,6 @@
* RadioError:SYSTEM_ERR
* RadioError:INVALID_STATE
* RadioError:FDN_CHECK_FAILURE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -507,7 +479,6 @@
* RadioError:SYSTEM_ERR
* RadioError:MODEM_ERR
* RadioError:INVALID_ARGUMENTS
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -527,7 +498,6 @@
* RadioError:CANCELLED
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_SIM_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SIM_PUK2
*/
void supplyIccPin2ForAppResponse(in RadioResponseInfo info, in int remainingRetries);
@@ -546,7 +516,6 @@
* RadioError:CANCELLED
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_SIM_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void supplyIccPinForAppResponse(in RadioResponseInfo info, in int remainingRetries);
@@ -564,7 +533,6 @@
* RadioError:CANCELLED
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_SIM_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void supplyIccPuk2ForAppResponse(in RadioResponseInfo info, in int remainingRetries);
@@ -582,7 +550,6 @@
* RadioError:CANCELLED
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_SIM_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void supplyIccPukForAppResponse(in RadioResponseInfo info, in int remainingRetries);
@@ -603,7 +570,6 @@
* RadioError:MODEM_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:NO_RESOURCES
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void supplySimDepersonalizationResponse(
in RadioResponseInfo info, in PersoSubstate persoType, in int remainingRetries);
@@ -616,7 +582,6 @@
* Valid errors returned:
* RadioError:NONE
* RadioError:RADIO_NOT_AVAILABLE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_ARGUMENTS
* RadioError:INVALID_SIM_STATE
* RadioError:MODEM_ERR
@@ -624,8 +589,6 @@
* RadioError:SIM_ERR
* RadioError:NO_SUCH_ENTRY
* RadioError:NO_RESOURCES
- * REQUEST_NOT_SUPPORTED may only be returned on devices that don't support this API,
- * indicated by the HAL capability CAPABILITY_SIM_PHONEBOOK_IN_MODEM.
*/
void updateSimPhonebookRecordsResponse(in RadioResponseInfo info, in int updatedRecordIndex);
}
diff --git a/radio/aidl/android/hardware/radio/sim/SimApdu.aidl b/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
index 43adbbc..4759e2e 100644
--- a/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
+++ b/radio/aidl/android/hardware/radio/sim/SimApdu.aidl
@@ -49,4 +49,9 @@
* In hex string format ([a-fA-F0-9]*)
*/
String data;
+ /**
+ * isEs10 indicates that the current streaming APDU contains an ES10 command or it is a regular
+ * APDU. (As per spec SGP.22 V3.0, ES10 commands needs to be sent over command port of MEP-A1)
+ */
+ boolean isEs10;
}
diff --git a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
index cf1b953..39e3ace 100644
--- a/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
+++ b/radio/aidl/android/hardware/radio/voice/IRadioVoiceResponse.aidl
@@ -42,7 +42,6 @@
* RadioError:INVALID_CALL_ID
* RadioError:INVALID_ARGUMENTS
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -71,7 +70,6 @@
* RadioError:INVALID_STATE
* RadioError:INVALID_ARGUMENTS
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -92,7 +90,6 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:INVALID_ARGUMENTS
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -122,7 +119,6 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:ABORTED
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:CANCELLED
*/
@@ -163,7 +159,6 @@
* RadioError:SYSTEM_ERR
* RadioError:INVALID_ARGUMENTS
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:SIM_ABSENT
@@ -185,7 +180,6 @@
* RadioError:INTERNAL_ERR
* RadioError:INVALID_CALL_ID
* RadioError:OPERATION_NOT_ALLOWED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -212,7 +206,6 @@
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
* RadioError:FDN_CHECK_FAILURE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SYSTEM_ERR
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -241,7 +234,6 @@
* RadioError:FDN_CHECK_FAILURE
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -260,7 +252,6 @@
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
* RadioError:FDN_CHECK_FAILURE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -282,7 +273,6 @@
* RadioError:INTERNAL_ERR
* RadioError:FDN_CHECK_FAILURE
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_ARGUMENTS
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -298,7 +288,6 @@
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
* RadioError:INVALID_ARGUMENTS
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -344,7 +333,6 @@
* RadioError:INVALID_ARGUMENTS
* RadioError:INTERNAL_ERR
* RadioError:MODEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_MEMORY
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -367,7 +355,6 @@
* RadioError:INVALID_ARGUMENTS
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -386,7 +373,6 @@
* RadioError:INTERNAL_ERR
* RadioError:NO_MEMORY
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -404,7 +390,6 @@
* RadioError:INTERNAL_ERR
* RadioError:NO_MEMORY
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -423,7 +408,6 @@
* RadioError:INVALID_ARGUMENTS
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:SIM_ABSENT
*/
void handleStkCallSetupRequestFromSimResponse(in RadioResponseInfo info);
@@ -442,7 +426,6 @@
* RadioError:INVALID_CALL_ID
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void hangupConnectionResponse(in RadioResponseInfo info);
@@ -461,7 +444,6 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:INVALID_ARGUMENTS
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -482,7 +464,6 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:INVALID_ARGUMENTS
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:CANCELLED
*/
void hangupWaitingOrBackgroundResponse(in RadioResponseInfo info);
@@ -497,7 +478,6 @@
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
* RadioError:NO_MEMORY
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void isVoNrEnabledResponse(in RadioResponseInfo info, in boolean enable);
@@ -516,7 +496,6 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:INVALID_ARGUMENTS
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -536,7 +515,6 @@
* RadioError:MODEM_ERR
* RadioError:INVALID_CALL_ID
* RadioError:INVALID_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
@@ -557,7 +535,6 @@
* RadioError:MODEM_ERR
* RadioError:INVALID_CALL_ID
* RadioError:INVALID_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -578,7 +555,6 @@
* RadioError:INVALID_CALL_ID
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
*/
@@ -603,7 +579,6 @@
* RadioError:ABORTED
* RadioError:SYSTEM_ERR
* RadioError:INVALID_STATE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -625,7 +600,6 @@
* RadioError:INTERNAL_ERR
* RadioError:INVALID_CALL_ID
* RadioError:OPERATION_NOT_ALLOWED
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:CANCELLED
*/
@@ -647,7 +621,6 @@
* RadioError:INTERNAL_ERR
* RadioError:INVALID_STATE
* RadioError:FDN_CHECK_FAILURE
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -670,7 +643,6 @@
* RadioError:INVALID_STATE
* RadioError:FDN_CHECK_FAILURE
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -690,7 +662,6 @@
* RadioError:NO_MEMORY
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -707,7 +678,6 @@
* RadioError:REQUEST_RATE_LIMITED
* RadioError:INTERNAL_ERR
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -724,7 +694,6 @@
* RadioError:INTERNAL_ERR
* RadioError:NO_MEMORY
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_CALL_ID
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
@@ -742,7 +711,6 @@
* RadioError:INTERNAL_ERR
* RadioError:NO_MEMORY
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
*/
@@ -758,7 +726,6 @@
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
* RadioError:NO_MEMORY
- * RadioError:REQUEST_NOT_SUPPORTED
*/
void setVoNrEnabledResponse(in RadioResponseInfo info);
@@ -776,7 +743,6 @@
* RadioError:INTERNAL_ERR
* RadioError:INVALID_CALL_ID
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
*/
@@ -796,7 +762,6 @@
* RadioError:MODEM_ERR
* RadioError:INTERNAL_ERR
* RadioError:INVALID_CALL_ID
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:CANCELLED
* RadioError:INVALID_MODEM_STATE
*/
@@ -817,7 +782,6 @@
* RadioError:OPERATION_NOT_ALLOWED
* RadioError:INVALID_ARGUMENTS
* RadioError:SYSTEM_ERR
- * RadioError:REQUEST_NOT_SUPPORTED
* RadioError:INVALID_MODEM_STATE
* RadioError:NO_RESOURCES
* RadioError:CANCELLED
diff --git a/radio/aidl/compat/libradiocompat/Android.bp b/radio/aidl/compat/libradiocompat/Android.bp
index f79e045..c40ca30 100644
--- a/radio/aidl/compat/libradiocompat/Android.bp
+++ b/radio/aidl/compat/libradiocompat/Android.bp
@@ -31,17 +31,18 @@
"-DANDROID_UTILS_REF_BASE_DISABLE_IMPLICIT_CONSTRUCTION",
],
shared_libs: [
- "android.hardware.radio.config-V1-ndk",
+ "android.hardware.radio.config-V2-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.data-V2-ndk",
+ "android.hardware.radio.ims-V1-ndk",
+ "android.hardware.radio.messaging-V2-ndk",
+ "android.hardware.radio.modem-V2-ndk",
"android.hardware.radio.network-V2-ndk",
- "android.hardware.radio.sim-V1-ndk",
- "android.hardware.radio.voice-V1-ndk",
+ "android.hardware.radio.sim-V2-ndk",
+ "android.hardware.radio.voice-V2-ndk",
"android.hardware.radio@1.0",
"android.hardware.radio@1.1",
"android.hardware.radio@1.2",
@@ -69,6 +70,9 @@
"data/RadioResponse-data.cpp",
"data/RadioData.cpp",
"data/structs.cpp",
+ "ims/RadioIndication-ims.cpp",
+ "ims/RadioResponse-ims.cpp",
+ "ims/RadioIms.cpp",
"messaging/RadioIndication-messaging.cpp",
"messaging/RadioMessaging.cpp",
"messaging/RadioResponse-messaging.cpp",
diff --git a/radio/aidl/compat/libradiocompat/data/structs.cpp b/radio/aidl/compat/libradiocompat/data/structs.cpp
index cc6dcbc..22cde6b 100644
--- a/radio/aidl/compat/libradiocompat/data/structs.cpp
+++ b/radio/aidl/compat/libradiocompat/data/structs.cpp
@@ -136,7 +136,7 @@
.fiveQi = qos.fiveQi,
.downlink = toAidl(qos.downlink),
.uplink = toAidl(qos.uplink),
- .qfi = static_cast<int8_t>(qos.qfi),
+ .qosFlowIdentifier = static_cast<int8_t>(qos.qfi),
.averagingWindowMs = qos.averagingWindowMs,
};
}
diff --git a/radio/aidl/compat/libradiocompat/ims/RadioIms.cpp b/radio/aidl/compat/libradiocompat/ims/RadioIms.cpp
new file mode 100644
index 0000000..d2bdfff
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/ims/RadioIms.cpp
@@ -0,0 +1,88 @@
+/*
+ * 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 <libradiocompat/RadioIms.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "Ims"
+
+namespace android::hardware::radio::compat {
+
+using ::ndk::ScopedAStatus;
+namespace aidl = ::aidl::android::hardware::radio::ims;
+constexpr auto ok = &ScopedAStatus::ok;
+
+std::shared_ptr<aidl::IRadioImsResponse> RadioIms::respond() {
+ return mCallbackManager->response().imsCb();
+}
+
+ScopedAStatus RadioIms::setSrvccCallInfo(
+ int32_t serial, const std::vector<aidl::SrvccCall>& /*srvccCalls*/) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " setSrvccCallInfo is unsupported by HIDL HALs";
+ return ok();
+}
+ScopedAStatus RadioIms::updateImsRegistrationInfo(
+ int32_t serial, const aidl::ImsRegistration& /*imsRegistration*/) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " updateImsRegistrationInfo is unsupported by HIDL HALs";
+ return ok();
+}
+ScopedAStatus RadioIms::startImsTraffic(
+ int32_t serial, int32_t /*token*/, aidl::ImsTrafficType /*imsTrafficType*/,
+ ::aidl::android::hardware::radio::AccessNetwork /*accessNetworkType*/,
+ ::aidl::android::hardware::radio::ims::ImsCall::Direction /*trafficDirection*/) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " startImsTraffic is unsupported by HIDL HALs";
+ return ok();
+}
+ScopedAStatus RadioIms::stopImsTraffic(int32_t serial, int32_t /*token*/) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " stopImsTraffic is unsupported by HIDL HALs";
+ return ok();
+}
+ScopedAStatus RadioIms::triggerEpsFallback(int32_t serial, aidl::EpsFallbackReason /*reason*/) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " triggerEpsFallback is unsupported by HIDL HALs";
+ return ok();
+}
+ScopedAStatus RadioIms::sendAnbrQuery(
+ int32_t serial, aidl::ImsStreamType /*mediaType*/, aidl::ImsStreamDirection /*direction*/,
+ int32_t /*bitsPerSecond*/) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " sendAnbrQuery is unsupported by HIDL HALs";
+ return ok();
+}
+ScopedAStatus RadioIms::updateImsCallStatus(
+ int32_t serial, const std::vector<aidl::ImsCall>& /*imsCalls*/) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " updateImsCallStatus is unsupported by HIDL HALs";
+ return ok();
+}
+
+ScopedAStatus RadioIms::setResponseFunctions(
+ const std::shared_ptr<aidl::IRadioImsResponse>& response,
+ const std::shared_ptr<aidl::IRadioImsIndication>& indication) {
+ LOG_CALL << response << ' ' << indication;
+ mCallbackManager->setResponseFunctions(response, indication);
+ return ok();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/ims/RadioIndication-ims.cpp b/radio/aidl/compat/libradiocompat/ims/RadioIndication-ims.cpp
new file mode 100644
index 0000000..10109b8
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/ims/RadioIndication-ims.cpp
@@ -0,0 +1,39 @@
+/*
+ * 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 <libradiocompat/RadioIndication.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ImsIndication"
+
+namespace android::hardware::radio::compat {
+
+using ::aidl::android::hardware::radio::RadioTechnology;
+namespace aidl = ::aidl::android::hardware::radio::ims;
+
+void RadioIndication::setResponseFunction(std::shared_ptr<aidl::IRadioImsIndication> imsCb) {
+ mImsCb = imsCb;
+}
+
+std::shared_ptr<aidl::IRadioImsIndication> RadioIndication::imsCb() {
+ return mImsCb.get();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/ims/RadioResponse-ims.cpp b/radio/aidl/compat/libradiocompat/ims/RadioResponse-ims.cpp
new file mode 100644
index 0000000..831a0ae
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/ims/RadioResponse-ims.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.
+ */
+
+#include <libradiocompat/RadioResponse.h>
+
+#include "commonStructs.h"
+#include "debug.h"
+
+#include "collections.h"
+
+#define RADIO_MODULE "ImsResponse"
+
+namespace android::hardware::radio::compat {
+
+namespace aidl = ::aidl::android::hardware::radio::ims;
+
+void RadioResponse::setResponseFunction(std::shared_ptr<aidl::IRadioImsResponse> imsCb) {
+ mImsCb = imsCb;
+}
+
+std::shared_ptr<aidl::IRadioImsResponse> RadioResponse::imsCb() {
+ return mImsCb.get();
+}
+
+} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIms.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIms.h
new file mode 100644
index 0000000..0dbc565
--- /dev/null
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIms.h
@@ -0,0 +1,62 @@
+/*
+ * 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 "RadioCompatBase.h"
+
+#include <aidl/android/hardware/radio/ims/BnRadioIms.h>
+
+namespace android::hardware::radio::compat {
+
+class RadioIms : public RadioCompatBase, public aidl::android::hardware::radio::ims::BnRadioIms {
+ ::ndk::ScopedAStatus setSrvccCallInfo(
+ int32_t serial,
+ const std::vector<::aidl::android::hardware::radio::ims::SrvccCall>& srvccCalls)
+ override;
+ ::ndk::ScopedAStatus updateImsRegistrationInfo(
+ int32_t serial,
+ const ::aidl::android::hardware::radio::ims::ImsRegistration& imsRegistration) override;
+ ::ndk::ScopedAStatus startImsTraffic(
+ int32_t serial, int32_t token,
+ ::aidl::android::hardware::radio::ims::ImsTrafficType imsTrafficType,
+ ::aidl::android::hardware::radio::AccessNetwork accessNetworkType,
+ ::aidl::android::hardware::radio::ims::ImsCall::Direction trafficDirection) override;
+ ::ndk::ScopedAStatus stopImsTraffic(int32_t serial, int32_t token) override;
+ ::ndk::ScopedAStatus triggerEpsFallback(
+ int32_t serial,
+ ::aidl::android::hardware::radio::ims::EpsFallbackReason reason) override;
+ ::ndk::ScopedAStatus sendAnbrQuery(
+ int32_t serial, ::aidl::android::hardware::radio::ims::ImsStreamType mediaType,
+ ::aidl::android::hardware::radio::ims::ImsStreamDirection direction,
+ int32_t bitsPerSecond) override;
+ ::ndk::ScopedAStatus updateImsCallStatus(
+ int32_t serial,
+ const std::vector<::aidl::android::hardware::radio::ims::ImsCall>& imsCalls) override;
+
+ ::ndk::ScopedAStatus setResponseFunctions(
+ const std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsResponse>&
+ radioImsResponse,
+ const std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsIndication>&
+ radioImsIndication) override;
+
+ protected:
+ std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsResponse> respond();
+
+ 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
index 6cfd59c..f042456 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioIndication.h
@@ -19,6 +19,7 @@
#include "GuaranteedCallback.h"
#include <aidl/android/hardware/radio/data/IRadioDataIndication.h>
+#include <aidl/android/hardware/radio/ims/IRadioImsIndication.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>
@@ -55,6 +56,10 @@
::aidl::android::hardware::radio::voice::IRadioVoiceIndication,
::aidl::android::hardware::radio::voice::IRadioVoiceIndicationDefault, true>
mVoiceCb;
+ GuaranteedCallback< //
+ ::aidl::android::hardware::radio::ims::IRadioImsIndication,
+ ::aidl::android::hardware::radio::ims::IRadioImsIndicationDefault, true>
+ mImsCb;
// IRadioIndication @ 1.0
Return<void> radioStateChanged(V1_0::RadioIndicationType type,
@@ -220,6 +225,8 @@
std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimIndication> simCb);
void setResponseFunction(
std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceIndication> voicCb);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsIndication> imsCb);
std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataIndication> dataCb();
std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingIndication>
@@ -228,6 +235,7 @@
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();
+ std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsIndication> imsCb();
};
} // 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
index c714190..b446103 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioNetwork.h
@@ -97,8 +97,15 @@
int32_t serial,
const ::aidl::android::hardware::radio::network::EmergencyNetworkScanTrigger&
scanTrigger) override;
- ::ndk::ScopedAStatus cancelEmergencyNetworkScan(int32_t serial) override;
+ ::ndk::ScopedAStatus cancelEmergencyNetworkScan(int32_t serial, bool resetScan) override;
::ndk::ScopedAStatus exitEmergencyMode(int32_t serial) override;
+ ::ndk::ScopedAStatus isN1ModeEnabled(int32_t serial) override;
+ ::ndk::ScopedAStatus setN1ModeEnabled(int32_t serial, bool enable) override;
+
+ ::ndk::ScopedAStatus setNullCipherAndIntegrityEnabled(int32_t serial, bool enabled) override;
+
+ ::ndk::ScopedAStatus setLocationPrivacySetting(int32_t serial, bool shareLocation) override;
+ ::ndk::ScopedAStatus getLocationPrivacySetting(int32_t serial) override;
protected:
std::shared_ptr<::aidl::android::hardware::radio::network::IRadioNetworkResponse> respond();
diff --git a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
index 1f82dd1..22451ae 100644
--- a/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
+++ b/radio/aidl/compat/libradiocompat/include/libradiocompat/RadioResponse.h
@@ -19,6 +19,7 @@
#include "GuaranteedCallback.h"
#include <aidl/android/hardware/radio/data/IRadioDataResponse.h>
+#include <aidl/android/hardware/radio/ims/IRadioImsResponse.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>
@@ -49,6 +50,9 @@
GuaranteedCallback<::aidl::android::hardware::radio::voice::IRadioVoiceResponse,
::aidl::android::hardware::radio::voice::IRadioVoiceResponseDefault>
mVoiceCb;
+ GuaranteedCallback<::aidl::android::hardware::radio::ims::IRadioImsResponse,
+ ::aidl::android::hardware::radio::ims::IRadioImsResponseDefault>
+ mImsCb;
// IRadioResponse @ 1.0
Return<void> getIccCardStatusResponse(const V1_0::RadioResponseInfo& info,
@@ -440,6 +444,8 @@
std::shared_ptr<::aidl::android::hardware::radio::sim::IRadioSimResponse> simCb);
void setResponseFunction(
std::shared_ptr<::aidl::android::hardware::radio::voice::IRadioVoiceResponse> voiceCb);
+ void setResponseFunction(
+ std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsResponse> imsCb);
std::shared_ptr<::aidl::android::hardware::radio::data::IRadioDataResponse> dataCb();
std::shared_ptr<::aidl::android::hardware::radio::messaging::IRadioMessagingResponse>
@@ -448,6 +454,7 @@
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();
+ std::shared_ptr<::aidl::android::hardware::radio::ims::IRadioImsResponse> imsCb();
};
} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
index ff30ac3..730b5dd 100644
--- a/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
+++ b/radio/aidl/compat/libradiocompat/network/RadioNetwork.cpp
@@ -326,7 +326,7 @@
return ok();
}
-ScopedAStatus RadioNetwork::cancelEmergencyNetworkScan(int32_t serial) {
+ScopedAStatus RadioNetwork::cancelEmergencyNetworkScan(int32_t serial, bool) {
LOG_CALL << serial;
LOG(ERROR) << " cancelEmergencyNetworkScan is unsupported by HIDL HALs";
respond()->cancelEmergencyNetworkScanResponse(notSupported(serial));
@@ -340,4 +340,38 @@
return ok();
}
+ScopedAStatus RadioNetwork::setNullCipherAndIntegrityEnabled(int32_t serial, bool) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " setNullCipherAndIntegrityEnabled is unsupported by HIDL HALs";
+ respond()->setNullCipherAndIntegrityEnabledResponse(notSupported(serial));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::isN1ModeEnabled(int32_t serial) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " isN1ModeEnabled is unsupported by HIDL HALs";
+ respond()->isN1ModeEnabledResponse(notSupported(serial), false);
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setN1ModeEnabled(int32_t serial, bool /*enable*/) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " setN1ModeEnabled is unsupported by HIDL HALs";
+ respond()->setN1ModeEnabledResponse(notSupported(serial));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::setLocationPrivacySetting(int32_t serial, bool /*shareLocation*/) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " setLocationPrivacySetting is unsupported by HIDL HALs";
+ respond()->setLocationPrivacySettingResponse(notSupported(serial));
+ return ok();
+}
+
+ScopedAStatus RadioNetwork::getLocationPrivacySetting(int32_t serial) {
+ LOG_CALL << serial;
+ LOG(ERROR) << " getLocationPrivacySetting is unsupported by HIDL HALs";
+ respond()->getLocationPrivacySettingResponse(notSupported(serial), false);
+ return ok();
+}
} // namespace android::hardware::radio::compat
diff --git a/radio/aidl/compat/service/Android.bp b/radio/aidl/compat/service/Android.bp
index 4dbaef4..7a48da2 100644
--- a/radio/aidl/compat/service/Android.bp
+++ b/radio/aidl/compat/service/Android.bp
@@ -34,17 +34,18 @@
],
shared_libs: [
"android.hardware.radio-library.compat",
- "android.hardware.radio.config-V1-ndk",
+ "android.hardware.radio.config-V2-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.data-V2-ndk",
+ "android.hardware.radio.ims-V1-ndk",
+ "android.hardware.radio.messaging-V2-ndk",
+ "android.hardware.radio.modem-V2-ndk",
"android.hardware.radio.network-V2-ndk",
- "android.hardware.radio.sim-V1-ndk",
- "android.hardware.radio.voice-V1-ndk",
+ "android.hardware.radio.sim-V2-ndk",
+ "android.hardware.radio.voice-V2-ndk",
"android.hardware.radio@1.0",
"android.hardware.radio@1.1",
"android.hardware.radio@1.2",
diff --git a/radio/aidl/vts/Android.bp b/radio/aidl/vts/Android.bp
index 0d4bb3e..5a0dbd0 100644
--- a/radio/aidl/vts/Android.bp
+++ b/radio/aidl/vts/Android.bp
@@ -41,6 +41,9 @@
"radio_data_indication.cpp",
"radio_data_response.cpp",
"radio_data_test.cpp",
+ "radio_ims_indication.cpp",
+ "radio_ims_response.cpp",
+ "radio_ims_test.cpp",
"radio_messaging_indication.cpp",
"radio_messaging_response.cpp",
"radio_messaging_test.cpp",
@@ -63,14 +66,15 @@
"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-V2-ndk",
+ "android.hardware.radio.config-V2-ndk",
+ "android.hardware.radio.data-V2-ndk",
+ "android.hardware.radio.ims-V1-ndk",
+ "android.hardware.radio.messaging-V2-ndk",
+ "android.hardware.radio.modem-V2-ndk",
"android.hardware.radio.network-V2-ndk",
- "android.hardware.radio.sim-V1-ndk",
- "android.hardware.radio.voice-V1-ndk",
+ "android.hardware.radio.sim-V2-ndk",
+ "android.hardware.radio.voice-V2-ndk",
],
test_suites: [
"general-tests",
diff --git a/radio/aidl/vts/VtsHalRadioTargetTest.cpp b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
index 1ebc6af..67a2672 100644
--- a/radio/aidl/vts/VtsHalRadioTargetTest.cpp
+++ b/radio/aidl/vts/VtsHalRadioTargetTest.cpp
@@ -18,6 +18,7 @@
#include "radio_config_utils.h"
#include "radio_data_utils.h"
+#include "radio_ims_utils.h"
#include "radio_messaging_utils.h"
#include "radio_modem_utils.h"
#include "radio_network_utils.h"
@@ -65,6 +66,12 @@
testing::ValuesIn(android::getAidlHalInstanceNames(IRadioVoice::descriptor)),
android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(RadioImsTest);
+INSTANTIATE_TEST_SUITE_P(
+ PerInstance, RadioImsTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IRadioIms::descriptor)),
+ android::PrintInstanceNameToString);
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
ABinderProcess_setThreadPoolMaxThreadCount(1);
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.cpp b/radio/aidl/vts/radio_aidl_hal_utils.cpp
index efc4f26..6ed8e7d 100644
--- a/radio/aidl/vts/radio_aidl_hal_utils.cpp
+++ b/radio/aidl/vts/radio_aidl_hal_utils.cpp
@@ -92,6 +92,10 @@
return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "dsds");
}
+bool isDsDaEnabled() {
+ return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "dsda");
+}
+
bool isTsTsEnabled() {
return testing::checkSubstringInCommandOutput("getprop persist.radio.multisim.config", "tsts");
}
diff --git a/radio/aidl/vts/radio_aidl_hal_utils.h b/radio/aidl/vts/radio_aidl_hal_utils.h
index 47976b9..d515e1a 100644
--- a/radio/aidl/vts/radio_aidl_hal_utils.h
+++ b/radio/aidl/vts/radio_aidl_hal_utils.h
@@ -67,6 +67,8 @@
static constexpr const char* FEATURE_TELEPHONY_CDMA = "android.hardware.telephony.cdma";
+static constexpr const char* FEATURE_TELEPHONY_IMS = "android.hardware.telephony.ims";
+
#define MODEM_EMERGENCY_CALL_ESTABLISH_TIME 3
#define MODEM_EMERGENCY_CALL_DISCONNECT_TIME 3
#define MODEM_SET_SIM_POWER_DELAY_IN_SECONDS 2
@@ -104,6 +106,11 @@
bool isDsDsEnabled();
/*
+ * Check if device is in DSDA (Dual SIM Dual Active).
+ */
+bool isDsDaEnabled();
+
+/*
* Check if device is in TSTS (Triple SIM Triple Standby).
*/
bool isTsTsEnabled();
diff --git a/radio/aidl/vts/radio_config_test.cpp b/radio/aidl/vts/radio_config_test.cpp
index 258b172..c979d28 100644
--- a/radio/aidl/vts/radio_config_test.cpp
+++ b/radio/aidl/vts/radio_config_test.cpp
@@ -176,7 +176,7 @@
slotPortMapping.physicalSlotId = -1;
slotPortMapping.portId = -1;
std::vector<SlotPortMapping> slotPortMappingList = {slotPortMapping};
- if (isDsDsEnabled()) {
+ if (isDsDsEnabled() || isDsDaEnabled()) {
slotPortMappingList.push_back(slotPortMapping);
} else if (isTsTsEnabled()) {
slotPortMappingList.push_back(slotPortMapping);
@@ -252,7 +252,7 @@
}
if (isSsSsEnabled()) {
EXPECT_EQ(1, simCount);
- } else if (isDsDsEnabled()) {
+ } else if (isDsDsEnabled() || isDsDaEnabled()) {
EXPECT_EQ(2, simCount);
} else if (isTsTsEnabled()) {
EXPECT_EQ(3, simCount);
diff --git a/radio/aidl/vts/radio_ims_indication.cpp b/radio/aidl/vts/radio_ims_indication.cpp
new file mode 100644
index 0000000..988038b
--- /dev/null
+++ b/radio/aidl/vts/radio_ims_indication.cpp
@@ -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.
+ */
+
+#include "radio_ims_utils.h"
+
+RadioImsIndication::RadioImsIndication(RadioServiceTest& parent) : parent_ims(parent) {}
+
+ndk::ScopedAStatus RadioImsIndication::onConnectionSetupFailure(RadioIndicationType /*type*/,
+ int32_t /*token*/, const ConnectionFailureInfo& /*info*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioImsIndication::notifyAnbr(RadioIndicationType /*type*/,
+ ImsStreamType /*mediaType*/, ImsStreamDirection /*direction*/, int /*bitsPerSecond*/) {
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioImsIndication::triggerImsDeregistration(RadioIndicationType /*type*/,
+ ImsDeregistrationReason /*reason*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_ims_response.cpp b/radio/aidl/vts/radio_ims_response.cpp
new file mode 100644
index 0000000..c6d62dc
--- /dev/null
+++ b/radio/aidl/vts/radio_ims_response.cpp
@@ -0,0 +1,64 @@
+/*
+ * 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 "radio_ims_utils.h"
+
+RadioImsResponse::RadioImsResponse(RadioServiceTest& parent) : parent_ims(parent) {}
+
+ndk::ScopedAStatus RadioImsResponse::setSrvccCallInfoResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_ims.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioImsResponse::updateImsRegistrationInfoResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_ims.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioImsResponse::startImsTrafficResponse(const RadioResponseInfo& info,
+ const std::optional<ConnectionFailureInfo>& response) {
+ rspInfo = info;
+ startImsTrafficResp = response;
+ parent_ims.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioImsResponse::stopImsTrafficResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_ims.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioImsResponse::triggerEpsFallbackResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_ims.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioImsResponse::sendAnbrQueryResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_ims.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioImsResponse::updateImsCallStatusResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_ims.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_ims_test.cpp b/radio/aidl/vts/radio_ims_test.cpp
new file mode 100644
index 0000000..289d3ed
--- /dev/null
+++ b/radio/aidl/vts/radio_ims_test.cpp
@@ -0,0 +1,262 @@
+/*
+ * 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/android/hardware/radio/config/IRadioConfig.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+
+#include "radio_ims_utils.h"
+
+#define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
+
+void RadioImsTest::SetUp() {
+ std::string serviceName = GetParam();
+
+ if (!isServiceValidForDeviceConfiguration(serviceName)) {
+ ALOGI("Skipped the test due to device configuration.");
+ GTEST_SKIP();
+ }
+
+ radio_ims = IRadioIms::fromBinder(
+ ndk::SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(nullptr, radio_ims.get());
+
+ radioRsp_ims = ndk::SharedRefBase::make<RadioImsResponse>(*this);
+ ASSERT_NE(nullptr, radioRsp_ims.get());
+
+ count_ = 0;
+
+ radioInd_ims = ndk::SharedRefBase::make<RadioImsIndication>(*this);
+ ASSERT_NE(nullptr, radioInd_ims.get());
+
+ radio_ims->setResponseFunctions(radioRsp_ims, radioInd_ims);
+
+ // 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 IRadioIms.setSrvccCallInfo() for the response returned.
+ */
+TEST_P(RadioImsTest, setSrvccCallInfo) {
+ if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
+ ALOGI("Skipping setSrvccCallInfo because ims is not supported in device");
+ return;
+ } else {
+ ALOGI("Running setSrvccCallInfo because ims is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ SrvccCall srvccCall;
+
+ ndk::ScopedAStatus res =
+ radio_ims->setSrvccCallInfo(serial, { srvccCall });
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_ims->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_ims->rspInfo.serial);
+
+ ALOGI("setSrvccCallInfo, rspInfo.error = %s\n",
+ toString(radioRsp_ims->rspInfo.error).c_str());
+
+ verifyError(radioRsp_ims->rspInfo.error);
+}
+
+/*
+ * Test IRadioIms.updateImsRegistrationInfo() for the response returned.
+ */
+TEST_P(RadioImsTest, updateImsRegistrationInfo) {
+ if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
+ ALOGI("Skipping updateImsRegistrationInfo because ims is not supported in device");
+ return;
+ } else {
+ ALOGI("Running updateImsRegistrationInfo because ims is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ ImsRegistration regInfo;
+ regInfo.regState = ImsRegistrationState::NOT_REGISTERED;
+ regInfo.accessNetworkType = AccessNetwork::EUTRAN;
+ regInfo.suggestedAction = SuggestedAction::NONE;
+ regInfo.capabilities = ImsRegistration::IMS_MMTEL_CAPABILITY_NONE;
+
+ ndk::ScopedAStatus res =
+ radio_ims->updateImsRegistrationInfo(serial, regInfo);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_ims->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_ims->rspInfo.serial);
+
+ ALOGI("updateImsRegistrationInfo, rspInfo.error = %s\n",
+ toString(radioRsp_ims->rspInfo.error).c_str());
+
+ verifyError(radioRsp_ims->rspInfo.error);
+}
+
+/*
+ * Test IRadioIms.startImsTraffic() for the response returned.
+ */
+TEST_P(RadioImsTest, startImsTraffic) {
+ if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
+ ALOGI("Skipping startImsTraffic because ims is not supported in device");
+ return;
+ } else {
+ ALOGI("Running startImsTraffic because ims is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res =
+ radio_ims->startImsTraffic(serial, 1,
+ ImsTrafficType::REGISTRATION, AccessNetwork::EUTRAN, ImsCall::Direction::OUTGOING);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_ims->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_ims->rspInfo.serial);
+
+ ALOGI("startImsTraffic, rspInfo.error = %s\n",
+ toString(radioRsp_ims->rspInfo.error).c_str());
+
+ verifyError(radioRsp_ims->rspInfo.error);
+}
+
+/*
+ * Test IRadioIms.stopImsTraffic() for the response returned.
+ */
+TEST_P(RadioImsTest, stopImsTraffic) {
+ if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
+ ALOGI("Skipping stopImsTraffic because ims is not supported in device");
+ return;
+ } else {
+ ALOGI("Running stopImsTraffic because ims is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_ims->stopImsTraffic(serial, 2);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_ims->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_ims->rspInfo.serial);
+
+ ALOGI("stopImsTraffic, rspInfo.error = %s\n",
+ toString(radioRsp_ims->rspInfo.error).c_str());
+
+ verifyError(radioRsp_ims->rspInfo.error);
+}
+
+/*
+ * Test IRadioIms.triggerEpsFallback() for the response returned.
+ */
+TEST_P(RadioImsTest, triggerEpsFallback) {
+ if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
+ ALOGI("Skipping triggerEpsFallback because ims is not supported in device");
+ return;
+ } else {
+ ALOGI("Running triggerEpsFallback because ims is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res =
+ radio_ims->triggerEpsFallback(serial, EpsFallbackReason::NO_NETWORK_TRIGGER);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_ims->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_ims->rspInfo.serial);
+
+ ALOGI("triggerEpsFallback, rspInfo.error = %s\n",
+ toString(radioRsp_ims->rspInfo.error).c_str());
+
+ verifyError(radioRsp_ims->rspInfo.error);
+}
+
+/*
+ * Test IRadioIms.sendAnbrQuery() for the response returned.
+ */
+TEST_P(RadioImsTest, sendAnbrQuery) {
+ if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
+ ALOGI("Skipping sendAnbrQuery because ims is not supported in device");
+ return;
+ } else {
+ ALOGI("Running sendAnbrQuery because ims is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res =
+ radio_ims->sendAnbrQuery(serial, ImsStreamType::AUDIO, ImsStreamDirection::UPLINK, 13200);
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_ims->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_ims->rspInfo.serial);
+
+ ALOGI("sendAnbrQuery, rspInfo.error = %s\n",
+ toString(radioRsp_ims->rspInfo.error).c_str());
+
+ verifyError(radioRsp_ims->rspInfo.error);
+}
+
+/*
+ * Test IRadioIms.updateImsCallStatus() for the response returned.
+ */
+TEST_P(RadioImsTest, updateImsCallStatus) {
+ if (!deviceSupportsFeature(FEATURE_TELEPHONY_IMS)) {
+ ALOGI("Skipping updateImsCallStatus because ims is not supported in device");
+ return;
+ } else {
+ ALOGI("Running updateImsCallStatus because ims is supported in device");
+ }
+
+ serial = GetRandomSerialNumber();
+
+ ImsCall imsCall;
+
+ ndk::ScopedAStatus res =
+ radio_ims->updateImsCallStatus(serial, { imsCall });
+ ASSERT_OK(res);
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_ims->rspInfo.type);
+ EXPECT_EQ(serial, radioRsp_ims->rspInfo.serial);
+
+ ALOGI("updateImsCallStatus, rspInfo.error = %s\n",
+ toString(radioRsp_ims->rspInfo.error).c_str());
+
+ verifyError(radioRsp_ims->rspInfo.error);
+}
+
+void RadioImsTest::verifyError(RadioError resp) {
+ switch (resp) {
+ case RadioError::NONE:
+ case RadioError::RADIO_NOT_AVAILABLE:
+ case RadioError::INVALID_STATE:
+ case RadioError::NO_MEMORY:
+ case RadioError::SYSTEM_ERR:
+ case RadioError::MODEM_ERR:
+ case RadioError::INTERNAL_ERR:
+ case RadioError::INVALID_ARGUMENTS:
+ case RadioError::NO_RESOURCES:
+ SUCCEED();
+ break;
+ default:
+ FAIL();
+ break;
+ }
+}
diff --git a/radio/aidl/vts/radio_ims_utils.h b/radio/aidl/vts/radio_ims_utils.h
new file mode 100644
index 0000000..2bf80dc
--- /dev/null
+++ b/radio/aidl/vts/radio_ims_utils.h
@@ -0,0 +1,92 @@
+/*
+ * 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/radio/ims/BnRadioImsIndication.h>
+#include <aidl/android/hardware/radio/ims/BnRadioImsResponse.h>
+#include <aidl/android/hardware/radio/ims/IRadioIms.h>
+
+#include "radio_aidl_hal_utils.h"
+
+using namespace aidl::android::hardware::radio::ims;
+
+class RadioImsTest;
+
+/* Callback class for radio ims response */
+class RadioImsResponse : public BnRadioImsResponse {
+ protected:
+ RadioServiceTest& parent_ims;
+
+ public:
+ RadioImsResponse(RadioServiceTest& parent_ims);
+ virtual ~RadioImsResponse() = default;
+
+ RadioResponseInfo rspInfo;
+ std::optional<ConnectionFailureInfo> startImsTrafficResp;
+
+ virtual ndk::ScopedAStatus setSrvccCallInfoResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus updateImsRegistrationInfoResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus startImsTrafficResponse(
+ const RadioResponseInfo& info,
+ const std::optional<ConnectionFailureInfo>& response) override;
+
+ virtual ndk::ScopedAStatus stopImsTrafficResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus triggerEpsFallbackResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus sendAnbrQueryResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus updateImsCallStatusResponse(const RadioResponseInfo& info) override;
+};
+
+/* Callback class for radio ims indication */
+class RadioImsIndication : public BnRadioImsIndication {
+ protected:
+ RadioServiceTest& parent_ims;
+
+ public:
+ RadioImsIndication(RadioServiceTest& parent_ims);
+ virtual ~RadioImsIndication() = default;
+
+ virtual ndk::ScopedAStatus onConnectionSetupFailure(RadioIndicationType type,
+ int32_t token, const ConnectionFailureInfo& info) override;
+
+ virtual ndk::ScopedAStatus notifyAnbr(RadioIndicationType type, ImsStreamType mediaType,
+ ImsStreamDirection direction, int bitsPerSecond) override;
+
+ virtual ndk::ScopedAStatus triggerImsDeregistration(RadioIndicationType type,
+ ImsDeregistrationReason reason) override;
+};
+
+// The main test class for Radio AIDL Ims.
+class RadioImsTest : public ::testing::TestWithParam<std::string>, public RadioServiceTest {
+ protected:
+ virtual void verifyError(RadioError resp);
+
+ public:
+ virtual void SetUp() override;
+
+ /* radio ims service handle */
+ std::shared_ptr<IRadioIms> radio_ims;
+ /* radio ims response handle */
+ std::shared_ptr<RadioImsResponse> radioRsp_ims;
+ /* radio ims indication handle */
+ std::shared_ptr<RadioImsIndication> radioInd_ims;
+};
diff --git a/radio/aidl/vts/radio_network_indication.cpp b/radio/aidl/vts/radio_network_indication.cpp
index ae3bd4b..7178982 100644
--- a/radio/aidl/vts/radio_network_indication.cpp
+++ b/radio/aidl/vts/radio_network_indication.cpp
@@ -97,3 +97,8 @@
RadioIndicationType /*type*/, const EmergencyRegResult& /*result*/) {
return ndk::ScopedAStatus::ok();
}
+
+ndk::ScopedAStatus RadioNetworkIndication::onNetworkInitiatedLocationResult(
+ RadioIndicationType /*type*/, LocationResponseType /*locationResponseType*/) {
+ return ndk::ScopedAStatus::ok();
+}
diff --git a/radio/aidl/vts/radio_network_response.cpp b/radio/aidl/vts/radio_network_response.cpp
index 5599c03..4f0e4f3 100644
--- a/radio/aidl/vts/radio_network_response.cpp
+++ b/radio/aidl/vts/radio_network_response.cpp
@@ -293,3 +293,37 @@
parent_network.notify(info.serial);
return ndk::ScopedAStatus::ok();
}
+
+ndk::ScopedAStatus RadioNetworkResponse::setNullCipherAndIntegrityEnabledResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::isN1ModeEnabledResponse(
+ const RadioResponseInfo& info, bool /*isEnabled*/) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setN1ModeEnabledResponse(const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::setLocationPrivacySettingResponse(
+ const RadioResponseInfo& info) {
+ rspInfo = info;
+ parent_network.notify(info.serial);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus RadioNetworkResponse::getLocationPrivacySettingResponse(
+ const RadioResponseInfo& info, bool /*shareLocation*/) {
+ 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
index 25c42d3..5872eb0 100644
--- a/radio/aidl/vts/radio_network_test.cpp
+++ b/radio/aidl/vts/radio_network_test.cpp
@@ -1499,11 +1499,12 @@
// 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) {
+ if (rat == RadioTechnology::LTE) {
ASSERT_EQ(info.getTag(), AccessTechnologySpecificInfo::eutranInfo);
} else if (rat == RadioTechnology::NR) {
- ASSERT_EQ(info.getTag(), AccessTechnologySpecificInfo::ngranNrVopsInfo);
+ ASSERT_TRUE(info.getTag() == AccessTechnologySpecificInfo::ngranNrVopsInfo);
}
}
@@ -1848,7 +1849,7 @@
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_network->rspInfo.error,
- {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::RADIO_NOT_AVAILABLE,
RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS}));
LOG(DEBUG) << "setEmergencyMode finished";
}
@@ -1871,7 +1872,7 @@
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_network->rspInfo.error,
- {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE,
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::RADIO_NOT_AVAILABLE,
RadioError::MODEM_ERR, RadioError::INVALID_ARGUMENTS}));
LOG(DEBUG) << "triggerEmergencyNetworkScan finished";
}
@@ -1883,14 +1884,15 @@
LOG(DEBUG) << "cancelEmergencyNetworkScan";
serial = GetRandomSerialNumber();
- radio_network->cancelEmergencyNetworkScan(serial);
+ radio_network->cancelEmergencyNetworkScan(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);
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_network->rspInfo.error,
- {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::MODEM_ERR}));
LOG(DEBUG) << "cancelEmergencyNetworkScan finished";
}
@@ -1908,6 +1910,54 @@
ASSERT_TRUE(CheckAnyOfErrors(
radioRsp_network->rspInfo.error,
- {RadioError::NONE, RadioError::RADIO_NOT_AVAILABLE, RadioError::MODEM_ERR}));
+ {RadioError::NONE, RadioError::REQUEST_NOT_SUPPORTED, RadioError::RADIO_NOT_AVAILABLE,
+ RadioError::MODEM_ERR}));
LOG(DEBUG) << "exitEmergencyMode finished";
}
+
+/*
+ * Test IRadioNetwork.setN1ModeEnabled() for the response returned.
+ */
+TEST_P(RadioNetworkTest, setN1ModeEnabled) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res =
+ radio_network->setN1ModeEnabled(serial, false);
+ 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.isN1ModeEnabled() for the response returned.
+ */
+TEST_P(RadioNetworkTest, isN1ModeEnabled) {
+ serial = GetRandomSerialNumber();
+
+ ndk::ScopedAStatus res = radio_network->isN1ModeEnabled(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::REQUEST_NOT_SUPPORTED, RadioError::NONE}));
+ }
+}
diff --git a/radio/aidl/vts/radio_network_utils.h b/radio/aidl/vts/radio_network_utils.h
index 8480825..92dcb1f 100644
--- a/radio/aidl/vts/radio_network_utils.h
+++ b/radio/aidl/vts/radio_network_utils.h
@@ -158,6 +158,20 @@
virtual ndk::ScopedAStatus cancelEmergencyNetworkScanResponse(
const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setNullCipherAndIntegrityEnabledResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus isN1ModeEnabledResponse(
+ const RadioResponseInfo& info, bool isEnabled) override;
+
+ virtual ndk::ScopedAStatus setN1ModeEnabledResponse(const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus setLocationPrivacySettingResponse(
+ const RadioResponseInfo& info) override;
+
+ virtual ndk::ScopedAStatus getLocationPrivacySettingResponse(const RadioResponseInfo& info,
+ bool shareLocation) override;
};
/* Callback class for radio network indication */
@@ -215,6 +229,9 @@
virtual ndk::ScopedAStatus emergencyNetworkScanResult(
RadioIndicationType type, const EmergencyRegResult& result) override;
+
+ virtual ndk::ScopedAStatus onNetworkInitiatedLocationResult(
+ RadioIndicationType type, LocationResponseType locationResponseType) override;
};
// The main test class for Radio AIDL Network.
diff --git a/secure_element/aidl/Android.bp b/secure_element/aidl/Android.bp
new file mode 100644
index 0000000..5a529a4
--- /dev/null
+++ b/secure_element/aidl/Android.bp
@@ -0,0 +1,35 @@
+aidl_interface {
+ name: "android.hardware.secure_element",
+ vendor_available: true,
+ host_supported: true,
+ srcs: ["android/hardware/secure_element/*.aidl"],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: false,
+ },
+ java: {
+ sdk_version: "system_current",
+ },
+ },
+}
+
+cc_test {
+ name: "VtsHalSecureElementTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["vts/VtsHalSecureElementTargetTest.cpp"],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ static_libs: [
+ "android.hardware.secure_element-V1-ndk",
+ "libgmock",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
diff --git a/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElement.aidl b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElement.aidl
new file mode 100644
index 0000000..fba29ab
--- /dev/null
+++ b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElement.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.secure_element;
+@VintfStability
+interface ISecureElement {
+ void closeChannel(in byte channelNumber);
+ byte[] getAtr();
+ void init(in android.hardware.secure_element.ISecureElementCallback clientCallback);
+ boolean isCardPresent();
+ byte[] openBasicChannel(in byte[] aid, in byte p2);
+ android.hardware.secure_element.LogicalChannelResponse openLogicalChannel(in byte[] aid, in byte p2);
+ void reset();
+ byte[] transmit(in byte[] data);
+ const int FAILED = 1;
+ const int CHANNEL_NOT_AVAILABLE = 2;
+ const int NO_SUCH_ELEMENT_ERROR = 3;
+ const int UNSUPPORTED_OPERATION = 4;
+ const int IOERROR = 5;
+}
diff --git a/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElementCallback.aidl b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElementCallback.aidl
new file mode 100644
index 0000000..6c2be2a
--- /dev/null
+++ b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/ISecureElementCallback.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.secure_element;
+@VintfStability
+interface ISecureElementCallback {
+ void onStateChange(in boolean connected, in String debugReason);
+}
diff --git a/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/LogicalChannelResponse.aidl b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/LogicalChannelResponse.aidl
new file mode 100644
index 0000000..f2e7f04
--- /dev/null
+++ b/secure_element/aidl/aidl_api/android.hardware.secure_element/current/android/hardware/secure_element/LogicalChannelResponse.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.secure_element;
+@VintfStability
+parcelable LogicalChannelResponse {
+ byte channelNumber;
+ byte[] selectResponse;
+}
diff --git a/secure_element/aidl/android/hardware/secure_element/ISecureElement.aidl b/secure_element/aidl/android/hardware/secure_element/ISecureElement.aidl
new file mode 100644
index 0000000..7c5a704
--- /dev/null
+++ b/secure_element/aidl/android/hardware/secure_element/ISecureElement.aidl
@@ -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.
+ */
+
+package android.hardware.secure_element;
+
+import android.hardware.secure_element.ISecureElementCallback;
+import android.hardware.secure_element.LogicalChannelResponse;
+
+@VintfStability
+interface ISecureElement {
+ const int FAILED = 1;
+ const int CHANNEL_NOT_AVAILABLE = 2;
+ const int NO_SUCH_ELEMENT_ERROR = 3;
+ const int UNSUPPORTED_OPERATION = 4;
+ const int IOERROR = 5;
+
+ /**
+ * Closes the channel indicated by the channelNumber.
+ *
+ * @throws ServiceSpecificException Closing a channel must return
+ * FAILED on an error or if a basic channel (i.e. channel 0)
+ * is used.
+ *
+ * @param channelNumber to be closed
+ */
+ void closeChannel(in byte channelNumber);
+
+ /**
+ * Returns Answer to Reset as per ISO/IEC 7816
+ *
+ * @return containing the response. Empty vector if Secure Element
+ * doesn't support ATR.
+ */
+ byte[] getAtr();
+
+ /**
+ * Initializes the Secure Element. This may include updating the applet
+ * and/or vendor-specific initialization.
+ *
+ * HAL service must send onStateChange() with connected equal to true
+ * after all the initialization has been successfully completed.
+ * Clients must wait for a onStateChange(true) before opening channels.
+ *
+ * @param clientCallback callback used to sent status of the SE back to the
+ * client
+ */
+ void init(in ISecureElementCallback clientCallback);
+
+ /**
+ * Returns the current state of the card.
+ *
+ * This is useful for removable Secure Elements like UICC,
+ * Secure Elements on SD cards etc.
+ *
+ * @return true if present, false otherwise
+ */
+ boolean isCardPresent();
+
+ /**
+ * Opens a basic channel with the Secure Element, selecting the applet
+ * represented by the Application ID (AID). A basic channel has channel
+ * number 0.
+ *
+ * @throws ServiceSpecificException with codes
+ * - CHANNEL_NOT_AVAILABLE if secure element has reached the maximum
+ * limit on the number of channels it can support.
+ * - NO_SUCH_ELEMENT_ERROR if AID provided doesn't match any applet
+ * on the secure element.
+ * - UNSUPPORTED_OPERATION if operation provided by the P2 parameter
+ * is not permitted by the applet.
+ * - IOERROR if there was an error communicating with the Secure Element.
+ *
+ * @param aid AID to uniquely identify the applet on the Secure Element
+ * @param p2 P2 parameter of SELECT APDU as per ISO 7816-4
+ *
+ * @return On success, response to SELECT command.
+ */
+ byte[] openBasicChannel(in byte[] aid, in byte p2);
+
+ /**
+ * Opens a logical channel with the Secure Element, selecting the applet
+ * represented by the Application ID (AID).
+ *
+ * @param aid AID to uniquely identify the applet on the Secure Element
+ * @param p2 P2 parameter of SELECT APDU as per ISO 7816-4
+ * @throws ServiceSpecificException on error with the following code:
+ * - CHANNEL_NOT_AVAILABLE if secure element has reached the maximum
+ * limit on the number of channels it can support.
+ * - NO_SUCH_ELEMENT_ERROR if AID provided doesn't match any applet
+ * on the secure element.
+ * - UNSUPPORTED_OPERATION if operation provided by the P2 parameter
+ * is not permitted by the applet.
+ * - IOERROR if there was an error communicating with the Secure Element.
+ *
+ * @return On success, response to SELECT command
+ */
+ LogicalChannelResponse openLogicalChannel(in byte[] aid, in byte p2);
+
+ /**
+ * Reset the Secure Element.
+ *
+ * HAL should trigger reset to the secure element. It could hardware power cycle or
+ * a soft reset depends on the hardware design.
+ * HAL service must send onStateChange() with connected equal to true
+ * after resetting and all the re-initialization has been successfully completed.
+ */
+ void reset();
+
+ /**
+ * Transmits an APDU command (as per ISO/IEC 7816) to the SE.
+ *
+ * @param data APDU command to be sent
+ * @return response to the command
+ */
+ byte[] transmit(in byte[] data);
+}
diff --git a/secure_element/aidl/android/hardware/secure_element/ISecureElementCallback.aidl b/secure_element/aidl/android/hardware/secure_element/ISecureElementCallback.aidl
new file mode 100644
index 0000000..d15a7fb
--- /dev/null
+++ b/secure_element/aidl/android/hardware/secure_element/ISecureElementCallback.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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.secure_element;
+
+@VintfStability
+interface ISecureElementCallback {
+ /**
+ * Used to inform the client about changes in the state of the Secure
+ * Element.
+ *
+ * @param connected indicates the current state of the SE
+ * @param reason provides additional data why there was a change in state
+ * ex. initialization error, SE removed etc
+ * This is used only for debugging purpose to understand
+ * in-field issues.
+ */
+ void onStateChange(in boolean connected, in String debugReason);
+}
diff --git a/secure_element/aidl/android/hardware/secure_element/LogicalChannelResponse.aidl b/secure_element/aidl/android/hardware/secure_element/LogicalChannelResponse.aidl
new file mode 100644
index 0000000..65ea71e
--- /dev/null
+++ b/secure_element/aidl/android/hardware/secure_element/LogicalChannelResponse.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.secure_element;
+
+@VintfStability
+parcelable LogicalChannelResponse {
+ /**
+ * Channel number to uniquely identify the channel
+ */
+ byte channelNumber;
+ /**
+ * Response to SELECT command as per ISO/IEC 7816
+ */
+ byte[] selectResponse;
+}
diff --git a/secure_element/aidl/default/Android.bp b/secure_element/aidl/default/Android.bp
new file mode 100644
index 0000000..c604b68
--- /dev/null
+++ b/secure_element/aidl/default/Android.bp
@@ -0,0 +1,15 @@
+cc_binary {
+ name: "android.hardware.secure_element-service.example",
+ relative_install_path: "hw",
+ vendor: true,
+ init_rc: ["secure_element.rc"],
+ vintf_fragments: ["secure_element.xml"],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "android.hardware.secure_element-V1-ndk",
+ ],
+ srcs: [
+ "main.cpp",
+ ],
+}
diff --git a/secure_element/aidl/default/main.cpp b/secure_element/aidl/default/main.cpp
new file mode 100644
index 0000000..16b8236
--- /dev/null
+++ b/secure_element/aidl/default/main.cpp
@@ -0,0 +1,159 @@
+/*
+ * 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/android/hardware/secure_element/BnSecureElement.h>
+
+#include <android-base/hex.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::secure_element::BnSecureElement;
+using aidl::android::hardware::secure_element::ISecureElementCallback;
+using aidl::android::hardware::secure_element::LogicalChannelResponse;
+using android::base::HexString;
+using ndk::ScopedAStatus;
+
+static const std::vector<uint8_t> kAndroidTestAid = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41,
+ 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64,
+ 0x43, 0x54, 0x53, 0x31};
+static const std::vector<uint8_t> kLongAndroidTestAid = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41,
+ 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64,
+ 0x43, 0x54, 0x53, 0x32};
+
+class MySecureElement : public BnSecureElement {
+ public:
+ ScopedAStatus closeChannel(int8_t channelNumber) override {
+ LOG(INFO) << __func__ << " channel number: " << channelNumber;
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus getAtr(std::vector<uint8_t>* _aidl_return) override {
+ LOG(INFO) << __func__;
+ _aidl_return->clear();
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus init(const std::shared_ptr<ISecureElementCallback>& clientCallback) override {
+ LOG(INFO) << __func__ << " callback: " << clientCallback.get();
+ if (!clientCallback) {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
+ mCb = clientCallback;
+ mCb->onStateChange(true, "");
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus isCardPresent(bool* _aidl_return) override {
+ LOG(INFO) << __func__;
+ *_aidl_return = true;
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus openBasicChannel(const std::vector<uint8_t>& aid, int8_t p2,
+ std::vector<uint8_t>* _aidl_return) override {
+ LOG(INFO) << __func__ << " aid: " << HexString(aid.data(), aid.size()) << " (" << aid.size()
+ << ") p2 " << p2;
+
+ // TODO(b/123254068) - this is not an implementation of the OMAPI protocol or APDU.
+ // The functionality here is enough to exercise the framework, but actual
+ // calls to the secure element will fail. This implementation does not model
+ // channel isolation or any other aspects important to implementing secure element.
+ *_aidl_return = {0x90, 0x00, 0x00}; // DO NOT COPY
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus openLogicalChannel(
+ const std::vector<uint8_t>& aid, int8_t p2,
+ ::aidl::android::hardware::secure_element::LogicalChannelResponse* _aidl_return)
+ override {
+ LOG(INFO) << __func__ << " aid: " << HexString(aid.data(), aid.size()) << " (" << aid.size()
+ << ") p2 " << p2;
+
+ if (aid != kAndroidTestAid && aid != kLongAndroidTestAid) {
+ return ScopedAStatus::fromServiceSpecificError(NO_SUCH_ELEMENT_ERROR);
+ }
+
+ *_aidl_return = LogicalChannelResponse{.channelNumber = 1, .selectResponse = {}};
+
+ // TODO(b/123254068) - this is not an implementation of the OMAPI protocol or APDU.
+ // The functionality here is enough to exercise the framework, but actual
+ // calls to the secure element will fail. This implementation does not model
+ // channel isolation or any other aspects important to implementing secure element.
+ if (aid == kAndroidTestAid) { // DO NOT COPY
+ size_t size = 2050; // DO NOT COPY
+ _aidl_return->selectResponse.resize(size); // DO NOT COPY
+ _aidl_return->selectResponse[size - 1] = 0x00; // DO NOT COPY
+ _aidl_return->selectResponse[size - 2] = 0x90; // DO NOT COPY
+ } else { // DO NOT COPY
+ _aidl_return->selectResponse = {0x00, 0x00, 0x90, 0x00}; // DO NOT COPY
+ } // DO NOT COPY
+
+ LOG(INFO) << __func__ << " sending response: "
+ << HexString(_aidl_return->selectResponse.data(),
+ _aidl_return->selectResponse.size());
+
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus reset() override {
+ LOG(INFO) << __func__;
+ mCb->onStateChange(false, "reset");
+ mCb->onStateChange(true, "reset");
+ return ScopedAStatus::ok();
+ }
+ ScopedAStatus transmit(const std::vector<uint8_t>& data,
+ std::vector<uint8_t>* _aidl_return) override {
+ LOG(INFO) << __func__ << " data: " << HexString(data.data(), data.size()) << " ("
+ << data.size() << ")";
+
+ // TODO(b/123254068) - this is not an implementation of the OMAPI protocol or APDU.
+ // The functionality here is enough to exercise the framework, but actual
+ // calls to the secure element will fail. This implementation does not model
+ // channel isolation or any other aspects important to implementing secure element.
+
+ std::string hex = HexString(data.data(), data.size()); // DO NOT COPY
+ if (hex == "01a4040210a000000476416e64726f696443545331") { // DO NOT COPY
+ *_aidl_return = {0x00, 0x6A, 0x00}; // DO NOT COPY
+ } else if (data == std::vector<uint8_t>{0x00, 0xF4, 0x00, 0x00, 0x00}) { // DO NOT COPY
+ // CHECK_SELECT_P2_APDU w/ channel 1 // DO NOT COPY
+ *_aidl_return = {0x00, 0x90, 0x00}; // DO NOT COPY
+ } else if (data == std::vector<uint8_t>{0x01, 0xF4, 0x00, 0x00, 0x00}) { // DO NOT COPY
+ // CHECK_SELECT_P2_APDU w/ channel 1 // DO NOT COPY
+ *_aidl_return = {0x00, 0x90, 0x00}; // DO NOT COPY
+ } else if (data.size() == 5 || data.size() == 8) { // DO NOT COPY
+ // SEGMENTED_RESP_APDU - happens to use length 5 and 8 // DO NOT COPY
+ size_t size = (data[2] << 8 | data[3]) + 2; // DO NOT COPY
+ _aidl_return->resize(size); // DO NOT COPY
+ (*_aidl_return)[size - 1] = 0x00; // DO NOT COPY
+ (*_aidl_return)[size - 2] = 0x90; // DO NOT COPY
+ if (size >= 3) (*_aidl_return)[size - 3] = 0xFF; // DO NOT COPY
+ } else { // DO NOT COPY
+ *_aidl_return = {0x90, 0x00, 0x00}; // DO NOT COPY
+ } // DO NOT COPY
+
+ return ScopedAStatus::ok();
+ }
+
+ private:
+ std::shared_ptr<ISecureElementCallback> mCb;
+};
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+
+ auto se = ndk::SharedRefBase::make<MySecureElement>();
+ const std::string name = std::string() + BnSecureElement::descriptor + "/eSE1";
+ binder_status_t status = AServiceManager_addService(se->asBinder().get(), name.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/secure_element/aidl/default/secure_element.rc b/secure_element/aidl/default/secure_element.rc
new file mode 100644
index 0000000..7d21666
--- /dev/null
+++ b/secure_element/aidl/default/secure_element.rc
@@ -0,0 +1,4 @@
+service vendor.secure_element /vendor/bin/hw/android.hardware.secure_element-service.example
+ class hal
+ user nobody
+ group nobody
diff --git a/secure_element/aidl/default/secure_element.xml b/secure_element/aidl/default/secure_element.xml
new file mode 100644
index 0000000..96ab2e7
--- /dev/null
+++ b/secure_element/aidl/default/secure_element.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.secure_element</name>
+ <version>1</version>
+ <fqname>ISecureElement/eSE1</fqname>
+ </hal>
+</manifest>
diff --git a/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp b/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
new file mode 100644
index 0000000..a85a8bc
--- /dev/null
+++ b/secure_element/aidl/vts/VtsHalSecureElementTargetTest.cpp
@@ -0,0 +1,176 @@
+/*
+ * 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/secure_element/BnSecureElementCallback.h>
+#include <aidl/android/hardware/secure_element/ISecureElement.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <chrono>
+#include <condition_variable>
+#include <mutex>
+
+using namespace std::chrono_literals;
+
+using aidl::android::hardware::secure_element::BnSecureElementCallback;
+using aidl::android::hardware::secure_element::ISecureElement;
+using aidl::android::hardware::secure_element::LogicalChannelResponse;
+using ndk::ScopedAStatus;
+using ndk::SharedRefBase;
+using ndk::SpAIBinder;
+using testing::ElementsAre;
+using testing::ElementsAreArray;
+
+#define EXPECT_OK(status) \
+ do { \
+ auto status_impl = (status); \
+ EXPECT_TRUE(status_impl.isOk()) << status_impl.getDescription(); \
+ } while (false)
+
+static const std::vector<uint8_t> kDataApdu = {0x00, 0x08, 0x00, 0x00, 0x00};
+static const std::vector<uint8_t> kAndroidTestAid = {0xA0, 0x00, 0x00, 0x04, 0x76, 0x41,
+ 0x6E, 0x64, 0x72, 0x6F, 0x69, 0x64,
+ 0x43, 0x54, 0x53, 0x31};
+
+class MySecureElementCallback : public BnSecureElementCallback {
+ public:
+ ScopedAStatus onStateChange(bool state, const std::string& debugReason) override {
+ {
+ std::unique_lock<std::mutex> l(m);
+ (void)debugReason;
+ history.push_back(state);
+ }
+ cv.notify_one();
+ return ScopedAStatus::ok();
+ };
+
+ void expectCallbackHistory(std::vector<bool>&& want) {
+ std::unique_lock<std::mutex> l(m);
+ cv.wait_for(l, 2s, [&]() { return history.size() >= want.size(); });
+ EXPECT_THAT(history, ElementsAreArray(want));
+ }
+
+ private:
+ std::mutex m; // guards history
+ std::condition_variable cv;
+ std::vector<bool> history;
+};
+
+class SecureElementAidl : public ::testing::TestWithParam<std::string> {
+ public:
+ virtual void SetUp() override {
+ SpAIBinder binder = SpAIBinder(AServiceManager_waitForService(GetParam().c_str()));
+ se = ISecureElement::fromBinder(binder);
+ ASSERT_NE(se, nullptr);
+
+ cb = SharedRefBase::make<MySecureElementCallback>();
+ EXPECT_OK(se->init(cb));
+
+ cb->expectCallbackHistory({true});
+ }
+
+ std::shared_ptr<ISecureElement> se;
+ std::shared_ptr<MySecureElementCallback> cb;
+};
+
+TEST_P(SecureElementAidl, isCardPresent) {
+ bool res = false;
+ EXPECT_OK(se->isCardPresent(&res));
+ EXPECT_TRUE(res);
+}
+
+TEST_P(SecureElementAidl, transmit) {
+ LogicalChannelResponse response;
+ EXPECT_OK(se->openLogicalChannel(kAndroidTestAid, 0x00, &response));
+
+ EXPECT_GE(response.selectResponse.size(), 2u);
+ EXPECT_GE(response.channelNumber, 1);
+
+ std::vector<uint8_t> command = kDataApdu;
+ command[0] |= response.channelNumber;
+
+ std::vector<uint8_t> transmitResponse;
+ EXPECT_OK(se->transmit(command, &transmitResponse));
+
+ EXPECT_LE(transmitResponse.size(), 3);
+ EXPECT_GE(transmitResponse.size(), 2);
+ EXPECT_EQ(transmitResponse[transmitResponse.size() - 1], 0x00);
+ EXPECT_EQ(transmitResponse[transmitResponse.size() - 2], 0x90);
+
+ EXPECT_OK(se->closeChannel(response.channelNumber));
+}
+
+TEST_P(SecureElementAidl, openBasicChannel) {
+ std::vector<uint8_t> response;
+ auto status = se->openBasicChannel(kAndroidTestAid, 0x00, &response);
+
+ if (!status.isOk()) {
+ EXPECT_EQ(status.getServiceSpecificError(), ISecureElement::CHANNEL_NOT_AVAILABLE)
+ << status.getDescription();
+ return;
+ }
+
+ EXPECT_GE(response.size(), 2u);
+ EXPECT_OK(se->closeChannel(0));
+}
+
+TEST_P(SecureElementAidl, getAtr) {
+ std::vector<uint8_t> atr;
+ EXPECT_OK(se->getAtr(&atr));
+ if (atr.size() == 0) {
+ return;
+ }
+ EXPECT_LE(atr.size(), 32u);
+ EXPECT_GE(atr.size(), 1u);
+}
+
+TEST_P(SecureElementAidl, openCloseLogicalChannel) {
+ LogicalChannelResponse response;
+ EXPECT_OK(se->openLogicalChannel(kAndroidTestAid, 0x00, &response));
+ EXPECT_GE(response.selectResponse.size(), 2u);
+ EXPECT_GE(response.channelNumber, 1);
+ EXPECT_OK(se->closeChannel(response.channelNumber));
+}
+
+TEST_P(SecureElementAidl, openInvalidAid) {
+ LogicalChannelResponse response;
+ auto status = se->openLogicalChannel({0x42}, 0x00, &response);
+ EXPECT_EQ(status.getServiceSpecificError(), ISecureElement::NO_SUCH_ELEMENT_ERROR)
+ << status.getDescription();
+}
+
+TEST_P(SecureElementAidl, Reset) {
+ cb->expectCallbackHistory({true});
+ EXPECT_OK(se->reset());
+ cb->expectCallbackHistory({true, false, true});
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SecureElementAidl);
+INSTANTIATE_TEST_SUITE_P(
+ SecureElement, SecureElementAidl,
+ testing::ValuesIn(android::getAidlHalInstanceNames(ISecureElement::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/security/OWNERS b/security/OWNERS
index f061cd6..fbaf854 100644
--- a/security/OWNERS
+++ b/security/OWNERS
@@ -1,7 +1,14 @@
-# Please assign all bugs related to /hardware/interfaces/security to the team alias,
-# android-hardware-security@google.com. This will get them auto-assigned to the on-call triage
-# engineer, ensuring quickest response.
+# Bug component: 1084733
+
+# Please assign all bugs related to /hardware/interfaces/security/ to the team alias:
+#
+# android-hardware-security@google.com
+#
+# This will get them auto-assigned to the on-call triage engineer, ensuring quickest response.
+
drysdale@google.com
+eranm@google.com
+hasinitg@google.com
jbires@google.com
-seleneh@google.com
swillden@google.com
+zeuthen@google.com
diff --git a/security/keymint/README.md b/security/keymint/README.md
new file mode 100644
index 0000000..54647af
--- /dev/null
+++ b/security/keymint/README.md
@@ -0,0 +1,10 @@
+# KeyMint HAL
+
+This directory contains the HAL definition for KeyMint. KeyMint provides
+cryptographic services in a hardware-isolated environment.
+
+Note that the `IRemotelyProvisionedComponent` HAL, and it's associated types,
+used to also be defined in this directory. As of Android U, this HAL has been
+moved to a different directory (../rkp). This move is ABI compatible, as the
+interfaces have been maintained. The build is split so that the generated
+code may be built with different options.
diff --git a/security/keymint/RKP_CHANGELOG.md b/security/keymint/RKP_CHANGELOG.md
deleted file mode 100644
index dfcc938..0000000
--- a/security/keymint/RKP_CHANGELOG.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Remote Provisioning Changelog
-
-This document provides an exact description of which changes have occurred in the
-`IRemotelyProvisionedComponent` HAL interface in each Android release.
-
-## Releases
-* **Android S (12):** IRemotelyProvisionedComponent v1
-* **Android T (13):** IRemotelyProvisionedComponent v2
-* **Android U (14):** IRemotelyProvisionedComponent v3
-
-## IRemotelyProvisionedComponent 1 -> 2
-* DeviceInfo
- * Most entries are no longer optional.
- * `att_id_state` is now `fused`. `fused` is used to indicate if SecureBoot is enabled.
- * `version` is now `2`.
- * `board` has been removed.
- * `device` has been added.
-* RpcHardwareInfo
- * `uniqueId` String added as a field in order to differentiate IRPC instances on device.
-
-## IRemotelyProvisionedComponent 2 -> 3
-* ProtectedData has been removed.
-* DeviceInfo
- * `cert_type` has been added, with values corresponding to `widevine` or `keymint`
- * `version` has moved to a top-level field within the CSR generated by the HAL
-* IRemotelyProvisionedComponent
- * The need for an EEK has been removed. There is no longer an encrypted portion of the CSR.
- * Test mode has been removed.
- * The schema for the CSR itself has been significantly simplified, please see
- IRemotelyProvisionedComponent.aidl for more details.
- * Notably, the chain of signing, MACing, and encryption operations has been replaced with a single
- COSE_Sign1 object.
-
diff --git a/security/keymint/RKP_README.md b/security/keymint/RKP_README.md
deleted file mode 100644
index 89a2598..0000000
--- a/security/keymint/RKP_README.md
+++ /dev/null
@@ -1,374 +0,0 @@
-# Remote Provisioning HAL
-
-## Objective
-
-Design a HAL to support over-the-air provisioning of certificates for asymmetric
-keys. The HAL must interact effectively with Keystore (and other daemons) and
-protect device privacy and security.
-
-Note that this API is designed for KeyMint, but with the intention that it
-should be usable for other HALs that require certificate provisioning.
-Throughout this document we'll refer to the Keystore and KeyMint (formerly
-called Keymaster) components, but only for concreteness and convenience; those
-labels could be replaced with the names of any system and secure area
-components, respectively, that need certificates provisioned.
-
-## Key design decisions
-
-### General approach
-
-To more securely and reliably get keys and certificates to Android devices, we
-need to create a system where no party outside of the device's secure components
-is responsible for managing private keys. The strategy we've chosen is to
-deliver certificates over the air, using an asymmetric key pair created
-on-device in the factory as a root of trust to create an authenticated, secure
-channel. In this document we refer to this device-unique asymmetric key pair as
-Device Key (DK), its public half DK\_pub, its private half DK\_priv and a Device
-Key Certificate containing DK\_pub is denoted DKC.
-
-In order for the provisioning service to use DK (or a key authenticated by DK),
-it must know whether a given DK\_pub is known and trusted. To prove trust, we
-ask device OEMs to use one of two mechanisms:
-
-1. (Preferred, recommended) The device OEM extracts DK\_pub from each device it
- manufactures and uploads the public keys to a backend server.
-
-1. The device OEM signs the DK\_pub to produce DKC and stores it on the device.
- This has the advantage that they don't need to upload a DK\_pub for every
- device immediately, but the disadvantage that they have to manage their
- private signing keys, which means they have to have HSMs, configure and
- secure them correctly, etc. Some backend providers may also require that the
- OEM passes a factory security audit, and additionally promises to upload the
- keys eventually as well.
-
-Note that in the full elaboration of this plan, DK\_pub is not the key used to
-establish a secure channel. Instead, DK\_pub is just the first public key in a
-chain of public keys which ends with the KeyMint public key, KM\_pub. All keys
-in the chain are device-unique and are joined in a certificate chain called the
-_Boot Certificate Chain_ (BCC), because in phases 2 and 3 of the remote
-provisioning project it is a chain of certificates corresponding to boot phases.
-We speak of the BCC even for phase 1, though in phase 1 it contains only a
-single self-signed DKC. This is described in more depth in the Phases section
-below.
-
-The BCC is authenticated by DK\_pub. To authenticate DK\_pub, we may have
-additional DKCs, from the SoC vendor, the device OEM, or both. Those are not
-part of the BCC but included as optional fields in the certificate request
-structure.
-
-The format of the the DK and BCC is specified within [Open Profile for DICE]
-(https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md). To
-map phrases within this document to their equivalent terminology in the DICE
-specification, read the terms as follows: the DK corresponds to the UDS-derived
-key pair, DKC corresponds to the UDS certificate, and the BCC entries between
-DK\_pub and KM\_pub correspond to a chain of CDI certificates.
-
-Note: In addition to allowing 32 byte hash values for fields in the BCC payload,
-this spec additionally constrains some of the choices allowed in open-DICE.
-Specifically, these include which entries are required and which are optional in
-the BCC payload, and which algorithms are acceptable for use.
-
-### Phases
-
-RKP will be deployed in three phases, in terms of managing the root of trust
-binding between the device and the backend. To briefly describe them:
-
-* Phase 1: In phase 1 there is only one entry in the BCC; DK_pub and KM_pub are
- the same key and the certificate is self-signed.
-* Phase 2: This is identical to phase 1, except it leverages the hardware root
- of trust process described by DICE. Instead of trust being rooted in the TEE,
- it is now rooted in the ROM by key material blown into fuses which are only
- accessible to the ROM code.
-* Phase 3: This is identical to Phase 2, except the SoC vendor also does the
- public key extraction or certification in their facilities, along with the OEM
- doing it in the factory. This tightens up the "supply chain" and aims to make
- key upload management more secure.
-
-### Privacy considerations
-
-Because DK and the DKCs are unique, immutable, unspoofable hardware-bound
-identifiers for the device, we must limit access to them to the absolute minimum
-possible. We do this in two ways:
-
-1. We require KeyMint (which knows the BCC and either knows or at least has the
-ability to use KM\_priv) to refuse to ever divulge the BCC or additional
-signatures in plaintext. Instead, KeyMint requires the caller to provide an
-_Endpoint Encryption Key_ (EEK), with which it will encrypt the data before
-returning it. When provisioning production keys, the EEK must be signed by an
-approved authority whose public key is embedded in KeyMint. When certifying test
-keys, KeyMint will accept any EEK without checking the signature, but will
-encrypt and return a test BCC, rather than the real one. The result is that
-only an entity in possession of an Trusted EEK (TEEK) private key can discover
-the plaintext of the production BCC.
-1. Having thus limited access to the public keys to the trusted party only, we
-need to prevent the entity from abusing this unique device identifier. The
-approach and mechanisms for doing that are beyond the scope of this document
-(they must be addressed in the server design), but generally involve taking care
-to ensure that we do not create any links between user IDs, IP addresses or
-issued certificates and the device pubkey.
-
-Although the details of the mechanisms for preventing the entity from abusing
-the BCC are, as stated, beyond the scope of this document, there is a subtle
-design decision here made specifically to enable abuse prevention. Specifically
-the `CertificateRequest` message sent to the server is (in
-[CDDL](https://tools.ietf.org/html/rfc8610)):
-
-```
-cddl
-CertificateRequest = [
- DeviceInfo,
- challenge : bstr,
- ProtectedData,
- MacedKeysToSign
-]
-```
-
-The public keys to be attested by the server are in `MacedKeysToSign`, which is
-a COSE\_Mac0 structure, MACed with a key that is found in `ProtectedData`. The
-MAC key is signed by DK\_pub.
-
-This structure allows the backend component that has access to EEK\_priv to
-decrypt `ProtectedData`, validate that the request is from an authorized device,
-check that the request is fresh and verify and extract the MAC key. That backend
-component never sees any data related to the keys to be signed, but can provide
-the MAC key to another backend component that can verify `MacedKeysToSign` and
-proceed to generate the certificates.
-
-In this way, we can partition the provisioning server into one component that
-knows the device identity, as represented by DK\_pub, but never sees the keys to
-be certified or certificates generated, and another component that sees the keys
-to be certified and certificates generated but does not know the device
-identity.
-
-### Key and cryptographic message formatting
-
-For simplicity of generation and parsing, compactness of wire representation,
-and flexibility and standardization, we've settled on using the CBOR Object
-Signing and Encryption (COSE) standard, defined in [RFC
-8152](https://tools.ietf.org/html/rfc8152). COSE provides compact and reasonably
-simple, yet easily-extensible, wire formats for:
-
-* Keys,
-* MACed messages,
-* Signed messages, and
-* Encrypted messages
-
-COSE enables easy layering of these message formats, such as using a COSE\_Sign
-structure to contain a COSE\_Key with a public key in it. We call this a
-"certificate".
-
-Due to the complexity of the standard, we'll spell out the COSE structures
-completely in this document and in the HAL and other documentation, so that
-although implementors will need to understand CBOR and the CBOR Data Definition
-Language ([CDDL, defined in RFC 8610](https://tools.ietf.org/html/rfc8610)),
-they shouldn't need to understand COSE.
-
-Note, however, that the certificate chains returned from the provisioning server
-are standard X.509 certificates.
-
-### Algorithm choices
-
-This document uses:
-
-* ECDSA P-256 for attestation signing keys;
-* Remote provisioning protocol signing keys:
- * Ed25519 / P-256
-* ECDH keys:
- * X25519 / P-256
-* AES-GCM for all encryption;
-* SHA-256 for all message digesting;
-* HMAC-SHA-256 for all MACing; and
-* HKDF-SHA-256 for all key derivation.
-
-We believe that Curve25519 offers the best tradeoff in terms of security,
-efficiency and global trustworthiness, and that it is now sufficiently
-widely-used and widely-implemented to make it a practical choice.
-
-However, since Secure Elements (SE) do not currently offer support for curve
-25519, we are allowing implementations to instead make use of EC P-256 for
-signing and ECDH. To put it simply, the device unique key pair will be a P-256
-key pair for ECDSA instead of Ed25519, and the ProtectedData COSE\_Encrypt
-message will have its payload encrypted with P-256 ECDH key exchange instead of
-X25519.
-
-The CDDL in the rest of the document will use the '/' operator to show areas
-where either curve 25519 or P-256 may be used. Since there is no easy way to
-bind choices across different CDDL groups, it is important that the implementor
-stays consistent in which type is chosen. E.g. taking ES256 as the choice for
-algorithm implies the implementor should also choose the P256 public key group
-further down in the COSE structure.
-
-### Testability
-
-It's critical that the remote provisioning implementation be testable, to
-minimize the probability that broken devices are sold to end users. To support
-testing, the remote provisioning HAL methods take a `testMode` argument. Keys
-created in test mode are tagged to indicate this. The provisioning server will
-check for the test mode tag and issue test certificates that do not chain back
-to a trusted public key. In test mode, any EEK will be accepted, enabling
-testing tools to use EEKs for which they have the private key so they can
-validate the content of certificate requests. The BCC included in the
-`CertificateRequest` must contain freshly-generated keys, not the real BCC keys.
-
-Keystore (or similar) will need to be able to handle both testMode keys and
-production keys and keep them distinct, generating test certificate requests
-when asked with a test EEK and production certificate requests when asked with a
-production EEK. Likewise, the interface used to instruct Keystore to create keys
-will need to be able to specify whether test or production keys are desired.
-
-## Design
-
-### Certificate provisioning flow
-
-TODO(jbires): Replace this with a `.png` containing a sequence diagram. The
-provisioning flow looks something like this:
-
-Provisioner -> Keystore: Prepare N keys
-Keystore -> KeyMint: generateKeyPair
-KeyMint -> KeyMint: Generate key pair
-KeyMint --> Keystore: key\_blob,pubkey
-Keystore -> Keystore: Store key\_blob,pubkey
-Provisioner -> Server: Get TEEK
-Server --> Provisioner: TEEK
-Provisioner -> Keystore: genCertReq(N, TEEK)
-Keystore -> KeyMint: genCertReq(pubkeys, TEEK)
-KeyMint -> KeyMint: Sign pubkeys & encrypt BCC
-KeyMint --> Keystore: signature, encrypted BCC
-Keystore -> Keystore: Construct cert\_request
-Keystore --> Provisioner: cert\_request
-Provisioner --> Server: cert\_request
-Server -> Server: Validate cert\_request
-Server -> Server: Generate certificates
-Server --> Provisioner: certificates
-Provisioner -> Keystore: certificates
-Keystore -> Keystore: Store certificates
-
-The actors in the above diagram are:
-
-* **Server** is the backend certificate provisioning server. It has access to
- the uploaded device public keys and is responsible for providing encryption
- keys, decrypting and validating requests, and generating certificates in
- response to requests.
-* **Provisioner** is an application that is responsible for communicating with
- the server and all of the system components that require key certificates
- from the server. It also implements the policy that defines how many key
- pairs each client should keep in their pool.
-* **Keystore** is the [Android keystore
- daemon](https://developer.android.com/training/articles/keystore) (or, more
- generally, whatever system component manages communications with a
- particular secure aread component).
-* **KeyMint** is the secure area component that manages cryptographic keys and
- performs attestations (or perhaps some other secure area component).
-
-### `BCC`
-
-The _Boot Certificate Chain_ (BCC) is the chain of certificates that contains
-DK\_pub as well as other often device-unique certificates. The BCC is
-represented as a COSE\_Key containing DK\_pub followed by an array of
-COSE\_Sign1 "certificates" containing public keys and optional additional
-information, ordered from root to leaf, with each certificate signing the next.
-The first certificate in the array is signed by DK\_pub, the last certificate
-has the KeyMint (or whatever) signing key's public key, KM\_pub. In phase 1
-there is only one entry; DK\_pub and KM\_pub are the same key and the
-certificate is self-signed.
-
-Each COSE\_Sign1 certificate is a CBOR Web Token (CWT) as described in [RFC
-8392](https://tools.ietf.org/html/rfc8392) with additional fields as described
-in the Open Profile for DICE. Of these additional fields, only the
-_subjectPublicKey_ and _keyUsage_ fields are expected to be present for the
-KM\_pub entry (that is, the last entry) in a BCC, but all fields required by the
-Open Profile for DICE are expected for other entries (each of which corresponds
-to a particular firmware component or boot stage). The CWT fields _iss_ and
-_sub_ identify the issuer and subject of the certificate and are consistent
-along the BCC entries; the issuer of a given entry matches the subject of the
-previous entry.
-
-The BCC is designed to be constructed using the Open Profile for DICE. In this
-case the DK key pair is derived from the UDS as described by that profile and
-all BCC entries before the leaf are CBOR CDI certificates chained from DK\_pub.
-The KM key pair is not part of the derived DICE chain. It is generated (not
-derived) by the KeyMint module, certified by the last key in the DICE chain, and
-added as the leaf BCC entry. The key usage field in this leaf certificate must
-indicate the key is not used to sign certificates. If a UDS certificate is
-available on the device it should appear in the certificate request as the leaf
-of a DKCertChain in AdditionalDKSignatures (see
-[CertificateRequest](#certificaterequest)).
-
-The Open Profile for DICE allows for an arbitrary configuration descriptor. For
-BCC entries, this configuration descriptor is a CBOR map with the following
-optional fields. If no fields are relevant, an empty map should be encoded.
-Additional implementation-specific fields may be added using key values not in
-the range \[-70000, -70999\] (these are reserved for future additions here).
-
-```
-| Name | Key | Value type | Meaning |
-| ----------------- | ------ | ---------- | ----------------------------------|
-| Component name | -70002 | tstr | Name of firmware component / boot |
-: : : : stage :
-| Component version | -70003 | int | Version of firmware component / |
-: : : : boot stage :
-| Resettable | -70004 | null | If present, key changes on factory|
-: : : : reset :
-```
-
-Please see
-[ProtectedData.aidl](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl)
-for a full CDDL definition of the BCC.
-
-### `CertificateRequest`
-
-The full CBOR message that will be sent to the server to request certificates
-is:
-
-```cddl
-CertificateRequest = [
- DeviceInfo,
- challenge : bstr, // Provided by the server
- ProtectedData, // See ProtectedData.aidl
- MacedKeysToSign // See IRemotelyProvisionedComponent.aidl
-]
-
-DeviceInfo = [
- VerifiedDeviceInfo, // See DeviceInfo.aidl
- UnverifiedDeviceInfo
-]
-
-// Unverified info is anything provided by the HLOS. Subject to change out of
-// step with the HAL.
-UnverifiedDeviceInfo = {
- ? "fingerprint" : tstr,
-}
-
-```
-
-It will be the responsibility of Keystore and the Provisioner to construct the
-`CertificateRequest`. The HAL provides a method to generate the elements that
-need to be constructed on the secure side, which are the tag field of
-`MacedKeysToSign`, `VerifiedDeviceInfo`, and the ciphertext field of
-`ProtectedData`.
-
-### HAL
-
-The remote provisioning HAL provides a simple interface that can be implemented
-by multiple secure components that require remote provisioning. It would be
-slightly simpler to extend the KeyMint API, but that approach would only serve
-the needs of KeyMint, this is more general.
-
-NOTE the data structures defined in this HAL may look a little bloated and
-complex. This is because the COSE data structures are fully spelled-out; we
-could make it much more compact by not re-specifying the standardized elements
-and instead just referencing the standard, but it seems better to fully specify
-them. If the apparent complexity seems daunting, consider what the same would
-look like if traditional ASN.1 DER-based structures from X.509 and related
-standards were used and also fully elaborated.
-
-Please see the related HAL documentation directly in the source code at the
-following links:
-
-* [IRemotelyProvisionedComponent
- HAL](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl)
-* [ProtectedData](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl)
-* [MacedPublicKey](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl)
-* [RpcHardwareInfo](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl)
-* [DeviceInfo](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl)
-
diff --git a/security/keymint/TEST_MAPPING b/security/keymint/TEST_MAPPING
new file mode 100644
index 0000000..4ab60b6
--- /dev/null
+++ b/security/keymint/TEST_MAPPING
@@ -0,0 +1,10 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsAidlKeyMintTargetTest"
+ },
+ {
+ "name": "VtsHalRemotelyProvisionedComponentTargetTest"
+ }
+ ]
+}
diff --git a/security/keymint/aidl/Android.bp b/security/keymint/aidl/Android.bp
index 96d44a7..5a76a21 100644
--- a/security/keymint/aidl/Android.bp
+++ b/security/keymint/aidl/Android.bp
@@ -17,6 +17,7 @@
"android.hardware.security.secureclock-V1",
],
stability: "vintf",
+ frozen: false,
backend: {
java: {
platform_apis: true,
@@ -52,21 +53,21 @@
cc_defaults {
name: "keymint_use_latest_hal_aidl_ndk_static",
static_libs: [
- "android.hardware.security.keymint-V2-ndk",
+ "android.hardware.security.keymint-V3-ndk",
],
}
cc_defaults {
name: "keymint_use_latest_hal_aidl_ndk_shared",
shared_libs: [
- "android.hardware.security.keymint-V2-ndk",
+ "android.hardware.security.keymint-V3-ndk",
],
}
cc_defaults {
name: "keymint_use_latest_hal_aidl_cpp_static",
static_libs: [
- "android.hardware.security.keymint-V2-cpp",
+ "android.hardware.security.keymint-V3-cpp",
],
}
@@ -76,6 +77,6 @@
rust_defaults {
name: "keymint_use_latest_hal_aidl_rust",
rustlibs: [
- "android.hardware.security.keymint-V2-rust",
+ "android.hardware.security.keymint-V3-rust",
],
}
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/.hash b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/.hash
index b712a52..3a6d415 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/.hash
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/.hash
@@ -1 +1,2 @@
976674616001f714f4a4df49ee45f548de828524
+cd862ae2e49b54fc965dc1b99c218eb729c93bb1
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/.hash b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/.hash
index 69ba9a6..b4c2b78 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/.hash
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/.hash
@@ -1 +1,2 @@
207c9f218b9b9e4e74ff5232eb16511eca9d7d2e
+70c734fbd5cac5b36676d66d8d9aa941967e1e7b
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
deleted file mode 100644
index 5ff45f8..0000000
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
+++ /dev/null
@@ -1,45 +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.
- */
-///////////////////////////////////////////////////////////////////////////////
-// 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.keymint;
-/* @hide */
-@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
-parcelable RpcHardwareInfo {
- 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/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
index e310b44..6ae2369 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/Tag.aidl
@@ -90,6 +90,7 @@
DEVICE_UNIQUE_ATTESTATION = 1879048912,
IDENTITY_CREDENTIAL_KEY = 1879048913,
STORAGE_KEY = 1879048914,
+ ATTESTATION_ID_SECOND_IMEI = -1879047469,
ASSOCIATED_DATA = -1879047192,
NONCE = -1879047191,
MAC_LENGTH = 805307371,
diff --git a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
deleted file mode 100644
index 6954d65..0000000
--- a/security/keymint/aidl/android/hardware/security/keymint/DeviceInfo.aidl
+++ /dev/null
@@ -1,56 +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.security.keymint;
-
-/**
- * DeviceInfo contains information about the device that's fed in as AAD in the signature of the
- * device private key over the MAC key used for the bundle of public keys. These values are intended
- * to be checked by the server to verify that the certificate signing request crafted by
- * an IRemotelyProvisionedComponent HAL instance is coming from the expected device based
- * on values initially uploaded during device manufacture in the factory.
- * @hide
- */
-@VintfStability
-parcelable DeviceInfo {
- /**
- * 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,
- * "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
- * "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.
- * "cert_type": "widevine" / "keymint"
- * }
- */
- byte[] deviceInfo;
-}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index 926d105..2e4fc15 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -624,9 +624,15 @@
*
* o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
*
- * o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be less than
- * the current secure timestamp (which is a monotonic timer counting milliseconds since
- * boot.)
+ * o If the device has a source of secure time, then the timestamp in the auth token plus the
+ * value of the Tag::AUTH_TIMEOUT must be greater than the current secure timestamp (which
+ * is a monotonic timer counting milliseconds since boot).
+ *
+ * o If the device does not have a source of secure time, then the timestamp check should be
+ * performed on the first update(), updateAad() or finish() invocation for the operation,
+ * using the timeStampToken parameter provided on the invocation to indicate the current
+ * timestamp. It may optionally also be performed on subsequent update() / updateAad() /
+ * finish() invocations.
*
* If any of these conditions are not met, begin() must return
* ErrorCode::KEY_USER_NOT_AUTHENTICATED.
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
index c30c183..82c8a0d 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintOperation.aidl
@@ -40,31 +40,7 @@
*
* == Authorization Enforcement ==
*
- * Key authorization enforcement is performed primarily in begin(). The one exception is the
- * case where the key has:
- *
- * o One or more Tag::USER_SECURE_IDs, and
- *
- * o Does not have a Tag::AUTH_TIMEOUT
- *
- * In this case, the key requires an authorization per operation, and the update method must
- * receive a non-null and valid HardwareAuthToken. For the auth token to be valid, all of the
- * following has to be true:
- *
- * o The HMAC field must validate correctly.
- *
- * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
- * the secure ID values in the token.
- *
- * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
- *
- * o The challenge field in the auth token must contain the value returned from
- * IKeyMintDevice::begin(), given by the challenge field of the BeginResult structure.
- *
- * If any of these conditions are not met, updateAad() must return
- * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
- *
- * The caller must provide the auth token on every call to updateAad(), update() and finish().
+ * See the Authorization Enforcement section for the update() method.
*
*
* For GCM encryption, the AEAD tag must be appended to the ciphertext by finish(). During
@@ -104,16 +80,22 @@
*
* == Authorization Enforcement ==
*
- * Key authorization enforcement is performed primarily in IKeyMintDevice::begin(). The one
- * exception is the case where the key has:
+ * Key authorization enforcement is performed primarily in IKeyMintDevice::begin(). There are
+ * two exceptions to this:
*
- * o One or more Tag::USER_SECURE_IDs, and
+ * 1) Key with USER_SECURE_IDs but no AUTH_TIMEOUT
*
- * o Does not have a Tag::AUTH_TIMEOUT
+ * 2) Key with USER_SECURE_IDs and AUTH_TIMEOUT, but the device does not support secure time.
*
- * In this case, the key requires an authorization per operation, and the update method must
- * receive a non-empty and valid HardwareAuthToken. For the auth token to be valid, all of the
- * following has to be true:
+ * The first exception is the case where the key:
+ *
+ * o Has one or more Tag::USER_SECURE_IDs, and
+ *
+ * o Does not have a Tag::AUTH_TIMEOUT
+ *
+ * In this case, the key requires an authorization per operation, and update() / updateAad() /
+ * finish() methods must receive a non-null and valid HardwareAuthToken. For the auth token to
+ * be valid, all of the following has to be true:
*
* o The HMAC field must validate correctly.
*
@@ -125,10 +107,47 @@
* o The challenge field in the auth token must contain the challenge value contained in the
* BeginResult returned from IKeyMintDevice::begin().
*
- * If any of these conditions are not met, update() must return
+ * If any of these conditions are not met, the method must return
* ErrorCode::KEY_USER_NOT_AUTHENTICATED.
*
- * The caller must provide the auth token on every call to update() and finish().
+ * The caller must provide the auth token on every call to update(), updateAad() and finish().
+ *
+ *
+ * The second exception is the case where the key:
+ *
+ * o Has one or more Tag::USER_SECURE_IDs, and
+ *
+ * o Has a Tag::AUTH_TIMEOUT value, but the device does not have a source of secure time (as
+ * indicated by the KeyMintHardwareInfo.timestampTokenRequired field).
+ *
+ * In this case, the key requires an per-operation authorization on the first call to update(),
+ * updateAad() or finish() for the operation, using the provided timeStampToken as a source of
+ * secure time. For this timeStampToken to be valid, all of the following has to be true:
+ *
+ * o The HMAC field must validate correctly.
+ *
+ * o The challenge field in the auth token must contain the challenge value contained in the
+ * BeginResult returned from IKeyMintDevice::begin().
+ *
+ * The resulting secure time value is then used to authenticate the HardwareAuthToken. For the
+ * auth token to be valid, all of the following has to be true:
+ *
+ * o The HMAC field must validate correctly.
+ *
+ * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
+ * the secure ID values in the token.
+ *
+ * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
+ *
+ * o The challenge field in the auth token must contain the challenge value contained in the
+ * BeginResult returned from IKeyMintDevice::begin().
+ *
+ * o The timestamp in the auth token plus the value of the Tag::AUTH_TIMEOUT must be greater
+ * than the provided secure timestamp.
+
+ * If any of these conditions are not met, the method must return
+ * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
+ *
*
* -- RSA keys --
*
@@ -187,24 +206,7 @@
* Key authorization enforcement is performed primarily in begin(). The exceptions are
* authorization per operation keys and confirmation-required keys.
*
- * Authorization per operation keys are the case where the key has one or more
- * Tag::USER_SECURE_IDs, and does not have a Tag::AUTH_TIMEOUT. In this case, the key requires
- * an authorization per operation, and the finish method must receive a non-empty and valid
- * authToken. For the auth token to be valid, all of the following has to be true:
- *
- * o The HMAC field must validate correctly.
- *
- * o At least one of the Tag::USER_SECURE_ID values from the key must match at least one of
- * the secure ID values in the token.
- *
- * o The key must have a Tag::USER_AUTH_TYPE that matches the auth type in the token.
- *
- * o The challenge field in the auth token must contain the operation challenge.
- *
- * If any of these conditions are not met, update() must return
- * ErrorCode::KEY_USER_NOT_AUTHENTICATED.
- *
- * The caller must provide the auth token on every call to update() and finish().
+ * Authorization per operation keys must be authorized as described for the update() method.
*
* Confirmation-required keys are keys that were generated with
* Tag::TRUSTED_CONFIRMATION_REQUIRED. For these keys, when doing a signing operation the
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
deleted file mode 100644
index c2acbed..0000000
--- a/security/keymint/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
+++ /dev/null
@@ -1,464 +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 android.hardware.security.keymint;
-
-import android.hardware.security.keymint.DeviceInfo;
-import android.hardware.security.keymint.MacedPublicKey;
-import android.hardware.security.keymint.ProtectedData;
-import android.hardware.security.keymint.RpcHardwareInfo;
-
-/**
- * An IRemotelyProvisionedComponent is a secure-side component for which certificates can be
- * remotely provisioned. It provides an interface for generating asymmetric key pairs and then
- * creating a CertificateRequest that contains the generated public keys, plus other information to
- * authenticate the request origin. The CertificateRequest can be sent to a server, which can
- * validate the request and create certificates.
- *
- * This interface does not provide any way to use the generated and certified key pairs. It's
- * intended to be implemented by a HAL service that does other things with keys (e.g. Keymint).
- *
- * The root of trust for secure provisioning is something called the Device Identifier Composition
- * Engine (DICE) Chain. The DICE Chain is a chain of certificates, represented as COSE_Sign1 objects
- * containing CBOR Web Tokens (CWT) which have descriptions about the stage of firmware being
- * signed, including a COSE_Key representation of that stage's public key.
- *
- * DICE Chain Design
- * =================
- *
- * For a more exhaustive and thorough look at DICE and the implementation used within this protocol,
- * please see: https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md
- *
- * The DICE Chain is designed to mirror the boot stages of a device, and to prove the content and
- * integrity of each firmware image. In a proper DICE Chain, each boot stage hashes its own private
- * key material with the code and any relevant configuration parameters of the next stage to produce
- * a Compound Device Identifier, or CDI, which is used as the secret key material for the next
- * stage. From the CDI, a key pair - CDI_*_Pub and CDI_*_Priv - is derived and certified for the
- * next stage by the current stages CDI_*_Priv. The next stage is then loaded and given its CDI and
- * the DICE certificate chain generated so far in a manner that does not leak the previous stage's
- * CDI_*_Priv or CDI to later boot stages. The final, "leaf" CDI certificate contains a public key,
- * denoted CDI_Leaf_Pub, whose corresponding private key, denoted CDI_Leaf_Priv, is available for
- * use by the IRemotelyProvisionedComponent.
- *
- * The root keypair is generated by immutable code (e.g. ROM), from a Unique Device Secret (UDS).
- * The keypair that is generated from it can be referred to as the UDS_Pub/UDS_Priv keys. After the
- * device-unique secret is used, it must be made unavailable to any later boot stage.
- *
- * In this way, booting the device incrementally builds a certificate chain that (a) identifies and
- * validates the integrity of every stage and (b) contains a set of public keys that correspond to
- * private keys, one known to each stage. Any stage can compute the secrets of all later stages
- * (given the necessary input), but no stage can compute the secret of any preceding stage. Updating
- * the firmware or configuration of any stage changes the key pair of that stage, and of all
- * subsequent stages, and no attacker who compromised the previous version of the updated firmware
- * can know or predict the post-update key pairs. It is recommended and expected that the DICE Chain
- * is constructed using the Open Profile for DICE.
- *
- * When the provisioning server receives a message signed by CDI_Leaf_Priv and containing a DICE
- * chain that chains from UDS_Pub to CDI_Leaf_Pub, it can be certain that (barring vulnerabilities
- * in some boot stage), the CertificateRequest came from the device associated with UDS_Pub, running
- * the specific software identified by the certificates in the chain. If the server has some
- * mechanism for knowing the hash values of compromised stages, it can determine whether signing
- * certificates is appropriate.
- *
- * Degenerate DICE Chains
- * ======================
- *
- * While a proper DICE Chain, as described above, reflects the complete boot sequence from boot ROM
- * to the secure area image of the IRemotelyProvisionedComponent, it's also possible to use a
- * "degenerate" DICE Chain which consists only of a single, self-signed certificate containing the
- * public key of a hardware-bound key pair. This is an appopriate solution for devices which haven't
- * implemented everything necessary to produce a proper DICE Chain, but can derive a unique key pair
- * in the secure area. In this degenerate case, UDS_Pub is the same as CDI_Leaf_Pub.
- *
- * DICE Chain Privacy
- * ==================
- *
- * Because the DICE Chain constitutes an unspoofable, device-unique identifier, special care is
- * taken to prevent its availability to entities who may wish to track devices. Three precautions
- * are taken:
- *
- * 1) The DICE chain is only handled by the native Remote Key Provisioning Daemon (RKPD) service on
- * the HLOS and is not exposed to apps running on device.
- *
- * 2) The CDI_Leaf_Priv key cannot be used to sign arbitrary data.
- *
- * 3) Backend infrastructure does not correlate UDS_Pub with the certificates signed and sent back
- * to the device.
- *
- * Versioning
- * ==========
- * Versions 1 and 2 of the schema, as previously defined in DeviceInfo.aidl, diverge in
- * functionality from Version 3. Version 3 removes the need to have testMode in function calls and
- * deprecates the Endpoint Encryption Key (EEK) as well. Vendors implementing Version 1
- * (Android S/12) or Version 2 (Android T/13) do not need to implement generateCertificateRequestV2.
- * Vendors implementing Version 3 (Android U/14) need to implement generateCertificateRequestV2.
- *
- * For better coverage of changes from version to version, please see RKP_CHANGELOG.md in the root
- * of the keymint interface directory.
- *
- * @hide
- */
-@VintfStability
-interface IRemotelyProvisionedComponent {
- const int STATUS_FAILED = 1;
- const int STATUS_INVALID_MAC = 2;
- // --------- START: Versions 1 and 2 Only ----------
- const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3;
- const int STATUS_TEST_KEY_IN_PRODUCTION_REQUEST = 4;
- const int STATUS_INVALID_EEK = 5;
- // --------- END: Versions 1 and 2 Only ------------
- const int STATUS_REMOVED = 6;
-
- /**
- * @return info which contains information about the underlying IRemotelyProvisionedComponent
- * hardware, such as version number, component name, author name, and supported curve.
- */
- RpcHardwareInfo getHardwareInfo();
-
- /**
- * generateKeyPair generates a new ECDSA P-256 key pair that can be attested by the remote
- * server.
- *
- * @param in boolean testMode this field is now deprecated. It is ignored by the implementation
- * in v3, but retained to simplify backwards compatibility support. V1 and V2
- * implementations must still respect the testMode flag.
- *
- * testMode indicates whether the generated key is for testing only. Test keys
- * are marked (see the definition of PublicKey in the MacedPublicKey structure) to
- * prevent them from being confused with production keys.
- *
- * @param out MacedPublicKey macedPublicKey contains the public key of the generated key pair,
- * MACed so that generateCertificateRequest can easily verify, without the
- * privateKeyHandle, that the contained public key is for remote certification.
- *
- * @return data representing a handle to the private key. The format is implementation-defined,
- * but note that specific services may define a required format. KeyMint does.
- */
- byte[] generateEcdsaP256KeyPair(in boolean testMode, out MacedPublicKey macedPublicKey);
-
- /**
- * This method has been removed in version 3 of the HAL. The header is kept around for
- * backwards compatibility purposes. Calling this method should return STATUS_REMOVED on v3.
- *
- * For v1 and v2 implementations:
- * generateCertificateRequest creates a certificate request to be sent to the provisioning
- * server.
- *
- * @param in boolean testMode indicates whether the generated certificate request is for testing
- * only.
- *
- * @param in MacedPublicKey[] keysToSign contains the set of keys to certify. The
- * IRemotelyProvisionedComponent must validate the MACs on each key. If any entry in the
- * array lacks a valid MAC, the method must return STATUS_INVALID_MAC.
- *
- * If testMode is true, the keysToCertify array must contain only keys flagged as test
- * keys. Otherwise, the method must return STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
- *
- * If testMode is false, the keysToCertify array must not contain any keys flagged as
- * test keys. Otherwise, the method must return STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
- *
- * @param in endpointEncryptionKey contains an X22519 public key which will be used to encrypt
- * the BCC. For flexibility, this is represented as a certificate chain, represented as a
- * CBOR array of COSE_Sign1 objects, ordered from root to leaf. The leaf contains the
- * X25519 encryption key, each other element is an Ed25519 key signing the next in the
- * chain. The root is self-signed. An implementor may also choose to use P256 as an
- * alternative curve for signing and encryption instead of Curve 25519.
- *
- * EekChain = [ + SignedSignatureKey, SignedEek ]
- *
- * SignedSignatureKey = [ ; COSE_Sign1
- * protected: bstr .cbor {
- * 1 : AlgorithmEdDSA / AlgorithmES256, ; Algorithm
- * },
- * unprotected: {},
- * payload: bstr .cbor SignatureKeyEd25519 /
- * bstr .cbor SignatureKeyP256,
- * signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) /
- * bstr ECDSA(.cbor SignatureKeySignatureInput)
- * ]
- *
- * SignatureKeyEd25519 = { ; COSE_Key
- * 1 : 1, ; Key type : Octet Key Pair
- * 3 : AlgorithmEdDSA, ; Algorithm
- * -1 : 6, ; Curve : Ed25519
- * -2 : bstr ; Ed25519 public key
- * }
- *
- * SignatureKeyP256 = {
- * 1 : 2, ; Key type : EC2
- * 3 : AlgorithmES256, ; Algorithm
- * -1 : 1, ; Curve: P256
- * -2 : bstr, ; X coordinate
- * -3 : bstr ; Y coordinate
- * }
- *
- * SignatureKeySignatureInput = [
- * context: "Signature1",
- * body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * external_aad: bstr .size 0,
- * payload: bstr .cbor SignatureKeyEd25519 /
- * bstr .cbor SignatureKeyP256
- * ]
- *
- * ; COSE_Sign1
- * SignedEek = [
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * unprotected: {},
- * payload: bstr .cbor EekX25519 / .cbor EekP256,
- * signature: bstr PureEd25519(.cbor EekSignatureInput) /
- * bstr ECDSA(.cbor EekSignatureInput)
- * ]
- *
- * EekX25519 = { ; COSE_Key
- * 1 : 1, ; Key type : Octet Key Pair
- * 2 : bstr ; KID : EEK ID
- * 3 : -25, ; Algorithm : ECDH-ES + HKDF-256
- * -1 : 4, ; Curve : X25519
- * -2 : bstr ; Ed25519 public key
- * }
- *
- * EekP256 = { ; COSE_Key
- * 1 : 2, ; Key type : EC2
- * 2 : bstr ; KID : EEK ID
- * 3 : -25, ; Algorithm : ECDH-ES + HKDF-256
- * -1 : 1, ; Curve : P256
- * -2 : bstr ; Sender X coordinate
- * -3 : bstr ; Sender Y coordinate
- * }
- *
- * EekSignatureInput = [
- * context: "Signature1",
- * body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * external_aad: bstr .size 0,
- * payload: bstr .cbor EekX25519 / .cbor EekP256
- * ]
- *
- * AlgorithmES256 = -7
- * AlgorithmEdDSA = -8
- *
- * If the contents of endpointEncryptionKey do not match the SignedEek structure above,
- * the method must return STATUS_INVALID_EEK.
- *
- * If testMode is true, the method must ignore the length and content of the signatures
- * in the chain, which implies that it must not attempt to validate the signature.
- *
- * If testMode is false, the method must validate the chain signatures, and must verify
- * that the public key in the root certifictate is in its pre-configured set of
- * authorized EEK root keys. If the public key is not in the database, or if signature
- * verification fails, the method must return STATUS_INVALID_EEK.
- *
- * @param in challenge contains a byte string from the provisioning server that must be signed
- * by the secure area. See the description of the 'signature' output parameter for
- * details.
- *
- * @param out DeviceInfo contains the VerifiedDeviceInfo portion of the DeviceInfo array in
- * CertificateRequest. The structure is described within the DeviceInfo.aidl file.
- *
- * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
- * authenticate the keysToSign (see keysToSignMac output argument).
- *
- * @return The of KeysToSign in the CertificateRequest structure. Specifically, it contains:
- *
- * HMAC-256(EK_mac, .cbor KeysToMacStructure)
- *
- * Where EK_mac is an ephemeral MAC key, found in ProtectedData (see below). The MACed
- * data is the "tag" field of a COSE_Mac0 structure like:
- *
- * MacedKeys = [ ; COSE_Mac0
- * protected : bstr .cbor {
- * 1 : 5, ; Algorithm : HMAC-256
- * },
- * unprotected : {},
- * ; Payload is PublicKeys from keysToSign argument, in provided order.
- * payload: bstr .cbor [ * PublicKey ],
- * tag: bstr
- * ]
- *
- * KeysToMacStructure = [
- * context : "MAC0",
- * protected : bstr .cbor { 1 : 5 }, ; Algorithm : HMAC-256
- * external_aad : bstr .size 0,
- * ; Payload is PublicKeys from keysToSign argument, in provided order.
- * payload : bstr .cbor [ * PublicKey ]
- * ]
- */
- byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
- in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
- out ProtectedData protectedData);
-
- /**
- * generateCertificateRequestV2 creates a certificate signing request to be sent to the
- * provisioning server.
- *
- * @param in MacedPublicKey[] keysToSign contains the set of keys to certify. The
- * IRemotelyProvisionedComponent must validate the MACs on each key. If any entry in the
- * array lacks a valid MAC, the method must return STATUS_INVALID_MAC.
- *
- * @param in challenge contains a byte string from the provisioning server which will be
- * included in the signed data of the CSR structure. Different provisioned backends may
- * use different semantic data for this field, but the supported sizes must be between 32
- * and 64 bytes, inclusive.
- *
- * @return the following CBOR Certificate Signing Request (Csr) serialized into a byte array:
- *
- * Csr = [
- * version: 3, ; The CDDL Schema version.
- * UdsCerts,
- * DiceCertChain,
- * SignedData
- * ]
- *
- * ; COSE_Sign1 (untagged)
- * SignedData = [
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * unprotected: {},
- * payload: bstr .cbor SignedDataPayload,
- * signature: bstr ; PureEd25519(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct) /
- * ; ECDSA(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct)
- * ]
- *
- * ; Sig_structure for SignedData
- * SignedDataSigStruct = [
- * context: "Signature1",
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * external_aad: bstr .size 0,
- * payload: bstr .cbor SignedDataPayload
- * ]
- *
- * SignedDataPayload = [ ; CBOR Array defining the payload for SignedData
- * DeviceInfo, ; Defined in DeviceInfo.aidl
- * challenge: bstr .size (32..64), ; Provided by the method parameters
- * KeysToSign, ; Provided by the method parameters
- * ]
- *
- * KeysToSign = [ * PublicKey ] ; Please see MacedPublicKey.aidl for the PublicKey definition.
- *
- * ; UdsCerts allows the platform to provide additional certifications for the UDS_Pub. For
- * ; example, this could be provided by the hardware vendor, who certifies all of their chips.
- * ; The SignerName is a free-form string describing who generated the signature. The root
- * ; certificate will need to be communicated to the verifier out of band, along with the
- * ; SignerName that is expected for the given root certificate.
- * UdsCerts = {
- * * SignerName => UdsCertChain
- * }
- *
- * ; SignerName is a string identifier that indicates both the signing authority as
- * ; well as the format of the UdsCertChain
- * SignerName = tstr
- *
- * UdsCertChain = [
- * 2* X509Certificate ; Root -> ... -> Leaf. "Root" is the vendor self-signed
- * ; cert, "Leaf" contains UDS_Public. There may also be
- * ; intermediate certificates between Root and Leaf.
- * ]
- *
- * ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or edDSA)
- * X509Certificate = bstr
- *
- * ; The DICE Chain contains measurements about the device firmware.
- * ; The first entry in the DICE Chain is the UDS_Pub, encoded as a COSE_key. All entries
- * ; after the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN)
- * ; Note that there is no DiceChainEntry for UDS_pub, only a "bare" COSE_key.
- * DiceCertChain = [
- * PubKeyEd25519 / PubKeyECDSA256, ; UDS_Pub
- * + DiceChainEntry, ; First CDI_Certificate -> Last CDI_Certificate
- * ; Last certificate corresponds to KeyMint's DICE key.
- * ]
- *
- * ; This is the signed payload for each entry in the DCC. Note that the "Configuration
- * ; Input Values" described by the Open Profile are not used here. Instead, the Dcc
- * ; defines its own configuration values for the Configuration Descriptor field. See
- * ; the Open Profile for DICE for more details on the fields. SHA256 and SHA512 are acceptable
- * ; hash algorithms. The digest bstr values in the payload are the digest values without any
- * ; padding. Note that for SHA256, this implies the digest bstr is 32 bytes. This is an
- * ; intentional, minor deviation from Open Profile for DICE, which specifies all digests are
- * ; 64 bytes.
- * DiceChainEntryPayload = { ; CWT [RFC8392]
- * 1 : tstr, ; Issuer
- * 2 : tstr, ; Subject
- * -4670552 : bstr .cbor PubKeyEd25519 /
- * bstr .cbor PubKeyECDSA256, ; Subject Public Key
- * -4670553 : bstr ; Key Usage
- *
- * ; NOTE: All of the following fields may be omitted for a "Degenerate DICE Chain", as
- * ; described above.
- * -4670545 : bstr, ; Code Hash
- * ? -4670546 : bstr, ; Code Descriptor
- * ? -4670547 : bstr, ; Configuration Hash
- * -4670548 : bstr .cbor { ; Configuration Descriptor
- * ? -70002 : tstr, ; Component name
- * ? -70003 : int, ; Firmware version
- * ? -70004 : null, ; Resettable
- * },
- * -4670549 : bstr, ; Authority Hash
- * ? -4670550 : bstr, ; Authority Descriptor
- * -4670551 : bstr, ; Mode
- * }
- *
- * ; Each entry in the Dcc is a DiceChainEntryPayload signed by the key from the previous entry
- * ; in the Dcc array.
- * DiceChainEntry = [ ; COSE_Sign1 (untagged)
- * protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * unprotected: {},
- * payload: bstr .cbor DiceChainEntryPayload,
- * signature: bstr ; PureEd25519(SigningKey, bstr .cbor DiceChainEntryInput) /
- * ; ECDSA(SigningKey, bstr .cbor DiceChainEntryInput)
- * ; See RFC 8032 for details of how to encode the signature value
- * ; for Ed25519.
- * ]
- *
- * DiceChainEntryInput = [
- * context: "Signature1",
- * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
- * external_aad: bstr .size 0,
- * payload: bstr .cbor DiceChainEntryPayload
- * ]
- *
- * ; The following section defines some types that are reused throughout the above
- * ; data structures.
- * PubKeyX25519 = { ; COSE_Key
- * 1 : 1, ; Key type : Octet Key Pair
- * -1 : 4, ; Curve : X25519
- * -2 : bstr ; Sender X25519 public key
- * }
- *
- * PubKeyEd25519 = { ; COSE_Key
- * 1 : 1, ; Key type : octet key pair
- * 3 : AlgorithmEdDSA, ; Algorithm : EdDSA
- * -1 : 6, ; Curve : Ed25519
- * -2 : bstr ; X coordinate, little-endian
- * }
- *
- * PubKeyEcdhP256 = { ; COSE_Key
- * 1 : 2, ; Key type : EC2
- * -1 : 1, ; Curve : P256
- * -2 : bstr ; Sender X coordinate
- * -3 : bstr ; Sender Y coordinate
- * }
- *
- * PubKeyECDSA256 = { ; COSE_Key
- * 1 : 2, ; Key type : EC2
- * 3 : AlgorithmES256, ; Algorithm : ECDSA w/ SHA-256
- * -1 : 1, ; Curve: P256
- * -2 : bstr, ; X coordinate
- * -3 : bstr ; Y coordinate
- * }
- *
- * AlgorithmES256 = -7
- * AlgorithmEdDSA = -8
- */
- byte[] generateCertificateRequestV2(in MacedPublicKey[] keysToSign, in byte[] challenge);
-}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
index 4c2be89..294c205 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/KeyCreationResult.aidl
@@ -125,9 +125,9 @@
* straightforward translation of the KeyMint tag/value parameter lists to ASN.1.
*
* KeyDescription ::= SEQUENCE {
- * attestationVersion INTEGER, # Value 200
+ * attestationVersion INTEGER, # Value 300
* attestationSecurityLevel SecurityLevel, # See below
- * keyMintVersion INTEGER, # Value 200
+ * keyMintVersion INTEGER, # Value 300
* keymintSecurityLevel SecurityLevel, # See below
* attestationChallenge OCTET_STRING, # Tag::ATTESTATION_CHALLENGE from attestParams
* uniqueId OCTET_STRING, # Empty unless key has Tag::INCLUDE_UNIQUE_ID
@@ -209,6 +209,7 @@
* vendorPatchLevel [718] EXPLICIT INTEGER OPTIONAL,
* bootPatchLevel [719] EXPLICIT INTEGER OPTIONAL,
* deviceUniqueAttestation [720] EXPLICIT NULL OPTIONAL,
+ * attestationIdSecondImei [723] EXPLICIT OCTET_STRING OPTIONAL,
* }
*/
Certificate[] certificateChain;
diff --git a/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
deleted file mode 100644
index 0cb33ce..0000000
--- a/security/keymint/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
+++ /dev/null
@@ -1,77 +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 android.hardware.security.keymint;
-
-/**
- * RpcHardwareInfo is the hardware information returned by calling RemotelyProvisionedComponent
- * getHardwareInfo()
- * @hide
- */
-@VintfStability
-@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
-parcelable RpcHardwareInfo {
- const int CURVE_NONE = 0;
- const int CURVE_P256 = 1;
- const int CURVE_25519 = 2;
-
- /**
- * Implementation version of the remotely provisioned component hardware. The version number is
- * implementation defined, and not necessarily globally meaningful. The version is used to
- * distinguish between different versions of a given implementation.
- */
- int versionNumber;
-
- /**
- * rpcAuthorName is the name of the author of the IRemotelyProvisionedComponent implementation
- * (organization name, not individual). This name is implementation defined, so it can be used
- * to distinguish between different implementations from the same author.
- */
- @utf8InCpp String rpcAuthorName;
-
- /**
- * supportedEekCurve returns an int representing which curve is supported for validating
- * signatures over the Endpoint Encryption Key certificate chain and for using the corresponding
- * signed encryption key in ECDH. Only one curve should be supported, with preference for 25519
- * if it's available. These values are defined as constants above.
- *
- * CURVE_NONE is made the default to help ensure that an implementor doesn't accidentally forget
- * to provide the correct information here, as the VTS tests will check to make certain that
- * 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, and it must be consistent across all devices.
- * It's critical that this identifier not be usable to uniquely identify a specific 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.
- *
- * A recommended construction for this value is "[Vendor] [Component Name] [Major Version]",
- * e.g. "Google Trusty KeyMint 1".
- *
- * This field was added in API version 2.
- *
- */
- @nullable @utf8InCpp String uniqueId;
-}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
index 47361d5..837fc81 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/Tag.aidl
@@ -726,9 +726,10 @@
ATTESTATION_ID_SERIAL = TagType.BYTES | 713,
/**
- * Tag::ATTESTATION_ID_IMEI provides the IMEIs for all radios on the device to attested key
+ * Tag::ATTESTATION_ID_IMEI provides the IMEI one of the radios on the device to attested key
* generation/import operations. This field must be set only when requesting attestation of the
- * device's identifiers.
+ * device's identifiers. If the device has more than one IMEI, a second IMEI may be included
+ * by using the Tag::ATTESTATION_ID_SECOND_IMEI tag.
*
* If the device does not support ID attestation (or destroyAttestationIds() was previously
* called and the device can no longer attest its IDs), any key attestation request that
@@ -883,6 +884,20 @@
STORAGE_KEY = TagType.BOOL | 722,
/**
+ * Tag::ATTESTATION_ID_SECOND_IMEI provides an additional IMEI of one of the radios on the
+ * device to attested key generation/import operations. This field MUST be accompanied by
+ * the Tag::ATTESTATION_ID_IMEI tag. It would only be used to convery a second IMEI the device
+ * has, after Tag::ATTESTATION_ID_SECOND_IMEI has been used to convery the first IMEI.
+ *
+ * If the device does not support ID attestation (or destroyAttestationIds() was previously
+ * called and the device can no longer attest its IDs), any key attestation request that
+ * includes this tag must fail with ErrorCode::CANNOT_ATTEST_IDS.
+ *
+ * Must never appear in KeyCharacteristics.
+ */
+ ATTESTATION_ID_SECOND_IMEI = TagType.BYTES | 723,
+
+ /**
* OBSOLETE: Do not use.
*
* This tag value is included for historical reasons -- in Keymaster it was used to hold
diff --git a/security/keymint/aidl/default/Android.bp b/security/keymint/aidl/default/Android.bp
index 1a17fd4..17520b7 100644
--- a/security/keymint/aidl/default/Android.bp
+++ b/security/keymint/aidl/default/Android.bp
@@ -25,6 +25,7 @@
"keymint_use_latest_hal_aidl_ndk_shared",
],
shared_libs: [
+ "android.hardware.security.rkp-V3-ndk",
"android.hardware.security.sharedsecret-V1-ndk",
"android.hardware.security.secureclock-V1-ndk",
"libbase",
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index ef5b0bd..13143bf 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -35,6 +35,7 @@
"libcrypto",
],
static_libs: [
+ "android.hardware.security.rkp-V3-ndk",
"android.hardware.security.secureclock-V1-ndk",
"libcppbor_external",
"libcppcose_rkp",
diff --git a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
index ca517ac..ea4ba18 100644
--- a/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
+++ b/security/keymint/aidl/vts/functional/AttestKeyTest.cpp
@@ -798,7 +798,7 @@
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
- add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serialno");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
"ro.product.manufacturer");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
@@ -892,6 +892,7 @@
ASSERT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG)
<< "result = " << result;
+ device_id_attestation_vsr_check(result);
}
CheckedDeleteKey(&attest_key.keyBlob);
}
diff --git a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
index 1dc5df3..26dc3f5 100644
--- a/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
+++ b/security/keymint/aidl/vts/functional/DeviceUniqueAttestationTest.cpp
@@ -252,7 +252,7 @@
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
- add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serialno");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MANUFACTURER,
"ro.product.manufacturer");
add_tag_from_prop(&attestation_id_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
@@ -348,8 +348,8 @@
// Add the tag that doesn't match the local device's real ID.
builder.push_back(invalid_tag);
auto result = GenerateKey(builder, &key_blob, &key_characteristics);
-
ASSERT_TRUE(result == ErrorCode::CANNOT_ATTEST_IDS || result == ErrorCode::INVALID_TAG);
+ device_id_attestation_vsr_check(result);
}
}
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 5473062..43ad30a 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -1919,30 +1919,32 @@
// The following check assumes that canonical CBOR encoding is used for the COSE_Key.
if (testMode) {
- EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
- MatchesRegex("{\n"
- " 1 : 2,\n" // kty: EC2
- " 3 : -7,\n" // alg: ES256
- " -1 : 1,\n" // EC id: P256
- // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
- // sequence of 32 hexadecimal bytes, enclosed in braces and
- // separated by commas. In this case, some Ed25519 public key.
- " -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_x: data
- " -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_y: data
- " -70000 : null,\n" // test marker
- "}"));
+ EXPECT_THAT(
+ cppbor::prettyPrint(parsedPayload.get()),
+ MatchesRegex("\\{\n"
+ " 1 : 2,\n" // kty: EC2
+ " 3 : -7,\n" // alg: ES256
+ " -1 : 1,\n" // EC id: P256
+ // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
+ // sequence of 32 hexadecimal bytes, enclosed in braces and
+ // separated by commas. In this case, some Ed25519 public key.
+ " -2 : \\{(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}\\},\n" // pub_x: data
+ " -3 : \\{(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}\\},\n" // pub_y: data
+ " -70000 : null,\n" // test marker
+ "\\}"));
} else {
- EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()),
- MatchesRegex("{\n"
- " 1 : 2,\n" // kty: EC2
- " 3 : -7,\n" // alg: ES256
- " -1 : 1,\n" // EC id: P256
- // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
- // sequence of 32 hexadecimal bytes, enclosed in braces and
- // separated by commas. In this case, some Ed25519 public key.
- " -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_x: data
- " -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_y: data
- "}"));
+ EXPECT_THAT(
+ cppbor::prettyPrint(parsedPayload.get()),
+ MatchesRegex("\\{\n"
+ " 1 : 2,\n" // kty: EC2
+ " 3 : -7,\n" // alg: ES256
+ " -1 : 1,\n" // EC id: P256
+ // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a
+ // sequence of 32 hexadecimal bytes, enclosed in braces and
+ // separated by commas. In this case, some Ed25519 public key.
+ " -2 : \\{(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}\\},\n" // pub_x: data
+ " -3 : \\{(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}\\},\n" // pub_y: data
+ "\\}"));
}
}
@@ -2029,6 +2031,16 @@
*signingKey = std::move(pubKey);
}
+void device_id_attestation_vsr_check(const ErrorCode& result) {
+ if (get_vsr_api_level() >= 34) {
+ ASSERT_FALSE(result == ErrorCode::INVALID_TAG)
+ << "It is a specification violation for INVALID_TAG to be returned due to ID "
+ << "mismatch in a Device ID Attestation call. INVALID_TAG is only intended to "
+ << "be used for a case where updateAad() is called after update(). As of "
+ << "VSR-14, this is now enforced as an error.";
+ }
+}
+
} // namespace test
} // namespace aidl::android::hardware::security::keymint
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 67e8b21..5b09ca5 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -395,6 +395,7 @@
void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode,
vector<uint8_t>* payload_value);
void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey);
+void device_id_attestation_vsr_check(const ErrorCode& result);
AuthorizationSet HwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
AuthorizationSet SwEnforcedAuthorizations(const vector<KeyCharacteristics>& key_characteristics);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index 4f5d821..b8d0c20 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -1027,6 +1027,15 @@
* without providing NOT_BEFORE and NOT_AFTER parameters.
*/
TEST_P(NewKeyGenerationTest, RsaWithMissingValidity) {
+ if (AidlVersion() < 2) {
+ /*
+ * The KeyMint V1 spec required that CERTIFICATE_NOT_{BEFORE,AFTER} be
+ * specified for asymmetric key generation. However, this was not
+ * checked at the time so we can only be strict about checking this for
+ * implementations of KeyMint version 2 and above.
+ */
+ GTEST_SKIP() << "Validity strict since KeyMint v2";
+ }
// 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;
@@ -1680,6 +1689,15 @@
* without providing NOT_BEFORE and NOT_AFTER parameters.
*/
TEST_P(NewKeyGenerationTest, EcdsaWithMissingValidity) {
+ if (AidlVersion() < 2) {
+ /*
+ * The KeyMint V1 spec required that CERTIFICATE_NOT_{BEFORE,AFTER} be
+ * specified for asymmetric key generation. However, this was not
+ * checked at the time so we can only be strict about checking this for
+ * implementations of KeyMint version 2 and above.
+ */
+ GTEST_SKIP() << "Validity strict since KeyMint v2";
+ }
// 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;
@@ -1990,7 +2008,7 @@
add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_BRAND, "ro.product.brand");
add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_DEVICE, "ro.product.device");
add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_PRODUCT, "ro.product.name");
- add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serial");
+ add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_SERIAL, "ro.serialno");
add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_MANUFACTURER, "ro.product.manufacturer");
add_tag_from_prop(&extra_tags, TAG_ATTESTATION_ID_MODEL, "ro.product.model");
@@ -4946,15 +4964,15 @@
TEST_P(ImportWrappedKeyTest, WrongDigest) {
auto wrapping_key_desc = AuthorizationSetBuilder()
.RsaEncryptionKey(2048, 65537)
- .Digest(Digest::SHA_2_512)
.Padding(PaddingMode::RSA_OAEP)
+ .Digest(Digest::SHA_2_256)
.Authorization(TAG_PURPOSE, KeyPurpose::WRAP_KEY)
.SetDefaultValidity();
ASSERT_EQ(ErrorCode::INCOMPATIBLE_DIGEST,
ImportWrappedKey(wrapped_key, wrapping_key, wrapping_key_desc, zero_masking_key,
AuthorizationSetBuilder()
- .Digest(Digest::SHA_2_256)
+ .Digest(Digest::SHA_2_512)
.Padding(PaddingMode::RSA_OAEP)));
}
diff --git a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
index e1f65fe..97fe08a 100644
--- a/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
+++ b/security/keymint/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp
@@ -46,6 +46,7 @@
namespace {
constexpr int32_t VERSION_WITH_UNIQUE_ID_SUPPORT = 2;
+constexpr int32_t VERSION_WITHOUT_TEST_MODE = 3;
#define INSTANTIATE_REM_PROV_AIDL_TEST(name) \
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(name); \
@@ -180,6 +181,15 @@
return params;
}
+ void checkMacedPubkeyVersioned(const MacedPublicKey& macedPubKey, bool testMode,
+ vector<uint8_t>* payload_value) {
+ if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
+ check_maced_pubkey(macedPubKey, false, payload_value);
+ } else {
+ check_maced_pubkey(macedPubKey, testMode, payload_value);
+ }
+ }
+
protected:
std::shared_ptr<IRemotelyProvisionedComponent> provisionable_;
RpcHardwareInfo rpcHardwareInfo;
@@ -200,9 +210,7 @@
RpcHardwareInfo hwInfo;
ASSERT_TRUE(rpc->getHardwareInfo(&hwInfo).isOk());
- int32_t version;
- ASSERT_TRUE(rpc->getInterfaceVersion(&version).isOk());
- if (version >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
+ if (hwInfo.versionNumber >= VERSION_WITH_UNIQUE_ID_SUPPORT) {
ASSERT_TRUE(hwInfo.uniqueId);
auto [_, wasInserted] = uniqueIds.insert(*hwInfo.uniqueId);
EXPECT_TRUE(wasInserted);
@@ -232,10 +240,7 @@
* 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) {
+ if (rpcHardwareInfo.versionNumber < VERSION_WITH_UNIQUE_ID_SUPPORT) {
return;
}
@@ -246,6 +251,19 @@
EXPECT_LE(hwInfo.uniqueId->size(), 32);
}
+/**
+ * Verify implementation supports at least MIN_SUPPORTED_NUM_KEYS_IN_CSR keys in a CSR.
+ */
+TEST_P(GetHardwareInfoTests, supportedNumKeysInCsr) {
+ if (rpcHardwareInfo.versionNumber < VERSION_WITHOUT_TEST_MODE) {
+ return;
+ }
+
+ RpcHardwareInfo hwInfo;
+ ASSERT_TRUE(provisionable_->getHardwareInfo(&hwInfo).isOk());
+ ASSERT_GE(hwInfo.supportedNumKeysInCsr, RpcHardwareInfo::MIN_SUPPORTED_NUM_KEYS_IN_CSR);
+}
+
using GenerateKeyTests = VtsRemotelyProvisionedComponentTests;
INSTANTIATE_REM_PROV_AIDL_TEST(GenerateKeyTests);
@@ -261,7 +279,7 @@
auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
ASSERT_TRUE(status.isOk());
vector<uint8_t> coseKeyData;
- check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
+ checkMacedPubkeyVersioned(macedPubKey, testMode, &coseKeyData);
}
/**
@@ -284,7 +302,7 @@
auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
ASSERT_TRUE(status.isOk());
vector<uint8_t> coseKeyData;
- check_maced_pubkey(macedPubKey, testMode, &coseKeyData);
+ checkMacedPubkeyVersioned(macedPubKey, testMode, &coseKeyData);
AttestationKey attestKey;
attestKey.keyBlob = std::move(privateKeyBlob);
@@ -339,13 +357,13 @@
bool testMode = true;
auto status = provisionable_->generateEcdsaP256KeyPair(testMode, &macedPubKey, &privateKeyBlob);
ASSERT_TRUE(status.isOk());
-
- check_maced_pubkey(macedPubKey, testMode, nullptr);
+ checkMacedPubkeyVersioned(macedPubKey, testMode, nullptr);
}
-class CertificateRequestTest : public VtsRemotelyProvisionedComponentTests {
+class CertificateRequestTestBase : public VtsRemotelyProvisionedComponentTests {
protected:
- CertificateRequestTest() : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
+ CertificateRequestTestBase()
+ : eekId_(string_to_bytevec("eekid")), challenge_(randomBytes(64)) {}
void generateTestEekChain(size_t eekLength) {
auto chain = generateEekChain(rpcHardwareInfo.supportedEekCurve, eekLength, eekId_);
@@ -364,7 +382,7 @@
ASSERT_TRUE(status.isOk()) << status.getMessage();
vector<uint8_t> payload_value;
- check_maced_pubkey(key, testMode, &payload_value);
+ checkMacedPubkeyVersioned(key, testMode, &payload_value);
cborKeysToSign_.add(cppbor::EncodedItem(payload_value));
}
}
@@ -377,6 +395,18 @@
cppbor::Array cborKeysToSign_;
};
+class CertificateRequestTest : public CertificateRequestTestBase {
+ protected:
+ void SetUp() override {
+ CertificateRequestTestBase::SetUp();
+
+ if (rpcHardwareInfo.versionNumber >= VERSION_WITHOUT_TEST_MODE) {
+ GTEST_SKIP() << "This test case only applies to RKP v1 and v2. "
+ << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
+ }
+ }
+};
+
/**
* Generate an empty certificate request in test mode, and decrypt and verify the structure and
* content.
@@ -643,4 +673,128 @@
INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestTest);
+class CertificateRequestV2Test : public CertificateRequestTestBase {
+ void SetUp() override {
+ CertificateRequestTestBase::SetUp();
+
+ if (rpcHardwareInfo.versionNumber < VERSION_WITHOUT_TEST_MODE) {
+ GTEST_SKIP() << "This test case only applies to RKP v3 and above. "
+ << "RKP version discovered: " << rpcHardwareInfo.versionNumber;
+ }
+ }
+};
+
+/**
+ * Generate an empty certificate request, and decrypt and verify the structure and content.
+ */
+TEST_P(CertificateRequestV2Test, EmptyRequest) {
+ bytevec csr;
+
+ auto status =
+ provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+ auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_);
+ ASSERT_TRUE(result) << result.message();
+}
+
+/**
+ * Generate a non-empty certificate request. Decrypt, parse and validate the contents.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequest) {
+ generateKeys(false /* testMode */, 1 /* numKeys */);
+
+ bytevec csr;
+
+ auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+ auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+ ASSERT_TRUE(result) << result.message();
+}
+
+/**
+ * Generate a non-empty certificate request. Make sure contents are reproducible but allow for the
+ * signature to be different since algorithms including ECDSA P-256 can include a random value.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequestReproducible) {
+ generateKeys(false /* testMode */, 1 /* numKeys */);
+
+ bytevec csr;
+
+ auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+ auto firstCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+ ASSERT_TRUE(firstCsr) << firstCsr.message();
+
+ status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+ auto secondCsr = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+ ASSERT_TRUE(secondCsr) << secondCsr.message();
+
+ ASSERT_EQ(**firstCsr, **secondCsr);
+}
+
+/**
+ * Generate a non-empty certificate request with multiple keys.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequestMultipleKeys) {
+ generateKeys(false /* testMode */, rpcHardwareInfo.supportedNumKeysInCsr /* numKeys */);
+
+ bytevec csr;
+
+ auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+
+ auto result = verifyProductionCsr(cborKeysToSign_, csr, provisionable_.get(), challenge_);
+ ASSERT_TRUE(result) << result.message();
+}
+
+/**
+ * Generate a non-empty certificate request, but with the MAC corrupted on the keypair.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequestCorruptMac) {
+ generateKeys(false /* testMode */, 1 /* numKeys */);
+ auto result = corrupt_maced_key(keysToSign_[0]);
+ ASSERT_TRUE(result) << result.moveMessage();
+ MacedPublicKey keyWithCorruptMac = result.moveValue();
+
+ bytevec csr;
+ auto status =
+ provisionable_->generateCertificateRequestV2({keyWithCorruptMac}, challenge_, &csr);
+ ASSERT_FALSE(status.isOk()) << status.getMessage();
+ EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_INVALID_MAC);
+}
+
+/**
+ * Generate a non-empty certificate request in prod mode, with test keys. Test mode must be
+ * ignored, i.e. test must pass.
+ */
+TEST_P(CertificateRequestV2Test, NonEmptyRequest_testKeyInProdCert) {
+ generateKeys(true /* testMode */, 1 /* numKeys */);
+
+ bytevec csr;
+ auto status = provisionable_->generateCertificateRequestV2(keysToSign_, challenge_, &csr);
+ ASSERT_TRUE(status.isOk()) << status.getMessage();
+}
+
+/**
+ * Call generateCertificateRequest(). Make sure it's removed.
+ */
+TEST_P(CertificateRequestV2Test, CertificateRequestV1Removed) {
+ generateTestEekChain(2);
+ bytevec keysToSignMac;
+ DeviceInfo deviceInfo;
+ ProtectedData protectedData;
+ auto status = provisionable_->generateCertificateRequest(
+ true /* testMode */, {} /* keysToSign */, testEekChain_.chain, challenge_, &deviceInfo,
+ &protectedData, &keysToSignMac);
+ ASSERT_FALSE(status.isOk()) << status.getMessage();
+ EXPECT_EQ(status.getServiceSpecificError(), BnRemotelyProvisionedComponent::STATUS_REMOVED);
+}
+
+INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test);
+
} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp b/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp
index 5bbae4c..0c61c25 100644
--- a/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp
+++ b/security/keymint/aidl/vts/performance/KeyMintBenchmark.cpp
@@ -16,16 +16,21 @@
#define LOG_TAG "keymint_benchmark"
+#include <iostream>
+
#include <base/command_line.h>
#include <benchmark/benchmark.h>
-#include <iostream>
#include <aidl/Vintf.h>
#include <aidl/android/hardware/security/keymint/ErrorCode.h>
#include <aidl/android/hardware/security/keymint/IKeyMintDevice.h>
#include <android/binder_manager.h>
#include <binder/IServiceManager.h>
+
#include <keymint_support/authorization_set.h>
+#include <keymint_support/openssl_utils.h>
+#include <openssl/curve25519.h>
+#include <openssl/x509.h>
#define SMALL_MESSAGE_SIZE 64
#define MEDIUM_MESSAGE_SIZE 1024
@@ -119,6 +124,22 @@
return {};
}
+ string getAlgorithmString(string transform) {
+ if (transform.find("AES") != string::npos) {
+ return "AES";
+ } else if (transform.find("Hmac") != string::npos) {
+ return "HMAC";
+ } else if (transform.find("DESede") != string::npos) {
+ return "TRIPLE_DES";
+ } else if (transform.find("RSA") != string::npos) {
+ return "RSA";
+ } else if (transform.find("EC") != string::npos) {
+ return "EC";
+ }
+ std::cerr << "Can't find algorithm for " << transform << std::endl;
+ return "";
+ }
+
Digest getDigest(string transform) {
if (transform.find("MD5") != string::npos) {
return Digest::MD5;
@@ -135,29 +156,56 @@
return Digest::SHA_2_512;
} else if (transform.find("RSA") != string::npos &&
transform.find("OAEP") != string::npos) {
- return Digest::SHA1;
+ if (securityLevel_ == SecurityLevel::STRONGBOX) {
+ return Digest::SHA_2_256;
+ } else {
+ return Digest::SHA1;
+ }
} else if (transform.find("Hmac") != string::npos) {
return Digest::SHA_2_256;
}
return Digest::NONE;
}
+ string getDigestString(string transform) {
+ if (transform.find("MD5") != string::npos) {
+ return "MD5";
+ } else if (transform.find("SHA1") != string::npos ||
+ transform.find("SHA-1") != string::npos) {
+ return "SHA1";
+ } else if (transform.find("SHA224") != string::npos) {
+ return "SHA_2_224";
+ } else if (transform.find("SHA256") != string::npos) {
+ return "SHA_2_256";
+ } else if (transform.find("SHA384") != string::npos) {
+ return "SHA_2_384";
+ } else if (transform.find("SHA512") != string::npos) {
+ return "SHA_2_512";
+ } else if (transform.find("RSA") != string::npos &&
+ transform.find("OAEP") != string::npos) {
+ if (securityLevel_ == SecurityLevel::STRONGBOX) {
+ return "SHA_2_256";
+ } else {
+ return "SHA1";
+ }
+ } else if (transform.find("Hmac") != string::npos) {
+ return "SHA_2_256";
+ }
+ return "";
+ }
+
optional<EcCurve> getCurveFromLength(int keySize) {
switch (keySize) {
case 224:
return EcCurve::P_224;
- break;
case 256:
return EcCurve::P_256;
- break;
case 384:
return EcCurve::P_384;
- break;
case 521:
return EcCurve::P_521;
- break;
default:
- return {};
+ return std::nullopt;
}
}
@@ -261,6 +309,109 @@
return GetReturnErrorCode(result);
}
+ /* Copied the function LocalRsaEncryptMessage from
+ * hardware/interfaces/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp in VTS.
+ * Replaced asserts with the condition check and return false in case of failure condition.
+ * Require return value to skip the benchmark test case from further execution in case
+ * LocalRsaEncryptMessage fails.
+ */
+ optional<string> LocalRsaEncryptMessage(const string& message, const AuthorizationSet& params) {
+ // Retrieve the public key from the leaf certificate.
+ if (cert_chain_.empty()) {
+ std::cerr << "Local RSA encrypt Error: invalid cert_chain_" << std::endl;
+ return "Failure";
+ }
+ X509_Ptr key_cert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+ EVP_PKEY_Ptr pub_key(X509_get_pubkey(key_cert.get()));
+ RSA_Ptr rsa(EVP_PKEY_get1_RSA(const_cast<EVP_PKEY*>(pub_key.get())));
+
+ // Retrieve relevant tags.
+ Digest digest = Digest::NONE;
+ Digest mgf_digest = Digest::SHA1;
+ PaddingMode padding = PaddingMode::NONE;
+
+ auto digest_tag = params.GetTagValue(TAG_DIGEST);
+ if (digest_tag.has_value()) digest = digest_tag.value();
+ auto pad_tag = params.GetTagValue(TAG_PADDING);
+ if (pad_tag.has_value()) padding = pad_tag.value();
+ auto mgf_tag = params.GetTagValue(TAG_RSA_OAEP_MGF_DIGEST);
+ if (mgf_tag.has_value()) mgf_digest = mgf_tag.value();
+
+ const EVP_MD* md = openssl_digest(digest);
+ const EVP_MD* mgf_md = openssl_digest(mgf_digest);
+
+ // Set up encryption context.
+ EVP_PKEY_CTX_Ptr ctx(EVP_PKEY_CTX_new(pub_key.get(), /* engine= */ nullptr));
+ if (EVP_PKEY_encrypt_init(ctx.get()) <= 0) {
+ std::cerr << "Local RSA encrypt Error: Encryption init failed" << std::endl;
+ return "Failure";
+ }
+
+ int rc = -1;
+ switch (padding) {
+ case PaddingMode::NONE:
+ rc = EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_NO_PADDING);
+ break;
+ case PaddingMode::RSA_PKCS1_1_5_ENCRYPT:
+ rc = EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_PADDING);
+ break;
+ case PaddingMode::RSA_OAEP:
+ rc = EVP_PKEY_CTX_set_rsa_padding(ctx.get(), RSA_PKCS1_OAEP_PADDING);
+ break;
+ default:
+ break;
+ }
+ if (rc <= 0) {
+ std::cerr << "Local RSA encrypt Error: Set padding failed" << std::endl;
+ return "Failure";
+ }
+ if (padding == PaddingMode::RSA_OAEP) {
+ if (!EVP_PKEY_CTX_set_rsa_oaep_md(ctx.get(), md)) {
+ std::cerr << "Local RSA encrypt Error: Set digest failed: " << ERR_peek_last_error()
+ << std::endl;
+ return "Failure";
+ }
+ if (!EVP_PKEY_CTX_set_rsa_mgf1_md(ctx.get(), mgf_md)) {
+ std::cerr << "Local RSA encrypt Error: Set digest failed: " << ERR_peek_last_error()
+ << std::endl;
+ return "Failure";
+ }
+ }
+
+ // Determine output size.
+ size_t outlen;
+ if (EVP_PKEY_encrypt(ctx.get(), nullptr /* out */, &outlen,
+ reinterpret_cast<const uint8_t*>(message.data()),
+ message.size()) <= 0) {
+ std::cerr << "Local RSA encrypt Error: Determine output size failed: "
+ << ERR_peek_last_error() << std::endl;
+ return "Failure";
+ }
+
+ // Left-zero-pad the input if necessary.
+ const uint8_t* to_encrypt = reinterpret_cast<const uint8_t*>(message.data());
+ size_t to_encrypt_len = message.size();
+
+ std::unique_ptr<string> zero_padded_message;
+ if (padding == PaddingMode::NONE && to_encrypt_len < outlen) {
+ zero_padded_message.reset(new string(outlen, '\0'));
+ memcpy(zero_padded_message->data() + (outlen - to_encrypt_len), message.data(),
+ message.size());
+ to_encrypt = reinterpret_cast<const uint8_t*>(zero_padded_message->data());
+ to_encrypt_len = outlen;
+ }
+
+ // Do the encryption.
+ string output(outlen, '\0');
+ if (EVP_PKEY_encrypt(ctx.get(), reinterpret_cast<uint8_t*>(output.data()), &outlen,
+ to_encrypt, to_encrypt_len) <= 0) {
+ std::cerr << "Local RSA encrypt Error: Encryption failed: " << ERR_peek_last_error()
+ << std::endl;
+ return "Failure";
+ }
+ return output;
+ }
+
SecurityLevel securityLevel_;
string name_;
@@ -268,12 +419,13 @@
ErrorCode GenerateKey(const AuthorizationSet& key_desc,
const optional<AttestationKey>& attest_key = std::nullopt) {
key_blob_.clear();
+ cert_chain_.clear();
KeyCreationResult creationResult;
Status result = keymint_->generateKey(key_desc.vector_data(), attest_key, &creationResult);
if (result.isOk()) {
key_blob_ = std::move(creationResult.keyBlob);
+ cert_chain_ = std::move(creationResult.certificateChain);
creationResult.keyCharacteristics.clear();
- creationResult.certificateChain.clear();
}
return GetReturnErrorCode(result);
}
@@ -338,6 +490,11 @@
return ErrorCode::UNKNOWN_ERROR;
}
+ X509_Ptr parse_cert_blob(const vector<uint8_t>& blob) {
+ const uint8_t* p = blob.data();
+ return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size()));
+ }
+
std::shared_ptr<IKeyMintOperation> op_;
vector<Certificate> cert_chain_;
vector<uint8_t> key_blob_;
@@ -390,6 +547,10 @@
BENCHMARK_KM_MSG(encrypt, transform, keySize, msgSize) \
BENCHMARK_KM_MSG(decrypt, transform, keySize, msgSize)
+// Skip public key operations as they are not supported in KeyMint.
+#define BENCHMARK_KM_ASYM_CIPHER(transform, keySize, msgSize) \
+ BENCHMARK_KM_MSG(decrypt, transform, keySize, msgSize)
+
#define BENCHMARK_KM_CIPHER_ALL_MSGS(transform, keySize) \
BENCHMARK_KM_ALL_MSGS(encrypt, transform, keySize) \
BENCHMARK_KM_ALL_MSGS(decrypt, transform, keySize)
@@ -397,12 +558,43 @@
#define BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, keySize) \
BENCHMARK_KM_ALL_MSGS(sign, transform, keySize) \
BENCHMARK_KM_ALL_MSGS(verify, transform, keySize)
-// clang-format on
+
+// Skip public key operations as they are not supported in KeyMint.
+#define BENCHMARK_KM_ASYM_SIGNATURE_ALL_MSGS(transform, keySize) \
+ BENCHMARK_KM_ALL_MSGS(sign, transform, keySize) \
+ // clang-format on
/*
* ============= KeyGen TESTS ==================
*/
+
+static bool isValidSBKeySize(string transform, int keySize) {
+ std::optional<Algorithm> algorithm = keymintTest->getAlgorithm(transform);
+ switch (algorithm.value()) {
+ case Algorithm::AES:
+ return (keySize == 128 || keySize == 256);
+ case Algorithm::HMAC:
+ return (keySize % 8 == 0 && keySize >= 64 && keySize <= 512);
+ case Algorithm::TRIPLE_DES:
+ return (keySize == 168);
+ case Algorithm::RSA:
+ return (keySize == 2048);
+ case Algorithm::EC:
+ return (keySize == 256);
+ }
+ return false;
+}
+
static void keygen(benchmark::State& state, string transform, int keySize) {
+ // Skip the test for unsupported key size in StrongBox
+ if (keymintTest->securityLevel_ == SecurityLevel::STRONGBOX &&
+ !isValidSBKeySize(transform, keySize)) {
+ state.SkipWithError(("Skipped for STRONGBOX: Keysize: " + std::to_string(keySize) +
+ " is not supported in StrongBox for algorithm: " +
+ keymintTest->getAlgorithmString(transform))
+ .c_str());
+ return;
+ }
addDefaultLabel(state);
for (auto _ : state) {
if (!keymintTest->GenerateKey(transform, keySize)) {
@@ -438,8 +630,24 @@
/*
* ============= SIGNATURE TESTS ==================
*/
-
static void sign(benchmark::State& state, string transform, int keySize, int msgSize) {
+ // Skip the test for unsupported key size or unsupported digest in StrongBox
+ if (keymintTest->securityLevel_ == SecurityLevel::STRONGBOX) {
+ if (!isValidSBKeySize(transform, keySize)) {
+ state.SkipWithError(("Skipped for STRONGBOX: Keysize: " + std::to_string(keySize) +
+ " is not supported in StrongBox for algorithm: " +
+ keymintTest->getAlgorithmString(transform))
+ .c_str());
+ return;
+ }
+ if (keymintTest->getDigest(transform) != Digest::SHA_2_256) {
+ state.SkipWithError(
+ ("Skipped for STRONGBOX: Digest: " + keymintTest->getDigestString(transform) +
+ " is not supported in StrongBox")
+ .c_str());
+ return;
+ }
+ }
addDefaultLabel(state);
if (!keymintTest->GenerateKey(transform, keySize, true)) {
state.SkipWithError(
@@ -469,6 +677,23 @@
}
static void verify(benchmark::State& state, string transform, int keySize, int msgSize) {
+ // Skip the test for unsupported key size or unsupported digest in StrongBox
+ if (keymintTest->securityLevel_ == SecurityLevel::STRONGBOX) {
+ if (!isValidSBKeySize(transform, keySize)) {
+ state.SkipWithError(("Skipped for STRONGBOX: Keysize: " + std::to_string(keySize) +
+ " is not supported in StrongBox for algorithm: " +
+ keymintTest->getAlgorithmString(transform))
+ .c_str());
+ return;
+ }
+ if (keymintTest->getDigest(transform) != Digest::SHA_2_256) {
+ state.SkipWithError(
+ ("Skipped for STRONGBOX: Digest: " + keymintTest->getDigestString(transform) +
+ " is not supported in StrongBox")
+ .c_str());
+ return;
+ }
+ }
addDefaultLabel(state);
if (!keymintTest->GenerateKey(transform, keySize, true)) {
state.SkipWithError(
@@ -525,10 +750,10 @@
BENCHMARK_KM_SIGNATURE_ALL_HMAC_KEYS(HmacSHA512)
#define BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(transform) \
- BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 224) \
- BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 256) \
- BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 384) \
- BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 521)
+ BENCHMARK_KM_ASYM_SIGNATURE_ALL_MSGS(transform, 224) \
+ BENCHMARK_KM_ASYM_SIGNATURE_ALL_MSGS(transform, 256) \
+ BENCHMARK_KM_ASYM_SIGNATURE_ALL_MSGS(transform, 384) \
+ BENCHMARK_KM_ASYM_SIGNATURE_ALL_MSGS(transform, 521)
BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(NONEwithECDSA);
BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA1withECDSA);
@@ -538,13 +763,14 @@
BENCHMARK_KM_SIGNATURE_ALL_ECDSA_KEYS(SHA512withECDSA);
#define BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(transform) \
- BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 2048) \
- BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 3072) \
- BENCHMARK_KM_SIGNATURE_ALL_MSGS(transform, 4096)
+ BENCHMARK_KM_ASYM_SIGNATURE_ALL_MSGS(transform, 2048) \
+ BENCHMARK_KM_ASYM_SIGNATURE_ALL_MSGS(transform, 3072) \
+ BENCHMARK_KM_ASYM_SIGNATURE_ALL_MSGS(transform, 4096)
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(MD5withRSA);
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA1withRSA);
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA224withRSA);
+BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA256withRSA);
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA384withRSA);
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA512withRSA);
@@ -553,6 +779,7 @@
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA224withRSA/PSS);
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA384withRSA/PSS);
BENCHMARK_KM_SIGNATURE_ALL_RSA_KEYS(SHA512withRSA/PSS);
+
// clang-format on
/*
@@ -560,6 +787,15 @@
*/
static void encrypt(benchmark::State& state, string transform, int keySize, int msgSize) {
+ // Skip the test for unsupported key size in StrongBox
+ if (keymintTest->securityLevel_ == SecurityLevel::STRONGBOX &&
+ (!isValidSBKeySize(transform, keySize))) {
+ state.SkipWithError(("Skipped for STRONGBOX: Keysize: " + std::to_string(keySize) +
+ " is not supported in StrongBox for algorithm: " +
+ keymintTest->getAlgorithmString(transform))
+ .c_str());
+ return;
+ }
addDefaultLabel(state);
if (!keymintTest->GenerateKey(transform, keySize)) {
state.SkipWithError(
@@ -589,6 +825,15 @@
}
static void decrypt(benchmark::State& state, string transform, int keySize, int msgSize) {
+ // Skip the test for unsupported key size in StrongBox
+ if (keymintTest->securityLevel_ == SecurityLevel::STRONGBOX &&
+ (!isValidSBKeySize(transform, keySize))) {
+ state.SkipWithError(("Skipped for STRONGBOX: Keysize: " + std::to_string(keySize) +
+ " is not supported in StrongBox for algorithm: " +
+ keymintTest->getAlgorithmString(transform))
+ .c_str());
+ return;
+ }
addDefaultLabel(state);
if (!keymintTest->GenerateKey(transform, keySize)) {
state.SkipWithError(
@@ -598,23 +843,34 @@
AuthorizationSet out_params;
AuthorizationSet in_params = keymintTest->getOperationParams(transform);
string message = keymintTest->GenerateMessage(msgSize);
- auto error = keymintTest->Begin(KeyPurpose::ENCRYPT, in_params, &out_params);
- if (error != ErrorCode::OK) {
- state.SkipWithError(
- ("Encryption begin error, " + std::to_string(keymintTest->getError())).c_str());
- return;
+ optional<string> encryptedMessage;
+
+ if (keymintTest->getAlgorithm(transform).value() == Algorithm::RSA) {
+ // Public key operation not supported, doing local Encryption
+ encryptedMessage = keymintTest->LocalRsaEncryptMessage(message, in_params);
+ if ((keySize / 8) != (*encryptedMessage).size()) {
+ state.SkipWithError("Local Encryption falied");
+ return;
+ }
+ } else {
+ auto error = keymintTest->Begin(KeyPurpose::ENCRYPT, in_params, &out_params);
+ if (error != ErrorCode::OK) {
+ state.SkipWithError(
+ ("Encryption begin error, " + std::to_string(keymintTest->getError())).c_str());
+ return;
+ }
+ encryptedMessage = keymintTest->Process(message);
+ if (!encryptedMessage) {
+ state.SkipWithError(
+ ("Encryption error, " + std::to_string(keymintTest->getError())).c_str());
+ return;
+ }
+ in_params.push_back(out_params);
+ out_params.Clear();
}
- auto encryptedMessage = keymintTest->Process(message);
- if (!encryptedMessage) {
- state.SkipWithError(
- ("Encryption error, " + std::to_string(keymintTest->getError())).c_str());
- return;
- }
- in_params.push_back(out_params);
- out_params.Clear();
for (auto _ : state) {
state.PauseTiming();
- error = keymintTest->Begin(KeyPurpose::DECRYPT, in_params, &out_params);
+ auto error = keymintTest->Begin(KeyPurpose::DECRYPT, in_params, &out_params);
if (error != ErrorCode::OK) {
state.SkipWithError(
("Decryption begin error, " + std::to_string(keymintTest->getError())).c_str());
@@ -649,9 +905,9 @@
BENCHMARK_KM_CIPHER_ALL_MSGS(DESede/ECB/PKCS7Padding, 168);
#define BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(transform, msgSize) \
- BENCHMARK_KM_CIPHER(transform, 2048, msgSize) \
- BENCHMARK_KM_CIPHER(transform, 3072, msgSize) \
- BENCHMARK_KM_CIPHER(transform, 4096, msgSize)
+ BENCHMARK_KM_ASYM_CIPHER(transform, 2048, msgSize) \
+ BENCHMARK_KM_ASYM_CIPHER(transform, 3072, msgSize) \
+ BENCHMARK_KM_ASYM_CIPHER(transform, 4096, msgSize)
BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/NoPadding, SMALL_MESSAGE_SIZE);
BENCHMARK_KM_CIPHER_ALL_RSA_KEYS(RSA/ECB/PKCS1Padding, SMALL_MESSAGE_SIZE);
diff --git a/security/keymint/support/Android.bp b/security/keymint/support/Android.bp
index 3f48320..efd6fc7 100644
--- a/security/keymint/support/Android.bp
+++ b/security/keymint/support/Android.bp
@@ -63,6 +63,9 @@
defaults: [
"keymint_use_latest_hal_aidl_ndk_shared",
],
+ static_libs: [
+ "android.hardware.security.rkp-V3-ndk",
+ ],
shared_libs: [
"libbase",
"libbinder_ndk",
@@ -78,6 +81,7 @@
name: "libkeymint_remote_prov_support_test",
srcs: ["remote_prov_utils_test.cpp"],
static_libs: [
+ "android.hardware.security.rkp-V3-ndk",
"libgmock",
"libgtest_main",
],
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 9ea20ac..1b94c62 100644
--- a/security/keymint/support/include/remote_prov/remote_prov_utils.h
+++ b/security/keymint/support/include/remote_prov/remote_prov_utils.h
@@ -177,4 +177,18 @@
const EekChain& eekChain, const std::vector<uint8_t>& eekId, int32_t supportedEekCurve,
IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+/**
+ * Verify the CSR as if the device is still early in the factory process and may not
+ * have all device identifiers provisioned yet.
+ */
+ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
+ const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
+ IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+/**
+ * Verify the CSR as if the device is a final production sample.
+ */
+ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
+ const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
+ IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge);
+
} // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/keymint/support/remote_prov_utils.cpp b/security/keymint/support/remote_prov_utils.cpp
index 0651496..7e164fd 100644
--- a/security/keymint/support/remote_prov_utils.cpp
+++ b/security/keymint/support/remote_prov_utils.cpp
@@ -32,6 +32,7 @@
#include <openssl/base64.h>
#include <openssl/evp.h>
#include <openssl/rand.h>
+#include <openssl/x509.h>
#include <remote_prov/remote_prov_utils.h>
namespace aidl::android::hardware::security::keymint::remote_prov {
@@ -45,6 +46,8 @@
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>;
+using X509_Ptr = bssl::UniquePtr<X509>;
+using CRYPTO_BUFFER_Ptr = bssl::UniquePtr<CRYPTO_BUFFER>;
ErrMsgOr<bytevec> ecKeyGetPrivateKey(const EC_KEY* ecKey) {
// Extract private key.
@@ -518,31 +521,35 @@
return errMsg;
}
- std::unique_ptr<cppbor::Map> parsed(parsedVerifiedDeviceInfo->asMap());
+ std::unique_ptr<cppbor::Map> parsed(parsedVerifiedDeviceInfo.release()->asMap());
if (!parsed) {
return "DeviceInfo must be a CBOR map.";
}
- parsedVerifiedDeviceInfo.release();
if (parsed->clone()->asMap()->canonicalize().encode() != deviceInfoBytes) {
return "DeviceInfo ordering is non-canonical.";
}
- const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
- if (!version) {
- return "Device info is missing version";
- }
- if (!version->asUint()) {
- return "version must be an unsigned integer";
- }
+
RpcHardwareInfo info;
provisionable->getHardwareInfo(&info);
- if (version->asUint()->value() != info.versionNumber) {
- return "DeviceInfo version (" + std::to_string(version->asUint()->value()) +
- ") does not match the remotely provisioned component version (" +
- std::to_string(info.versionNumber) + ").";
+ if (info.versionNumber < 3) {
+ const std::unique_ptr<cppbor::Item>& version = parsed->get("version");
+ if (!version) {
+ return "Device info is missing version";
+ }
+ if (!version->asUint()) {
+ return "version must be an unsigned integer";
+ }
+ if (version->asUint()->value() != info.versionNumber) {
+ return "DeviceInfo version (" + std::to_string(version->asUint()->value()) +
+ ") does not match the remotely provisioned component version (" +
+ std::to_string(info.versionNumber) + ").";
+ }
}
+
std::string error;
- switch (version->asUint()->value()) {
+ switch (info.versionNumber) {
+ case 3:
case 2:
for (const auto& entry : kAttestationIdEntrySet) {
error += checkMapEntry(isFactory && !entry.alwaysValidate, *parsed, cppbor::TSTR,
@@ -579,7 +586,7 @@
kValidAttIdStates);
break;
default:
- return "Unrecognized version: " + std::to_string(version->asUint()->value());
+ return "Unrecognized version: " + std::to_string(info.versionNumber);
}
if (!error.empty()) {
@@ -734,4 +741,296 @@
/*isFactory=*/false);
}
-} // namespace aidl::android::hardware::security::keymint::remote_prov
\ No newline at end of file
+ErrMsgOr<X509_Ptr> parseX509Cert(const std::vector<uint8_t>& cert) {
+ CRYPTO_BUFFER_Ptr certBuf(CRYPTO_BUFFER_new(cert.data(), cert.size(), nullptr));
+ if (!certBuf.get()) {
+ return "Failed to create crypto buffer.";
+ }
+ X509_Ptr result(X509_parse_from_buffer(certBuf.get()));
+ if (!result.get()) {
+ return "Failed to parse certificate.";
+ }
+ return result;
+}
+
+std::string getX509IssuerName(const X509_Ptr& cert) {
+ char* name = X509_NAME_oneline(X509_get_issuer_name(cert.get()), nullptr, 0);
+ std::string result(name);
+ OPENSSL_free(name);
+ return result;
+}
+
+std::string getX509SubjectName(const X509_Ptr& cert) {
+ char* name = X509_NAME_oneline(X509_get_subject_name(cert.get()), nullptr, 0);
+ std::string result(name);
+ OPENSSL_free(name);
+ return result;
+}
+
+// Validates the certificate chain and returns the leaf public key.
+ErrMsgOr<bytevec> validateCertChain(const cppbor::Array& chain) {
+ uint8_t rawPubKey[64];
+ size_t rawPubKeySize = sizeof(rawPubKey);
+ for (size_t i = 0; i < chain.size(); ++i) {
+ // Root must be self-signed.
+ size_t signingCertIndex = (i > 1) ? i - 1 : i;
+ auto& keyCertItem = chain[i];
+ auto& signingCertItem = chain[signingCertIndex];
+ if (!keyCertItem || !keyCertItem->asBstr()) {
+ return "Key certificate must be a Bstr.";
+ }
+ if (!signingCertItem || !signingCertItem->asBstr()) {
+ return "Signing certificate must be a Bstr.";
+ }
+
+ auto keyCert = parseX509Cert(keyCertItem->asBstr()->value());
+ if (!keyCert) {
+ return keyCert.message();
+ }
+ auto signingCert = parseX509Cert(keyCertItem->asBstr()->value());
+ if (!signingCert) {
+ return signingCert.message();
+ }
+
+ EVP_PKEY_Ptr pubKey(X509_get_pubkey(keyCert->get()));
+ if (!pubKey.get()) {
+ return "Failed to get public key.";
+ }
+ EVP_PKEY_Ptr signingPubKey(X509_get_pubkey(signingCert->get()));
+ if (!signingPubKey.get()) {
+ return "Failed to get signing public key.";
+ }
+
+ if (!X509_verify(keyCert->get(), signingPubKey.get())) {
+ return "Verification of certificate " + std::to_string(i) +
+ " faile. OpenSSL error string: " + ERR_error_string(ERR_get_error(), NULL);
+ }
+
+ auto certIssuer = getX509IssuerName(*keyCert);
+ auto signerSubj = getX509SubjectName(*signingCert);
+ if (certIssuer != signerSubj) {
+ return "Certificate " + std::to_string(i) + " has wrong issuer. Signer subject is " +
+ signerSubj + " Issuer subject is " + certIssuer;
+ }
+
+ rawPubKeySize = sizeof(rawPubKey);
+ if (!EVP_PKEY_get_raw_public_key(pubKey.get(), rawPubKey, &rawPubKeySize)) {
+ return "Failed to get raw public key.";
+ }
+ }
+
+ return bytevec(rawPubKey, rawPubKey + rawPubKeySize);
+}
+
+std::string validateUdsCerts(const cppbor::Map& udsCerts, const bytevec& udsPub) {
+ for (const auto& [signerName, udsCertChain] : udsCerts) {
+ if (!signerName || !signerName->asTstr()) {
+ return "Signer Name must be a Tstr.";
+ }
+ if (!udsCertChain || !udsCertChain->asArray()) {
+ return "UDS certificate chain must be an Array.";
+ }
+ if (udsCertChain->asArray()->size() < 2) {
+ return "UDS certificate chain must have at least two entries: root and leaf.";
+ }
+
+ auto leafPubKey = validateCertChain(*udsCertChain->asArray());
+ if (!leafPubKey) {
+ return leafPubKey.message();
+ }
+ if (*leafPubKey != udsPub) {
+ return "Leaf public key in UDS certificat chain doesn't match UDS public key.";
+ }
+ }
+ return "";
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Array>> parseAndValidateCsrPayload(
+ const cppbor::Array& keysToSign, const std::vector<uint8_t>& csrPayload,
+ IRemotelyProvisionedComponent* provisionable, bool isFactory) {
+ auto [parsedCsrPayload, _, errMsg] = cppbor::parse(csrPayload);
+ if (!parsedCsrPayload) {
+ return errMsg;
+ }
+
+ std::unique_ptr<cppbor::Array> parsed(parsedCsrPayload.release()->asArray());
+ if (!parsed) {
+ return "CSR payload is not a CBOR array.";
+ }
+
+ if (parsed->size() != 4U) {
+ return "CSR payload must contain version, certificate type, device info, keys. "
+ "However, the parsed CSR payload has " +
+ std::to_string(parsed->size()) + " entries.";
+ }
+
+ auto signedVersion = parsed->get(0)->asUint();
+ auto signedCertificateType = parsed->get(1)->asTstr();
+ auto signedDeviceInfo = parsed->get(2)->asMap();
+ auto signedKeys = parsed->get(3)->asArray();
+
+ if (!signedVersion || signedVersion->value() != 3U) {
+ return "CSR payload version must be an unsigned integer and must be equal to 3.";
+ }
+ if (!signedCertificateType) {
+ // Certificate type is allowed to be extendend by vendor, i.e. we can't
+ // enforce its value.
+ return "Certificate type must be a Tstr.";
+ }
+ if (!signedDeviceInfo) {
+ return "Device info must be an Map.";
+ }
+ if (!signedKeys) {
+ return "Keys must be an Array.";
+ }
+
+ auto result = parseAndValidateDeviceInfo(signedDeviceInfo->encode(), provisionable, isFactory);
+ if (!result) {
+ return result.message();
+ }
+
+ if (signedKeys->encode() != keysToSign.encode()) {
+ return "Signed keys do not match.";
+ }
+
+ return std::move(parsed);
+}
+
+ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequestSignedPayload(
+ const std::vector<uint8_t>& signedPayload, const std::vector<uint8_t>& challenge) {
+ auto [parsedSignedPayload, _, errMsg] = cppbor::parse(signedPayload);
+ if (!parsedSignedPayload) {
+ return errMsg;
+ }
+ if (!parsedSignedPayload->asArray()) {
+ return "SignedData payload is not a CBOR array.";
+ }
+ if (parsedSignedPayload->asArray()->size() != 2U) {
+ return "SignedData payload must contain the challenge and request. However, the parsed "
+ "SignedData payload has " +
+ std::to_string(parsedSignedPayload->asArray()->size()) + " entries.";
+ }
+
+ auto signedChallenge = parsedSignedPayload->asArray()->get(0)->asBstr();
+ auto signedRequest = parsedSignedPayload->asArray()->get(1)->asBstr();
+
+ if (!signedChallenge) {
+ return "Challenge must be a Bstr.";
+ }
+
+ if (challenge.size() < 32 || challenge.size() > 64) {
+ return "Challenge size must be between 32 and 64 bytes inclusive. "
+ "However, challenge is " +
+ std::to_string(challenge.size()) + " bytes long.";
+ }
+
+ auto challengeBstr = cppbor::Bstr(challenge);
+ if (*signedChallenge != challengeBstr) {
+ return "Signed challenge does not match."
+ "\n Actual: " +
+ cppbor::prettyPrint(signedChallenge->asBstr(), 64 /* maxBStrSize */) +
+ "\nExpected: " + cppbor::prettyPrint(&challengeBstr, 64 /* maxBStrSize */);
+ }
+
+ if (!signedRequest) {
+ return "Request must be a Bstr.";
+ }
+
+ return signedRequest->value();
+}
+
+ErrMsgOr<bytevec> parseAndValidateAuthenticatedRequest(const std::vector<uint8_t>& request,
+ const std::vector<uint8_t>& challenge) {
+ auto [parsedRequest, _, csrErrMsg] = cppbor::parse(request);
+ if (!parsedRequest) {
+ return csrErrMsg;
+ }
+ if (!parsedRequest->asArray()) {
+ return "AuthenticatedRequest is not a CBOR array.";
+ }
+ if (parsedRequest->asArray()->size() != 4U) {
+ return "AuthenticatedRequest must contain version, UDS certificates, DICE chain, and "
+ "signed data. However, the parsed AuthenticatedRequest has " +
+ std::to_string(parsedRequest->asArray()->size()) + " entries.";
+ }
+
+ auto version = parsedRequest->asArray()->get(0)->asUint();
+ auto udsCerts = parsedRequest->asArray()->get(1)->asMap();
+ auto diceCertChain = parsedRequest->asArray()->get(2)->asArray();
+ auto signedData = parsedRequest->asArray()->get(3)->asArray();
+
+ if (!version || version->value() != 1U) {
+ return "AuthenticatedRequest version must be an unsigned integer and must be equal to 1.";
+ }
+ if (!udsCerts) {
+ return "AuthenticatedRequest UdsCerts must be an Map.";
+ }
+ if (!diceCertChain) {
+ return "AuthenticatedRequest DiceCertChain must be an Array.";
+ }
+ if (!signedData) {
+ return "AuthenticatedRequest SignedData must be an Array.";
+ }
+
+ // DICE chain is [ pubkey, + DiceChainEntry ]. Its format is the same as BCC from RKP v1-2.
+ auto diceContents = validateBcc(diceCertChain);
+ if (!diceContents) {
+ return diceContents.message() + "\n" + prettyPrint(diceCertChain);
+ }
+ if (diceContents->size() == 0U) {
+ return "The DICE chain is empty. It must contain at least one entry.";
+ }
+
+ auto& udsPub = diceContents->back().pubKey;
+
+ auto error = validateUdsCerts(*udsCerts, udsPub);
+ if (!error.empty()) {
+ return error;
+ }
+
+ auto signedPayload = verifyAndParseCoseSign1(signedData, udsPub, {} /* aad */);
+ if (!signedPayload) {
+ return signedPayload.message();
+ }
+
+ auto payload = parseAndValidateAuthenticatedRequestSignedPayload(*signedPayload, challenge);
+ if (!payload) {
+ return payload.message();
+ }
+
+ return payload;
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyCsr(const cppbor::Array& keysToSign,
+ const std::vector<uint8_t>& csr,
+ IRemotelyProvisionedComponent* provisionable,
+ const std::vector<uint8_t>& challenge,
+ bool isFactory) {
+ RpcHardwareInfo info;
+ provisionable->getHardwareInfo(&info);
+ if (info.versionNumber != 3) {
+ return "Remotely provisioned component version (" + std::to_string(info.versionNumber) +
+ ") does not match expected version (3).";
+ }
+
+ auto csrPayload = parseAndValidateAuthenticatedRequest(csr, challenge);
+ if (!csrPayload) {
+ return csrPayload.message();
+ }
+
+ return parseAndValidateCsrPayload(keysToSign, *csrPayload, provisionable, isFactory);
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyFactoryCsr(
+ const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
+ IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+ return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/true);
+}
+
+ErrMsgOr<std::unique_ptr<cppbor::Array>> verifyProductionCsr(
+ const cppbor::Array& keysToSign, const std::vector<uint8_t>& csr,
+ IRemotelyProvisionedComponent* provisionable, const std::vector<uint8_t>& challenge) {
+ return verifyCsr(keysToSign, csr, provisionable, challenge, /*isFactory=*/false);
+}
+
+} // namespace aidl::android::hardware::security::keymint::remote_prov
diff --git a/security/rkp/CHANGELOG.md b/security/rkp/CHANGELOG.md
new file mode 100644
index 0000000..c3e3609
--- /dev/null
+++ b/security/rkp/CHANGELOG.md
@@ -0,0 +1,45 @@
+# Remote Provisioning Changelog
+
+This document provides an exact description of which changes have occurred in the
+`IRemotelyProvisionedComponent` HAL interface in each Android release.
+
+## Releases
+* **Android S (12):** IRemotelyProvisionedComponent v1
+* **Android T (13):** IRemotelyProvisionedComponent v2
+* **Android U (14):** IRemotelyProvisionedComponent v3
+
+## IRemotelyProvisionedComponent 1 -> 2
+* DeviceInfo
+ * Most entries are no longer optional.
+ * `att_id_state` is now `fused`. `fused` is used to indicate if SecureBoot is enabled.
+ * `version` is now `2`.
+ * `board` has been removed.
+ * `device` has been added.
+* RpcHardwareInfo
+ * `uniqueId` String added as a field in order to differentiate IRPC instances on device.
+
+## IRemotelyProvisionedComponent 2 -> 3
+* The RKP HAL now builds separately from KeyMint.
+ * The HAL remains under the `android.hardware.security.keymint` package for
+ compatibility with previous releases. ABI compatibility requires this.
+ * Dependencies on the RKP HAL must add a dependency on
+ `"android.hardware.security.rkp"` generated code (instead of
+ `"android.hardward.security.keymint"`).
+* ProtectedData has been removed.
+* DeviceInfo
+ * `version` has moved to a top-level field within the CSR generated by the HAL.
+* IRemotelyProvisionedComponent
+ * The need for an EEK has been removed. There is no longer an encrypted portion of the CSR.
+ * Test mode has been removed.
+ * The schema for the CSR itself has been significantly simplified, please see
+ IRemotelyProvisionedComponent.aidl for more details. Notably,
+ * the chain of signing, MACing, and encryption operations has been replaced with a single
+ COSE_Sign1 object.
+ * CertificateType has been added to identify the type of certificate being requested.
+ * The structure has been composed to enable a clear split between what is required to validate a
+ payload and the implementation-defined payload itself. This is done by creating a typed
+ `AuthenticatedRequest<T>` object representing the top level data required to authenticate
+ the data provided in the payload, `T`.
+* RpcHardwareInfo
+ * `supportedNumKeysInCsr` added to report the maximum number of keys supported in a CSR.
+ * `supportedEekCurve` is no longer used, due to the removal of the EEK from the scheme.
diff --git a/security/rkp/README.md b/security/rkp/README.md
new file mode 100644
index 0000000..5fb4948
--- /dev/null
+++ b/security/rkp/README.md
@@ -0,0 +1,374 @@
+# Remote Provisioning HAL
+
+## Objective
+
+Design a HAL to support over-the-air provisioning of certificates for asymmetric
+keys. The HAL must interact effectively with Keystore (and other daemons) and
+protect device privacy and security.
+
+Note that this API was originally designed for KeyMint, with the intention that
+it should be usable for other HALs that require certificate provisioning.
+Throughout this document we'll refer to the Keystore and KeyMint (formerly
+called Keymaster) components, but only for concreteness and convenience; those
+labels could be replaced with the names of any system and secure area
+components, respectively, that need certificates provisioned.
+
+## Key design decisions
+
+### General approach
+
+To more securely and reliably get keys and certificates to Android devices, we
+need to create a system where no party outside of the device's secure components
+is responsible for managing private keys. The strategy we've chosen is to
+deliver certificates over the air, using an asymmetric key pair created
+on-device in the factory as a root of trust to create an authenticated, secure
+channel. In this document we refer to this device-unique asymmetric key pair as
+Device Key (DK), its public half DK\_pub, its private half DK\_priv and a Device
+Key Certificate containing DK\_pub is denoted DKC.
+
+In order for the provisioning service to use DK (or a key authenticated by DK),
+it must know whether a given DK\_pub is known and trusted. To prove trust, we
+ask device OEMs to use one of two mechanisms:
+
+1. (Preferred, recommended) The device OEM extracts DK\_pub from each device it
+ manufactures and uploads the public keys to a backend server.
+
+1. The device OEM signs the DK\_pub to produce DKC and stores it on the device.
+ This has the advantage that they don't need to upload a DK\_pub for every
+ device immediately, but the disadvantage that they have to manage their
+ private signing keys, which means they have to have HSMs, configure and
+ secure them correctly, etc. Some backend providers may also require that the
+ OEM passes a factory security audit, and additionally promises to upload the
+ keys eventually as well.
+
+Note that in the full elaboration of this plan, DK\_pub is not the key used to
+establish a secure channel. Instead, DK\_pub is just the first public key in a
+chain of public keys which ends with the KeyMint public key, KM\_pub. All keys
+in the chain are device-unique and are joined in a certificate chain called the
+_Boot Certificate Chain_ (BCC), because in phases 2 and 3 of the remote
+provisioning project it is a chain of certificates corresponding to boot phases.
+We speak of the BCC even for phase 1, though in phase 1 it contains only a
+single self-signed DKC. This is described in more depth in the Phases section
+below.
+
+The BCC is authenticated by DK\_pub. To authenticate DK\_pub, we may have
+additional DKCs, from the SoC vendor, the device OEM, or both. Those are not
+part of the BCC but included as optional fields in the certificate request
+structure.
+
+The format of the the DK and BCC is specified within [Open Profile for DICE]
+(https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md). To
+map phrases within this document to their equivalent terminology in the DICE
+specification, read the terms as follows: the DK corresponds to the UDS-derived
+key pair, DKC corresponds to the UDS certificate, and the BCC entries between
+DK\_pub and KM\_pub correspond to a chain of CDI certificates.
+
+Note: In addition to allowing 32 byte hash values for fields in the BCC payload,
+this spec additionally constrains some of the choices allowed in open-DICE.
+Specifically, these include which entries are required and which are optional in
+the BCC payload, and which algorithms are acceptable for use.
+
+### Phases
+
+RKP will be deployed in three phases, in terms of managing the root of trust
+binding between the device and the backend. To briefly describe them:
+
+* Phase 1: In phase 1 there is only one entry in the BCC; DK_pub and KM_pub are
+ the same key and the certificate is self-signed.
+* Phase 2: This is identical to phase 1, except it leverages the hardware root
+ of trust process described by DICE. Instead of trust being rooted in the TEE,
+ it is now rooted in the ROM by key material blown into fuses which are only
+ accessible to the ROM code.
+* Phase 3: This is identical to Phase 2, except the SoC vendor also does the
+ public key extraction or certification in their facilities, along with the OEM
+ doing it in the factory. This tightens up the "supply chain" and aims to make
+ key upload management more secure.
+
+### Privacy considerations
+
+Because DK and the DKCs are unique, immutable, unspoofable hardware-bound
+identifiers for the device, we must limit access to them to the absolute minimum
+possible. We do this in two ways:
+
+1. We require KeyMint (which knows the BCC and either knows or at least has the
+ability to use KM\_priv) to refuse to ever divulge the BCC or additional
+signatures in plaintext. Instead, KeyMint requires the caller to provide an
+_Endpoint Encryption Key_ (EEK), with which it will encrypt the data before
+returning it. When provisioning production keys, the EEK must be signed by an
+approved authority whose public key is embedded in KeyMint. When certifying test
+keys, KeyMint will accept any EEK without checking the signature, but will
+encrypt and return a test BCC, rather than the real one. The result is that
+only an entity in possession of an Trusted EEK (TEEK) private key can discover
+the plaintext of the production BCC.
+1. Having thus limited access to the public keys to the trusted party only, we
+need to prevent the entity from abusing this unique device identifier. The
+approach and mechanisms for doing that are beyond the scope of this document
+(they must be addressed in the server design), but generally involve taking care
+to ensure that we do not create any links between user IDs, IP addresses or
+issued certificates and the device pubkey.
+
+Although the details of the mechanisms for preventing the entity from abusing
+the BCC are, as stated, beyond the scope of this document, there is a subtle
+design decision here made specifically to enable abuse prevention. Specifically
+the `CertificateRequest` message sent to the server is (in
+[CDDL](https://tools.ietf.org/html/rfc8610)):
+
+```
+cddl
+CertificateRequest = [
+ DeviceInfo,
+ challenge : bstr,
+ ProtectedData,
+ MacedKeysToSign
+]
+```
+
+The public keys to be attested by the server are in `MacedKeysToSign`, which is
+a COSE\_Mac0 structure, MACed with a key that is found in `ProtectedData`. The
+MAC key is signed by DK\_pub.
+
+This structure allows the backend component that has access to EEK\_priv to
+decrypt `ProtectedData`, validate that the request is from an authorized device,
+check that the request is fresh and verify and extract the MAC key. That backend
+component never sees any data related to the keys to be signed, but can provide
+the MAC key to another backend component that can verify `MacedKeysToSign` and
+proceed to generate the certificates.
+
+In this way, we can partition the provisioning server into one component that
+knows the device identity, as represented by DK\_pub, but never sees the keys to
+be certified or certificates generated, and another component that sees the keys
+to be certified and certificates generated but does not know the device
+identity.
+
+### Key and cryptographic message formatting
+
+For simplicity of generation and parsing, compactness of wire representation,
+and flexibility and standardization, we've settled on using the CBOR Object
+Signing and Encryption (COSE) standard, defined in [RFC
+8152](https://tools.ietf.org/html/rfc8152). COSE provides compact and reasonably
+simple, yet easily-extensible, wire formats for:
+
+* Keys,
+* MACed messages,
+* Signed messages, and
+* Encrypted messages
+
+COSE enables easy layering of these message formats, such as using a COSE\_Sign
+structure to contain a COSE\_Key with a public key in it. We call this a
+"certificate".
+
+Due to the complexity of the standard, we'll spell out the COSE structures
+completely in this document and in the HAL and other documentation, so that
+although implementors will need to understand CBOR and the CBOR Data Definition
+Language ([CDDL, defined in RFC 8610](https://tools.ietf.org/html/rfc8610)),
+they shouldn't need to understand COSE.
+
+Note, however, that the certificate chains returned from the provisioning server
+are standard X.509 certificates.
+
+### Algorithm choices
+
+This document uses:
+
+* ECDSA P-256 for attestation signing keys;
+* Remote provisioning protocol signing keys:
+ * Ed25519 / P-256
+* ECDH keys:
+ * X25519 / P-256
+* AES-GCM for all encryption;
+* SHA-256 for all message digesting;
+* HMAC-SHA-256 for all MACing; and
+* HKDF-SHA-256 for all key derivation.
+
+We believe that Curve25519 offers the best tradeoff in terms of security,
+efficiency and global trustworthiness, and that it is now sufficiently
+widely-used and widely-implemented to make it a practical choice.
+
+However, since Secure Elements (SE) do not currently offer support for curve
+25519, we are allowing implementations to instead make use of EC P-256 for
+signing and ECDH. To put it simply, the device unique key pair will be a P-256
+key pair for ECDSA instead of Ed25519, and the ProtectedData COSE\_Encrypt
+message will have its payload encrypted with P-256 ECDH key exchange instead of
+X25519.
+
+The CDDL in the rest of the document will use the '/' operator to show areas
+where either curve 25519 or P-256 may be used. Since there is no easy way to
+bind choices across different CDDL groups, it is important that the implementor
+stays consistent in which type is chosen. E.g. taking ES256 as the choice for
+algorithm implies the implementor should also choose the P256 public key group
+further down in the COSE structure.
+
+### Testability
+
+It's critical that the remote provisioning implementation be testable, to
+minimize the probability that broken devices are sold to end users. To support
+testing, the remote provisioning HAL methods take a `testMode` argument. Keys
+created in test mode are tagged to indicate this. The provisioning server will
+check for the test mode tag and issue test certificates that do not chain back
+to a trusted public key. In test mode, any EEK will be accepted, enabling
+testing tools to use EEKs for which they have the private key so they can
+validate the content of certificate requests. The BCC included in the
+`CertificateRequest` must contain freshly-generated keys, not the real BCC keys.
+
+Keystore (or similar) will need to be able to handle both testMode keys and
+production keys and keep them distinct, generating test certificate requests
+when asked with a test EEK and production certificate requests when asked with a
+production EEK. Likewise, the interface used to instruct Keystore to create keys
+will need to be able to specify whether test or production keys are desired.
+
+## Design
+
+### Certificate provisioning flow
+
+TODO(jbires): Replace this with a `.png` containing a sequence diagram. The
+provisioning flow looks something like this:
+
+Provisioner -> Keystore: Prepare N keys
+Keystore -> KeyMint: generateKeyPair
+KeyMint -> KeyMint: Generate key pair
+KeyMint --> Keystore: key\_blob,pubkey
+Keystore -> Keystore: Store key\_blob,pubkey
+Provisioner -> Server: Get TEEK
+Server --> Provisioner: TEEK
+Provisioner -> Keystore: genCertReq(N, TEEK)
+Keystore -> KeyMint: genCertReq(pubkeys, TEEK)
+KeyMint -> KeyMint: Sign pubkeys & encrypt BCC
+KeyMint --> Keystore: signature, encrypted BCC
+Keystore -> Keystore: Construct cert\_request
+Keystore --> Provisioner: cert\_request
+Provisioner --> Server: cert\_request
+Server -> Server: Validate cert\_request
+Server -> Server: Generate certificates
+Server --> Provisioner: certificates
+Provisioner -> Keystore: certificates
+Keystore -> Keystore: Store certificates
+
+The actors in the above diagram are:
+
+* **Server** is the backend certificate provisioning server. It has access to
+ the uploaded device public keys and is responsible for providing encryption
+ keys, decrypting and validating requests, and generating certificates in
+ response to requests.
+* **Provisioner** is an application that is responsible for communicating with
+ the server and all of the system components that require key certificates
+ from the server. It also implements the policy that defines how many key
+ pairs each client should keep in their pool.
+* **Keystore** is the [Android keystore
+ daemon](https://developer.android.com/training/articles/keystore) (or, more
+ generally, whatever system component manages communications with a
+ particular secure aread component).
+* **KeyMint** is the secure area component that manages cryptographic keys and
+ performs attestations (or perhaps some other secure area component).
+
+### `BCC`
+
+The _Boot Certificate Chain_ (BCC) is the chain of certificates that contains
+DK\_pub as well as other often device-unique certificates. The BCC is
+represented as a COSE\_Key containing DK\_pub followed by an array of
+COSE\_Sign1 "certificates" containing public keys and optional additional
+information, ordered from root to leaf, with each certificate signing the next.
+The first certificate in the array is signed by DK\_pub, the last certificate
+has the KeyMint (or whatever) signing key's public key, KM\_pub. In phase 1
+there is only one entry; DK\_pub and KM\_pub are the same key and the
+certificate is self-signed.
+
+Each COSE\_Sign1 certificate is a CBOR Web Token (CWT) as described in [RFC
+8392](https://tools.ietf.org/html/rfc8392) with additional fields as described
+in the Open Profile for DICE. Of these additional fields, only the
+_subjectPublicKey_ and _keyUsage_ fields are expected to be present for the
+KM\_pub entry (that is, the last entry) in a BCC, but all fields required by the
+Open Profile for DICE are expected for other entries (each of which corresponds
+to a particular firmware component or boot stage). The CWT fields _iss_ and
+_sub_ identify the issuer and subject of the certificate and are consistent
+along the BCC entries; the issuer of a given entry matches the subject of the
+previous entry.
+
+The BCC is designed to be constructed using the Open Profile for DICE. In this
+case the DK key pair is derived from the UDS as described by that profile and
+all BCC entries before the leaf are CBOR CDI certificates chained from DK\_pub.
+The KM key pair is not part of the derived DICE chain. It is generated (not
+derived) by the KeyMint module, certified by the last key in the DICE chain, and
+added as the leaf BCC entry. The key usage field in this leaf certificate must
+indicate the key is not used to sign certificates. If a UDS certificate is
+available on the device it should appear in the certificate request as the leaf
+of a DKCertChain in AdditionalDKSignatures (see
+[CertificateRequest](#certificaterequest)).
+
+The Open Profile for DICE allows for an arbitrary configuration descriptor. For
+BCC entries, this configuration descriptor is a CBOR map with the following
+optional fields. If no fields are relevant, an empty map should be encoded.
+Additional implementation-specific fields may be added using key values not in
+the range \[-70000, -70999\] (these are reserved for future additions here).
+
+```
+| Name | Key | Value type | Meaning |
+| ----------------- | ------ | ---------- | ----------------------------------|
+| Component name | -70002 | tstr | Name of firmware component / boot |
+: : : : stage :
+| Component version | -70003 | int | Version of firmware component / |
+: : : : boot stage :
+| Resettable | -70004 | null | If present, key changes on factory|
+: : : : reset :
+```
+
+Please see
+[ProtectedData.aidl](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/ProtectedData.aidl)
+for a full CDDL definition of the BCC.
+
+### `CertificateRequest`
+
+The full CBOR message that will be sent to the server to request certificates
+is:
+
+```cddl
+CertificateRequest = [
+ DeviceInfo,
+ challenge : bstr, // Provided by the server
+ ProtectedData, // See ProtectedData.aidl
+ MacedKeysToSign // See IRemotelyProvisionedComponent.aidl
+]
+
+DeviceInfo = [
+ VerifiedDeviceInfo, // See DeviceInfo.aidl
+ UnverifiedDeviceInfo
+]
+
+// Unverified info is anything provided by the HLOS. Subject to change out of
+// step with the HAL.
+UnverifiedDeviceInfo = {
+ ? "fingerprint" : tstr,
+}
+
+```
+
+It will be the responsibility of Keystore and the Provisioner to construct the
+`CertificateRequest`. The HAL provides a method to generate the elements that
+need to be constructed on the secure side, which are the tag field of
+`MacedKeysToSign`, `VerifiedDeviceInfo`, and the ciphertext field of
+`ProtectedData`.
+
+### HAL
+
+The remote provisioning HAL provides a simple interface that can be implemented
+by multiple secure components that require remote provisioning. It would be
+slightly simpler to extend the KeyMint API, but that approach would only serve
+the needs of KeyMint, this is more general.
+
+NOTE the data structures defined in this HAL may look a little bloated and
+complex. This is because the COSE data structures are fully spelled-out; we
+could make it much more compact by not re-specifying the standardized elements
+and instead just referencing the standard, but it seems better to fully specify
+them. If the apparent complexity seems daunting, consider what the same would
+look like if traditional ASN.1 DER-based structures from X.509 and related
+standards were used and also fully elaborated.
+
+Please see the related HAL documentation directly in the source code at the
+following links:
+
+* [IRemotelyProvisionedComponent
+ HAL](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl)
+* [ProtectedData](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/ProtectedData.aidl)
+* [MacedPublicKey](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.aidl)
+* [RpcHardwareInfo](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl)
+* [DeviceInfo](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/DeviceInfo.aidl)
+
diff --git a/security/rkp/aidl/Android.bp b/security/rkp/aidl/Android.bp
new file mode 100644
index 0000000..5285477
--- /dev/null
+++ b/security/rkp/aidl/Android.bp
@@ -0,0 +1,41 @@
+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.rkp",
+ vendor_available: true,
+ srcs: [
+ // This HAL was originally part of keymint.
+ "android/hardware/security/keymint/*.aidl",
+
+ // in the future
+ // "android/hardware/security/rkp/*.aidl",
+ ],
+ stability: "vintf",
+ backend: {
+ java: {
+ min_sdk_version: "33",
+ apex_available: [
+ "//apex_available:platform",
+ "com.android.rkpd",
+ ],
+ },
+ rust: {
+ enabled: true,
+ },
+ },
+ versions_with_info: [
+ {
+ version: "1",
+ },
+ {
+ version: "2",
+ },
+ ],
+}
diff --git a/security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/.hash b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/.hash
new file mode 100644
index 0000000..404553b
--- /dev/null
+++ b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/.hash
@@ -0,0 +1 @@
+d285480d2e0002adc0ace80edf34aa725679512e
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/DeviceInfo.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/DeviceInfo.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/DeviceInfo.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/DeviceInfo.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/MacedPublicKey.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/MacedPublicKey.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/MacedPublicKey.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/MacedPublicKey.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/ProtectedData.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/ProtectedData.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/ProtectedData.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/ProtectedData.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/RpcHardwareInfo.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/1/android/hardware/security/keymint/RpcHardwareInfo.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/1/android/hardware/security/keymint/RpcHardwareInfo.aidl
diff --git a/security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/.hash b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/.hash
new file mode 100644
index 0000000..8700d33
--- /dev/null
+++ b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/.hash
@@ -0,0 +1 @@
+c8d34e56ae0807b61f028019622d8b60a37e0a8b
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/DeviceInfo.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/DeviceInfo.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/DeviceInfo.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/DeviceInfo.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/MacedPublicKey.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/MacedPublicKey.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/MacedPublicKey.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/MacedPublicKey.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/ProtectedData.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/ProtectedData.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/ProtectedData.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/ProtectedData.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/RpcHardwareInfo.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/2/android/hardware/security/keymint/RpcHardwareInfo.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/2/android/hardware/security/keymint/RpcHardwareInfo.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/DeviceInfo.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/DeviceInfo.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/DeviceInfo.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/MacedPublicKey.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/MacedPublicKey.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/MacedPublicKey.aidl
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/ProtectedData.aidl
similarity index 100%
rename from security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/ProtectedData.aidl
rename to security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/ProtectedData.aidl
diff --git a/security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
new file mode 100644
index 0000000..b1f99e1
--- /dev/null
+++ b/security/rkp/aidl/aidl_api/android.hardware.security.rkp/current/android/hardware/security/keymint/RpcHardwareInfo.aidl
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.keymint;
+/* @hide */
+@RustDerive(Clone=true, Eq=true, Hash=true, Ord=true, PartialEq=true, PartialOrd=true) @VintfStability
+parcelable RpcHardwareInfo {
+ int versionNumber;
+ @utf8InCpp String rpcAuthorName;
+ int supportedEekCurve = 0;
+ @nullable @utf8InCpp String uniqueId;
+ int supportedNumKeysInCsr = 4;
+ const int CURVE_NONE = 0;
+ const int CURVE_P256 = 1;
+ const int CURVE_25519 = 2;
+ const int MIN_SUPPORTED_NUM_KEYS_IN_CSR = 20;
+}
diff --git a/security/rkp/aidl/android/hardware/security/keymint/DeviceInfo.aidl b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfo.aidl
new file mode 100644
index 0000000..f0af619
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/DeviceInfo.aidl
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.keymint;
+
+/**
+ * DeviceInfo contains information about the device that's fed in as AAD in the signature of the
+ * device private key over the MAC key used for the bundle of public keys. These values are intended
+ * to be checked by the server to verify that the certificate signing request crafted by
+ * an IRemotelyProvisionedComponent HAL instance is coming from the expected device based
+ * on values initially uploaded during device manufacture in the factory.
+ * @hide
+ */
+@VintfStability
+parcelable DeviceInfo {
+ /**
+ * 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,
+ * "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
+ * "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/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
new file mode 100644
index 0000000..2fc780c
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl
@@ -0,0 +1,479 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.keymint;
+
+import android.hardware.security.keymint.DeviceInfo;
+import android.hardware.security.keymint.MacedPublicKey;
+import android.hardware.security.keymint.ProtectedData;
+import android.hardware.security.keymint.RpcHardwareInfo;
+
+/**
+ * An IRemotelyProvisionedComponent is a secure-side component for which certificates can be
+ * remotely provisioned. It provides an interface for generating asymmetric key pairs and then
+ * creating a CertificateRequest that contains the generated public keys, plus other information to
+ * authenticate the request origin. The CertificateRequest can be sent to a server, which can
+ * validate the request and create certificates.
+ *
+ * This interface does not provide any way to use the generated and certified key pairs. It's
+ * intended to be implemented by a HAL service that does other things with keys (e.g. KeyMint).
+ *
+ * The root of trust for secure provisioning is something called the Device Identifier Composition
+ * Engine (DICE) Chain. The DICE Chain is a chain of certificates, represented as COSE_Sign1 objects
+ * containing CBOR Web Tokens (CWT) which have descriptions about the stage of firmware being
+ * signed, including a COSE_Key representation of that stage's public key.
+ *
+ * DICE Chain Design
+ * =================
+ *
+ * For a more exhaustive and thorough look at DICE and the implementation used within this protocol,
+ * please see: https://pigweed.googlesource.com/open-dice/+/HEAD/docs/specification.md
+ *
+ * The DICE Chain is designed to mirror the boot stages of a device, and to prove the content and
+ * integrity of each firmware image. In a proper DICE Chain, each boot stage hashes its own private
+ * key material with the code and any relevant configuration parameters of the next stage to produce
+ * a Compound Device Identifier, or CDI, which is used as the secret key material for the next
+ * stage. From the CDI, a key pair - CDI_*_Pub and CDI_*_Priv - is derived and certified for the
+ * next stage by the current stages CDI_*_Priv. The next stage is then loaded and given its CDI and
+ * the DICE certificate chain generated so far in a manner that does not leak the previous stage's
+ * CDI_*_Priv or CDI to later boot stages. The final, "leaf" CDI certificate contains a public key,
+ * denoted CDI_Leaf_Pub, whose corresponding private key, denoted CDI_Leaf_Priv, is available for
+ * use by the IRemotelyProvisionedComponent.
+ *
+ * The root keypair is generated by immutable code (e.g. ROM), from a Unique Device Secret (UDS).
+ * The keypair that is generated from it can be referred to as the UDS_Pub/UDS_Priv keys. After the
+ * device-unique secret is used, it must be made unavailable to any later boot stage.
+ *
+ * In this way, booting the device incrementally builds a certificate chain that (a) identifies and
+ * validates the integrity of every stage and (b) contains a set of public keys that correspond to
+ * private keys, one known to each stage. Any stage can compute the secrets of all later stages
+ * (given the necessary input), but no stage can compute the secret of any preceding stage. Updating
+ * the firmware or configuration of any stage changes the key pair of that stage, and of all
+ * subsequent stages, and no attacker who compromised the previous version of the updated firmware
+ * can know or predict the post-update key pairs. It is recommended and expected that the DICE Chain
+ * is constructed using the Open Profile for DICE.
+ *
+ * When the provisioning server receives a message signed by CDI_Leaf_Priv and containing a DICE
+ * chain that chains from UDS_Pub to CDI_Leaf_Pub, it can be certain that (barring vulnerabilities
+ * in some boot stage), the CertificateRequest came from the device associated with UDS_Pub, running
+ * the specific software identified by the certificates in the chain. If the server has some
+ * mechanism for knowing the hash values of compromised stages, it can determine whether signing
+ * certificates is appropriate.
+ *
+ * Degenerate DICE Chains
+ * ======================
+ *
+ * While a proper DICE Chain, as described above, reflects the complete boot sequence from boot ROM
+ * to the secure area image of the IRemotelyProvisionedComponent, it's also possible to use a
+ * "degenerate" DICE Chain which consists only of a single, self-signed certificate containing the
+ * public key of a hardware-bound key pair. This is an appropriate solution for devices which
+ * haven't implemented everything necessary to produce a proper DICE Chain, but can derive a unique
+ * key pair in the secure area. In this degenerate case, UDS_Pub is the same as CDI_Leaf_Pub.
+ *
+ * DICE Chain Privacy
+ * ==================
+ *
+ * Because the DICE Chain constitutes an unspoofable, device-unique identifier, special care is
+ * taken to prevent its availability to entities who may wish to track devices. Three precautions
+ * are taken:
+ *
+ * 1) The DICE chain is only handled by the native Remote Key Provisioning Daemon (RKPD) service on
+ * the HLOS and is not exposed to apps running on device.
+ *
+ * 2) The CDI_Leaf_Priv key cannot be used to sign arbitrary data.
+ *
+ * 3) Backend infrastructure does not correlate UDS_Pub with the certificates signed and sent back
+ * to the device.
+ *
+ * Versioning
+ * ==========
+ * Versions 1 and 2 of the schema, as previously defined in DeviceInfo.aidl, diverge in
+ * functionality from Version 3. Version 3 removes the need to have testMode in function calls and
+ * deprecates the Endpoint Encryption Key (EEK) as well. Vendors implementing Version 1
+ * (Android S/12) or Version 2 (Android T/13) do not need to implement generateCertificateRequestV2.
+ * Vendors implementing Version 3 (Android U/14) need to implement generateCertificateRequestV2.
+ *
+ * For better coverage of changes from version to version, please see RKP_CHANGELOG.md in the root
+ * of the keymint interface directory.
+ *
+ * @hide
+ */
+@VintfStability
+interface IRemotelyProvisionedComponent {
+ const int STATUS_FAILED = 1;
+ const int STATUS_INVALID_MAC = 2;
+ // --------- START: Versions 1 and 2 Only ----------
+ const int STATUS_PRODUCTION_KEY_IN_TEST_REQUEST = 3;
+ const int STATUS_TEST_KEY_IN_PRODUCTION_REQUEST = 4;
+ const int STATUS_INVALID_EEK = 5;
+ // --------- END: Versions 1 and 2 Only ------------
+ const int STATUS_REMOVED = 6;
+
+ /**
+ * @return info which contains information about the underlying IRemotelyProvisionedComponent
+ * hardware, such as version number, component name, author name, and supported curve.
+ */
+ RpcHardwareInfo getHardwareInfo();
+
+ /**
+ * generateKeyPair generates a new ECDSA P-256 key pair that can be attested by the remote
+ * server.
+ *
+ * @param in boolean testMode this field is now deprecated. It is ignored by the implementation
+ * in v3, but retained to simplify backwards compatibility support. V1 and V2
+ * implementations must still respect the testMode flag.
+ *
+ * testMode indicates whether the generated key is for testing only. Test keys
+ * are marked (see the definition of PublicKey in the MacedPublicKey structure) to
+ * prevent them from being confused with production keys.
+ *
+ * @param out MacedPublicKey macedPublicKey contains the public key of the generated key pair,
+ * MACed so that generateCertificateRequest can easily verify, without the
+ * privateKeyHandle, that the contained public key is for remote certification.
+ *
+ * @return data representing a handle to the private key. The format is implementation-defined,
+ * but note that specific services may define a required format. KeyMint does.
+ */
+ byte[] generateEcdsaP256KeyPair(in boolean testMode, out MacedPublicKey macedPublicKey);
+
+ /**
+ * This method has been removed in version 3 of the HAL. The header is kept around for
+ * backwards compatibility purposes. From v3, this method should raise a
+ * ServiceSpecificException with an error code of STATUS_REMOVED.
+ *
+ * For v1 and v2 implementations:
+ * generateCertificateRequest creates a certificate request to be sent to the provisioning
+ * server.
+ *
+ * @param in boolean testMode indicates whether the generated certificate request is for testing
+ * only.
+ *
+ * @param in MacedPublicKey[] keysToSign contains the set of keys to certify. The
+ * IRemotelyProvisionedComponent must validate the MACs on each key. If any entry in the
+ * array lacks a valid MAC, the method must return STATUS_INVALID_MAC.
+ *
+ * If testMode is true, the keysToCertify array must contain only keys flagged as test
+ * keys. Otherwise, the method must return STATUS_PRODUCTION_KEY_IN_TEST_REQUEST.
+ *
+ * If testMode is false, the keysToCertify array must not contain any keys flagged as
+ * test keys. Otherwise, the method must return STATUS_TEST_KEY_IN_PRODUCTION_REQUEST.
+ *
+ * @param in endpointEncryptionKey contains an X25519 public key which will be used to encrypt
+ * the BCC. For flexibility, this is represented as a certificate chain, represented as a
+ * CBOR array of COSE_Sign1 objects, ordered from root to leaf. The leaf contains the
+ * X25519 encryption key, each other element is an Ed25519 key signing the next in the
+ * chain. The root is self-signed. An implementor may also choose to use P256 as an
+ * alternative curve for signing and encryption instead of Curve 25519.
+ *
+ * EekChain = [ + SignedSignatureKey, SignedEek ]
+ *
+ * SignedSignatureKey = [ ; COSE_Sign1
+ * protected: bstr .cbor {
+ * 1 : AlgorithmEdDSA / AlgorithmES256, ; Algorithm
+ * },
+ * unprotected: {},
+ * payload: bstr .cbor SignatureKeyEd25519 /
+ * bstr .cbor SignatureKeyP256,
+ * signature: bstr PureEd25519(.cbor SignatureKeySignatureInput) /
+ * bstr ECDSA(.cbor SignatureKeySignatureInput)
+ * ]
+ *
+ * SignatureKeyEd25519 = { ; COSE_Key
+ * 1 : 1, ; Key type : Octet Key Pair
+ * 3 : AlgorithmEdDSA, ; Algorithm
+ * -1 : 6, ; Curve : Ed25519
+ * -2 : bstr ; Ed25519 public key
+ * }
+ *
+ * SignatureKeyP256 = { ; COSE_Key
+ * 1 : 2, ; Key type : EC2
+ * 3 : AlgorithmES256, ; Algorithm
+ * -1 : 1, ; Curve: P256
+ * -2 : bstr, ; X coordinate
+ * -3 : bstr ; Y coordinate
+ * }
+ *
+ * SignatureKeySignatureInput = [
+ * context: "Signature1",
+ * body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ * external_aad: bstr .size 0,
+ * payload: bstr .cbor SignatureKeyEd25519 /
+ * bstr .cbor SignatureKeyP256
+ * ]
+ *
+ * ; COSE_Sign1
+ * SignedEek = [
+ * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ * unprotected: {},
+ * payload: bstr .cbor EekX25519 / .cbor EekP256,
+ * signature: bstr PureEd25519(.cbor EekSignatureInput) /
+ * bstr ECDSA(.cbor EekSignatureInput)
+ * ]
+ *
+ * EekX25519 = { ; COSE_Key
+ * 1 : 1, ; Key type : Octet Key Pair
+ * 2 : bstr ; KID : EEK ID
+ * 3 : -25, ; Algorithm : ECDH-ES + HKDF-256
+ * -1 : 4, ; Curve : X25519
+ * -2 : bstr ; X25519 public key
+ * }
+ *
+ * EekP256 = { ; COSE_Key
+ * 1 : 2, ; Key type : EC2
+ * 2 : bstr ; KID : EEK ID
+ * 3 : -25, ; Algorithm : ECDH-ES + HKDF-256
+ * -1 : 1, ; Curve : P256
+ * -2 : bstr ; Sender X coordinate
+ * -3 : bstr ; Sender Y coordinate
+ * }
+ *
+ * EekSignatureInput = [
+ * context: "Signature1",
+ * body_protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ * external_aad: bstr .size 0,
+ * payload: bstr .cbor EekX25519 / .cbor EekP256
+ * ]
+ *
+ * AlgorithmES256 = -7 ; RFC 8152 section 8.1
+ * AlgorithmEdDSA = -8 ; RFC 8152 section 8.2
+ *
+ * If the contents of endpointEncryptionKey do not match the SignedEek structure above,
+ * the method must return STATUS_INVALID_EEK.
+ *
+ * If testMode is true, the method must ignore the length and content of the signatures
+ * in the chain, which implies that it must not attempt to validate the signature.
+ *
+ * If testMode is false, the method must validate the chain signatures, and must verify
+ * that the public key in the root certificate is in its pre-configured set of
+ * authorized EEK root keys. If the public key is not in the database, or if signature
+ * verification fails, the method must return STATUS_INVALID_EEK.
+ *
+ * @param in challenge contains a byte string from the provisioning server that must be signed
+ * by the secure area. See the description of the 'signature' output parameter for
+ * details.
+ *
+ * @param out DeviceInfo contains the VerifiedDeviceInfo portion of the DeviceInfo array in
+ * CertificateRequest. The structure is described within the DeviceInfo.aidl file.
+ *
+ * @param out ProtectedData contains the encrypted BCC and the ephemeral MAC key used to
+ * authenticate the keysToSign (see keysToSignMac output argument).
+ *
+ * @return The MAC of KeysToSign in the CertificateRequest structure. Specifically, it contains:
+ *
+ * HMAC-256(EK_mac, .cbor KeysToMacStructure)
+ *
+ * Where EK_mac is an ephemeral MAC key, found in ProtectedData (see below). The MACed
+ * data is the "tag" field of a COSE_Mac0 structure like:
+ *
+ * MacedKeys = [ ; COSE_Mac0
+ * protected : bstr .cbor {
+ * 1 : 5, ; Algorithm : HMAC-256
+ * },
+ * unprotected : {},
+ * ; Payload is PublicKeys from keysToSign argument, in provided order.
+ * payload: bstr .cbor [ * PublicKey ],
+ * tag: bstr
+ * ]
+ *
+ * KeysToMacStructure = [
+ * context : "MAC0",
+ * protected : bstr .cbor { 1 : 5 }, ; Algorithm : HMAC-256
+ * external_aad : bstr .size 0,
+ * ; Payload is PublicKeys from keysToSign argument, in provided order.
+ * payload : bstr .cbor [ * PublicKey ]
+ * ]
+ */
+ byte[] generateCertificateRequest(in boolean testMode, in MacedPublicKey[] keysToSign,
+ in byte[] endpointEncryptionCertChain, in byte[] challenge, out DeviceInfo deviceInfo,
+ out ProtectedData protectedData);
+
+ /**
+ * generateCertificateRequestV2 creates a certificate signing request to be sent to the
+ * provisioning server.
+ *
+ * @param in MacedPublicKey[] keysToSign contains the set of keys to certify. The
+ * IRemotelyProvisionedComponent must validate the MACs on each key. If any entry in the
+ * array lacks a valid MAC, the method must return STATUS_INVALID_MAC.
+ *
+ * @param in challenge contains a byte string from the provisioning server which will be
+ * included in the signed data of the CSR structure. Different provisioned backends may
+ * use different semantic data for this field, but the supported sizes must be between 32
+ * and 64 bytes, inclusive.
+ *
+ * @return the following CBOR Certificate Signing Request (Csr) serialized into a byte array:
+ *
+ * Csr = AuthenticatedRequest<CsrPayload>
+ *
+ * CsrPayload = [ ; CBOR Array defining the payload for Csr
+ * version: 3, ; The CsrPayload CDDL Schema version.
+ * CertificateType, ; The type of certificate being requested.
+ * DeviceInfo, ; Defined in DeviceInfo.aidl
+ * KeysToSign, ; Provided by the method parameters
+ * ]
+ *
+ * ; A tstr identifying the type of certificate. The set of supported certificate types may
+ * ; be extended without requiring a version bump of the HAL. Custom certificate types may
+ * ; be used, but the provisioning server may reject the request for an unknown certificate
+ * ; type. The currently defined certificate types are:
+ * ; - "widevine"
+ * ; - "keymint"
+ * CertificateType = tstr
+ *
+ * KeysToSign = [ * PublicKey ] ; Please see MacedPublicKey.aidl for the PublicKey definition.
+ *
+ * AuthenticatedRequest<T> = [
+ * version: 1, ; The AuthenticatedRequest CDDL Schema version.
+ * UdsCerts,
+ * DiceCertChain,
+ * SignedData<[
+ * challenge: bstr .size (32..64), ; Provided by the method parameters
+ * bstr .cbor T,
+ * ]>,
+ * ]
+ *
+ * ; COSE_Sign1 (untagged)
+ * SignedData<Data> = [
+ * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ * unprotected: {},
+ * payload: bstr .cbor Data / nil,
+ * signature: bstr ; PureEd25519(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct<Data>) /
+ * ; ECDSA(CDI_Leaf_Priv, bstr .cbor SignedDataSigStruct<Data>)
+ * ]
+ *
+ * ; Sig_structure for SignedData
+ * SignedDataSigStruct<Data> = [
+ * context: "Signature1",
+ * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ * external_aad: bstr .size 0,
+ * payload: bstr .cbor Data / nil,
+ * ]
+ *
+ * ; UdsCerts allows the platform to provide additional certifications for the UDS_Pub. For
+ * ; example, this could be provided by the hardware vendor, who certifies all of their chips.
+ * ; The SignerName is a free-form string describing who generated the signature. The root
+ * ; certificate will need to be communicated to the verifier out of band, along with the
+ * ; SignerName that is expected for the given root certificate.
+ * UdsCerts = {
+ * * SignerName => UdsCertChain
+ * }
+ *
+ * ; SignerName is a string identifier that indicates both the signing authority as
+ * ; well as the format of the UdsCertChain
+ * SignerName = tstr
+ *
+ * UdsCertChain = [
+ * 2* X509Certificate ; Root -> ... -> Leaf. "Root" is the vendor self-signed
+ * ; cert, "Leaf" contains UDS_Public. There may also be
+ * ; intermediate certificates between Root and Leaf.
+ * ]
+ *
+ * ; A bstr containing a DER-encoded X.509 certificate (RSA, NIST P-curve, or EdDSA)
+ * X509Certificate = bstr
+ *
+ * ; The DICE Chain contains measurements about the device firmware.
+ * ; The first entry in the DICE Chain is the UDS_Pub, encoded as a COSE_key. All entries
+ * ; after the first describe a link in the boot chain (e.g. bootloaders: BL1, BL2, ... BLN)
+ * ; Note that there is no DiceChainEntry for UDS_pub, only a "bare" COSE_key.
+ * DiceCertChain = [
+ * PubKeyEd25519 / PubKeyECDSA256, ; UDS_Pub
+ * + DiceChainEntry, ; First CDI_Certificate -> Last CDI_Certificate
+ * ; Last certificate corresponds to KeyMint's DICE key.
+ * ]
+ *
+ * ; This is the signed payload for each entry in the DICE chain. Note that the "Configuration
+ * ; Input Values" described by the Open Profile are not used here. Instead, the DICE chain
+ * ; defines its own configuration values for the Configuration Descriptor field. See
+ * ; the Open Profile for DICE for more details on the fields. SHA256 and SHA512 are acceptable
+ * ; hash algorithms. The digest bstr values in the payload are the digest values without any
+ * ; padding. Note that for SHA256, this implies the digest bstr is 32 bytes. This is an
+ * ; intentional, minor deviation from Open Profile for DICE, which specifies all digests are
+ * ; 64 bytes.
+ * DiceChainEntryPayload = { ; CWT [RFC8392]
+ * 1 : tstr, ; Issuer
+ * 2 : tstr, ; Subject
+ * -4670552 : bstr .cbor PubKeyEd25519 /
+ * bstr .cbor PubKeyECDSA256, ; Subject Public Key
+ * -4670553 : bstr ; Key Usage
+ *
+ * ; NOTE: All of the following fields may be omitted for a "Degenerate DICE Chain", as
+ * ; described above.
+ * -4670545 : bstr, ; Code Hash
+ * ? -4670546 : bstr, ; Code Descriptor
+ * ? -4670547 : bstr, ; Configuration Hash
+ * -4670548 : bstr .cbor { ; Configuration Descriptor
+ * ? -70002 : tstr, ; Component name
+ * ? -70003 : int, ; Firmware version
+ * ? -70004 : null, ; Resettable
+ * },
+ * -4670549 : bstr, ; Authority Hash
+ * ? -4670550 : bstr, ; Authority Descriptor
+ * -4670551 : bstr, ; Mode
+ * }
+ *
+ * ; Each entry in the DICE chain is a DiceChainEntryPayload signed by the key from the previous
+ * ; entry in the DICE chain array.
+ * DiceChainEntry = [ ; COSE_Sign1 (untagged)
+ * protected : bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ * unprotected: {},
+ * payload: bstr .cbor DiceChainEntryPayload,
+ * signature: bstr ; PureEd25519(SigningKey, bstr .cbor DiceChainEntryInput) /
+ * ; ECDSA(SigningKey, bstr .cbor DiceChainEntryInput)
+ * ; See RFC 8032 for details of how to encode the signature value
+ * ; for Ed25519.
+ * ]
+ *
+ * DiceChainEntryInput = [
+ * context: "Signature1",
+ * protected: bstr .cbor { 1 : AlgorithmEdDSA / AlgorithmES256 },
+ * external_aad: bstr .size 0,
+ * payload: bstr .cbor DiceChainEntryPayload
+ * ]
+ *
+ * ; The following section defines some types that are reused throughout the above
+ * ; data structures.
+ * PubKeyX25519 = { ; COSE_Key
+ * 1 : 1, ; Key type : Octet Key Pair
+ * -1 : 4, ; Curve : X25519
+ * -2 : bstr ; Sender X25519 public key
+ * }
+ *
+ * PubKeyEd25519 = { ; COSE_Key
+ * 1 : 1, ; Key type : octet key pair
+ * 3 : AlgorithmEdDSA, ; Algorithm : EdDSA
+ * -1 : 6, ; Curve : Ed25519
+ * -2 : bstr ; X coordinate, little-endian
+ * }
+ *
+ * PubKeyEcdhP256 = { ; COSE_Key
+ * 1 : 2, ; Key type : EC2
+ * -1 : 1, ; Curve : P256
+ * -2 : bstr ; Sender X coordinate
+ * -3 : bstr ; Sender Y coordinate
+ * }
+ *
+ * PubKeyECDSA256 = { ; COSE_Key
+ * 1 : 2, ; Key type : EC2
+ * 3 : AlgorithmES256, ; Algorithm : ECDSA w/ SHA-256
+ * -1 : 1, ; Curve: P256
+ * -2 : bstr, ; X coordinate
+ * -3 : bstr ; Y coordinate
+ * }
+ *
+ * AlgorithmES256 = -7
+ * AlgorithmEdDSA = -8
+ */
+ byte[] generateCertificateRequestV2(in MacedPublicKey[] keysToSign, in byte[] challenge);
+}
diff --git a/security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl b/security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
similarity index 100%
rename from security/keymint/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
rename to security/rkp/aidl/android/hardware/security/keymint/MacedPublicKey.aidl
diff --git a/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl b/security/rkp/aidl/android/hardware/security/keymint/ProtectedData.aidl
similarity index 100%
rename from security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl
rename to security/rkp/aidl/android/hardware/security/keymint/ProtectedData.aidl
diff --git a/security/rkp/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl b/security/rkp/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
new file mode 100644
index 0000000..d0b059d
--- /dev/null
+++ b/security/rkp/aidl/android/hardware/security/keymint/RpcHardwareInfo.aidl
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.security.keymint;
+
+/**
+ * RpcHardwareInfo is the hardware information returned by calling RemotelyProvisionedComponent
+ * getHardwareInfo()
+ * @hide
+ */
+@VintfStability
+@RustDerive(Clone=true, Eq=true, PartialEq=true, Ord=true, PartialOrd=true, Hash=true)
+parcelable RpcHardwareInfo {
+ const int CURVE_NONE = 0;
+ const int CURVE_P256 = 1;
+ const int CURVE_25519 = 2;
+
+ /**
+ * Implementation version of the remotely provisioned component hardware. The version provided
+ * here must match the version reported in the CsrPayload produced by the HAL interface. This
+ * field primarily acts as a convenience for the system components interacting with the HALs.
+ */
+ int versionNumber;
+
+ /**
+ * rpcAuthorName is the name of the author of the IRemotelyProvisionedComponent implementation
+ * (organization name, not individual). This name is implementation defined, so it can be used
+ * to distinguish between different implementations from the same author.
+ */
+ @utf8InCpp String rpcAuthorName;
+
+ /**
+ * NOTE: This field is no longer used as of version 3 of the HAL interface. This is because the
+ * Endpoint Encryption Key is no longer used in the provisioning scheme.
+ *
+ * supportedEekCurve returns an int representing which curve is supported for validating
+ * signatures over the Endpoint Encryption Key certificate chain and for using the corresponding
+ * signed encryption key in ECDH. Only one curve should be supported, with preference for 25519
+ * if it's available. These values are defined as constants above.
+ *
+ * CURVE_NONE is made the default to help ensure that an implementor doesn't accidentally forget
+ * to provide the correct information here, as the VTS tests will check to make certain that
+ * 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, and it must be consistent across all devices.
+ * It's critical that this identifier not be usable to uniquely identify a specific 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.
+ *
+ * A recommended construction for this value is "[Vendor] [Component Name] [Major Version]",
+ * e.g. "Google Trusty KeyMint 1".
+ *
+ * This field was added in API version 2.
+ *
+ */
+ @nullable @utf8InCpp String uniqueId;
+
+ /**
+ * supportedNumKeysInCsr is the maximum number of keys in a CSR that this implementation can
+ * support. This value is implementation defined.
+ *
+ * From version 3 onwards, supportedNumKeysInCsr must be larger or equal to
+ * MIN_SUPPORTED_NUM_KEYS_IN_CSR.
+ *
+ * The default value was chosen as the value enforced by the VTS test in versions 1 and 2 of
+ * this interface.
+ */
+ const int MIN_SUPPORTED_NUM_KEYS_IN_CSR = 20;
+ int supportedNumKeysInCsr = 4;
+}
diff --git a/sensors/aidl/Android.bp b/sensors/aidl/Android.bp
index d04017c..9673190 100644
--- a/sensors/aidl/Android.bp
+++ b/sensors/aidl/Android.bp
@@ -11,6 +11,7 @@
name: "android.hardware.sensors",
vendor_available: true,
srcs: ["android/hardware/sensors/*.aidl"],
+ host_supported: true,
imports: [
"android.hardware.common-V2",
"android.hardware.common.fmq-V1",
diff --git a/sensors/aidl/convert/Android.bp b/sensors/aidl/convert/Android.bp
new file mode 100644
index 0000000..d47de8e
--- /dev/null
+++ b/sensors/aidl/convert/Android.bp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package {
+ // 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: "android.hardware.sensors-V1-convert",
+ vendor_available: true,
+ host_supported: true,
+ srcs: ["convert.cpp"],
+ export_include_dirs: ["include"],
+ shared_libs: [
+ "liblog",
+ "libcutils",
+ "libhardware",
+ "libbase",
+ "libutils",
+ "android.hardware.sensors-V1-ndk",
+ ],
+ local_include_dirs: ["include/aidl/sensors"],
+ export_shared_lib_headers: [
+ "libhardware",
+ ],
+}
diff --git a/sensors/aidl/convert/convert.cpp b/sensors/aidl/convert/convert.cpp
new file mode 100644
index 0000000..415f435
--- /dev/null
+++ b/sensors/aidl/convert/convert.cpp
@@ -0,0 +1,496 @@
+/*
+ * 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/sensors/convert.h"
+#include "android-base/logging.h"
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace implementation {
+
+using aidl::android::hardware::sensors::AdditionalInfo;
+using aidl::android::hardware::sensors::DynamicSensorInfo;
+using aidl::android::hardware::sensors::Event;
+using aidl::android::hardware::sensors::ISensors;
+using aidl::android::hardware::sensors::SensorInfo;
+using aidl::android::hardware::sensors::SensorStatus;
+using aidl::android::hardware::sensors::SensorType;
+
+status_t convertToStatus(ndk::ScopedAStatus status) {
+ if (status.isOk()) {
+ return OK;
+ } else {
+ switch (status.getExceptionCode()) {
+ case EX_ILLEGAL_ARGUMENT: {
+ return BAD_VALUE;
+ }
+ case EX_SECURITY: {
+ return PERMISSION_DENIED;
+ }
+ case EX_UNSUPPORTED_OPERATION: {
+ return INVALID_OPERATION;
+ }
+ case EX_SERVICE_SPECIFIC: {
+ switch (status.getServiceSpecificError()) {
+ case ISensors::ERROR_BAD_VALUE: {
+ return BAD_VALUE;
+ }
+ case ISensors::ERROR_NO_MEMORY: {
+ return NO_MEMORY;
+ }
+ default: {
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+ default: {
+ return UNKNOWN_ERROR;
+ }
+ }
+ }
+}
+
+void convertToSensor(const SensorInfo& src, sensor_t* dst) {
+ dst->name = strdup(src.name.c_str());
+ dst->vendor = strdup(src.vendor.c_str());
+ dst->version = src.version;
+ dst->handle = src.sensorHandle;
+ dst->type = (int)src.type;
+ dst->maxRange = src.maxRange;
+ dst->resolution = src.resolution;
+ dst->power = src.power;
+ dst->minDelay = src.minDelayUs;
+ dst->fifoReservedEventCount = src.fifoReservedEventCount;
+ dst->fifoMaxEventCount = src.fifoMaxEventCount;
+ dst->stringType = strdup(src.typeAsString.c_str());
+ dst->requiredPermission = strdup(src.requiredPermission.c_str());
+ dst->maxDelay = src.maxDelayUs;
+ dst->flags = src.flags;
+ dst->reserved[0] = dst->reserved[1] = 0;
+}
+
+void convertToSensorEvent(const Event& src, sensors_event_t* dst) {
+ *dst = {.version = sizeof(sensors_event_t),
+ .sensor = src.sensorHandle,
+ .type = (int32_t)src.sensorType,
+ .reserved0 = 0,
+ .timestamp = src.timestamp};
+
+ switch (src.sensorType) {
+ case SensorType::META_DATA: {
+ // Legacy HALs expect the handle reference in the meta data field.
+ // Copy it over from the handle of the event.
+ dst->meta_data.what = (int32_t)src.payload.get<Event::EventPayload::meta>().what;
+ dst->meta_data.sensor = src.sensorHandle;
+ // Set the sensor handle to 0 to maintain compatibility.
+ dst->sensor = 0;
+ break;
+ }
+
+ case SensorType::ACCELEROMETER:
+ case SensorType::MAGNETIC_FIELD:
+ case SensorType::ORIENTATION:
+ case SensorType::GYROSCOPE:
+ case SensorType::GRAVITY:
+ case SensorType::LINEAR_ACCELERATION: {
+ dst->acceleration.x = src.payload.get<Event::EventPayload::vec3>().x;
+ dst->acceleration.y = src.payload.get<Event::EventPayload::vec3>().y;
+ dst->acceleration.z = src.payload.get<Event::EventPayload::vec3>().z;
+ dst->acceleration.status = (int32_t)src.payload.get<Event::EventPayload::vec3>().status;
+ break;
+ }
+
+ case SensorType::GAME_ROTATION_VECTOR: {
+ dst->data[0] = src.payload.get<Event::EventPayload::vec4>().x;
+ dst->data[1] = src.payload.get<Event::EventPayload::vec4>().y;
+ dst->data[2] = src.payload.get<Event::EventPayload::vec4>().z;
+ dst->data[3] = src.payload.get<Event::EventPayload::vec4>().w;
+ break;
+ }
+
+ case SensorType::ROTATION_VECTOR:
+ case SensorType::GEOMAGNETIC_ROTATION_VECTOR: {
+ dst->data[0] = src.payload.get<Event::EventPayload::data>().values[0];
+ dst->data[1] = src.payload.get<Event::EventPayload::data>().values[1];
+ dst->data[2] = src.payload.get<Event::EventPayload::data>().values[2];
+ dst->data[3] = src.payload.get<Event::EventPayload::data>().values[3];
+ dst->data[4] = src.payload.get<Event::EventPayload::data>().values[4];
+ break;
+ }
+
+ case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+ case SensorType::GYROSCOPE_UNCALIBRATED:
+ case SensorType::ACCELEROMETER_UNCALIBRATED: {
+ dst->uncalibrated_gyro.x_uncalib = src.payload.get<Event::EventPayload::uncal>().x;
+ dst->uncalibrated_gyro.y_uncalib = src.payload.get<Event::EventPayload::uncal>().y;
+ dst->uncalibrated_gyro.z_uncalib = src.payload.get<Event::EventPayload::uncal>().z;
+ dst->uncalibrated_gyro.x_bias = src.payload.get<Event::EventPayload::uncal>().xBias;
+ dst->uncalibrated_gyro.y_bias = src.payload.get<Event::EventPayload::uncal>().yBias;
+ dst->uncalibrated_gyro.z_bias = src.payload.get<Event::EventPayload::uncal>().zBias;
+ break;
+ }
+
+ case SensorType::HINGE_ANGLE:
+ case SensorType::DEVICE_ORIENTATION:
+ case SensorType::LIGHT:
+ case SensorType::PRESSURE:
+ case SensorType::PROXIMITY:
+ case SensorType::RELATIVE_HUMIDITY:
+ case SensorType::AMBIENT_TEMPERATURE:
+ case SensorType::SIGNIFICANT_MOTION:
+ case SensorType::STEP_DETECTOR:
+ case SensorType::TILT_DETECTOR:
+ case SensorType::WAKE_GESTURE:
+ case SensorType::GLANCE_GESTURE:
+ case SensorType::PICK_UP_GESTURE:
+ case SensorType::WRIST_TILT_GESTURE:
+ case SensorType::STATIONARY_DETECT:
+ case SensorType::MOTION_DETECT:
+ case SensorType::HEART_BEAT:
+ case SensorType::LOW_LATENCY_OFFBODY_DETECT: {
+ dst->data[0] = src.payload.get<Event::EventPayload::scalar>();
+ break;
+ }
+
+ case SensorType::STEP_COUNTER: {
+ dst->u64.step_counter = src.payload.get<Event::EventPayload::stepCount>();
+ break;
+ }
+
+ case SensorType::HEART_RATE: {
+ dst->heart_rate.bpm = src.payload.get<Event::EventPayload::heartRate>().bpm;
+ dst->heart_rate.status =
+ (int8_t)src.payload.get<Event::EventPayload::heartRate>().status;
+ break;
+ }
+
+ case SensorType::POSE_6DOF: { // 15 floats
+ for (size_t i = 0; i < 15; ++i) {
+ dst->data[i] = src.payload.get<Event::EventPayload::pose6DOF>().values[i];
+ }
+ break;
+ }
+
+ case SensorType::DYNAMIC_SENSOR_META: {
+ dst->dynamic_sensor_meta.connected =
+ src.payload.get<Event::EventPayload::dynamic>().connected;
+ dst->dynamic_sensor_meta.handle =
+ src.payload.get<Event::EventPayload::dynamic>().sensorHandle;
+ dst->dynamic_sensor_meta.sensor = NULL; // to be filled in later
+
+ memcpy(dst->dynamic_sensor_meta.uuid,
+ src.payload.get<Event::EventPayload::dynamic>().uuid.values.data(), 16);
+
+ break;
+ }
+
+ case SensorType::ADDITIONAL_INFO: {
+ const AdditionalInfo& srcInfo = src.payload.get<Event::EventPayload::additional>();
+
+ additional_info_event_t* dstInfo = &dst->additional_info;
+ dstInfo->type = (int32_t)srcInfo.type;
+ dstInfo->serial = srcInfo.serial;
+
+ switch (srcInfo.payload.getTag()) {
+ case AdditionalInfo::AdditionalInfoPayload::Tag::dataInt32: {
+ const auto& values =
+ srcInfo.payload.get<AdditionalInfo::AdditionalInfoPayload::dataInt32>()
+ .values;
+ CHECK_EQ(values.size() * sizeof(int32_t), sizeof(dstInfo->data_int32));
+ memcpy(dstInfo->data_int32, values.data(), sizeof(dstInfo->data_int32));
+ break;
+ }
+ case AdditionalInfo::AdditionalInfoPayload::Tag::dataFloat: {
+ const auto& values =
+ srcInfo.payload.get<AdditionalInfo::AdditionalInfoPayload::dataFloat>()
+ .values;
+ CHECK_EQ(values.size() * sizeof(float), sizeof(dstInfo->data_float));
+ memcpy(dstInfo->data_float, values.data(), sizeof(dstInfo->data_float));
+ break;
+ }
+ default: {
+ LOG(ERROR) << "Invalid sensor additional info tag: ",
+ (int)srcInfo.payload.getTag();
+ }
+ }
+ break;
+ }
+
+ case SensorType::HEAD_TRACKER: {
+ const auto& ht = src.payload.get<Event::EventPayload::headTracker>();
+ dst->head_tracker.rx = ht.rx;
+ dst->head_tracker.ry = ht.ry;
+ dst->head_tracker.rz = ht.rz;
+ dst->head_tracker.vx = ht.vx;
+ dst->head_tracker.vy = ht.vy;
+ dst->head_tracker.vz = ht.vz;
+ dst->head_tracker.discontinuity_count = ht.discontinuityCount;
+ break;
+ }
+
+ case SensorType::ACCELEROMETER_LIMITED_AXES:
+ case SensorType::GYROSCOPE_LIMITED_AXES:
+ dst->limited_axes_imu.x = src.payload.get<Event::EventPayload::limitedAxesImu>().x;
+ dst->limited_axes_imu.y = src.payload.get<Event::EventPayload::limitedAxesImu>().y;
+ dst->limited_axes_imu.z = src.payload.get<Event::EventPayload::limitedAxesImu>().z;
+ dst->limited_axes_imu.x_supported =
+ src.payload.get<Event::EventPayload::limitedAxesImu>().xSupported;
+ dst->limited_axes_imu.y_supported =
+ src.payload.get<Event::EventPayload::limitedAxesImu>().ySupported;
+ dst->limited_axes_imu.z_supported =
+ src.payload.get<Event::EventPayload::limitedAxesImu>().zSupported;
+ break;
+
+ case SensorType::ACCELEROMETER_LIMITED_AXES_UNCALIBRATED:
+ case SensorType::GYROSCOPE_LIMITED_AXES_UNCALIBRATED:
+ dst->limited_axes_imu_uncalibrated.x_uncalib =
+ src.payload.get<Event::EventPayload::limitedAxesImuUncal>().x;
+ dst->limited_axes_imu_uncalibrated.y_uncalib =
+ src.payload.get<Event::EventPayload::limitedAxesImuUncal>().y;
+ dst->limited_axes_imu_uncalibrated.z_uncalib =
+ src.payload.get<Event::EventPayload::limitedAxesImuUncal>().z;
+ dst->limited_axes_imu_uncalibrated.x_bias =
+ src.payload.get<Event::EventPayload::limitedAxesImuUncal>().xBias;
+ dst->limited_axes_imu_uncalibrated.y_bias =
+ src.payload.get<Event::EventPayload::limitedAxesImuUncal>().yBias;
+ dst->limited_axes_imu_uncalibrated.z_bias =
+ src.payload.get<Event::EventPayload::limitedAxesImuUncal>().zBias;
+ dst->limited_axes_imu_uncalibrated.x_supported =
+ src.payload.get<Event::EventPayload::limitedAxesImuUncal>().xSupported;
+ dst->limited_axes_imu_uncalibrated.y_supported =
+ src.payload.get<Event::EventPayload::limitedAxesImuUncal>().ySupported;
+ dst->limited_axes_imu_uncalibrated.z_supported =
+ src.payload.get<Event::EventPayload::limitedAxesImuUncal>().zSupported;
+ break;
+
+ case SensorType::HEADING:
+ dst->heading.heading = src.payload.get<Event::EventPayload::heading>().heading;
+ dst->heading.accuracy = src.payload.get<Event::EventPayload::heading>().accuracy;
+ break;
+
+ default: {
+ CHECK_GE((int32_t)src.sensorType, (int32_t)SensorType::DEVICE_PRIVATE_BASE);
+
+ memcpy(dst->data, src.payload.get<Event::EventPayload::data>().values.data(),
+ 16 * sizeof(float));
+ break;
+ }
+ }
+}
+
+void convertFromSensorEvent(const sensors_event_t& src, Event* dst) {
+ *dst = {
+ .timestamp = src.timestamp,
+ .sensorHandle = src.sensor,
+ .sensorType = (SensorType)src.type,
+ };
+
+ switch (dst->sensorType) {
+ case SensorType::META_DATA: {
+ Event::EventPayload::MetaData meta;
+ meta.what = (Event::EventPayload::MetaData::MetaDataEventType)src.meta_data.what;
+ // Legacy HALs contain the handle reference in the meta data field.
+ // Copy that over to the handle of the event. In legacy HALs this
+ // field was expected to be 0.
+ dst->sensorHandle = src.meta_data.sensor;
+ dst->payload.set<Event::EventPayload::Tag::meta>(meta);
+ break;
+ }
+
+ case SensorType::ACCELEROMETER:
+ case SensorType::MAGNETIC_FIELD:
+ case SensorType::ORIENTATION:
+ case SensorType::GYROSCOPE:
+ case SensorType::GRAVITY:
+ case SensorType::LINEAR_ACCELERATION: {
+ Event::EventPayload::Vec3 vec3;
+ vec3.x = src.acceleration.x;
+ vec3.y = src.acceleration.y;
+ vec3.z = src.acceleration.z;
+ vec3.status = (SensorStatus)src.acceleration.status;
+ dst->payload.set<Event::EventPayload::Tag::vec3>(vec3);
+ break;
+ }
+
+ case SensorType::GAME_ROTATION_VECTOR: {
+ Event::EventPayload::Vec4 vec4;
+ vec4.x = src.data[0];
+ vec4.y = src.data[1];
+ vec4.z = src.data[2];
+ vec4.w = src.data[3];
+ dst->payload.set<Event::EventPayload::Tag::vec4>(vec4);
+ break;
+ }
+
+ case SensorType::ROTATION_VECTOR:
+ case SensorType::GEOMAGNETIC_ROTATION_VECTOR: {
+ Event::EventPayload::Data data;
+ memcpy(data.values.data(), src.data, 5 * sizeof(float));
+ dst->payload.set<Event::EventPayload::Tag::data>(data);
+ break;
+ }
+
+ case SensorType::MAGNETIC_FIELD_UNCALIBRATED:
+ case SensorType::GYROSCOPE_UNCALIBRATED:
+ case SensorType::ACCELEROMETER_UNCALIBRATED: {
+ Event::EventPayload::Uncal uncal;
+ uncal.x = src.uncalibrated_gyro.x_uncalib;
+ uncal.y = src.uncalibrated_gyro.y_uncalib;
+ uncal.z = src.uncalibrated_gyro.z_uncalib;
+ uncal.xBias = src.uncalibrated_gyro.x_bias;
+ uncal.yBias = src.uncalibrated_gyro.y_bias;
+ uncal.zBias = src.uncalibrated_gyro.z_bias;
+ dst->payload.set<Event::EventPayload::Tag::uncal>(uncal);
+ break;
+ }
+
+ case SensorType::DEVICE_ORIENTATION:
+ case SensorType::LIGHT:
+ case SensorType::PRESSURE:
+ case SensorType::PROXIMITY:
+ case SensorType::RELATIVE_HUMIDITY:
+ case SensorType::AMBIENT_TEMPERATURE:
+ case SensorType::SIGNIFICANT_MOTION:
+ case SensorType::STEP_DETECTOR:
+ case SensorType::TILT_DETECTOR:
+ case SensorType::WAKE_GESTURE:
+ case SensorType::GLANCE_GESTURE:
+ case SensorType::PICK_UP_GESTURE:
+ case SensorType::WRIST_TILT_GESTURE:
+ case SensorType::STATIONARY_DETECT:
+ case SensorType::MOTION_DETECT:
+ case SensorType::HEART_BEAT:
+ case SensorType::LOW_LATENCY_OFFBODY_DETECT:
+ case SensorType::HINGE_ANGLE: {
+ dst->payload.set<Event::EventPayload::Tag::scalar>((float)src.data[0]);
+ break;
+ }
+
+ case SensorType::STEP_COUNTER: {
+ dst->payload.set<Event::EventPayload::Tag::stepCount>(src.u64.step_counter);
+ break;
+ }
+
+ case SensorType::HEART_RATE: {
+ Event::EventPayload::HeartRate heartRate;
+ heartRate.bpm = src.heart_rate.bpm;
+ heartRate.status = (SensorStatus)src.heart_rate.status;
+ dst->payload.set<Event::EventPayload::Tag::heartRate>(heartRate);
+ break;
+ }
+
+ case SensorType::POSE_6DOF: { // 15 floats
+ Event::EventPayload::Pose6Dof pose6DOF;
+ for (size_t i = 0; i < 15; ++i) {
+ pose6DOF.values[i] = src.data[i];
+ }
+ dst->payload.set<Event::EventPayload::Tag::pose6DOF>(pose6DOF);
+ break;
+ }
+
+ case SensorType::DYNAMIC_SENSOR_META: {
+ DynamicSensorInfo dynamic;
+ dynamic.connected = src.dynamic_sensor_meta.connected;
+ dynamic.sensorHandle = src.dynamic_sensor_meta.handle;
+
+ memcpy(dynamic.uuid.values.data(), src.dynamic_sensor_meta.uuid, 16);
+ dst->payload.set<Event::EventPayload::Tag::dynamic>(dynamic);
+ break;
+ }
+
+ case SensorType::ADDITIONAL_INFO: {
+ AdditionalInfo info;
+ const additional_info_event_t& srcInfo = src.additional_info;
+ info.type = (AdditionalInfo::AdditionalInfoType)srcInfo.type;
+ info.serial = srcInfo.serial;
+
+ AdditionalInfo::AdditionalInfoPayload::Int32Values data;
+ CHECK_EQ(data.values.size() * sizeof(int32_t), sizeof(srcInfo.data_int32));
+ memcpy(data.values.data(), srcInfo.data_int32, sizeof(srcInfo.data_int32));
+ info.payload.set<AdditionalInfo::AdditionalInfoPayload::Tag::dataInt32>(data);
+
+ dst->payload.set<Event::EventPayload::Tag::additional>(info);
+ break;
+ }
+
+ case SensorType::HEAD_TRACKER: {
+ Event::EventPayload::HeadTracker headTracker;
+ headTracker.rx = src.head_tracker.rx;
+ headTracker.ry = src.head_tracker.ry;
+ headTracker.rz = src.head_tracker.rz;
+ headTracker.vx = src.head_tracker.vx;
+ headTracker.vy = src.head_tracker.vy;
+ headTracker.vz = src.head_tracker.vz;
+ headTracker.discontinuityCount = src.head_tracker.discontinuity_count;
+
+ dst->payload.set<Event::EventPayload::Tag::headTracker>(headTracker);
+ break;
+ }
+
+ case SensorType::ACCELEROMETER_LIMITED_AXES:
+ case SensorType::GYROSCOPE_LIMITED_AXES: {
+ Event::EventPayload::LimitedAxesImu limitedAxesImu;
+ limitedAxesImu.x = src.limited_axes_imu.x;
+ limitedAxesImu.y = src.limited_axes_imu.y;
+ limitedAxesImu.z = src.limited_axes_imu.z;
+ limitedAxesImu.xSupported = src.limited_axes_imu.x_supported;
+ limitedAxesImu.ySupported = src.limited_axes_imu.y_supported;
+ limitedAxesImu.zSupported = src.limited_axes_imu.z_supported;
+ dst->payload.set<Event::EventPayload::Tag::limitedAxesImu>(limitedAxesImu);
+ break;
+ }
+
+ case SensorType::ACCELEROMETER_LIMITED_AXES_UNCALIBRATED:
+ case SensorType::GYROSCOPE_LIMITED_AXES_UNCALIBRATED: {
+ Event::EventPayload::LimitedAxesImuUncal limitedAxesImuUncal;
+ limitedAxesImuUncal.x = src.limited_axes_imu_uncalibrated.x_uncalib;
+ limitedAxesImuUncal.y = src.limited_axes_imu_uncalibrated.y_uncalib;
+ limitedAxesImuUncal.z = src.limited_axes_imu_uncalibrated.z_uncalib;
+ limitedAxesImuUncal.xBias = src.limited_axes_imu_uncalibrated.x_bias;
+ limitedAxesImuUncal.yBias = src.limited_axes_imu_uncalibrated.y_bias;
+ limitedAxesImuUncal.yBias = src.limited_axes_imu_uncalibrated.y_bias;
+ limitedAxesImuUncal.zBias = src.limited_axes_imu_uncalibrated.z_bias;
+ limitedAxesImuUncal.xSupported = src.limited_axes_imu_uncalibrated.x_supported;
+ limitedAxesImuUncal.ySupported = src.limited_axes_imu_uncalibrated.y_supported;
+ limitedAxesImuUncal.zSupported = src.limited_axes_imu_uncalibrated.z_supported;
+ dst->payload.set<Event::EventPayload::Tag::limitedAxesImuUncal>(limitedAxesImuUncal);
+ break;
+ }
+
+ case SensorType::HEADING: {
+ Event::EventPayload::Heading heading;
+ heading.heading = src.heading.heading;
+ heading.accuracy = src.heading.accuracy;
+ dst->payload.set<Event::EventPayload::heading>(heading);
+ break;
+ }
+
+ default: {
+ CHECK_GE((int32_t)dst->sensorType, (int32_t)SensorType::DEVICE_PRIVATE_BASE);
+
+ Event::EventPayload::Data data;
+ memcpy(data.values.data(), src.data, 16 * sizeof(float));
+ dst->payload.set<Event::EventPayload::Tag::data>(data);
+ break;
+ }
+ }
+}
+
+} // namespace implementation
+} // namespace sensors
+} // namespace hardware
+} // namespace android
diff --git a/sensors/aidl/convert/include/aidl/sensors/convert.h b/sensors/aidl/convert/include/aidl/sensors/convert.h
new file mode 100644
index 0000000..702b226
--- /dev/null
+++ b/sensors/aidl/convert/include/aidl/sensors/convert.h
@@ -0,0 +1,36 @@
+/*
+ * 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/sensors/ISensors.h>
+#include <hardware/sensors.h>
+
+namespace android {
+namespace hardware {
+namespace sensors {
+namespace implementation {
+
+status_t convertToStatus(ndk::ScopedAStatus status);
+void convertToSensor(const aidl::android::hardware::sensors::SensorInfo& src, sensor_t* dst);
+void convertToSensorEvent(const aidl::android::hardware::sensors::Event& src, sensors_event_t* dst);
+void convertFromSensorEvent(const sensors_event_t& src,
+ aidl::android::hardware::sensors::Event* dst);
+
+} // namespace implementation
+} // namespace sensors
+} // namespace hardware
+} // namespace android
diff --git a/sensors/aidl/default/Sensor.cpp b/sensors/aidl/default/Sensor.cpp
index 62193d6..3bdd8b6 100644
--- a/sensors/aidl/default/Sensor.cpp
+++ b/sensors/aidl/default/Sensor.cpp
@@ -223,7 +223,7 @@
EventPayload::Vec3 vec3 = {
.x = 0,
.y = 0,
- .z = -9.8,
+ .z = 9.8,
.status = SensorStatus::ACCURACY_HIGH,
};
payload.set<EventPayload::Tag::vec3>(vec3);
diff --git a/sensors/common/default/2.X/Sensor.cpp b/sensors/common/default/2.X/Sensor.cpp
index fd701fd..2c1cdfb 100644
--- a/sensors/common/default/2.X/Sensor.cpp
+++ b/sensors/common/default/2.X/Sensor.cpp
@@ -218,7 +218,7 @@
void AccelSensor::readEventPayload(EventPayload& payload) {
payload.vec3.x = 0;
payload.vec3.y = 0;
- payload.vec3.z = -9.8;
+ payload.vec3.z = 9.8;
payload.vec3.status = SensorStatus::ACCURACY_HIGH;
}
diff --git a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
index f5745c5..a0bb67a 100644
--- a/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
+++ b/sensors/common/default/2.X/multihal/tests/fake_subhal/Sensor.cpp
@@ -237,7 +237,7 @@
event.timestamp = ::android::elapsedRealtimeNano();
event.u.vec3.x = 0;
event.u.vec3.y = 0;
- event.u.vec3.z = -9.815;
+ event.u.vec3.z = 9.815;
event.u.vec3.status = SensorStatus::ACCURACY_HIGH;
events.push_back(event);
return events;
diff --git a/thermal/OWNERS b/thermal/OWNERS
new file mode 100644
index 0000000..7229b22
--- /dev/null
+++ b/thermal/OWNERS
@@ -0,0 +1,5 @@
+# Bug component: 826709
+
+# ADPF virtual team
+lpy@google.com
+wvw@google.com
diff --git a/thermal/aidl/Android.bp b/thermal/aidl/Android.bp
new file mode 100644
index 0000000..b132746
--- /dev/null
+++ b/thermal/aidl/Android.bp
@@ -0,0 +1,39 @@
+// Copyright (C) 2022 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "hardware_interfaces_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+aidl_interface {
+ name: "android.hardware.thermal",
+ vendor_available: true,
+ srcs: [
+ "android/hardware/thermal/*.aidl",
+ ],
+ stability: "vintf",
+ backend: {
+ cpp: {
+ enabled: true,
+ },
+ java: {
+ platform_apis: true,
+ },
+ },
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.aidl
new file mode 100644
index 0000000..50be508
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingDevice.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
+ *
+1 * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.thermal;
+@VintfStability
+parcelable CoolingDevice {
+ android.hardware.thermal.CoolingType type;
+ String name;
+ long value;
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl
new file mode 100644
index 0000000..57c8939
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/CoolingType.aidl
@@ -0,0 +1,48 @@
+/*
+ * 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.thermal;
+@Backing(type="int") @VintfStability
+enum CoolingType {
+ FAN = 0,
+ BATTERY = 1,
+ CPU = 2,
+ GPU = 3,
+ MODEM = 4,
+ NPU = 5,
+ COMPONENT = 6,
+ TPU = 7,
+ POWER_AMPLIFIER = 8,
+ DISPLAY = 9,
+ SPEAKER = 10,
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
new file mode 100644
index 0000000..0aed5ec
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermal.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.thermal;
+@VintfStability
+interface IThermal {
+ android.hardware.thermal.CoolingDevice[] getCoolingDevices();
+ android.hardware.thermal.CoolingDevice[] getCoolingDevicesWithType(in android.hardware.thermal.CoolingType type);
+ android.hardware.thermal.Temperature[] getTemperatures();
+ android.hardware.thermal.Temperature[] getTemperaturesWithType(in android.hardware.thermal.TemperatureType type);
+ android.hardware.thermal.TemperatureThreshold[] getTemperatureThresholds();
+ android.hardware.thermal.TemperatureThreshold[] getTemperatureThresholdsWithType(in android.hardware.thermal.TemperatureType type);
+ void registerThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback);
+ void registerThermalChangedCallbackWithType(in android.hardware.thermal.IThermalChangedCallback callback, in android.hardware.thermal.TemperatureType type);
+ void unregisterThermalChangedCallback(in android.hardware.thermal.IThermalChangedCallback callback);
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.aidl
new file mode 100644
index 0000000..6b3f922
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/IThermalChangedCallback.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.thermal;
+@VintfStability
+interface IThermalChangedCallback {
+ oneway void notifyThrottling(in android.hardware.thermal.Temperature temperature);
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl
new file mode 100644
index 0000000..7156415
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/Temperature.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.thermal;
+@VintfStability
+parcelable Temperature {
+ android.hardware.thermal.TemperatureType type;
+ String name;
+ float value;
+ android.hardware.thermal.ThrottlingSeverity throttlingStatus;
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl
new file mode 100644
index 0000000..6da561f
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureThreshold.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.thermal;
+@VintfStability
+parcelable TemperatureThreshold {
+ android.hardware.thermal.TemperatureType type;
+ String name;
+ float[] hotThrottlingThresholds;
+ float[] coldThrottlingThresholds;
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl
new file mode 100644
index 0000000..c6a08c1
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/TemperatureType.aidl
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible change, it has a high risk of breaking
+// later when a module using the interface is updated, e.g., Mainline modules.
+
+package android.hardware.thermal;
+@Backing(type="int") @VintfStability
+enum TemperatureType {
+ UNKNOWN = -1,
+ CPU = 0,
+ GPU = 1,
+ BATTERY = 2,
+ SKIN = 3,
+ USB_PORT = 4,
+ POWER_AMPLIFIER = 5,
+ BCL_VOLTAGE = 6,
+ BCL_CURRENT = 7,
+ BCL_PERCENTAGE = 8,
+ NPU = 9,
+ TPU = 10,
+ DISPLAY = 11,
+ MODEM = 12,
+ SOC = 13,
+}
diff --git a/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl
new file mode 100644
index 0000000..e86b581
--- /dev/null
+++ b/thermal/aidl/aidl_api/android.hardware.thermal/current/android/hardware/thermal/ThrottlingSeverity.aidl
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.thermal;
+@Backing(type="int") @VintfStability
+enum ThrottlingSeverity {
+ NONE = 0,
+ LIGHT = 1,
+ MODERATE = 2,
+ SEVERE = 3,
+ CRITICAL = 4,
+ EMERGENCY = 5,
+ SHUTDOWN = 6,
+}
diff --git a/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl b/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl
new file mode 100644
index 0000000..6d974a5
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/CoolingDevice.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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
+ *
+1 * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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.thermal;
+
+import android.hardware.thermal.CoolingType;
+
+@VintfStability
+parcelable CoolingDevice {
+ /**
+ * This cooling device type, CPU, GPU, BATTERY, and etc.
+ */
+ CoolingType type;
+ /**
+ * Name of this cooling device.
+ * All cooling devices of the same "type" must have a different "name".
+ * The name is usually defined in kernel device tree, and this is for client
+ * logging purpose.
+ */
+ String name;
+ /**
+ * Current throttle state of the cooling device. The value can any unsigned integer
+ * numbers between 0 and max_state defined in its driver, usually representing the
+ * associated device's power state. 0 means device is not in throttling, higher value
+ * means deeper throttling.
+ */
+ long value;
+}
diff --git a/thermal/aidl/android/hardware/thermal/CoolingType.aidl b/thermal/aidl/android/hardware/thermal/CoolingType.aidl
new file mode 100644
index 0000000..1b430d2
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/CoolingType.aidl
@@ -0,0 +1,36 @@
+/*
+ * 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.thermal;
+
+/**
+ * Device cooling device types
+ */
+@VintfStability
+@Backing(type="int")
+enum CoolingType {
+ FAN,
+ BATTERY,
+ CPU,
+ GPU,
+ MODEM,
+ NPU,
+ COMPONENT,
+ TPU,
+ POWER_AMPLIFIER,
+ DISPLAY,
+ SPEAKER,
+}
diff --git a/thermal/aidl/android/hardware/thermal/IThermal.aidl b/thermal/aidl/android/hardware/thermal/IThermal.aidl
new file mode 100644
index 0000000..8b79cb4
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/IThermal.aidl
@@ -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.
+ */
+
+package android.hardware.thermal;
+
+import android.hardware.thermal.CoolingDevice;
+import android.hardware.thermal.CoolingType;
+import android.hardware.thermal.IThermalChangedCallback;
+import android.hardware.thermal.Temperature;
+import android.hardware.thermal.TemperatureThreshold;
+import android.hardware.thermal.TemperatureType;
+
+@VintfStability
+interface IThermal {
+ /**
+ * Retrieves the cooling devices information.
+ *
+ * @return devices If succeed, it's filled with the
+ * current cooling device information. The order of built-in cooling
+ * devices in the list must be kept the same regardless the number
+ * of calls to this method even if they go offline, if these devices
+ * exist on boot. The method always returns and never removes from
+ * the list such cooling devices.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, getMessage() must be populated with the human-readable
+ * error message.
+ */
+ CoolingDevice[] getCoolingDevices();
+
+ /**
+ * Retrieves the cooling devices information of a given CoolingType.
+ *
+ * @param type the CoolingDevice such as CPU/GPU.
+ *
+ * @return devices If succeed, it's filled with the current
+ * cooling device information. The order of built-in cooling
+ * devices in the list must be kept the same regardless of the number
+ * of calls to this method even if they go offline, if these devices
+ * exist on boot. The method always returns and never removes from
+ * the list such cooling devices.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ CoolingDevice[] getCoolingDevicesWithType(in CoolingType type);
+
+ /**
+ * Retrieves temperatures in Celsius.
+ *
+ * @return temperatures If succeed, it's filled with the
+ * current temperatures. The order of temperatures of built-in
+ * devices (such as CPUs, GPUs and etc.) in the list must be kept
+ * the same regardless the number of calls to this method even if
+ * they go offline, if these devices exist on boot. The method
+ * always returns and never removes such temperatures.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ Temperature[] getTemperatures();
+
+ /**
+ * Retrieves temperatures in Celsius with a given TemperatureType.
+ *
+ * @param type the TemperatureType such as battery or skin.
+ *
+ * @return temperatures If succeed, it's filled with the
+ * current temperatures. The order of temperatures of built-in
+ * devices (such as CPUs, GPUs and etc.) in the list must be kept
+ * the same regardless of the number of calls to this method even if
+ * they go offline, if these devices exist on boot. The method
+ * always returns and never removes such temperatures.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ Temperature[] getTemperaturesWithType(in TemperatureType type);
+
+ /**
+ * Retrieves static temperature thresholds in Celsius.
+ *
+ * @return temperatureThresholds If succeed, it's filled with the
+ * temperatures thresholds. The order of temperatures of built-in
+ * devices (such as CPUs, GPUs and etc.) in the list must be kept
+ * the same regardless of the number of calls to this method even if
+ * they go offline, if these devices exist on boot. The method
+ * always returns and never removes such temperatures. The thresholds
+ * are returned as static values and must not change across calls. The actual
+ * throttling state is determined in device thermal mitigation policy/agorithm
+ * which might not be simple thresholds so these values Thermal HAL provided
+ * may not be accurate to detemin the throttling status. To get accurate
+ * throttling status, use getTemperatures or registerThermalChangedCallback
+ * and listen to the callback.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ TemperatureThreshold[] getTemperatureThresholds();
+
+ /**
+ * Retrieves static temperature thresholds in Celsius of a given temperature
+ * type.
+ *
+ * @param type the TemperatureType such as battery or skin.
+ *
+ * @return temperatureThresholds If succeed, it's filled with the
+ * temperatures thresholds. The order of temperatures of built-in
+ * devices (such as CPUs, GPUs and etc.) in the list must be kept
+ * the same regardless of the number of calls to this method even if
+ * they go offline, if these devices exist on boot. The method
+ * always returns and never removes such temperatures. The thresholds
+ * are returned as static values and must not change across calls. The actual
+ * throttling state is determined in device thermal mitigation policy/agorithm
+ * which might not be simple thresholds so these values Thermal HAL provided
+ * may not be accurate to detemin the throttling status. To get accurate
+ * throttling status, use getTemperatures or registerThermalChangedCallback
+ * and listen to the callback.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message.
+ */
+ TemperatureThreshold[] getTemperatureThresholdsWithType(in TemperatureType type);
+
+ /**
+ * Register an IThermalChangedCallback, used by the Thermal HAL to receive
+ * thermal events when thermal mitigation status changed.
+ * Multiple registrations with different IThermalChangedCallback must be allowed.
+ * Multiple registrations with same IThermalChangedCallback is not allowed, client
+ * should unregister the given IThermalChangedCallback first.
+ *
+ * @param callback the IThermalChangedCallback to use for receiving
+ * thermal events. if nullptr callback is given, the status code will be
+ * STATUS_BAD_VALUE and the operation will fail.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message. If callback is given nullptr, the returned status code
+ * will be STATUS_BAD_VALUE and the exception will be EX_ILLEGAL_ARGUMENT.
+ * if callback is already registered, the returned status code will be
+ * STATUS_INVALID_OPERATION, the exception will be EX_ILLEGAL_ARGUMENT.
+ */
+ void registerThermalChangedCallback(in IThermalChangedCallback callback);
+
+ /**
+ * Register an IThermalChangedCallback for a given TemperatureType, used by
+ * the Thermal HAL to receive thermal events when thermal mitigation status
+ * changed.
+ * Multiple registrations with different IThermalChangedCallback must be allowed.
+ * Multiple registrations with same IThermalChangedCallback is not allowed, client
+ * should unregister the given IThermalChangedCallback first.
+ *
+ * @param callback the IThermalChangedCallback to use for receiving
+ * thermal events. if nullptr callback is given, the status code will be
+ * STATUS_BAD_VALUE and the operation will fail.
+ * @param type the type to be filtered.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message. If callback is given nullptr, the returned status code
+ * will be STATUS_BAD_VALUE and the exception will be EX_ILLEGAL_ARGUMENT.
+ * if callback is already registered, the returned status code will be
+ * STATUS_INVALID_OPERATION, the exception will be EX_ILLEGAL_ARGUMENT.
+ */
+ void registerThermalChangedCallbackWithType(
+ in IThermalChangedCallback callback, in TemperatureType type);
+
+ /**
+ * Unregister an IThermalChangedCallback, used by the Thermal HAL
+ * to receive thermal events when thermal mitigation status changed.
+ *
+ * @param callback the IThermalChangedCallback to use for receiving
+ * thermal events. if nullptr callback is given, the status code will be
+ * STATUS_BAD_VALUE and the operation will fail.
+ *
+ * @throws ScopedAStatus Status of the operation. If status code is not
+ * STATUS_OK, the getMessage() must be populated with the human-readable
+ * error message. If callback is given nullptr, the returned status code
+ * will be STATUS_BAD_VALUE and the exception will be EX_ILLEGAL_ARGUMENT.
+ * if callback is not registered, the returned status code will be
+ * STATUS_INVALID_OPERATION, the exception will be EX_ILLEGAL_ARGUMENT.
+ */
+ void unregisterThermalChangedCallback(in IThermalChangedCallback callback);
+}
diff --git a/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl
new file mode 100644
index 0000000..6fe2dac
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/IThermalChangedCallback.aidl
@@ -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.thermal;
+
+import android.hardware.thermal.Temperature;
+
+/**
+ * IThermalChangedCallback send throttling notification to clients.
+ */
+@VintfStability
+interface IThermalChangedCallback {
+ /**
+ * Send a thermal throttling event to all ThermalHAL
+ * thermal event listeners.
+ *
+ * @param temperature The temperature associated with the
+ * throttling event.
+ */
+ oneway void notifyThrottling(in Temperature temperature);
+}
diff --git a/thermal/aidl/android/hardware/thermal/Temperature.aidl b/thermal/aidl/android/hardware/thermal/Temperature.aidl
new file mode 100644
index 0000000..f0041ed
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/Temperature.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.thermal;
+
+import android.hardware.thermal.TemperatureType;
+import android.hardware.thermal.ThrottlingSeverity;
+
+@VintfStability
+parcelable Temperature {
+ /**
+ * This temperature's type.
+ */
+ TemperatureType type;
+ /**
+ * Name of this temperature matching the TemperatureThreshold.
+ * All temperatures of the same "type" must have a different "name",
+ * e.g., cpu0, battery. Clients use it to match with TemperatureThreshold
+ * struct.
+ */
+ String name;
+ /**
+ * For BCL, this is the current reading of the virtual sensor and the unit is
+ * millivolt, milliamp, percentage for BCL_VOLTAGE, BCL_CURRENT and BCL_PERCENTAGE
+ * respectively. For everything else, this is the current temperature in Celsius.
+ * If not available set by HAL to NAN.
+ */
+ float value;
+ /**
+ * The current throttling level of the sensor.
+ */
+ ThrottlingSeverity throttlingStatus;
+}
diff --git a/thermal/aidl/android/hardware/thermal/TemperatureThreshold.aidl b/thermal/aidl/android/hardware/thermal/TemperatureThreshold.aidl
new file mode 100644
index 0000000..9ecdab3
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/TemperatureThreshold.aidl
@@ -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.
+ */
+
+package android.hardware.thermal;
+
+import android.hardware.thermal.TemperatureType;
+
+@VintfStability
+parcelable TemperatureThreshold {
+ /**
+ * This temperature's type.
+ */
+ TemperatureType type;
+ /**
+ * Name of this temperature matching the Temperature struct.
+ * All temperatures of the same "type" must have a different "name",
+ * e.g., cpu0, battery. Clients use it to match Temperature struct.
+ */
+ String name;
+ /**
+ * Hot throttling temperature constant for this temperature sensor in
+ * level defined in ThrottlingSeverity including shutdown. Throttling
+ * happens when temperature >= threshold. If not available, set to NAN.
+ * Unit is same as Temperature's value.
+ * The number of thresholds must be the same as ThrottlingSeverity#len.
+ */
+ float[] hotThrottlingThresholds;
+ /**
+ * Cold throttling temperature constant for this temperature sensor in
+ * level defined in ThrottlingSeverity including shutdown. Throttling
+ * happens when temperature <= threshold. If not available, set to NAN.
+ * Unit is same as Temperature's value.
+ * The number of theresholds must be the same as ThrottlingSeverity#len.
+ */
+ float[] coldThrottlingThresholds;
+}
diff --git a/thermal/aidl/android/hardware/thermal/TemperatureType.aidl b/thermal/aidl/android/hardware/thermal/TemperatureType.aidl
new file mode 100644
index 0000000..aebe7ce
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/TemperatureType.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.thermal;
+
+/**
+ * Device temperature types
+ */
+@VintfStability
+@Backing(type="int")
+enum TemperatureType {
+ UNKNOWN = -1,
+ CPU = 0,
+ GPU = 1,
+ BATTERY = 2,
+ SKIN = 3,
+ USB_PORT = 4,
+ POWER_AMPLIFIER = 5,
+ /**
+ * Battery Current Limit - virtual sensors
+ */
+ BCL_VOLTAGE = 6,
+ BCL_CURRENT = 7,
+ BCL_PERCENTAGE = 8,
+ /**
+ * Neural Processing Unit
+ */
+ NPU = 9,
+ TPU = 10,
+ DISPLAY = 11,
+ MODEM = 12,
+ SOC = 13,
+}
diff --git a/thermal/aidl/android/hardware/thermal/ThrottlingSeverity.aidl b/thermal/aidl/android/hardware/thermal/ThrottlingSeverity.aidl
new file mode 100644
index 0000000..29f0724
--- /dev/null
+++ b/thermal/aidl/android/hardware/thermal/ThrottlingSeverity.aidl
@@ -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 android.hardware.thermal;
+
+/**
+ * Device throttling severity
+ */
+@VintfStability
+@Backing(type="int")
+enum ThrottlingSeverity {
+ /**
+ * Not under throttling.
+ */
+ NONE = 0,
+ /**
+ * Light throttling where UX is not impacted.
+ */
+ LIGHT,
+ /**
+ * Moderate throttling where UX is not largely impacted.
+ */
+ MODERATE,
+ /**
+ * Severe throttling where UX is largely impacted.
+ * Similar to 1.0 throttlingThreshold.
+ */
+ SEVERE,
+ /**
+ * Platform has done everything to reduce power.
+ */
+ CRITICAL,
+ /**
+ * Key components in platform are shutting down due to thermal condition.
+ * Device functionalities will be limited.
+ */
+ EMERGENCY,
+ /**
+ * Need shutdown immediately.
+ */
+ SHUTDOWN,
+}
diff --git a/thermal/aidl/default/Android.bp b/thermal/aidl/default/Android.bp
new file mode 100644
index 0000000..49a578b
--- /dev/null
+++ b/thermal/aidl/default/Android.bp
@@ -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.
+
+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.thermal-service.example",
+ relative_install_path: "hw",
+ init_rc: [":android.hardware.thermal.example.rc"],
+ vintf_fragments: [":android.hardware.thermal.example.xml"],
+ vendor: true,
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "android.hardware.thermal-V1-ndk",
+ ],
+ srcs: [
+ "main.cpp",
+ "Thermal.cpp",
+ ],
+}
+
+filegroup {
+ name: "android.hardware.thermal.example.xml",
+ srcs: ["thermal-example.xml"],
+}
+
+filegroup {
+ name: "android.hardware.thermal.example.rc",
+ srcs: ["thermal-example.rc"],
+}
diff --git a/thermal/aidl/default/Thermal.cpp b/thermal/aidl/default/Thermal.cpp
new file mode 100644
index 0000000..5771e0e
--- /dev/null
+++ b/thermal/aidl/default/Thermal.cpp
@@ -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.
+ */
+
+#include "Thermal.h"
+
+#include <android-base/logging.h>
+
+namespace aidl::android::hardware::thermal::impl::example {
+
+using ndk::ScopedAStatus;
+
+ScopedAStatus Thermal::getCoolingDevices(std::vector<CoolingDevice>* /* out_devices */) {
+ LOG(VERBOSE) << __func__;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getCoolingDevicesWithType(CoolingType in_type,
+ std::vector<CoolingDevice>* /* out_devices */) {
+ LOG(VERBOSE) << __func__ << " CoolingType: " << static_cast<int32_t>(in_type);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperatures(std::vector<Temperature>* /* out_temperatures */) {
+ LOG(VERBOSE) << __func__;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperaturesWithType(TemperatureType in_type,
+ std::vector<Temperature>* /* out_temperatures */) {
+ LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast<int32_t>(in_type);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperatureThresholds(
+ std::vector<TemperatureThreshold>* /* out_temperatureThresholds */) {
+ LOG(VERBOSE) << __func__;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::getTemperatureThresholdsWithType(
+ TemperatureType in_type,
+ std::vector<TemperatureThreshold>* /* out_temperatureThresholds */) {
+ LOG(VERBOSE) << __func__ << " TemperatureType: " << static_cast<int32_t>(in_type);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::registerThermalChangedCallback(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback) {
+ LOG(VERBOSE) << __func__ << " IThermalChangedCallback: " << in_callback;
+ if (in_callback == nullptr) {
+ return ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+ }
+ if (mCallbacks.find(in_callback) != mCallbacks.end()) {
+ return ScopedAStatus::fromStatus(STATUS_INVALID_OPERATION);
+ }
+ mCallbacks.insert(in_callback);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::registerThermalChangedCallbackWithType(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback, TemperatureType in_type) {
+ LOG(VERBOSE) << __func__ << " IThermalChangedCallback: " << in_callback
+ << ", TemperatureType: " << static_cast<int32_t>(in_type);
+ if (in_callback == nullptr) {
+ return ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+ }
+ if (mCallbacks.find(in_callback) != mCallbacks.end()) {
+ return ScopedAStatus::fromStatus(STATUS_INVALID_OPERATION);
+ }
+ mCallbacks.insert(in_callback);
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus Thermal::unregisterThermalChangedCallback(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback) {
+ LOG(VERBOSE) << __func__ << " IThermalChangedCallback: " << in_callback;
+ bool found = false;
+ if (in_callback == nullptr) {
+ return ScopedAStatus::fromStatus(STATUS_BAD_VALUE);
+ }
+ if (mCallbacks.find(in_callback) == mCallbacks.end()) {
+ return ScopedAStatus::fromStatus(STATUS_INVALID_OPERATION);
+ }
+ mCallbacks.erase(in_callback);
+ return ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::thermal::impl::example
diff --git a/thermal/aidl/default/Thermal.h b/thermal/aidl/default/Thermal.h
new file mode 100644
index 0000000..788af4a
--- /dev/null
+++ b/thermal/aidl/default/Thermal.h
@@ -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.
+ */
+
+#pragma once
+
+#include <set>
+
+#include <aidl/android/hardware/thermal/BnThermal.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace thermal {
+namespace impl {
+namespace example {
+
+class Thermal : public BnThermal {
+ public:
+ ndk::ScopedAStatus getCoolingDevices(std::vector<CoolingDevice>* out_devices) override;
+ ndk::ScopedAStatus getCoolingDevicesWithType(CoolingType in_type,
+ std::vector<CoolingDevice>* out_devices) override;
+
+ ndk::ScopedAStatus getTemperatures(std::vector<Temperature>* out_temperatures) override;
+ ndk::ScopedAStatus getTemperaturesWithType(TemperatureType in_type,
+ std::vector<Temperature>* out_temperatures) override;
+
+ ndk::ScopedAStatus getTemperatureThresholds(
+ std::vector<TemperatureThreshold>* out_temperatureThresholds) override;
+
+ ndk::ScopedAStatus getTemperatureThresholdsWithType(
+ TemperatureType in_type,
+ std::vector<TemperatureThreshold>* out_temperatureThresholds) override;
+
+ ndk::ScopedAStatus registerThermalChangedCallback(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback) override;
+ ndk::ScopedAStatus registerThermalChangedCallbackWithType(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback,
+ TemperatureType in_type) override;
+
+ ndk::ScopedAStatus unregisterThermalChangedCallback(
+ const std::shared_ptr<IThermalChangedCallback>& in_callback) override;
+
+ private:
+ std::set<std::shared_ptr<IThermalChangedCallback>> mCallbacks;
+};
+
+} // namespace example
+} // namespace impl
+} // namespace thermal
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/thermal/aidl/default/main.cpp b/thermal/aidl/default/main.cpp
new file mode 100644
index 0000000..61d8ad0
--- /dev/null
+++ b/thermal/aidl/default/main.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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 "Thermal.h"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+
+using aidl::android::hardware::thermal::impl::example::Thermal;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(0);
+ std::shared_ptr<Thermal> thermal = ndk::SharedRefBase::make<Thermal>();
+
+ const std::string instance = std::string() + Thermal::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(thermal->asBinder().get(), instance.c_str());
+ CHECK(status == STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return EXIT_FAILURE; // should not reach
+}
diff --git a/thermal/aidl/default/thermal-example.rc b/thermal/aidl/default/thermal-example.rc
new file mode 100644
index 0000000..591ca03
--- /dev/null
+++ b/thermal/aidl/default/thermal-example.rc
@@ -0,0 +1,4 @@
+service vendor.thermal-example /vendor/bin/hw/android.hardware.thermal-service.example
+ class hal
+ user nobody
+ group system
diff --git a/thermal/aidl/default/thermal-example.xml b/thermal/aidl/default/thermal-example.xml
new file mode 100644
index 0000000..bdee744
--- /dev/null
+++ b/thermal/aidl/default/thermal-example.xml
@@ -0,0 +1,7 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.thermal</name>
+ <version>1</version>
+ <fqname>IThermal/default</fqname>
+ </hal>
+</manifest>
diff --git a/thermal/aidl/vts/Android.bp b/thermal/aidl/vts/Android.bp
new file mode 100644
index 0000000..b00eb33
--- /dev/null
+++ b/thermal/aidl/vts/Android.bp
@@ -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.
+
+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: "VtsHalThermalTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalThermalTargetTest.cpp"],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ static_libs: [
+ "android.hardware.thermal-V1-ndk",
+ ],
+ test_suites: [
+ "vts",
+ ],
+}
diff --git a/thermal/aidl/vts/VtsHalThermalTargetTest.cpp b/thermal/aidl/vts/VtsHalThermalTargetTest.cpp
new file mode 100644
index 0000000..b93250e
--- /dev/null
+++ b/thermal/aidl/vts/VtsHalThermalTargetTest.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.
+ */
+
+#include <algorithm>
+#include <chrono>
+#include <cmath>
+#include <memory>
+#include <string>
+#include <thread>
+#include <vector>
+
+#define LOG_TAG "thermal_aidl_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/thermal/BnThermal.h>
+#include <aidl/android/hardware/thermal/BnThermalChangedCallback.h>
+#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android/binder_ibinder.h>
+#include <android/binder_interface_utils.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <android/binder_status.h>
+#include <gtest/gtest.h>
+
+#include <unistd.h>
+
+namespace aidl::android::hardware::thermal {
+
+namespace {
+
+using ::android::sp;
+using android::hardware::thermal::CoolingDevice;
+using android::hardware::thermal::IThermal;
+using android::hardware::thermal::Temperature;
+using android::hardware::thermal::TemperatureType;
+
+using namespace std::string_literals;
+using namespace std::chrono_literals;
+
+static const Temperature kThrottleTemp = {
+ .type = TemperatureType::SKIN,
+ .name = "test temperature sensor",
+ .value = 98.6,
+ .throttlingStatus = ThrottlingSeverity::CRITICAL,
+};
+
+// Callback class for receiving thermal event notifications from main class
+class ThermalCallback : public BnThermalChangedCallback {
+ public:
+ ndk::ScopedAStatus notifyThrottling(const Temperature&) override {
+ {
+ std::lock_guard<std::mutex> lock(mMutex);
+ mInvoke = true;
+ }
+ mNotifyThrottling.notify_all();
+ return ndk::ScopedAStatus::ok();
+ }
+
+ template <typename R, typename P>
+ [[nodiscard]] bool waitForCallback(std::chrono::duration<R, P> duration) {
+ std::unique_lock<std::mutex> lock(mMutex);
+ bool r = mNotifyThrottling.wait_for(lock, duration, [this] { return this->mInvoke; });
+ mInvoke = false;
+ return r;
+ }
+
+ private:
+ std::mutex mMutex;
+ std::condition_variable mNotifyThrottling;
+ bool mInvoke = false;
+};
+
+// The main test class for THERMAL HIDL HAL.
+class ThermalAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ AIBinder* binder = AServiceManager_waitForService(GetParam().c_str());
+ ASSERT_NE(binder, nullptr);
+ mThermal = IThermal::fromBinder(ndk::SpAIBinder(binder));
+
+ mThermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
+ ASSERT_NE(mThermalCallback, nullptr);
+ auto ret = mThermal->registerThermalChangedCallback(mThermalCallback);
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail if register again
+ ret = mThermal->registerThermalChangedCallback(mThermalCallback);
+ ASSERT_FALSE(ret.isOk());
+ ASSERT_TRUE(ret.getStatus() == STATUS_INVALID_OPERATION);
+ }
+
+ void TearDown() override {
+ auto ret = mThermal->unregisterThermalChangedCallback(mThermalCallback);
+ ASSERT_TRUE(ret.isOk());
+ // Expect to fail if unregister again
+ ret = mThermal->unregisterThermalChangedCallback(mThermalCallback);
+ ASSERT_FALSE(ret.isOk());
+ ASSERT_TRUE(ret.getStatus() == STATUS_INVALID_OPERATION);
+ }
+
+ protected:
+ std::shared_ptr<IThermal> mThermal;
+ std::shared_ptr<ThermalCallback> mThermalCallback;
+};
+
+// Test ThermalChangedCallback::notifyThrottling().
+// This just calls into and back from our local ThermalChangedCallback impl.
+TEST_P(ThermalAidlTest, NotifyThrottlingTest) {
+ std::shared_ptr<ThermalCallback> thermalCallback = ndk::SharedRefBase::make<ThermalCallback>();
+ auto ret = thermalCallback->notifyThrottling(kThrottleTemp);
+ ASSERT_TRUE(ret.isOk());
+ ASSERT_TRUE(thermalCallback->waitForCallback(200ms));
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ThermalAidlTest);
+INSTANTIATE_TEST_SUITE_P(
+ Thermal, ThermalAidlTest,
+ testing::ValuesIn(::android::getAidlHalInstanceNames(IThermal::descriptor)),
+ ::android::PrintInstanceNameToString);
+
+} // namespace
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+ return RUN_ALL_TESTS();
+}
+
+} // namespace aidl::android::hardware::thermal
diff --git a/tv/cec/aidl/Android.bp b/tv/cec/aidl/Android.bp
new file mode 100644
index 0000000..0b0e7cf
--- /dev/null
+++ b/tv/cec/aidl/Android.bp
@@ -0,0 +1,29 @@
+// 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"],
+}
+
+aidl_interface {
+ name: "android.hardware.tv.cec",
+ vendor_available: true,
+ srcs: ["android/hardware/tv/cec/*.aidl"],
+ stability: "vintf",
+ backend: {
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+}
diff --git a/tv/cec/aidl/OWNERS b/tv/cec/aidl/OWNERS
new file mode 100644
index 0000000..d9c6783
--- /dev/null
+++ b/tv/cec/aidl/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 826094
+include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
\ No newline at end of file
diff --git a/tv/cec/aidl/TEST_MAPPING b/tv/cec/aidl/TEST_MAPPING
new file mode 100644
index 0000000..ef4bee1
--- /dev/null
+++ b/tv/cec/aidl/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalTvCecAidlTargetTest"
+ }
+ ]
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/AbortReason.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/AbortReason.aidl
new file mode 100644
index 0000000..7377d81
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/AbortReason.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.tv.cec;
+@Backing(type="int") @VintfStability
+enum AbortReason {
+ UNRECOGNIZED_MODE = 0,
+ NOT_IN_CORRECT_MODE = 1,
+ CANNOT_PROVIDE_SOURCE = 2,
+ INVALID_OPERAND = 3,
+ REFUSED = 4,
+ UNABLE_TO_DETERMINE = 5,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecDeviceType.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecDeviceType.aidl
new file mode 100644
index 0000000..4d991cd
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecDeviceType.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.tv.cec;
+@Backing(type="byte") @VintfStability
+enum CecDeviceType {
+ INACTIVE = -1,
+ TV = 0,
+ RECORDER = 1,
+ TUNER = 3,
+ PLAYBACK = 4,
+ AUDIO_SYSTEM = 5,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecLogicalAddress.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecLogicalAddress.aidl
new file mode 100644
index 0000000..a36935b
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecLogicalAddress.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.tv.cec;
+@Backing(type="byte") @VintfStability
+enum CecLogicalAddress {
+ TV = 0,
+ RECORDER_1 = 1,
+ RECORDER_2 = 2,
+ TUNER_1 = 3,
+ PLAYBACK_1 = 4,
+ AUDIO_SYSTEM = 5,
+ TUNER_2 = 6,
+ TUNER_3 = 7,
+ PLAYBACK_2 = 8,
+ RECORDER_3 = 9,
+ TUNER_4 = 10,
+ PLAYBACK_3 = 11,
+ BACKUP_1 = 12,
+ BACKUP_2 = 13,
+ FREE_USE = 14,
+ BROADCAST = 15,
+ UNREGISTERED = 15,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessage.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessage.aidl
new file mode 100644
index 0000000..5ce5ce8
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessage.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.tv.cec;
+@VintfStability
+parcelable CecMessage {
+ android.hardware.tv.cec.CecLogicalAddress initiator;
+ android.hardware.tv.cec.CecLogicalAddress destination;
+ byte[] body;
+ const int MAX_MESSAGE_BODY_LENGTH = 15;
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessageType.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessageType.aidl
new file mode 100644
index 0000000..61ebb94
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/CecMessageType.aidl
@@ -0,0 +1,111 @@
+/*
+ * 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.tv.cec;
+@Backing(type="int") @VintfStability
+enum CecMessageType {
+ FEATURE_ABORT = 0,
+ IMAGE_VIEW_ON = 4,
+ TUNER_STEP_INCREMENT = 5,
+ TUNER_STEP_DECREMENT = 6,
+ TUNER_DEVICE_STATUS = 7,
+ GIVE_TUNER_DEVICE_STATUS = 8,
+ RECORD_ON = 9,
+ RECORD_STATUS = 10,
+ RECORD_OFF = 11,
+ TEXT_VIEW_ON = 13,
+ RECORD_TV_SCREEN = 15,
+ GIVE_DECK_STATUS = 26,
+ DECK_STATUS = 27,
+ SET_MENU_LANGUAGE = 50,
+ CLEAR_ANALOG_TIMER = 51,
+ SET_ANALOG_TIMER = 52,
+ TIMER_STATUS = 53,
+ STANDBY = 54,
+ PLAY = 65,
+ DECK_CONTROL = 66,
+ TIMER_CLEARED_STATUS = 67,
+ USER_CONTROL_PRESSED = 68,
+ USER_CONTROL_RELEASED = 69,
+ GIVE_OSD_NAME = 70,
+ SET_OSD_NAME = 71,
+ SET_OSD_STRING = 100,
+ SET_TIMER_PROGRAM_TITLE = 103,
+ SYSTEM_AUDIO_MODE_REQUEST = 112,
+ GIVE_AUDIO_STATUS = 113,
+ SET_SYSTEM_AUDIO_MODE = 114,
+ REPORT_AUDIO_STATUS = 122,
+ GIVE_SYSTEM_AUDIO_MODE_STATUS = 125,
+ SYSTEM_AUDIO_MODE_STATUS = 126,
+ ROUTING_CHANGE = 128,
+ ROUTING_INFORMATION = 129,
+ ACTIVE_SOURCE = 130,
+ GIVE_PHYSICAL_ADDRESS = 131,
+ REPORT_PHYSICAL_ADDRESS = 132,
+ REQUEST_ACTIVE_SOURCE = 133,
+ SET_STREAM_PATH = 134,
+ DEVICE_VENDOR_ID = 135,
+ VENDOR_COMMAND = 137,
+ VENDOR_REMOTE_BUTTON_DOWN = 138,
+ VENDOR_REMOTE_BUTTON_UP = 139,
+ GIVE_DEVICE_VENDOR_ID = 140,
+ MENU_REQUEST = 141,
+ MENU_STATUS = 142,
+ GIVE_DEVICE_POWER_STATUS = 143,
+ REPORT_POWER_STATUS = 144,
+ GET_MENU_LANGUAGE = 145,
+ SELECT_ANALOG_SERVICE = 146,
+ SELECT_DIGITAL_SERVICE = 147,
+ SET_DIGITAL_TIMER = 151,
+ CLEAR_DIGITAL_TIMER = 153,
+ SET_AUDIO_RATE = 154,
+ INACTIVE_SOURCE = 157,
+ CEC_VERSION = 158,
+ GET_CEC_VERSION = 159,
+ VENDOR_COMMAND_WITH_ID = 160,
+ CLEAR_EXTERNAL_TIMER = 161,
+ SET_EXTERNAL_TIMER = 162,
+ REPORT_SHORT_AUDIO_DESCRIPTOR = 163,
+ REQUEST_SHORT_AUDIO_DESCRIPTOR = 164,
+ INITIATE_ARC = 192,
+ REPORT_ARC_INITIATED = 193,
+ REPORT_ARC_TERMINATED = 194,
+ REQUEST_ARC_INITIATION = 195,
+ REQUEST_ARC_TERMINATION = 196,
+ TERMINATE_ARC = 197,
+ ABORT = 255,
+ GIVE_FEATURES = 165,
+ REPORT_FEATURES = 166,
+ REQUEST_CURRENT_LATENCY = 167,
+ REPORT_CURRENT_LATENCY = 168,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCec.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCec.aidl
new file mode 100644
index 0000000..cf8425e
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCec.aidl
@@ -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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// 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.tv.cec;
+@VintfStability
+interface IHdmiCec {
+ android.hardware.tv.cec.Result addLogicalAddress(in android.hardware.tv.cec.CecLogicalAddress addr);
+ void clearLogicalAddress();
+ void enableAudioReturnChannel(in int portId, in boolean enable);
+ int getCecVersion();
+ int getPhysicalAddress();
+ int getVendorId();
+ android.hardware.tv.cec.SendMessageResult sendMessage(in android.hardware.tv.cec.CecMessage message);
+ void setCallback(in android.hardware.tv.cec.IHdmiCecCallback callback);
+ void setLanguage(in String language);
+ void enableWakeupByOtp(in boolean value);
+ void enableCec(in boolean value);
+ void enableSystemCecControl(in boolean value);
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCecCallback.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCecCallback.aidl
new file mode 100644
index 0000000..1918765
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/IHdmiCecCallback.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.tv.cec;
+@VintfStability
+interface IHdmiCecCallback {
+ oneway void onCecMessage(in android.hardware.tv.cec.CecMessage message);
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/Result.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/Result.aidl
new file mode 100644
index 0000000..a5ba276
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/Result.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.tv.cec;
+@Backing(type="byte") @VintfStability
+enum Result {
+ SUCCESS = 0,
+ FAILURE_UNKNOWN = 1,
+ FAILURE_INVALID_ARGS = 2,
+ FAILURE_INVALID_STATE = 3,
+ FAILURE_NOT_SUPPORTED = 4,
+ FAILURE_BUSY = 5,
+}
diff --git a/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/SendMessageResult.aidl b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/SendMessageResult.aidl
new file mode 100644
index 0000000..58206c8
--- /dev/null
+++ b/tv/cec/aidl/aidl_api/android.hardware.tv.cec/current/android/hardware/tv/cec/SendMessageResult.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.tv.cec;
+@Backing(type="byte") @VintfStability
+enum SendMessageResult {
+ SUCCESS = 0,
+ NACK = 1,
+ BUSY = 2,
+ FAIL = 3,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/AbortReason.aidl b/tv/cec/aidl/android/hardware/tv/cec/AbortReason.aidl
new file mode 100644
index 0000000..3ae23ec
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/AbortReason.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.tv.cec;
+
+/**
+ * Operand description [Abort Reason]
+ */
+@VintfStability
+@Backing(type="int")
+enum AbortReason {
+ UNRECOGNIZED_MODE = 0,
+ NOT_IN_CORRECT_MODE = 1,
+ CANNOT_PROVIDE_SOURCE = 2,
+ INVALID_OPERAND = 3,
+ REFUSED = 4,
+ UNABLE_TO_DETERMINE = 5,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecDeviceType.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecDeviceType.aidl
new file mode 100644
index 0000000..16dfbec
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/CecDeviceType.aidl
@@ -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.tv.cec;
+
+@VintfStability
+@Backing(type="byte")
+enum CecDeviceType {
+ INACTIVE = -1,
+ TV = 0,
+ RECORDER = 1,
+ TUNER = 3,
+ PLAYBACK = 4,
+ AUDIO_SYSTEM = 5,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecLogicalAddress.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecLogicalAddress.aidl
new file mode 100644
index 0000000..fbf5328
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/CecLogicalAddress.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.tv.cec;
+
+@VintfStability
+@Backing(type="byte")
+enum CecLogicalAddress {
+ TV = 0,
+ RECORDER_1 = 1,
+ RECORDER_2 = 2,
+ TUNER_1 = 3,
+ PLAYBACK_1 = 4,
+ AUDIO_SYSTEM = 5,
+ TUNER_2 = 6,
+ TUNER_3 = 7,
+ PLAYBACK_2 = 8,
+ RECORDER_3 = 9,
+ TUNER_4 = 10,
+ PLAYBACK_3 = 11,
+ BACKUP_1 = 12,
+ BACKUP_2 = 13,
+ FREE_USE = 14,
+ BROADCAST = 15,
+ UNREGISTERED = 15,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecMessage.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecMessage.aidl
new file mode 100644
index 0000000..b126045
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/CecMessage.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.
+ */
+
+package android.hardware.tv.cec;
+
+import android.hardware.tv.cec.CecLogicalAddress;
+
+@VintfStability
+parcelable CecMessage {
+ /**
+ * Maximum length of the message body
+ */
+ const int MAX_MESSAGE_BODY_LENGTH = 15;
+ /**
+ * logical address of the initiator
+ */
+ CecLogicalAddress initiator;
+ /**
+ * logical address of destination
+ */
+ CecLogicalAddress destination;
+ /**
+ * The maximum size of body is 15 (MAX_MESSAGE_BODY_LENGTH) as specified in
+ * the section 6 of the CEC Spec 1.4b. Overflowed data must be ignored.
+ */
+ byte[] body;
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/CecMessageType.aidl b/tv/cec/aidl/android/hardware/tv/cec/CecMessageType.aidl
new file mode 100644
index 0000000..b544a91
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/CecMessageType.aidl
@@ -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.
+ */
+
+package android.hardware.tv.cec;
+
+@VintfStability
+@Backing(type="int")
+enum CecMessageType {
+ FEATURE_ABORT = 0x00,
+ IMAGE_VIEW_ON = 0x04,
+ TUNER_STEP_INCREMENT = 0x05,
+ TUNER_STEP_DECREMENT = 0x06,
+ TUNER_DEVICE_STATUS = 0x07,
+ GIVE_TUNER_DEVICE_STATUS = 0x08,
+ RECORD_ON = 0x09,
+ RECORD_STATUS = 0x0A,
+ RECORD_OFF = 0x0B,
+ TEXT_VIEW_ON = 0x0D,
+ RECORD_TV_SCREEN = 0x0F,
+ GIVE_DECK_STATUS = 0x1A,
+ DECK_STATUS = 0x1B,
+ SET_MENU_LANGUAGE = 0x32,
+ CLEAR_ANALOG_TIMER = 0x33,
+ SET_ANALOG_TIMER = 0x34,
+ TIMER_STATUS = 0x35,
+ STANDBY = 0x36,
+ PLAY = 0x41,
+ DECK_CONTROL = 0x42,
+ TIMER_CLEARED_STATUS = 0x43,
+ USER_CONTROL_PRESSED = 0x44,
+ USER_CONTROL_RELEASED = 0x45,
+ GIVE_OSD_NAME = 0x46,
+ SET_OSD_NAME = 0x47,
+ SET_OSD_STRING = 0x64,
+ SET_TIMER_PROGRAM_TITLE = 0x67,
+ SYSTEM_AUDIO_MODE_REQUEST = 0x70,
+ GIVE_AUDIO_STATUS = 0x71,
+ SET_SYSTEM_AUDIO_MODE = 0x72,
+ REPORT_AUDIO_STATUS = 0x7A,
+ GIVE_SYSTEM_AUDIO_MODE_STATUS = 0x7D,
+ SYSTEM_AUDIO_MODE_STATUS = 0x7E,
+ ROUTING_CHANGE = 0x80,
+ ROUTING_INFORMATION = 0x81,
+ ACTIVE_SOURCE = 0x82,
+ GIVE_PHYSICAL_ADDRESS = 0x83,
+ REPORT_PHYSICAL_ADDRESS = 0x84,
+ REQUEST_ACTIVE_SOURCE = 0x85,
+ SET_STREAM_PATH = 0x86,
+ DEVICE_VENDOR_ID = 0x87,
+ VENDOR_COMMAND = 0x89,
+ VENDOR_REMOTE_BUTTON_DOWN = 0x8A,
+ VENDOR_REMOTE_BUTTON_UP = 0x8B,
+ GIVE_DEVICE_VENDOR_ID = 0x8C,
+ MENU_REQUEST = 0x8D,
+ MENU_STATUS = 0x8E,
+ GIVE_DEVICE_POWER_STATUS = 0x8F,
+ REPORT_POWER_STATUS = 0x90,
+ GET_MENU_LANGUAGE = 0x91,
+ SELECT_ANALOG_SERVICE = 0x92,
+ SELECT_DIGITAL_SERVICE = 0x93,
+ SET_DIGITAL_TIMER = 0x97,
+ CLEAR_DIGITAL_TIMER = 0x99,
+ SET_AUDIO_RATE = 0x9A,
+ INACTIVE_SOURCE = 0x9D,
+ CEC_VERSION = 0x9E,
+ GET_CEC_VERSION = 0x9F,
+ VENDOR_COMMAND_WITH_ID = 0xA0,
+ CLEAR_EXTERNAL_TIMER = 0xA1,
+ SET_EXTERNAL_TIMER = 0xA2,
+ REPORT_SHORT_AUDIO_DESCRIPTOR = 0xA3,
+ REQUEST_SHORT_AUDIO_DESCRIPTOR = 0xA4,
+ INITIATE_ARC = 0xC0,
+ REPORT_ARC_INITIATED = 0xC1,
+ REPORT_ARC_TERMINATED = 0xC2,
+ REQUEST_ARC_INITIATION = 0xC3,
+ REQUEST_ARC_TERMINATION = 0xC4,
+ TERMINATE_ARC = 0xC5,
+ ABORT = 0xFF,
+ GIVE_FEATURES = 0xA5,
+ REPORT_FEATURES = 0xA6,
+ REQUEST_CURRENT_LATENCY = 0xA7,
+ REPORT_CURRENT_LATENCY = 0xA8,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/IHdmiCec.aidl b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCec.aidl
new file mode 100644
index 0000000..dbf7139
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCec.aidl
@@ -0,0 +1,156 @@
+/*
+ * 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.tv.cec;
+
+import android.hardware.tv.cec.CecLogicalAddress;
+import android.hardware.tv.cec.CecMessage;
+import android.hardware.tv.cec.IHdmiCecCallback;
+import android.hardware.tv.cec.Result;
+import android.hardware.tv.cec.SendMessageResult;
+
+/**
+ * HDMI-CEC HAL interface definition.
+ */
+@VintfStability
+interface IHdmiCec {
+ /**
+ * Passes the logical address that must be used in this system.
+ *
+ * HAL must use it to configure the hardware so that the CEC commands
+ * addressed the given logical address can be filtered in. This method must
+ * be able to be called as many times as necessary in order to support
+ * multiple logical devices.
+ *
+ * @param addr Logical address that must be used in this system. It must be
+ * in the range of valid logical addresses for the call to succeed.
+ * @return Result status of the operation. SUCCESS if successful,
+ * FAILURE_INVALID_ARGS if the given logical address is invalid,
+ * FAILURE_BUSY if device or resource is busy
+ */
+ Result addLogicalAddress(in CecLogicalAddress addr);
+
+ /**
+ * Clears all the logical addresses.
+ *
+ * It is used when the system doesn't need to process CEC command any more,
+ * hence to tell HAL to stop receiving commands from the CEC bus, and change
+ * the state back to the beginning.
+ */
+ void clearLogicalAddress();
+
+ /**
+ * Configures ARC circuit in the hardware logic to start or stop the
+ * feature.
+ *
+ * @param portId Port id to be configured.
+ * @param enable Flag must be either true to start the feature or false to
+ * stop it.
+ */
+ void enableAudioReturnChannel(in int portId, in boolean enable);
+
+ /**
+ * Returns the CEC version supported by underlying hardware.
+ *
+ * @return the CEC version supported by underlying hardware.
+ */
+ int getCecVersion();
+
+ /**
+ * Gets the CEC physical address.
+ *
+ * The physical address depends on the topology of the network formed by
+ * connected HDMI devices. It is therefore likely to change if the cable is
+ * plugged off and on again. It is advised to call getPhysicalAddress to get
+ * the updated address when hot plug event takes place.
+ *
+ * @param out addr Physical address of this device.
+ */
+ int getPhysicalAddress();
+
+ /**
+ * Gets the identifier of the vendor.
+ *
+ * @return Identifier of the vendor that is the 24-bit unique
+ * company ID obtained from the IEEE Registration Authority
+ * Committee (RAC). The upper 8 bits must be 0.
+ */
+ int getVendorId();
+
+ /**
+ * Transmits HDMI-CEC message to other HDMI device.
+ *
+ * The method must be designed to return in a certain amount of time and not
+ * hanging forever which may happen if CEC signal line is pulled low for
+ * some reason.
+ *
+ * It must try retransmission at least once as specified in the section '7.1
+ * Frame Re-transmissions' of the CEC Spec 1.4b.
+ *
+ * @param message CEC message to be sent to other HDMI device.
+ * @return Result status of the operation. SUCCESS if successful,
+ * NACK if the sent message is not acknowledged,
+ * BUSY if the CEC bus is busy,
+ * FAIL if the message could not be sent.
+ */
+ SendMessageResult sendMessage(in CecMessage message);
+
+ /**
+ * Sets a callback that HDMI-CEC HAL must later use for incoming CEC
+ * messages.
+ *
+ * @param callback Callback object to pass hdmi events to the system. The
+ * previously registered callback must be replaced with this one.
+ * setCallback(null) should deregister the callback.
+ */
+ void setCallback(in IHdmiCecCallback callback);
+
+ /**
+ * Passes the updated language information of Android system. Contains
+ * three-letter code as defined in ISO/FDIS 639-2. Must be used for HAL to
+ * respond to <Get Menu Language> while in standby mode.
+ *
+ * @param language Three-letter code defined in ISO/FDIS 639-2. Must be
+ * lowercase letters. (e.g., eng for English)
+ */
+ void setLanguage(in String language);
+
+ /**
+ * Determines whether a TV panel device in standby mode should wake up when
+ * it receives an OTP (One Touch Play) from a source device.
+ *
+ * @param value If true, the TV device will wake up when OTP is received
+ * and if false, the TV device will not wake up for an OTP.
+ */
+ void enableWakeupByOtp(in boolean value);
+
+ /**
+ * Switch to enable or disable CEC on the device.
+ *
+ * @param value If true, the device will have all CEC functionalities
+ * and if false, the device will not perform any CEC functions.
+ */
+ void enableCec(in boolean value);
+
+ /**
+ * Determines which module processes CEC messages - the Android framework or
+ * the HAL.
+ *
+ * @param value If true, the Android framework will actively process CEC
+ * messages and if false, only the HAL will process the CEC messages.
+ */
+ void enableSystemCecControl(in boolean value);
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/IHdmiCecCallback.aidl b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCecCallback.aidl
new file mode 100644
index 0000000..4934a64
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/IHdmiCecCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * 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.tv.cec;
+
+import android.hardware.tv.cec.CecMessage;
+
+/**
+ * Callbacks from the HAL implementation to notify the system of new events.
+ */
+@VintfStability
+oneway interface IHdmiCecCallback {
+ /**
+ * The callback function that must be called by HAL implementation to notify
+ * the system of new CEC message arrival.
+ */
+ void onCecMessage(in CecMessage message);
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/Result.aidl b/tv/cec/aidl/android/hardware/tv/cec/Result.aidl
new file mode 100644
index 0000000..3184c46
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/Result.aidl
@@ -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.tv.cec;
+
+@VintfStability
+@Backing(type="byte")
+enum Result {
+ SUCCESS = 0,
+ FAILURE_UNKNOWN = 1,
+ FAILURE_INVALID_ARGS = 2,
+ FAILURE_INVALID_STATE = 3,
+ FAILURE_NOT_SUPPORTED = 4,
+ FAILURE_BUSY = 5,
+}
diff --git a/tv/cec/aidl/android/hardware/tv/cec/SendMessageResult.aidl b/tv/cec/aidl/android/hardware/tv/cec/SendMessageResult.aidl
new file mode 100644
index 0000000..8cb98bc
--- /dev/null
+++ b/tv/cec/aidl/android/hardware/tv/cec/SendMessageResult.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.tv.cec;
+
+/**
+ * error code used for send_message.
+ */
+@VintfStability
+@Backing(type="byte")
+enum SendMessageResult {
+ SUCCESS = 0,
+ NACK = 1,
+ BUSY = 2,
+ FAIL = 3,
+}
diff --git a/tv/cec/aidl/default/Android.bp b/tv/cec/aidl/default/Android.bp
new file mode 100644
index 0000000..5479601
--- /dev/null
+++ b/tv/cec/aidl/default/Android.bp
@@ -0,0 +1,58 @@
+// 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"],
+}
+
+cc_binary {
+ name: "android.hardware.tv.cec-service",
+ vintf_fragments: ["android.hardware.tv.cec-service.xml"],
+ relative_install_path: "hw",
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ ],
+ init_rc: ["android.hardware.tv.cec-service.rc"],
+ srcs: [
+ "serviceMock.cpp",
+ "HdmiCecMock.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "liblog",
+ "libbase",
+ "libutils",
+ "libhardware",
+ "libhidlbase",
+ "android.hardware.tv.cec-V1-ndk",
+ ],
+}
+
+cc_fuzz {
+ name: "android.hardware.tv.cec-service_fuzzer",
+ defaults: ["service_fuzzer_defaults"],
+ static_libs: [
+ "android.hardware.tv.cec-V1-ndk",
+ "liblog",
+ ],
+ srcs: [
+ "fuzzer.cpp",
+ "HdmiCecMock.cpp",
+ ],
+ fuzz_config: {
+ componentid: 826094,
+ },
+}
diff --git a/tv/cec/aidl/default/HdmiCecMock.cpp b/tv/cec/aidl/default/HdmiCecMock.cpp
new file mode 100644
index 0000000..d8d655b
--- /dev/null
+++ b/tv/cec/aidl/default/HdmiCecMock.cpp
@@ -0,0 +1,266 @@
+/*
+ * 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 "android.hardware.tv.cec"
+#include <android-base/logging.h>
+#include <fcntl.h>
+#include <utils/Log.h>
+
+#include <hardware/hardware.h>
+#include <hardware/hdmi_cec.h>
+#include "HdmiCecMock.h"
+
+using ndk::ScopedAStatus;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace implementation {
+
+void HdmiCecMock::serviceDied(void* cookie) {
+ ALOGE("HdmiCecMock died");
+ auto hdmiCecMock = static_cast<HdmiCecMock*>(cookie);
+ hdmiCecMock->mCecThreadRun = false;
+}
+
+ScopedAStatus HdmiCecMock::addLogicalAddress(CecLogicalAddress addr, Result* _aidl_return) {
+ // Have a list to maintain logical addresses
+ mLogicalAddresses.push_back(addr);
+ *_aidl_return = Result::SUCCESS;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::clearLogicalAddress() {
+ // Remove logical address from the list
+ mLogicalAddresses = {};
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::enableAudioReturnChannel(int32_t portId __unused, bool enable __unused) {
+ // Maintain ARC status
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::getCecVersion(int32_t* _aidl_return) {
+ // Maintain a cec version and return it
+ *_aidl_return = mCecVersion;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::getPhysicalAddress(int32_t* _aidl_return) {
+ // Maintain a physical address and return it
+ // Default 0xFFFF, update on hotplug event
+ *_aidl_return = mPhysicalAddress;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::getVendorId(int32_t* _aidl_return) {
+ *_aidl_return = mCecVendorId;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::sendMessage(const CecMessage& message, SendMessageResult* _aidl_return) {
+ if (message.body.size() == 0) {
+ *_aidl_return = SendMessageResult::NACK;
+ } else {
+ sendMessageToFifo(message);
+ *_aidl_return = SendMessageResult::SUCCESS;
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::setCallback(const std::shared_ptr<IHdmiCecCallback>& callback) {
+ // If callback is null, mCallback is also set to null so we do not call the old callback.
+ mCallback = callback;
+
+ if (callback != nullptr) {
+ AIBinder_linkToDeath(this->asBinder().get(), mDeathRecipient.get(), 0 /* cookie */);
+
+ mInputFile = open(CEC_MSG_IN_FIFO, O_RDWR | O_CLOEXEC);
+ mOutputFile = open(CEC_MSG_OUT_FIFO, O_RDWR | O_CLOEXEC);
+ pthread_create(&mThreadId, NULL, __threadLoop, this);
+ pthread_setname_np(mThreadId, "hdmi_cec_loop");
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::setLanguage(const std::string& language) {
+ if (language.size() != 3) {
+ LOG(ERROR) << "Wrong language code: expected 3 letters, but it was " << language.size()
+ << ".";
+ return ScopedAStatus::ok();
+ }
+ // TODO Validate if language is a valid language code
+ const char* languageStr = language.c_str();
+ int convertedLanguage = ((languageStr[0] & 0xFF) << 16) | ((languageStr[1] & 0xFF) << 8) |
+ (languageStr[2] & 0xFF);
+ mOptionLanguage = convertedLanguage;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::enableWakeupByOtp(bool value) {
+ mOptionWakeUp = value;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::enableCec(bool value) {
+ mOptionEnableCec = value;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiCecMock::enableSystemCecControl(bool value) {
+ mOptionSystemCecControl = value;
+ return ScopedAStatus::ok();
+}
+
+void* HdmiCecMock::__threadLoop(void* user) {
+ HdmiCecMock* const self = static_cast<HdmiCecMock*>(user);
+ self->threadLoop();
+ return 0;
+}
+
+int HdmiCecMock::readMessageFromFifo(unsigned char* buf, int msgCount) {
+ if (msgCount <= 0 || !buf) {
+ return 0;
+ }
+
+ int ret = -1;
+ // Maybe blocked at driver
+ ret = read(mInputFile, buf, msgCount);
+ if (ret < 0) {
+ ALOGE("[halimp_aidl] read :%s failed, ret:%d\n", CEC_MSG_IN_FIFO, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+int HdmiCecMock::sendMessageToFifo(const CecMessage& message) {
+ unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH + 1] = {0};
+ int ret = -1;
+
+ msgBuf[0] = ((static_cast<uint8_t>(message.initiator) & 0xf) << 4) |
+ (static_cast<uint8_t>(message.destination) & 0xf);
+
+ size_t length = std::min(static_cast<size_t>(message.body.size()),
+ static_cast<size_t>(CEC_MESSAGE_BODY_MAX_LENGTH));
+ for (size_t i = 0; i < length; ++i) {
+ msgBuf[i + 1] = static_cast<unsigned char>(message.body[i]);
+ }
+
+ // Open the output pipe for writing outgoing cec message
+ mOutputFile = open(CEC_MSG_OUT_FIFO, O_WRONLY | O_CLOEXEC);
+ if (mOutputFile < 0) {
+ ALOGD("[halimp_aidl] file open failed for writing");
+ return -1;
+ }
+
+ // Write message into the output pipe
+ ret = write(mOutputFile, msgBuf, length + 1);
+ close(mOutputFile);
+ if (ret < 0) {
+ ALOGE("[halimp_aidl] write :%s failed, ret:%d\n", CEC_MSG_OUT_FIFO, ret);
+ return -1;
+ }
+ return ret;
+}
+
+void HdmiCecMock::printCecMsgBuf(const char* msg_buf, int len) {
+ int i, size = 0;
+ const int bufSize = CEC_MESSAGE_BODY_MAX_LENGTH * 3;
+ // Use 2 characters for each byte in the message plus 1 space
+ char buf[bufSize] = {0};
+
+ // Messages longer than max length will be truncated.
+ for (i = 0; i < len && size < bufSize; i++) {
+ size += sprintf(buf + size, " %02x", msg_buf[i]);
+ }
+ ALOGD("[halimp_aidl] %s, msg:%.*s", __FUNCTION__, size, buf);
+}
+
+void HdmiCecMock::handleCecMessage(unsigned char* msgBuf, int msgSize) {
+ CecMessage message;
+ size_t length = std::min(static_cast<size_t>(msgSize - 1),
+ static_cast<size_t>(CEC_MESSAGE_BODY_MAX_LENGTH));
+ message.body.resize(length);
+
+ for (size_t i = 0; i < length; ++i) {
+ message.body[i] = static_cast<uint8_t>(msgBuf[i + 1]);
+ ALOGD("[halimp_aidl] msg body %x", message.body[i]);
+ }
+
+ message.initiator = static_cast<CecLogicalAddress>((msgBuf[0] >> 4) & 0xf);
+ ALOGD("[halimp_aidl] msg init %hhd", message.initiator);
+ message.destination = static_cast<CecLogicalAddress>((msgBuf[0] >> 0) & 0xf);
+ ALOGD("[halimp_aidl] msg dest %hhd", message.destination);
+
+ if (mCallback != nullptr) {
+ mCallback->onCecMessage(message);
+ }
+}
+
+void HdmiCecMock::threadLoop() {
+ ALOGD("[halimp_aidl] threadLoop start.");
+ unsigned char msgBuf[CEC_MESSAGE_BODY_MAX_LENGTH];
+ int r = -1;
+
+ // Open the input pipe
+ while (mInputFile < 0) {
+ usleep(1000 * 1000);
+ mInputFile = open(CEC_MSG_IN_FIFO, O_RDONLY | O_CLOEXEC);
+ }
+ ALOGD("[halimp_aidl] file open ok, fd = %d.", mInputFile);
+
+ while (mCecThreadRun) {
+ if (!mOptionSystemCecControl) {
+ usleep(1000 * 1000);
+ continue;
+ }
+
+ memset(msgBuf, 0, sizeof(msgBuf));
+ // Try to get a message from dev.
+ // echo -n -e '\x04\x83' >> /dev/cec
+ r = readMessageFromFifo(msgBuf, CEC_MESSAGE_BODY_MAX_LENGTH);
+ if (r <= 1) {
+ // Ignore received ping messages
+ continue;
+ }
+
+ printCecMsgBuf((const char*)msgBuf, r);
+
+ if (((msgBuf[0] >> 4) & 0xf) == 0xf) {
+ // The message is a hotplug event, handled by HDMI HAL.
+ continue;
+ }
+
+ handleCecMessage(msgBuf, r);
+ }
+
+ ALOGD("[halimp_aidl] thread end.");
+}
+
+HdmiCecMock::HdmiCecMock() {
+ ALOGE("[halimp_aidl] Opening a virtual CEC HAL for testing and virtual machine.");
+ mCallback = nullptr;
+ mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied));
+}
+
+} // namespace implementation
+} // namespace cec
+} // namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/cec/aidl/default/HdmiCecMock.h b/tv/cec/aidl/default/HdmiCecMock.h
new file mode 100644
index 0000000..08f4d6f
--- /dev/null
+++ b/tv/cec/aidl/default/HdmiCecMock.h
@@ -0,0 +1,94 @@
+/*
+ * 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/android/hardware/tv/cec/BnHdmiCec.h>
+#include <algorithm>
+#include <vector>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace cec {
+namespace implementation {
+
+using ::aidl::android::hardware::tv::cec::BnHdmiCec;
+using ::aidl::android::hardware::tv::cec::CecLogicalAddress;
+using ::aidl::android::hardware::tv::cec::CecMessage;
+using ::aidl::android::hardware::tv::cec::IHdmiCec;
+using ::aidl::android::hardware::tv::cec::IHdmiCecCallback;
+using ::aidl::android::hardware::tv::cec::Result;
+using ::aidl::android::hardware::tv::cec::SendMessageResult;
+
+#define CEC_MSG_IN_FIFO "/dev/cec_aidl_in_pipe"
+#define CEC_MSG_OUT_FIFO "/dev/cec_aidl_out_pipe"
+
+struct HdmiCecMock : public BnHdmiCec {
+ HdmiCecMock();
+ ::ndk::ScopedAStatus addLogicalAddress(CecLogicalAddress addr, Result* _aidl_return) override;
+ ::ndk::ScopedAStatus clearLogicalAddress() override;
+ ::ndk::ScopedAStatus enableAudioReturnChannel(int32_t portId, bool enable) override;
+ ::ndk::ScopedAStatus getCecVersion(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getPhysicalAddress(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus getVendorId(int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus sendMessage(const CecMessage& message,
+ SendMessageResult* _aidl_return) override;
+ ::ndk::ScopedAStatus setCallback(const std::shared_ptr<IHdmiCecCallback>& callback) override;
+ ::ndk::ScopedAStatus setLanguage(const std::string& language) override;
+ ::ndk::ScopedAStatus enableWakeupByOtp(bool value) override;
+ ::ndk::ScopedAStatus enableCec(bool value) override;
+ ::ndk::ScopedAStatus enableSystemCecControl(bool value) override;
+ void printCecMsgBuf(const char* msg_buf, int len);
+
+ private:
+ static void* __threadLoop(void* data);
+ void threadLoop();
+ int readMessageFromFifo(unsigned char* buf, int msgCount);
+ int sendMessageToFifo(const CecMessage& message);
+ void handleCecMessage(unsigned char* msgBuf, int length);
+
+ private:
+ static void serviceDied(void* cookie);
+ std::shared_ptr<IHdmiCecCallback> mCallback;
+
+ // Variables for the virtual cec hal impl
+ uint16_t mPhysicalAddress = 0xFFFF;
+ vector<CecLogicalAddress> mLogicalAddresses;
+ int32_t mCecVersion = 0x06;
+ uint32_t mCecVendorId = 0x01;
+
+ // CEC Option value
+ bool mOptionWakeUp = 0;
+ bool mOptionEnableCec = 0;
+ bool mOptionSystemCecControl = 0;
+ int mOptionLanguage;
+
+ // Testing variables
+ // Input file descriptor
+ int mInputFile;
+ // Output file descriptor
+ int mOutputFile;
+ bool mCecThreadRun = true;
+ pthread_t mThreadId = 0;
+
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+};
+} // namespace implementation
+} // namespace cec
+} // namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/cec/aidl/default/android.hardware.tv.cec-service.rc b/tv/cec/aidl/default/android.hardware.tv.cec-service.rc
new file mode 100644
index 0000000..c79520c
--- /dev/null
+++ b/tv/cec/aidl/default/android.hardware.tv.cec-service.rc
@@ -0,0 +1,5 @@
+service vendor.cec-default /vendor/bin/hw/android.hardware.tv.cec-service
+ interface aidl android.hardware.tv.cec.IHdmiCec/default
+ class hal
+ user system
+ group system
diff --git a/tv/cec/aidl/default/android.hardware.tv.cec-service.xml b/tv/cec/aidl/default/android.hardware.tv.cec-service.xml
new file mode 100644
index 0000000..e68450d
--- /dev/null
+++ b/tv/cec/aidl/default/android.hardware.tv.cec-service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.tv.cec</name>
+ <version>1</version>
+ <interface>
+ <name>IHdmiCec</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/tv/cec/aidl/default/fuzzer.cpp b/tv/cec/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..9f6a9ac
--- /dev/null
+++ b/tv/cec/aidl/default/fuzzer.cpp
@@ -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.
+ */
+#include <HdmiCecMock.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using android::fuzzService;
+using android::hardware::tv::cec::implementation::HdmiCecMock;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto hdmiCecAidl = SharedRefBase::make<HdmiCecMock>();
+
+ fuzzService(hdmiCecAidl->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
diff --git a/tv/cec/aidl/default/serviceMock.cpp b/tv/cec/aidl/default/serviceMock.cpp
new file mode 100644
index 0000000..ab86c3f
--- /dev/null
+++ b/tv/cec/aidl/default/serviceMock.cpp
@@ -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.
+ */
+
+#define LOG_TAG "android.hardware.tv.cec-service-shim"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Log.h>
+#include "HdmiCecMock.h"
+
+using android::hardware::tv::cec::implementation::HdmiCecMock;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+
+ std::shared_ptr<HdmiCecMock> hdmiCecAidl = ndk::SharedRefBase::make<HdmiCecMock>();
+ const std::string instance = std::string() + HdmiCecMock::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(hdmiCecAidl->asBinder().get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return 0;
+}
diff --git a/tv/cec/aidl/vts/functional/Android.bp b/tv/cec/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..37fbaf0
--- /dev/null
+++ b/tv/cec/aidl/vts/functional/Android.bp
@@ -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.
+
+package {
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+cc_test {
+ name: "VtsHalTvCecAidlTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalTvCecAidlTargetTest.cpp"],
+ static_libs: [
+ "android.hardware.tv.cec-V1-ndk",
+ "android.hardware.tv.hdmi-V1-ndk",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ disable_framework: true,
+}
diff --git a/tv/cec/aidl/vts/functional/AndroidTest.xml b/tv/cec/aidl/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..8604147
--- /dev/null
+++ b/tv/cec/aidl/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalTvCecAidlTargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalTvCecAidlTargetTest->/data/local/tmp/VtsHalTvCecAidlTargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalTvCecAidlTargetTest" />
+ <option name="native-test-timeout" value="30m" />
+ </test>
+</configuration>
diff --git a/tv/cec/aidl/vts/functional/VtsHalTvCecAidlTargetTest.cpp b/tv/cec/aidl/vts/functional/VtsHalTvCecAidlTargetTest.cpp
new file mode 100644
index 0000000..69c209f
--- /dev/null
+++ b/tv/cec/aidl/vts/functional/VtsHalTvCecAidlTargetTest.cpp
@@ -0,0 +1,170 @@
+/*
+ * 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 "HdmiCec_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/tv/cec/BnHdmiCec.h>
+#include <aidl/android/hardware/tv/cec/BnHdmiCecCallback.h>
+#include <aidl/android/hardware/tv/cec/CecDeviceType.h>
+#include <aidl/android/hardware/tv/hdmi/BnHdmi.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <sstream>
+#include <vector>
+
+using ::aidl::android::hardware::tv::cec::BnHdmiCecCallback;
+using ::aidl::android::hardware::tv::cec::CecDeviceType;
+using ::aidl::android::hardware::tv::cec::CecLogicalAddress;
+using ::aidl::android::hardware::tv::cec::CecMessage;
+using ::aidl::android::hardware::tv::cec::IHdmiCec;
+using ::aidl::android::hardware::tv::cec::IHdmiCecCallback;
+using ::aidl::android::hardware::tv::cec::Result;
+using ::aidl::android::hardware::tv::cec::SendMessageResult;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortInfo;
+using ::ndk::SpAIBinder;
+
+#define CEC_VERSION 0x05
+#define INCORRECT_VENDOR_ID 0x00
+#define TV_PHYSICAL_ADDRESS 0x0000
+
+// The main test class for TV CEC HAL.
+class HdmiCecTest : public ::testing::TestWithParam<std::string> {
+ static void serviceDied(void* /* cookie */) { ALOGE("VtsHalTvCecAidlTargetTest died"); }
+
+ public:
+ void SetUp() override {
+ hdmiCec = IHdmiCec::fromBinder(
+ SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(hdmiCec, nullptr);
+ ALOGI("%s: getService() for hdmiCec is %s", __func__,
+ hdmiCec->isRemote() ? "remote" : "local");
+
+ hdmiCecCallback = ::ndk::SharedRefBase::make<CecCallback>();
+ ASSERT_NE(hdmiCecCallback, nullptr);
+ hdmiCecDeathRecipient =
+ ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&serviceDied));
+ ASSERT_EQ(AIBinder_linkToDeath(hdmiCec->asBinder().get(), hdmiCecDeathRecipient.get(), 0),
+ STATUS_OK);
+ }
+
+ std::vector<int> getDeviceTypes() {
+ std::vector<int> deviceTypes;
+ FILE* p = popen("getprop ro.hdmi.device_type", "re");
+ if (p) {
+ char* line = NULL;
+ size_t len = 0;
+ if (getline(&line, &len, p) > 0) {
+ std::istringstream stream(line);
+ std::string number{};
+ while (std::getline(stream, number, ',')) {
+ deviceTypes.push_back(stoi(number));
+ }
+ }
+ pclose(p);
+ }
+ return deviceTypes;
+ }
+
+ bool hasDeviceType(CecDeviceType type) {
+ std::vector<int> deviceTypes = getDeviceTypes();
+ return std::find(deviceTypes.begin(), deviceTypes.end(), (int)type) != deviceTypes.end();
+ }
+
+ class CecCallback : public BnHdmiCecCallback {
+ public:
+ ::ndk::ScopedAStatus onCecMessage(const CecMessage& message __unused) {
+ return ::ndk::ScopedAStatus::ok();
+ };
+ };
+
+ std::shared_ptr<IHdmiCec> hdmiCec;
+ std::shared_ptr<IHdmiCecCallback> hdmiCecCallback;
+ ::ndk::ScopedAIBinder_DeathRecipient hdmiCecDeathRecipient;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HdmiCecTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, HdmiCecTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IHdmiCec::descriptor)),
+ android::PrintInstanceNameToString);
+
+TEST_P(HdmiCecTest, ClearAddLogicalAddress) {
+ Result addLaResult;
+ ASSERT_TRUE(hdmiCec->clearLogicalAddress().isOk());
+ ASSERT_TRUE(hdmiCec->addLogicalAddress(CecLogicalAddress::PLAYBACK_3, &addLaResult).isOk());
+ EXPECT_EQ(addLaResult, Result::SUCCESS);
+}
+
+TEST_P(HdmiCecTest, PhysicalAddress) {
+ int32_t addr;
+ ASSERT_TRUE(hdmiCec->getPhysicalAddress(&addr).isOk());
+ if (!hasDeviceType(CecDeviceType::TV)) {
+ EXPECT_NE(addr, TV_PHYSICAL_ADDRESS);
+ }
+}
+
+TEST_P(HdmiCecTest, SendMessage) {
+ CecMessage message;
+ message.initiator = CecLogicalAddress::PLAYBACK_1;
+ message.destination = CecLogicalAddress::BROADCAST;
+ message.body.resize(1);
+ message.body[0] = 131;
+ SendMessageResult result;
+ ASSERT_TRUE(hdmiCec->sendMessage(message, &result).isOk());
+ EXPECT_EQ(result, SendMessageResult::SUCCESS);
+}
+
+TEST_P(HdmiCecTest, CecVersion) {
+ int32_t version;
+ ASSERT_TRUE(hdmiCec->getCecVersion(&version).isOk());
+ EXPECT_GE(version, CEC_VERSION);
+}
+
+TEST_P(HdmiCecTest, SetCallback) {
+ ASSERT_TRUE(hdmiCec->setCallback(::ndk::SharedRefBase::make<CecCallback>()).isOk());
+}
+
+TEST_P(HdmiCecTest, VendorId) {
+ int32_t vendorId;
+ ASSERT_TRUE(hdmiCec->getVendorId(&vendorId).isOk());
+ EXPECT_NE(vendorId, INCORRECT_VENDOR_ID);
+}
+
+TEST_P(HdmiCecTest, EnableWakeupByOtp) {
+ ASSERT_TRUE(hdmiCec->enableWakeupByOtp(false).isOk());
+ // Restore option to its default value
+ ASSERT_TRUE(hdmiCec->enableWakeupByOtp(true).isOk());
+}
+
+TEST_P(HdmiCecTest, EnableCec) {
+ ASSERT_TRUE(hdmiCec->enableCec(false).isOk());
+ // Restore option to its default value
+ ASSERT_TRUE(hdmiCec->enableCec(true).isOk());
+}
+
+TEST_P(HdmiCecTest, EnableSystemCecControl) {
+ ASSERT_TRUE(hdmiCec->enableSystemCecControl(true).isOk());
+ // Restore option to its default value
+ ASSERT_TRUE(hdmiCec->enableSystemCecControl(false).isOk());
+}
+
+TEST_P(HdmiCecTest, SetLanguage) {
+ ASSERT_TRUE(hdmiCec->setLanguage("eng").isOk());
+}
diff --git a/tv/hdmi/aidl/Android.bp b/tv/hdmi/aidl/Android.bp
new file mode 100644
index 0000000..d8c6e5f
--- /dev/null
+++ b/tv/hdmi/aidl/Android.bp
@@ -0,0 +1,29 @@
+// 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"],
+}
+
+aidl_interface {
+ name: "android.hardware.tv.hdmi",
+ vendor_available: true,
+ srcs: ["android/hardware/tv/hdmi/*.aidl"],
+ stability: "vintf",
+ backend: {
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+}
diff --git a/tv/hdmi/aidl/OWNERS b/tv/hdmi/aidl/OWNERS
new file mode 100644
index 0000000..d9c6783
--- /dev/null
+++ b/tv/hdmi/aidl/OWNERS
@@ -0,0 +1,2 @@
+# Bug component: 826094
+include platform/frameworks/base:/core/java/android/hardware/hdmi/OWNERS
\ No newline at end of file
diff --git a/tv/hdmi/aidl/TEST_MAPPING b/tv/hdmi/aidl/TEST_MAPPING
new file mode 100644
index 0000000..6bd3b57
--- /dev/null
+++ b/tv/hdmi/aidl/TEST_MAPPING
@@ -0,0 +1,7 @@
+{
+ "presubmit": [
+ {
+ "name": "VtsHalTvHdmiAidlTargetTest"
+ }
+ ]
+}
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortInfo.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortInfo.aidl
new file mode 100644
index 0000000..25c3be1
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortInfo.aidl
@@ -0,0 +1,43 @@
+/*
+ * 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.tv.hdmi;
+@VintfStability
+parcelable HdmiPortInfo {
+ android.hardware.tv.hdmi.HdmiPortType type;
+ int portId;
+ boolean cecSupported;
+ boolean arcSupported;
+ boolean eArcSupported;
+ int physicalAddress;
+}
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortType.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortType.aidl
new file mode 100644
index 0000000..af5f0f7
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HdmiPortType.aidl
@@ -0,0 +1,39 @@
+/*
+ * 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.tv.hdmi;
+@Backing(type="byte") @VintfStability
+enum HdmiPortType {
+ INPUT = 0,
+ OUTPUT = 1,
+}
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmi.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmi.aidl
new file mode 100644
index 0000000..3fc7f41
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmi.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.tv.hdmi;
+@VintfStability
+interface IHdmi {
+ android.hardware.tv.hdmi.HdmiPortInfo[] getPortInfo();
+ boolean isConnected(in int portId);
+ void setCallback(in android.hardware.tv.hdmi.IHdmiCallback callback);
+}
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmiCallback.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmiCallback.aidl
new file mode 100644
index 0000000..05fe623
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/IHdmiCallback.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.tv.hdmi;
+@VintfStability
+interface IHdmiCallback {
+ oneway void onHotplugEvent(in boolean connected, in int portId);
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortInfo.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortInfo.aidl
new file mode 100644
index 0000000..2e2c858
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortInfo.aidl
@@ -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.tv.hdmi;
+
+import android.hardware.tv.hdmi.HdmiPortType;
+
+/**
+ * HDMI port descriptor
+ */
+@VintfStability
+parcelable HdmiPortInfo {
+ HdmiPortType type;
+ int portId; // Should start from 1 which corresponds to HDMI "port 1".
+ boolean cecSupported;
+ boolean arcSupported;
+ boolean eArcSupported;
+ // The physical address of the device connected to this port, valid range is 0x0000 to 0xFFFF
+ // (ref Sec 8.7.2 of HDMI 1.4b).
+ int physicalAddress;
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortType.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortType.aidl
new file mode 100644
index 0000000..59c0d42
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/HdmiPortType.aidl
@@ -0,0 +1,27 @@
+/*
+ * 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.tv.hdmi;
+
+/**
+ * HDMI port type.
+ */
+@VintfStability
+@Backing(type="byte")
+enum HdmiPortType {
+ INPUT = 0,
+ OUTPUT = 1,
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl
new file mode 100644
index 0000000..5536846
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.tv.hdmi;
+
+import android.hardware.tv.hdmi.HdmiPortInfo;
+import android.hardware.tv.hdmi.IHdmiCallback;
+
+/**
+ * HDMI HAL interface definition.
+ */
+@VintfStability
+interface IHdmi {
+ /**
+ * Gets the hdmi port information of underlying hardware.
+ *
+ * @return The list of HDMI port information
+ */
+ HdmiPortInfo[] getPortInfo();
+
+ /**
+ * Gets the connection status of the specified port.
+ *
+ * @param portId Port id to be inspected for the connection status.
+ * @return True if a device is connected, otherwise false. The HAL
+ * must watch for +5V power signal to determine the status.
+ */
+ boolean isConnected(in int portId);
+
+ /**
+ * Sets a callback that HDMI HAL must later use for internal HDMI events
+ *
+ * @param callback Callback object to pass hdmi events to the system. The
+ * previously registered callback must be replaced with this one.
+ * setCallback(null) should deregister the callback.
+ */
+ void setCallback(in IHdmiCallback callback);
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmiCallback.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmiCallback.aidl
new file mode 100644
index 0000000..51275b0
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmiCallback.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.tv.hdmi;
+
+/**
+ * Callbacks from the HDMI HAL implementation to notify the system of new events.
+ */
+@VintfStability
+oneway interface IHdmiCallback {
+ /**
+ * The callback function that must be called by HAL implementation to notify
+ * the system of new hotplug event.
+ */
+ void onHotplugEvent(in boolean connected, in int portId);
+}
diff --git a/tv/hdmi/aidl/default/Android.bp b/tv/hdmi/aidl/default/Android.bp
new file mode 100644
index 0000000..3e466a0
--- /dev/null
+++ b/tv/hdmi/aidl/default/Android.bp
@@ -0,0 +1,58 @@
+// 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"],
+}
+
+cc_binary {
+ name: "android.hardware.tv.hdmi-service",
+ vintf_fragments: ["android.hardware.tv.hdmi-service.xml"],
+ relative_install_path: "hw",
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ ],
+ init_rc: ["android.hardware.tv.hdmi-service.rc"],
+ srcs: [
+ "serviceMock.cpp",
+ "HdmiMock.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "liblog",
+ "libbase",
+ "libutils",
+ "libhardware",
+ "libhidlbase",
+ "android.hardware.tv.hdmi-V1-ndk",
+ ],
+}
+
+cc_fuzz {
+ name: "android.hardware.tv.hdmi-service_fuzzer",
+ defaults: ["service_fuzzer_defaults"],
+ static_libs: [
+ "android.hardware.tv.hdmi-V1-ndk",
+ "liblog",
+ ],
+ srcs: [
+ "fuzzer.cpp",
+ "HdmiMock.cpp",
+ ],
+ fuzz_config: {
+ componentid: 826094,
+ },
+}
diff --git a/tv/hdmi/aidl/default/HdmiMock.cpp b/tv/hdmi/aidl/default/HdmiMock.cpp
new file mode 100644
index 0000000..bbc4705
--- /dev/null
+++ b/tv/hdmi/aidl/default/HdmiMock.cpp
@@ -0,0 +1,179 @@
+/*
+ * 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 "android.hardware.tv.hdmi"
+#include <android-base/logging.h>
+#include <fcntl.h>
+#include <utils/Log.h>
+
+#include "HdmiMock.h"
+
+using ndk::ScopedAStatus;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace hdmi {
+namespace implementation {
+
+void HdmiMock::serviceDied(void* cookie) {
+ ALOGE("HdmiMock died");
+ auto hdmi = static_cast<HdmiMock*>(cookie);
+ hdmi->mHdmiThreadRun = false;
+}
+
+ScopedAStatus HdmiMock::getPortInfo(std::vector<HdmiPortInfo>* _aidl_return) {
+ *_aidl_return = mPortInfos;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiMock::isConnected(int32_t portId, bool* _aidl_return) {
+ // Maintain port connection status and update on hotplug event
+ if (portId <= mTotalPorts && portId >= 1) {
+ *_aidl_return = mPortConnectionStatus[portId];
+ } else {
+ *_aidl_return = false;
+ }
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus HdmiMock::setCallback(const std::shared_ptr<IHdmiCallback>& callback) {
+ if (mCallback != nullptr) {
+ mCallback = nullptr;
+ }
+
+ if (callback != nullptr) {
+ mCallback = callback;
+ AIBinder_linkToDeath(this->asBinder().get(), mDeathRecipient.get(), 0 /* cookie */);
+
+ mInputFile = open(HDMI_MSG_IN_FIFO, O_RDWR | O_CLOEXEC);
+ pthread_create(&mThreadId, NULL, __threadLoop, this);
+ pthread_setname_np(mThreadId, "hdmi_loop");
+ }
+ return ScopedAStatus::ok();
+}
+
+void* HdmiMock::__threadLoop(void* user) {
+ HdmiMock* const self = static_cast<HdmiMock*>(user);
+ self->threadLoop();
+ return 0;
+}
+
+int HdmiMock::readMessageFromFifo(unsigned char* buf, int msgCount) {
+ if (msgCount <= 0 || !buf) {
+ return 0;
+ }
+
+ int ret = -1;
+ // Maybe blocked at driver
+ ret = read(mInputFile, buf, msgCount);
+ if (ret < 0) {
+ ALOGE("[halimp_aidl] read :%s failed, ret:%d\n", HDMI_MSG_IN_FIFO, ret);
+ return -1;
+ }
+
+ return ret;
+}
+
+void HdmiMock::printEventBuf(const char* msg_buf, int len) {
+ int i, size = 0;
+ const int bufSize = MESSAGE_BODY_MAX_LENGTH * 3;
+ // Use 2 characters for each byte in the message plus 1 space
+ char buf[bufSize] = {0};
+
+ // Messages longer than max length will be truncated.
+ for (i = 0; i < len && size < bufSize; i++) {
+ size += sprintf(buf + size, " %02x", msg_buf[i]);
+ }
+ ALOGD("[halimp_aidl] %s, msg:%.*s", __FUNCTION__, size, buf);
+}
+
+void HdmiMock::handleHotplugMessage(unsigned char* msgBuf) {
+ bool connected = ((msgBuf[3]) & 0xf) > 0;
+ int32_t portId = static_cast<uint32_t>(msgBuf[0] & 0xf);
+
+ if (portId > static_cast<int32_t>(mPortInfos.size())) {
+ ALOGD("[halimp_aidl] ignore hot plug message, id %x does not exist", portId);
+ return;
+ }
+
+ ALOGD("[halimp_aidl] hot plug port id %x, is connected %x", (msgBuf[0] & 0xf),
+ (msgBuf[3] & 0xf));
+ mPortConnectionStatus[portId] = connected;
+ if (mPortInfos[portId].type == HdmiPortType::OUTPUT) {
+ mPhysicalAddress = (connected ? 0xffff : ((msgBuf[1] << 8) | (msgBuf[2])));
+ mPortInfos[portId].physicalAddress = mPhysicalAddress;
+ ALOGD("[halimp_aidl] hot plug physical address %x", mPhysicalAddress);
+ }
+
+ if (mCallback != nullptr) {
+ mCallback->onHotplugEvent(connected, portId);
+ }
+}
+
+void HdmiMock::threadLoop() {
+ ALOGD("[halimp_aidl] threadLoop start.");
+ unsigned char msgBuf[MESSAGE_BODY_MAX_LENGTH];
+ int r = -1;
+
+ // Open the input pipe
+ while (mInputFile < 0) {
+ usleep(1000 * 1000);
+ mInputFile = open(HDMI_MSG_IN_FIFO, O_RDONLY | O_CLOEXEC);
+ }
+ ALOGD("[halimp_aidl] file open ok, fd = %d.", mInputFile);
+
+ while (mHdmiThreadRun) {
+ memset(msgBuf, 0, sizeof(msgBuf));
+ // Try to get a message from dev.
+ // echo -n -e '\x04\x83' >> /dev/cec
+ r = readMessageFromFifo(msgBuf, MESSAGE_BODY_MAX_LENGTH);
+ if (r <= 1) {
+ // Ignore received ping messages
+ continue;
+ }
+
+ printEventBuf((const char*)msgBuf, r);
+
+ if (((msgBuf[0] >> 4) & 0xf) == 0xf) {
+ handleHotplugMessage(msgBuf);
+ }
+ }
+
+ ALOGD("[halimp_aidl] thread end.");
+}
+
+HdmiMock::HdmiMock() {
+ ALOGE("[halimp_aidl] Opening a virtual HDMI HAL for testing and virtual machine.");
+ mCallback = nullptr;
+ mPortInfos.resize(mTotalPorts);
+ mPortConnectionStatus.resize(mTotalPorts);
+ mPortInfos[0] = {.type = HdmiPortType::OUTPUT,
+ .portId = static_cast<uint32_t>(1),
+ .cecSupported = true,
+ .arcSupported = false,
+ .eArcSupported = false,
+ .physicalAddress = mPhysicalAddress};
+ mPortConnectionStatus[0] = false;
+ mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied));
+}
+
+} // namespace implementation
+} // namespace hdmi
+} // namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/hdmi/aidl/default/HdmiMock.h b/tv/hdmi/aidl/default/HdmiMock.h
new file mode 100644
index 0000000..05795dd
--- /dev/null
+++ b/tv/hdmi/aidl/default/HdmiMock.h
@@ -0,0 +1,77 @@
+/*
+ * 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/android/hardware/tv/hdmi/BnHdmi.h>
+#include <algorithm>
+#include <vector>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace hdmi {
+namespace implementation {
+
+using ::aidl::android::hardware::tv::hdmi::BnHdmi;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortInfo;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortType;
+using ::aidl::android::hardware::tv::hdmi::IHdmi;
+using ::aidl::android::hardware::tv::hdmi::IHdmiCallback;
+
+#define HDMI_MSG_IN_FIFO "/dev/hdmi_in_pipe"
+#define MESSAGE_BODY_MAX_LENGTH 4
+
+struct HdmiMock : public BnHdmi {
+ HdmiMock();
+
+ ::ndk::ScopedAStatus getPortInfo(std::vector<HdmiPortInfo>* _aidl_return) override;
+ ::ndk::ScopedAStatus isConnected(int32_t portId, bool* _aidl_return) override;
+ ::ndk::ScopedAStatus setCallback(const std::shared_ptr<IHdmiCallback>& callback) override;
+
+ void printEventBuf(const char* msg_buf, int len);
+
+ private:
+ static void* __threadLoop(void* data);
+ void threadLoop();
+ int readMessageFromFifo(unsigned char* buf, int msgCount);
+ void handleHotplugMessage(unsigned char* msgBuf);
+
+ private:
+ static void serviceDied(void* cookie);
+ std::shared_ptr<IHdmiCallback> mCallback;
+
+ // Variables for the virtual HDMI hal impl
+ std::vector<HdmiPortInfo> mPortInfos;
+ std::vector<bool> mPortConnectionStatus;
+
+ // Port configuration
+ uint16_t mPhysicalAddress = 0xFFFF;
+ int mTotalPorts = 1;
+
+ // Testing variables
+ // Input file descriptor
+ int mInputFile;
+ bool mHdmiThreadRun = true;
+ pthread_t mThreadId = 0;
+
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+};
+} // namespace implementation
+} // namespace hdmi
+} // Namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.rc b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.rc
new file mode 100644
index 0000000..c926221
--- /dev/null
+++ b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.rc
@@ -0,0 +1,5 @@
+service vendor.hdmi-default /vendor/bin/hw/android.hardware.tv.hdmi-service
+ interface aidl android.hardware.tv.hdmi.IHdmi/default
+ class hal
+ user system
+ group system
diff --git a/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.xml b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.xml
new file mode 100644
index 0000000..a03c199
--- /dev/null
+++ b/tv/hdmi/aidl/default/android.hardware.tv.hdmi-service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.tv.hdmi</name>
+ <version>1</version>
+ <interface>
+ <name>IHdmi</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/tv/hdmi/aidl/default/fuzzer.cpp b/tv/hdmi/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..06a2bc0
--- /dev/null
+++ b/tv/hdmi/aidl/default/fuzzer.cpp
@@ -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.
+ */
+#include <HdmiMock.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using android::fuzzService;
+using android::hardware::tv::hdmi::implementation::HdmiMock;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto hdmiAidl = SharedRefBase::make<HdmiMock>();
+
+ fuzzService(hdmiAidl->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
diff --git a/tv/hdmi/aidl/default/serviceMock.cpp b/tv/hdmi/aidl/default/serviceMock.cpp
new file mode 100644
index 0000000..1d8bf51
--- /dev/null
+++ b/tv/hdmi/aidl/default/serviceMock.cpp
@@ -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.
+ */
+
+#define LOG_TAG "android.hardware.tv.hdmi-service-shim"
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <hidl/HidlTransportSupport.h>
+#include <utils/Log.h>
+#include "HdmiMock.h"
+
+using android::hardware::tv::hdmi::implementation::HdmiMock;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+
+ std::shared_ptr<HdmiMock> hdmiAidl = ndk::SharedRefBase::make<HdmiMock>();
+ const std::string instance = std::string() + HdmiMock::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(hdmiAidl->asBinder().get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return 0;
+}
diff --git a/tv/hdmi/aidl/vts/functional/Android.bp b/tv/hdmi/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..f9af58d
--- /dev/null
+++ b/tv/hdmi/aidl/vts/functional/Android.bp
@@ -0,0 +1,37 @@
+// 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"],
+}
+
+cc_test {
+ name: "VtsHalTvHdmiAidlTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalTvHdmiAidlTargetTest.cpp"],
+ static_libs: [
+ "android.hardware.tv.hdmi-V1-ndk",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ disable_framework: true,
+}
diff --git a/tv/hdmi/aidl/vts/functional/AndroidTest.xml b/tv/hdmi/aidl/vts/functional/AndroidTest.xml
new file mode 100644
index 0000000..0640b2d
--- /dev/null
+++ b/tv/hdmi/aidl/vts/functional/AndroidTest.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- 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.
+-->
+<configuration description="Runs VtsHalTvHdmiAidlTargetTest.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-native" />
+
+ <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer">
+ </target_preparer>
+
+ <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+ <option name="cleanup" value="true" />
+ <option name="push" value="VtsHalTvHdmiAidlTargetTest->/data/local/tmp/VtsHalTvHdmiAidlTargetTest" />
+ </target_preparer>
+
+ <test class="com.android.tradefed.testtype.GTest" >
+ <option name="native-test-device-path" value="/data/local/tmp" />
+ <option name="module-name" value="VtsHalTvHdmiAidlTargetTest" />
+ <option name="native-test-timeout" value="30m" />
+ </test>
+</configuration>
diff --git a/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp b/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp
new file mode 100644
index 0000000..78c2590
--- /dev/null
+++ b/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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 "Hdmi_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/tv/hdmi/BnHdmi.h>
+#include <aidl/android/hardware/tv/hdmi/BnHdmiCallback.h>
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <gtest/gtest.h>
+#include <log/log.h>
+#include <sstream>
+#include <vector>
+
+using ::aidl::android::hardware::tv::hdmi::BnHdmiCallback;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortInfo;
+using ::aidl::android::hardware::tv::hdmi::HdmiPortType;
+using ::aidl::android::hardware::tv::hdmi::IHdmi;
+using ::aidl::android::hardware::tv::hdmi::IHdmiCallback;
+using ::ndk::SpAIBinder;
+
+#define INCORRECT_VENDOR_ID 0x00
+#define TV_PHYSICAL_ADDRESS 0x0000
+
+// The main test class for TV HDMI HAL.
+class HdmiTest : public ::testing::TestWithParam<std::string> {
+ static void serviceDied(void* /* cookie */) { ALOGE("VtsHalTvCecAidlTargetTest died"); }
+
+ public:
+ void SetUp() override {
+ hdmi = IHdmi::fromBinder(SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(hdmi, nullptr);
+ ALOGI("%s: getService() for hdmi is %s", __func__, hdmi->isRemote() ? "remote" : "local");
+
+ hdmiCallback = ::ndk::SharedRefBase::make<HdmiCallback>();
+ ASSERT_NE(hdmiCallback, nullptr);
+ hdmiDeathRecipient =
+ ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&serviceDied));
+ ASSERT_EQ(AIBinder_linkToDeath(hdmi->asBinder().get(), hdmiDeathRecipient.get(), 0),
+ STATUS_OK);
+ }
+
+ class HdmiCallback : public BnHdmiCallback {
+ public:
+ ::ndk::ScopedAStatus onHotplugEvent(bool connected __unused, int32_t portId __unused) {
+ return ::ndk::ScopedAStatus::ok();
+ };
+ };
+
+ std::shared_ptr<IHdmi> hdmi;
+ std::shared_ptr<IHdmiCallback> hdmiCallback;
+ ::ndk::ScopedAIBinder_DeathRecipient hdmiDeathRecipient;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HdmiTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, HdmiTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IHdmi::descriptor)),
+ android::PrintInstanceNameToString);
+
+TEST_P(HdmiTest, SetCallback) {
+ ASSERT_TRUE(hdmi->setCallback(::ndk::SharedRefBase::make<HdmiCallback>()).isOk());
+}
+
+TEST_P(HdmiTest, GetPortInfo) {
+ std::vector<HdmiPortInfo> ports;
+ ASSERT_TRUE(hdmi->getPortInfo(&ports).isOk());
+
+ bool cecSupportedOnDevice = false;
+ for (size_t i = 0; i < ports.size(); ++i) {
+ EXPECT_TRUE((ports[i].type == HdmiPortType::OUTPUT) ||
+ (ports[i].type == HdmiPortType::INPUT));
+ if (ports[i].portId == 0) {
+ ALOGW("%s: Port id should start from 1", __func__);
+ }
+ cecSupportedOnDevice = cecSupportedOnDevice | ports[i].cecSupported;
+ }
+ EXPECT_NE(cecSupportedOnDevice, false) << "At least one port should support CEC";
+}
+
+TEST_P(HdmiTest, IsConnected) {
+ std::vector<HdmiPortInfo> ports;
+ ASSERT_TRUE(hdmi->getPortInfo(&ports).isOk());
+ for (size_t i = 0; i < ports.size(); ++i) {
+ bool connected;
+ ASSERT_TRUE(hdmi->isConnected(ports[i].portId, &connected).isOk());
+ }
+}
diff --git a/tv/input/aidl/default/TvInput.cpp b/tv/input/aidl/default/TvInput.cpp
index 6c3a138..ed12cbc 100644
--- a/tv/input/aidl/default/TvInput.cpp
+++ b/tv/input/aidl/default/TvInput.cpp
@@ -96,8 +96,7 @@
}
mStreamConfigs[in_deviceId][in_streamId]->handle = createNativeHandle(in_streamId);
mStreamConfigs[in_deviceId][in_streamId]->isOpen = true;
- NativeHandle aidlHandle = makeToAidl(mStreamConfigs[in_deviceId][in_streamId]->handle);
- _aidl_return = &aidlHandle;
+ *_aidl_return = makeToAidl(mStreamConfigs[in_deviceId][in_streamId]->handle);
return ::ndk::ScopedAStatus::ok();
}
diff --git a/tv/tuner/OWNERS b/tv/tuner/OWNERS
new file mode 100644
index 0000000..83e090d
--- /dev/null
+++ b/tv/tuner/OWNERS
@@ -0,0 +1,6 @@
+# Bug component: 136752
+
+quxiangfang@google.com
+shubang@google.com
+hgchen@google.com
+raychin@google.com
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl
index 450cd79..4648712 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/IDvr.aidl
@@ -43,4 +43,5 @@
void stop();
void flush();
void close();
+ void setStatusCheckIntervalHint(in long milliseconds);
}
diff --git a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl
index 0ff2da9..5d1d215 100644
--- a/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl
+++ b/tv/tuner/aidl/aidl_api/android.hardware.tv.tuner/current/android/hardware/tv/tuner/ITuner.aidl
@@ -47,4 +47,5 @@
void setLna(in boolean bEnable);
void setMaxNumberOfFrontends(in android.hardware.tv.tuner.FrontendType frontendType, in int maxNumber);
int getMaxNumberOfFrontends(in android.hardware.tv.tuner.FrontendType frontendType);
+ boolean isLnaSupported();
}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl
index 0534f9d..4cb5b15 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/IDvr.aidl
@@ -18,7 +18,6 @@
import android.hardware.common.fmq.MQDescriptor;
import android.hardware.common.fmq.SynchronizedReadWrite;
-
import android.hardware.tv.tuner.DvrSettings;
import android.hardware.tv.tuner.IFilter;
@@ -101,4 +100,12 @@
* instance any more and all methods should return a failure.
*/
void close();
+
+ /**
+ * Set status check time interval.
+ *
+ * This time interval hint will be used by the Dvr to decide how often
+ * to evaluate data.
+ */
+ void setStatusCheckIntervalHint(in long milliseconds);
}
diff --git a/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
index 03def33..4a0b7a2 100644
--- a/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
+++ b/tv/tuner/aidl/android/hardware/tv/tuner/ITuner.aidl
@@ -125,6 +125,9 @@
/**
* Enable or Disable Low Noise Amplifier (LNA).
*
+ * If the device doesn't support LNA, the HAL implement should set {@link Result#UNAVAILABLE}
+ * to EX_SERVICE_SPECIFIC as the service specific error.
+ *
* @param bEnable true if activate LNA module; false if deactivate LNA
*/
void setLna(in boolean bEnable);
@@ -148,4 +151,11 @@
* @return the maximum usable number of the queried frontend type.
*/
int getMaxNumberOfFrontends(in FrontendType frontendType);
+
+ /**
+ * Is Low Noise Amplifier (LNA) supported.
+ *
+ * @return true if supported, otherwise false
+ */
+ boolean isLnaSupported();
}
diff --git a/tv/tuner/aidl/default/Android.bp b/tv/tuner/aidl/default/Android.bp
index c10ad22..65fa821 100644
--- a/tv/tuner/aidl/default/Android.bp
+++ b/tv/tuner/aidl/default/Android.bp
@@ -29,7 +29,7 @@
],
shared_libs: [
"android.hardware.common.fmq-V1-ndk",
- "android.hardware.tv.tuner-V1-ndk",
+ "android.hardware.tv.tuner-V2-ndk",
"libbase",
"libbinder_ndk",
"libcutils",
diff --git a/tv/tuner/aidl/default/Dvr.cpp b/tv/tuner/aidl/default/Dvr.cpp
index 9928a59..c9dd8ee 100644
--- a/tv/tuner/aidl/default/Dvr.cpp
+++ b/tv/tuner/aidl/default/Dvr.cpp
@@ -154,6 +154,14 @@
return ::ndk::ScopedAStatus::ok();
}
+::ndk::ScopedAStatus Dvr::setStatusCheckIntervalHint(int64_t /* in_milliseconds */) {
+ ALOGV("%s", __FUNCTION__);
+
+ // There is no active polling in this default implementation,
+ // so directly return ok here.
+ return ::ndk::ScopedAStatus::ok();
+}
+
bool Dvr::createDvrMQ() {
ALOGV("%s", __FUNCTION__);
diff --git a/tv/tuner/aidl/default/Dvr.h b/tv/tuner/aidl/default/Dvr.h
index 6ff71cd..293c533 100644
--- a/tv/tuner/aidl/default/Dvr.h
+++ b/tv/tuner/aidl/default/Dvr.h
@@ -70,6 +70,7 @@
::ndk::ScopedAStatus stop() override;
::ndk::ScopedAStatus flush() override;
::ndk::ScopedAStatus close() override;
+ ::ndk::ScopedAStatus setStatusCheckIntervalHint(int64_t in_milliseconds) override;
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
diff --git a/tv/tuner/aidl/default/Tuner.cpp b/tv/tuner/aidl/default/Tuner.cpp
index 591f936..8c715a0 100644
--- a/tv/tuner/aidl/default/Tuner.cpp
+++ b/tv/tuner/aidl/default/Tuner.cpp
@@ -204,6 +204,13 @@
return ::ndk::ScopedAStatus::ok();
}
+::ndk::ScopedAStatus Tuner::isLnaSupported(bool* _aidl_return) {
+ ALOGV("%s", __FUNCTION__);
+
+ *_aidl_return = true;
+ return ::ndk::ScopedAStatus::ok();
+}
+
binder_status_t Tuner::dump(int fd, const char** args, uint32_t numArgs) {
ALOGV("%s", __FUNCTION__);
{
diff --git a/tv/tuner/aidl/default/Tuner.h b/tv/tuner/aidl/default/Tuner.h
index ad73003..a77c930 100644
--- a/tv/tuner/aidl/default/Tuner.h
+++ b/tv/tuner/aidl/default/Tuner.h
@@ -61,6 +61,7 @@
int32_t in_maxNumber) override;
::ndk::ScopedAStatus getMaxNumberOfFrontends(FrontendType in_frontendType,
int32_t* _aidl_return) override;
+ ::ndk::ScopedAStatus isLnaSupported(bool* _aidl_return) override;
binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
diff --git a/tv/tuner/aidl/vts/functional/Android.bp b/tv/tuner/aidl/vts/functional/Android.bp
index e5fb1e6..6a71544 100644
--- a/tv/tuner/aidl/vts/functional/Android.bp
+++ b/tv/tuner/aidl/vts/functional/Android.bp
@@ -53,7 +53,7 @@
"android.hardware.cas@1.2",
"android.hardware.common-V2-ndk",
"android.hardware.common.fmq-V1-ndk",
- "android.hardware.tv.tuner-V1-ndk",
+ "android.hardware.tv.tuner-V2-ndk",
"libaidlcommonsupport",
"libfmq",
"libcutils",
diff --git a/tv/tuner/aidl/vts/functional/DvrTests.cpp b/tv/tuner/aidl/vts/functional/DvrTests.cpp
index a9c3b51..50f4de2 100644
--- a/tv/tuner/aidl/vts/functional/DvrTests.cpp
+++ b/tv/tuner/aidl/vts/functional/DvrTests.cpp
@@ -323,3 +323,41 @@
ASSERT_TRUE(mDvrRecord);
ASSERT_TRUE(mDvrRecord->close().isOk());
}
+
+AssertionResult DvrTests::setPlaybackStatusCheckIntervalHint(int64_t milliseconds) {
+ ndk::ScopedAStatus status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrPlayback) << "Test with openDvr first.";
+
+ status = mDvrPlayback->setStatusCheckIntervalHint(milliseconds);
+
+ if (getDvrPlaybackInterfaceVersion() < 2) {
+ return AssertionResult(status.getStatus() == STATUS_UNKNOWN_TRANSACTION);
+ }
+ return AssertionResult(status.isOk());
+}
+
+AssertionResult DvrTests::setRecordStatusCheckIntervalHint(int64_t milliseconds) {
+ ndk::ScopedAStatus status;
+ EXPECT_TRUE(mDemux) << "Test with openDemux first.";
+ EXPECT_TRUE(mDvrRecord) << "Test with openDvr first.";
+
+ status = mDvrRecord->setStatusCheckIntervalHint(milliseconds);
+
+ if (getDvrRecordInterfaceVersion() < 2) {
+ return AssertionResult(status.getStatus() == STATUS_UNKNOWN_TRANSACTION);
+ }
+ return AssertionResult(status.isOk());
+}
+
+int32_t DvrTests::getDvrPlaybackInterfaceVersion() {
+ int32_t version;
+ mDvrPlayback->getInterfaceVersion(&version);
+ return version;
+}
+
+int32_t DvrTests::getDvrRecordInterfaceVersion() {
+ int32_t version;
+ mDvrRecord->getInterfaceVersion(&version);
+ return version;
+}
diff --git a/tv/tuner/aidl/vts/functional/DvrTests.h b/tv/tuner/aidl/vts/functional/DvrTests.h
index 6662637..a88ba24 100644
--- a/tv/tuner/aidl/vts/functional/DvrTests.h
+++ b/tv/tuner/aidl/vts/functional/DvrTests.h
@@ -162,8 +162,12 @@
AssertionResult startDvrPlayback();
AssertionResult stopDvrRecord();
AssertionResult startDvrRecord();
+ AssertionResult setPlaybackStatusCheckIntervalHint(int64_t milliseconds);
+ AssertionResult setRecordStatusCheckIntervalHint(int64_t milliseconds);
void closeDvrPlayback();
void closeDvrRecord();
+ int32_t getDvrPlaybackInterfaceVersion();
+ int32_t getDvrRecordInterfaceVersion();
protected:
static AssertionResult failure() { return ::testing::AssertionFailure(); }
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
index 9a17d05..6aa1e16 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.cpp
@@ -241,6 +241,28 @@
ASSERT_TRUE(mDemuxTests.closeDemux());
}
+void TunerPlaybackAidlTest::setStatusCheckIntervalHintTest(int64_t statusCheckIntervalHint,
+ DvrConfig dvrConf) {
+ int32_t demuxId;
+ std::shared_ptr<IDemux> demux;
+
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ mDvrTests.setDemux(demux);
+ ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+ ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
+
+ ASSERT_TRUE(mDvrTests.setPlaybackStatusCheckIntervalHint(statusCheckIntervalHint));
+
+ mDvrTests.startPlaybackInputThread(dvrConf.playbackInputFile,
+ dvrConf.settings.get<DvrSettings::Tag::playback>());
+ ASSERT_TRUE(mDvrTests.startDvrPlayback());
+ mDvrTests.stopPlaybackThread();
+ ASSERT_TRUE(mDvrTests.stopDvrPlayback());
+ mDvrTests.closeDvrPlayback();
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+}
+
void TunerRecordAidlTest::recordSingleFilterTestWithLnb(FilterConfig filterConf,
FrontendConfig frontendConf,
DvrConfig dvrConf, LnbConfig lnbConf) {
@@ -426,6 +448,45 @@
ASSERT_TRUE(mDemuxTests.closeDemux());
}
+void TunerRecordAidlTest::setStatusCheckIntervalHintTest(int64_t statusCheckIntervalHint,
+ FrontendConfig frontendConf,
+ DvrConfig dvrConf) {
+ int32_t demuxId;
+ std::shared_ptr<IDemux> demux;
+ ASSERT_TRUE(mDemuxTests.openDemux(demux, demuxId));
+ mDvrTests.setDemux(demux);
+
+ DvrConfig dvrSourceConfig;
+ if (record.hasFrontendConnection) {
+ int32_t feId;
+ mFrontendTests.getFrontendIdByType(frontendConf.type, feId);
+ ASSERT_TRUE(feId != INVALID_ID);
+ ASSERT_TRUE(mFrontendTests.openFrontendById(feId));
+ ASSERT_TRUE(mFrontendTests.setFrontendCallback());
+ ASSERT_TRUE(mDemuxTests.setDemuxFrontendDataSource(feId));
+ } else {
+ dvrSourceConfig = dvrMap[record.dvrSourceId];
+ ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrSourceConfig.type, dvrSourceConfig.bufferSize));
+ ASSERT_TRUE(mDvrTests.configDvrPlayback(dvrSourceConfig.settings));
+ ASSERT_TRUE(mDvrTests.getDvrPlaybackMQDescriptor());
+ }
+
+ ASSERT_TRUE(mDvrTests.openDvrInDemux(dvrConf.type, dvrConf.bufferSize));
+ ASSERT_TRUE(mDvrTests.configDvrRecord(dvrConf.settings));
+ ASSERT_TRUE(mDvrTests.getDvrRecordMQDescriptor());
+
+ ASSERT_TRUE(mDvrTests.setRecordStatusCheckIntervalHint(statusCheckIntervalHint));
+
+ ASSERT_TRUE(mDvrTests.startDvrRecord());
+ ASSERT_TRUE(mDvrTests.stopDvrRecord());
+ mDvrTests.closeDvrRecord();
+ ASSERT_TRUE(mDemuxTests.closeDemux());
+
+ if (record.hasFrontendConnection) {
+ ASSERT_TRUE(mFrontendTests.closeFrontend());
+ }
+}
+
void TunerDescramblerAidlTest::scrambledBroadcastTest(set<struct FilterConfig> mediaFilterConfs,
FrontendConfig frontendConf,
DescramblerConfig descConfig,
@@ -1000,6 +1061,18 @@
}
}
+TEST_P(TunerPlaybackAidlTest, SetStatusCheckIntervalHintToPlaybackTest) {
+ description("Set status check interval hint to playback test.");
+ if (!playback.support) {
+ return;
+ }
+ vector<DvrPlaybackHardwareConnections> playback_configs = generatePlaybackConfigs();
+ for (auto& configuration : playback_configs) {
+ playback = configuration;
+ setStatusCheckIntervalHintTest(STATUS_CHECK_INTERVAL_MS, dvrMap[playback.dvrId]);
+ }
+}
+
TEST_P(TunerRecordAidlTest, RecordDataFlowWithTsRecordFilterTest) {
description("Feed ts data from frontend to recording and test with ts record filter");
if (!record.support) {
@@ -1046,6 +1119,19 @@
}
}
+TEST_P(TunerRecordAidlTest, SetStatusCheckIntervalHintToRecordTest) {
+ description("Set status check interval hint to record test.");
+ if (!record.support) {
+ return;
+ }
+ auto record_configs = generateRecordConfigurations();
+ for (auto& configuration : record_configs) {
+ record = configuration;
+ setStatusCheckIntervalHintTest(STATUS_CHECK_INTERVAL_MS, frontendMap[record.frontendId],
+ dvrMap[record.dvrRecordId]);
+ }
+}
+
TEST_P(TunerFrontendAidlTest, TuneFrontend) {
description("Tune one Frontend with specific setting and check Lock event");
if (!live.hasFrontendConnection) {
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
index f68e1ec..3bfa78f 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTargetTest.h
@@ -255,6 +255,8 @@
AssertionResult filterDataOutputTest();
void playbackSingleFilterTest(FilterConfig filterConf, DvrConfig dvrConf);
+
+ void setStatusCheckIntervalHintTest(int64_t milliseconds, DvrConfig dvrConf);
};
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TunerPlaybackAidlTest);
@@ -294,6 +296,8 @@
DvrConfig dvrConf, LnbConfig lnbConf);
void recordSingleFilterTest(FilterConfig filterConf, FrontendConfig frontendConf,
DvrConfig dvrConf, Dataflow_Context context);
+ void setStatusCheckIntervalHintTest(int64_t milliseconds, FrontendConfig frontendConf,
+ DvrConfig dvrConf);
std::shared_ptr<ITuner> mService;
FrontendTests mFrontendTests;
diff --git a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
index fea5f83..516cb62 100644
--- a/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
+++ b/tv/tuner/aidl/vts/functional/VtsHalTvTunerTestConfigurations.h
@@ -55,6 +55,7 @@
const string configFilePath = "/vendor/etc/tuner_vts_config_aidl_V1.xml";
#define FILTER_MAIN_TYPE_BIT_COUNT 5
+#define STATUS_CHECK_INTERVAL_MS 100L
// Hardware configs
static map<string, FrontendConfig> frontendMap;
diff --git a/usb/1.0/default/Android.bp b/usb/1.0/default/Android.bp
index 4bed2c7..5f56fe0 100644
--- a/usb/1.0/default/Android.bp
+++ b/usb/1.0/default/Android.bp
@@ -21,21 +21,11 @@
default_applicable_licenses: ["hardware_interfaces_license"],
}
-filegroup {
- name: "android.hardware.usb@1.0-service.xml",
- srcs: ["android.hardware.usb@1.0-service.xml"],
-}
-
-filegroup {
- name: "android.hardware.usb@1.0-service.rc",
- srcs: ["android.hardware.usb@1.0-service.rc"],
-}
-
cc_binary {
name: "android.hardware.usb@1.0-service",
defaults: ["hidl_defaults"],
- init_rc: [":android.hardware.usb@1.0-service.rc"],
- vintf_fragments: [":android.hardware.usb@1.0-service.xml"],
+ init_rc: ["android.hardware.usb@1.0-service.rc"],
+ vintf_fragments: ["android.hardware.usb@1.0-service.xml"],
relative_install_path: "hw",
vendor: true,
srcs: [
diff --git a/usb/1.0/default/apex/Android.bp b/usb/1.0/default/apex/Android.bp
deleted file mode 100644
index ee50fdf..0000000
--- a/usb/1.0/default/apex/Android.bp
+++ /dev/null
@@ -1,59 +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 {
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-apex_key {
- name: "com.android.hardware.usb.key",
- public_key: "com.android.hardware.usb.avbpubkey",
- private_key: "com.android.hardware.usb.pem",
-}
-
-android_app_certificate {
- name: "com.android.hardware.usb.certificate",
- certificate: "com.android.hardware.usb",
-}
-
-genrule {
- name: "com.android.hardware.usb.rc-gen",
- srcs: [":android.hardware.usb@1.0-service.rc"],
- out: ["com.android.hardware.usb.rc"],
- cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.usb/' $(in) > $(out)",
-}
-
-prebuilt_etc {
- name: "com.android.hardware.usb.rc",
- src: ":com.android.hardware.usb.rc-gen",
- installable: false,
-}
-
-apex {
- name: "com.android.hardware.usb",
- manifest: "manifest.json",
- file_contexts: "file_contexts",
- key: "com.android.hardware.usb.key",
- certificate: ":com.android.hardware.usb.certificate",
- updatable: false,
- soc_specific: true,
- use_vndk_as_stable: true,
- binaries: ["android.hardware.usb@1.0-service"],
- prebuilts: [
- "com.android.hardware.usb.rc",
- "android.hardware.usb.accessory.prebuilt.xml",
- "android.hardware.usb.host.prebuilt.xml",
- ],
- vintf_fragments: [":android.hardware.usb@1.0-service.xml"],
-}
diff --git a/usb/1.0/default/apex/file_contexts b/usb/1.0/default/apex/file_contexts
deleted file mode 100644
index bc84ac4..0000000
--- a/usb/1.0/default/apex/file_contexts
+++ /dev/null
@@ -1,5 +0,0 @@
-(/.*)? u:object_r:vendor_file:s0
-# Permission XMLs
-/etc/permissions(/.*)? u:object_r:vendor_configs_file:s0
-# binary
-/bin/hw/android\.hardware\.usb@1\.0-service u:object_r:hal_usb_default_exec:s0
\ No newline at end of file
diff --git a/usb/1.0/default/apex/manifest.json b/usb/1.0/default/apex/manifest.json
deleted file mode 100644
index 6a1095f..0000000
--- a/usb/1.0/default/apex/manifest.json
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "name": "com.android.hardware.usb",
- "version": 1
-}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ComplianceWarning.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ComplianceWarning.aidl
new file mode 100644
index 0000000..8b67070
--- /dev/null
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/ComplianceWarning.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.usb;
+@Backing(type="int") @VintfStability
+enum ComplianceWarning {
+ OTHER = 1,
+ DEBUG_ACCESSORY = 2,
+ BC_1_2 = 3,
+ MISSING_RP = 4,
+}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl
index f866c1e..859f526 100644
--- a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/IUsb.aidl
@@ -41,5 +41,5 @@
oneway void setCallback(in android.hardware.usb.IUsbCallback callback);
oneway void switchRole(in String portName, in android.hardware.usb.PortRole role, long transactionId);
oneway void limitPowerTransfer(in String portName, boolean limit, long transactionId);
- oneway void resetUsbPort(in String portName,long transactionId);
+ oneway void resetUsbPort(in String portName, long transactionId);
}
diff --git a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl
index dfd99fb..b0b7552 100644
--- a/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl
+++ b/usb/aidl/aidl_api/android.hardware.usb/current/android/hardware/usb/PortStatus.aidl
@@ -50,4 +50,6 @@
android.hardware.usb.UsbDataStatus[] usbDataStatus;
boolean powerTransferLimited;
android.hardware.usb.PowerBrickStatus powerBrickStatus;
+ boolean supportsComplianceWarnings = false;
+ android.hardware.usb.ComplianceWarning[] complianceWarnings = {};
}
diff --git a/usb/aidl/android/hardware/usb/ComplianceWarning.aidl b/usb/aidl/android/hardware/usb/ComplianceWarning.aidl
new file mode 100644
index 0000000..4c18a31
--- /dev/null
+++ b/usb/aidl/android/hardware/usb/ComplianceWarning.aidl
@@ -0,0 +1,59 @@
+/*
+ * 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.usb;
+
+@VintfStability
+@Backing(type="int")
+/**
+ * Indicates the potential non-compliance reasons for the
+ * connected USB Type-C port partner which could be a power
+ * source, accessory or cable. Applicable for USB-C receptacles
+ * in Android devices.
+ */
+enum ComplianceWarning {
+ /**
+ * Used to indicate Type-C sources/cables/accessories/ports
+ * whose issue is not listed below but do not meet
+ * specification requirements from including but not limited to
+ * USB Type-C Cable and Connector Specification, Universal Serial Bus
+ * Power Delivery Specification, and Universal Serial Bus
+ * 1.x/2.0/3.x/4.0.
+ */
+ OTHER = 1,
+ /**
+ * Used to indicate Type-C port partner
+ * (cable/accessory/source) that identifies itself as debug
+ * accessory source as defined in USB Type-C Cable and
+ * Connector Specification. However, the specification
+ * states that this is meant for debug only and shall not
+ * be used for with commercial products.
+ */
+ DEBUG_ACCESSORY = 2,
+ /**
+ * Used to indicate Type-C port partner that does not
+ * identify itself as one of the charging port types
+ * (SDP/CDP/DCP etc) as defined by Battery Charging v1.2
+ * Specification.
+ */
+ BC_1_2 = 3,
+ /**
+ * Used to indicate Type-C sources/cables that are missing
+ * pull up resistors on the CC pins as required by USB
+ * Type-C Cable and Connector Specification.
+ */
+ MISSING_RP = 4,
+}
diff --git a/usb/aidl/android/hardware/usb/PortStatus.aidl b/usb/aidl/android/hardware/usb/PortStatus.aidl
index 51bee71..d7e61ec 100644
--- a/usb/aidl/android/hardware/usb/PortStatus.aidl
+++ b/usb/aidl/android/hardware/usb/PortStatus.aidl
@@ -19,6 +19,7 @@
import android.hardware.usb.ContaminantDetectionStatus;
import android.hardware.usb.ContaminantProtectionMode;
import android.hardware.usb.ContaminantProtectionStatus;
+import android.hardware.usb.ComplianceWarning;
import android.hardware.usb.PortDataRole;
import android.hardware.usb.PortMode;
import android.hardware.usb.PortPowerRole;
@@ -115,4 +116,15 @@
* Denotes whether Power brick is connected.
*/
PowerBrickStatus powerBrickStatus;
+ /**
+ * True if the hal implementation can support identifying
+ * non compliant USB power source/cable/accessory. False other
+ * otherwise.
+ */
+ boolean supportsComplianceWarnings = false;
+ /**
+ * List of reasons as to why the attached USB
+ * power source/cable/accessory is non compliant.
+ */
+ ComplianceWarning[] complianceWarnings = {};
}
diff --git a/usb/aidl/default/Android.bp b/usb/aidl/default/Android.bp
index 7cb2822..472e732 100644
--- a/usb/aidl/default/Android.bp
+++ b/usb/aidl/default/Android.bp
@@ -34,11 +34,21 @@
"Usb.cpp",
],
shared_libs: [
- "android.hardware.usb-V1-ndk",
+ "android.hardware.usb-V2-ndk",
"libbase",
"libbinder_ndk",
- "libcutils",
+ "libcutils",
"liblog",
"libutils",
],
}
+
+filegroup {
+ name: "android.hardware.usb-service.example.xml",
+ srcs: ["android.hardware.usb-service.example.xml"],
+}
+
+filegroup {
+ name: "android.hardware.usb-service.example.rc",
+ srcs: ["android.hardware.usb-service.example.rc"],
+}
diff --git a/usb/aidl/default/Usb.cpp b/usb/aidl/default/Usb.cpp
index 7e738c4..dd12da0 100644
--- a/usb/aidl/default/Usb.cpp
+++ b/usb/aidl/default/Usb.cpp
@@ -123,6 +123,15 @@
return Status::SUCCESS;
}
+Status queryNonCompliantChargerStatus(std::vector<PortStatus> *currentPortStatus) {
+ string reasons, path;
+
+ for (int i = 0; i < currentPortStatus->size(); i++) {
+ (*currentPortStatus)[i].supportsComplianceWarnings = false;
+ }
+ return Status::SUCCESS;
+}
+
string appendRoleNodeHelper(const string &portName, PortRole::Tag tag) {
string node(kTypecPath + portName);
@@ -527,6 +536,7 @@
pthread_mutex_lock(&usb->mLock);
status = getPortStatusHelper(currentPortStatus);
queryMoistureDetectionStatus(currentPortStatus);
+ queryNonCompliantChargerStatus(currentPortStatus);
if (usb->mCallback != NULL) {
ScopedAStatus ret = usb->mCallback->notifyPortStatusChange(*currentPortStatus,
status);
diff --git a/usb/aidl/default/android.hardware.usb-service.example.xml b/usb/aidl/default/android.hardware.usb-service.example.xml
index 6088194..c3f07f5 100644
--- a/usb/aidl/default/android.hardware.usb-service.example.xml
+++ b/usb/aidl/default/android.hardware.usb-service.example.xml
@@ -1,7 +1,7 @@
<manifest version="1.0" type="device">
<hal format="aidl">
<name>android.hardware.usb</name>
- <version>1</version>
+ <version>2</version>
<interface>
<name>IUsb</name>
<instance>default</instance>
diff --git a/usb/aidl/vts/Android.bp b/usb/aidl/vts/Android.bp
index 00a7c93..d0e0eec 100644
--- a/usb/aidl/vts/Android.bp
+++ b/usb/aidl/vts/Android.bp
@@ -34,7 +34,7 @@
"libbinder_ndk",
],
static_libs: [
- "android.hardware.usb-V1-ndk",
+ "android.hardware.usb-V2-ndk",
],
test_suites: [
"general-tests",
diff --git a/usb/aidl/vts/VtsAidlUsbTargetTest.cpp b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp
index ea2f985..c4ec8a4 100644
--- a/usb/aidl/vts/VtsAidlUsbTargetTest.cpp
+++ b/usb/aidl/vts/VtsAidlUsbTargetTest.cpp
@@ -43,6 +43,7 @@
#define TIMEOUT_PERIOD 10
using ::aidl::android::hardware::usb::BnUsbCallback;
+using ::aidl::android::hardware::usb::ComplianceWarning;
using ::aidl::android::hardware::usb::IUsb;
using ::aidl::android::hardware::usb::IUsbCallback;
using ::aidl::android::hardware::usb::PortDataRole;
@@ -560,6 +561,53 @@
ALOGI("UsbAidlTest resetUsbPort end");
}
+/*
+ * Test charger compliance warning
+ * The test asserts that complianceWarnings is
+ * empty when the feature is not supported. i.e.
+ * supportsComplianceWarning is false.
+ */
+TEST_P(UsbAidlTest, nonCompliantChargerStatus) {
+ ALOGI("UsbAidlTest nonCompliantChargerStatus start");
+ int64_t transactionId = rand() % 10000;
+ const auto& ret = usb->queryPortStatus(transactionId);
+ ASSERT_TRUE(ret.isOk());
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(2, usb_last_cookie);
+ EXPECT_EQ(transactionId, last_transactionId);
+
+ if (!usb_last_port_status.supportsComplianceWarnings) {
+ EXPECT_TRUE(usb_last_port_status.complianceWarnings.empty());
+ }
+
+ ALOGI("UsbAidlTest nonCompliantChargerStatus end");
+}
+
+/*
+ * Test charger compliance warning values
+ * The test asserts that complianceWarning values
+ * are valid.
+ */
+TEST_P(UsbAidlTest, nonCompliantChargerValues) {
+ ALOGI("UsbAidlTest nonCompliantChargerValues start");
+ int64_t transactionId = rand() % 10000;
+ const auto& ret = usb->queryPortStatus(transactionId);
+ ASSERT_TRUE(ret.isOk());
+ EXPECT_EQ(std::cv_status::no_timeout, wait());
+ EXPECT_EQ(2, usb_last_cookie);
+ EXPECT_EQ(transactionId, last_transactionId);
+
+ // Current compliance values range from [1, 4]
+ if (usb_last_port_status.supportsComplianceWarnings) {
+ for (auto warning : usb_last_port_status.complianceWarnings) {
+ EXPECT_TRUE((int)warning >= (int)ComplianceWarning::OTHER);
+ EXPECT_TRUE((int)warning <= (int)ComplianceWarning::MISSING_RP);
+ }
+ }
+
+ ALOGI("UsbAidlTest nonCompliantChargerValues end");
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(UsbAidlTest);
INSTANTIATE_TEST_SUITE_P(
PerInstance, UsbAidlTest,
diff --git a/usb/apex/Android.bp b/usb/apex/Android.bp
new file mode 100644
index 0000000..765aa21
--- /dev/null
+++ b/usb/apex/Android.bp
@@ -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 {
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+ name: "com.android.hardware.usb.key",
+ public_key: "com.android.hardware.usb.avbpubkey",
+ private_key: "com.android.hardware.usb.pem",
+}
+
+android_app_certificate {
+ name: "com.android.hardware.usb.certificate",
+ certificate: "com.android.hardware.usb",
+}
+
+apex {
+ name: "com.android.hardware.usb",
+ manifest: "manifest.json",
+ file_contexts: "file_contexts",
+ key: "com.android.hardware.usb.key",
+ certificate: ":com.android.hardware.usb.certificate",
+ updatable: false,
+ soc_specific: true,
+ use_vndk_as_stable: true,
+ binaries: ["android.hardware.usb-service.example"],
+ prebuilts: [
+ "com.android.hardware.usb.rc", // init .rc
+ "android.hardware.usb.accessory.prebuilt.xml",
+ "android.hardware.usb.host.prebuilt.xml",
+ ],
+ vintf_fragments: [":android.hardware.usb-service.example.xml"],
+}
+
+// Replace the binary path from /vendor/bin to /apex/{name}/bin in the init .rc file
+genrule {
+ name: "com.android.hardware.usb.rc-gen",
+ srcs: [":android.hardware.usb-service.example.rc"],
+ out: ["com.android.hardware.usb.rc"],
+ cmd: "sed -E 's/\\/vendor/\\/apex\\/com.android.hardware.usb/' $(in) > $(out)",
+}
+
+prebuilt_etc {
+ name: "com.android.hardware.usb.rc",
+ src: ":com.android.hardware.usb.rc-gen",
+ installable: false,
+}
diff --git a/usb/1.0/default/apex/com.android.hardware.usb.avbpubkey b/usb/apex/com.android.hardware.usb.avbpubkey
similarity index 100%
rename from usb/1.0/default/apex/com.android.hardware.usb.avbpubkey
rename to usb/apex/com.android.hardware.usb.avbpubkey
Binary files differ
diff --git a/usb/1.0/default/apex/com.android.hardware.usb.pem b/usb/apex/com.android.hardware.usb.pem
similarity index 100%
rename from usb/1.0/default/apex/com.android.hardware.usb.pem
rename to usb/apex/com.android.hardware.usb.pem
diff --git a/usb/1.0/default/apex/com.android.hardware.usb.pk8 b/usb/apex/com.android.hardware.usb.pk8
similarity index 100%
rename from usb/1.0/default/apex/com.android.hardware.usb.pk8
rename to usb/apex/com.android.hardware.usb.pk8
Binary files differ
diff --git a/usb/1.0/default/apex/com.android.hardware.usb.x509.pem b/usb/apex/com.android.hardware.usb.x509.pem
similarity index 100%
rename from usb/1.0/default/apex/com.android.hardware.usb.x509.pem
rename to usb/apex/com.android.hardware.usb.x509.pem
diff --git a/usb/apex/file_contexts b/usb/apex/file_contexts
new file mode 100644
index 0000000..f223a56
--- /dev/null
+++ b/usb/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\.usb-service\.example u:object_r:hal_usb_default_exec:s0
\ No newline at end of file
diff --git a/usb/apex/manifest.json b/usb/apex/manifest.json
new file mode 100644
index 0000000..1a41b90
--- /dev/null
+++ b/usb/apex/manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.usb",
+ "version": 1
+}
diff --git a/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp b/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp
index fa50821..0924da7 100644
--- a/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp
+++ b/usb/gadget/1.2/default/lib/UsbGadgetUtils.cpp
@@ -170,7 +170,6 @@
if ((functions & GadgetFunction::RNDIS) != 0) {
ALOGI("setCurrentUsbFunctions rndis");
- if (linkFunction("gsi.rndis", (*functionCount)++)) return Status::ERROR;
std::string rndisFunction = GetProperty(kVendorRndisConfig, "");
if (rndisFunction != "") {
if (linkFunction(rndisFunction.c_str(), (*functionCount)++)) return Status::ERROR;
diff --git a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index 39bb5d9..6ec8d57 100644
--- a/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/aidl_api/android.hardware.uwb.fira_android/current/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -48,4 +48,5 @@
SUPPORTED_RANGE_DATA_NTF_CONFIG = 229,
SUPPORTED_RSSI_REPORTING = 230,
SUPPORTED_DIAGNOSTICS = 231,
+ SUPPORTED_MIN_SLOT_DURATION = 232,
}
diff --git a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
index 86479fb..b182f9d 100644
--- a/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
+++ b/uwb/aidl/android/hardware/uwb/fira_android/UwbVendorCapabilityTlvTypes.aidl
@@ -179,4 +179,9 @@
* 0 - Feature not supported.
*/
SUPPORTED_DIAGNOSTICS = 0xE7,
+
+ /**
+ * 4 byte value to indicate supported min slot duration in ms.
+ */
+ SUPPORTED_MIN_SLOT_DURATION = 0xE8,
}
diff --git a/vibrator/aidl/Android.bp b/vibrator/aidl/Android.bp
index 86ef027..c5936e3 100644
--- a/vibrator/aidl/Android.bp
+++ b/vibrator/aidl/Android.bp
@@ -17,7 +17,7 @@
stability: "vintf",
backend: {
java: {
- sdk_version: "module_current",
+ sdk_version: "system_current",
},
},
versions: [
diff --git a/vibrator/aidl/default/example_vendor_java_client/Android.bp b/vibrator/aidl/default/example_vendor_java_client/Android.bp
new file mode 100644
index 0000000..f615cb1
--- /dev/null
+++ b/vibrator/aidl/default/example_vendor_java_client/Android.bp
@@ -0,0 +1,34 @@
+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: "libexample_vib_getter",
+ srcs: ["getter.cpp"],
+ vendor: true,
+ shared_libs: [
+ "liblog",
+ "libbinder_ndk",
+ ],
+ header_libs: ["jni_headers"],
+ stl: "c++_shared",
+ visibility: [":__subpackages__"],
+}
+
+android_app {
+ name: "ExampleVibratorJavaVendorClient",
+ privileged: true,
+ vendor: true,
+ static_libs: ["android.hardware.vibrator-V1-java"],
+ jni_libs: ["libexample_vib_getter"],
+ jarjar_rules: "jarjar.txt",
+ stl: "c++_shared",
+ srcs: ["example/vib/MyActivity.java"],
+ sdk_version: "system_current",
+ visibility: [":__subpackages__"],
+}
diff --git a/vibrator/aidl/default/example_vendor_java_client/AndroidManifest.xml b/vibrator/aidl/default/example_vendor_java_client/AndroidManifest.xml
new file mode 100644
index 0000000..0561066
--- /dev/null
+++ b/vibrator/aidl/default/example_vendor_java_client/AndroidManifest.xml
@@ -0,0 +1,7 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ package="example.vib">
+ <application>
+ <activity android:name=".MyActivity"/>
+ </application>
+</manifest>
diff --git a/vibrator/aidl/default/example_vendor_java_client/example/vib/MyActivity.java b/vibrator/aidl/default/example_vendor_java_client/example/vib/MyActivity.java
new file mode 100644
index 0000000..aadce8e
--- /dev/null
+++ b/vibrator/aidl/default/example_vendor_java_client/example/vib/MyActivity.java
@@ -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 example.vib;
+
+import android.app.Activity;
+import android.hardware.vibrator.IVibrator;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+
+public class MyActivity extends Activity {
+ private static native IBinder gimme(String name);
+
+ @Override
+ public void onCreate(Bundle b) {
+ super.onCreate(b);
+ System.loadLibrary("example_vib_getter");
+
+ // There is no API to get ahold of a Stable AIDL service from a vendor app
+ // in Java. This is because this is not the recommended way to get ahold
+ // of functionality in Android. The Android API Council recommendation is to
+ // implement uses-library APIs in the system/system_ext partition which add
+ // new APIs. AIDL as an API in Java is not recommended or supported way to
+ // communicate by apps - the recommendation is to use Java APIs. However,
+ // there also exists a large number of vendor apps which are coupled with
+ // hardware-specific code, and are therefore on the vendor partition. A
+ // large number of these use HIDL, and this is how they can continue to
+ // use that structure with AIDL.
+ IVibrator v =
+ IVibrator.Stub.asInterface(gimme("android.hardware.vibrator.IVibrator/default"));
+
+ try {
+ v.on(100 /*ms*/, null /*cb*/);
+ } catch (RemoteException e) {
+ throw new RuntimeException(e);
+ }
+
+ finish();
+ }
+}
diff --git a/vibrator/aidl/default/example_vendor_java_client/getter.cpp b/vibrator/aidl/default/example_vendor_java_client/getter.cpp
new file mode 100644
index 0000000..6115445
--- /dev/null
+++ b/vibrator/aidl/default/example_vendor_java_client/getter.cpp
@@ -0,0 +1,48 @@
+/*
+ * 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/binder_auto_utils.h>
+#include <android/binder_ibinder_jni.h>
+#include <android/binder_manager.h>
+#include <jni.h>
+#include <log/log.h>
+
+extern "C" JNIEXPORT jobject JNICALL
+Java_example_vib_MyActivity_gimme__Ljava_lang_String_2(JNIEnv* env, jclass /**/, jstring str) {
+ ALOGI("%s", __func__);
+
+ // Best practice is probably libnativehelper ScopedUtfChars or
+ // libbase ScopeGuard (for platform code), but this is with minimal
+ // dependencies.
+ const char* name = env->GetStringUTFChars(str, nullptr);
+
+ ALOGI("example vib gimme %s", name);
+
+ jobject jbinder = nullptr;
+
+ // Java does not have vendor variants. It's only safe to pass a service when
+ // 'vendor: true' if it is @VintfStability.
+ if (AServiceManager_isDeclared(name)) {
+ ndk::SpAIBinder binder = ndk::SpAIBinder(AServiceManager_waitForService(name));
+ jbinder = AIBinder_toJavaBinder(env, binder.get());
+ } else {
+ ALOGI("not declared");
+ }
+
+ env->ReleaseStringUTFChars(str, name);
+
+ return jbinder;
+}
diff --git a/vibrator/aidl/default/example_vendor_java_client/jarjar.txt b/vibrator/aidl/default/example_vendor_java_client/jarjar.txt
new file mode 100644
index 0000000..e7613a0
--- /dev/null
+++ b/vibrator/aidl/default/example_vendor_java_client/jarjar.txt
@@ -0,0 +1,2 @@
+rule android.hardware.** example.vib.ah.@1
+
diff --git a/wifi/1.0/vts/OWNERS b/wifi/1.0/vts/OWNERS
deleted file mode 100644
index 287152d..0000000
--- a/wifi/1.0/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 33618
-arabawy@google.com
-etancohen@google.com
diff --git a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
index e6e61cf..02f8209 100644
--- a/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
+++ b/wifi/1.0/vts/functional/wifi_hidl_test_utils.cpp
@@ -66,7 +66,7 @@
bool configureChipToSupportIfaceTypeInternal(const sp<IWifiChip>& wifi_chip,
IfaceType type,
ChipModeId* configured_mode_id) {
- if (!configured_mode_id) {
+ if (!configured_mode_id || !wifi_chip.get()) {
return false;
}
const auto& status_and_modes = HIDL_INVOKE(wifi_chip, getAvailableModes);
diff --git a/wifi/1.1/vts/OWNERS b/wifi/1.1/vts/OWNERS
deleted file mode 100644
index 294fc82..0000000
--- a/wifi/1.1/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.0/vts/OWNERS
diff --git a/wifi/1.2/vts/OWNERS b/wifi/1.2/vts/OWNERS
deleted file mode 100644
index 294fc82..0000000
--- a/wifi/1.2/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.0/vts/OWNERS
diff --git a/wifi/1.3/vts/OWNERS b/wifi/1.3/vts/OWNERS
deleted file mode 100644
index 294fc82..0000000
--- a/wifi/1.3/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.0/vts/OWNERS
diff --git a/wifi/1.4/vts/OWNERS b/wifi/1.4/vts/OWNERS
deleted file mode 100644
index 294fc82..0000000
--- a/wifi/1.4/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.0/vts/OWNERS
diff --git a/wifi/1.5/vts/OWNERS b/wifi/1.5/vts/OWNERS
deleted file mode 100644
index 294fc82..0000000
--- a/wifi/1.5/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.0/vts/OWNERS
diff --git a/wifi/1.6/default/Android.bp b/wifi/1.6/default/Android.bp
deleted file mode 100644
index a132dee..0000000
--- a/wifi/1.6/default/Android.bp
+++ /dev/null
@@ -1,228 +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 {
- default_applicable_licenses: ["hardware_interfaces_license"],
-}
-
-soong_config_module_type {
- name: "wifi_hal_cc_defaults",
- module_type: "cc_defaults",
- config_namespace: "wifi",
- bool_variables: [
- "hidl_feature_aware", // WIFI_HIDL_FEATURE_AWARE
- "hidl_feature_dual_interface", // WIFI_HIDL_FEATURE_DUAL_INTERFACE
- "hidl_feature_disable_ap", // WIFI_HIDL_FEATURE_DISABLE_AP
- "hidl_feature_disable_ap_mac_randomization", // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
- "avoid_iface_reset_mac_change", // WIFI_AVOID_IFACE_RESET_MAC_CHANGE
- ],
- value_variables: [
- "hal_interface_combinations", // WIFI_HAL_INTERFACE_COMBINATIONS
- ],
- properties: [
- "cppflags",
- ],
-}
-
-wifi_hal_cc_defaults {
- name: "android.hardware.wifi@1.0-service-cppflags-defaults",
- soong_config_variables: {
- hidl_feature_aware: {
- cppflags: ["-DWIFI_HIDL_FEATURE_AWARE"],
- },
- hidl_feature_dual_interface: {
- cppflags: ["-DWIFI_HIDL_FEATURE_DUAL_INTERFACE"],
- },
- hidl_feature_disable_ap: {
- cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP"],
- },
- hidl_feature_disable_ap_mac_randomization: {
- cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION"],
- },
- avoid_iface_reset_mac_change: {
- cppflags: ["-DWIFI_AVOID_IFACE_RESET_MAC_CHANGE"],
- },
- hal_interface_combinations: {
- cppflags: ["-DWIFI_HAL_INTERFACE_COMBINATIONS=%s"],
- },
- },
-}
-
-cc_library_static {
- name: "android.hardware.wifi@1.0-service-lib",
- defaults: ["android.hardware.wifi@1.0-service-cppflags-defaults"],
- proprietary: true,
- compile_multilib: "first",
- cppflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- // Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
- cflags: ["-Wno-error=implicit-fallthrough"],
- 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",
- ],
-
- shared_libs: [
- "libbase",
- "libcutils",
- "libhidlbase",
- "liblog",
- "libnl",
- "libutils",
- "libwifi-hal",
- "libwifi-system-iface",
- "libxml2",
- "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@1.6",
- ],
-
- export_include_dirs: ["."],
-}
-
-cc_binary {
- name: "android.hardware.wifi@1.0-service",
- vintf_fragments: ["android.hardware.wifi@1.0-service.xml"],
- relative_install_path: "hw",
- proprietary: true,
- cppflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- srcs: ["service.cpp"],
- shared_libs: [
- "libbase",
- "libcutils",
- "libhidlbase",
- "liblog",
- "libnl",
- "libutils",
- "libwifi-hal",
- "libwifi-system-iface",
- "libxml2",
- "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@1.6",
- ],
- static_libs: ["android.hardware.wifi@1.0-service-lib"],
- init_rc: ["android.hardware.wifi@1.0-service.rc"],
-}
-
-cc_binary {
- name: "android.hardware.wifi@1.0-service-lazy",
- vintf_fragments: ["android.hardware.wifi@1.0-service.xml"],
- overrides: ["android.hardware.wifi@1.0-service"],
- cflags: ["-DLAZY_SERVICE"],
- relative_install_path: "hw",
- proprietary: true,
- cppflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- srcs: ["service.cpp"],
- shared_libs: [
- "libbase",
- "libcutils",
- "libhidlbase",
- "liblog",
- "libnl",
- "libutils",
- "libwifi-hal",
- "libwifi-system-iface",
- "libxml2",
- "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@1.6",
- ],
- static_libs: ["android.hardware.wifi@1.0-service-lib"],
- init_rc: ["android.hardware.wifi@1.0-service-lazy.rc"],
-}
-
-cc_test {
- name: "android.hardware.wifi@1.0-service-tests",
- proprietary: true,
- compile_multilib: "first",
- cppflags: [
- "-Wall",
- "-Werror",
- "-Wextra",
- ],
- srcs: [
- "tests/hidl_struct_util_unit_tests.cpp",
- "tests/main.cpp",
- "tests/mock_interface_tool.cpp",
- "tests/mock_wifi_feature_flags.cpp",
- "tests/mock_wifi_iface_util.cpp",
- "tests/mock_wifi_legacy_hal.cpp",
- "tests/mock_wifi_mode_controller.cpp",
- "tests/ringbuffer_unit_tests.cpp",
- "tests/wifi_nan_iface_unit_tests.cpp",
- "tests/wifi_chip_unit_tests.cpp",
- "tests/wifi_iface_util_unit_tests.cpp",
- ],
- static_libs: [
- "libgmock",
- "libgtest",
- "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@1.6",
- "android.hardware.wifi@1.0-service-lib",
- ],
- shared_libs: [
- "libbase",
- "libcutils",
- "libhidlbase",
- "liblog",
- "libnl",
- "libutils",
- "libwifi-hal",
- "libwifi-system-iface",
- ],
-}
diff --git a/wifi/1.6/default/OWNERS b/wifi/1.6/default/OWNERS
deleted file mode 100644
index cf81c79..0000000
--- a/wifi/1.6/default/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-arabawy@google.com
-etancohen@google.com
diff --git a/wifi/1.6/default/THREADING.README b/wifi/1.6/default/THREADING.README
deleted file mode 100644
index 8366ca0..0000000
--- a/wifi/1.6/default/THREADING.README
+++ /dev/null
@@ -1,35 +0,0 @@
-Vendor HAL Threading Model
-==========================
-The vendor HAL service has two threads:
-1. HIDL thread: This is the main thread which processes all the incoming HIDL
-RPC's.
-2. Legacy HAL event loop thread: This is the thread forked off for processing
-the legacy HAL event loop (wifi_event_loop()). This thread is used to process
-any asynchronous netlink events posted by the driver. Any asynchronous
-callbacks passed to the legacy HAL API's are invoked on this thread.
-
-Synchronization Concerns
-========================
-wifi_legacy_hal.cpp has a bunch of global "C" style functions to handle the
-legacy callbacks. Each of these "C" style function invokes a corresponding
-"std::function" version of the callback which does the actual processing.
-The variables holding these "std::function" callbacks are reset from the HIDL
-thread when they are no longer used. For example: stopGscan() will reset the
-corresponding "on_gscan_*" callback variables which were set when startGscan()
-was invoked. This is not thread safe since these callback variables are
-accesed from the legacy hal event loop thread as well.
-
-Synchronization Solution
-========================
-Adding a global lock seems to be the most trivial solution to the problem.
-a) All of the asynchronous "C" style callbacks will acquire the global lock
-before invoking the corresponding "std::function" callback variables.
-b) All of the HIDL methods will also acquire the global lock before processing
-(in hidl_return_util::validateAndCall()).
-
-Note: It's important that we only acquire the global lock for asynchronous
-callbacks, because there is no guarantee (or documentation to clarify) that the
-synchronous callbacks are invoked on the same invocation thread. If that is not
-the case in some implementation, we will end up deadlocking the system since the
-HIDL thread would have acquired the global lock which is needed by the
-synchronous callback executed on the legacy hal event loop thread.
diff --git a/wifi/1.6/default/android.hardware.wifi@1.0-service-lazy.rc b/wifi/1.6/default/android.hardware.wifi@1.0-service-lazy.rc
deleted file mode 100644
index ee8c818..0000000
--- a/wifi/1.6/default/android.hardware.wifi@1.0-service-lazy.rc
+++ /dev/null
@@ -1,14 +0,0 @@
-service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service-lazy
- interface android.hardware.wifi@1.0::IWifi default
- interface android.hardware.wifi@1.1::IWifi default
- interface android.hardware.wifi@1.2::IWifi default
- interface android.hardware.wifi@1.3::IWifi default
- interface android.hardware.wifi@1.4::IWifi default
- interface android.hardware.wifi@1.5::IWifi default
- interface android.hardware.wifi@1.6::IWifi default
- oneshot
- disabled
- class hal
- capabilities NET_ADMIN NET_RAW SYS_MODULE
- user wifi
- group wifi gps
diff --git a/wifi/1.6/default/android.hardware.wifi@1.0-service.rc b/wifi/1.6/default/android.hardware.wifi@1.0-service.rc
deleted file mode 100644
index 18f40d0..0000000
--- a/wifi/1.6/default/android.hardware.wifi@1.0-service.rc
+++ /dev/null
@@ -1,12 +0,0 @@
-service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi@1.0-service
- interface android.hardware.wifi@1.0::IWifi default
- interface android.hardware.wifi@1.1::IWifi default
- interface android.hardware.wifi@1.2::IWifi default
- interface android.hardware.wifi@1.3::IWifi default
- interface android.hardware.wifi@1.4::IWifi default
- interface android.hardware.wifi@1.5::IWifi default
- interface android.hardware.wifi@1.6::IWifi default
- class hal
- capabilities NET_ADMIN NET_RAW SYS_MODULE
- user wifi
- group wifi gps
diff --git a/wifi/1.6/default/android.hardware.wifi@1.0-service.xml b/wifi/1.6/default/android.hardware.wifi@1.0-service.xml
deleted file mode 100644
index 771fbaa..0000000
--- a/wifi/1.6/default/android.hardware.wifi@1.0-service.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<manifest version="1.0" type="device">
- <hal format="hidl">
- <name>android.hardware.wifi</name>
- <transport>hwbinder</transport>
- <version>1.6</version>
- <interface>
- <name>IWifi</name>
- <instance>default</instance>
- </interface>
- </hal>
-</manifest>
diff --git a/wifi/1.6/default/hidl_callback_util.h b/wifi/1.6/default/hidl_callback_util.h
deleted file mode 100644
index aab0ae5..0000000
--- a/wifi/1.6/default/hidl_callback_util.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HIDL_CALLBACK_UTIL_H_
-#define HIDL_CALLBACK_UTIL_H_
-
-#include <set>
-
-#include <hidl/HidlSupport.h>
-#include <hidl/HidlTransportSupport.h>
-
-namespace {
-// Type of callback invoked by the death handler.
-using on_death_cb_function = std::function<void(uint64_t)>;
-
-// Private class used to keep track of death of individual
-// callbacks stored in HidlCallbackHandler.
-template <typename CallbackType>
-class HidlDeathHandler : public android::hardware::hidl_death_recipient {
- public:
- HidlDeathHandler(const on_death_cb_function& user_cb_function)
- : cb_function_(user_cb_function) {}
- ~HidlDeathHandler() = default;
-
- // Death notification for callbacks.
- void serviceDied(uint64_t cookie,
- const android::wp<android::hidl::base::V1_0::IBase>& /* who */) override {
- cb_function_(cookie);
- }
-
- private:
- on_death_cb_function cb_function_;
-
- DISALLOW_COPY_AND_ASSIGN(HidlDeathHandler);
-};
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace hidl_callback_util {
-template <typename CallbackType>
-// Provides a class to manage callbacks for the various HIDL interfaces and
-// handle the death of the process hosting each callback.
-class HidlCallbackHandler {
- public:
- HidlCallbackHandler()
- : death_handler_(new HidlDeathHandler<CallbackType>(
- std::bind(&HidlCallbackHandler::onObjectDeath, this, std::placeholders::_1))) {}
- ~HidlCallbackHandler() = default;
-
- bool addCallback(const sp<CallbackType>& cb) {
- // TODO(b/33818800): Can't compare proxies yet. So, use the cookie
- // (callback proxy's raw pointer) to track the death of individual
- // clients.
- uint64_t cookie = reinterpret_cast<uint64_t>(cb.get());
- for (const auto& s : cb_set_) {
- if (interfacesEqual(cb, s)) {
- LOG(ERROR) << "Duplicate death notification registration";
- return true;
- }
- }
- if (!cb->linkToDeath(death_handler_, cookie)) {
- LOG(ERROR) << "Failed to register death notification";
- return false;
- }
- cb_set_.insert(cb);
- return true;
- }
-
- const std::set<android::sp<CallbackType>>& getCallbacks() { return cb_set_; }
-
- // Death notification for callbacks.
- void onObjectDeath(uint64_t cookie) {
- CallbackType* cb = reinterpret_cast<CallbackType*>(cookie);
- const auto& iter = cb_set_.find(cb);
- if (iter == cb_set_.end()) {
- LOG(ERROR) << "Unknown callback death notification received";
- return;
- }
- cb_set_.erase(iter);
- LOG(DEBUG) << "Dead callback removed from list";
- }
-
- void invalidate() {
- for (const sp<CallbackType>& cb : cb_set_) {
- if (!cb->unlinkToDeath(death_handler_)) {
- LOG(ERROR) << "Failed to deregister death notification";
- }
- }
- cb_set_.clear();
- }
-
- private:
- std::set<sp<CallbackType>> cb_set_;
- sp<HidlDeathHandler<CallbackType>> death_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(HidlCallbackHandler);
-};
-
-} // namespace hidl_callback_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-#endif // HIDL_CALLBACK_UTIL_H_
diff --git a/wifi/1.6/default/hidl_return_util.h b/wifi/1.6/default/hidl_return_util.h
deleted file mode 100644
index a0efac2..0000000
--- a/wifi/1.6/default/hidl_return_util.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HIDL_RETURN_UTIL_H_
-#define HIDL_RETURN_UTIL_H_
-
-#include "hidl_sync_util.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace hidl_return_util {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * These utility functions are used to invoke a method on the provided
- * HIDL interface object.
- * These functions checks if the provided HIDL interface object is valid.
- * a) if valid, Invokes the corresponding internal implementation function of
- * the HIDL method. It then invokes the HIDL continuation callback with
- * the status and any returned values.
- * b) if invalid, invokes the HIDL continuation callback with the
- * provided error status and default values.
- */
-// Use for HIDL methods which return only an instance of WifiStatus.
-template <typename ObjT, typename WorkFuncT, typename... Args>
-Return<void> validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
- const std::function<void(const WifiStatus&)>& hidl_cb,
- Args&&... args) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (obj->isValid()) {
- hidl_cb((obj->*work)(std::forward<Args>(args)...));
- } else {
- hidl_cb(createWifiStatus(status_code_if_invalid));
- }
- return Void();
-}
-
-// Use for HIDL methods which return only an instance of WifiStatus.
-// This version passes the global lock acquired to the body of the method.
-// Note: Only used by IWifi::stop() currently.
-template <typename ObjT, typename WorkFuncT, typename... Args>
-Return<void> validateAndCallWithLock(ObjT* obj, WifiStatusCode status_code_if_invalid,
- WorkFuncT&& work,
- const std::function<void(const WifiStatus&)>& hidl_cb,
- Args&&... args) {
- auto lock = hidl_sync_util::acquireGlobalLock();
- if (obj->isValid()) {
- hidl_cb((obj->*work)(&lock, std::forward<Args>(args)...));
- } else {
- hidl_cb(createWifiStatus(status_code_if_invalid));
- }
- return Void();
-}
-
-// Use for HIDL methods which return instance of WifiStatus and a single return
-// value.
-template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
-Return<void> validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
- const std::function<void(const WifiStatus&, ReturnT)>& hidl_cb,
- Args&&... args) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (obj->isValid()) {
- const auto& ret_pair = (obj->*work)(std::forward<Args>(args)...);
- const WifiStatus& status = std::get<0>(ret_pair);
- const auto& ret_value = std::get<1>(ret_pair);
- hidl_cb(status, ret_value);
- } else {
- hidl_cb(createWifiStatus(status_code_if_invalid),
- typename std::remove_reference<ReturnT>::type());
- }
- return Void();
-}
-
-// Use for HIDL methods which return instance of WifiStatus and 2 return
-// values.
-template <typename ObjT, typename WorkFuncT, typename ReturnT1, typename ReturnT2, typename... Args>
-Return<void> validateAndCall(
- ObjT* obj, WifiStatusCode status_code_if_invalid, WorkFuncT&& work,
- const std::function<void(const WifiStatus&, ReturnT1, ReturnT2)>& hidl_cb, Args&&... args) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (obj->isValid()) {
- const auto& ret_tuple = (obj->*work)(std::forward<Args>(args)...);
- const WifiStatus& status = std::get<0>(ret_tuple);
- const auto& ret_value1 = std::get<1>(ret_tuple);
- const auto& ret_value2 = std::get<2>(ret_tuple);
- hidl_cb(status, ret_value1, ret_value2);
- } else {
- hidl_cb(createWifiStatus(status_code_if_invalid),
- typename std::remove_reference<ReturnT1>::type(),
- typename std::remove_reference<ReturnT2>::type());
- }
- return Void();
-}
-
-} // namespace hidl_return_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-#endif // HIDL_RETURN_UTIL_H_
diff --git a/wifi/1.6/default/hidl_struct_util.cpp b/wifi/1.6/default/hidl_struct_util.cpp
deleted file mode 100644
index 2112b26..0000000
--- a/wifi/1.6/default/hidl_struct_util.cpp
+++ /dev/null
@@ -1,3007 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <utils/SystemClock.h>
-
-#include "hidl_struct_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace hidl_struct_util {
-
-using V1_6::NanConfigRequestSupplemental;
-
-WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(legacy_hal::wifi_channel_width type);
-
-hidl_string safeConvertChar(const char* str, size_t max_len) {
- const char* c = str;
- size_t size = 0;
- while (*c && (unsigned char)*c < 128 && size < max_len) {
- ++size;
- ++c;
- }
- return hidl_string(str, size);
-}
-
-IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToHidlChipCapability(uint32_t feature) {
- using HidlChipCaps = IWifiChip::ChipCapabilityMask;
- switch (feature) {
- case legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED:
- return HidlChipCaps::DEBUG_MEMORY_FIRMWARE_DUMP;
- case legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED:
- return HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP;
- case legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED:
- return HidlChipCaps::DEBUG_RING_BUFFER_CONNECT_EVENT;
- case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED:
- return HidlChipCaps::DEBUG_RING_BUFFER_POWER_EVENT;
- case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED:
- return HidlChipCaps::DEBUG_RING_BUFFER_WAKELOCK_EVENT;
- };
- CHECK(false) << "Unknown legacy feature: " << feature;
- return {};
-}
-
-IWifiStaIface::StaIfaceCapabilityMask convertLegacyLoggerFeatureToHidlStaIfaceCapability(
- uint32_t feature) {
- using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
- switch (feature) {
- case legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED:
- return HidlStaIfaceCaps::DEBUG_PACKET_FATE;
- };
- CHECK(false) << "Unknown legacy feature: " << feature;
- return {};
-}
-
-V1_5::IWifiChip::ChipCapabilityMask convertLegacyFeatureToHidlChipCapability(uint64_t feature) {
- using HidlChipCaps = V1_5::IWifiChip::ChipCapabilityMask;
- switch (feature) {
- case WIFI_FEATURE_SET_TX_POWER_LIMIT:
- return HidlChipCaps::SET_TX_POWER_LIMIT;
- case WIFI_FEATURE_USE_BODY_HEAD_SAR:
- return HidlChipCaps::USE_BODY_HEAD_SAR;
- case WIFI_FEATURE_D2D_RTT:
- return HidlChipCaps::D2D_RTT;
- case WIFI_FEATURE_D2AP_RTT:
- return HidlChipCaps::D2AP_RTT;
- case WIFI_FEATURE_INFRA_60G:
- return HidlChipCaps::WIGIG;
- case WIFI_FEATURE_SET_LATENCY_MODE:
- return HidlChipCaps::SET_LATENCY_MODE;
- case WIFI_FEATURE_P2P_RAND_MAC:
- return HidlChipCaps::P2P_RAND_MAC;
- };
- CHECK(false) << "Unknown legacy feature: " << feature;
- return {};
-}
-
-IWifiStaIface::StaIfaceCapabilityMask convertLegacyFeatureToHidlStaIfaceCapability(
- uint64_t feature) {
- using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
- switch (feature) {
- case WIFI_FEATURE_GSCAN:
- return HidlStaIfaceCaps::BACKGROUND_SCAN;
- case WIFI_FEATURE_LINK_LAYER_STATS:
- return HidlStaIfaceCaps::LINK_LAYER_STATS;
- case WIFI_FEATURE_RSSI_MONITOR:
- return HidlStaIfaceCaps::RSSI_MONITOR;
- case WIFI_FEATURE_CONTROL_ROAMING:
- return HidlStaIfaceCaps::CONTROL_ROAMING;
- case WIFI_FEATURE_IE_WHITELIST:
- return HidlStaIfaceCaps::PROBE_IE_WHITELIST;
- case WIFI_FEATURE_SCAN_RAND:
- return HidlStaIfaceCaps::SCAN_RAND;
- case WIFI_FEATURE_INFRA_5G:
- return HidlStaIfaceCaps::STA_5G;
- case WIFI_FEATURE_HOTSPOT:
- return HidlStaIfaceCaps::HOTSPOT;
- case WIFI_FEATURE_PNO:
- return HidlStaIfaceCaps::PNO;
- case WIFI_FEATURE_TDLS:
- return HidlStaIfaceCaps::TDLS;
- case WIFI_FEATURE_TDLS_OFFCHANNEL:
- return HidlStaIfaceCaps::TDLS_OFFCHANNEL;
- case WIFI_FEATURE_CONFIG_NDO:
- return HidlStaIfaceCaps::ND_OFFLOAD;
- case WIFI_FEATURE_MKEEP_ALIVE:
- return HidlStaIfaceCaps::KEEP_ALIVE;
- };
- CHECK(false) << "Unknown legacy feature: " << feature;
- return {};
-}
-
-bool convertLegacyFeaturesToHidlChipCapabilities(uint64_t legacy_feature_set,
- uint32_t legacy_logger_feature_set,
- uint32_t* hidl_caps) {
- if (!hidl_caps) {
- return false;
- }
- *hidl_caps = {};
- using HidlChipCaps = IWifiChip::ChipCapabilityMask;
- for (const auto feature : {legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED,
- legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED,
- legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED,
- legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED,
- legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED}) {
- if (feature & legacy_logger_feature_set) {
- *hidl_caps |= convertLegacyLoggerFeatureToHidlChipCapability(feature);
- }
- }
- std::vector<uint64_t> features = {WIFI_FEATURE_SET_TX_POWER_LIMIT,
- WIFI_FEATURE_USE_BODY_HEAD_SAR,
- WIFI_FEATURE_D2D_RTT,
- WIFI_FEATURE_D2AP_RTT,
- WIFI_FEATURE_INFRA_60G,
- WIFI_FEATURE_SET_LATENCY_MODE,
- WIFI_FEATURE_P2P_RAND_MAC};
- for (const auto feature : features) {
- if (feature & legacy_feature_set) {
- *hidl_caps |= convertLegacyFeatureToHidlChipCapability(feature);
- }
- }
-
- // There are no flags for these 3 in the legacy feature set. Adding them to
- // the set because all the current devices support it.
- *hidl_caps |= HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA;
- *hidl_caps |= HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS;
- *hidl_caps |= HidlChipCaps::DEBUG_ERROR_ALERTS;
- return true;
-}
-
-WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToHidl(uint32_t flag) {
- switch (flag) {
- case WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES:
- return WifiDebugRingBufferFlags::HAS_BINARY_ENTRIES;
- case WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES:
- return WifiDebugRingBufferFlags::HAS_ASCII_ENTRIES;
- };
- CHECK(false) << "Unknown legacy flag: " << flag;
- return {};
-}
-
-bool convertLegacyDebugRingBufferStatusToHidl(
- const legacy_hal::wifi_ring_buffer_status& legacy_status,
- WifiDebugRingBufferStatus* hidl_status) {
- if (!hidl_status) {
- return false;
- }
- *hidl_status = {};
- hidl_status->ringName = safeConvertChar(reinterpret_cast<const char*>(legacy_status.name),
- sizeof(legacy_status.name));
- hidl_status->flags = 0;
- for (const auto flag :
- {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES, WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) {
- if (flag & legacy_status.flags) {
- hidl_status->flags |= static_cast<std::underlying_type<WifiDebugRingBufferFlags>::type>(
- convertLegacyDebugRingBufferFlagsToHidl(flag));
- }
- }
- hidl_status->ringId = legacy_status.ring_id;
- hidl_status->sizeInBytes = legacy_status.ring_buffer_byte_size;
- // Calculate free size of the ring the buffer. We don't need to send the
- // exact read/write pointers that were there in the legacy HAL interface.
- if (legacy_status.written_bytes >= legacy_status.read_bytes) {
- hidl_status->freeSizeInBytes = legacy_status.ring_buffer_byte_size -
- (legacy_status.written_bytes - legacy_status.read_bytes);
- } else {
- hidl_status->freeSizeInBytes = legacy_status.read_bytes - legacy_status.written_bytes;
- }
- hidl_status->verboseLevel = legacy_status.verbose_level;
- return true;
-}
-
-bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
- const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
- std::vector<WifiDebugRingBufferStatus>* hidl_status_vec) {
- if (!hidl_status_vec) {
- return false;
- }
- *hidl_status_vec = {};
- for (const auto& legacy_status : legacy_status_vec) {
- WifiDebugRingBufferStatus hidl_status;
- if (!convertLegacyDebugRingBufferStatusToHidl(legacy_status, &hidl_status)) {
- return false;
- }
- hidl_status_vec->push_back(hidl_status);
- }
- return true;
-}
-
-bool convertLegacyWakeReasonStatsToHidl(const legacy_hal::WakeReasonStats& legacy_stats,
- WifiDebugHostWakeReasonStats* hidl_stats) {
- if (!hidl_stats) {
- return false;
- }
- *hidl_stats = {};
- hidl_stats->totalCmdEventWakeCnt = legacy_stats.wake_reason_cnt.total_cmd_event_wake;
- hidl_stats->cmdEventWakeCntPerType = legacy_stats.cmd_event_wake_cnt;
- hidl_stats->totalDriverFwLocalWakeCnt = legacy_stats.wake_reason_cnt.total_driver_fw_local_wake;
- hidl_stats->driverFwLocalWakeCntPerType = legacy_stats.driver_fw_local_wake_cnt;
- hidl_stats->totalRxPacketWakeCnt = legacy_stats.wake_reason_cnt.total_rx_data_wake;
- hidl_stats->rxPktWakeDetails.rxUnicastCnt =
- legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt;
- hidl_stats->rxPktWakeDetails.rxMulticastCnt =
- legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt;
- hidl_stats->rxPktWakeDetails.rxBroadcastCnt =
- legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt;
- hidl_stats->rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt =
- legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt;
- hidl_stats->rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt =
- legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt;
- hidl_stats->rxMulticastPkWakeDetails.otherRxMulticastAddrCnt =
- legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt;
- hidl_stats->rxIcmpPkWakeDetails.icmpPkt =
- legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt;
- hidl_stats->rxIcmpPkWakeDetails.icmp6Pkt =
- legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt;
- hidl_stats->rxIcmpPkWakeDetails.icmp6Ra =
- legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra;
- hidl_stats->rxIcmpPkWakeDetails.icmp6Na =
- legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na;
- hidl_stats->rxIcmpPkWakeDetails.icmp6Ns =
- legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns;
- return true;
-}
-
-legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
- V1_1::IWifiChip::TxPowerScenario hidl_scenario) {
- switch (hidl_scenario) {
- // This is the only supported scenario for V1_1
- case V1_1::IWifiChip::TxPowerScenario::VOICE_CALL:
- return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL;
- };
- CHECK(false);
-}
-
-legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2(
- V1_2::IWifiChip::TxPowerScenario hidl_scenario) {
- switch (hidl_scenario) {
- // This is the only supported scenario for V1_1
- case V1_2::IWifiChip::TxPowerScenario::VOICE_CALL:
- return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL;
- // Those are the supported scenarios for V1_2
- case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF:
- return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF;
- case V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_ON:
- return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON;
- case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF:
- return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF;
- case V1_2::IWifiChip::TxPowerScenario::ON_BODY_CELL_ON:
- return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON;
- };
- CHECK(false);
-}
-
-legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy(
- V1_3::IWifiChip::LatencyMode hidl_latency_mode) {
- switch (hidl_latency_mode) {
- case V1_3::IWifiChip::LatencyMode::NORMAL:
- return legacy_hal::WIFI_LATENCY_MODE_NORMAL;
- case V1_3::IWifiChip::LatencyMode::LOW:
- return legacy_hal::WIFI_LATENCY_MODE_LOW;
- }
- CHECK(false);
-}
-
-bool convertLegacyWifiMacInfoToHidl(
- const legacy_hal::WifiMacInfo& legacy_mac_info,
- V1_4::IWifiChipEventCallback::RadioModeInfo* hidl_radio_mode_info) {
- if (!hidl_radio_mode_info) {
- return false;
- }
- *hidl_radio_mode_info = {};
-
- hidl_radio_mode_info->radioId = legacy_mac_info.wlan_mac_id;
- // Convert from bitmask of bands in the legacy HAL to enum value in
- // the HIDL interface.
- if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND &&
- legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND &&
- legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) {
- hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ_6GHZ;
- } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND &&
- legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
- hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ_6GHZ;
- } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND) {
- hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_6GHZ;
- } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND &&
- legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
- hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ_5GHZ;
- } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) {
- hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_24GHZ;
- } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
- hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_5GHZ;
- } else {
- hidl_radio_mode_info->bandInfo = V1_4::WifiBand::BAND_UNSPECIFIED;
- }
- std::vector<V1_2::IWifiChipEventCallback::IfaceInfo> iface_info_vec;
- for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) {
- V1_2::IWifiChipEventCallback::IfaceInfo iface_info;
- iface_info.name = legacy_iface_info.name;
- iface_info.channel = legacy_iface_info.channel;
- iface_info_vec.push_back(iface_info);
- }
- hidl_radio_mode_info->ifaceInfos = iface_info_vec;
- return true;
-}
-
-uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand hidl_band) {
- switch (hidl_band) {
- case V1_5::WifiBand::BAND_24GHZ:
- return legacy_hal::WLAN_MAC_2_4_BAND;
- case V1_5::WifiBand::BAND_5GHZ:
- case V1_5::WifiBand::BAND_5GHZ_DFS:
- case V1_5::WifiBand::BAND_5GHZ_WITH_DFS:
- return legacy_hal::WLAN_MAC_5_0_BAND;
- case V1_5::WifiBand::BAND_24GHZ_5GHZ:
- case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
- return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND);
- case V1_5::WifiBand::BAND_6GHZ:
- return legacy_hal::WLAN_MAC_6_0_BAND;
- case V1_5::WifiBand::BAND_5GHZ_6GHZ:
- return (legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_6_0_BAND);
- case V1_5::WifiBand::BAND_24GHZ_5GHZ_6GHZ:
- case V1_5::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ:
- return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND |
- legacy_hal::WLAN_MAC_6_0_BAND);
- case V1_5::WifiBand::BAND_60GHZ:
- return legacy_hal::WLAN_MAC_60_0_BAND;
- default:
- return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND |
- legacy_hal::WLAN_MAC_6_0_BAND | legacy_hal::WLAN_MAC_60_0_BAND);
- }
-}
-
-V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band) {
- switch (band) {
- case legacy_hal::WLAN_MAC_2_4_BAND:
- return V1_5::WifiBand::BAND_24GHZ;
- case legacy_hal::WLAN_MAC_5_0_BAND:
- return V1_5::WifiBand::BAND_5GHZ;
- case legacy_hal::WLAN_MAC_6_0_BAND:
- return V1_5::WifiBand::BAND_6GHZ;
- case legacy_hal::WLAN_MAC_60_0_BAND:
- return V1_5::WifiBand::BAND_60GHZ;
- default:
- return V1_5::WifiBand::BAND_UNSPECIFIED;
- }
-}
-
-uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask) {
- uint32_t legacy_iface_mask = 0;
- if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_STA) {
- legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_STA);
- }
- if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP) {
- legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_SOFTAP);
- }
- if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT) {
- legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT);
- }
- if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO) {
- legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_GO);
- }
- if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_NAN) {
- legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_NAN);
- }
- if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_TDLS) {
- legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_TDLS);
- }
- if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_MESH) {
- legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_MESH);
- }
- if (hidl_iface_mask & V1_5::WifiIfaceMode::IFACE_MODE_IBSS) {
- legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_IBSS);
- }
- return legacy_iface_mask;
-}
-
-uint32_t convertLegacyWifiInterfaceModeToHidl(uint32_t legacy_iface_mask) {
- uint32_t hidl_iface_mask = 0;
- if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_STA)) {
- hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_STA;
- }
- if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_SOFTAP)) {
- hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_SOFTAP;
- }
- if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT)) {
- hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_CLIENT;
- }
- if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_GO)) {
- hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_P2P_GO;
- }
- if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_NAN)) {
- hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_NAN;
- }
- if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_TDLS)) {
- hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_TDLS;
- }
- if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_MESH)) {
- hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_MESH;
- }
- if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_IBSS)) {
- hidl_iface_mask |= V1_5::WifiIfaceMode::IFACE_MODE_IBSS;
- }
- return hidl_iface_mask;
-}
-
-uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask) {
- uint32_t legacy_filter_mask = 0;
- if (hidl_filter_mask & V1_5::IWifiChip::UsableChannelFilter::CELLULAR_COEXISTENCE) {
- legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE;
- }
- if (hidl_filter_mask & V1_5::IWifiChip::UsableChannelFilter::CONCURRENCY) {
- legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY;
- }
- if (hidl_filter_mask & V1_6::IWifiChip::UsableChannelFilter::NAN_INSTANT_MODE) {
- legacy_filter_mask |= WIFI_USABLE_CHANNEL_FILTER_NAN_INSTANT_MODE;
- }
- return legacy_filter_mask;
-}
-
-bool convertLegacyWifiUsableChannelToHidl(
- const legacy_hal::wifi_usable_channel& legacy_usable_channel,
- V1_6::WifiUsableChannel* hidl_usable_channel) {
- if (!hidl_usable_channel) {
- return false;
- }
- *hidl_usable_channel = {};
- hidl_usable_channel->channel = legacy_usable_channel.freq;
- hidl_usable_channel->channelBandwidth =
- convertLegacyWifiChannelWidthToHidl(legacy_usable_channel.width);
- hidl_usable_channel->ifaceModeMask =
- convertLegacyWifiInterfaceModeToHidl(legacy_usable_channel.iface_mode_mask);
-
- return true;
-}
-
-bool convertLegacyWifiUsableChannelsToHidl(
- const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
- std::vector<V1_6::WifiUsableChannel>* hidl_usable_channels) {
- if (!hidl_usable_channels) {
- return false;
- }
- *hidl_usable_channels = {};
- for (const auto& legacy_usable_channel : legacy_usable_channels) {
- V1_6::WifiUsableChannel hidl_usable_channel;
- if (!convertLegacyWifiUsableChannelToHidl(legacy_usable_channel, &hidl_usable_channel)) {
- return false;
- }
- hidl_usable_channels->push_back(hidl_usable_channel);
- }
- return true;
-}
-
-bool convertLegacyWifiMacInfosToHidl(
- const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
- std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos) {
- if (!hidl_radio_mode_infos) {
- return false;
- }
- *hidl_radio_mode_infos = {};
-
- for (const auto& legacy_mac_info : legacy_mac_infos) {
- V1_4::IWifiChipEventCallback::RadioModeInfo hidl_radio_mode_info;
- if (!convertLegacyWifiMacInfoToHidl(legacy_mac_info, &hidl_radio_mode_info)) {
- return false;
- }
- hidl_radio_mode_infos->push_back(hidl_radio_mode_info);
- }
- return true;
-}
-
-bool convertLegacyFeaturesToHidlStaCapabilities(uint64_t legacy_feature_set,
- uint32_t legacy_logger_feature_set,
- uint32_t* hidl_caps) {
- if (!hidl_caps) {
- return false;
- }
- *hidl_caps = {};
- using HidlStaIfaceCaps = IWifiStaIface::StaIfaceCapabilityMask;
- for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) {
- if (feature & legacy_logger_feature_set) {
- *hidl_caps |= convertLegacyLoggerFeatureToHidlStaIfaceCapability(feature);
- }
- }
- for (const auto feature :
- {WIFI_FEATURE_GSCAN, WIFI_FEATURE_LINK_LAYER_STATS, WIFI_FEATURE_RSSI_MONITOR,
- WIFI_FEATURE_CONTROL_ROAMING, WIFI_FEATURE_IE_WHITELIST, WIFI_FEATURE_SCAN_RAND,
- WIFI_FEATURE_INFRA_5G, WIFI_FEATURE_HOTSPOT, WIFI_FEATURE_PNO, WIFI_FEATURE_TDLS,
- WIFI_FEATURE_TDLS_OFFCHANNEL, WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE}) {
- if (feature & legacy_feature_set) {
- *hidl_caps |= convertLegacyFeatureToHidlStaIfaceCapability(feature);
- }
- }
- // There is no flag for this one in the legacy feature set. Adding it to the
- // set because all the current devices support it.
- *hidl_caps |= HidlStaIfaceCaps::APF;
- return true;
-}
-
-bool convertLegacyApfCapabilitiesToHidl(const legacy_hal::PacketFilterCapabilities& legacy_caps,
- StaApfPacketFilterCapabilities* hidl_caps) {
- if (!hidl_caps) {
- return false;
- }
- *hidl_caps = {};
- hidl_caps->version = legacy_caps.version;
- hidl_caps->maxLength = legacy_caps.max_len;
- return true;
-}
-
-uint8_t convertHidlGscanReportEventFlagToLegacy(
- StaBackgroundScanBucketEventReportSchemeMask hidl_flag) {
- using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
- switch (hidl_flag) {
- case HidlFlag::EACH_SCAN:
- return REPORT_EVENTS_EACH_SCAN;
- case HidlFlag::FULL_RESULTS:
- return REPORT_EVENTS_FULL_RESULTS;
- case HidlFlag::NO_BATCH:
- return REPORT_EVENTS_NO_BATCH;
- };
- CHECK(false);
-}
-
-StaScanDataFlagMask convertLegacyGscanDataFlagToHidl(uint8_t legacy_flag) {
- switch (legacy_flag) {
- case legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED:
- return StaScanDataFlagMask::INTERRUPTED;
- };
- CHECK(false) << "Unknown legacy flag: " << legacy_flag;
- // To silence the compiler warning about reaching the end of non-void
- // function.
- return {};
-}
-
-bool convertLegacyGscanCapabilitiesToHidl(const legacy_hal::wifi_gscan_capabilities& legacy_caps,
- StaBackgroundScanCapabilities* hidl_caps) {
- if (!hidl_caps) {
- return false;
- }
- *hidl_caps = {};
- hidl_caps->maxCacheSize = legacy_caps.max_scan_cache_size;
- hidl_caps->maxBuckets = legacy_caps.max_scan_buckets;
- hidl_caps->maxApCachePerScan = legacy_caps.max_ap_cache_per_scan;
- hidl_caps->maxReportingThreshold = legacy_caps.max_scan_reporting_threshold;
- return true;
-}
-
-legacy_hal::wifi_band convertHidlWifiBandToLegacy(V1_0::WifiBand band) {
- switch (band) {
- case V1_0::WifiBand::BAND_UNSPECIFIED:
- return legacy_hal::WIFI_BAND_UNSPECIFIED;
- case V1_0::WifiBand::BAND_24GHZ:
- return legacy_hal::WIFI_BAND_BG;
- case V1_0::WifiBand::BAND_5GHZ:
- return legacy_hal::WIFI_BAND_A;
- case V1_0::WifiBand::BAND_5GHZ_DFS:
- return legacy_hal::WIFI_BAND_A_DFS;
- case V1_0::WifiBand::BAND_5GHZ_WITH_DFS:
- return legacy_hal::WIFI_BAND_A_WITH_DFS;
- case V1_0::WifiBand::BAND_24GHZ_5GHZ:
- return legacy_hal::WIFI_BAND_ABG;
- case V1_0::WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
- return legacy_hal::WIFI_BAND_ABG_WITH_DFS;
- };
- CHECK(false);
-}
-
-bool convertHidlGscanParamsToLegacy(const StaBackgroundScanParameters& hidl_scan_params,
- legacy_hal::wifi_scan_cmd_params* legacy_scan_params) {
- if (!legacy_scan_params) {
- return false;
- }
- *legacy_scan_params = {};
- legacy_scan_params->base_period = hidl_scan_params.basePeriodInMs;
- legacy_scan_params->max_ap_per_scan = hidl_scan_params.maxApPerScan;
- legacy_scan_params->report_threshold_percent = hidl_scan_params.reportThresholdPercent;
- legacy_scan_params->report_threshold_num_scans = hidl_scan_params.reportThresholdNumScans;
- if (hidl_scan_params.buckets.size() > MAX_BUCKETS) {
- return false;
- }
- legacy_scan_params->num_buckets = hidl_scan_params.buckets.size();
- for (uint32_t bucket_idx = 0; bucket_idx < hidl_scan_params.buckets.size(); bucket_idx++) {
- const StaBackgroundScanBucketParameters& hidl_bucket_spec =
- hidl_scan_params.buckets[bucket_idx];
- legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec =
- legacy_scan_params->buckets[bucket_idx];
- if (hidl_bucket_spec.bucketIdx >= MAX_BUCKETS) {
- return false;
- }
- legacy_bucket_spec.bucket = hidl_bucket_spec.bucketIdx;
- legacy_bucket_spec.band = convertHidlWifiBandToLegacy(hidl_bucket_spec.band);
- legacy_bucket_spec.period = hidl_bucket_spec.periodInMs;
- legacy_bucket_spec.max_period = hidl_bucket_spec.exponentialMaxPeriodInMs;
- legacy_bucket_spec.base = hidl_bucket_spec.exponentialBase;
- legacy_bucket_spec.step_count = hidl_bucket_spec.exponentialStepCount;
- legacy_bucket_spec.report_events = 0;
- using HidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
- for (const auto flag : {HidlFlag::EACH_SCAN, HidlFlag::FULL_RESULTS, HidlFlag::NO_BATCH}) {
- if (hidl_bucket_spec.eventReportScheme &
- static_cast<std::underlying_type<HidlFlag>::type>(flag)) {
- legacy_bucket_spec.report_events |= convertHidlGscanReportEventFlagToLegacy(flag);
- }
- }
- if (hidl_bucket_spec.frequencies.size() > MAX_CHANNELS) {
- return false;
- }
- legacy_bucket_spec.num_channels = hidl_bucket_spec.frequencies.size();
- for (uint32_t freq_idx = 0; freq_idx < hidl_bucket_spec.frequencies.size(); freq_idx++) {
- legacy_bucket_spec.channels[freq_idx].channel = hidl_bucket_spec.frequencies[freq_idx];
- }
- }
- return true;
-}
-
-bool convertLegacyIeToHidl(const legacy_hal::wifi_information_element& legacy_ie,
- WifiInformationElement* hidl_ie) {
- if (!hidl_ie) {
- return false;
- }
- *hidl_ie = {};
- hidl_ie->id = legacy_ie.id;
- hidl_ie->data = std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len);
- return true;
-}
-
-bool convertLegacyIeBlobToHidl(const uint8_t* ie_blob, uint32_t ie_blob_len,
- std::vector<WifiInformationElement>* hidl_ies) {
- if (!ie_blob || !hidl_ies) {
- return false;
- }
- *hidl_ies = {};
- const uint8_t* ies_begin = ie_blob;
- const uint8_t* ies_end = ie_blob + ie_blob_len;
- const uint8_t* next_ie = ies_begin;
- using wifi_ie = legacy_hal::wifi_information_element;
- constexpr size_t kIeHeaderLen = sizeof(wifi_ie);
- // Each IE should atleast have the header (i.e |id| & |len| fields).
- while (next_ie + kIeHeaderLen <= ies_end) {
- const wifi_ie& legacy_ie = (*reinterpret_cast<const wifi_ie*>(next_ie));
- uint32_t curr_ie_len = kIeHeaderLen + legacy_ie.len;
- if (next_ie + curr_ie_len > ies_end) {
- LOG(ERROR) << "Error parsing IE blob. Next IE: " << (void*)next_ie
- << ", Curr IE len: " << curr_ie_len << ", IEs End: " << (void*)ies_end;
- break;
- }
- WifiInformationElement hidl_ie;
- if (!convertLegacyIeToHidl(legacy_ie, &hidl_ie)) {
- LOG(ERROR) << "Error converting IE. Id: " << legacy_ie.id << ", len: " << legacy_ie.len;
- break;
- }
- hidl_ies->push_back(std::move(hidl_ie));
- next_ie += curr_ie_len;
- }
- // Check if the blob has been fully consumed.
- if (next_ie != ies_end) {
- LOG(ERROR) << "Failed to fully parse IE blob. Next IE: " << (void*)next_ie
- << ", IEs End: " << (void*)ies_end;
- }
- return true;
-}
-
-bool convertLegacyGscanResultToHidl(const legacy_hal::wifi_scan_result& legacy_scan_result,
- bool has_ie_data, StaScanResult* hidl_scan_result) {
- if (!hidl_scan_result) {
- return false;
- }
- *hidl_scan_result = {};
- hidl_scan_result->timeStampInUs = legacy_scan_result.ts;
- hidl_scan_result->ssid = std::vector<uint8_t>(
- legacy_scan_result.ssid,
- legacy_scan_result.ssid +
- strnlen(legacy_scan_result.ssid, sizeof(legacy_scan_result.ssid) - 1));
- memcpy(hidl_scan_result->bssid.data(), legacy_scan_result.bssid,
- hidl_scan_result->bssid.size());
- hidl_scan_result->frequency = legacy_scan_result.channel;
- hidl_scan_result->rssi = legacy_scan_result.rssi;
- hidl_scan_result->beaconPeriodInMs = legacy_scan_result.beacon_period;
- hidl_scan_result->capability = legacy_scan_result.capability;
- if (has_ie_data) {
- std::vector<WifiInformationElement> ies;
- if (!convertLegacyIeBlobToHidl(reinterpret_cast<const uint8_t*>(legacy_scan_result.ie_data),
- legacy_scan_result.ie_length, &ies)) {
- return false;
- }
- hidl_scan_result->informationElements = std::move(ies);
- }
- return true;
-}
-
-bool convertLegacyCachedGscanResultsToHidl(
- const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result,
- StaScanData* hidl_scan_data) {
- if (!hidl_scan_data) {
- return false;
- }
- *hidl_scan_data = {};
- hidl_scan_data->flags = 0;
- for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) {
- if (legacy_cached_scan_result.flags & flag) {
- hidl_scan_data->flags |= static_cast<std::underlying_type<StaScanDataFlagMask>::type>(
- convertLegacyGscanDataFlagToHidl(flag));
- }
- }
- hidl_scan_data->bucketsScanned = legacy_cached_scan_result.buckets_scanned;
-
- CHECK(legacy_cached_scan_result.num_results >= 0 &&
- legacy_cached_scan_result.num_results <= MAX_AP_CACHE_PER_SCAN);
- std::vector<StaScanResult> hidl_scan_results;
- for (int32_t result_idx = 0; result_idx < legacy_cached_scan_result.num_results; result_idx++) {
- StaScanResult hidl_scan_result;
- if (!convertLegacyGscanResultToHidl(legacy_cached_scan_result.results[result_idx], false,
- &hidl_scan_result)) {
- return false;
- }
- hidl_scan_results.push_back(hidl_scan_result);
- }
- hidl_scan_data->results = std::move(hidl_scan_results);
- return true;
-}
-
-bool convertLegacyVectorOfCachedGscanResultsToHidl(
- const std::vector<legacy_hal::wifi_cached_scan_results>& legacy_cached_scan_results,
- std::vector<StaScanData>* hidl_scan_datas) {
- if (!hidl_scan_datas) {
- return false;
- }
- *hidl_scan_datas = {};
- for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) {
- StaScanData hidl_scan_data;
- if (!convertLegacyCachedGscanResultsToHidl(legacy_cached_scan_result, &hidl_scan_data)) {
- return false;
- }
- hidl_scan_datas->push_back(hidl_scan_data);
- }
- return true;
-}
-
-WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToHidl(legacy_hal::wifi_tx_packet_fate fate) {
- switch (fate) {
- case legacy_hal::TX_PKT_FATE_ACKED:
- return WifiDebugTxPacketFate::ACKED;
- case legacy_hal::TX_PKT_FATE_SENT:
- return WifiDebugTxPacketFate::SENT;
- case legacy_hal::TX_PKT_FATE_FW_QUEUED:
- return WifiDebugTxPacketFate::FW_QUEUED;
- case legacy_hal::TX_PKT_FATE_FW_DROP_INVALID:
- return WifiDebugTxPacketFate::FW_DROP_INVALID;
- case legacy_hal::TX_PKT_FATE_FW_DROP_NOBUFS:
- return WifiDebugTxPacketFate::FW_DROP_NOBUFS;
- case legacy_hal::TX_PKT_FATE_FW_DROP_OTHER:
- return WifiDebugTxPacketFate::FW_DROP_OTHER;
- case legacy_hal::TX_PKT_FATE_DRV_QUEUED:
- return WifiDebugTxPacketFate::DRV_QUEUED;
- case legacy_hal::TX_PKT_FATE_DRV_DROP_INVALID:
- return WifiDebugTxPacketFate::DRV_DROP_INVALID;
- case legacy_hal::TX_PKT_FATE_DRV_DROP_NOBUFS:
- return WifiDebugTxPacketFate::DRV_DROP_NOBUFS;
- case legacy_hal::TX_PKT_FATE_DRV_DROP_OTHER:
- return WifiDebugTxPacketFate::DRV_DROP_OTHER;
- };
- CHECK(false) << "Unknown legacy fate type: " << fate;
-}
-
-WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToHidl(legacy_hal::wifi_rx_packet_fate fate) {
- switch (fate) {
- case legacy_hal::RX_PKT_FATE_SUCCESS:
- return WifiDebugRxPacketFate::SUCCESS;
- case legacy_hal::RX_PKT_FATE_FW_QUEUED:
- return WifiDebugRxPacketFate::FW_QUEUED;
- case legacy_hal::RX_PKT_FATE_FW_DROP_FILTER:
- return WifiDebugRxPacketFate::FW_DROP_FILTER;
- case legacy_hal::RX_PKT_FATE_FW_DROP_INVALID:
- return WifiDebugRxPacketFate::FW_DROP_INVALID;
- case legacy_hal::RX_PKT_FATE_FW_DROP_NOBUFS:
- return WifiDebugRxPacketFate::FW_DROP_NOBUFS;
- case legacy_hal::RX_PKT_FATE_FW_DROP_OTHER:
- return WifiDebugRxPacketFate::FW_DROP_OTHER;
- case legacy_hal::RX_PKT_FATE_DRV_QUEUED:
- return WifiDebugRxPacketFate::DRV_QUEUED;
- case legacy_hal::RX_PKT_FATE_DRV_DROP_FILTER:
- return WifiDebugRxPacketFate::DRV_DROP_FILTER;
- case legacy_hal::RX_PKT_FATE_DRV_DROP_INVALID:
- return WifiDebugRxPacketFate::DRV_DROP_INVALID;
- case legacy_hal::RX_PKT_FATE_DRV_DROP_NOBUFS:
- return WifiDebugRxPacketFate::DRV_DROP_NOBUFS;
- case legacy_hal::RX_PKT_FATE_DRV_DROP_OTHER:
- return WifiDebugRxPacketFate::DRV_DROP_OTHER;
- };
- CHECK(false) << "Unknown legacy fate type: " << fate;
-}
-
-WifiDebugPacketFateFrameType convertLegacyDebugPacketFateFrameTypeToHidl(
- legacy_hal::frame_type type) {
- switch (type) {
- case legacy_hal::FRAME_TYPE_UNKNOWN:
- return WifiDebugPacketFateFrameType::UNKNOWN;
- case legacy_hal::FRAME_TYPE_ETHERNET_II:
- return WifiDebugPacketFateFrameType::ETHERNET_II;
- case legacy_hal::FRAME_TYPE_80211_MGMT:
- return WifiDebugPacketFateFrameType::MGMT_80211;
- };
- CHECK(false) << "Unknown legacy frame type: " << type;
-}
-
-bool convertLegacyDebugPacketFateFrameToHidl(const legacy_hal::frame_info& legacy_frame,
- WifiDebugPacketFateFrameInfo* hidl_frame) {
- if (!hidl_frame) {
- return false;
- }
- *hidl_frame = {};
- hidl_frame->frameType = convertLegacyDebugPacketFateFrameTypeToHidl(legacy_frame.payload_type);
- hidl_frame->frameLen = legacy_frame.frame_len;
- hidl_frame->driverTimestampUsec = legacy_frame.driver_timestamp_usec;
- hidl_frame->firmwareTimestampUsec = legacy_frame.firmware_timestamp_usec;
- const uint8_t* frame_begin =
- reinterpret_cast<const uint8_t*>(legacy_frame.frame_content.ethernet_ii_bytes);
- hidl_frame->frameContent =
- std::vector<uint8_t>(frame_begin, frame_begin + legacy_frame.frame_len);
- return true;
-}
-
-bool convertLegacyDebugTxPacketFateToHidl(const legacy_hal::wifi_tx_report& legacy_fate,
- WifiDebugTxPacketFateReport* hidl_fate) {
- if (!hidl_fate) {
- return false;
- }
- *hidl_fate = {};
- hidl_fate->fate = convertLegacyDebugTxPacketFateToHidl(legacy_fate.fate);
- return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, &hidl_fate->frameInfo);
-}
-
-bool convertLegacyVectorOfDebugTxPacketFateToHidl(
- const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
- std::vector<WifiDebugTxPacketFateReport>* hidl_fates) {
- if (!hidl_fates) {
- return false;
- }
- *hidl_fates = {};
- for (const auto& legacy_fate : legacy_fates) {
- WifiDebugTxPacketFateReport hidl_fate;
- if (!convertLegacyDebugTxPacketFateToHidl(legacy_fate, &hidl_fate)) {
- return false;
- }
- hidl_fates->push_back(hidl_fate);
- }
- return true;
-}
-
-bool convertLegacyDebugRxPacketFateToHidl(const legacy_hal::wifi_rx_report& legacy_fate,
- WifiDebugRxPacketFateReport* hidl_fate) {
- if (!hidl_fate) {
- return false;
- }
- *hidl_fate = {};
- hidl_fate->fate = convertLegacyDebugRxPacketFateToHidl(legacy_fate.fate);
- return convertLegacyDebugPacketFateFrameToHidl(legacy_fate.frame_inf, &hidl_fate->frameInfo);
-}
-
-bool convertLegacyVectorOfDebugRxPacketFateToHidl(
- const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
- std::vector<WifiDebugRxPacketFateReport>* hidl_fates) {
- if (!hidl_fates) {
- return false;
- }
- *hidl_fates = {};
- for (const auto& legacy_fate : legacy_fates) {
- WifiDebugRxPacketFateReport hidl_fate;
- if (!convertLegacyDebugRxPacketFateToHidl(legacy_fate, &hidl_fate)) {
- return false;
- }
- hidl_fates->push_back(hidl_fate);
- }
- return true;
-}
-
-bool convertLegacyLinkLayerRadioStatsToHidl(
- const legacy_hal::LinkLayerRadioStats& legacy_radio_stat,
- V1_6::StaLinkLayerRadioStats* hidl_radio_stat) {
- if (!hidl_radio_stat) {
- return false;
- }
- *hidl_radio_stat = {};
-
- hidl_radio_stat->radioId = legacy_radio_stat.stats.radio;
- hidl_radio_stat->V1_0.onTimeInMs = legacy_radio_stat.stats.on_time;
- hidl_radio_stat->V1_0.txTimeInMs = legacy_radio_stat.stats.tx_time;
- hidl_radio_stat->V1_0.rxTimeInMs = legacy_radio_stat.stats.rx_time;
- hidl_radio_stat->V1_0.onTimeInMsForScan = legacy_radio_stat.stats.on_time_scan;
- hidl_radio_stat->V1_0.txTimeInMsPerLevel = legacy_radio_stat.tx_time_per_levels;
- hidl_radio_stat->onTimeInMsForNanScan = legacy_radio_stat.stats.on_time_nbd;
- hidl_radio_stat->onTimeInMsForBgScan = legacy_radio_stat.stats.on_time_gscan;
- hidl_radio_stat->onTimeInMsForRoamScan = legacy_radio_stat.stats.on_time_roam_scan;
- hidl_radio_stat->onTimeInMsForPnoScan = legacy_radio_stat.stats.on_time_pno_scan;
- hidl_radio_stat->onTimeInMsForHs20Scan = legacy_radio_stat.stats.on_time_hs20;
-
- std::vector<V1_6::WifiChannelStats> hidl_channel_stats;
-
- for (const auto& channel_stat : legacy_radio_stat.channel_stats) {
- V1_6::WifiChannelStats hidl_channel_stat;
- hidl_channel_stat.onTimeInMs = channel_stat.on_time;
- hidl_channel_stat.ccaBusyTimeInMs = channel_stat.cca_busy_time;
- /*
- * TODO once b/119142899 is fixed,
- * replace below code with convertLegacyWifiChannelInfoToHidl()
- */
- hidl_channel_stat.channel.width = WifiChannelWidthInMhz::WIDTH_20;
- hidl_channel_stat.channel.centerFreq = channel_stat.channel.center_freq;
- hidl_channel_stat.channel.centerFreq0 = channel_stat.channel.center_freq0;
- hidl_channel_stat.channel.centerFreq1 = channel_stat.channel.center_freq1;
- hidl_channel_stats.push_back(hidl_channel_stat);
- }
-
- hidl_radio_stat->channelStats = hidl_channel_stats;
-
- return true;
-}
-
-bool convertLegacyLinkLayerStatsToHidl(const legacy_hal::LinkLayerStats& legacy_stats,
- V1_6::StaLinkLayerStats* hidl_stats) {
- if (!hidl_stats) {
- return false;
- }
- *hidl_stats = {};
- // iface legacy_stats conversion.
- hidl_stats->iface.V1_0.beaconRx = legacy_stats.iface.beacon_rx;
- hidl_stats->iface.V1_0.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
- hidl_stats->iface.V1_0.wmeBePktStats.rxMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
- hidl_stats->iface.V1_0.wmeBePktStats.txMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
- hidl_stats->iface.V1_0.wmeBePktStats.lostMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
- hidl_stats->iface.V1_0.wmeBePktStats.retries =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries;
- hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMinInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min;
- hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max;
- hidl_stats->iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg;
- hidl_stats->iface.wmeBeContentionTimeStats.contentionNumSamples =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples;
- hidl_stats->iface.V1_0.wmeBkPktStats.rxMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
- hidl_stats->iface.V1_0.wmeBkPktStats.txMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
- hidl_stats->iface.V1_0.wmeBkPktStats.lostMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
- hidl_stats->iface.V1_0.wmeBkPktStats.retries =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries;
- hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMinInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min;
- hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max;
- hidl_stats->iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg;
- hidl_stats->iface.wmeBkContentionTimeStats.contentionNumSamples =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples;
- hidl_stats->iface.V1_0.wmeViPktStats.rxMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
- hidl_stats->iface.V1_0.wmeViPktStats.txMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
- hidl_stats->iface.V1_0.wmeViPktStats.lostMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
- hidl_stats->iface.V1_0.wmeViPktStats.retries =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries;
- hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMinInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min;
- hidl_stats->iface.wmeViContentionTimeStats.contentionTimeMaxInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max;
- hidl_stats->iface.wmeViContentionTimeStats.contentionTimeAvgInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg;
- hidl_stats->iface.wmeViContentionTimeStats.contentionNumSamples =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples;
- hidl_stats->iface.V1_0.wmeVoPktStats.rxMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
- hidl_stats->iface.V1_0.wmeVoPktStats.txMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
- hidl_stats->iface.V1_0.wmeVoPktStats.lostMpdu =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
- hidl_stats->iface.V1_0.wmeVoPktStats.retries =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
- hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMinInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min;
- hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max;
- hidl_stats->iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg;
- hidl_stats->iface.wmeVoContentionTimeStats.contentionNumSamples =
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples;
- hidl_stats->iface.timeSliceDutyCycleInPercent =
- legacy_stats.iface.info.time_slicing_duty_cycle_percent;
- // peer info legacy_stats conversion.
- std::vector<V1_6::StaPeerInfo> hidl_peers_info_stats;
- for (const auto& legacy_peer_info_stats : legacy_stats.peers) {
- V1_6::StaPeerInfo hidl_peer_info_stats;
- if (!convertLegacyPeerInfoStatsToHidl(legacy_peer_info_stats, &hidl_peer_info_stats)) {
- return false;
- }
- hidl_peers_info_stats.push_back(hidl_peer_info_stats);
- }
- hidl_stats->iface.peers = hidl_peers_info_stats;
- // radio legacy_stats conversion.
- std::vector<V1_6::StaLinkLayerRadioStats> hidl_radios_stats;
- for (const auto& legacy_radio_stats : legacy_stats.radios) {
- V1_6::StaLinkLayerRadioStats hidl_radio_stats;
- if (!convertLegacyLinkLayerRadioStatsToHidl(legacy_radio_stats, &hidl_radio_stats)) {
- return false;
- }
- hidl_radios_stats.push_back(hidl_radio_stats);
- }
- hidl_stats->radios = hidl_radios_stats;
- // Timestamp in the HAL wrapper here since it's not provided in the legacy
- // HAL API.
- hidl_stats->timeStampInMs = uptimeMillis();
- return true;
-}
-
-bool convertLegacyPeerInfoStatsToHidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats,
- V1_6::StaPeerInfo* hidl_peer_info_stats) {
- if (!hidl_peer_info_stats) {
- return false;
- }
- *hidl_peer_info_stats = {};
- hidl_peer_info_stats->staCount = legacy_peer_info_stats.peer_info.bssload.sta_count;
- hidl_peer_info_stats->chanUtil = legacy_peer_info_stats.peer_info.bssload.chan_util;
-
- std::vector<V1_6::StaRateStat> hidlRateStats;
- for (const auto& legacy_rate_stats : legacy_peer_info_stats.rate_stats) {
- V1_6::StaRateStat rateStat;
- if (!convertLegacyWifiRateInfoToHidl(legacy_rate_stats.rate, &rateStat.rateInfo)) {
- return false;
- }
- rateStat.txMpdu = legacy_rate_stats.tx_mpdu;
- rateStat.rxMpdu = legacy_rate_stats.rx_mpdu;
- rateStat.mpduLost = legacy_rate_stats.mpdu_lost;
- rateStat.retries = legacy_rate_stats.retries;
- hidlRateStats.push_back(rateStat);
- }
- hidl_peer_info_stats->rateStats = hidlRateStats;
- return true;
-}
-
-bool convertLegacyRoamingCapabilitiesToHidl(
- const legacy_hal::wifi_roaming_capabilities& legacy_caps,
- StaRoamingCapabilities* hidl_caps) {
- if (!hidl_caps) {
- return false;
- }
- *hidl_caps = {};
- hidl_caps->maxBlacklistSize = legacy_caps.max_blacklist_size;
- hidl_caps->maxWhitelistSize = legacy_caps.max_whitelist_size;
- return true;
-}
-
-bool convertHidlRoamingConfigToLegacy(const StaRoamingConfig& hidl_config,
- legacy_hal::wifi_roaming_config* legacy_config) {
- if (!legacy_config) {
- return false;
- }
- *legacy_config = {};
- if (hidl_config.bssidBlacklist.size() > MAX_BLACKLIST_BSSID ||
- hidl_config.ssidWhitelist.size() > MAX_WHITELIST_SSID) {
- return false;
- }
- legacy_config->num_blacklist_bssid = hidl_config.bssidBlacklist.size();
- uint32_t i = 0;
- for (const auto& bssid : hidl_config.bssidBlacklist) {
- CHECK(bssid.size() == sizeof(legacy_hal::mac_addr));
- memcpy(legacy_config->blacklist_bssid[i++], bssid.data(), bssid.size());
- }
- legacy_config->num_whitelist_ssid = hidl_config.ssidWhitelist.size();
- i = 0;
- for (const auto& ssid : hidl_config.ssidWhitelist) {
- CHECK(ssid.size() <= sizeof(legacy_hal::ssid_t::ssid_str));
- legacy_config->whitelist_ssid[i].length = ssid.size();
- memcpy(legacy_config->whitelist_ssid[i].ssid_str, ssid.data(), ssid.size());
- i++;
- }
- return true;
-}
-
-legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(StaRoamingState state) {
- switch (state) {
- case StaRoamingState::ENABLED:
- return legacy_hal::ROAMING_ENABLE;
- case StaRoamingState::DISABLED:
- return legacy_hal::ROAMING_DISABLE;
- };
- CHECK(false);
-}
-
-legacy_hal::NanMatchAlg convertHidlNanMatchAlgToLegacy(NanMatchAlg type) {
- switch (type) {
- case NanMatchAlg::MATCH_ONCE:
- return legacy_hal::NAN_MATCH_ALG_MATCH_ONCE;
- case NanMatchAlg::MATCH_CONTINUOUS:
- return legacy_hal::NAN_MATCH_ALG_MATCH_CONTINUOUS;
- case NanMatchAlg::MATCH_NEVER:
- return legacy_hal::NAN_MATCH_ALG_MATCH_NEVER;
- }
- CHECK(false);
-}
-
-legacy_hal::NanPublishType convertHidlNanPublishTypeToLegacy(NanPublishType type) {
- switch (type) {
- case NanPublishType::UNSOLICITED:
- return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED;
- case NanPublishType::SOLICITED:
- return legacy_hal::NAN_PUBLISH_TYPE_SOLICITED;
- case NanPublishType::UNSOLICITED_SOLICITED:
- return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
- }
- CHECK(false);
-}
-
-legacy_hal::NanTxType convertHidlNanTxTypeToLegacy(NanTxType type) {
- switch (type) {
- case NanTxType::BROADCAST:
- return legacy_hal::NAN_TX_TYPE_BROADCAST;
- case NanTxType::UNICAST:
- return legacy_hal::NAN_TX_TYPE_UNICAST;
- }
- CHECK(false);
-}
-
-legacy_hal::NanSubscribeType convertHidlNanSubscribeTypeToLegacy(NanSubscribeType type) {
- switch (type) {
- case NanSubscribeType::PASSIVE:
- return legacy_hal::NAN_SUBSCRIBE_TYPE_PASSIVE;
- case NanSubscribeType::ACTIVE:
- return legacy_hal::NAN_SUBSCRIBE_TYPE_ACTIVE;
- }
- CHECK(false);
-}
-
-legacy_hal::NanSRFType convertHidlNanSrfTypeToLegacy(NanSrfType type) {
- switch (type) {
- case NanSrfType::BLOOM_FILTER:
- return legacy_hal::NAN_SRF_ATTR_BLOOM_FILTER;
- case NanSrfType::PARTIAL_MAC_ADDR:
- return legacy_hal::NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
- }
- CHECK(false);
-}
-
-legacy_hal::NanDataPathChannelCfg convertHidlNanDataPathChannelCfgToLegacy(
- NanDataPathChannelCfg type) {
- switch (type) {
- case NanDataPathChannelCfg::CHANNEL_NOT_REQUESTED:
- return legacy_hal::NAN_DP_CHANNEL_NOT_REQUESTED;
- case NanDataPathChannelCfg::REQUEST_CHANNEL_SETUP:
- return legacy_hal::NAN_DP_REQUEST_CHANNEL_SETUP;
- case NanDataPathChannelCfg::FORCE_CHANNEL_SETUP:
- return legacy_hal::NAN_DP_FORCE_CHANNEL_SETUP;
- }
- CHECK(false);
-}
-
-NanStatusType convertLegacyNanStatusTypeToHidl(legacy_hal::NanStatusType type) {
- switch (type) {
- case legacy_hal::NAN_STATUS_SUCCESS:
- return NanStatusType::SUCCESS;
- case legacy_hal::NAN_STATUS_INTERNAL_FAILURE:
- return NanStatusType::INTERNAL_FAILURE;
- case legacy_hal::NAN_STATUS_PROTOCOL_FAILURE:
- return NanStatusType::PROTOCOL_FAILURE;
- case legacy_hal::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID:
- return NanStatusType::INVALID_SESSION_ID;
- case legacy_hal::NAN_STATUS_NO_RESOURCE_AVAILABLE:
- return NanStatusType::NO_RESOURCES_AVAILABLE;
- case legacy_hal::NAN_STATUS_INVALID_PARAM:
- return NanStatusType::INVALID_ARGS;
- case legacy_hal::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID:
- return NanStatusType::INVALID_PEER_ID;
- case legacy_hal::NAN_STATUS_INVALID_NDP_ID:
- return NanStatusType::INVALID_NDP_ID;
- case legacy_hal::NAN_STATUS_NAN_NOT_ALLOWED:
- return NanStatusType::NAN_NOT_ALLOWED;
- case legacy_hal::NAN_STATUS_NO_OTA_ACK:
- return NanStatusType::NO_OTA_ACK;
- case legacy_hal::NAN_STATUS_ALREADY_ENABLED:
- return NanStatusType::ALREADY_ENABLED;
- case legacy_hal::NAN_STATUS_FOLLOWUP_QUEUE_FULL:
- return NanStatusType::FOLLOWUP_TX_QUEUE_FULL;
- case legacy_hal::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED:
- return NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
- }
- CHECK(false);
-}
-
-void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
- WifiNanStatus* wifiNanStatus) {
- wifiNanStatus->status = convertLegacyNanStatusTypeToHidl(type);
- wifiNanStatus->description = safeConvertChar(str, max_len);
-}
-
-bool convertHidlNanEnableRequestToLegacy(const V1_4::NanEnableRequest& hidl_request,
- legacy_hal::NanEnableRequest* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: null legacy_request";
- return false;
- }
- *legacy_request = {};
-
- legacy_request->config_2dot4g_support = 1;
- legacy_request->support_2dot4g_val =
- hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_24GHZ];
- legacy_request->config_support_5g = 1;
- legacy_request->support_5g_val =
- hidl_request.operateInBand[(size_t)NanBandIndex::NAN_BAND_5GHZ];
- legacy_request->config_hop_count_limit = 1;
- legacy_request->hop_count_limit_val = hidl_request.hopCountMax;
- legacy_request->master_pref = hidl_request.configParams.masterPref;
- legacy_request->discovery_indication_cfg = 0;
- legacy_request->discovery_indication_cfg |=
- hidl_request.configParams.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
- legacy_request->discovery_indication_cfg |=
- hidl_request.configParams.disableStartedClusterIndication ? 0x2 : 0x0;
- legacy_request->discovery_indication_cfg |=
- hidl_request.configParams.disableJoinedClusterIndication ? 0x4 : 0x0;
- legacy_request->config_sid_beacon = 1;
- if (hidl_request.configParams.numberOfPublishServiceIdsInBeacon > 127) {
- LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
- "numberOfPublishServiceIdsInBeacon > 127";
- return false;
- }
- legacy_request->sid_beacon_val =
- (hidl_request.configParams.includePublishServiceIdsInBeacon ? 0x1 : 0x0) |
- (hidl_request.configParams.numberOfPublishServiceIdsInBeacon << 1);
- legacy_request->config_subscribe_sid_beacon = 1;
- if (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon > 127) {
- LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
- "numberOfSubscribeServiceIdsInBeacon > 127";
- return false;
- }
- legacy_request->subscribe_sid_beacon_val =
- (hidl_request.configParams.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) |
- (hidl_request.configParams.numberOfSubscribeServiceIdsInBeacon << 1);
- legacy_request->config_rssi_window_size = 1;
- legacy_request->rssi_window_size_val = hidl_request.configParams.rssiWindowSize;
- legacy_request->config_disc_mac_addr_randomization = 1;
- legacy_request->disc_mac_addr_rand_interval_sec =
- hidl_request.configParams.macAddressRandomizationIntervalSec;
- legacy_request->config_2dot4g_rssi_close = 1;
- if (hidl_request.configParams.bandSpecificConfig.size() != 3) {
- LOG(ERROR) << "convertHidlNanEnableRequestToLegacy: "
- "bandSpecificConfig.size() != 3";
- return false;
- }
- legacy_request->rssi_close_2dot4g_val =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
- .rssiClose;
- legacy_request->config_2dot4g_rssi_middle = 1;
- legacy_request->rssi_middle_2dot4g_val =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
- .rssiMiddle;
- legacy_request->config_2dot4g_rssi_proximity = 1;
- legacy_request->rssi_proximity_2dot4g_val =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
- .rssiCloseProximity;
- legacy_request->config_scan_params = 1;
- legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
- .dwellTimeMs;
- legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
- .scanPeriodSec;
- legacy_request->config_dw.config_2dot4g_dw_band =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
- .validDiscoveryWindowIntervalVal;
- legacy_request->config_dw.dw_2dot4g_interval_val =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
- .discoveryWindowIntervalVal;
- legacy_request->config_5g_rssi_close = 1;
- legacy_request->rssi_close_5g_val =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .rssiClose;
- legacy_request->config_5g_rssi_middle = 1;
- legacy_request->rssi_middle_5g_val =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .rssiMiddle;
- legacy_request->config_5g_rssi_close_proximity = 1;
- legacy_request->rssi_close_proximity_5g_val =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .rssiCloseProximity;
- legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .dwellTimeMs;
- legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .scanPeriodSec;
- legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .dwellTimeMs;
- legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .scanPeriodSec;
- legacy_request->config_dw.config_5g_dw_band =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .validDiscoveryWindowIntervalVal;
- legacy_request->config_dw.dw_5g_interval_val =
- hidl_request.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .discoveryWindowIntervalVal;
- if (hidl_request.debugConfigs.validClusterIdVals) {
- legacy_request->cluster_low = hidl_request.debugConfigs.clusterIdBottomRangeVal;
- legacy_request->cluster_high = hidl_request.debugConfigs.clusterIdTopRangeVal;
- } else { // need 'else' since not configurable in legacy HAL
- legacy_request->cluster_low = 0x0000;
- legacy_request->cluster_high = 0xFFFF;
- }
- legacy_request->config_intf_addr = hidl_request.debugConfigs.validIntfAddrVal;
- memcpy(legacy_request->intf_addr_val, hidl_request.debugConfigs.intfAddrVal.data(), 6);
- legacy_request->config_oui = hidl_request.debugConfigs.validOuiVal;
- legacy_request->oui_val = hidl_request.debugConfigs.ouiVal;
- legacy_request->config_random_factor_force =
- hidl_request.debugConfigs.validRandomFactorForceVal;
- legacy_request->random_factor_force_val = hidl_request.debugConfigs.randomFactorForceVal;
- legacy_request->config_hop_count_force = hidl_request.debugConfigs.validHopCountForceVal;
- legacy_request->hop_count_force_val = hidl_request.debugConfigs.hopCountForceVal;
- legacy_request->config_24g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal;
- legacy_request->channel_24g_val =
- hidl_request.debugConfigs.discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
- legacy_request->config_5g_channel = hidl_request.debugConfigs.validDiscoveryChannelVal;
- legacy_request->channel_5g_val =
- hidl_request.debugConfigs.discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
- legacy_request->config_2dot4g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal;
- legacy_request->beacon_2dot4g_val =
- hidl_request.debugConfigs.useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
- legacy_request->config_5g_beacons = hidl_request.debugConfigs.validUseBeaconsInBandVal;
- legacy_request->beacon_5g_val =
- hidl_request.debugConfigs.useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
- legacy_request->config_2dot4g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal;
- legacy_request->sdf_2dot4g_val =
- hidl_request.debugConfigs.useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
- legacy_request->config_5g_sdf = hidl_request.debugConfigs.validUseSdfInBandVal;
- legacy_request->sdf_5g_val =
- hidl_request.debugConfigs.useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
-
- /* TODO: b/145609058
- * Missing updates needed to legacy_hal::NanEnableRequest and conversion to
- * it for 6GHz band */
-
- return true;
-}
-
-bool convertHidlNanEnableRequest_1_6ToLegacy(const V1_4::NanEnableRequest& hidl_request1,
- const NanConfigRequestSupplemental& hidl_request2,
- legacy_hal::NanEnableRequest* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanEnableRequest_1_6ToLegacy: null legacy_request";
- return false;
- }
-
- *legacy_request = {};
- if (!convertHidlNanEnableRequestToLegacy(hidl_request1, legacy_request)) {
- return false;
- }
-
- legacy_request->config_discovery_beacon_int = 1;
- legacy_request->discovery_beacon_interval = hidl_request2.V1_5.V1_2.discoveryBeaconIntervalMs;
- legacy_request->config_nss = 1;
- legacy_request->nss = hidl_request2.V1_5.V1_2.numberOfSpatialStreamsInDiscovery;
- legacy_request->config_dw_early_termination = 1;
- legacy_request->enable_dw_termination =
- hidl_request2.V1_5.V1_2.enableDiscoveryWindowEarlyTermination;
- legacy_request->config_enable_ranging = 1;
- legacy_request->enable_ranging = hidl_request2.V1_5.V1_2.enableRanging;
-
- legacy_request->config_enable_instant_mode = 1;
- legacy_request->enable_instant_mode = hidl_request2.V1_5.enableInstantCommunicationMode;
- legacy_request->config_instant_mode_channel = 1;
- legacy_request->instant_mode_channel = hidl_request2.instantModeChannel;
-
- return true;
-}
-
-bool convertHidlNanConfigRequest_1_6ToLegacy(const V1_4::NanConfigRequest& hidl_request1,
- const NanConfigRequestSupplemental& hidl_request2,
- legacy_hal::NanConfigRequest* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanConfigRequest_1_6ToLegacy: null legacy_request";
- return false;
- }
-
- *legacy_request = {};
- if (!convertHidlNanConfigRequestToLegacy(hidl_request1, legacy_request)) {
- return false;
- }
-
- legacy_request->config_discovery_beacon_int = 1;
- legacy_request->discovery_beacon_interval = hidl_request2.V1_5.V1_2.discoveryBeaconIntervalMs;
- legacy_request->config_nss = 1;
- legacy_request->nss = hidl_request2.V1_5.V1_2.numberOfSpatialStreamsInDiscovery;
- legacy_request->config_dw_early_termination = 1;
- legacy_request->enable_dw_termination =
- hidl_request2.V1_5.V1_2.enableDiscoveryWindowEarlyTermination;
- legacy_request->config_enable_ranging = 1;
- legacy_request->enable_ranging = hidl_request2.V1_5.V1_2.enableRanging;
-
- legacy_request->config_enable_instant_mode = 1;
- legacy_request->enable_instant_mode = hidl_request2.V1_5.enableInstantCommunicationMode;
- legacy_request->config_instant_mode_channel = 1;
- legacy_request->instant_mode_channel = hidl_request2.instantModeChannel;
-
- return true;
-}
-
-bool convertHidlNanPublishRequestToLegacy(const V1_6::NanPublishRequest& hidl_request,
- legacy_hal::NanPublishRequest* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: null legacy_request";
- return false;
- }
- *legacy_request = {};
-
- legacy_request->publish_id = hidl_request.baseConfigs.sessionId;
- legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
- legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod;
- legacy_request->publish_count = hidl_request.baseConfigs.discoveryCount;
- legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size();
- if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: service_name_len "
- "too large";
- return false;
- }
- memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(),
- legacy_request->service_name_len);
- legacy_request->publish_match_indicator =
- convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator);
- legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size();
- if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
- "service_specific_info_len too large";
- return false;
- }
- memcpy(legacy_request->service_specific_info,
- hidl_request.baseConfigs.serviceSpecificInfo.data(),
- legacy_request->service_specific_info_len);
- legacy_request->sdea_service_specific_info_len =
- hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
- if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
- "sdea_service_specific_info_len too large";
- return false;
- }
- memcpy(legacy_request->sdea_service_specific_info,
- hidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
- legacy_request->sdea_service_specific_info_len);
- legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size();
- if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
- "rx_match_filter_len too large";
- return false;
- }
- memcpy(legacy_request->rx_match_filter, hidl_request.baseConfigs.rxMatchFilter.data(),
- legacy_request->rx_match_filter_len);
- legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size();
- if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
- "tx_match_filter_len too large";
- return false;
- }
- memcpy(legacy_request->tx_match_filter, hidl_request.baseConfigs.txMatchFilter.data(),
- legacy_request->tx_match_filter_len);
- legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold;
- legacy_request->recv_indication_cfg = 0;
- legacy_request->recv_indication_cfg |=
- hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0;
- legacy_request->recv_indication_cfg |=
- hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
- legacy_request->recv_indication_cfg |=
- hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
- legacy_request->recv_indication_cfg |= 0x8;
- legacy_request->cipher_type = (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType;
-
- legacy_request->scid_len = hidl_request.baseConfigs.securityConfig.scid.size();
- if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: scid_len too large";
- return false;
- }
- memcpy(legacy_request->scid, hidl_request.baseConfigs.securityConfig.scid.data(),
- legacy_request->scid_len);
-
- if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
- legacy_request->key_info.body.pmk_info.pmk_len =
- hidl_request.baseConfigs.securityConfig.pmk.size();
- if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: invalid pmk_len";
- return false;
- }
- memcpy(legacy_request->key_info.body.pmk_info.pmk,
- hidl_request.baseConfigs.securityConfig.pmk.data(),
- legacy_request->key_info.body.pmk_info.pmk_len);
- }
- if (hidl_request.baseConfigs.securityConfig.securityType ==
- NanDataPathSecurityType::PASSPHRASE) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
- legacy_request->key_info.body.passphrase_info.passphrase_len =
- hidl_request.baseConfigs.securityConfig.passphrase.size();
- if (legacy_request->key_info.body.passphrase_info.passphrase_len <
- NAN_SECURITY_MIN_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
- "passphrase_len too small";
- return false;
- }
- if (legacy_request->key_info.body.passphrase_info.passphrase_len >
- NAN_SECURITY_MAX_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanPublishRequestToLegacy: "
- "passphrase_len too large";
- return false;
- }
- memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
- hidl_request.baseConfigs.securityConfig.passphrase.data(),
- legacy_request->key_info.body.passphrase_info.passphrase_len);
- }
- legacy_request->sdea_params.security_cfg =
- (hidl_request.baseConfigs.securityConfig.securityType != NanDataPathSecurityType::OPEN)
- ? legacy_hal::NAN_DP_CONFIG_SECURITY
- : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
-
- legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired
- ? legacy_hal::NAN_RANGING_ENABLE
- : legacy_hal::NAN_RANGING_DISABLE;
- legacy_request->ranging_cfg.ranging_interval_msec =
- hidl_request.baseConfigs.rangingIntervalMsec;
- legacy_request->ranging_cfg.config_ranging_indications =
- hidl_request.baseConfigs.configRangingIndications;
- legacy_request->ranging_cfg.distance_ingress_mm =
- hidl_request.baseConfigs.distanceIngressCm * 10;
- legacy_request->ranging_cfg.distance_egress_mm = hidl_request.baseConfigs.distanceEgressCm * 10;
- legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired
- ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
- : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
- legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT;
- legacy_request->publish_type = convertHidlNanPublishTypeToLegacy(hidl_request.publishType);
- legacy_request->tx_type = convertHidlNanTxTypeToLegacy(hidl_request.txType);
- legacy_request->service_responder_policy = hidl_request.autoAcceptDataPathRequests
- ? legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL
- : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE;
-
- return true;
-}
-
-bool convertHidlNanSubscribeRequestToLegacy(const V1_0::NanSubscribeRequest& hidl_request,
- legacy_hal::NanSubscribeRequest* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: legacy_request is null";
- return false;
- }
- *legacy_request = {};
-
- legacy_request->subscribe_id = hidl_request.baseConfigs.sessionId;
- legacy_request->ttl = hidl_request.baseConfigs.ttlSec;
- legacy_request->period = hidl_request.baseConfigs.discoveryWindowPeriod;
- legacy_request->subscribe_count = hidl_request.baseConfigs.discoveryCount;
- legacy_request->service_name_len = hidl_request.baseConfigs.serviceName.size();
- if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
- "service_name_len too large";
- return false;
- }
- memcpy(legacy_request->service_name, hidl_request.baseConfigs.serviceName.data(),
- legacy_request->service_name_len);
- legacy_request->subscribe_match_indicator =
- convertHidlNanMatchAlgToLegacy(hidl_request.baseConfigs.discoveryMatchIndicator);
- legacy_request->service_specific_info_len = hidl_request.baseConfigs.serviceSpecificInfo.size();
- if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
- "service_specific_info_len too large";
- return false;
- }
- memcpy(legacy_request->service_specific_info,
- hidl_request.baseConfigs.serviceSpecificInfo.data(),
- legacy_request->service_specific_info_len);
- legacy_request->sdea_service_specific_info_len =
- hidl_request.baseConfigs.extendedServiceSpecificInfo.size();
- if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
- "sdea_service_specific_info_len too large";
- return false;
- }
- memcpy(legacy_request->sdea_service_specific_info,
- hidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
- legacy_request->sdea_service_specific_info_len);
- legacy_request->rx_match_filter_len = hidl_request.baseConfigs.rxMatchFilter.size();
- if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
- "rx_match_filter_len too large";
- return false;
- }
- memcpy(legacy_request->rx_match_filter, hidl_request.baseConfigs.rxMatchFilter.data(),
- legacy_request->rx_match_filter_len);
- legacy_request->tx_match_filter_len = hidl_request.baseConfigs.txMatchFilter.size();
- if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
- "tx_match_filter_len too large";
- return false;
- }
- memcpy(legacy_request->tx_match_filter, hidl_request.baseConfigs.txMatchFilter.data(),
- legacy_request->tx_match_filter_len);
- legacy_request->rssi_threshold_flag = hidl_request.baseConfigs.useRssiThreshold;
- legacy_request->recv_indication_cfg = 0;
- legacy_request->recv_indication_cfg |=
- hidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0;
- legacy_request->recv_indication_cfg |=
- hidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
- legacy_request->recv_indication_cfg |=
- hidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
- legacy_request->cipher_type = (unsigned int)hidl_request.baseConfigs.securityConfig.cipherType;
- if (hidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
- legacy_request->key_info.body.pmk_info.pmk_len =
- hidl_request.baseConfigs.securityConfig.pmk.size();
- if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: invalid pmk_len";
- return false;
- }
- memcpy(legacy_request->key_info.body.pmk_info.pmk,
- hidl_request.baseConfigs.securityConfig.pmk.data(),
- legacy_request->key_info.body.pmk_info.pmk_len);
- }
- if (hidl_request.baseConfigs.securityConfig.securityType ==
- NanDataPathSecurityType::PASSPHRASE) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
- legacy_request->key_info.body.passphrase_info.passphrase_len =
- hidl_request.baseConfigs.securityConfig.passphrase.size();
- if (legacy_request->key_info.body.passphrase_info.passphrase_len <
- NAN_SECURITY_MIN_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
- "passphrase_len too small";
- return false;
- }
- if (legacy_request->key_info.body.passphrase_info.passphrase_len >
- NAN_SECURITY_MAX_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
- "passphrase_len too large";
- return false;
- }
- memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
- hidl_request.baseConfigs.securityConfig.passphrase.data(),
- legacy_request->key_info.body.passphrase_info.passphrase_len);
- }
- legacy_request->sdea_params.security_cfg =
- (hidl_request.baseConfigs.securityConfig.securityType != NanDataPathSecurityType::OPEN)
- ? legacy_hal::NAN_DP_CONFIG_SECURITY
- : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
- legacy_request->sdea_params.ranging_state = hidl_request.baseConfigs.rangingRequired
- ? legacy_hal::NAN_RANGING_ENABLE
- : legacy_hal::NAN_RANGING_DISABLE;
- legacy_request->ranging_cfg.ranging_interval_msec =
- hidl_request.baseConfigs.rangingIntervalMsec;
- legacy_request->ranging_cfg.config_ranging_indications =
- hidl_request.baseConfigs.configRangingIndications;
- legacy_request->ranging_cfg.distance_ingress_mm =
- hidl_request.baseConfigs.distanceIngressCm * 10;
- legacy_request->ranging_cfg.distance_egress_mm = hidl_request.baseConfigs.distanceEgressCm * 10;
- legacy_request->ranging_auto_response = hidl_request.baseConfigs.rangingRequired
- ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
- : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
- legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT;
- legacy_request->subscribe_type =
- convertHidlNanSubscribeTypeToLegacy(hidl_request.subscribeType);
- legacy_request->serviceResponseFilter = convertHidlNanSrfTypeToLegacy(hidl_request.srfType);
- legacy_request->serviceResponseInclude = hidl_request.srfRespondIfInAddressSet
- ? legacy_hal::NAN_SRF_INCLUDE_RESPOND
- : legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
- legacy_request->useServiceResponseFilter =
- hidl_request.shouldUseSrf ? legacy_hal::NAN_USE_SRF : legacy_hal::NAN_DO_NOT_USE_SRF;
- legacy_request->ssiRequiredForMatchIndication =
- hidl_request.isSsiRequiredForMatch ? legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND
- : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
- legacy_request->num_intf_addr_present = hidl_request.intfAddr.size();
- if (legacy_request->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) {
- LOG(ERROR) << "convertHidlNanSubscribeRequestToLegacy: "
- "num_intf_addr_present - too many";
- return false;
- }
- for (int i = 0; i < legacy_request->num_intf_addr_present; i++) {
- memcpy(legacy_request->intf_addr[i], hidl_request.intfAddr[i].data(), 6);
- }
-
- return true;
-}
-
-bool convertHidlNanTransmitFollowupRequestToLegacy(
- const NanTransmitFollowupRequest& hidl_request,
- legacy_hal::NanTransmitFollowupRequest* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: "
- "legacy_request is null";
- return false;
- }
- *legacy_request = {};
-
- legacy_request->publish_subscribe_id = hidl_request.discoverySessionId;
- legacy_request->requestor_instance_id = hidl_request.peerId;
- memcpy(legacy_request->addr, hidl_request.addr.data(), 6);
- legacy_request->priority = hidl_request.isHighPriority ? legacy_hal::NAN_TX_PRIORITY_HIGH
- : legacy_hal::NAN_TX_PRIORITY_NORMAL;
- legacy_request->dw_or_faw = hidl_request.shouldUseDiscoveryWindow
- ? legacy_hal::NAN_TRANSMIT_IN_DW
- : legacy_hal::NAN_TRANSMIT_IN_FAW;
- legacy_request->service_specific_info_len = hidl_request.serviceSpecificInfo.size();
- if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: "
- "service_specific_info_len too large";
- return false;
- }
- memcpy(legacy_request->service_specific_info, hidl_request.serviceSpecificInfo.data(),
- legacy_request->service_specific_info_len);
- legacy_request->sdea_service_specific_info_len =
- hidl_request.extendedServiceSpecificInfo.size();
- if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanTransmitFollowupRequestToLegacy: "
- "sdea_service_specific_info_len too large";
- return false;
- }
- memcpy(legacy_request->sdea_service_specific_info,
- hidl_request.extendedServiceSpecificInfo.data(),
- legacy_request->sdea_service_specific_info_len);
- legacy_request->recv_indication_cfg = hidl_request.disableFollowupResultIndication ? 0x1 : 0x0;
-
- return true;
-}
-
-bool convertHidlNanConfigRequestToLegacy(const V1_4::NanConfigRequest& hidl_request,
- legacy_hal::NanConfigRequest* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: legacy_request is null";
- return false;
- }
- *legacy_request = {};
-
- // TODO: b/34059183 tracks missing configurations in legacy HAL or uknown
- // defaults
- legacy_request->master_pref = hidl_request.masterPref;
- legacy_request->discovery_indication_cfg = 0;
- legacy_request->discovery_indication_cfg |=
- hidl_request.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
- legacy_request->discovery_indication_cfg |=
- hidl_request.disableStartedClusterIndication ? 0x2 : 0x0;
- legacy_request->discovery_indication_cfg |=
- hidl_request.disableJoinedClusterIndication ? 0x4 : 0x0;
- legacy_request->config_sid_beacon = 1;
- if (hidl_request.numberOfPublishServiceIdsInBeacon > 127) {
- LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: "
- "numberOfPublishServiceIdsInBeacon > 127";
- return false;
- }
- legacy_request->sid_beacon = (hidl_request.includePublishServiceIdsInBeacon ? 0x1 : 0x0) |
- (hidl_request.numberOfPublishServiceIdsInBeacon << 1);
- legacy_request->config_subscribe_sid_beacon = 1;
- if (hidl_request.numberOfSubscribeServiceIdsInBeacon > 127) {
- LOG(ERROR) << "convertHidlNanConfigRequestToLegacy: "
- "numberOfSubscribeServiceIdsInBeacon > 127";
- return false;
- }
- legacy_request->subscribe_sid_beacon_val =
- (hidl_request.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) |
- (hidl_request.numberOfSubscribeServiceIdsInBeacon << 1);
- legacy_request->config_rssi_window_size = 1;
- legacy_request->rssi_window_size_val = hidl_request.rssiWindowSize;
- legacy_request->config_disc_mac_addr_randomization = 1;
- legacy_request->disc_mac_addr_rand_interval_sec =
- hidl_request.macAddressRandomizationIntervalSec;
- /* TODO : missing
- legacy_request->config_2dot4g_rssi_close = 1;
- legacy_request->rssi_close_2dot4g_val =
- hidl_request.bandSpecificConfig[
- (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiClose;
- legacy_request->config_2dot4g_rssi_middle = 1;
- legacy_request->rssi_middle_2dot4g_val =
- hidl_request.bandSpecificConfig[
- (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiMiddle;
- legacy_request->config_2dot4g_rssi_proximity = 1;
- legacy_request->rssi_proximity_2dot4g_val =
- hidl_request.bandSpecificConfig[
- (size_t) NanBandIndex::NAN_BAND_24GHZ].rssiCloseProximity;
- */
- legacy_request->config_scan_params = 1;
- legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ].dwellTimeMs;
- legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ].scanPeriodSec;
- legacy_request->config_dw.config_2dot4g_dw_band =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
- .validDiscoveryWindowIntervalVal;
- legacy_request->config_dw.dw_2dot4g_interval_val =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
- .discoveryWindowIntervalVal;
- /* TODO: missing
- legacy_request->config_5g_rssi_close = 1;
- legacy_request->rssi_close_5g_val =
- hidl_request.bandSpecificConfig[
- (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiClose;
- legacy_request->config_5g_rssi_middle = 1;
- legacy_request->rssi_middle_5g_val =
- hidl_request.bandSpecificConfig[
- (size_t) NanBandIndex::NAN_BAND_5GHZ].rssiMiddle;
- */
- legacy_request->config_5g_rssi_close_proximity = 1;
- legacy_request->rssi_close_proximity_5g_val =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].rssiCloseProximity;
- legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
- legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
- legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
- legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
- legacy_request->config_dw.config_5g_dw_band =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .validDiscoveryWindowIntervalVal;
- legacy_request->config_dw.dw_5g_interval_val =
- hidl_request.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
- .discoveryWindowIntervalVal;
- /* TODO: b/145609058
- * Missing updates needed to legacy_hal::NanConfigRequest and conversion to
- * it for 6GHz band */
-
- return true;
-}
-
-bool convertHidlNanDataPathInitiatorRequestToLegacy(
- const V1_0::NanInitiateDataPathRequest& hidl_request,
- legacy_hal::NanDataPathInitiatorRequest* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
- "legacy_request is null";
- return false;
- }
- *legacy_request = {};
-
- legacy_request->requestor_instance_id = hidl_request.peerId;
- memcpy(legacy_request->peer_disc_mac_addr, hidl_request.peerDiscMacAddr.data(), 6);
- legacy_request->channel_request_type =
- convertHidlNanDataPathChannelCfgToLegacy(hidl_request.channelRequestType);
- legacy_request->channel = hidl_request.channel;
- if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
- "ifaceName too long";
- return false;
- }
- strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1);
- legacy_request->ndp_cfg.security_cfg =
- (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN)
- ? legacy_hal::NAN_DP_CONFIG_SECURITY
- : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
- legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
- if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
- "ndp_app_info_len too large";
- return false;
- }
- memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
- legacy_request->app_info.ndp_app_info_len);
- legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType;
- if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
- legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
- if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
- "invalid pmk_len";
- return false;
- }
- memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(),
- legacy_request->key_info.body.pmk_info.pmk_len);
- }
- if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
- legacy_request->key_info.body.passphrase_info.passphrase_len =
- hidl_request.securityConfig.passphrase.size();
- if (legacy_request->key_info.body.passphrase_info.passphrase_len <
- NAN_SECURITY_MIN_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
- "passphrase_len too small";
- return false;
- }
- if (legacy_request->key_info.body.passphrase_info.passphrase_len >
- NAN_SECURITY_MAX_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
- "passphrase_len too large";
- return false;
- }
- memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
- hidl_request.securityConfig.passphrase.data(),
- legacy_request->key_info.body.passphrase_info.passphrase_len);
- }
- legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
- if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequestToLegacy: "
- "service_name_len too large";
- return false;
- }
- memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
- legacy_request->service_name_len);
-
- return true;
-}
-
-bool convertHidlNanDataPathInitiatorRequest_1_6ToLegacy(
- const V1_6::NanInitiateDataPathRequest& hidl_request,
- legacy_hal::NanDataPathInitiatorRequest* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: "
- "legacy_request is null";
- return false;
- }
- *legacy_request = {};
-
- legacy_request->requestor_instance_id = hidl_request.peerId;
- memcpy(legacy_request->peer_disc_mac_addr, hidl_request.peerDiscMacAddr.data(), 6);
- legacy_request->channel_request_type =
- convertHidlNanDataPathChannelCfgToLegacy(hidl_request.channelRequestType);
- legacy_request->channel = hidl_request.channel;
- if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: "
- "ifaceName too long";
- return false;
- }
- strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1);
- legacy_request->ndp_cfg.security_cfg =
- (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN)
- ? legacy_hal::NAN_DP_CONFIG_SECURITY
- : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
- legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
- if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: "
- "ndp_app_info_len too large";
- return false;
- }
- memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
- legacy_request->app_info.ndp_app_info_len);
- legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType;
- if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
- legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
- if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: "
- "invalid pmk_len";
- return false;
- }
- memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(),
- legacy_request->key_info.body.pmk_info.pmk_len);
- }
- if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
- legacy_request->key_info.body.passphrase_info.passphrase_len =
- hidl_request.securityConfig.passphrase.size();
- if (legacy_request->key_info.body.passphrase_info.passphrase_len <
- NAN_SECURITY_MIN_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: "
- "passphrase_len too small";
- return false;
- }
- if (legacy_request->key_info.body.passphrase_info.passphrase_len >
- NAN_SECURITY_MAX_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: "
- "passphrase_len too large";
- return false;
- }
- memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
- hidl_request.securityConfig.passphrase.data(),
- legacy_request->key_info.body.passphrase_info.passphrase_len);
- }
- legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
- if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: "
- "service_name_len too large";
- return false;
- }
- memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
- legacy_request->service_name_len);
- legacy_request->scid_len = hidl_request.securityConfig.scid.size();
- if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathInitiatorRequest_1_6ToLegacy: scid_len too large";
- return false;
- }
- memcpy(legacy_request->scid, hidl_request.securityConfig.scid.data(), legacy_request->scid_len);
-
- return true;
-}
-
-bool convertHidlNanDataPathIndicationResponseToLegacy(
- const V1_0::NanRespondToDataPathIndicationRequest& hidl_request,
- legacy_hal::NanDataPathIndicationResponse* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
- "legacy_request is null";
- return false;
- }
- *legacy_request = {};
-
- legacy_request->rsp_code = hidl_request.acceptRequest ? legacy_hal::NAN_DP_REQUEST_ACCEPT
- : legacy_hal::NAN_DP_REQUEST_REJECT;
- legacy_request->ndp_instance_id = hidl_request.ndpInstanceId;
- if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
- "ifaceName too long";
- return false;
- }
- strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1);
- legacy_request->ndp_cfg.security_cfg =
- (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN)
- ? legacy_hal::NAN_DP_CONFIG_SECURITY
- : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
- legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
- if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
- "ndp_app_info_len too large";
- return false;
- }
- memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
- legacy_request->app_info.ndp_app_info_len);
- legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType;
- if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
- legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
- if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
- "invalid pmk_len";
- return false;
- }
- memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(),
- legacy_request->key_info.body.pmk_info.pmk_len);
- }
- if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
- legacy_request->key_info.body.passphrase_info.passphrase_len =
- hidl_request.securityConfig.passphrase.size();
- if (legacy_request->key_info.body.passphrase_info.passphrase_len <
- NAN_SECURITY_MIN_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
- "passphrase_len too small";
- return false;
- }
- if (legacy_request->key_info.body.passphrase_info.passphrase_len >
- NAN_SECURITY_MAX_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
- "passphrase_len too large";
- return false;
- }
- memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
- hidl_request.securityConfig.passphrase.data(),
- legacy_request->key_info.body.passphrase_info.passphrase_len);
- }
- legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
- if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponseToLegacy: "
- "service_name_len too large";
- return false;
- }
- memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
- legacy_request->service_name_len);
-
- return true;
-}
-
-bool convertHidlNanDataPathIndicationResponse_1_6ToLegacy(
- const V1_6::NanRespondToDataPathIndicationRequest& hidl_request,
- legacy_hal::NanDataPathIndicationResponse* legacy_request) {
- if (!legacy_request) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: "
- "legacy_request is null";
- return false;
- }
- *legacy_request = {};
-
- legacy_request->rsp_code = hidl_request.acceptRequest ? legacy_hal::NAN_DP_REQUEST_ACCEPT
- : legacy_hal::NAN_DP_REQUEST_REJECT;
- legacy_request->ndp_instance_id = hidl_request.ndpInstanceId;
- if (strnlen(hidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: "
- "ifaceName too long";
- return false;
- }
- strlcpy(legacy_request->ndp_iface, hidl_request.ifaceName.c_str(), IFNAMSIZ + 1);
- legacy_request->ndp_cfg.security_cfg =
- (hidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN)
- ? legacy_hal::NAN_DP_CONFIG_SECURITY
- : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
- legacy_request->app_info.ndp_app_info_len = hidl_request.appInfo.size();
- if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: "
- "ndp_app_info_len too large";
- return false;
- }
- memcpy(legacy_request->app_info.ndp_app_info, hidl_request.appInfo.data(),
- legacy_request->app_info.ndp_app_info_len);
- legacy_request->cipher_type = (unsigned int)hidl_request.securityConfig.cipherType;
- if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
- legacy_request->key_info.body.pmk_info.pmk_len = hidl_request.securityConfig.pmk.size();
- if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: "
- "invalid pmk_len";
- return false;
- }
- memcpy(legacy_request->key_info.body.pmk_info.pmk, hidl_request.securityConfig.pmk.data(),
- legacy_request->key_info.body.pmk_info.pmk_len);
- }
- if (hidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
- legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
- legacy_request->key_info.body.passphrase_info.passphrase_len =
- hidl_request.securityConfig.passphrase.size();
- if (legacy_request->key_info.body.passphrase_info.passphrase_len <
- NAN_SECURITY_MIN_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: "
- "passphrase_len too small";
- return false;
- }
- if (legacy_request->key_info.body.passphrase_info.passphrase_len >
- NAN_SECURITY_MAX_PASSPHRASE_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: "
- "passphrase_len too large";
- return false;
- }
- memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
- hidl_request.securityConfig.passphrase.data(),
- legacy_request->key_info.body.passphrase_info.passphrase_len);
- }
- legacy_request->service_name_len = hidl_request.serviceNameOutOfBand.size();
- if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: "
- "service_name_len too large";
- return false;
- }
- memcpy(legacy_request->service_name, hidl_request.serviceNameOutOfBand.data(),
- legacy_request->service_name_len);
- legacy_request->scid_len = hidl_request.securityConfig.scid.size();
- if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) {
- LOG(ERROR) << "convertHidlNanDataPathIndicationResponse_1_6ToLegacy: scid_len too large";
- return false;
- }
- memcpy(legacy_request->scid, hidl_request.securityConfig.scid.data(), legacy_request->scid_len);
-
- return true;
-}
-
-bool convertLegacyNanResponseHeaderToHidl(const legacy_hal::NanResponseMsg& legacy_response,
- WifiNanStatus* wifiNanStatus) {
- if (!wifiNanStatus) {
- LOG(ERROR) << "convertLegacyNanResponseHeaderToHidl: wifiNanStatus is null";
- return false;
- }
- *wifiNanStatus = {};
-
- convertToWifiNanStatus(legacy_response.status, legacy_response.nan_error,
- sizeof(legacy_response.nan_error), wifiNanStatus);
- return true;
-}
-
-bool convertLegacyNanCapabilitiesResponseToHidl(const legacy_hal::NanCapabilities& legacy_response,
- V1_6::NanCapabilities* hidl_response) {
- if (!hidl_response) {
- LOG(ERROR) << "convertLegacyNanCapabilitiesResponseToHidl: "
- "hidl_response is null";
- return false;
- }
- *hidl_response = {};
-
- hidl_response->maxConcurrentClusters = legacy_response.max_concurrent_nan_clusters;
- hidl_response->maxPublishes = legacy_response.max_publishes;
- hidl_response->maxSubscribes = legacy_response.max_subscribes;
- hidl_response->maxServiceNameLen = legacy_response.max_service_name_len;
- hidl_response->maxMatchFilterLen = legacy_response.max_match_filter_len;
- hidl_response->maxTotalMatchFilterLen = legacy_response.max_total_match_filter_len;
- hidl_response->maxServiceSpecificInfoLen = legacy_response.max_service_specific_info_len;
- hidl_response->maxExtendedServiceSpecificInfoLen =
- legacy_response.max_sdea_service_specific_info_len;
- hidl_response->maxNdiInterfaces = legacy_response.max_ndi_interfaces;
- hidl_response->maxNdpSessions = legacy_response.max_ndp_sessions;
- hidl_response->maxAppInfoLen = legacy_response.max_app_info_len;
- hidl_response->maxQueuedTransmitFollowupMsgs =
- legacy_response.max_queued_transmit_followup_msgs;
- hidl_response->maxSubscribeInterfaceAddresses = legacy_response.max_subscribe_address;
- hidl_response->supportedCipherSuites = legacy_response.cipher_suites_supported;
- hidl_response->instantCommunicationModeSupportFlag = legacy_response.is_instant_mode_supported;
-
- return true;
-}
-
-bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind,
- V1_6::NanMatchInd* hidl_ind) {
- if (!hidl_ind) {
- LOG(ERROR) << "convertLegacyNanMatchIndToHidl: hidl_ind is null";
- return false;
- }
- *hidl_ind = {};
-
- hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
- hidl_ind->peerId = legacy_ind.requestor_instance_id;
- hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
- hidl_ind->serviceSpecificInfo = std::vector<uint8_t>(
- legacy_ind.service_specific_info,
- legacy_ind.service_specific_info + legacy_ind.service_specific_info_len);
- hidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>(
- legacy_ind.sdea_service_specific_info,
- legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len);
- hidl_ind->matchFilter =
- std::vector<uint8_t>(legacy_ind.sdf_match_filter,
- legacy_ind.sdf_match_filter + legacy_ind.sdf_match_filter_len);
- hidl_ind->matchOccuredInBeaconFlag = legacy_ind.match_occured_flag == 1;
- hidl_ind->outOfResourceFlag = legacy_ind.out_of_resource_flag == 1;
- hidl_ind->rssiValue = legacy_ind.rssi_value;
- hidl_ind->peerCipherType = (V1_6::NanCipherSuiteType)legacy_ind.peer_cipher_type;
- hidl_ind->peerRequiresSecurityEnabledInNdp =
- legacy_ind.peer_sdea_params.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
- hidl_ind->peerRequiresRanging =
- legacy_ind.peer_sdea_params.ranging_state == legacy_hal::NAN_RANGING_ENABLE;
- hidl_ind->rangingMeasurementInMm = legacy_ind.range_info.range_measurement_mm;
- hidl_ind->rangingIndicationType = legacy_ind.range_info.ranging_event_type;
- hidl_ind->scid = std::vector<uint8_t>(legacy_ind.scid, legacy_ind.scid + legacy_ind.scid_len);
- return true;
-}
-
-bool convertLegacyNanFollowupIndToHidl(const legacy_hal::NanFollowupInd& legacy_ind,
- NanFollowupReceivedInd* hidl_ind) {
- if (!hidl_ind) {
- LOG(ERROR) << "convertLegacyNanFollowupIndToHidl: hidl_ind is null";
- return false;
- }
- *hidl_ind = {};
-
- hidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
- hidl_ind->peerId = legacy_ind.requestor_instance_id;
- hidl_ind->addr = hidl_array<uint8_t, 6>(legacy_ind.addr);
- hidl_ind->receivedInFaw = legacy_ind.dw_or_faw == 1;
- hidl_ind->serviceSpecificInfo = std::vector<uint8_t>(
- legacy_ind.service_specific_info,
- legacy_ind.service_specific_info + legacy_ind.service_specific_info_len);
- hidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>(
- legacy_ind.sdea_service_specific_info,
- legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len);
-
- return true;
-}
-
-bool convertLegacyNanDataPathRequestIndToHidl(const legacy_hal::NanDataPathRequestInd& legacy_ind,
- NanDataPathRequestInd* hidl_ind) {
- if (!hidl_ind) {
- LOG(ERROR) << "convertLegacyNanDataPathRequestIndToHidl: hidl_ind is null";
- return false;
- }
- *hidl_ind = {};
-
- hidl_ind->discoverySessionId = legacy_ind.service_instance_id;
- hidl_ind->peerDiscMacAddr = hidl_array<uint8_t, 6>(legacy_ind.peer_disc_mac_addr);
- hidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
- hidl_ind->securityRequired =
- legacy_ind.ndp_cfg.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
- hidl_ind->appInfo = std::vector<uint8_t>(
- legacy_ind.app_info.ndp_app_info,
- legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len);
-
- return true;
-}
-
-bool convertLegacyNdpChannelInfoToHidl(const legacy_hal::NanChannelInfo& legacy_struct,
- V1_6::NanDataPathChannelInfo* hidl_struct) {
- if (!hidl_struct) {
- LOG(ERROR) << "convertLegacyNdpChannelInfoToHidl: hidl_struct is null";
- return false;
- }
- *hidl_struct = {};
-
- hidl_struct->channelFreq = legacy_struct.channel;
- hidl_struct->channelBandwidth = convertLegacyWifiChannelWidthToHidl(
- (legacy_hal::wifi_channel_width)legacy_struct.bandwidth);
- hidl_struct->numSpatialStreams = legacy_struct.nss;
-
- return true;
-}
-
-bool convertLegacyNanDataPathConfirmIndToHidl(const legacy_hal::NanDataPathConfirmInd& legacy_ind,
- V1_6::NanDataPathConfirmInd* hidl_ind) {
- if (!hidl_ind) {
- LOG(ERROR) << "convertLegacyNanDataPathConfirmIndToHidl: hidl_ind is null";
- return false;
- }
- *hidl_ind = {};
-
- hidl_ind->V1_0.ndpInstanceId = legacy_ind.ndp_instance_id;
- hidl_ind->V1_0.dataPathSetupSuccess = legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT;
- hidl_ind->V1_0.peerNdiMacAddr = hidl_array<uint8_t, 6>(legacy_ind.peer_ndi_mac_addr);
- hidl_ind->V1_0.appInfo = std::vector<uint8_t>(
- legacy_ind.app_info.ndp_app_info,
- legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len);
- hidl_ind->V1_0.status.status = convertLegacyNanStatusTypeToHidl(legacy_ind.reason_code);
- hidl_ind->V1_0.status.description = ""; // TODO: b/34059183
-
- std::vector<V1_6::NanDataPathChannelInfo> channelInfo;
- for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
- V1_6::NanDataPathChannelInfo hidl_struct;
- if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) {
- return false;
- }
- channelInfo.push_back(hidl_struct);
- }
- hidl_ind->channelInfo = channelInfo;
-
- return true;
-}
-
-bool convertLegacyNanDataPathScheduleUpdateIndToHidl(
- const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
- V1_6::NanDataPathScheduleUpdateInd* hidl_ind) {
- if (!hidl_ind) {
- LOG(ERROR) << "convertLegacyNanDataPathScheduleUpdateIndToHidl: "
- "hidl_ind is null";
- return false;
- }
- *hidl_ind = {};
-
- hidl_ind->peerDiscoveryAddress = hidl_array<uint8_t, 6>(legacy_ind.peer_mac_addr);
- std::vector<V1_6::NanDataPathChannelInfo> channelInfo;
- for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
- V1_6::NanDataPathChannelInfo hidl_struct;
- if (!convertLegacyNdpChannelInfoToHidl(legacy_ind.channel_info[i], &hidl_struct)) {
- return false;
- }
- channelInfo.push_back(hidl_struct);
- }
- hidl_ind->channelInfo = channelInfo;
- std::vector<uint32_t> ndpInstanceIds;
- for (unsigned int i = 0; i < legacy_ind.num_ndp_instances; ++i) {
- ndpInstanceIds.push_back(legacy_ind.ndp_instance_id[i]);
- }
- hidl_ind->ndpInstanceIds = ndpInstanceIds;
-
- return true;
-}
-
-legacy_hal::wifi_rtt_type convertHidlRttTypeToLegacy(RttType type) {
- switch (type) {
- case RttType::ONE_SIDED:
- return legacy_hal::RTT_TYPE_1_SIDED;
- case RttType::TWO_SIDED:
- return legacy_hal::RTT_TYPE_2_SIDED;
- };
- CHECK(false);
-}
-
-RttType convertLegacyRttTypeToHidl(legacy_hal::wifi_rtt_type type) {
- switch (type) {
- case legacy_hal::RTT_TYPE_1_SIDED:
- return RttType::ONE_SIDED;
- case legacy_hal::RTT_TYPE_2_SIDED:
- return RttType::TWO_SIDED;
- };
- CHECK(false) << "Unknown legacy type: " << type;
-}
-
-legacy_hal::rtt_peer_type convertHidlRttPeerTypeToLegacy(RttPeerType type) {
- switch (type) {
- case RttPeerType::AP:
- return legacy_hal::RTT_PEER_AP;
- case RttPeerType::STA:
- return legacy_hal::RTT_PEER_STA;
- case RttPeerType::P2P_GO:
- return legacy_hal::RTT_PEER_P2P_GO;
- case RttPeerType::P2P_CLIENT:
- return legacy_hal::RTT_PEER_P2P_CLIENT;
- case RttPeerType::NAN:
- return legacy_hal::RTT_PEER_NAN;
- };
- CHECK(false);
-}
-
-legacy_hal::wifi_channel_width convertHidlWifiChannelWidthToLegacy(WifiChannelWidthInMhz type) {
- switch (type) {
- case WifiChannelWidthInMhz::WIDTH_20:
- return legacy_hal::WIFI_CHAN_WIDTH_20;
- case WifiChannelWidthInMhz::WIDTH_40:
- return legacy_hal::WIFI_CHAN_WIDTH_40;
- case WifiChannelWidthInMhz::WIDTH_80:
- return legacy_hal::WIFI_CHAN_WIDTH_80;
- case WifiChannelWidthInMhz::WIDTH_160:
- return legacy_hal::WIFI_CHAN_WIDTH_160;
- case WifiChannelWidthInMhz::WIDTH_80P80:
- return legacy_hal::WIFI_CHAN_WIDTH_80P80;
- case WifiChannelWidthInMhz::WIDTH_5:
- return legacy_hal::WIFI_CHAN_WIDTH_5;
- case WifiChannelWidthInMhz::WIDTH_10:
- return legacy_hal::WIFI_CHAN_WIDTH_10;
- case V1_6::WifiChannelWidthInMhz::WIDTH_320:
- return legacy_hal::WIFI_CHAN_WIDTH_320;
- case WifiChannelWidthInMhz::WIDTH_INVALID:
- return legacy_hal::WIFI_CHAN_WIDTH_INVALID;
- };
- CHECK(false);
-}
-
-V1_6::WifiChannelWidthInMhz convertLegacyWifiChannelWidthToHidl(
- legacy_hal::wifi_channel_width type) {
- switch (type) {
- case legacy_hal::WIFI_CHAN_WIDTH_20:
- return WifiChannelWidthInMhz::WIDTH_20;
- case legacy_hal::WIFI_CHAN_WIDTH_40:
- return WifiChannelWidthInMhz::WIDTH_40;
- case legacy_hal::WIFI_CHAN_WIDTH_80:
- return WifiChannelWidthInMhz::WIDTH_80;
- case legacy_hal::WIFI_CHAN_WIDTH_160:
- return WifiChannelWidthInMhz::WIDTH_160;
- case legacy_hal::WIFI_CHAN_WIDTH_80P80:
- return WifiChannelWidthInMhz::WIDTH_80P80;
- case legacy_hal::WIFI_CHAN_WIDTH_5:
- return WifiChannelWidthInMhz::WIDTH_5;
- case legacy_hal::WIFI_CHAN_WIDTH_10:
- return WifiChannelWidthInMhz::WIDTH_10;
- case legacy_hal::WIFI_CHAN_WIDTH_320:
- return V1_6::WifiChannelWidthInMhz::WIDTH_320;
- default:
- return WifiChannelWidthInMhz::WIDTH_INVALID;
- };
-}
-
-legacy_hal::wifi_rtt_preamble convertHidlRttPreambleToLegacy(V1_6::RttPreamble type) {
- switch (type) {
- case V1_6::RttPreamble::LEGACY:
- return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY;
- case V1_6::RttPreamble::HT:
- return legacy_hal::WIFI_RTT_PREAMBLE_HT;
- case V1_6::RttPreamble::VHT:
- return legacy_hal::WIFI_RTT_PREAMBLE_VHT;
- case V1_6::RttPreamble::HE:
- return legacy_hal::WIFI_RTT_PREAMBLE_HE;
- case V1_6::RttPreamble::EHT:
- return legacy_hal::WIFI_RTT_PREAMBLE_EHT;
- };
- CHECK(false);
-}
-
-V1_6::RttPreamble convertLegacyRttPreambleToHidl(legacy_hal::wifi_rtt_preamble type) {
- switch (type) {
- case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY:
- return V1_6::RttPreamble::LEGACY;
- case legacy_hal::WIFI_RTT_PREAMBLE_HT:
- return V1_6::RttPreamble::HT;
- case legacy_hal::WIFI_RTT_PREAMBLE_VHT:
- return V1_6::RttPreamble::VHT;
- case legacy_hal::WIFI_RTT_PREAMBLE_HE:
- return V1_6::RttPreamble::HE;
- case legacy_hal::WIFI_RTT_PREAMBLE_EHT:
- return V1_6::RttPreamble::EHT;
- };
- CHECK(false) << "Unknown legacy type: " << type;
-}
-
-legacy_hal::wifi_rtt_bw convertHidlRttBwToLegacy(RttBw type) {
- switch (type) {
- case RttBw::BW_5MHZ:
- return legacy_hal::WIFI_RTT_BW_5;
- case RttBw::BW_10MHZ:
- return legacy_hal::WIFI_RTT_BW_10;
- case RttBw::BW_20MHZ:
- return legacy_hal::WIFI_RTT_BW_20;
- case RttBw::BW_40MHZ:
- return legacy_hal::WIFI_RTT_BW_40;
- case RttBw::BW_80MHZ:
- return legacy_hal::WIFI_RTT_BW_80;
- case RttBw::BW_160MHZ:
- return legacy_hal::WIFI_RTT_BW_160;
- case RttBw::BW_320MHZ:
- return legacy_hal::WIFI_RTT_BW_320;
- };
- CHECK(false);
-}
-
-RttBw convertLegacyRttBwToHidl(legacy_hal::wifi_rtt_bw type) {
- switch (type) {
- case legacy_hal::WIFI_RTT_BW_5:
- return RttBw::BW_5MHZ;
- case legacy_hal::WIFI_RTT_BW_10:
- return RttBw::BW_10MHZ;
- case legacy_hal::WIFI_RTT_BW_20:
- return RttBw::BW_20MHZ;
- case legacy_hal::WIFI_RTT_BW_40:
- return RttBw::BW_40MHZ;
- case legacy_hal::WIFI_RTT_BW_80:
- return RttBw::BW_80MHZ;
- case legacy_hal::WIFI_RTT_BW_160:
- return RttBw::BW_160MHZ;
- case legacy_hal::WIFI_RTT_BW_320:
- return RttBw::BW_320MHZ;
- };
- CHECK(false) << "Unknown legacy type: " << type;
-}
-
-legacy_hal::wifi_motion_pattern convertHidlRttMotionPatternToLegacy(RttMotionPattern type) {
- switch (type) {
- case RttMotionPattern::NOT_EXPECTED:
- return legacy_hal::WIFI_MOTION_NOT_EXPECTED;
- case RttMotionPattern::EXPECTED:
- return legacy_hal::WIFI_MOTION_EXPECTED;
- case RttMotionPattern::UNKNOWN:
- return legacy_hal::WIFI_MOTION_UNKNOWN;
- };
- CHECK(false);
-}
-
-V1_6::WifiRatePreamble convertLegacyWifiRatePreambleToHidl(uint8_t preamble) {
- switch (preamble) {
- case 0:
- return V1_6::WifiRatePreamble::OFDM;
- case 1:
- return V1_6::WifiRatePreamble::CCK;
- case 2:
- return V1_6::WifiRatePreamble::HT;
- case 3:
- return V1_6::WifiRatePreamble::VHT;
- case 4:
- return V1_6::WifiRatePreamble::HE;
- case 5:
- return V1_6::WifiRatePreamble::EHT;
- default:
- return V1_6::WifiRatePreamble::RESERVED;
- };
- CHECK(false) << "Unknown legacy preamble: " << preamble;
-}
-
-WifiRateNss convertLegacyWifiRateNssToHidl(uint8_t nss) {
- switch (nss) {
- case 0:
- return WifiRateNss::NSS_1x1;
- case 1:
- return WifiRateNss::NSS_2x2;
- case 2:
- return WifiRateNss::NSS_3x3;
- case 3:
- return WifiRateNss::NSS_4x4;
- };
- CHECK(false) << "Unknown legacy nss: " << nss;
- return {};
-}
-
-RttStatus convertLegacyRttStatusToHidl(legacy_hal::wifi_rtt_status status) {
- switch (status) {
- case legacy_hal::RTT_STATUS_SUCCESS:
- return RttStatus::SUCCESS;
- case legacy_hal::RTT_STATUS_FAILURE:
- return RttStatus::FAILURE;
- case legacy_hal::RTT_STATUS_FAIL_NO_RSP:
- return RttStatus::FAIL_NO_RSP;
- case legacy_hal::RTT_STATUS_FAIL_REJECTED:
- return RttStatus::FAIL_REJECTED;
- case legacy_hal::RTT_STATUS_FAIL_NOT_SCHEDULED_YET:
- return RttStatus::FAIL_NOT_SCHEDULED_YET;
- case legacy_hal::RTT_STATUS_FAIL_TM_TIMEOUT:
- return RttStatus::FAIL_TM_TIMEOUT;
- case legacy_hal::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL:
- return RttStatus::FAIL_AP_ON_DIFF_CHANNEL;
- case legacy_hal::RTT_STATUS_FAIL_NO_CAPABILITY:
- return RttStatus::FAIL_NO_CAPABILITY;
- case legacy_hal::RTT_STATUS_ABORTED:
- return RttStatus::ABORTED;
- case legacy_hal::RTT_STATUS_FAIL_INVALID_TS:
- return RttStatus::FAIL_INVALID_TS;
- case legacy_hal::RTT_STATUS_FAIL_PROTOCOL:
- return RttStatus::FAIL_PROTOCOL;
- case legacy_hal::RTT_STATUS_FAIL_SCHEDULE:
- return RttStatus::FAIL_SCHEDULE;
- case legacy_hal::RTT_STATUS_FAIL_BUSY_TRY_LATER:
- return RttStatus::FAIL_BUSY_TRY_LATER;
- case legacy_hal::RTT_STATUS_INVALID_REQ:
- return RttStatus::INVALID_REQ;
- case legacy_hal::RTT_STATUS_NO_WIFI:
- return RttStatus::NO_WIFI;
- case legacy_hal::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE:
- return RttStatus::FAIL_FTM_PARAM_OVERRIDE;
- case legacy_hal::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE:
- return RttStatus::FAILURE; // TODO: add HIDL enumeration
- case legacy_hal::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED:
- return RttStatus::FAILURE; // TODO: add HIDL enumeration
- };
- CHECK(false) << "Unknown legacy status: " << status;
-}
-
-bool convertHidlWifiChannelInfoToLegacy(const WifiChannelInfo& hidl_info,
- legacy_hal::wifi_channel_info* legacy_info) {
- if (!legacy_info) {
- return false;
- }
- *legacy_info = {};
- legacy_info->width = convertHidlWifiChannelWidthToLegacy(hidl_info.width);
- legacy_info->center_freq = hidl_info.centerFreq;
- legacy_info->center_freq0 = hidl_info.centerFreq0;
- legacy_info->center_freq1 = hidl_info.centerFreq1;
- return true;
-}
-
-bool convertLegacyWifiChannelInfoToHidl(const legacy_hal::wifi_channel_info& legacy_info,
- WifiChannelInfo* hidl_info) {
- if (!hidl_info) {
- return false;
- }
- *hidl_info = {};
- hidl_info->width = convertLegacyWifiChannelWidthToHidl(legacy_info.width);
- hidl_info->centerFreq = legacy_info.center_freq;
- hidl_info->centerFreq0 = legacy_info.center_freq0;
- hidl_info->centerFreq1 = legacy_info.center_freq1;
- return true;
-}
-
-bool convertHidlRttConfigToLegacy(const V1_6::RttConfig& hidl_config,
- legacy_hal::wifi_rtt_config* legacy_config) {
- if (!legacy_config) {
- return false;
- }
- *legacy_config = {};
- CHECK(hidl_config.addr.size() == sizeof(legacy_config->addr));
- memcpy(legacy_config->addr, hidl_config.addr.data(), hidl_config.addr.size());
- legacy_config->type = convertHidlRttTypeToLegacy(hidl_config.type);
- legacy_config->peer = convertHidlRttPeerTypeToLegacy(hidl_config.peer);
- if (!convertHidlWifiChannelInfoToLegacy(hidl_config.channel, &legacy_config->channel)) {
- return false;
- }
- legacy_config->burst_period = hidl_config.burstPeriod;
- legacy_config->num_burst = hidl_config.numBurst;
- legacy_config->num_frames_per_burst = hidl_config.numFramesPerBurst;
- legacy_config->num_retries_per_rtt_frame = hidl_config.numRetriesPerRttFrame;
- legacy_config->num_retries_per_ftmr = hidl_config.numRetriesPerFtmr;
- legacy_config->LCI_request = hidl_config.mustRequestLci;
- legacy_config->LCR_request = hidl_config.mustRequestLcr;
- legacy_config->burst_duration = hidl_config.burstDuration;
- legacy_config->preamble = convertHidlRttPreambleToLegacy(hidl_config.preamble);
- legacy_config->bw = convertHidlRttBwToLegacy(hidl_config.bw);
- return true;
-}
-
-bool convertHidlVectorOfRttConfigToLegacy(
- const std::vector<V1_6::RttConfig>& hidl_configs,
- std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
- if (!legacy_configs) {
- return false;
- }
- *legacy_configs = {};
- for (const auto& hidl_config : hidl_configs) {
- legacy_hal::wifi_rtt_config legacy_config;
- if (!convertHidlRttConfigToLegacy(hidl_config, &legacy_config)) {
- return false;
- }
- legacy_configs->push_back(legacy_config);
- }
- return true;
-}
-
-bool convertHidlRttLciInformationToLegacy(const RttLciInformation& hidl_info,
- legacy_hal::wifi_lci_information* legacy_info) {
- if (!legacy_info) {
- return false;
- }
- *legacy_info = {};
- legacy_info->latitude = hidl_info.latitude;
- legacy_info->longitude = hidl_info.longitude;
- legacy_info->altitude = hidl_info.altitude;
- legacy_info->latitude_unc = hidl_info.latitudeUnc;
- legacy_info->longitude_unc = hidl_info.longitudeUnc;
- legacy_info->altitude_unc = hidl_info.altitudeUnc;
- legacy_info->motion_pattern = convertHidlRttMotionPatternToLegacy(hidl_info.motionPattern);
- legacy_info->floor = hidl_info.floor;
- legacy_info->height_above_floor = hidl_info.heightAboveFloor;
- legacy_info->height_unc = hidl_info.heightUnc;
- return true;
-}
-
-bool convertHidlRttLcrInformationToLegacy(const RttLcrInformation& hidl_info,
- legacy_hal::wifi_lcr_information* legacy_info) {
- if (!legacy_info) {
- return false;
- }
- *legacy_info = {};
- CHECK(hidl_info.countryCode.size() == sizeof(legacy_info->country_code));
- memcpy(legacy_info->country_code, hidl_info.countryCode.data(), hidl_info.countryCode.size());
- if (hidl_info.civicInfo.size() > sizeof(legacy_info->civic_info)) {
- return false;
- }
- legacy_info->length = hidl_info.civicInfo.size();
- memcpy(legacy_info->civic_info, hidl_info.civicInfo.c_str(), hidl_info.civicInfo.size());
- return true;
-}
-
-bool convertHidlRttResponderToLegacy(const V1_6::RttResponder& hidl_responder,
- legacy_hal::wifi_rtt_responder* legacy_responder) {
- if (!legacy_responder) {
- return false;
- }
- *legacy_responder = {};
- if (!convertHidlWifiChannelInfoToLegacy(hidl_responder.channel, &legacy_responder->channel)) {
- return false;
- }
- legacy_responder->preamble = convertHidlRttPreambleToLegacy(hidl_responder.preamble);
- return true;
-}
-
-bool convertLegacyRttResponderToHidl(const legacy_hal::wifi_rtt_responder& legacy_responder,
- V1_6::RttResponder* hidl_responder) {
- if (!hidl_responder) {
- return false;
- }
- *hidl_responder = {};
- if (!convertLegacyWifiChannelInfoToHidl(legacy_responder.channel, &hidl_responder->channel)) {
- return false;
- }
- hidl_responder->preamble = convertLegacyRttPreambleToHidl(legacy_responder.preamble);
- return true;
-}
-
-bool convertLegacyRttCapabilitiesToHidl(
- const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
- V1_6::RttCapabilities* hidl_capabilities) {
- if (!hidl_capabilities) {
- return false;
- }
- *hidl_capabilities = {};
- hidl_capabilities->rttOneSidedSupported = legacy_capabilities.rtt_one_sided_supported;
- hidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported;
- hidl_capabilities->lciSupported = legacy_capabilities.lci_support;
- hidl_capabilities->lcrSupported = legacy_capabilities.lcr_support;
- hidl_capabilities->responderSupported = legacy_capabilities.responder_supported;
- hidl_capabilities->preambleSupport = 0;
- for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY, legacy_hal::WIFI_RTT_PREAMBLE_HT,
- legacy_hal::WIFI_RTT_PREAMBLE_VHT, legacy_hal::WIFI_RTT_PREAMBLE_HE,
- legacy_hal::WIFI_RTT_PREAMBLE_EHT}) {
- if (legacy_capabilities.preamble_support & flag) {
- hidl_capabilities->preambleSupport |=
- static_cast<std::underlying_type<V1_6::RttPreamble>::type>(
- convertLegacyRttPreambleToHidl(flag));
- }
- }
- hidl_capabilities->bwSupport = 0;
- for (const auto flag :
- {legacy_hal::WIFI_RTT_BW_5, legacy_hal::WIFI_RTT_BW_10, legacy_hal::WIFI_RTT_BW_20,
- legacy_hal::WIFI_RTT_BW_40, legacy_hal::WIFI_RTT_BW_80, legacy_hal::WIFI_RTT_BW_160,
- legacy_hal::WIFI_RTT_BW_320}) {
- if (legacy_capabilities.bw_support & flag) {
- hidl_capabilities->bwSupport |=
- static_cast<std::underlying_type<RttBw>::type>(convertLegacyRttBwToHidl(flag));
- }
- }
- hidl_capabilities->mcVersion = legacy_capabilities.mc_version;
- return true;
-}
-
-bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate,
- V1_6::WifiRateInfo* hidl_rate) {
- if (!hidl_rate) {
- return false;
- }
- *hidl_rate = {};
- hidl_rate->preamble = convertLegacyWifiRatePreambleToHidl(legacy_rate.preamble);
- hidl_rate->nss = convertLegacyWifiRateNssToHidl(legacy_rate.nss);
- hidl_rate->bw = convertLegacyWifiChannelWidthToHidl(
- static_cast<legacy_hal::wifi_channel_width>(legacy_rate.bw));
- hidl_rate->rateMcsIdx = legacy_rate.rateMcsIdx;
- hidl_rate->bitRateInKbps = legacy_rate.bitrate;
- return true;
-}
-
-bool convertLegacyRttResultToHidl(const legacy_hal::wifi_rtt_result& legacy_result,
- V1_6::RttResult* hidl_result) {
- if (!hidl_result) {
- return false;
- }
- *hidl_result = {};
- CHECK(sizeof(legacy_result.addr) == hidl_result->addr.size());
- memcpy(hidl_result->addr.data(), legacy_result.addr, sizeof(legacy_result.addr));
- hidl_result->burstNum = legacy_result.burst_num;
- hidl_result->measurementNumber = legacy_result.measurement_number;
- hidl_result->successNumber = legacy_result.success_number;
- hidl_result->numberPerBurstPeer = legacy_result.number_per_burst_peer;
- hidl_result->status = convertLegacyRttStatusToHidl(legacy_result.status);
- hidl_result->retryAfterDuration = legacy_result.retry_after_duration;
- hidl_result->type = convertLegacyRttTypeToHidl(legacy_result.type);
- hidl_result->rssi = legacy_result.rssi;
- hidl_result->rssiSpread = legacy_result.rssi_spread;
- if (!convertLegacyWifiRateInfoToHidl(legacy_result.tx_rate, &hidl_result->txRate)) {
- return false;
- }
- if (!convertLegacyWifiRateInfoToHidl(legacy_result.rx_rate, &hidl_result->rxRate)) {
- return false;
- }
- hidl_result->rtt = legacy_result.rtt;
- hidl_result->rttSd = legacy_result.rtt_sd;
- hidl_result->rttSpread = legacy_result.rtt_spread;
- hidl_result->distanceInMm = legacy_result.distance_mm;
- hidl_result->distanceSdInMm = legacy_result.distance_sd_mm;
- hidl_result->distanceSpreadInMm = legacy_result.distance_spread_mm;
- hidl_result->timeStampInUs = legacy_result.ts;
- hidl_result->burstDurationInMs = legacy_result.burst_duration;
- hidl_result->negotiatedBurstNum = legacy_result.negotiated_burst_num;
- if (legacy_result.LCI && !convertLegacyIeToHidl(*legacy_result.LCI, &hidl_result->lci)) {
- return false;
- }
- if (legacy_result.LCR && !convertLegacyIeToHidl(*legacy_result.LCR, &hidl_result->lcr)) {
- return false;
- }
- return true;
-}
-
-bool convertLegacyVectorOfRttResultToHidl(
- const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
- std::vector<V1_6::RttResult>* hidl_results) {
- if (!hidl_results) {
- return false;
- }
- *hidl_results = {};
- for (const auto legacy_result : legacy_results) {
- V1_6::RttResult hidl_result;
- if (!convertLegacyRttResultToHidl(*legacy_result, &hidl_result)) {
- return false;
- }
- hidl_results->push_back(hidl_result);
- }
- return true;
-}
-
-legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(IfaceType hidl_interface_type) {
- switch (hidl_interface_type) {
- case IfaceType::STA:
- return legacy_hal::WIFI_INTERFACE_TYPE_STA;
- case IfaceType::AP:
- return legacy_hal::WIFI_INTERFACE_TYPE_AP;
- case IfaceType::P2P:
- return legacy_hal::WIFI_INTERFACE_TYPE_P2P;
- case IfaceType::NAN:
- return legacy_hal::WIFI_INTERFACE_TYPE_NAN;
- }
- CHECK(false);
-}
-
-legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy(
- V1_5::IWifiChip::MultiStaUseCase use_case) {
- switch (use_case) {
- case V1_5::IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY:
- return legacy_hal::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY;
- case V1_5::IWifiChip::MultiStaUseCase::DUAL_STA_NON_TRANSIENT_UNBIASED:
- return legacy_hal::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED;
- }
- CHECK(false);
-}
-
-bool convertHidlCoexUnsafeChannelToLegacy(
- const V1_5::IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel,
- legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel) {
- if (!legacy_unsafe_channel) {
- return false;
- }
- *legacy_unsafe_channel = {};
- switch (hidl_unsafe_channel.band) {
- case V1_5::WifiBand::BAND_24GHZ:
- legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_2_4_BAND;
- break;
- case V1_5::WifiBand::BAND_5GHZ:
- legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_5_0_BAND;
- break;
- default:
- return false;
- };
- legacy_unsafe_channel->channel = hidl_unsafe_channel.channel;
- legacy_unsafe_channel->power_cap_dbm = hidl_unsafe_channel.powerCapDbm;
- return true;
-}
-
-bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
- const std::vector<V1_5::IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
- std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels) {
- if (!legacy_unsafe_channels) {
- return false;
- }
- *legacy_unsafe_channels = {};
- for (const auto& hidl_unsafe_channel : hidl_unsafe_channels) {
- legacy_hal::wifi_coex_unsafe_channel legacy_unsafe_channel;
- if (!hidl_struct_util::convertHidlCoexUnsafeChannelToLegacy(hidl_unsafe_channel,
- &legacy_unsafe_channel)) {
- return false;
- }
- legacy_unsafe_channels->push_back(legacy_unsafe_channel);
- }
- return true;
-}
-
-V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg) {
- switch (antenna_cfg) {
- case legacy_hal::WIFI_ANTENNA_1X1:
- return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_1X1;
- case legacy_hal::WIFI_ANTENNA_2X2:
- return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_2X2;
- case legacy_hal::WIFI_ANTENNA_3X3:
- return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_3X3;
- case legacy_hal::WIFI_ANTENNA_4X4:
- return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_4X4;
- default:
- return V1_6::WifiAntennaMode::WIFI_ANTENNA_MODE_UNSPECIFIED;
- }
-}
-
-bool convertLegacyWifiRadioConfigurationToHidl(
- legacy_hal::wifi_radio_configuration* radio_configuration,
- V1_6::WifiRadioConfiguration* hidl_radio_configuration) {
- if (!hidl_radio_configuration) {
- return false;
- }
- *hidl_radio_configuration = {};
- hidl_radio_configuration->bandInfo =
- hidl_struct_util::convertLegacyMacBandToHidlWifiBand(radio_configuration->band);
- if (hidl_radio_configuration->bandInfo == V1_5::WifiBand::BAND_UNSPECIFIED) {
- LOG(ERROR) << "Unspecified band";
- return false;
- }
- hidl_radio_configuration->antennaMode =
- hidl_struct_util::convertLegacyAntennaConfigurationToHidl(
- radio_configuration->antenna_cfg);
- return true;
-}
-
-bool convertLegacyRadioCombinationsMatrixToHidl(
- legacy_hal::wifi_radio_combination_matrix* legacy_matrix,
- WifiRadioCombinationMatrix* hidl_matrix) {
- if (!hidl_matrix || !legacy_matrix) {
- return false;
- }
- *hidl_matrix = {};
-
- int num_combinations = legacy_matrix->num_radio_combinations;
- std::vector<V1_6::WifiRadioCombination> radio_combinations_vec;
- if (!num_combinations) {
- LOG(ERROR) << "zero radio combinations";
- return false;
- }
- wifi_radio_combination* l_radio_combinations_ptr = legacy_matrix->radio_combinations;
- for (int i = 0; i < num_combinations; i++) {
- int num_configurations = l_radio_combinations_ptr->num_radio_configurations;
- WifiRadioCombination radioCombination;
- std::vector<V1_6::WifiRadioConfiguration> radio_configurations_vec;
- if (!num_configurations) {
- LOG(ERROR) << "zero radio configurations";
- return false;
- }
- for (int j = 0; j < num_configurations; j++) {
- WifiRadioConfiguration radioConfiguration;
- wifi_radio_configuration* l_radio_configurations_ptr =
- &l_radio_combinations_ptr->radio_configurations[j];
- if (!hidl_struct_util::convertLegacyWifiRadioConfigurationToHidl(
- l_radio_configurations_ptr, &radioConfiguration)) {
- LOG(ERROR) << "Error converting wifi radio configuration";
- return false;
- }
- radio_configurations_vec.push_back(radioConfiguration);
- }
- radioCombination.radioConfigurations = radio_configurations_vec;
- radio_combinations_vec.push_back(radioCombination);
- l_radio_combinations_ptr =
- (wifi_radio_combination*)((u8*)l_radio_combinations_ptr +
- sizeof(wifi_radio_combination) +
- (sizeof(wifi_radio_configuration) * num_configurations));
- }
- hidl_matrix->radioCombinations = radio_combinations_vec;
- return true;
-}
-
-} // namespace hidl_struct_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/hidl_struct_util.h b/wifi/1.6/default/hidl_struct_util.h
deleted file mode 100644
index 2d4a5f1..0000000
--- a/wifi/1.6/default/hidl_struct_util.h
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HIDL_STRUCT_UTIL_H_
-#define HIDL_STRUCT_UTIL_H_
-
-#include <vector>
-
-#include <android/hardware/wifi/1.0/IWifiChip.h>
-#include <android/hardware/wifi/1.0/types.h>
-#include <android/hardware/wifi/1.2/types.h>
-#include <android/hardware/wifi/1.3/types.h>
-#include <android/hardware/wifi/1.4/IWifiChipEventCallback.h>
-#include <android/hardware/wifi/1.4/types.h>
-#include <android/hardware/wifi/1.6/IWifiChip.h>
-#include <android/hardware/wifi/1.6/types.h>
-
-#include "wifi_legacy_hal.h"
-
-/**
- * This file contains a bunch of functions to convert structs from the legacy
- * HAL to HIDL and vice versa.
- * TODO(b/32093047): Add unit tests for these conversion methods in the VTS test
- * suite.
- */
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace hidl_struct_util {
-using namespace android::hardware::wifi::V1_0;
-
-// Chip conversion methods.
-bool convertLegacyFeaturesToHidlChipCapabilities(uint64_t legacy_feature_set,
- uint32_t legacy_logger_feature_set,
- uint32_t* hidl_caps);
-bool convertLegacyDebugRingBufferStatusToHidl(
- const legacy_hal::wifi_ring_buffer_status& legacy_status,
- WifiDebugRingBufferStatus* hidl_status);
-bool convertLegacyVectorOfDebugRingBufferStatusToHidl(
- const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
- std::vector<WifiDebugRingBufferStatus>* hidl_status_vec);
-bool convertLegacyWakeReasonStatsToHidl(const legacy_hal::WakeReasonStats& legacy_stats,
- WifiDebugHostWakeReasonStats* hidl_stats);
-legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy(
- V1_1::IWifiChip::TxPowerScenario hidl_scenario);
-legacy_hal::wifi_latency_mode convertHidlLatencyModeToLegacy(
- V1_3::IWifiChip::LatencyMode hidl_latency_mode);
-legacy_hal::wifi_power_scenario convertHidlTxPowerScenarioToLegacy_1_2(
- V1_2::IWifiChip::TxPowerScenario hidl_scenario);
-bool convertLegacyWifiMacInfosToHidl(
- const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
- std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo>* hidl_radio_mode_infos);
-legacy_hal::wifi_interface_type convertHidlIfaceTypeToLegacy(IfaceType hidl_interface_type);
-legacy_hal::wifi_multi_sta_use_case convertHidlMultiStaUseCaseToLegacy(
- V1_5::IWifiChip::MultiStaUseCase use_case);
-bool convertHidlCoexUnsafeChannelToLegacy(
- const V1_5::IWifiChip::CoexUnsafeChannel& hidl_unsafe_channel,
- legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel);
-bool convertHidlVectorOfCoexUnsafeChannelToLegacy(
- const std::vector<V1_5::IWifiChip::CoexUnsafeChannel>& hidl_unsafe_channels,
- std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels);
-bool convertLegacyRadioCombinationsMatrixToHidl(
- legacy_hal::wifi_radio_combination_matrix* legacy_matrix,
- V1_6::WifiRadioCombinationMatrix* hidl_matrix);
-V1_5::WifiBand convertLegacyMacBandToHidlWifiBand(uint32_t band);
-V1_6::WifiAntennaMode convertLegacyAntennaConfigurationToHidl(uint32_t antenna_cfg);
-
-// STA iface conversion methods.
-bool convertLegacyFeaturesToHidlStaCapabilities(uint64_t legacy_feature_set,
- uint32_t legacy_logger_feature_set,
- uint32_t* hidl_caps);
-bool convertLegacyApfCapabilitiesToHidl(const legacy_hal::PacketFilterCapabilities& legacy_caps,
- StaApfPacketFilterCapabilities* hidl_caps);
-bool convertLegacyGscanCapabilitiesToHidl(const legacy_hal::wifi_gscan_capabilities& legacy_caps,
- StaBackgroundScanCapabilities* hidl_caps);
-legacy_hal::wifi_band convertHidlWifiBandToLegacy(V1_0::WifiBand band);
-bool convertHidlGscanParamsToLegacy(const StaBackgroundScanParameters& hidl_scan_params,
- legacy_hal::wifi_scan_cmd_params* legacy_scan_params);
-// |has_ie_data| indicates whether or not the wifi_scan_result includes 802.11
-// Information Elements (IEs)
-bool convertLegacyGscanResultToHidl(const legacy_hal::wifi_scan_result& legacy_scan_result,
- bool has_ie_data, StaScanResult* hidl_scan_result);
-// |cached_results| is assumed to not include IEs.
-bool convertLegacyVectorOfCachedGscanResultsToHidl(
- const std::vector<legacy_hal::wifi_cached_scan_results>& legacy_cached_scan_results,
- std::vector<StaScanData>* hidl_scan_datas);
-bool convertLegacyLinkLayerStatsToHidl(const legacy_hal::LinkLayerStats& legacy_stats,
- V1_6::StaLinkLayerStats* hidl_stats);
-bool convertLegacyRoamingCapabilitiesToHidl(
- const legacy_hal::wifi_roaming_capabilities& legacy_caps,
- StaRoamingCapabilities* hidl_caps);
-bool convertHidlRoamingConfigToLegacy(const StaRoamingConfig& hidl_config,
- legacy_hal::wifi_roaming_config* legacy_config);
-legacy_hal::fw_roaming_state_t convertHidlRoamingStateToLegacy(StaRoamingState state);
-bool convertLegacyVectorOfDebugTxPacketFateToHidl(
- const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
- std::vector<WifiDebugTxPacketFateReport>* hidl_fates);
-bool convertLegacyVectorOfDebugRxPacketFateToHidl(
- const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
- std::vector<WifiDebugRxPacketFateReport>* hidl_fates);
-
-// NAN iface conversion methods.
-void convertToWifiNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
- WifiNanStatus* wifiNanStatus);
-bool convertHidlNanEnableRequestToLegacy(const V1_4::NanEnableRequest& hidl_request,
- legacy_hal::NanEnableRequest* legacy_request);
-bool convertHidlNanConfigRequestToLegacy(const V1_4::NanConfigRequest& hidl_request,
- legacy_hal::NanConfigRequest* legacy_request);
-bool convertHidlNanEnableRequest_1_6ToLegacy(
- const V1_4::NanEnableRequest& hidl_request1,
- const V1_6::NanConfigRequestSupplemental& hidl_request2,
- legacy_hal::NanEnableRequest* legacy_request);
-bool convertHidlNanConfigRequest_1_6ToLegacy(
- const V1_4::NanConfigRequest& hidl_request1,
- const V1_6::NanConfigRequestSupplemental& hidl_request2,
- legacy_hal::NanConfigRequest* legacy_request);
-bool convertHidlNanPublishRequestToLegacy(const V1_6::NanPublishRequest& hidl_request,
- legacy_hal::NanPublishRequest* legacy_request);
-bool convertHidlNanSubscribeRequestToLegacy(const V1_0::NanSubscribeRequest& hidl_request,
- legacy_hal::NanSubscribeRequest* legacy_request);
-bool convertHidlNanTransmitFollowupRequestToLegacy(
- const NanTransmitFollowupRequest& hidl_request,
- legacy_hal::NanTransmitFollowupRequest* legacy_request);
-bool convertHidlNanDataPathInitiatorRequestToLegacy(
- const V1_0::NanInitiateDataPathRequest& hidl_request,
- legacy_hal::NanDataPathInitiatorRequest* legacy_request);
-bool convertHidlNanDataPathIndicationResponseToLegacy(
- const V1_0::NanRespondToDataPathIndicationRequest& hidl_response,
- legacy_hal::NanDataPathIndicationResponse* legacy_response);
-bool convertHidlNanDataPathInitiatorRequest_1_6ToLegacy(
- const V1_6::NanInitiateDataPathRequest& hidl_request,
- legacy_hal::NanDataPathInitiatorRequest* legacy_request);
-bool convertHidlNanDataPathIndicationResponse_1_6ToLegacy(
- const V1_6::NanRespondToDataPathIndicationRequest& hidl_response,
- legacy_hal::NanDataPathIndicationResponse* legacy_response);
-
-bool convertLegacyNanResponseHeaderToHidl(const legacy_hal::NanResponseMsg& legacy_response,
- WifiNanStatus* wifiNanStatus);
-bool convertLegacyNanCapabilitiesResponseToHidl(const legacy_hal::NanCapabilities& legacy_response,
- V1_6::NanCapabilities* hidl_response);
-bool convertLegacyNanMatchIndToHidl(const legacy_hal::NanMatchInd& legacy_ind,
- V1_6::NanMatchInd* hidl_ind);
-bool convertLegacyNanFollowupIndToHidl(const legacy_hal::NanFollowupInd& legacy_ind,
- NanFollowupReceivedInd* hidl_ind);
-bool convertLegacyNanDataPathRequestIndToHidl(const legacy_hal::NanDataPathRequestInd& legacy_ind,
- NanDataPathRequestInd* hidl_ind);
-bool convertLegacyNanDataPathConfirmIndToHidl(const legacy_hal::NanDataPathConfirmInd& legacy_ind,
- V1_6::NanDataPathConfirmInd* hidl_ind);
-bool convertLegacyNanDataPathScheduleUpdateIndToHidl(
- const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
- V1_6::NanDataPathScheduleUpdateInd* hidl_ind);
-
-// RTT controller conversion methods.
-bool convertHidlVectorOfRttConfigToLegacy(const std::vector<V1_6::RttConfig>& hidl_configs,
- std::vector<legacy_hal::wifi_rtt_config>* legacy_configs);
-bool convertHidlRttLciInformationToLegacy(const RttLciInformation& hidl_info,
- legacy_hal::wifi_lci_information* legacy_info);
-bool convertHidlRttLcrInformationToLegacy(const RttLcrInformation& hidl_info,
- legacy_hal::wifi_lcr_information* legacy_info);
-bool convertHidlRttResponderToLegacy(const V1_6::RttResponder& hidl_responder,
- legacy_hal::wifi_rtt_responder* legacy_responder);
-bool convertHidlWifiChannelInfoToLegacy(const V1_6::WifiChannelInfo& hidl_info,
- legacy_hal::wifi_channel_info* legacy_info);
-bool convertLegacyRttResponderToHidl(const legacy_hal::wifi_rtt_responder& legacy_responder,
- V1_6::RttResponder* hidl_responder);
-bool convertLegacyRttCapabilitiesToHidl(
- const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
- V1_6::RttCapabilities* hidl_capabilities);
-bool convertLegacyVectorOfRttResultToHidl(
- const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
- std::vector<V1_6::RttResult>* hidl_results);
-uint32_t convertHidlWifiBandToLegacyMacBand(V1_5::WifiBand band);
-uint32_t convertHidlWifiIfaceModeToLegacy(uint32_t hidl_iface_mask);
-uint32_t convertHidlUsableChannelFilterToLegacy(uint32_t hidl_filter_mask);
-bool convertLegacyWifiUsableChannelsToHidl(
- const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
- std::vector<V1_6::WifiUsableChannel>* hidl_usable_channels);
-bool convertLegacyPeerInfoStatsToHidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats,
- V1_6::StaPeerInfo* hidl_peer_info_stats);
-bool convertLegacyWifiRateInfoToHidl(const legacy_hal::wifi_rate& legacy_rate,
- V1_6::WifiRateInfo* hidl_rate);
-} // namespace hidl_struct_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // HIDL_STRUCT_UTIL_H_
diff --git a/wifi/1.6/default/hidl_sync_util.cpp b/wifi/1.6/default/hidl_sync_util.cpp
deleted file mode 100644
index 358d95e..0000000
--- a/wifi/1.6/default/hidl_sync_util.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "hidl_sync_util.h"
-
-namespace {
-std::recursive_mutex g_mutex;
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace hidl_sync_util {
-
-std::unique_lock<std::recursive_mutex> acquireGlobalLock() {
- return std::unique_lock<std::recursive_mutex>{g_mutex};
-}
-
-} // namespace hidl_sync_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/hidl_sync_util.h b/wifi/1.6/default/hidl_sync_util.h
deleted file mode 100644
index 2c1c37b..0000000
--- a/wifi/1.6/default/hidl_sync_util.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef HIDL_SYNC_UTIL_H_
-#define HIDL_SYNC_UTIL_H_
-
-#include <mutex>
-
-// Utility that provides a global lock to synchronize access between
-// the HIDL thread and the legacy HAL's event loop.
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace hidl_sync_util {
-std::unique_lock<std::recursive_mutex> acquireGlobalLock();
-} // namespace hidl_sync_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-#endif // HIDL_SYNC_UTIL_H_
diff --git a/wifi/1.6/default/ringbuffer.cpp b/wifi/1.6/default/ringbuffer.cpp
deleted file mode 100644
index 981bf7b..0000000
--- a/wifi/1.6/default/ringbuffer.cpp
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "ringbuffer.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-
-Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {}
-
-enum Ringbuffer::AppendStatus Ringbuffer::append(const std::vector<uint8_t>& input) {
- if (input.size() == 0) {
- return AppendStatus::FAIL_IP_BUFFER_ZERO;
- }
- if (input.size() > maxSize_) {
- LOG(INFO) << "Oversized message of " << input.size() << " bytes is dropped";
- return AppendStatus::FAIL_IP_BUFFER_EXCEEDED_MAXSIZE;
- }
- data_.push_back(input);
- size_ += input.size() * sizeof(input[0]);
- while (size_ > maxSize_) {
- if (data_.front().size() <= 0 || data_.front().size() > maxSize_) {
- LOG(ERROR) << "First buffer in the ring buffer is Invalid. Size: "
- << data_.front().size();
- return AppendStatus::FAIL_RING_BUFFER_CORRUPTED;
- }
- size_ -= data_.front().size() * sizeof(data_.front()[0]);
- data_.pop_front();
- }
- return AppendStatus::SUCCESS;
-}
-
-const std::list<std::vector<uint8_t>>& Ringbuffer::getData() const {
- return data_;
-}
-
-void Ringbuffer::clear() {
- data_.clear();
- size_ = 0;
-}
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/ringbuffer.h b/wifi/1.6/default/ringbuffer.h
deleted file mode 100644
index c6a1e4c..0000000
--- a/wifi/1.6/default/ringbuffer.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef RINGBUFFER_H_
-#define RINGBUFFER_H_
-
-#include <list>
-#include <vector>
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-
-/**
- * Ringbuffer object used to store debug data.
- */
-class Ringbuffer {
- public:
- // Error codes for the append ring buffer operation
- enum AppendStatus {
- SUCCESS,
- FAIL_GENERIC,
- FAIL_IP_BUFFER_ZERO,
- FAIL_IP_BUFFER_EXCEEDED_MAXSIZE,
- FAIL_RING_BUFFER_CORRUPTED
- };
- explicit Ringbuffer(size_t maxSize);
-
- // Appends the data buffer and deletes from the front until buffer is
- // within |maxSize_|.
- enum AppendStatus append(const std::vector<uint8_t>& input);
- const std::list<std::vector<uint8_t>>& getData() const;
- void clear();
-
- private:
- std::list<std::vector<uint8_t>> data_;
- size_t size_;
- size_t maxSize_;
-};
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // RINGBUFFER_H_
diff --git a/wifi/1.6/default/service.cpp b/wifi/1.6/default/service.cpp
deleted file mode 100644
index c874d8b..0000000
--- a/wifi/1.6/default/service.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <hidl/HidlLazyUtils.h>
-#include <hidl/HidlTransportSupport.h>
-#include <signal.h>
-#include <utils/Looper.h>
-#include <utils/StrongPointer.h>
-
-#include "wifi.h"
-#include "wifi_feature_flags.h"
-#include "wifi_legacy_hal.h"
-#include "wifi_legacy_hal_factory.h"
-#include "wifi_mode_controller.h"
-
-using android::hardware::configureRpcThreadpool;
-using android::hardware::joinRpcThreadpool;
-using android::hardware::LazyServiceRegistrar;
-using android::hardware::wifi::V1_6::implementation::feature_flags::WifiFeatureFlags;
-using android::hardware::wifi::V1_6::implementation::legacy_hal::WifiLegacyHal;
-using android::hardware::wifi::V1_6::implementation::legacy_hal::WifiLegacyHalFactory;
-using android::hardware::wifi::V1_6::implementation::mode_controller::WifiModeController;
-
-#ifdef LAZY_SERVICE
-const bool kLazyService = true;
-#else
-const bool kLazyService = false;
-#endif
-
-int main(int /*argc*/, char** argv) {
- signal(SIGPIPE, SIG_IGN);
- android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
- LOG(INFO) << "Wifi Hal is booting up...";
-
- configureRpcThreadpool(1, true /* callerWillJoin */);
-
- const auto iface_tool = std::make_shared<android::wifi_system::InterfaceTool>();
- const auto legacy_hal_factory = std::make_shared<WifiLegacyHalFactory>(iface_tool);
-
- // Setup hwbinder service
- android::sp<android::hardware::wifi::V1_6::IWifi> service =
- new android::hardware::wifi::V1_6::implementation::Wifi(
- iface_tool, legacy_hal_factory, std::make_shared<WifiModeController>(),
- std::make_shared<WifiFeatureFlags>());
- if (kLazyService) {
- auto registrar = LazyServiceRegistrar::getInstance();
- CHECK_EQ(registrar.registerService(service), android::NO_ERROR)
- << "Failed to register wifi HAL";
- } else {
- CHECK_EQ(service->registerAsService(), android::NO_ERROR) << "Failed to register wifi HAL";
- }
-
- joinRpcThreadpool();
-
- LOG(INFO) << "Wifi Hal is terminating...";
- return 0;
-}
diff --git a/wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp b/wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp
deleted file mode 100644
index 0dd0aa1..0000000
--- a/wifi/1.6/default/tests/hidl_struct_util_unit_tests.cpp
+++ /dev/null
@@ -1,486 +0,0 @@
-/*
- * Copyright (C) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <gmock/gmock.h>
-
-#undef NAN
-#include "hidl_struct_util.h"
-
-using testing::Test;
-
-namespace {
-constexpr uint32_t kMacId1 = 1;
-constexpr uint32_t kMacId2 = 2;
-constexpr uint32_t kIfaceChannel1 = 3;
-constexpr uint32_t kIfaceChannel2 = 5;
-constexpr char kIfaceName1[] = "wlan0";
-constexpr char kIfaceName2[] = "wlan1";
-} // namespace
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-using ::android::hardware::wifi::V1_6::WifiChannelWidthInMhz;
-
-class HidlStructUtilTest : public Test {};
-
-TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithOneMac) {
- std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
- legacy_hal::WifiMacInfo legacy_mac_info1 = {
- .wlan_mac_id = kMacId1,
- .mac_band = legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_2_4_BAND};
- legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1, .channel = kIfaceChannel1};
- legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2, .channel = kIfaceChannel2};
- legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
- legacy_mac_info1.iface_infos.push_back(legacy_iface_info2);
- legacy_mac_infos.push_back(legacy_mac_info1);
-
- std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
- ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(legacy_mac_infos,
- &hidl_radio_mode_infos));
-
- ASSERT_EQ(1u, hidl_radio_mode_infos.size());
- auto hidl_radio_mode_info1 = hidl_radio_mode_infos[0];
- EXPECT_EQ(legacy_mac_info1.wlan_mac_id, hidl_radio_mode_info1.radioId);
- EXPECT_EQ(V1_4::WifiBand::BAND_24GHZ_5GHZ, hidl_radio_mode_info1.bandInfo);
- ASSERT_EQ(2u, hidl_radio_mode_info1.ifaceInfos.size());
- auto hidl_iface_info1 = hidl_radio_mode_info1.ifaceInfos[0];
- EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
- EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel), hidl_iface_info1.channel);
- auto hidl_iface_info2 = hidl_radio_mode_info1.ifaceInfos[1];
- EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
- EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel), hidl_iface_info2.channel);
-}
-
-TEST_F(HidlStructUtilTest, CanConvertLegacyWifiMacInfosToHidlWithTwoMac) {
- std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
- legacy_hal::WifiMacInfo legacy_mac_info1 = {.wlan_mac_id = kMacId1,
- .mac_band = legacy_hal::WLAN_MAC_5_0_BAND};
- legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1, .channel = kIfaceChannel1};
- legacy_hal::WifiMacInfo legacy_mac_info2 = {.wlan_mac_id = kMacId2,
- .mac_band = legacy_hal::WLAN_MAC_2_4_BAND};
- legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2, .channel = kIfaceChannel2};
- legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
- legacy_mac_infos.push_back(legacy_mac_info1);
- legacy_mac_info2.iface_infos.push_back(legacy_iface_info2);
- legacy_mac_infos.push_back(legacy_mac_info2);
-
- std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
- ASSERT_TRUE(hidl_struct_util::convertLegacyWifiMacInfosToHidl(legacy_mac_infos,
- &hidl_radio_mode_infos));
-
- ASSERT_EQ(2u, hidl_radio_mode_infos.size());
-
- // Find mac info 1.
- const auto hidl_radio_mode_info1 =
- std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
- [&legacy_mac_info1](const V1_4::IWifiChipEventCallback::RadioModeInfo& x) {
- return x.radioId == legacy_mac_info1.wlan_mac_id;
- });
- ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info1);
- EXPECT_EQ(V1_4::WifiBand::BAND_5GHZ, hidl_radio_mode_info1->bandInfo);
- ASSERT_EQ(1u, hidl_radio_mode_info1->ifaceInfos.size());
- auto hidl_iface_info1 = hidl_radio_mode_info1->ifaceInfos[0];
- EXPECT_EQ(legacy_iface_info1.name, hidl_iface_info1.name);
- EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info1.channel), hidl_iface_info1.channel);
-
- // Find mac info 2.
- const auto hidl_radio_mode_info2 =
- std::find_if(hidl_radio_mode_infos.begin(), hidl_radio_mode_infos.end(),
- [&legacy_mac_info2](const V1_4::IWifiChipEventCallback::RadioModeInfo& x) {
- return x.radioId == legacy_mac_info2.wlan_mac_id;
- });
- ASSERT_NE(hidl_radio_mode_infos.end(), hidl_radio_mode_info2);
- EXPECT_EQ(V1_4::WifiBand::BAND_24GHZ, hidl_radio_mode_info2->bandInfo);
- ASSERT_EQ(1u, hidl_radio_mode_info2->ifaceInfos.size());
- auto hidl_iface_info2 = hidl_radio_mode_info2->ifaceInfos[0];
- EXPECT_EQ(legacy_iface_info2.name, hidl_iface_info2.name);
- EXPECT_EQ(static_cast<uint32_t>(legacy_iface_info2.channel), hidl_iface_info2.channel);
-}
-
-TEST_F(HidlStructUtilTest, canConvertLegacyLinkLayerStatsToHidl) {
- legacy_hal::LinkLayerStats legacy_stats{};
- legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
- legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
- legacy_stats.peers.push_back(legacy_hal::WifiPeerInfo{});
- legacy_stats.peers.push_back(legacy_hal::WifiPeerInfo{});
- legacy_stats.iface.beacon_rx = rand();
- legacy_stats.iface.rssi_mgmt = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples = rand();
-
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples = rand();
-
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples = rand();
-
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg = rand();
- legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples = rand();
-
- legacy_stats.iface.info.time_slicing_duty_cycle_percent = rand();
- legacy_stats.iface.num_peers = 1;
-
- for (auto& radio : legacy_stats.radios) {
- radio.stats.radio = rand();
- radio.stats.on_time = rand();
- radio.stats.tx_time = rand();
- radio.stats.rx_time = rand();
- radio.stats.on_time_scan = rand();
- radio.stats.on_time_nbd = rand();
- radio.stats.on_time_gscan = rand();
- radio.stats.on_time_roam_scan = rand();
- radio.stats.on_time_pno_scan = rand();
- radio.stats.on_time_hs20 = rand();
- for (int i = 0; i < 4; i++) {
- radio.tx_time_per_levels.push_back(rand());
- }
-
- legacy_hal::wifi_channel_stat channel_stat1 = {
- .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 2437, 2437, 0},
- .on_time = 0x1111,
- .cca_busy_time = 0x55,
- };
- legacy_hal::wifi_channel_stat channel_stat2 = {
- .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 5180, 5180, 0},
- .on_time = 0x2222,
- .cca_busy_time = 0x66,
- };
- radio.channel_stats.push_back(channel_stat1);
- radio.channel_stats.push_back(channel_stat2);
- }
-
- for (auto& peer : legacy_stats.peers) {
- peer.peer_info.bssload.sta_count = rand();
- peer.peer_info.bssload.chan_util = rand();
- wifi_rate_stat rate_stat1 = {
- .rate = {3, 1, 2, 5, 0, 0},
- .tx_mpdu = 0,
- .rx_mpdu = 1,
- .mpdu_lost = 2,
- .retries = 3,
- .retries_short = 4,
- .retries_long = 5,
- };
- wifi_rate_stat rate_stat2 = {
- .rate = {2, 2, 1, 6, 0, 1},
- .tx_mpdu = 6,
- .rx_mpdu = 7,
- .mpdu_lost = 8,
- .retries = 9,
- .retries_short = 10,
- .retries_long = 11,
- };
- peer.rate_stats.push_back(rate_stat1);
- peer.rate_stats.push_back(rate_stat2);
- }
-
- V1_6::StaLinkLayerStats converted{};
- hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, &converted);
- EXPECT_EQ(legacy_stats.iface.beacon_rx, converted.iface.V1_0.beaconRx);
- EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.V1_0.avgRssiMgmt);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu,
- converted.iface.V1_0.wmeBePktStats.rxMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu,
- converted.iface.V1_0.wmeBePktStats.txMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost,
- converted.iface.V1_0.wmeBePktStats.lostMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries,
- converted.iface.V1_0.wmeBePktStats.retries);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min,
- converted.iface.wmeBeContentionTimeStats.contentionTimeMinInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max,
- converted.iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg,
- converted.iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples,
- converted.iface.wmeBeContentionTimeStats.contentionNumSamples);
-
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu,
- converted.iface.V1_0.wmeBkPktStats.rxMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu,
- converted.iface.V1_0.wmeBkPktStats.txMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost,
- converted.iface.V1_0.wmeBkPktStats.lostMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries,
- converted.iface.V1_0.wmeBkPktStats.retries);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min,
- converted.iface.wmeBkContentionTimeStats.contentionTimeMinInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max,
- converted.iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg,
- converted.iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples,
- converted.iface.wmeBkContentionTimeStats.contentionNumSamples);
-
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu,
- converted.iface.V1_0.wmeViPktStats.rxMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu,
- converted.iface.V1_0.wmeViPktStats.txMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost,
- converted.iface.V1_0.wmeViPktStats.lostMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries,
- converted.iface.V1_0.wmeViPktStats.retries);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min,
- converted.iface.wmeViContentionTimeStats.contentionTimeMinInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max,
- converted.iface.wmeViContentionTimeStats.contentionTimeMaxInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg,
- converted.iface.wmeViContentionTimeStats.contentionTimeAvgInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples,
- converted.iface.wmeViContentionTimeStats.contentionNumSamples);
-
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu,
- converted.iface.V1_0.wmeVoPktStats.rxMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu,
- converted.iface.V1_0.wmeVoPktStats.txMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost,
- converted.iface.V1_0.wmeVoPktStats.lostMpdu);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries,
- converted.iface.V1_0.wmeVoPktStats.retries);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min,
- converted.iface.wmeVoContentionTimeStats.contentionTimeMinInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max,
- converted.iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg,
- converted.iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec);
- EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples,
- converted.iface.wmeVoContentionTimeStats.contentionNumSamples);
-
- EXPECT_EQ(legacy_stats.iface.info.time_slicing_duty_cycle_percent,
- converted.iface.timeSliceDutyCycleInPercent);
-
- EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
- for (size_t i = 0; i < legacy_stats.radios.size(); i++) {
- EXPECT_EQ(legacy_stats.radios[i].stats.radio, converted.radios[i].radioId);
- EXPECT_EQ(legacy_stats.radios[i].stats.on_time, converted.radios[i].V1_0.onTimeInMs);
- EXPECT_EQ(legacy_stats.radios[i].stats.tx_time, converted.radios[i].V1_0.txTimeInMs);
- EXPECT_EQ(legacy_stats.radios[i].stats.rx_time, converted.radios[i].V1_0.rxTimeInMs);
- EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan,
- converted.radios[i].V1_0.onTimeInMsForScan);
- EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(),
- converted.radios[i].V1_0.txTimeInMsPerLevel.size());
- for (size_t j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size(); j++) {
- EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j],
- converted.radios[i].V1_0.txTimeInMsPerLevel[j]);
- }
- EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd,
- converted.radios[i].onTimeInMsForNanScan);
- EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan,
- converted.radios[i].onTimeInMsForBgScan);
- EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan,
- converted.radios[i].onTimeInMsForRoamScan);
- EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan,
- converted.radios[i].onTimeInMsForPnoScan);
- EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20,
- converted.radios[i].onTimeInMsForHs20Scan);
- EXPECT_EQ(legacy_stats.radios[i].channel_stats.size(),
- converted.radios[i].channelStats.size());
- for (size_t k = 0; k < legacy_stats.radios[i].channel_stats.size(); k++) {
- auto& legacy_channel_st = legacy_stats.radios[i].channel_stats[k];
- EXPECT_EQ(WifiChannelWidthInMhz::WIDTH_20,
- converted.radios[i].channelStats[k].channel.width);
- EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq),
- converted.radios[i].channelStats[k].channel.centerFreq);
- EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq0),
- converted.radios[i].channelStats[k].channel.centerFreq0);
- EXPECT_EQ(WifiChannelInMhz(legacy_channel_st.channel.center_freq1),
- converted.radios[i].channelStats[k].channel.centerFreq1);
- EXPECT_EQ(legacy_channel_st.cca_busy_time,
- converted.radios[i].channelStats[k].ccaBusyTimeInMs);
- EXPECT_EQ(legacy_channel_st.on_time, converted.radios[i].channelStats[k].onTimeInMs);
- }
- }
-
- EXPECT_EQ(legacy_stats.peers.size(), converted.iface.peers.size());
- for (size_t i = 0; i < legacy_stats.peers.size(); i++) {
- EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.sta_count,
- converted.iface.peers[i].staCount);
- EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.chan_util,
- converted.iface.peers[i].chanUtil);
- for (size_t j = 0; j < legacy_stats.peers[i].rate_stats.size(); j++) {
- EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.preamble,
- (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.preamble);
- EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.nss,
- (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.nss);
- EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.bw,
- (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.bw);
- EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.rateMcsIdx,
- converted.iface.peers[i].rateStats[j].rateInfo.rateMcsIdx);
- EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].tx_mpdu,
- converted.iface.peers[i].rateStats[j].txMpdu);
- EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rx_mpdu,
- converted.iface.peers[i].rateStats[j].rxMpdu);
- EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].mpdu_lost,
- converted.iface.peers[i].rateStats[j].mpduLost);
- EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].retries,
- converted.iface.peers[i].rateStats[j].retries);
- }
- }
-}
-
-TEST_F(HidlStructUtilTest, CanConvertLegacyFeaturesToHidl) {
- using HidlChipCaps = V1_3::IWifiChip::ChipCapabilityMask;
-
- uint32_t hidle_caps;
-
- uint32_t legacy_feature_set = WIFI_FEATURE_D2D_RTT | WIFI_FEATURE_SET_LATENCY_MODE;
- uint32_t legacy_logger_feature_set = legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
-
- ASSERT_TRUE(hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
- legacy_feature_set, legacy_logger_feature_set, &hidle_caps));
-
- EXPECT_EQ(HidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA |
- HidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS |
- HidlChipCaps::DEBUG_ERROR_ALERTS | HidlChipCaps::D2D_RTT |
- HidlChipCaps::SET_LATENCY_MODE | HidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP,
- hidle_caps);
-}
-
-void insertRadioCombination(legacy_hal::wifi_radio_combination* dst_radio_combination_ptr,
- int num_radio_configurations,
- legacy_hal::wifi_radio_configuration* radio_configuration) {
- dst_radio_combination_ptr->num_radio_configurations = num_radio_configurations;
- memcpy(dst_radio_combination_ptr->radio_configurations, radio_configuration,
- num_radio_configurations * sizeof(legacy_hal::wifi_radio_configuration));
-}
-
-void verifyRadioCombination(WifiRadioCombination* radioCombination, size_t num_radio_configurations,
- legacy_hal::wifi_radio_configuration* radio_configuration) {
- EXPECT_EQ(num_radio_configurations, radioCombination->radioConfigurations.size());
- for (size_t i = 0; i < num_radio_configurations; i++) {
- EXPECT_EQ(hidl_struct_util::convertLegacyMacBandToHidlWifiBand(radio_configuration->band),
- radioCombination->radioConfigurations[i].bandInfo);
- EXPECT_EQ(hidl_struct_util::convertLegacyAntennaConfigurationToHidl(
- radio_configuration->antenna_cfg),
- radioCombination->radioConfigurations[i].antennaMode);
- radio_configuration++;
- }
-}
-
-TEST_F(HidlStructUtilTest, canConvertLegacyRadioCombinationsMatrixToHidl) {
- legacy_hal::wifi_radio_configuration radio_configurations_array1[] = {
- {.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_1X1},
- };
- legacy_hal::wifi_radio_configuration radio_configurations_array2[] = {
- {.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_2X2},
- {.band = legacy_hal::WLAN_MAC_5_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_3X3},
- };
- legacy_hal::wifi_radio_configuration radio_configurations_array3[] = {
- {.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_2X2},
- {.band = legacy_hal::WLAN_MAC_6_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_1X1},
- {.band = legacy_hal::WLAN_MAC_5_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_4X4},
- };
-
- int num_radio_configs = 0;
- int num_combinations = 0;
- std::array<char, 256> buffer;
- buffer.fill(0);
- legacy_hal::wifi_radio_combination_matrix* legacy_matrix =
- reinterpret_cast<wifi_radio_combination_matrix*>(buffer.data());
- legacy_hal::wifi_radio_combination* radio_combinations;
-
- // Prepare a legacy wifi_radio_combination_matrix
- legacy_matrix->num_radio_combinations = 3;
- // Insert first combination
- radio_combinations =
- (legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations);
- insertRadioCombination(
- radio_combinations,
- sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]),
- radio_configurations_array1);
- num_combinations++;
- num_radio_configs +=
- sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]);
-
- // Insert second combination
- radio_combinations =
- (legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations +
- (num_combinations *
- sizeof(legacy_hal::wifi_radio_combination)) +
- (num_radio_configs *
- sizeof(wifi_radio_configuration)));
- insertRadioCombination(
- radio_combinations,
- sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]),
- radio_configurations_array2);
- num_combinations++;
- num_radio_configs +=
- sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]);
-
- // Insert third combination
- radio_combinations =
- (legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations +
- (num_combinations *
- sizeof(legacy_hal::wifi_radio_combination)) +
- (num_radio_configs *
- sizeof(wifi_radio_configuration)));
- insertRadioCombination(
- radio_combinations,
- sizeof(radio_configurations_array3) / sizeof(radio_configurations_array3[0]),
- radio_configurations_array3);
-
- V1_6::WifiRadioCombinationMatrix converted_matrix{};
- hidl_struct_util::convertLegacyRadioCombinationsMatrixToHidl(legacy_matrix, &converted_matrix);
-
- // Verify the conversion
- EXPECT_EQ(legacy_matrix->num_radio_combinations, converted_matrix.radioCombinations.size());
- verifyRadioCombination(
- &converted_matrix.radioCombinations[0],
- sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]),
- radio_configurations_array1);
- verifyRadioCombination(
- &converted_matrix.radioCombinations[1],
- sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]),
- radio_configurations_array2);
- verifyRadioCombination(
- &converted_matrix.radioCombinations[2],
- sizeof(radio_configurations_array3) / sizeof(radio_configurations_array3[0]),
- radio_configurations_array3);
-}
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/tests/main.cpp b/wifi/1.6/default/tests/main.cpp
deleted file mode 100644
index 9aac837..0000000
--- a/wifi/1.6/default/tests/main.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-
-#include <android-base/logging.h>
-
-int main(int argc, char** argv) {
- ::testing::InitGoogleTest(&argc, argv);
- ::testing::InitGoogleMock(&argc, argv);
- // Force ourselves to always log to stderr
- android::base::InitLogging(argv, android::base::StderrLogger);
- return RUN_ALL_TESTS();
-}
diff --git a/wifi/1.6/default/tests/mock_interface_tool.cpp b/wifi/1.6/default/tests/mock_interface_tool.cpp
deleted file mode 100644
index b99a164..0000000
--- a/wifi/1.6/default/tests/mock_interface_tool.cpp
+++ /dev/null
@@ -1,29 +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 <android-base/logging.h>
-#include <android-base/macros.h>
-#include <gmock/gmock.h>
-
-#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
-#include "mock_interface_tool.h"
-
-namespace android {
-namespace wifi_system {
-
-MockInterfaceTool::MockInterfaceTool() {}
-
-} // namespace wifi_system
-} // namespace android
diff --git a/wifi/1.6/default/tests/mock_interface_tool.h b/wifi/1.6/default/tests/mock_interface_tool.h
deleted file mode 100644
index 7ce3992..0000000
--- a/wifi/1.6/default/tests/mock_interface_tool.h
+++ /dev/null
@@ -1,42 +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.
- */
-
-#ifndef MOCK_INTERFACE_TOOL_H
-#define MOCK_INTERFACE_TOOL_H
-
-#include <gmock/gmock.h>
-#include <wifi_system/interface_tool.h>
-
-namespace android {
-namespace wifi_system {
-
-class MockInterfaceTool : public InterfaceTool {
- public:
- MockInterfaceTool();
-
- MOCK_METHOD1(GetUpState, bool(const char* if_name));
- MOCK_METHOD2(SetUpState, bool(const char* if_name, bool request_up));
- MOCK_METHOD1(SetWifiUpState, bool(bool request_up));
- MOCK_METHOD2(SetMacAddress,
- bool(const char* if_name, const std::array<uint8_t, ETH_ALEN>& address));
- MOCK_METHOD1(GetFactoryMacAddress, std::array<uint8_t, ETH_ALEN>(const char* if_name));
-
-}; // class MockInterfaceTool
-
-} // namespace wifi_system
-} // namespace android
-
-#endif // MOCK_INTERFACE_TOOL_H
diff --git a/wifi/1.6/default/tests/mock_wifi_feature_flags.cpp b/wifi/1.6/default/tests/mock_wifi_feature_flags.cpp
deleted file mode 100644
index d10b74c..0000000
--- a/wifi/1.6/default/tests/mock_wifi_feature_flags.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gmock/gmock.h>
-
-#include "mock_wifi_feature_flags.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace feature_flags {
-
-MockWifiFeatureFlags::MockWifiFeatureFlags() {}
-
-} // namespace feature_flags
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/tests/mock_wifi_feature_flags.h b/wifi/1.6/default/tests/mock_wifi_feature_flags.h
deleted file mode 100644
index fbe1f7a..0000000
--- a/wifi/1.6/default/tests/mock_wifi_feature_flags.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MOCK_WIFI_FEATURE_FLAGS_H_
-#define MOCK_WIFI_FEATURE_FLAGS_H_
-
-#include <gmock/gmock.h>
-#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
-
-#include "wifi_feature_flags.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace feature_flags {
-
-class MockWifiFeatureFlags : public WifiFeatureFlags {
- public:
- MockWifiFeatureFlags();
-
- MOCK_METHOD1(getChipModes, std::vector<V1_6::IWifiChip::ChipMode>(bool is_primary));
- MOCK_METHOD0(isApMacRandomizationDisabled, bool());
-};
-
-} // namespace feature_flags
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // MOCK_WIFI_FEATURE_FLAGS_H_
diff --git a/wifi/1.6/default/tests/mock_wifi_iface_util.cpp b/wifi/1.6/default/tests/mock_wifi_iface_util.cpp
deleted file mode 100644
index 24b16cb..0000000
--- a/wifi/1.6/default/tests/mock_wifi_iface_util.cpp
+++ /dev/null
@@ -1,39 +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 <android-base/logging.h>
-#include <android-base/macros.h>
-#include <gmock/gmock.h>
-
-#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
-#include "mock_wifi_iface_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace iface_util {
-
-MockWifiIfaceUtil::MockWifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
- : WifiIfaceUtil(iface_tool, legacy_hal) {}
-} // namespace iface_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/tests/mock_wifi_iface_util.h b/wifi/1.6/default/tests/mock_wifi_iface_util.h
deleted file mode 100644
index 2701c36..0000000
--- a/wifi/1.6/default/tests/mock_wifi_iface_util.h
+++ /dev/null
@@ -1,50 +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.
- */
-
-#ifndef MOCK_WIFI_IFACE_UTIL_H_
-#define MOCK_WIFI_IFACE_UTIL_H_
-
-#include <gmock/gmock.h>
-
-#include "wifi_iface_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace iface_util {
-
-class MockWifiIfaceUtil : public WifiIfaceUtil {
- public:
- MockWifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
- MOCK_METHOD1(getFactoryMacAddress, std::array<uint8_t, 6>(const std::string&));
- MOCK_METHOD2(setMacAddress, bool(const std::string&, const std::array<uint8_t, 6>&));
- MOCK_METHOD0(getOrCreateRandomMacAddress, std::array<uint8_t, 6>());
- MOCK_METHOD2(registerIfaceEventHandlers, void(const std::string&, IfaceEventHandlers));
- MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&));
- MOCK_METHOD2(setUpState, bool(const std::string&, bool));
- MOCK_METHOD1(ifNameToIndex, unsigned(const std::string&));
-};
-} // namespace iface_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // MOCK_WIFI_IFACE_UTIL_H_
diff --git a/wifi/1.6/default/tests/mock_wifi_legacy_hal.cpp b/wifi/1.6/default/tests/mock_wifi_legacy_hal.cpp
deleted file mode 100644
index 2c55861..0000000
--- a/wifi/1.6/default/tests/mock_wifi_legacy_hal.cpp
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <gmock/gmock.h>
-
-#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
-#include "mock_wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace legacy_hal {
-
-MockWifiLegacyHal::MockWifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
- const wifi_hal_fn& fn, bool is_primary)
- : WifiLegacyHal(iface_tool, fn, is_primary) {}
-} // namespace legacy_hal
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/tests/mock_wifi_legacy_hal.h b/wifi/1.6/default/tests/mock_wifi_legacy_hal.h
deleted file mode 100644
index 85dbf0f..0000000
--- a/wifi/1.6/default/tests/mock_wifi_legacy_hal.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MOCK_WIFI_LEGACY_HAL_H_
-#define MOCK_WIFI_LEGACY_HAL_H_
-
-#include <gmock/gmock.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace legacy_hal {
-
-class MockWifiLegacyHal : public WifiLegacyHal {
- public:
- MockWifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
- const wifi_hal_fn& fn, bool is_primary);
- MOCK_METHOD0(initialize, wifi_error());
- MOCK_METHOD0(start, wifi_error());
- MOCK_METHOD2(stop,
- wifi_error(std::unique_lock<std::recursive_mutex>*, const std::function<void()>&));
- MOCK_METHOD2(setDfsFlag, wifi_error(const std::string&, bool));
- MOCK_METHOD2(registerRadioModeChangeCallbackHandler,
- wifi_error(const std::string&, const on_radio_mode_change_callback&));
- MOCK_METHOD1(getFirmwareVersion,
- std::pair<wifi_error, std::string>(const std::string& iface_name));
- MOCK_METHOD1(getDriverVersion,
- std::pair<wifi_error, std::string>(const std::string& iface_name));
-
- MOCK_METHOD2(selectTxPowerScenario,
- wifi_error(const std::string& iface_name, wifi_power_scenario scenario));
- MOCK_METHOD1(resetTxPowerScenario, wifi_error(const std::string& iface_name));
- MOCK_METHOD2(nanRegisterCallbackHandlers,
- wifi_error(const std::string&, const NanCallbackHandlers&));
- MOCK_METHOD2(nanDisableRequest, wifi_error(const std::string&, transaction_id));
- MOCK_METHOD3(nanDataInterfaceDelete,
- wifi_error(const std::string&, transaction_id, const std::string&));
- MOCK_METHOD2(createVirtualInterface,
- wifi_error(const std::string& ifname, wifi_interface_type iftype));
- MOCK_METHOD1(deleteVirtualInterface, wifi_error(const std::string& ifname));
- MOCK_METHOD0(waitForDriverReady, wifi_error());
- MOCK_METHOD2(getSupportedIfaceName, wifi_error(uint32_t, std::string&));
- MOCK_METHOD1(registerSubsystemRestartCallbackHandler,
- wifi_error(const on_subsystem_restart_callback&));
- MOCK_METHOD1(getSupportedFeatureSet, std::pair<wifi_error, uint64_t>(const std::string&));
-};
-} // namespace legacy_hal
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // MOCK_WIFI_LEGACY_HAL_H_
diff --git a/wifi/1.6/default/tests/mock_wifi_mode_controller.cpp b/wifi/1.6/default/tests/mock_wifi_mode_controller.cpp
deleted file mode 100644
index 446f829..0000000
--- a/wifi/1.6/default/tests/mock_wifi_mode_controller.cpp
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <gmock/gmock.h>
-
-#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
-#include "mock_wifi_mode_controller.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace mode_controller {
-
-MockWifiModeController::MockWifiModeController() : WifiModeController() {}
-} // namespace mode_controller
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/tests/mock_wifi_mode_controller.h b/wifi/1.6/default/tests/mock_wifi_mode_controller.h
deleted file mode 100644
index addcc81..0000000
--- a/wifi/1.6/default/tests/mock_wifi_mode_controller.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef MOCK_WIFI_MODE_CONTROLLER_H_
-#define MOCK_WIFI_MODE_CONTROLLER_H_
-
-#include <gmock/gmock.h>
-
-#include "wifi_mode_controller.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace mode_controller {
-
-class MockWifiModeController : public WifiModeController {
- public:
- MockWifiModeController();
- MOCK_METHOD0(initialize, bool());
- MOCK_METHOD1(changeFirmwareMode, bool(IfaceType));
- MOCK_METHOD1(isFirmwareModeChangeNeeded, bool(IfaceType));
- MOCK_METHOD0(deinitialize, bool());
-};
-} // namespace mode_controller
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // MOCK_WIFI_MODE_CONTROLLER_H_
diff --git a/wifi/1.6/default/tests/ringbuffer_unit_tests.cpp b/wifi/1.6/default/tests/ringbuffer_unit_tests.cpp
deleted file mode 100644
index eb86194..0000000
--- a/wifi/1.6/default/tests/ringbuffer_unit_tests.cpp
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright (C) 2018, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <gmock/gmock.h>
-
-#include "ringbuffer.h"
-
-using testing::Return;
-using testing::Test;
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-
-class RingbufferTest : public Test {
- public:
- const uint32_t maxBufferSize_ = 10;
- Ringbuffer buffer_{maxBufferSize_};
-};
-
-TEST_F(RingbufferTest, CreateEmptyBuffer) {
- ASSERT_TRUE(buffer_.getData().empty());
-}
-
-TEST_F(RingbufferTest, CanUseFullBufferCapacity) {
- const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
- const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
- buffer_.append(input);
- buffer_.append(input2);
- ASSERT_EQ(2u, buffer_.getData().size());
- EXPECT_EQ(input, buffer_.getData().front());
- EXPECT_EQ(input2, buffer_.getData().back());
-}
-
-TEST_F(RingbufferTest, OldDataIsRemovedOnOverflow) {
- const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
- const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
- const std::vector<uint8_t> input3 = {'G'};
- buffer_.append(input);
- buffer_.append(input2);
- buffer_.append(input3);
- ASSERT_EQ(2u, buffer_.getData().size());
- EXPECT_EQ(input2, buffer_.getData().front());
- EXPECT_EQ(input3, buffer_.getData().back());
-}
-
-TEST_F(RingbufferTest, MultipleOldDataIsRemovedOnOverflow) {
- const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
- const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
- const std::vector<uint8_t> input3(maxBufferSize_, '2');
- buffer_.append(input);
- buffer_.append(input2);
- buffer_.append(input3);
- ASSERT_EQ(1u, buffer_.getData().size());
- EXPECT_EQ(input3, buffer_.getData().front());
-}
-
-TEST_F(RingbufferTest, AppendingEmptyBufferDoesNotAddGarbage) {
- const std::vector<uint8_t> input = {};
- buffer_.append(input);
- ASSERT_TRUE(buffer_.getData().empty());
-}
-
-TEST_F(RingbufferTest, OversizedAppendIsDropped) {
- const std::vector<uint8_t> input(maxBufferSize_ + 1, '0');
- buffer_.append(input);
- ASSERT_TRUE(buffer_.getData().empty());
-}
-
-TEST_F(RingbufferTest, OversizedAppendDoesNotDropExistingData) {
- const std::vector<uint8_t> input(maxBufferSize_, '0');
- const std::vector<uint8_t> input2(maxBufferSize_ + 1, '1');
- buffer_.append(input);
- buffer_.append(input2);
- ASSERT_EQ(1u, buffer_.getData().size());
- EXPECT_EQ(input, buffer_.getData().front());
-}
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/tests/runtests.sh b/wifi/1.6/default/tests/runtests.sh
deleted file mode 100755
index 6bce3ef..0000000
--- a/wifi/1.6/default/tests/runtests.sh
+++ /dev/null
@@ -1,26 +0,0 @@
-#!/usr/bin/env bash
-
-# Copyright(C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0(the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http:// www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-if [ -z $ANDROID_BUILD_TOP ]; then
- echo "You need to source and lunch before you can use this script"
- exit 1
-fi
-set -e
-
-$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode android.hardware.wifi@1.0-service-tests
-adb root
-adb sync data
-adb shell /data/nativetest64/vendor/android.hardware.wifi@1.0-service-tests/android.hardware.wifi@1.0-service-tests
diff --git a/wifi/1.6/default/tests/wifi_chip_unit_tests.cpp b/wifi/1.6/default/tests/wifi_chip_unit_tests.cpp
deleted file mode 100644
index 81117c5..0000000
--- a/wifi/1.6/default/tests/wifi_chip_unit_tests.cpp
+++ /dev/null
@@ -1,864 +0,0 @@
-/*
- * Copyright (C) 2017, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <cutils/properties.h>
-#include <gmock/gmock.h>
-
-#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
-#include "wifi_chip.h"
-
-#include "mock_interface_tool.h"
-#include "mock_wifi_feature_flags.h"
-#include "mock_wifi_iface_util.h"
-#include "mock_wifi_legacy_hal.h"
-#include "mock_wifi_mode_controller.h"
-
-using testing::NiceMock;
-using testing::Return;
-using testing::Test;
-
-namespace {
-using android::hardware::wifi::V1_0::ChipId;
-
-constexpr ChipId kFakeChipId = 5;
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-
-class WifiChipTest : public Test {
- protected:
- void setupV1IfaceCombination() {
- // clang-format off
- const hidl_vec<IWifiChip::ChipConcurrencyCombination> combinationsSta = {
- {{{{IfaceConcurrencyType::STA}, 1}, {{IfaceConcurrencyType::P2P}, 1}}}
- };
- const hidl_vec<IWifiChip::ChipConcurrencyCombination> combinationsAp = {
- {{{{IfaceConcurrencyType::AP}, 1}}}
- };
- const std::vector<V1_6::IWifiChip::ChipMode> modes = {
- {feature_flags::chip_mode_ids::kV1Sta, combinationsSta},
- {feature_flags::chip_mode_ids::kV1Ap, combinationsAp}
- };
- // clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
- }
-
- void setupV1_AwareIfaceCombination() {
- // clang-format off
- const hidl_vec<IWifiChip::ChipConcurrencyCombination> combinationsSta = {
- {{{{IfaceConcurrencyType::STA}, 1},
- {{IfaceConcurrencyType::P2P, IfaceConcurrencyType::NAN}, 1}}}
- };
- const hidl_vec<IWifiChip::ChipConcurrencyCombination> combinationsAp = {
- {{{{IfaceConcurrencyType::AP}, 1}}}
- };
- const std::vector<V1_6::IWifiChip::ChipMode> modes = {
- {feature_flags::chip_mode_ids::kV1Sta, combinationsSta},
- {feature_flags::chip_mode_ids::kV1Ap, combinationsAp}
- };
- // clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
- }
-
- void setupV1_AwareDisabledApIfaceCombination() {
- // clang-format off
- const hidl_vec<IWifiChip::ChipConcurrencyCombination> combinationsSta = {
- {{{{IfaceConcurrencyType::STA}, 1},
- {{IfaceConcurrencyType::P2P, IfaceConcurrencyType::NAN}, 1}}}
- };
- const std::vector<V1_6::IWifiChip::ChipMode> modes = {
- {feature_flags::chip_mode_ids::kV1Sta, combinationsSta}
- };
- // clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
- }
-
- void setupV2_AwareIfaceCombination() {
- // clang-format off
- const hidl_vec<IWifiChip::ChipConcurrencyCombination> combinations = {
- {{{{IfaceConcurrencyType::STA}, 1}, {{IfaceConcurrencyType::AP}, 1}}},
- {{{{IfaceConcurrencyType::STA}, 1},
- {{IfaceConcurrencyType::P2P, IfaceConcurrencyType::NAN}, 1}}}
- };
- const std::vector<V1_6::IWifiChip::ChipMode> modes = {
- {feature_flags::chip_mode_ids::kV3, combinations}
- };
- // clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
- }
-
- void setupV2_AwareDisabledApIfaceCombination() {
- // clang-format off
- const hidl_vec<IWifiChip::ChipConcurrencyCombination> combinations = {
- {{{{IfaceConcurrencyType::STA}, 1},
- {{IfaceConcurrencyType::P2P, IfaceConcurrencyType::NAN}, 1}}}
- };
- const std::vector<V1_6::IWifiChip::ChipMode> modes = {
- {feature_flags::chip_mode_ids::kV3, combinations}
- };
- // clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
- }
-
- void setup_MultiIfaceCombination() {
- // clang-format off
- const hidl_vec<IWifiChip::ChipConcurrencyCombination> combinations = {
- {{{{IfaceConcurrencyType::STA}, 3}, {{IfaceConcurrencyType::AP}, 1}}}
- };
- const std::vector<V1_6::IWifiChip::ChipMode> modes = {
- {feature_flags::chip_mode_ids::kV3, combinations}
- };
- // clang-format on
- EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
- }
-
- void assertNumberOfModes(uint32_t num_modes) {
- chip_->getAvailableModes_1_6([num_modes](const WifiStatus& status,
- const std::vector<WifiChip::ChipMode>& modes) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- // V2_Aware has 1 mode of operation.
- ASSERT_EQ(num_modes, modes.size());
- });
- }
-
- void findModeAndConfigureForIfaceType(const IfaceConcurrencyType& type) {
- // This should be aligned with kInvalidModeId in wifi_chip.cpp.
- ChipModeId mode_id = UINT32_MAX;
- chip_->getAvailableModes_1_6([&mode_id, &type](
- const WifiStatus& status,
- const std::vector<WifiChip::ChipMode>& modes) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- for (const auto& mode : modes) {
- for (const auto& combination : mode.availableCombinations) {
- for (const auto& limit : combination.limits) {
- if (limit.types.end() !=
- std::find(limit.types.begin(), limit.types.end(), type)) {
- mode_id = mode.id;
- }
- }
- }
- }
- });
- ASSERT_NE(UINT32_MAX, mode_id);
-
- chip_->configureChip(mode_id, [](const WifiStatus& status) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- });
- }
-
- // Returns an empty string on error.
- std::string createIface(const IfaceType& type) {
- std::string iface_name;
- if (type == IfaceType::AP) {
- chip_->createApIface(
- [&iface_name](const WifiStatus& status, const sp<V1_0::IWifiApIface>& iface) {
- if (WifiStatusCode::SUCCESS == status.code) {
- ASSERT_NE(iface.get(), nullptr);
- iface->getName([&iface_name](const WifiStatus& status,
- const hidl_string& name) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- iface_name = name.c_str();
- });
- }
- });
- } else if (type == IfaceType::NAN) {
- chip_->createNanIface(
- [&iface_name](const WifiStatus& status,
- const sp<android::hardware::wifi::V1_0::IWifiNanIface>& iface) {
- if (WifiStatusCode::SUCCESS == status.code) {
- ASSERT_NE(iface.get(), nullptr);
- iface->getName([&iface_name](const WifiStatus& status,
- const hidl_string& name) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- iface_name = name.c_str();
- });
- }
- });
- } else if (type == IfaceType::P2P) {
- chip_->createP2pIface(
- [&iface_name](const WifiStatus& status, const sp<IWifiP2pIface>& iface) {
- if (WifiStatusCode::SUCCESS == status.code) {
- ASSERT_NE(iface.get(), nullptr);
- iface->getName([&iface_name](const WifiStatus& status,
- const hidl_string& name) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- iface_name = name.c_str();
- });
- }
- });
- } else if (type == IfaceType::STA) {
- chip_->createStaIface(
- [&iface_name](const WifiStatus& status, const sp<V1_0::IWifiStaIface>& iface) {
- if (WifiStatusCode::SUCCESS == status.code) {
- ASSERT_NE(iface.get(), nullptr);
- iface->getName([&iface_name](const WifiStatus& status,
- const hidl_string& name) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- iface_name = name.c_str();
- });
- }
- });
- }
- return iface_name;
- }
-
- void removeIface(const IfaceType& type, const std::string& iface_name) {
- if (type == IfaceType::AP) {
- chip_->removeApIface(iface_name, [](const WifiStatus& status) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- });
- } else if (type == IfaceType::NAN) {
- chip_->removeNanIface(iface_name, [](const WifiStatus& status) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- });
- } else if (type == IfaceType::P2P) {
- chip_->removeP2pIface(iface_name, [](const WifiStatus& status) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- });
- } else if (type == IfaceType::STA) {
- chip_->removeStaIface(iface_name, [](const WifiStatus& status) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- });
- }
- }
-
- bool createRttController() {
- bool success = false;
- chip_->createRttController_1_6(
- NULL, [&success](const WifiStatus& status, const sp<IWifiRttController>& rtt) {
- if (WifiStatusCode::SUCCESS == status.code) {
- ASSERT_NE(rtt.get(), nullptr);
- success = true;
- }
- });
- return success;
- }
-
- static void subsystemRestartHandler(const std::string& /*error*/) {}
-
- sp<WifiChip> chip_;
- ChipId chip_id_ = kFakeChipId;
- legacy_hal::wifi_hal_fn fake_func_table_;
- std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
- new NiceMock<wifi_system::MockInterfaceTool>};
- std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
- new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_, fake_func_table_, true)};
- std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>> mode_controller_{
- new NiceMock<mode_controller::MockWifiModeController>};
- std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
- new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_, legacy_hal_)};
- std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>> feature_flags_{
- new NiceMock<feature_flags::MockWifiFeatureFlags>};
-
- public:
- void SetUp() override {
- chip_ = new WifiChip(chip_id_, true, legacy_hal_, mode_controller_, iface_util_,
- feature_flags_, subsystemRestartHandler);
-
- EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_))
- .WillRepeatedly(testing::Return(true));
- EXPECT_CALL(*legacy_hal_, start())
- .WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS));
- // Vendor HAL does not override the name by default.
- EXPECT_CALL(*legacy_hal_, getSupportedIfaceName(testing::_, testing::_))
- .WillRepeatedly(testing::Return(legacy_hal::WIFI_ERROR_UNKNOWN));
- }
-
- void TearDown() override {
- // Restore default system iface names (This should ideally be using a
- // mock).
- property_set("wifi.interface", "wlan0");
- property_set("wifi.concurrent.interface", "wlan1");
- property_set("wifi.aware.interface", nullptr);
- }
-};
-
-////////// V1 Iface Combinations ////////////
-// Mode 1 - STA + P2P
-// Mode 2 - AP
-class WifiChipV1IfaceCombinationTest : public WifiChipTest {
- public:
- void SetUp() override {
- setupV1IfaceCombination();
- WifiChipTest::SetUp();
- // V1 has 2 modes of operation.
- assertNumberOfModes(2u);
- }
-};
-
-TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
-}
-
-TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateNan_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_TRUE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateAp_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_TRUE(createIface(IfaceType::AP).empty());
-}
-
-TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateStaP2p_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
-}
-
-TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_TRUE(createIface(IfaceType::STA).empty());
-}
-
-TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateP2p_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_TRUE(createIface(IfaceType::STA).empty());
-}
-
-TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateNan_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_TRUE(createIface(IfaceType::NAN).empty());
-}
-
-////////// V1 + Aware Iface Combinations ////////////
-// Mode 1 - STA + P2P/NAN
-// Mode 2 - AP
-class WifiChipV1_AwareIfaceCombinationTest : public WifiChipTest {
- public:
- void SetUp() override {
- setupV1_AwareIfaceCombination();
- WifiChipTest::SetUp();
- // V1_Aware has 2 modes of operation.
- assertNumberOfModes(2u);
- }
-};
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateNan_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateAp_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_TRUE(createIface(IfaceType::AP).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaP2p_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaNan_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaP2PNan_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
- ASSERT_TRUE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- const auto p2p_iface_name = createIface(IfaceType::P2P);
- ASSERT_FALSE(p2p_iface_name.empty());
- ASSERT_TRUE(createIface(IfaceType::NAN).empty());
-
- // After removing P2P iface, NAN iface creation should succeed.
- removeIface(IfaceType::P2P, p2p_iface_name);
- ASSERT_FALSE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- const auto nan_iface_name = createIface(IfaceType::NAN);
- ASSERT_FALSE(nan_iface_name.empty());
- ASSERT_TRUE(createIface(IfaceType::P2P).empty());
-
- // After removing NAN iface, P2P iface creation should succeed.
- removeIface(IfaceType::NAN, nan_iface_name);
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_TRUE(createIface(IfaceType::STA).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateP2p_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_TRUE(createIface(IfaceType::STA).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateNan_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_TRUE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_TRUE(createRttController());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_TRUE(createRttController());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowApToSta) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- const auto ap_iface_name = createIface(IfaceType::AP);
- ASSERT_FALSE(ap_iface_name.empty());
- ASSERT_FALSE(createRttController());
-
- removeIface(IfaceType::AP, ap_iface_name);
-
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_TRUE(createRttController());
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
- EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
- .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
- chip_->selectTxPowerScenario_1_2(
- V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
- [](const WifiStatus& status) { ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); });
-}
-
-TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
- EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
- .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
- chip_->selectTxPowerScenario_1_2(
- V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
- [](const WifiStatus& status) { ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); });
-}
-
-////////// V2 + Aware Iface Combinations ////////////
-// Mode 1 - STA + STA/AP
-// - STA + P2P/NAN
-class WifiChipV2_AwareIfaceCombinationTest : public WifiChipTest {
- public:
- void SetUp() override {
- setupV2_AwareIfaceCombination();
- WifiChipTest::SetUp();
- // V2_Aware has 1 mode of operation.
- assertNumberOfModes(1u);
- }
-};
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateP2p_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNan_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateAp_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaSta_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
- ASSERT_TRUE(createIface(IfaceType::STA).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
- ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApSta_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_AfterStaApRemove_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- const auto sta_iface_name = createIface(IfaceType::STA);
- ASSERT_FALSE(sta_iface_name.empty());
- const auto ap_iface_name = createIface(IfaceType::AP);
- ASSERT_FALSE(ap_iface_name.empty());
-
- ASSERT_TRUE(createIface(IfaceType::STA).empty());
-
- // After removing AP & STA iface, STA iface creation should succeed.
- removeIface(IfaceType::STA, sta_iface_name);
- removeIface(IfaceType::AP, ap_iface_name);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2p_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaNan_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2PNan_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
- ASSERT_TRUE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaNan_AfterP2pRemove_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- const auto p2p_iface_name = createIface(IfaceType::P2P);
- ASSERT_FALSE(p2p_iface_name.empty());
- ASSERT_TRUE(createIface(IfaceType::NAN).empty());
-
- // After removing P2P iface, NAN iface creation should succeed.
- removeIface(IfaceType::P2P, p2p_iface_name);
- ASSERT_FALSE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2p_AfterNanRemove_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- const auto nan_iface_name = createIface(IfaceType::NAN);
- ASSERT_FALSE(nan_iface_name.empty());
- ASSERT_TRUE(createIface(IfaceType::P2P).empty());
-
- // After removing NAN iface, P2P iface creation should succeed.
- removeIface(IfaceType::NAN, nan_iface_name);
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApNan_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_FALSE(createIface(IfaceType::AP).empty());
- ASSERT_TRUE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApP2p_ShouldFail) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_FALSE(createIface(IfaceType::AP).empty());
- ASSERT_TRUE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- const auto p2p_iface_name = createIface(IfaceType::P2P);
- ASSERT_FALSE(p2p_iface_name.empty());
- ASSERT_TRUE(createIface(IfaceType::NAN).empty());
-
- // After removing P2P iface, NAN iface creation should succeed.
- removeIface(IfaceType::P2P, p2p_iface_name);
- ASSERT_FALSE(createIface(IfaceType::NAN).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- const auto nan_iface_name = createIface(IfaceType::NAN);
- ASSERT_FALSE(nan_iface_name.empty());
- ASSERT_TRUE(createIface(IfaceType::P2P).empty());
-
- // After removing NAN iface, P2P iface creation should succeed.
- removeIface(IfaceType::NAN, nan_iface_name);
- ASSERT_FALSE(createIface(IfaceType::P2P).empty());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_EnsureDifferentIfaceNames) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- const auto sta_iface_name = createIface(IfaceType::STA);
- const auto ap_iface_name = createIface(IfaceType::AP);
- ASSERT_FALSE(sta_iface_name.empty());
- ASSERT_FALSE(ap_iface_name.empty());
- ASSERT_NE(sta_iface_name, ap_iface_name);
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_TRUE(createRttController());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_TRUE(createRttController());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlow) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::AP).empty());
- ASSERT_TRUE(createRttController());
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
- EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
- .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
- chip_->selectTxPowerScenario_1_2(
- V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
- [](const WifiStatus& status) { ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); });
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
- ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
- EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan1", testing::_))
- .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
- chip_->selectTxPowerScenario_1_2(
- V1_2::IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF,
- [](const WifiStatus& status) { ASSERT_EQ(WifiStatusCode::SUCCESS, status.code); });
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, InvalidateAndRemoveNanOnStaRemove) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
-
- // Create NAN iface
- ASSERT_EQ(createIface(IfaceType::NAN), "wlan0");
-
- // We should have 1 nan iface.
- chip_->getNanIfaceNames([](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- ASSERT_EQ(iface_names.size(), 1u);
- ASSERT_EQ(iface_names[0], "wlan0");
- });
- // Retrieve the exact iface object.
- sp<android::hardware::wifi::V1_0::IWifiNanIface> nan_iface;
- chip_->getNanIface("wlan0",
- [&nan_iface](const WifiStatus& status,
- const sp<android::hardware::wifi::V1_0::IWifiNanIface>& iface) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- ASSERT_NE(iface.get(), nullptr);
- nan_iface = iface;
- });
-
- // Remove the STA iface.
- removeIface(IfaceType::STA, "wlan0");
- // We should have 0 nan iface now.
- chip_->getNanIfaceNames([](const WifiStatus& status, const hidl_vec<hidl_string>& iface_names) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- ASSERT_EQ(iface_names.size(), 0u);
- });
- // Any operation on the nan iface object should return error now.
- nan_iface->getName([](const WifiStatus& status, const std::string& /* iface_name */) {
- ASSERT_EQ(WifiStatusCode::ERROR_WIFI_IFACE_INVALID, status.code);
- });
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, InvalidateAndRemoveRttControllerOnStaRemove) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
-
- // Create RTT controller
- sp<IWifiRttController> rtt_controller;
- chip_->createRttController_1_6(
- NULL, [&rtt_controller](const WifiStatus& status, const sp<IWifiRttController>& rtt) {
- if (WifiStatusCode::SUCCESS == status.code) {
- ASSERT_NE(rtt.get(), nullptr);
- rtt_controller = rtt;
- }
- });
-
- // Remove the STA iface.
- removeIface(IfaceType::STA, "wlan0");
-
- // Any operation on the rtt controller object should return error now.
- rtt_controller->getBoundIface([](const WifiStatus& status, const sp<IWifiIface>& /* iface */) {
- ASSERT_EQ(WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID, status.code);
- });
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNanWithSharedNanIface) {
- property_set("wifi.aware.interface", nullptr);
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
- ASSERT_EQ(createIface(IfaceType::NAN), "wlan0");
- removeIface(IfaceType::NAN, "wlan0");
- EXPECT_CALL(*iface_util_, setUpState(testing::_, testing::_)).Times(0);
-}
-
-TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNanWithDedicatedNanIface) {
- property_set("wifi.aware.interface", "aware0");
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
- EXPECT_CALL(*iface_util_, ifNameToIndex("aware0")).WillOnce(testing::Return(4));
- EXPECT_CALL(*iface_util_, setUpState("aware0", true)).WillOnce(testing::Return(true));
- ASSERT_EQ(createIface(IfaceType::NAN), "aware0");
-
- EXPECT_CALL(*iface_util_, setUpState("aware0", false)).WillOnce(testing::Return(true));
- removeIface(IfaceType::NAN, "aware0");
-}
-
-////////// V1 Iface Combinations when AP creation is disabled //////////
-class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
- public:
- void SetUp() override {
- setupV1_AwareDisabledApIfaceCombination();
- WifiChipTest::SetUp();
- }
-};
-
-TEST_F(WifiChipV1_AwareDisabledApIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_TRUE(createIface(IfaceType::AP).empty());
-}
-
-////////// V2 Iface Combinations when AP creation is disabled //////////
-class WifiChipV2_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
- public:
- void SetUp() override {
- setupV2_AwareDisabledApIfaceCombination();
- WifiChipTest::SetUp();
- }
-};
-
-TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest, CreateSta_ShouldSucceed) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_TRUE(createIface(IfaceType::AP).empty());
-}
-
-////////// Hypothetical Iface Combination with multiple ifaces //////////
-class WifiChip_MultiIfaceTest : public WifiChipTest {
- public:
- void SetUp() override {
- setup_MultiIfaceCombination();
- WifiChipTest::SetUp();
- }
-};
-
-TEST_F(WifiChip_MultiIfaceTest, Create3Sta) {
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_FALSE(createIface(IfaceType::STA).empty());
- ASSERT_TRUE(createIface(IfaceType::STA).empty());
-}
-
-TEST_F(WifiChip_MultiIfaceTest, CreateStaWithDefaultNames) {
- property_set("wifi.interface.0", "");
- property_set("wifi.interface.1", "");
- property_set("wifi.interface.2", "");
- property_set("wifi.interface", "");
- property_set("wifi.concurrent.interface", "");
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
- ASSERT_EQ(createIface(IfaceType::STA), "wlan1");
- ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
-}
-
-TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomNames) {
- property_set("wifi.interface.0", "test0");
- property_set("wifi.interface.1", "test1");
- property_set("wifi.interface.2", "test2");
- property_set("wifi.interface", "bad0");
- property_set("wifi.concurrent.interface", "bad1");
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "bad0");
- ASSERT_EQ(createIface(IfaceType::STA), "bad1");
- ASSERT_EQ(createIface(IfaceType::STA), "test2");
-}
-
-TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomAltNames) {
- property_set("wifi.interface.0", "");
- property_set("wifi.interface.1", "");
- property_set("wifi.interface.2", "");
- property_set("wifi.interface", "testA0");
- property_set("wifi.concurrent.interface", "testA1");
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- ASSERT_EQ(createIface(IfaceType::STA), "testA0");
- ASSERT_EQ(createIface(IfaceType::STA), "testA1");
- ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
-}
-
-TEST_F(WifiChip_MultiIfaceTest, CreateApStartsWithIdx1) {
- // WifiChip_MultiIfaceTest iface combo: STAx3 + APx1
- // When the HAL support dual STAs, AP should start with idx 2.
- findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
- // First AP will be slotted to wlan1.
- ASSERT_EQ(createIface(IfaceType::AP), "wlan2");
- // First STA will be slotted to wlan0.
- ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
- // All further STA will be slotted to the remaining free indices.
- ASSERT_EQ(createIface(IfaceType::STA), "wlan1");
- ASSERT_EQ(createIface(IfaceType::STA), "wlan3");
-}
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/1.6/default/tests/wifi_iface_util_unit_tests.cpp
deleted file mode 100644
index cc9a334..0000000
--- a/wifi/1.6/default/tests/wifi_iface_util_unit_tests.cpp
+++ /dev/null
@@ -1,96 +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 <android-base/logging.h>
-#include <android-base/macros.h>
-#include <gmock/gmock.h>
-
-#undef NAN
-#include "wifi_iface_util.h"
-
-#include "mock_interface_tool.h"
-#include "mock_wifi_legacy_hal.h"
-
-using testing::NiceMock;
-using testing::Test;
-
-namespace {
-constexpr uint8_t kValidUnicastLocallyAssignedMacAddressMask = 0x02;
-constexpr uint8_t kMacAddress[] = {0x02, 0x12, 0x45, 0x56, 0xab, 0xcc};
-constexpr char kIfaceName[] = "test-wlan0";
-
-bool isValidUnicastLocallyAssignedMacAddress(const std::array<uint8_t, 6>& mac_address) {
- uint8_t first_byte = mac_address[0];
- return (first_byte & 0x3) == kValidUnicastLocallyAssignedMacAddressMask;
-}
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace iface_util {
-class WifiIfaceUtilTest : public Test {
- protected:
- std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
- new NiceMock<wifi_system::MockInterfaceTool>};
- legacy_hal::wifi_hal_fn fake_func_table_;
- std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
- new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_, fake_func_table_, true)};
- WifiIfaceUtil* iface_util_ = new WifiIfaceUtil(iface_tool_, legacy_hal_);
-};
-
-TEST_F(WifiIfaceUtilTest, GetOrCreateRandomMacAddress) {
- auto mac_address = iface_util_->getOrCreateRandomMacAddress();
- ASSERT_TRUE(isValidUnicastLocallyAssignedMacAddress(mac_address));
-
- // All further calls should return the same MAC address.
- ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress());
- ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress());
-}
-
-TEST_F(WifiIfaceUtilTest, IfaceEventHandlers_SetMacAddress) {
- std::array<uint8_t, 6> mac_address = {};
- std::copy(std::begin(kMacAddress), std::end(kMacAddress), std::begin(mac_address));
- EXPECT_CALL(*iface_tool_, SetMacAddress(testing::_, testing::_))
- .WillRepeatedly(testing::Return(true));
- EXPECT_CALL(*iface_tool_, SetUpState(testing::_, testing::_))
- .WillRepeatedly(testing::Return(true));
-
- // Register for iface state toggle events.
- bool callback_invoked = false;
- iface_util::IfaceEventHandlers event_handlers = {};
- event_handlers.on_state_toggle_off_on =
- [&callback_invoked](const std::string& /* iface_name */) { callback_invoked = true; };
- iface_util_->registerIfaceEventHandlers(kIfaceName, event_handlers);
- // Invoke setMacAddress and ensure that the cb is invoked.
- ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address));
- ASSERT_TRUE(callback_invoked);
-
- // Unregister for iface state toggle events.
- callback_invoked = false;
- iface_util_->unregisterIfaceEventHandlers(kIfaceName);
- // Invoke setMacAddress and ensure that the cb is not invoked.
- ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address));
- ASSERT_FALSE(callback_invoked);
-}
-} // namespace iface_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/1.6/default/tests/wifi_nan_iface_unit_tests.cpp
deleted file mode 100644
index 8a5ddcd..0000000
--- a/wifi/1.6/default/tests/wifi_nan_iface_unit_tests.cpp
+++ /dev/null
@@ -1,138 +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 <android-base/logging.h>
-#include <android-base/macros.h>
-#include <cutils/properties.h>
-#include <gmock/gmock.h>
-
-#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
-#include "wifi_nan_iface.h"
-
-#include "mock_interface_tool.h"
-#include "mock_wifi_feature_flags.h"
-#include "mock_wifi_iface_util.h"
-#include "mock_wifi_legacy_hal.h"
-
-using testing::NiceMock;
-using testing::Return;
-using testing::Test;
-
-namespace {
-constexpr char kIfaceName[] = "mockWlan0";
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-
-using android::hardware::wifi::V1_2::NanDataPathConfirmInd;
-
-bool CaptureIfaceEventHandlers(const std::string& /* iface_name*/,
- iface_util::IfaceEventHandlers in_iface_event_handlers,
- iface_util::IfaceEventHandlers* out_iface_event_handlers) {
- *out_iface_event_handlers = in_iface_event_handlers;
- return true;
-}
-
-class MockNanIfaceEventCallback : public V1_5::IWifiNanIfaceEventCallback {
- public:
- MockNanIfaceEventCallback() = default;
-
- MOCK_METHOD3(notifyCapabilitiesResponse,
- Return<void>(uint16_t, const WifiNanStatus&,
- const android::hardware::wifi::V1_0::NanCapabilities&));
- MOCK_METHOD2(notifyEnableResponse, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD2(notifyConfigResponse, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD2(notifyDisableResponse, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD3(notifyStartPublishResponse, Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
- MOCK_METHOD2(notifyStopPublishResponse, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD3(notifyStartSubscribeResponse,
- Return<void>(uint16_t, const WifiNanStatus&, uint8_t));
- MOCK_METHOD2(notifyStopSubscribeResponse, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD2(notifyTransmitFollowupResponse, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD2(notifyCreateDataInterfaceResponse, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD2(notifyDeleteDataInterfaceResponse, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD3(notifyInitiateDataPathResponse,
- Return<void>(uint16_t, const WifiNanStatus&, uint32_t));
- MOCK_METHOD2(notifyRespondToDataPathIndicationResponse,
- Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD2(notifyTerminateDataPathResponse, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD1(eventClusterEvent, Return<void>(const NanClusterEventInd&));
- MOCK_METHOD1(eventDisabled, Return<void>(const WifiNanStatus&));
- MOCK_METHOD2(eventPublishTerminated, Return<void>(uint8_t, const WifiNanStatus&));
- MOCK_METHOD2(eventSubscribeTerminated, Return<void>(uint8_t, const WifiNanStatus&));
- MOCK_METHOD1(eventMatch, Return<void>(const V1_0::NanMatchInd&));
- MOCK_METHOD1(eventMatch_1_6, Return<void>(const NanMatchInd&));
- MOCK_METHOD2(eventMatchExpired, Return<void>(uint8_t, uint32_t));
- MOCK_METHOD1(eventFollowupReceived, Return<void>(const NanFollowupReceivedInd&));
- MOCK_METHOD2(eventTransmitFollowup, Return<void>(uint16_t, const WifiNanStatus&));
- MOCK_METHOD1(eventDataPathRequest, Return<void>(const NanDataPathRequestInd&));
- MOCK_METHOD1(eventDataPathConfirm,
- Return<void>(const android::hardware::wifi::V1_0::NanDataPathConfirmInd&));
- MOCK_METHOD1(eventDataPathTerminated, Return<void>(uint32_t));
- MOCK_METHOD1(eventDataPathConfirm_1_2,
- Return<void>(const android::hardware::wifi::V1_2::NanDataPathConfirmInd&));
- MOCK_METHOD1(eventDataPathConfirm_1_6, Return<void>(const NanDataPathConfirmInd&));
- MOCK_METHOD1(eventDataPathScheduleUpdate,
- Return<void>(const android::hardware::wifi::V1_2::NanDataPathScheduleUpdateInd&));
- MOCK_METHOD1(eventDataPathScheduleUpdate_1_6,
- Return<void>(const NanDataPathScheduleUpdateInd&));
- MOCK_METHOD3(notifyCapabilitiesResponse_1_5,
- Return<void>(uint16_t, const WifiNanStatus&, const V1_5::NanCapabilities&));
-};
-
-class WifiNanIfaceTest : public Test {
- protected:
- legacy_hal::wifi_hal_fn fake_func_table_;
- std::shared_ptr<NiceMock<wifi_system::MockInterfaceTool>> iface_tool_{
- new NiceMock<wifi_system::MockInterfaceTool>};
- std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
- new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_, fake_func_table_, true)};
- std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
- new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_, legacy_hal_)};
-};
-
-TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) {
- iface_util::IfaceEventHandlers captured_iface_event_handlers = {};
- EXPECT_CALL(*legacy_hal_, nanRegisterCallbackHandlers(testing::_, testing::_))
- .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
- EXPECT_CALL(*iface_util_, registerIfaceEventHandlers(testing::_, testing::_))
- .WillOnce(testing::Invoke(bind(CaptureIfaceEventHandlers, std::placeholders::_1,
- std::placeholders::_2, &captured_iface_event_handlers)));
- sp<WifiNanIface> nan_iface = new WifiNanIface(kIfaceName, false, legacy_hal_, iface_util_);
-
- // Register a mock nan event callback.
- sp<NiceMock<MockNanIfaceEventCallback>> mock_event_callback{
- new NiceMock<MockNanIfaceEventCallback>};
- nan_iface->registerEventCallback(mock_event_callback, [](const WifiStatus& status) {
- ASSERT_EQ(WifiStatusCode::SUCCESS, status.code);
- });
- // Ensure that the eventDisabled() function in mock callback will be
- // invoked.
- WifiNanStatus expected_nan_status = {NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
- EXPECT_CALL(*mock_event_callback, eventDisabled(expected_nan_status)).Times(1);
-
- // Trigger the iface state toggle callback.
- captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName);
-}
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi.cpp b/wifi/1.6/default/wifi.cpp
deleted file mode 100644
index c302ce2..0000000
--- a/wifi/1.6/default/wifi.cpp
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "wifi.h"
-#include "wifi_status_util.h"
-
-namespace {
-// Starting Chip ID, will be assigned to primary chip
-static constexpr android::hardware::wifi::V1_0::ChipId kPrimaryChipId = 0;
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-using hidl_return_util::validateAndCallWithLock;
-
-Wifi::Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
- const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
- const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
- const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
- : iface_tool_(iface_tool),
- legacy_hal_factory_(legacy_hal_factory),
- mode_controller_(mode_controller),
- feature_flags_(feature_flags),
- run_state_(RunState::STOPPED) {}
-
-bool Wifi::isValid() {
- // This object is always valid.
- return true;
-}
-
-Return<void> Wifi::registerEventCallback(const sp<V1_0::IWifiEventCallback>& event_callback,
- registerEventCallback_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
- &Wifi::registerEventCallbackInternal, hidl_status_cb, event_callback);
-}
-
-Return<void> Wifi::registerEventCallback_1_5(const sp<V1_5::IWifiEventCallback>& event_callback,
- registerEventCallback_1_5_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
- &Wifi::registerEventCallbackInternal_1_5, hidl_status_cb,
- event_callback);
-}
-
-Return<bool> Wifi::isStarted() {
- return run_state_ != RunState::STOPPED;
-}
-
-Return<void> Wifi::start(start_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal,
- hidl_status_cb);
-}
-
-Return<void> Wifi::stop(stop_cb hidl_status_cb) {
- return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal,
- hidl_status_cb);
-}
-
-Return<void> Wifi::getChipIds(getChipIds_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipIdsInternal,
- hidl_status_cb);
-}
-
-Return<void> Wifi::getChip(ChipId chip_id, getChip_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipInternal,
- hidl_status_cb, chip_id);
-}
-
-Return<void> Wifi::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
- LOG(INFO) << "-----------Debug is called----------------";
- if (chips_.size() == 0) {
- return Void();
- }
-
- for (sp<WifiChip> chip : chips_) {
- if (!chip.get()) continue;
-
- chip->debug(handle, {});
- }
- return Void();
-}
-
-WifiStatus Wifi::registerEventCallbackInternal(
- const sp<V1_0::IWifiEventCallback>& event_callback __unused) {
- // Deprecated support for this callback.
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus Wifi::registerEventCallbackInternal_1_5(
- const sp<V1_5::IWifiEventCallback>& event_callback) {
- if (!event_cb_handler_.addCallback(event_callback)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus Wifi::startInternal() {
- if (run_state_ == RunState::STARTED) {
- return createWifiStatus(WifiStatusCode::SUCCESS);
- } else if (run_state_ == RunState::STOPPING) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
- }
- WifiStatus wifi_status = initializeModeControllerAndLegacyHal();
- if (wifi_status.code == WifiStatusCode::SUCCESS) {
- // Register the callback for subsystem restart
- const auto& on_subsystem_restart_callback = [this](const std::string& error) {
- 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 onSubsystemRestart callback";
- } else {
- LOG(INFO) << "Succeeded to invoke onSubsystemRestart "
- "callback";
- }
- }
- };
-
- // Create the chip instance once the HAL is started.
- android::hardware::wifi::V1_0::ChipId chipId = kPrimaryChipId;
- for (auto& hal : legacy_hals_) {
- chips_.push_back(
- new WifiChip(chipId, chipId == kPrimaryChipId, hal, mode_controller_,
- std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal),
- feature_flags_, on_subsystem_restart_callback));
- chipId++;
- }
- run_state_ = RunState::STARTED;
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onStart().isOk()) {
- LOG(ERROR) << "Failed to invoke onStart callback";
- };
- }
- LOG(INFO) << "Wifi HAL started";
- } else {
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onFailure(wifi_status).isOk()) {
- LOG(ERROR) << "Failed to invoke onFailure callback";
- }
- }
- LOG(ERROR) << "Wifi HAL start failed";
- // Clear the event callback objects since the HAL start failed.
- event_cb_handler_.invalidate();
- }
- return wifi_status;
-}
-
-WifiStatus Wifi::stopInternal(
- /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
- if (run_state_ == RunState::STOPPED) {
- return createWifiStatus(WifiStatusCode::SUCCESS);
- } else if (run_state_ == RunState::STOPPING) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
- }
- // Clear the chip object and its child objects since the HAL is now
- // stopped.
- for (auto& chip : chips_) {
- if (chip.get()) {
- chip->invalidate();
- chip.clear();
- }
- }
- chips_.clear();
- WifiStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
- if (wifi_status.code == WifiStatusCode::SUCCESS) {
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onStop().isOk()) {
- LOG(ERROR) << "Failed to invoke onStop callback";
- };
- }
- LOG(INFO) << "Wifi HAL stopped";
- } else {
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onFailure(wifi_status).isOk()) {
- LOG(ERROR) << "Failed to invoke onFailure callback";
- }
- }
- LOG(ERROR) << "Wifi HAL stop failed";
- }
- // Clear the event callback objects since the HAL is now stopped.
- event_cb_handler_.invalidate();
- return wifi_status;
-}
-
-std::pair<WifiStatus, std::vector<ChipId>> Wifi::getChipIdsInternal() {
- std::vector<ChipId> chip_ids;
-
- for (auto& chip : chips_) {
- ChipId chip_id = getChipIdFromWifiChip(chip);
- if (chip_id != UINT32_MAX) chip_ids.emplace_back(chip_id);
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), std::move(chip_ids)};
-}
-
-std::pair<WifiStatus, sp<V1_4::IWifiChip>> Wifi::getChipInternal(ChipId chip_id) {
- for (auto& chip : chips_) {
- ChipId cand_id = getChipIdFromWifiChip(chip);
- if ((cand_id != UINT32_MAX) && (cand_id == chip_id))
- return {createWifiStatus(WifiStatusCode::SUCCESS), chip};
- }
-
- return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
-}
-
-WifiStatus Wifi::initializeModeControllerAndLegacyHal() {
- if (!mode_controller_->initialize()) {
- LOG(ERROR) << "Failed to initialize firmware mode controller";
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
-
- legacy_hals_ = legacy_hal_factory_->getHals();
- if (legacy_hals_.empty()) return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- int index = 0; // for failure log
- for (auto& hal : legacy_hals_) {
- legacy_hal::wifi_error legacy_status = hal->initialize();
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- // Currently WifiLegacyHal::initialize does not allocate extra mem,
- // only initializes the function table. If this changes, need to
- // implement WifiLegacyHal::deinitialize and deinitalize the
- // HALs already initialized
- LOG(ERROR) << "Failed to initialize legacy HAL index: " << index
- << " error: " << legacyErrorToString(legacy_status);
- return createWifiStatusFromLegacyError(legacy_status);
- }
- index++;
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus Wifi::stopLegacyHalAndDeinitializeModeController(
- /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
- legacy_hal::wifi_error legacy_status = legacy_hal::WIFI_SUCCESS;
- int index = 0;
-
- run_state_ = RunState::STOPPING;
- for (auto& hal : legacy_hals_) {
- legacy_hal::wifi_error tmp = hal->stop(lock, [&]() {});
- if (tmp != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to stop legacy HAL index: " << index
- << " error: " << legacyErrorToString(legacy_status);
- legacy_status = tmp;
- }
- index++;
- }
- run_state_ = RunState::STOPPED;
-
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "One or more legacy HALs failed to stop";
- return createWifiStatusFromLegacyError(legacy_status);
- }
- if (!mode_controller_->deinitialize()) {
- LOG(ERROR) << "Failed to deinitialize firmware mode controller";
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-ChipId Wifi::getChipIdFromWifiChip(sp<WifiChip>& chip) {
- ChipId chip_id = UINT32_MAX;
- if (chip.get()) {
- chip->getId([&](WifiStatus status, uint32_t id) {
- if (status.code == WifiStatusCode::SUCCESS) {
- chip_id = id;
- }
- });
- }
-
- return chip_id;
-}
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi.h b/wifi/1.6/default/wifi.h
deleted file mode 100644
index 435358e..0000000
--- a/wifi/1.6/default/wifi.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_H_
-#define WIFI_H_
-
-// HACK: NAN is a macro defined in math.h, which can be included in various
-// headers. This wifi HAL uses an enum called NAN, which does not compile when
-// the macro is defined. Undefine NAN to work around it.
-#undef NAN
-#include <android/hardware/wifi/1.6/IWifi.h>
-
-#include <android-base/macros.h>
-#include <utils/Looper.h>
-#include <functional>
-
-#include "hidl_callback_util.h"
-#include "wifi_chip.h"
-#include "wifi_feature_flags.h"
-#include "wifi_legacy_hal.h"
-#include "wifi_legacy_hal_factory.h"
-#include "wifi_mode_controller.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-
-/**
- * Root HIDL interface object used to control the Wifi HAL.
- */
-class Wifi : public V1_6::IWifi {
- public:
- Wifi(const std::shared_ptr<wifi_system::InterfaceTool> iface_tool,
- const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
- const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
- const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags);
-
- bool isValid();
-
- // HIDL methods exposed.
- Return<void> registerEventCallback(const sp<V1_0::IWifiEventCallback>& event_callback,
- registerEventCallback_cb hidl_status_cb) override;
- Return<void> registerEventCallback_1_5(const sp<V1_5::IWifiEventCallback>& event_callback,
- registerEventCallback_1_5_cb hidl_status_cb) override;
- Return<bool> isStarted() override;
- Return<void> start(start_cb hidl_status_cb) override;
- Return<void> stop(stop_cb hidl_status_cb) override;
- Return<void> getChipIds(getChipIds_cb hidl_status_cb) override;
- Return<void> getChip(ChipId chip_id, getChip_cb hidl_status_cb) override;
- Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override;
-
- private:
- enum class RunState { STOPPED, STARTED, STOPPING };
-
- // Corresponding worker functions for the HIDL methods.
- WifiStatus registerEventCallbackInternal(
- const sp<V1_0::IWifiEventCallback>& event_callback __unused);
- WifiStatus registerEventCallbackInternal_1_5(
- const sp<V1_5::IWifiEventCallback>& event_callback);
- WifiStatus startInternal();
- WifiStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
- std::pair<WifiStatus, std::vector<ChipId>> getChipIdsInternal();
- std::pair<WifiStatus, sp<V1_4::IWifiChip>> getChipInternal(ChipId chip_id);
-
- WifiStatus initializeModeControllerAndLegacyHal();
- WifiStatus stopLegacyHalAndDeinitializeModeController(
- std::unique_lock<std::recursive_mutex>* lock);
- ChipId getChipIdFromWifiChip(sp<WifiChip>& chip);
-
- // Instance is created in this root level |IWifi| HIDL interface object
- // and shared with all the child HIDL interface objects.
- std::shared_ptr<wifi_system::InterfaceTool> iface_tool_;
- std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory_;
- std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
- std::vector<std::shared_ptr<legacy_hal::WifiLegacyHal>> legacy_hals_;
- std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
- RunState run_state_;
- std::vector<sp<WifiChip>> chips_;
- hidl_callback_util::HidlCallbackHandler<V1_5::IWifiEventCallback> event_cb_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(Wifi);
-};
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_H_
diff --git a/wifi/1.6/default/wifi_ap_iface.cpp b/wifi/1.6/default/wifi_ap_iface.cpp
deleted file mode 100644
index b2957db..0000000
--- a/wifi/1.6/default/wifi_ap_iface.cpp
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_ap_iface.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiApIface::WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
- const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
- : ifname_(ifname),
- instances_(instances),
- legacy_hal_(legacy_hal),
- iface_util_(iface_util),
- is_valid_(true) {}
-
-void WifiApIface::invalidate() {
- legacy_hal_.reset();
- is_valid_ = false;
-}
-
-bool WifiApIface::isValid() {
- return is_valid_;
-}
-
-std::string WifiApIface::getName() {
- return ifname_;
-}
-
-void WifiApIface::removeInstance(std::string instance) {
- instances_.erase(std::remove(instances_.begin(), instances_.end(), instance), instances_.end());
-}
-
-Return<void> WifiApIface::getName(getName_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiApIface::getNameInternal, hidl_status_cb);
-}
-
-Return<void> WifiApIface::getType(getType_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiApIface::getTypeInternal, hidl_status_cb);
-}
-
-Return<void> WifiApIface::setCountryCode(const hidl_array<int8_t, 2>& code,
- setCountryCode_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiApIface::setCountryCodeInternal, hidl_status_cb, code);
-}
-
-Return<void> WifiApIface::getValidFrequenciesForBand(V1_0::WifiBand band,
- getValidFrequenciesForBand_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiApIface::getValidFrequenciesForBandInternal, hidl_status_cb, band);
-}
-
-Return<void> WifiApIface::setMacAddress(const hidl_array<uint8_t, 6>& mac,
- setMacAddress_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiApIface::setMacAddressInternal, hidl_status_cb, mac);
-}
-
-Return<void> WifiApIface::getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiApIface::getFactoryMacAddressInternal, hidl_status_cb,
- instances_.size() > 0 ? instances_[0] : ifname_);
-}
-
-Return<void> WifiApIface::resetToFactoryMacAddress(resetToFactoryMacAddress_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiApIface::resetToFactoryMacAddressInternal, hidl_status_cb);
-}
-
-Return<void> WifiApIface::getBridgedInstances(getBridgedInstances_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiApIface::getBridgedInstancesInternal, hidl_status_cb);
-}
-
-std::pair<WifiStatus, std::string> WifiApIface::getNameInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
-}
-
-std::pair<WifiStatus, IfaceType> WifiApIface::getTypeInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::AP};
-}
-
-WifiStatus WifiApIface::setCountryCodeInternal(const std::array<int8_t, 2>& code) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode(
- instances_.size() > 0 ? instances_[0] : ifname_, code);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-WifiApIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) {
- static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch");
- legacy_hal::wifi_error legacy_status;
- std::vector<uint32_t> valid_frequencies;
- std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand(
- instances_.size() > 0 ? instances_[0] : ifname_,
- hidl_struct_util::convertHidlWifiBandToLegacy(band));
- return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
-}
-
-WifiStatus WifiApIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) {
- // Support random MAC up to 2 interfaces
- if (instances_.size() == 2) {
- int rbyte = 1;
- for (auto const& intf : instances_) {
- std::array<uint8_t, 6> rmac = mac;
- // reverse the bits to avoid collision
- rmac[rbyte] = 0xff - rmac[rbyte];
- if (!iface_util_.lock()->setMacAddress(intf, rmac)) {
- LOG(INFO) << "Failed to set random mac address on " << intf;
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- rbyte++;
- }
- }
- // It also needs to set mac address for bridged interface, otherwise the mac
- // address of bridged interface will be changed after one of instance
- // down.
- if (!iface_util_.lock()->setMacAddress(ifname_, mac)) {
- LOG(ERROR) << "Fail to config MAC for interface " << ifname_;
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, std::array<uint8_t, 6>> WifiApIface::getFactoryMacAddressInternal(
- const std::string& ifaceName) {
- std::array<uint8_t, 6> mac = iface_util_.lock()->getFactoryMacAddress(ifaceName);
- if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
-}
-
-WifiStatus WifiApIface::resetToFactoryMacAddressInternal() {
- std::pair<WifiStatus, std::array<uint8_t, 6>> getMacResult;
- if (instances_.size() == 2) {
- for (auto const& intf : instances_) {
- getMacResult = getFactoryMacAddressInternal(intf);
- LOG(DEBUG) << "Reset MAC to factory MAC on " << intf;
- if (getMacResult.first.code != WifiStatusCode::SUCCESS ||
- !iface_util_.lock()->setMacAddress(intf, getMacResult.second)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- }
- // It needs to set mac address for bridged interface, otherwise the mac
- // address of the bridged interface will be changed after one of the
- // instance down. Thus we are generating a random MAC address for the
- // bridged interface even if we got the request to reset the Factory
- // MAC. Since the bridged interface is an internal interface for the
- // operation of bpf and others networking operation.
- if (!iface_util_.lock()->setMacAddress(ifname_,
- iface_util_.lock()->createRandomMacAddress())) {
- LOG(ERROR) << "Fail to config MAC for bridged interface " << ifname_;
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- } else {
- getMacResult = getFactoryMacAddressInternal(ifname_);
- LOG(DEBUG) << "Reset MAC to factory MAC on " << ifname_;
- if (getMacResult.first.code != WifiStatusCode::SUCCESS ||
- !iface_util_.lock()->setMacAddress(ifname_, getMacResult.second)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, std::vector<hidl_string>> WifiApIface::getBridgedInstancesInternal() {
- std::vector<hidl_string> instances;
- for (const auto& instance_name : instances_) {
- instances.push_back(instance_name);
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), instances};
-}
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_ap_iface.h b/wifi/1.6/default/wifi_ap_iface.h
deleted file mode 100644
index d1c0642..0000000
--- a/wifi/1.6/default/wifi_ap_iface.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_AP_IFACE_H_
-#define WIFI_AP_IFACE_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.5/IWifiApIface.h>
-
-#include "wifi_iface_util.h"
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * HIDL interface object used to control a AP Iface instance.
- */
-class WifiApIface : public V1_5::IWifiApIface {
- public:
- WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
- const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
- // Refer to |WifiChip::invalidate()|.
- void invalidate();
- bool isValid();
- std::string getName();
- void removeInstance(std::string instance);
-
- // HIDL methods exposed.
- Return<void> getName(getName_cb hidl_status_cb) override;
- Return<void> getType(getType_cb hidl_status_cb) override;
- Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
- setCountryCode_cb hidl_status_cb) override;
- Return<void> getValidFrequenciesForBand(V1_0::WifiBand band,
- getValidFrequenciesForBand_cb hidl_status_cb) override;
- Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac,
- setMacAddress_cb hidl_status_cb) override;
- Return<void> getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) override;
- Return<void> resetToFactoryMacAddress(resetToFactoryMacAddress_cb hidl_status_cb) override;
-
- Return<void> getBridgedInstances(getBridgedInstances_cb hidl_status_cb) override;
-
- private:
- // Corresponding worker functions for the HIDL methods.
- std::pair<WifiStatus, std::string> getNameInternal();
- std::pair<WifiStatus, IfaceType> getTypeInternal();
- WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
- std::pair<WifiStatus, std::vector<WifiChannelInMhz>> getValidFrequenciesForBandInternal(
- V1_0::WifiBand band);
- WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
- std::pair<WifiStatus, std::array<uint8_t, 6>> getFactoryMacAddressInternal(
- const std::string& ifaceName);
- WifiStatus resetToFactoryMacAddressInternal();
- std::pair<WifiStatus, std::vector<hidl_string>> getBridgedInstancesInternal();
-
- std::string ifname_;
- std::vector<std::string> instances_;
- std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
- std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
- bool is_valid_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiApIface);
-};
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_AP_IFACE_H_
diff --git a/wifi/1.6/default/wifi_chip.cpp b/wifi/1.6/default/wifi_chip.cpp
deleted file mode 100644
index 920beb8..0000000
--- a/wifi/1.6/default/wifi_chip.cpp
+++ /dev/null
@@ -1,2062 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <fcntl.h>
-
-#include <android-base/logging.h>
-#include <android-base/unique_fd.h>
-#include <cutils/properties.h>
-#include <net/if.h>
-#include <sys/stat.h>
-#include <sys/sysmacros.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#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;
-using android::hardware::hidl_string;
-using android::hardware::hidl_vec;
-using android::hardware::wifi::V1_0::ChipModeId;
-using android::hardware::wifi::V1_0::IfaceType;
-using android::hardware::wifi::V1_0::IWifiChip;
-
-constexpr char kCpioMagic[] = "070701";
-constexpr size_t kMaxBufferSizeBytes = 1024 * 1024 * 3;
-constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10;
-constexpr uint32_t kMaxRingBufferFileNum = 20;
-constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
-constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface";
-constexpr char kNoActiveWlanIfaceNamePropertyValue[] = "";
-constexpr unsigned kMaxWlanIfaces = 5;
-constexpr char kApBridgeIfacePrefix[] = "ap_br_";
-
-template <typename Iface>
-void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
- iface->invalidate();
- ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface), ifaces.end());
-}
-
-template <typename Iface>
-void invalidateAndClearAll(std::vector<sp<Iface>>& ifaces) {
- for (const auto& iface : ifaces) {
- iface->invalidate();
- }
- ifaces.clear();
-}
-
-template <typename Iface>
-std::vector<hidl_string> getNames(std::vector<sp<Iface>>& ifaces) {
- std::vector<hidl_string> names;
- for (const auto& iface : ifaces) {
- names.emplace_back(iface->getName());
- }
- return names;
-}
-
-template <typename Iface>
-sp<Iface> findUsingName(std::vector<sp<Iface>>& ifaces, const std::string& name) {
- std::vector<hidl_string> names;
- for (const auto& iface : ifaces) {
- if (name == iface->getName()) {
- return iface;
- }
- }
- return nullptr;
-}
-
-std::string getWlanIfaceName(unsigned idx) {
- if (idx >= kMaxWlanIfaces) {
- CHECK(false) << "Requested interface beyond wlan" << kMaxWlanIfaces;
- return {};
- }
-
- std::array<char, PROPERTY_VALUE_MAX> buffer;
- if (idx == 0 || idx == 1) {
- const char* altPropName = (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface";
- auto res = property_get(altPropName, buffer.data(), nullptr);
- if (res > 0) return buffer.data();
- }
- std::string propName = "wifi.interface." + std::to_string(idx);
- auto res = property_get(propName.c_str(), buffer.data(), nullptr);
- if (res > 0) return buffer.data();
-
- return "wlan" + std::to_string(idx);
-}
-
-// Returns the dedicated iface name if defined.
-// Returns two ifaces in bridged mode.
-std::vector<std::string> getPredefinedApIfaceNames(bool is_bridged) {
- std::vector<std::string> ifnames;
- std::array<char, PROPERTY_VALUE_MAX> buffer;
- buffer.fill(0);
- if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) == 0) {
- return ifnames;
- }
- ifnames.push_back(buffer.data());
- if (is_bridged) {
- buffer.fill(0);
- if (property_get("ro.vendor.wifi.sap.concurrent.iface", buffer.data(), nullptr) == 0) {
- return ifnames;
- }
- ifnames.push_back(buffer.data());
- }
- return ifnames;
-}
-
-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 */
- strlcpy(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();
-}
-
-// Returns the dedicated iface name if one is defined.
-std::string getPredefinedNanIfaceName() {
- std::array<char, PROPERTY_VALUE_MAX> buffer;
- if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) {
- return {};
- }
- return buffer.data();
-}
-
-void setActiveWlanIfaceNameProperty(const std::string& ifname) {
- auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data());
- if (res != 0) {
- PLOG(ERROR) << "Failed to set active wlan iface name property";
- }
-}
-
-// delete files that meet either conditions:
-// 1. older than a predefined time in the wifi tombstone dir.
-// 2. Files in excess to a predefined amount, starting from the oldest ones
-bool removeOldFilesInternal() {
- time_t now = time(0);
- const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds;
- std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(kTombstoneFolderPath), closedir);
- if (!dir_dump) {
- PLOG(ERROR) << "Failed to open directory";
- return false;
- }
- struct dirent* dp;
- bool success = true;
- std::list<std::pair<const time_t, std::string>> valid_files;
- while ((dp = readdir(dir_dump.get()))) {
- if (dp->d_type != DT_REG) {
- continue;
- }
- std::string cur_file_name(dp->d_name);
- struct stat cur_file_stat;
- std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
- if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) {
- PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
- success = false;
- continue;
- }
- const time_t cur_file_time = cur_file_stat.st_mtime;
- valid_files.push_back(std::pair<const time_t, std::string>(cur_file_time, cur_file_path));
- }
- valid_files.sort(); // sort the list of files by last modified time from
- // small to big.
- uint32_t cur_file_count = valid_files.size();
- for (auto cur_file : valid_files) {
- if (cur_file_count > kMaxRingBufferFileNum || cur_file.first < delete_files_before) {
- if (unlink(cur_file.second.c_str()) != 0) {
- PLOG(ERROR) << "Error deleting file";
- success = false;
- }
- cur_file_count--;
- } else {
- break;
- }
- }
- return success;
-}
-
-// Helper function for |cpioArchiveFilesInDir|
-bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, size_t file_name_len) {
- const int buf_size = 32 * 1024;
- std::array<char, buf_size> read_buf;
- ssize_t llen = snprintf(
- read_buf.data(), buf_size, "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
- kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid, st.st_gid,
- static_cast<int>(st.st_nlink), static_cast<int>(st.st_mtime),
- static_cast<int>(st.st_size), major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
- minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
- if (write(out_fd, read_buf.data(), llen < buf_size ? llen : buf_size - 1) == -1) {
- PLOG(ERROR) << "Error writing cpio header to file " << file_name;
- return false;
- }
- if (write(out_fd, file_name, file_name_len) == -1) {
- PLOG(ERROR) << "Error writing filename to file " << file_name;
- return false;
- }
-
- // NUL Pad header up to 4 multiple bytes.
- llen = (llen + file_name_len) % 4;
- if (llen != 0) {
- const uint32_t zero = 0;
- if (write(out_fd, &zero, 4 - llen) == -1) {
- PLOG(ERROR) << "Error padding 0s to file " << file_name;
- return false;
- }
- }
- return true;
-}
-
-// Helper function for |cpioArchiveFilesInDir|
-size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) {
- // writing content of file
- std::array<char, 32 * 1024> read_buf;
- ssize_t llen = st.st_size;
- size_t n_error = 0;
- while (llen > 0) {
- ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
- if (bytes_read == -1) {
- PLOG(ERROR) << "Error reading file";
- return ++n_error;
- }
- llen -= bytes_read;
- if (write(out_fd, read_buf.data(), bytes_read) == -1) {
- PLOG(ERROR) << "Error writing data to file";
- return ++n_error;
- }
- if (bytes_read == 0) { // this should never happen, but just in case
- // to unstuck from while loop
- PLOG(ERROR) << "Unexpected read result";
- n_error++;
- break;
- }
- }
- llen = st.st_size % 4;
- if (llen != 0) {
- const uint32_t zero = 0;
- if (write(out_fd, &zero, 4 - llen) == -1) {
- PLOG(ERROR) << "Error padding 0s to file";
- return ++n_error;
- }
- }
- return n_error;
-}
-
-// Helper function for |cpioArchiveFilesInDir|
-bool cpioWriteFileTrailer(int out_fd) {
- const int buf_size = 4096;
- std::array<char, buf_size> read_buf;
- read_buf.fill(0);
- ssize_t llen = snprintf(read_buf.data(), 4096, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0);
- if (write(out_fd, read_buf.data(), (llen < buf_size ? llen : buf_size - 1) + 4) == -1) {
- PLOG(ERROR) << "Error writing trailing bytes";
- return false;
- }
- return true;
-}
-
-// Archives all files in |input_dir| and writes result into |out_fd|
-// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive"
-// portion
-size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
- struct dirent* dp;
- size_t n_error = 0;
- std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir), closedir);
- if (!dir_dump) {
- PLOG(ERROR) << "Failed to open directory";
- return ++n_error;
- }
- while ((dp = readdir(dir_dump.get()))) {
- if (dp->d_type != DT_REG) {
- continue;
- }
- std::string cur_file_name(dp->d_name);
- struct stat st;
- const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
- if (stat(cur_file_path.c_str(), &st) == -1) {
- PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
- n_error++;
- continue;
- }
- const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
- if (fd_read == -1) {
- PLOG(ERROR) << "Failed to open file " << cur_file_path;
- n_error++;
- continue;
- }
- std::string file_name_with_last_modified_time =
- cur_file_name + "-" + std::to_string(st.st_mtime);
- // string.size() does not include the null terminator. The cpio FreeBSD
- // file header expects the null character to be included in the length.
- const size_t file_name_len = file_name_with_last_modified_time.size() + 1;
- unique_fd file_auto_closer(fd_read);
- if (!cpioWriteHeader(out_fd, st, file_name_with_last_modified_time.c_str(),
- file_name_len)) {
- return ++n_error;
- }
- size_t write_error = cpioWriteFileContent(fd_read, out_fd, st);
- if (write_error) {
- return n_error + write_error;
- }
- }
- if (!cpioWriteFileTrailer(out_fd)) {
- return ++n_error;
- }
- return n_error;
-}
-
-// Helper function to create a non-const char*.
-std::vector<char> makeCharVec(const std::string& str) {
- std::vector<char> vec(str.size() + 1);
- vec.assign(str.begin(), str.end());
- vec.push_back('\0');
- return vec;
-}
-
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-using hidl_return_util::validateAndCallWithLock;
-
-WifiChip::WifiChip(ChipId chip_id, bool is_primary,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
- const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
- const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
- const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
- const std::function<void(const std::string&)>& handler)
- : chip_id_(chip_id),
- legacy_hal_(legacy_hal),
- mode_controller_(mode_controller),
- iface_util_(iface_util),
- is_valid_(true),
- current_mode_id_(feature_flags::chip_mode_ids::kInvalid),
- modes_(feature_flags.lock()->getChipModes(is_primary)),
- debug_ring_buffer_cb_registered_(false),
- subsystemCallbackHandler_(handler) {
- setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
-}
-
-void WifiChip::invalidate() {
- if (!writeRingbufferFilesInternal()) {
- LOG(ERROR) << "Error writing files to flash";
- }
- invalidateAndRemoveAllIfaces();
- setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
- legacy_hal_.reset();
- event_cb_handler_.invalidate();
- is_valid_ = false;
-}
-
-bool WifiChip::isValid() {
- return is_valid_;
-}
-
-std::set<sp<V1_4::IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
- return event_cb_handler_.getCallbacks();
-}
-
-Return<void> WifiChip::getId(getId_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::getIdInternal,
- hidl_status_cb);
-}
-
-// Deprecated support for this callback
-Return<void> WifiChip::registerEventCallback(const sp<V1_0::IWifiChipEventCallback>& event_callback,
- registerEventCallback_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::registerEventCallbackInternal, hidl_status_cb,
- event_callback);
-}
-
-Return<void> WifiChip::getCapabilities(getCapabilities_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getCapabilitiesInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getAvailableModes(getAvailableModes_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getAvailableModesInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) {
- return validateAndCallWithLock(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::configureChipInternal, hidl_status_cb, mode_id);
-}
-
-Return<void> WifiChip::getMode(getMode_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getModeInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::requestChipDebugInfo(requestChipDebugInfo_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::requestChipDebugInfoInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::requestDriverDebugDump(requestDriverDebugDump_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::requestDriverDebugDumpInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::requestFirmwareDebugDump(requestFirmwareDebugDump_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::requestFirmwareDebugDumpInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::createApIface(createApIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::createApIfaceInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::createBridgedApIface(createBridgedApIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::createBridgedApIfaceInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getApIfaceNamesInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getApIface(const hidl_string& ifname, getApIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getApIfaceInternal, hidl_status_cb, ifname);
-}
-
-Return<void> WifiChip::removeApIface(const hidl_string& ifname, removeApIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::removeApIfaceInternal, hidl_status_cb, ifname);
-}
-
-Return<void> WifiChip::removeIfaceInstanceFromBridgedApIface(
- const hidl_string& ifname, const hidl_string& ifInstanceName,
- removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal, hidl_status_cb,
- ifname, ifInstanceName);
-}
-
-Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::createNanIfaceInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getNanIfaceNamesInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getNanIface(const hidl_string& ifname, getNanIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getNanIfaceInternal, hidl_status_cb, ifname);
-}
-
-Return<void> WifiChip::removeNanIface(const hidl_string& ifname, removeNanIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::removeNanIfaceInternal, hidl_status_cb, ifname);
-}
-
-Return<void> WifiChip::createP2pIface(createP2pIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::createP2pIfaceInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getP2pIfaceNamesInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getP2pIface(const hidl_string& ifname, getP2pIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getP2pIfaceInternal, hidl_status_cb, ifname);
-}
-
-Return<void> WifiChip::removeP2pIface(const hidl_string& ifname, removeP2pIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::removeP2pIfaceInternal, hidl_status_cb, ifname);
-}
-
-Return<void> WifiChip::createStaIface(createStaIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::createStaIfaceInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getStaIfaceNamesInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getStaIface(const hidl_string& ifname, getStaIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getStaIfaceInternal, hidl_status_cb, ifname);
-}
-
-Return<void> WifiChip::removeStaIface(const hidl_string& ifname, removeStaIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::removeStaIfaceInternal, hidl_status_cb, ifname);
-}
-
-Return<void> WifiChip::createRttController(const sp<IWifiIface>& bound_iface,
- createRttController_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::createRttControllerInternal, hidl_status_cb, bound_iface);
-}
-
-Return<void> WifiChip::getDebugRingBuffersStatus(getDebugRingBuffersStatus_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getDebugRingBuffersStatusInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::startLoggingToDebugRingBuffer(
- const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
- uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
- startLoggingToDebugRingBuffer_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::startLoggingToDebugRingBufferInternal, hidl_status_cb,
- ring_name, verbose_level, max_interval_in_sec, min_data_size_in_bytes);
-}
-
-Return<void> WifiChip::forceDumpToDebugRingBuffer(const hidl_string& ring_name,
- forceDumpToDebugRingBuffer_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::forceDumpToDebugRingBufferInternal, hidl_status_cb,
- ring_name);
-}
-
-Return<void> WifiChip::flushRingBufferToFile(flushRingBufferToFile_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::flushRingBufferToFileInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::stopLoggingToDebugRingBuffer(
- stopLoggingToDebugRingBuffer_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::stopLoggingToDebugRingBufferInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getDebugHostWakeReasonStats(getDebugHostWakeReasonStats_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getDebugHostWakeReasonStatsInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::enableDebugErrorAlerts(bool enable,
- enableDebugErrorAlerts_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::enableDebugErrorAlertsInternal, hidl_status_cb, enable);
-}
-
-Return<void> WifiChip::selectTxPowerScenario(V1_1::IWifiChip::TxPowerScenario scenario,
- selectTxPowerScenario_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::selectTxPowerScenarioInternal, hidl_status_cb, scenario);
-}
-
-Return<void> WifiChip::resetTxPowerScenario(resetTxPowerScenario_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::resetTxPowerScenarioInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::setLatencyMode(LatencyMode mode, setLatencyMode_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::setLatencyModeInternal, hidl_status_cb, mode);
-}
-
-Return<void> WifiChip::registerEventCallback_1_2(
- const sp<V1_2::IWifiChipEventCallback>& event_callback,
- registerEventCallback_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::registerEventCallbackInternal_1_2, hidl_status_cb,
- event_callback);
-}
-
-Return<void> WifiChip::selectTxPowerScenario_1_2(TxPowerScenario scenario,
- selectTxPowerScenario_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::selectTxPowerScenarioInternal_1_2, hidl_status_cb, scenario);
-}
-
-Return<void> WifiChip::getCapabilities_1_3(getCapabilities_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getCapabilitiesInternal_1_3, hidl_status_cb);
-}
-
-Return<void> WifiChip::getCapabilities_1_5(getCapabilities_1_5_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getCapabilitiesInternal_1_5, hidl_status_cb);
-}
-
-Return<void> WifiChip::debug(const hidl_handle& handle, const hidl_vec<hidl_string>&) {
- if (handle != nullptr && handle->numFds >= 1) {
- {
- std::unique_lock<std::mutex> lk(lock_t);
- for (const auto& item : ringbuffer_map_) {
- forceDumpToDebugRingBufferInternal(item.first);
- }
- // unique_lock unlocked here
- }
- usleep(100 * 1000); // sleep for 100 milliseconds to wait for
- // ringbuffer updates.
- int fd = handle->data[0];
- if (!writeRingbufferFilesInternal()) {
- LOG(ERROR) << "Error writing files to flash";
- }
- uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath);
- if (n_error != 0) {
- LOG(ERROR) << n_error << " errors occured in cpio function";
- }
- fsync(fd);
- } else {
- LOG(ERROR) << "File handle error";
- }
- return Void();
-}
-
-Return<void> WifiChip::createRttController_1_4(const sp<IWifiIface>& bound_iface,
- createRttController_1_4_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::createRttControllerInternal_1_4, hidl_status_cb, bound_iface);
-}
-
-Return<void> WifiChip::registerEventCallback_1_4(
- const sp<V1_4::IWifiChipEventCallback>& event_callback,
- registerEventCallback_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::registerEventCallbackInternal_1_4, hidl_status_cb,
- event_callback);
-}
-
-Return<void> WifiChip::setMultiStaPrimaryConnection(
- const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::setMultiStaPrimaryConnectionInternal, hidl_status_cb, ifname);
-}
-
-Return<void> WifiChip::setMultiStaUseCase(MultiStaUseCase use_case,
- setMultiStaUseCase_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::setMultiStaUseCaseInternal, hidl_status_cb, use_case);
-}
-
-Return<void> WifiChip::setCoexUnsafeChannels(const hidl_vec<CoexUnsafeChannel>& unsafeChannels,
- hidl_bitfield<CoexRestriction> restrictions,
- setCoexUnsafeChannels_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::setCoexUnsafeChannelsInternal, hidl_status_cb, unsafeChannels,
- restrictions);
-}
-
-Return<void> WifiChip::setCountryCode(const hidl_array<int8_t, 2>& code,
- setCountryCode_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiChip::setCountryCodeInternal, hidl_status_cb, code);
-}
-
-Return<void> WifiChip::getUsableChannels(
- WifiBand band, hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask,
- hidl_bitfield<V1_5::IWifiChip::UsableChannelFilter> filterMask,
- getUsableChannels_cb _hidl_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getUsableChannelsInternal, _hidl_cb, band, ifaceModeMask,
- filterMask);
-}
-
-Return<void> WifiChip::triggerSubsystemRestart(triggerSubsystemRestart_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::triggerSubsystemRestartInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::createRttController_1_6(const sp<IWifiIface>& bound_iface,
- createRttController_1_6_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::createRttControllerInternal_1_6, hidl_status_cb, bound_iface);
-}
-
-Return<void> WifiChip::getUsableChannels_1_6(
- WifiBand band, hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask,
- hidl_bitfield<V1_6::IWifiChip::UsableChannelFilter> filterMask,
- getUsableChannels_1_6_cb _hidl_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getUsableChannelsInternal_1_6, _hidl_cb, band, ifaceModeMask,
- filterMask);
-}
-
-Return<void> WifiChip::getSupportedRadioCombinationsMatrix(
- getSupportedRadioCombinationsMatrix_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getSupportedRadioCombinationsMatrixInternal, hidl_status_cb);
-}
-
-Return<void> WifiChip::getAvailableModes_1_6(getAvailableModes_1_6_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
- &WifiChip::getAvailableModesInternal_1_6, hidl_status_cb);
-}
-
-void WifiChip::invalidateAndRemoveAllIfaces() {
- invalidateAndClearBridgedApAll();
- invalidateAndClearAll(ap_ifaces_);
- invalidateAndClearAll(nan_ifaces_);
- invalidateAndClearAll(p2p_ifaces_);
- invalidateAndClearAll(sta_ifaces_);
- // Since all the ifaces are invalid now, all RTT controller objects
- // using those ifaces also need to be invalidated.
- for (const auto& rtt : rtt_controllers_) {
- rtt->invalidate();
- }
- rtt_controllers_.clear();
-}
-
-void WifiChip::invalidateAndRemoveDependencies(const std::string& removed_iface_name) {
- for (auto it = nan_ifaces_.begin(); it != nan_ifaces_.end();) {
- auto nan_iface = *it;
- if (nan_iface->getName() == removed_iface_name) {
- nan_iface->invalidate();
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onIfaceRemoved(IfaceType::NAN, removed_iface_name).isOk()) {
- LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
- }
- }
- it = nan_ifaces_.erase(it);
- } else {
- ++it;
- }
- }
-
- for (auto it = rtt_controllers_.begin(); it != rtt_controllers_.end();) {
- auto rtt = *it;
- if (rtt->getIfaceName() == removed_iface_name) {
- rtt->invalidate();
- it = rtt_controllers_.erase(it);
- } else {
- ++it;
- }
- }
-}
-
-std::pair<WifiStatus, ChipId> WifiChip::getIdInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), chip_id_};
-}
-
-WifiStatus WifiChip::registerEventCallbackInternal(
- const sp<V1_0::IWifiChipEventCallback>& /* event_callback */) {
- // Deprecated support for this callback.
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal() {
- // Deprecated support for this callback.
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0};
-}
-
-std::pair<WifiStatus, std::vector<V1_0::IWifiChip::ChipMode>>
-WifiChip::getAvailableModesInternal() {
- // Deprecated support -- use getAvailableModes_1_6 for more granular concurrency combinations.
- std::vector<V1_0::IWifiChip::ChipMode> modes_1_0 = {};
- for (const auto& mode_1_6 : modes_) {
- std::vector<V1_0::IWifiChip::ChipIfaceCombination> combos_1_0;
- for (const auto& combo_1_6 : mode_1_6.availableCombinations) {
- std::vector<V1_0::IWifiChip::ChipIfaceCombinationLimit> limits_1_0;
- for (const auto& limit_1_6 : combo_1_6.limits) {
- std::vector<IfaceType> types_1_0;
- for (IfaceConcurrencyType type_1_6 : limit_1_6.types) {
- switch (type_1_6) {
- case IfaceConcurrencyType::STA:
- types_1_0.push_back(IfaceType::STA);
- break;
- case IfaceConcurrencyType::AP:
- types_1_0.push_back(IfaceType::AP);
- break;
- case IfaceConcurrencyType::AP_BRIDGED:
- // Ignore AP_BRIDGED
- break;
- case IfaceConcurrencyType::P2P:
- types_1_0.push_back(IfaceType::P2P);
- break;
- case IfaceConcurrencyType::NAN:
- types_1_0.push_back(IfaceType::NAN);
- break;
- }
- }
- if (types_1_0.empty()) {
- continue;
- }
- V1_0::IWifiChip::ChipIfaceCombinationLimit limit_1_0;
- limit_1_0.types = hidl_vec(types_1_0);
- limit_1_0.maxIfaces = limit_1_6.maxIfaces;
- limits_1_0.push_back(limit_1_0);
- }
- if (limits_1_0.empty()) {
- continue;
- }
- V1_0::IWifiChip::ChipIfaceCombination combo_1_0;
- combo_1_0.limits = hidl_vec(limits_1_0);
- combos_1_0.push_back(combo_1_0);
- }
- if (combos_1_0.empty()) {
- continue;
- }
- V1_0::IWifiChip::ChipMode mode_1_0;
- mode_1_0.id = mode_1_6.id;
- mode_1_0.availableCombinations = hidl_vec(combos_1_0);
- modes_1_0.push_back(mode_1_0);
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), modes_1_0};
-}
-
-WifiStatus WifiChip::configureChipInternal(
- /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id) {
- if (!isValidModeId(mode_id)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- if (mode_id == current_mode_id_) {
- LOG(DEBUG) << "Already in the specified mode " << mode_id;
- return createWifiStatus(WifiStatusCode::SUCCESS);
- }
- WifiStatus status = handleChipConfiguration(lock, mode_id);
- if (status.code != WifiStatusCode::SUCCESS) {
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onChipReconfigureFailure(status).isOk()) {
- LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback";
- }
- }
- return status;
- }
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onChipReconfigured(mode_id).isOk()) {
- LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
- }
- }
- current_mode_id_ = mode_id;
- LOG(INFO) << "Configured chip in mode " << mode_id;
- setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
-
- legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(subsystemCallbackHandler_);
-
- return status;
-}
-
-std::pair<WifiStatus, uint32_t> WifiChip::getModeInternal() {
- if (!isValidModeId(current_mode_id_)) {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), current_mode_id_};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), current_mode_id_};
-}
-
-std::pair<WifiStatus, V1_4::IWifiChip::ChipDebugInfo> WifiChip::requestChipDebugInfoInternal() {
- V1_4::IWifiChip::ChipDebugInfo result;
- legacy_hal::wifi_error legacy_status;
- std::string driver_desc;
- const auto ifname = getFirstActiveWlanIfaceName();
- std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion(ifname);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to get driver version: " << legacyErrorToString(legacy_status);
- WifiStatus status =
- createWifiStatusFromLegacyError(legacy_status, "failed to get driver version");
- return {status, result};
- }
- result.driverDescription = driver_desc.c_str();
-
- std::string firmware_desc;
- std::tie(legacy_status, firmware_desc) = legacy_hal_.lock()->getFirmwareVersion(ifname);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to get firmware version: " << legacyErrorToString(legacy_status);
- WifiStatus status =
- createWifiStatusFromLegacyError(legacy_status, "failed to get firmware version");
- return {status, result};
- }
- result.firmwareDescription = firmware_desc.c_str();
-
- return {createWifiStatus(WifiStatusCode::SUCCESS), result};
-}
-
-std::pair<WifiStatus, std::vector<uint8_t>> WifiChip::requestDriverDebugDumpInternal() {
- legacy_hal::wifi_error legacy_status;
- std::vector<uint8_t> driver_dump;
- std::tie(legacy_status, driver_dump) =
- legacy_hal_.lock()->requestDriverMemoryDump(getFirstActiveWlanIfaceName());
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to get driver debug dump: " << legacyErrorToString(legacy_status);
- return {createWifiStatusFromLegacyError(legacy_status), std::vector<uint8_t>()};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), driver_dump};
-}
-
-std::pair<WifiStatus, std::vector<uint8_t>> WifiChip::requestFirmwareDebugDumpInternal() {
- legacy_hal::wifi_error legacy_status;
- std::vector<uint8_t> firmware_dump;
- std::tie(legacy_status, firmware_dump) =
- legacy_hal_.lock()->requestFirmwareMemoryDump(getFirstActiveWlanIfaceName());
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to get firmware debug dump: " << legacyErrorToString(legacy_status);
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump};
-}
-
-WifiStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) {
- legacy_hal::wifi_error legacy_status;
- legacy_status = legacy_hal_.lock()->createVirtualInterface(
- apVirtIf, hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to add interface: " << apVirtIf << " "
- << legacyErrorToString(legacy_status);
- return createWifiStatusFromLegacyError(legacy_status);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-sp<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
- std::vector<std::string> ap_instances;
- for (auto const& it : br_ifaces_ap_instances_) {
- if (it.first == ifname) {
- ap_instances = it.second;
- }
- }
- sp<WifiApIface> iface = new WifiApIface(ifname, ap_instances, legacy_hal_, iface_util_);
- ap_ifaces_.push_back(iface);
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
- LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
- }
- }
- setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
- return iface;
-}
-
-std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::createApIfaceInternal() {
- if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP)) {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- std::string ifname = allocateApIfaceName();
- WifiStatus status = createVirtualApInterface(ifname);
- if (status.code != WifiStatusCode::SUCCESS) {
- return {status, {}};
- }
- sp<WifiApIface> iface = newWifiApIface(ifname);
- return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
-}
-
-std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::createBridgedApIfaceInternal() {
- if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- std::vector<std::string> ap_instances = allocateBridgedApInstanceNames();
- if (ap_instances.size() < 2) {
- LOG(ERROR) << "Fail to allocate two instances";
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0];
- for (int i = 0; i < 2; i++) {
- WifiStatus status = createVirtualApInterface(ap_instances[i]);
- if (status.code != WifiStatusCode::SUCCESS) {
- if (i != 0) { // The failure happened when creating second virtual
- // iface.
- legacy_hal_.lock()->deleteVirtualInterface(
- ap_instances.front()); // Remove the first virtual iface.
- }
- return {status, {}};
- }
- }
- br_ifaces_ap_instances_[br_ifname] = ap_instances;
- if (!iface_util_->createBridge(br_ifname)) {
- LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
- deleteApIface(br_ifname);
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- for (auto const& instance : ap_instances) {
- // Bind ap instance interface to AP bridge
- if (!iface_util_->addIfaceToBridge(br_ifname, instance)) {
- LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str();
- deleteApIface(br_ifname);
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- }
- sp<WifiApIface> iface = newWifiApIface(br_ifname);
- return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
-}
-
-std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getApIfaceNamesInternal() {
- if (ap_ifaces_.empty()) {
- return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(ap_ifaces_)};
-}
-
-std::pair<WifiStatus, sp<V1_5::IWifiApIface>> WifiChip::getApIfaceInternal(
- const std::string& ifname) {
- const auto iface = findUsingName(ap_ifaces_, ifname);
- if (!iface.get()) {
- return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
-}
-
-WifiStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
- const auto iface = findUsingName(ap_ifaces_, ifname);
- if (!iface.get()) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- // Invalidate & remove any dependent objects first.
- // Note: This is probably not required because we never create
- // nan/rtt objects over AP iface. But, there is no harm to do it
- // here and not make that assumption all over the place.
- invalidateAndRemoveDependencies(ifname);
- deleteApIface(ifname);
- invalidateAndClear(ap_ifaces_, iface);
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
- LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
- }
- }
- setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal(
- const std::string& ifname, const std::string& ifInstanceName) {
- const auto iface = findUsingName(ap_ifaces_, ifname);
- if (!iface.get() || ifInstanceName.empty()) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- // Requires to remove one of the instance in bridge mode
- for (auto const& it : br_ifaces_ap_instances_) {
- if (it.first == ifname) {
- std::vector<std::string> ap_instances = it.second;
- for (auto const& iface : ap_instances) {
- if (iface == ifInstanceName) {
- if (!iface_util_->removeIfaceFromBridge(it.first, iface)) {
- LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from "
- << ifname;
- return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->deleteVirtualInterface(iface);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to del interface: " << iface << " "
- << legacyErrorToString(legacy_status);
- return createWifiStatusFromLegacyError(legacy_status);
- }
- ap_instances.erase(
- std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName),
- ap_instances.end());
- br_ifaces_ap_instances_[ifname] = ap_instances;
- break;
- }
- }
- break;
- }
- }
- iface->removeInstance(ifInstanceName);
- setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
-
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> WifiChip::createNanIfaceInternal() {
- if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::NAN)) {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- bool is_dedicated_iface = true;
- std::string ifname = getPredefinedNanIfaceName();
- if (ifname.empty() || !iface_util_->ifNameToIndex(ifname)) {
- // Use the first shared STA iface (wlan0) if a dedicated aware iface is
- // not defined.
- ifname = getFirstActiveWlanIfaceName();
- is_dedicated_iface = false;
- }
- sp<WifiNanIface> iface = new WifiNanIface(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
- nan_ifaces_.push_back(iface);
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onIfaceAdded(IfaceType::NAN, ifname).isOk()) {
- LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
- }
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
-}
-
-std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getNanIfaceNamesInternal() {
- if (nan_ifaces_.empty()) {
- return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(nan_ifaces_)};
-}
-
-std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> WifiChip::getNanIfaceInternal(
- const std::string& ifname) {
- const auto iface = findUsingName(nan_ifaces_, ifname);
- if (!iface.get()) {
- return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
-}
-
-WifiStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
- const auto iface = findUsingName(nan_ifaces_, ifname);
- if (!iface.get()) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- invalidateAndClear(nan_ifaces_, iface);
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onIfaceRemoved(IfaceType::NAN, ifname).isOk()) {
- LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
- }
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::createP2pIfaceInternal() {
- if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::P2P)) {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- std::string ifname = getPredefinedP2pIfaceName();
- sp<WifiP2pIface> iface = new WifiP2pIface(ifname, legacy_hal_);
- p2p_ifaces_.push_back(iface);
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
- LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
- }
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
-}
-
-std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getP2pIfaceNamesInternal() {
- if (p2p_ifaces_.empty()) {
- return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(p2p_ifaces_)};
-}
-
-std::pair<WifiStatus, sp<IWifiP2pIface>> WifiChip::getP2pIfaceInternal(const std::string& ifname) {
- const auto iface = findUsingName(p2p_ifaces_, ifname);
- if (!iface.get()) {
- return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
-}
-
-WifiStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
- const auto iface = findUsingName(p2p_ifaces_, ifname);
- if (!iface.get()) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- invalidateAndClear(p2p_ifaces_, iface);
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
- LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
- }
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, sp<V1_6::IWifiStaIface>> WifiChip::createStaIfaceInternal() {
- if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- std::string ifname = allocateStaIfaceName();
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->createVirtualInterface(
- ifname, hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::STA));
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to add interface: " << ifname << " "
- << legacyErrorToString(legacy_status);
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- sp<WifiStaIface> iface = new WifiStaIface(ifname, legacy_hal_, iface_util_);
- sta_ifaces_.push_back(iface);
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
- LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
- }
- }
- setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
- return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
-}
-
-std::pair<WifiStatus, std::vector<hidl_string>> WifiChip::getStaIfaceNamesInternal() {
- if (sta_ifaces_.empty()) {
- return {createWifiStatus(WifiStatusCode::SUCCESS), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), getNames(sta_ifaces_)};
-}
-
-std::pair<WifiStatus, sp<V1_6::IWifiStaIface>> WifiChip::getStaIfaceInternal(
- const std::string& ifname) {
- const auto iface = findUsingName(sta_ifaces_, ifname);
- if (!iface.get()) {
- return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), nullptr};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
-}
-
-WifiStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
- const auto iface = findUsingName(sta_ifaces_, ifname);
- if (!iface.get()) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- // Invalidate & remove any dependent objects first.
- invalidateAndRemoveDependencies(ifname);
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deleteVirtualInterface(ifname);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to remove interface: " << ifname << " "
- << legacyErrorToString(legacy_status);
- }
- invalidateAndClear(sta_ifaces_, iface);
- for (const auto& callback : event_cb_handler_.getCallbacks()) {
- if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
- LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
- }
- }
- setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, sp<V1_0::IWifiRttController>> WifiChip::createRttControllerInternal(
- const sp<IWifiIface>& /*bound_iface*/) {
- LOG(ERROR) << "createRttController is not supported on this HAL";
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
-WifiChip::getDebugRingBuffersStatusInternal() {
- legacy_hal::wifi_error legacy_status;
- std::vector<legacy_hal::wifi_ring_buffer_status> legacy_ring_buffer_status_vec;
- std::tie(legacy_status, legacy_ring_buffer_status_vec) =
- legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName());
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- std::vector<WifiDebugRingBufferStatus> hidl_ring_buffer_status_vec;
- if (!hidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToHidl(
- legacy_ring_buffer_status_vec, &hidl_ring_buffer_status_vec)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_ring_buffer_status_vec};
-}
-
-WifiStatus WifiChip::startLoggingToDebugRingBufferInternal(
- const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
- uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) {
- WifiStatus status = registerDebugRingBufferCallback();
- if (status.code != WifiStatusCode::SUCCESS) {
- return status;
- }
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRingBufferLogging(
- getFirstActiveWlanIfaceName(), ring_name,
- static_cast<std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(verbose_level),
- max_interval_in_sec, min_data_size_in_bytes);
- ringbuffer_map_.insert(
- std::pair<std::string, Ringbuffer>(ring_name, Ringbuffer(kMaxBufferSizeBytes)));
- // if verbose logging enabled, turn up HAL daemon logging as well.
- if (verbose_level < WifiDebugRingBufferVerboseLevel::VERBOSE) {
- android::base::SetMinimumLogSeverity(android::base::DEBUG);
- } else {
- android::base::SetMinimumLogSeverity(android::base::VERBOSE);
- }
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::forceDumpToDebugRingBufferInternal(const hidl_string& ring_name) {
- WifiStatus status = registerDebugRingBufferCallback();
- if (status.code != WifiStatusCode::SUCCESS) {
- return status;
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(), ring_name);
-
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::flushRingBufferToFileInternal() {
- if (!writeRingbufferFilesInternal()) {
- LOG(ERROR) << "Error writing files to flash";
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->deregisterRingBufferCallbackHandler(getFirstActiveWlanIfaceName());
- if (legacy_status == legacy_hal::WIFI_SUCCESS) {
- debug_ring_buffer_cb_registered_ = false;
- }
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, WifiDebugHostWakeReasonStats>
-WifiChip::getDebugHostWakeReasonStatsInternal() {
- legacy_hal::wifi_error legacy_status;
- legacy_hal::WakeReasonStats legacy_stats;
- std::tie(legacy_status, legacy_stats) =
- legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName());
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- WifiDebugHostWakeReasonStats hidl_stats;
- if (!hidl_struct_util::convertLegacyWakeReasonStatsToHidl(legacy_stats, &hidl_stats)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
-}
-
-WifiStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) {
- legacy_hal::wifi_error legacy_status;
- if (enable) {
- android::wp<WifiChip> weak_ptr_this(this);
- const auto& on_alert_callback = [weak_ptr_this](int32_t error_code,
- std::vector<uint8_t> debug_data) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->onDebugErrorAlert(error_code, debug_data).isOk()) {
- LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback";
- }
- }
- };
- legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
- getFirstActiveWlanIfaceName(), on_alert_callback);
- } else {
- legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
- getFirstActiveWlanIfaceName());
- }
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario) {
- auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
- getFirstActiveWlanIfaceName(),
- hidl_struct_util::convertHidlTxPowerScenarioToLegacy(scenario));
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::resetTxPowerScenarioInternal() {
- auto legacy_status = legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName());
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::setLatencyModeInternal(LatencyMode mode) {
- auto legacy_status = legacy_hal_.lock()->setLatencyMode(
- getFirstActiveWlanIfaceName(), hidl_struct_util::convertHidlLatencyModeToLegacy(mode));
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::registerEventCallbackInternal_1_2(
- const sp<V1_2::IWifiChipEventCallback>& /* event_callback */) {
- // Deprecated support for this callback.
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiChip::selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario) {
- auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
- getFirstActiveWlanIfaceName(),
- hidl_struct_util::convertHidlTxPowerScenarioToLegacy_1_2(scenario));
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal_1_3() {
- // Deprecated support for this callback.
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), 0};
-}
-
-std::pair<WifiStatus, uint32_t> WifiChip::getCapabilitiesInternal_1_5() {
- legacy_hal::wifi_error legacy_status;
- uint64_t legacy_feature_set;
- uint32_t legacy_logger_feature_set;
- const auto ifname = getFirstActiveWlanIfaceName();
- std::tie(legacy_status, legacy_feature_set) =
- legacy_hal_.lock()->getSupportedFeatureSet(ifname);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), 0};
- }
- std::tie(legacy_status, legacy_logger_feature_set) =
- legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- // some devices don't support querying logger feature set
- legacy_logger_feature_set = 0;
- }
- uint32_t hidl_caps;
- if (!hidl_struct_util::convertLegacyFeaturesToHidlChipCapabilities(
- legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, sp<V1_4::IWifiRttController>> WifiChip::createRttControllerInternal_1_4(
- const sp<IWifiIface>& /*bound_iface*/) {
- LOG(ERROR) << "createRttController_1_4 is not supported on this HAL";
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-WifiStatus WifiChip::registerEventCallbackInternal_1_4(
- const sp<V1_4::IWifiChipEventCallback>& event_callback) {
- if (!event_cb_handler_.addCallback(event_callback)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiChip::setMultiStaPrimaryConnectionInternal(const std::string& ifname) {
- auto legacy_status = legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::setMultiStaUseCaseInternal(MultiStaUseCase use_case) {
- auto legacy_status = legacy_hal_.lock()->multiStaSetUseCase(
- hidl_struct_util::convertHidlMultiStaUseCaseToLegacy(use_case));
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::setCoexUnsafeChannelsInternal(std::vector<CoexUnsafeChannel> unsafe_channels,
- uint32_t restrictions) {
- std::vector<legacy_hal::wifi_coex_unsafe_channel> legacy_unsafe_channels;
- if (!hidl_struct_util::convertHidlVectorOfCoexUnsafeChannelToLegacy(unsafe_channels,
- &legacy_unsafe_channels)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- uint32_t legacy_restrictions = 0;
- if (restrictions & CoexRestriction::WIFI_DIRECT) {
- legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_DIRECT;
- }
- if (restrictions & CoexRestriction::SOFTAP) {
- legacy_restrictions |= legacy_hal::wifi_coex_restriction::SOFTAP;
- }
- if (restrictions & CoexRestriction::WIFI_AWARE) {
- legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_AWARE;
- }
- auto legacy_status =
- legacy_hal_.lock()->setCoexUnsafeChannels(legacy_unsafe_channels, legacy_restrictions);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::setCountryCodeInternal(const std::array<int8_t, 2>& code) {
- auto legacy_status = legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, std::vector<V1_5::WifiUsableChannel>> WifiChip::getUsableChannelsInternal(
- WifiBand /*band*/, uint32_t /*ifaceModeMask*/, uint32_t /*filterMask*/) {
- LOG(ERROR) << "getUsableChannels is not supported on this HAL";
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-WifiStatus WifiChip::triggerSubsystemRestartInternal() {
- auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart();
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, sp<V1_6::IWifiRttController>> WifiChip::createRttControllerInternal_1_6(
- const sp<IWifiIface>& bound_iface) {
- if (sta_ifaces_.size() == 0 &&
- !canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) {
- LOG(ERROR) << "createRttControllerInternal_1_6: Chip cannot support STAs "
- "(and RTT by extension)";
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
- }
- sp<WifiRttController> rtt =
- new WifiRttController(getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_);
- rtt_controllers_.emplace_back(rtt);
- return {createWifiStatus(WifiStatusCode::SUCCESS), rtt};
-}
-
-std::pair<WifiStatus, std::vector<V1_6::WifiUsableChannel>> WifiChip::getUsableChannelsInternal_1_6(
- WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask) {
- legacy_hal::wifi_error legacy_status;
- std::vector<legacy_hal::wifi_usable_channel> legacy_usable_channels;
- std::tie(legacy_status, legacy_usable_channels) = legacy_hal_.lock()->getUsableChannels(
- hidl_struct_util::convertHidlWifiBandToLegacyMacBand(band),
- hidl_struct_util::convertHidlWifiIfaceModeToLegacy(ifaceModeMask),
- hidl_struct_util::convertHidlUsableChannelFilterToLegacy(filterMask));
-
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- std::vector<V1_6::WifiUsableChannel> hidl_usable_channels;
- if (!hidl_struct_util::convertLegacyWifiUsableChannelsToHidl(legacy_usable_channels,
- &hidl_usable_channels)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_usable_channels};
-}
-
-std::pair<WifiStatus, V1_6::WifiRadioCombinationMatrix>
-WifiChip::getSupportedRadioCombinationsMatrixInternal() {
- legacy_hal::wifi_error legacy_status;
- legacy_hal::wifi_radio_combination_matrix* legacy_matrix;
-
- std::tie(legacy_status, legacy_matrix) =
- legacy_hal_.lock()->getSupportedRadioCombinationsMatrix();
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: "
- << legacyErrorToString(legacy_status);
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
-
- V1_6::WifiRadioCombinationMatrix hidl_matrix;
- if (!hidl_struct_util::convertLegacyRadioCombinationsMatrixToHidl(legacy_matrix,
- &hidl_matrix)) {
- LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToHidl() ";
- return {createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_matrix};
-}
-
-std::pair<WifiStatus, std::vector<V1_6::IWifiChip::ChipMode>>
-WifiChip::getAvailableModesInternal_1_6() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), modes_};
-}
-
-WifiStatus WifiChip::handleChipConfiguration(
- /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, ChipModeId mode_id) {
- // If the chip is already configured in a different mode, stop
- // the legacy HAL and then start it after firmware mode change.
- if (isValidModeId(current_mode_id_)) {
- LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_ << " to mode " << mode_id;
- invalidateAndRemoveAllIfaces();
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stop(lock, []() {});
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to stop legacy HAL: " << legacyErrorToString(legacy_status);
- return createWifiStatusFromLegacyError(legacy_status);
- }
- }
- // Firmware mode change not needed for V2 devices.
- bool success = true;
- if (mode_id == feature_flags::chip_mode_ids::kV1Sta) {
- success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
- } else if (mode_id == feature_flags::chip_mode_ids::kV1Ap) {
- success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
- }
- if (!success) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to start legacy HAL: " << legacyErrorToString(legacy_status);
- return createWifiStatusFromLegacyError(legacy_status);
- }
- // Every time the HAL is restarted, we need to register the
- // radio mode change callback.
- WifiStatus status = registerRadioModeChangeCallback();
- if (status.code != WifiStatusCode::SUCCESS) {
- // This probably is not a critical failure?
- LOG(ERROR) << "Failed to register radio mode change callback";
- }
- // Extract and save the version information into property.
- std::pair<WifiStatus, V1_4::IWifiChip::ChipDebugInfo> version_info;
- version_info = WifiChip::requestChipDebugInfoInternal();
- if (WifiStatusCode::SUCCESS == version_info.first.code) {
- property_set("vendor.wlan.firmware.version",
- version_info.second.firmwareDescription.c_str());
- property_set("vendor.wlan.driver.version", version_info.second.driverDescription.c_str());
- }
-
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiChip::registerDebugRingBufferCallback() {
- if (debug_ring_buffer_cb_registered_) {
- return createWifiStatus(WifiStatusCode::SUCCESS);
- }
-
- android::wp<WifiChip> weak_ptr_this(this);
- const auto& on_ring_buffer_data_callback =
- [weak_ptr_this](const std::string& name, const std::vector<uint8_t>& data,
- const legacy_hal::wifi_ring_buffer_status& status) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- WifiDebugRingBufferStatus hidl_status;
- Ringbuffer::AppendStatus appendstatus;
- if (!hidl_struct_util::convertLegacyDebugRingBufferStatusToHidl(status,
- &hidl_status)) {
- LOG(ERROR) << "Error converting ring buffer status";
- return;
- }
- {
- std::unique_lock<std::mutex> lk(shared_ptr_this->lock_t);
- const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
- if (target != shared_ptr_this->ringbuffer_map_.end()) {
- Ringbuffer& cur_buffer = target->second;
- appendstatus = cur_buffer.append(data);
- } else {
- LOG(ERROR) << "Ringname " << name << " not found";
- return;
- }
- // unique_lock unlocked here
- }
- if (appendstatus == Ringbuffer::AppendStatus::FAIL_RING_BUFFER_CORRUPTED) {
- LOG(ERROR) << "Ringname " << name << " is corrupted. Clear the ring buffer";
- shared_ptr_this->writeRingbufferFilesInternal();
- return;
- }
-
- };
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRingBufferCallbackHandler(
- getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback);
-
- if (legacy_status == legacy_hal::WIFI_SUCCESS) {
- debug_ring_buffer_cb_registered_ = true;
- }
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiChip::registerRadioModeChangeCallback() {
- android::wp<WifiChip> weak_ptr_this(this);
- const auto& on_radio_mode_change_callback =
- [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- std::vector<V1_4::IWifiChipEventCallback::RadioModeInfo> hidl_radio_mode_infos;
- if (!hidl_struct_util::convertLegacyWifiMacInfosToHidl(mac_infos,
- &hidl_radio_mode_infos)) {
- LOG(ERROR) << "Error converting wifi mac info";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->onRadioModeChange_1_4(hidl_radio_mode_infos).isOk()) {
- LOG(ERROR) << "Failed to invoke onRadioModeChange_1_4"
- << " callback on: " << toString(callback);
- }
- }
- };
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
- getFirstActiveWlanIfaceName(), on_radio_mode_change_callback);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::vector<V1_6::IWifiChip::ChipConcurrencyCombination>
-WifiChip::getCurrentModeConcurrencyCombinations() {
- if (!isValidModeId(current_mode_id_)) {
- LOG(ERROR) << "Chip not configured in a mode yet";
- return {};
- }
- for (const auto& mode : modes_) {
- if (mode.id == current_mode_id_) {
- return mode.availableCombinations;
- }
- }
- CHECK(0) << "Expected to find concurrency combinations for current mode!";
- return {};
-}
-
-// Returns a map indexed by IfaceConcurrencyType with the number of ifaces currently
-// created of the corresponding concurrency type.
-std::map<IfaceConcurrencyType, size_t> WifiChip::getCurrentConcurrencyCombination() {
- std::map<IfaceConcurrencyType, size_t> iface_counts;
- uint32_t num_ap = 0;
- uint32_t num_ap_bridged = 0;
- for (const auto& ap_iface : ap_ifaces_) {
- std::string ap_iface_name = ap_iface->getName();
- if (br_ifaces_ap_instances_.count(ap_iface_name) > 0 &&
- br_ifaces_ap_instances_[ap_iface_name].size() > 1) {
- num_ap_bridged++;
- } else {
- num_ap++;
- }
- }
- iface_counts[IfaceConcurrencyType::AP] = num_ap;
- iface_counts[IfaceConcurrencyType::AP_BRIDGED] = num_ap_bridged;
- iface_counts[IfaceConcurrencyType::NAN] = nan_ifaces_.size();
- iface_counts[IfaceConcurrencyType::P2P] = p2p_ifaces_.size();
- iface_counts[IfaceConcurrencyType::STA] = sta_ifaces_.size();
- return iface_counts;
-}
-
-// This expands the provided concurrency combinations to a more parseable
-// form. Returns a vector of available combinations possible with the number
-// of each concurrency type in the combination.
-// This method is a port of HalDeviceManager.expandConcurrencyCombos() from framework.
-std::vector<std::map<IfaceConcurrencyType, size_t>> WifiChip::expandConcurrencyCombinations(
- const V1_6::IWifiChip::ChipConcurrencyCombination& combination) {
- uint32_t num_expanded_combos = 1;
- for (const auto& limit : combination.limits) {
- for (uint32_t i = 0; i < limit.maxIfaces; i++) {
- num_expanded_combos *= limit.types.size();
- }
- }
-
- // Allocate the vector of expanded combos and reset all concurrency type counts to 0
- // in each combo.
- std::vector<std::map<IfaceConcurrencyType, size_t>> expanded_combos;
- expanded_combos.resize(num_expanded_combos);
- for (auto& expanded_combo : expanded_combos) {
- for (const auto type :
- {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED, IfaceConcurrencyType::NAN,
- IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) {
- expanded_combo[type] = 0;
- }
- }
- uint32_t span = num_expanded_combos;
- for (const auto& limit : combination.limits) {
- for (uint32_t i = 0; i < limit.maxIfaces; i++) {
- span /= limit.types.size();
- for (uint32_t k = 0; k < num_expanded_combos; ++k) {
- const auto iface_type = limit.types[(k / span) % limit.types.size()];
- expanded_combos[k][iface_type]++;
- }
- }
- }
- return expanded_combos;
-}
-
-bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(
- const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
- IfaceConcurrencyType requested_type) {
- const auto current_combo = getCurrentConcurrencyCombination();
-
- // Check if we have space for 1 more iface of |type| in this combo
- for (const auto type :
- {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED, IfaceConcurrencyType::NAN,
- IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) {
- size_t num_ifaces_needed = current_combo.at(type);
- if (type == requested_type) {
- num_ifaces_needed++;
- }
- size_t num_ifaces_allowed = expanded_combo.at(type);
- if (num_ifaces_needed > num_ifaces_allowed) {
- return false;
- }
- }
- return true;
-}
-
-// This method does the following:
-// a) Enumerate all possible concurrency combos by expanding the current
-// ChipConcurrencyCombination.
-// b) Check if the requested concurrency type can be added to the current mode
-// with the concurrency combination that is already active.
-bool WifiChip::canCurrentModeSupportConcurrencyTypeWithCurrentTypes(
- IfaceConcurrencyType requested_type) {
- if (!isValidModeId(current_mode_id_)) {
- LOG(ERROR) << "Chip not configured in a mode yet";
- return false;
- }
- const auto combinations = getCurrentModeConcurrencyCombinations();
- for (const auto& combination : combinations) {
- const auto expanded_combos = expandConcurrencyCombinations(combination);
- for (const auto& expanded_combo : expanded_combos) {
- if (canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(expanded_combo,
- requested_type)) {
- return true;
- }
- }
- }
- return false;
-}
-
-// Note: This does not consider concurrency types already active. It only checks if the
-// provided expanded concurrency combination can support the requested combo.
-bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyCombo(
- const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
- const std::map<IfaceConcurrencyType, size_t>& req_combo) {
- // Check if we have space for 1 more |type| in this combo
- for (const auto type :
- {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED, IfaceConcurrencyType::NAN,
- IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) {
- if (req_combo.count(type) == 0) {
- // Concurrency type not in the req_combo.
- continue;
- }
- size_t num_ifaces_needed = req_combo.at(type);
- size_t num_ifaces_allowed = expanded_combo.at(type);
- if (num_ifaces_needed > num_ifaces_allowed) {
- return false;
- }
- }
- return true;
-}
-// This method does the following:
-// a) Enumerate all possible concurrency combos by expanding the current
-// ChipConcurrencyCombination.
-// b) Check if the requested concurrency combo can be added to the current mode.
-// Note: This does not consider concurrency types already active. It only checks if the
-// current mode can support the requested combo.
-bool WifiChip::canCurrentModeSupportConcurrencyCombo(
- const std::map<IfaceConcurrencyType, size_t>& req_combo) {
- if (!isValidModeId(current_mode_id_)) {
- LOG(ERROR) << "Chip not configured in a mode yet";
- return false;
- }
- const auto combinations = getCurrentModeConcurrencyCombinations();
- for (const auto& combination : combinations) {
- const auto expanded_combos = expandConcurrencyCombinations(combination);
- for (const auto& expanded_combo : expanded_combos) {
- if (canExpandedConcurrencyComboSupportConcurrencyCombo(expanded_combo, req_combo)) {
- return true;
- }
- }
- }
- return false;
-}
-
-// This method does the following:
-// a) Enumerate all possible concurrency combos by expanding the current
-// ChipConcurrencyCombination.
-// b) Check if the requested concurrency type can be added to the current mode.
-bool WifiChip::canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type) {
- // Check if we can support at least 1 of the requested concurrency type.
- std::map<IfaceConcurrencyType, size_t> req_iface_combo;
- req_iface_combo[requested_type] = 1;
- return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
-}
-
-bool WifiChip::isValidModeId(ChipModeId mode_id) {
- for (const auto& mode : modes_) {
- if (mode.id == mode_id) {
- return true;
- }
- }
- return false;
-}
-
-bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() {
- // Check if we can support at least 1 STA & 1 AP concurrently.
- std::map<IfaceConcurrencyType, size_t> req_iface_combo;
- req_iface_combo[IfaceConcurrencyType::STA] = 1;
- req_iface_combo[IfaceConcurrencyType::AP] = 1;
- return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
-}
-
-bool WifiChip::isDualStaConcurrencyAllowedInCurrentMode() {
- // Check if we can support at least 2 STA concurrently.
- std::map<IfaceConcurrencyType, size_t> req_iface_combo;
- req_iface_combo[IfaceConcurrencyType::STA] = 2;
- return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
-}
-
-std::string WifiChip::getFirstActiveWlanIfaceName() {
- if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName();
- if (ap_ifaces_.size() > 0) {
- // If the first active wlan iface is bridged iface.
- // Return first instance name.
- for (auto const& it : br_ifaces_ap_instances_) {
- if (it.first == ap_ifaces_[0]->getName()) {
- return it.second[0];
- }
- }
- return ap_ifaces_[0]->getName();
- }
- // This could happen if the chip call is made before any STA/AP
- // iface is created. Default to wlan0 for such cases.
- LOG(WARNING) << "No active wlan interfaces in use! Using default";
- return getWlanIfaceNameWithType(IfaceType::STA, 0);
-}
-
-// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx|
-// not already in use.
-// Note: This doesn't check the actual presence of these interfaces.
-std::string WifiChip::allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx) {
- for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
- const auto ifname = getWlanIfaceNameWithType(type, idx);
- if (findUsingNameFromBridgedApInstances(ifname)) continue;
- if (findUsingName(ap_ifaces_, ifname)) continue;
- if (findUsingName(sta_ifaces_, ifname)) continue;
- return ifname;
- }
- // This should never happen. We screwed up somewhere if it did.
- CHECK(false) << "All wlan interfaces in use already!";
- return {};
-}
-
-uint32_t WifiChip::startIdxOfApIface() {
- if (isDualStaConcurrencyAllowedInCurrentMode()) {
- // When the HAL support dual STAs, AP should start with idx 2.
- return 2;
- } else if (isStaApConcurrencyAllowedInCurrentMode()) {
- // When the HAL support STA + AP but it doesn't support dual STAs.
- // AP should start with idx 1.
- return 1;
- }
- // No concurrency support.
- return 0;
-}
-
-// AP iface names start with idx 1 for modes supporting
-// concurrent STA and not dual AP, else start with idx 0.
-std::string WifiChip::allocateApIfaceName() {
- // Check if we have a dedicated iface for AP.
- std::vector<std::string> ifnames = getPredefinedApIfaceNames(true);
- for (auto const& ifname : ifnames) {
- if (findUsingName(ap_ifaces_, ifname)) continue;
- return ifname;
- }
- return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
-}
-
-std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() {
- // Check if we have a dedicated iface for AP.
- std::vector<std::string> instances = getPredefinedApIfaceNames(true);
- if (instances.size() == 2) {
- return instances;
- } else {
- int num_ifaces_need_to_allocate = 2 - instances.size();
- for (int i = 0; i < num_ifaces_need_to_allocate; i++) {
- std::string instance_name =
- allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface() + i);
- if (!instance_name.empty()) {
- instances.push_back(instance_name);
- }
- }
- }
- return instances;
-}
-
-// STA iface names start with idx 0.
-// Primary STA iface will always be 0.
-std::string WifiChip::allocateStaIfaceName() {
- return allocateApOrStaIfaceName(IfaceType::STA, 0);
-}
-
-bool WifiChip::writeRingbufferFilesInternal() {
- if (!removeOldFilesInternal()) {
- LOG(ERROR) << "Error occurred while deleting old tombstone files";
- return false;
- }
- // write ringbuffers to file
- {
- std::unique_lock<std::mutex> lk(lock_t);
- for (auto& item : ringbuffer_map_) {
- Ringbuffer& cur_buffer = item.second;
- if (cur_buffer.getData().empty()) {
- continue;
- }
- const std::string file_path_raw = kTombstoneFolderPath + item.first + "XXXXXXXXXX";
- const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
- if (dump_fd == -1) {
- PLOG(ERROR) << "create file failed";
- return false;
- }
- unique_fd file_auto_closer(dump_fd);
- for (const auto& cur_block : cur_buffer.getData()) {
- if (cur_block.size() <= 0 || cur_block.size() > kMaxBufferSizeBytes) {
- PLOG(ERROR) << "Ring buffer: " << item.first
- << " is corrupted. Invalid block size: " << cur_block.size();
- break;
- }
- if (write(dump_fd, cur_block.data(), sizeof(cur_block[0]) * cur_block.size()) ==
- -1) {
- PLOG(ERROR) << "Error writing to file";
- }
- }
- cur_buffer.clear();
- }
- // unique_lock unlocked here
- }
- return true;
-}
-
-std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) {
- std::string ifname;
-
- // let the legacy hal override the interface name
- legacy_hal::wifi_error err = legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname);
- if (err == legacy_hal::WIFI_SUCCESS) return ifname;
-
- return getWlanIfaceName(idx);
-}
-
-void WifiChip::invalidateAndClearBridgedApAll() {
- for (auto const& it : br_ifaces_ap_instances_) {
- for (auto const& iface : it.second) {
- iface_util_->removeIfaceFromBridge(it.first, iface);
- legacy_hal_.lock()->deleteVirtualInterface(iface);
- }
- iface_util_->deleteBridge(it.first);
- }
- br_ifaces_ap_instances_.clear();
-}
-
-void WifiChip::deleteApIface(const std::string& if_name) {
- if (if_name.empty()) return;
- // delete bridged interfaces if have
- for (auto const& it : br_ifaces_ap_instances_) {
- if (it.first == if_name) {
- for (auto const& iface : it.second) {
- iface_util_->removeIfaceFromBridge(if_name, iface);
- legacy_hal_.lock()->deleteVirtualInterface(iface);
- }
- iface_util_->deleteBridge(if_name);
- br_ifaces_ap_instances_.erase(if_name);
- // ifname is bridged AP, return here.
- return;
- }
- }
-
- // No bridged AP case, delete AP iface
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deleteVirtualInterface(if_name);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to remove interface: " << if_name << " "
- << legacyErrorToString(legacy_status);
- }
-}
-
-bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) {
- for (auto const& it : br_ifaces_ap_instances_) {
- if (it.first == name) {
- return true;
- }
- for (auto const& iface : it.second) {
- if (iface == name) {
- return true;
- }
- }
- }
- return false;
-}
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_chip.h b/wifi/1.6/default/wifi_chip.h
deleted file mode 100644
index e8ddaa6..0000000
--- a/wifi/1.6/default/wifi_chip.h
+++ /dev/null
@@ -1,317 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_CHIP_H_
-#define WIFI_CHIP_H_
-
-// HACK: NAN is a macro defined in math.h, which can be included in various
-// headers. This wifi HAL uses an enum called NAN, which does not compile when
-// the macro is defined. Undefine NAN to work around it.
-#undef NAN
-
-#include <list>
-#include <map>
-#include <mutex>
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.6/IWifiChip.h>
-#include <android/hardware/wifi/1.6/IWifiRttController.h>
-#include <android/hardware/wifi/1.6/IWifiStaIface.h>
-
-#include "hidl_callback_util.h"
-#include "ringbuffer.h"
-#include "wifi_ap_iface.h"
-#include "wifi_feature_flags.h"
-#include "wifi_legacy_hal.h"
-#include "wifi_mode_controller.h"
-#include "wifi_nan_iface.h"
-#include "wifi_p2p_iface.h"
-#include "wifi_rtt_controller.h"
-#include "wifi_sta_iface.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-using V1_5::WifiBand;
-
-/**
- * HIDL interface object used to control a Wifi HAL chip instance.
- * Since there is only a single chip instance used today, there is no
- * identifying handle information stored here.
- */
-class WifiChip : public V1_6::IWifiChip {
- public:
- WifiChip(ChipId chip_id, bool is_primary,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
- const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
- const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
- const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
- const std::function<void(const std::string&)>& subsystemCallbackHandler);
- // HIDL does not provide a built-in mechanism to let the server invalidate
- // a HIDL interface object after creation. If any client process holds onto
- // a reference to the object in their context, any method calls on that
- // reference will continue to be directed to the server.
- //
- // However Wifi HAL needs to control the lifetime of these objects. So, add
- // a public |invalidate| method to |WifiChip| and it's child objects. This
- // will be used to mark an object invalid when either:
- // a) Wifi HAL is stopped, or
- // b) Wifi Chip is reconfigured.
- //
- // All HIDL method implementations should check if the object is still
- // marked valid before processing them.
- void invalidate();
- bool isValid();
- std::set<sp<V1_4::IWifiChipEventCallback>> getEventCallbacks();
-
- // HIDL methods exposed.
- Return<void> getId(getId_cb hidl_status_cb) override;
- // Deprecated support for this callback
- Return<void> registerEventCallback(const sp<V1_0::IWifiChipEventCallback>& event_callback,
- registerEventCallback_cb hidl_status_cb) override;
- Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
- Return<void> getAvailableModes(getAvailableModes_cb hidl_status_cb) override;
- Return<void> configureChip(ChipModeId mode_id, configureChip_cb hidl_status_cb) override;
- Return<void> getMode(getMode_cb hidl_status_cb) override;
- Return<void> requestChipDebugInfo(requestChipDebugInfo_cb hidl_status_cb) override;
- Return<void> requestDriverDebugDump(requestDriverDebugDump_cb hidl_status_cb) override;
- Return<void> requestFirmwareDebugDump(requestFirmwareDebugDump_cb hidl_status_cb) override;
- Return<void> createApIface(createApIface_cb hidl_status_cb) override;
- Return<void> createBridgedApIface(createBridgedApIface_cb hidl_status_cb) override;
- Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override;
- Return<void> getApIface(const hidl_string& ifname, getApIface_cb hidl_status_cb) override;
- Return<void> removeApIface(const hidl_string& ifname, removeApIface_cb hidl_status_cb) override;
- Return<void> removeIfaceInstanceFromBridgedApIface(
- const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName,
- removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override;
- Return<void> createNanIface(createNanIface_cb hidl_status_cb) override;
- Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override;
- Return<void> getNanIface(const hidl_string& ifname, getNanIface_cb hidl_status_cb) override;
- Return<void> removeNanIface(const hidl_string& ifname,
- removeNanIface_cb hidl_status_cb) override;
- Return<void> createP2pIface(createP2pIface_cb hidl_status_cb) override;
- Return<void> getP2pIfaceNames(getP2pIfaceNames_cb hidl_status_cb) override;
- Return<void> getP2pIface(const hidl_string& ifname, getP2pIface_cb hidl_status_cb) override;
- Return<void> removeP2pIface(const hidl_string& ifname,
- removeP2pIface_cb hidl_status_cb) override;
- Return<void> createStaIface(createStaIface_cb hidl_status_cb) override;
- Return<void> getStaIfaceNames(getStaIfaceNames_cb hidl_status_cb) override;
- Return<void> getStaIface(const hidl_string& ifname, getStaIface_cb hidl_status_cb) override;
- Return<void> removeStaIface(const hidl_string& ifname,
- removeStaIface_cb hidl_status_cb) override;
- Return<void> createRttController(const sp<IWifiIface>& bound_iface,
- createRttController_cb hidl_status_cb) override;
- Return<void> getDebugRingBuffersStatus(getDebugRingBuffersStatus_cb hidl_status_cb) override;
- Return<void> startLoggingToDebugRingBuffer(
- const hidl_string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
- uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes,
- startLoggingToDebugRingBuffer_cb hidl_status_cb) override;
- Return<void> forceDumpToDebugRingBuffer(const hidl_string& ring_name,
- forceDumpToDebugRingBuffer_cb hidl_status_cb) override;
- Return<void> flushRingBufferToFile(flushRingBufferToFile_cb hidl_status_cb) override;
- Return<void> stopLoggingToDebugRingBuffer(
- stopLoggingToDebugRingBuffer_cb hidl_status_cb) override;
- Return<void> getDebugHostWakeReasonStats(
- getDebugHostWakeReasonStats_cb hidl_status_cb) override;
- Return<void> enableDebugErrorAlerts(bool enable,
- enableDebugErrorAlerts_cb hidl_status_cb) override;
- Return<void> selectTxPowerScenario(V1_1::IWifiChip::TxPowerScenario scenario,
- selectTxPowerScenario_cb hidl_status_cb) override;
- Return<void> resetTxPowerScenario(resetTxPowerScenario_cb hidl_status_cb) override;
- Return<void> setLatencyMode(LatencyMode mode, setLatencyMode_cb hidl_status_cb) override;
- Return<void> registerEventCallback_1_2(const sp<V1_2::IWifiChipEventCallback>& event_callback,
- registerEventCallback_1_2_cb hidl_status_cb) override;
- Return<void> selectTxPowerScenario_1_2(TxPowerScenario scenario,
- selectTxPowerScenario_cb hidl_status_cb) override;
- Return<void> getCapabilities_1_3(getCapabilities_cb hidl_status_cb) override;
- Return<void> getCapabilities_1_5(getCapabilities_1_5_cb hidl_status_cb) override;
- Return<void> debug(const hidl_handle& handle, const hidl_vec<hidl_string>& options) override;
- Return<void> createRttController_1_4(const sp<IWifiIface>& bound_iface,
- createRttController_1_4_cb hidl_status_cb) override;
- Return<void> registerEventCallback_1_4(const sp<V1_4::IWifiChipEventCallback>& event_callback,
- registerEventCallback_1_4_cb hidl_status_cb) override;
- Return<void> setMultiStaPrimaryConnection(
- const hidl_string& ifname, setMultiStaPrimaryConnection_cb hidl_status_cb) override;
- Return<void> setMultiStaUseCase(MultiStaUseCase use_case,
- setMultiStaUseCase_cb hidl_status_cb) override;
- Return<void> setCoexUnsafeChannels(const hidl_vec<CoexUnsafeChannel>& unsafe_channels,
- hidl_bitfield<IfaceType> restrictions,
- setCoexUnsafeChannels_cb hidl_status_cb) override;
- Return<void> setCountryCode(const hidl_array<int8_t, 2>& code,
- setCountryCode_cb _hidl_cb) override;
- Return<void> getUsableChannels(WifiBand band, hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask,
- hidl_bitfield<V1_5::IWifiChip::UsableChannelFilter> filterMask,
- getUsableChannels_cb _hidl_cb) override;
- Return<void> triggerSubsystemRestart(triggerSubsystemRestart_cb hidl_status_cb) override;
- Return<void> createRttController_1_6(const sp<IWifiIface>& bound_iface,
- createRttController_1_6_cb hidl_status_cb) override;
- Return<void> getUsableChannels_1_6(WifiBand band,
- hidl_bitfield<V1_5::WifiIfaceMode> ifaceModeMask,
- hidl_bitfield<UsableChannelFilter> filterMask,
- getUsableChannels_1_6_cb _hidl_cb) override;
- Return<void> getSupportedRadioCombinationsMatrix(
- getSupportedRadioCombinationsMatrix_cb hidl_status_cb) override;
- Return<void> getAvailableModes_1_6(getAvailableModes_1_6_cb hidl_status_cb) override;
-
- private:
- void invalidateAndRemoveAllIfaces();
- // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are
- // invalidated & removed.
- void invalidateAndRemoveDependencies(const std::string& removed_iface_name);
-
- // Corresponding worker functions for the HIDL methods.
- std::pair<WifiStatus, ChipId> getIdInternal();
- // Deprecated support for this callback
- WifiStatus registerEventCallbackInternal(
- const sp<V1_0::IWifiChipEventCallback>& event_callback);
- std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
- std::pair<WifiStatus, std::vector<V1_0::IWifiChip::ChipMode>> getAvailableModesInternal();
- WifiStatus configureChipInternal(std::unique_lock<std::recursive_mutex>* lock,
- ChipModeId mode_id);
- std::pair<WifiStatus, uint32_t> getModeInternal();
- std::pair<WifiStatus, IWifiChip::ChipDebugInfo> requestChipDebugInfoInternal();
- std::pair<WifiStatus, std::vector<uint8_t>> requestDriverDebugDumpInternal();
- std::pair<WifiStatus, std::vector<uint8_t>> requestFirmwareDebugDumpInternal();
- sp<WifiApIface> newWifiApIface(std::string& ifname);
- WifiStatus createVirtualApInterface(const std::string& apVirtIf);
- std::pair<WifiStatus, sp<V1_5::IWifiApIface>> createApIfaceInternal();
- std::pair<WifiStatus, sp<V1_5::IWifiApIface>> createBridgedApIfaceInternal();
- std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal();
- std::pair<WifiStatus, sp<V1_5::IWifiApIface>> getApIfaceInternal(const std::string& ifname);
- WifiStatus removeApIfaceInternal(const std::string& ifname);
- WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal(const std::string& brIfaceName,
- const std::string& ifInstanceName);
- std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> createNanIfaceInternal();
- std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal();
- std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> getNanIfaceInternal(const std::string& ifname);
- WifiStatus removeNanIfaceInternal(const std::string& ifname);
- std::pair<WifiStatus, sp<IWifiP2pIface>> createP2pIfaceInternal();
- std::pair<WifiStatus, std::vector<hidl_string>> getP2pIfaceNamesInternal();
- std::pair<WifiStatus, sp<IWifiP2pIface>> getP2pIfaceInternal(const std::string& ifname);
- WifiStatus removeP2pIfaceInternal(const std::string& ifname);
- std::pair<WifiStatus, sp<V1_6::IWifiStaIface>> createStaIfaceInternal();
- std::pair<WifiStatus, std::vector<hidl_string>> getStaIfaceNamesInternal();
- std::pair<WifiStatus, sp<V1_6::IWifiStaIface>> getStaIfaceInternal(const std::string& ifname);
- WifiStatus removeStaIfaceInternal(const std::string& ifname);
- std::pair<WifiStatus, sp<V1_0::IWifiRttController>> createRttControllerInternal(
- const sp<IWifiIface>& bound_iface);
- std::pair<WifiStatus, std::vector<WifiDebugRingBufferStatus>>
- getDebugRingBuffersStatusInternal();
- WifiStatus startLoggingToDebugRingBufferInternal(const hidl_string& ring_name,
- WifiDebugRingBufferVerboseLevel verbose_level,
- uint32_t max_interval_in_sec,
- uint32_t min_data_size_in_bytes);
- WifiStatus forceDumpToDebugRingBufferInternal(const hidl_string& ring_name);
- WifiStatus flushRingBufferToFileInternal();
- WifiStatus stopLoggingToDebugRingBufferInternal();
- std::pair<WifiStatus, WifiDebugHostWakeReasonStats> getDebugHostWakeReasonStatsInternal();
- WifiStatus enableDebugErrorAlertsInternal(bool enable);
- WifiStatus selectTxPowerScenarioInternal(V1_1::IWifiChip::TxPowerScenario scenario);
- WifiStatus resetTxPowerScenarioInternal();
- WifiStatus setLatencyModeInternal(LatencyMode mode);
- WifiStatus registerEventCallbackInternal_1_2(
- const sp<V1_2::IWifiChipEventCallback>& event_callback);
- WifiStatus selectTxPowerScenarioInternal_1_2(TxPowerScenario scenario);
- std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_3();
- std::pair<WifiStatus, uint32_t> getCapabilitiesInternal_1_5();
- std::pair<WifiStatus, sp<V1_4::IWifiRttController>> createRttControllerInternal_1_4(
- const sp<IWifiIface>& bound_iface);
- WifiStatus registerEventCallbackInternal_1_4(
- const sp<V1_4::IWifiChipEventCallback>& event_callback);
- WifiStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname);
- WifiStatus setMultiStaUseCaseInternal(MultiStaUseCase use_case);
- WifiStatus setCoexUnsafeChannelsInternal(std::vector<CoexUnsafeChannel> unsafe_channels,
- uint32_t restrictions);
- WifiStatus setCountryCodeInternal(const std::array<int8_t, 2>& code);
- std::pair<WifiStatus, std::vector<V1_5::WifiUsableChannel>> getUsableChannelsInternal(
- WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask);
- WifiStatus handleChipConfiguration(std::unique_lock<std::recursive_mutex>* lock,
- ChipModeId mode_id);
- WifiStatus registerDebugRingBufferCallback();
- WifiStatus registerRadioModeChangeCallback();
- std::vector<V1_6::IWifiChip::ChipConcurrencyCombination>
- getCurrentModeConcurrencyCombinations();
- std::map<IfaceConcurrencyType, size_t> getCurrentConcurrencyCombination();
- std::vector<std::map<IfaceConcurrencyType, size_t>> expandConcurrencyCombinations(
- const V1_6::IWifiChip::ChipConcurrencyCombination& combination);
- bool canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(
- const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
- IfaceConcurrencyType requested_type);
- bool canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType requested_type);
- bool canExpandedConcurrencyComboSupportConcurrencyCombo(
- const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
- const std::map<IfaceConcurrencyType, size_t>& req_combo);
- bool canCurrentModeSupportConcurrencyCombo(
- const std::map<IfaceConcurrencyType, size_t>& req_combo);
- bool canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type);
- bool isValidModeId(ChipModeId mode_id);
- bool isStaApConcurrencyAllowedInCurrentMode();
- bool isDualStaConcurrencyAllowedInCurrentMode();
- uint32_t startIdxOfApIface();
- std::string getFirstActiveWlanIfaceName();
- std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
- std::string allocateApIfaceName();
- std::vector<std::string> allocateBridgedApInstanceNames();
- std::string allocateStaIfaceName();
- bool writeRingbufferFilesInternal();
- std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
- void invalidateAndClearBridgedApAll();
- void deleteApIface(const std::string& if_name);
- bool findUsingNameFromBridgedApInstances(const std::string& name);
- WifiStatus triggerSubsystemRestartInternal();
- std::pair<WifiStatus, sp<V1_6::IWifiRttController>> createRttControllerInternal_1_6(
- const sp<IWifiIface>& bound_iface);
- std::pair<WifiStatus, std::vector<V1_6::WifiUsableChannel>> getUsableChannelsInternal_1_6(
- WifiBand band, uint32_t ifaceModeMask, uint32_t filterMask);
- std::pair<WifiStatus, WifiRadioCombinationMatrix> getSupportedRadioCombinationsMatrixInternal();
- std::pair<WifiStatus, std::vector<V1_6::IWifiChip::ChipMode>> getAvailableModesInternal_1_6();
-
- ChipId chip_id_;
- std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
- std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
- std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_;
- std::vector<sp<WifiApIface>> ap_ifaces_;
- std::vector<sp<WifiNanIface>> nan_ifaces_;
- std::vector<sp<WifiP2pIface>> p2p_ifaces_;
- std::vector<sp<WifiStaIface>> sta_ifaces_;
- std::vector<sp<WifiRttController>> rtt_controllers_;
- std::map<std::string, Ringbuffer> ringbuffer_map_;
- bool is_valid_;
- // Members pertaining to chip configuration.
- uint32_t current_mode_id_;
- std::mutex lock_t;
- std::vector<V1_6::IWifiChip::ChipMode> modes_;
- // The legacy ring buffer callback API has only a global callback
- // registration mechanism. Use this to check if we have already
- // registered a callback.
- bool debug_ring_buffer_cb_registered_;
- hidl_callback_util::HidlCallbackHandler<V1_4::IWifiChipEventCallback> event_cb_handler_;
-
- const std::function<void(const std::string&)> subsystemCallbackHandler_;
- std::map<std::string, std::vector<std::string>> br_ifaces_ap_instances_;
- DISALLOW_COPY_AND_ASSIGN(WifiChip);
-};
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_CHIP_H_
diff --git a/wifi/1.6/default/wifi_feature_flags.cpp b/wifi/1.6/default/wifi_feature_flags.cpp
deleted file mode 100644
index e80a3cd..0000000
--- a/wifi/1.6/default/wifi_feature_flags.cpp
+++ /dev/null
@@ -1,247 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string>
-
-#include <android-base/logging.h>
-#include <cutils/properties.h>
-
-#include "wifi_feature_flags.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace feature_flags {
-
-using V1_0::ChipModeId;
-using V1_0::IWifiChip;
-using V1_6::IfaceConcurrencyType;
-
-/* The chip may either have a single mode supporting any number of combinations,
- * or a fixed dual-mode (so it involves firmware loading to switch between
- * modes) setting. If there is a need to support more modes, it needs to be
- * implemented manually in WiFi HAL (see changeFirmwareMode in
- * WifiChip::handleChipConfiguration).
- *
- * Supported combinations are defined in device's makefile, for example:
- * WIFI_HAL_INTERFACE_COMBINATIONS := {{{STA, AP}, 1}, {{P2P, NAN}, 1}},
- * WIFI_HAL_INTERFACE_COMBINATIONS += {{{STA}, 1}, {{AP}, 2}}
- * What means:
- * Interface concurrency combination 1: 1 STA or AP and 1 P2P or NAN concurrent iface
- * operations.
- * Interface concurrency combination 2: 1 STA and 2 AP concurrent iface operations.
- *
- * For backward compatibility, the following makefile flags can be used to
- * generate combinations list:
- * - WIFI_HIDL_FEATURE_DUAL_INTERFACE
- * - WIFI_HIDL_FEATURE_DISABLE_AP
- * - WIFI_HIDL_FEATURE_AWARE
- * However, they are ignored if WIFI_HAL_INTERFACE_COMBINATIONS was provided.
- * With WIFI_HIDL_FEATURE_DUAL_INTERFACE flag set, there is a single mode with
- * two concurrency combinations:
- * Interface Concurrency Combination 1: Will support 1 STA and 1 P2P or NAN (optional)
- * concurrent iface operations.
- * Interface Concurrency Combination 2: Will support 1 STA and 1 AP concurrent
- * iface operations.
- *
- * The only dual-mode configuration supported is for alternating STA and AP
- * mode, that may involve firmware reloading. In such case, there are 2 separate
- * modes of operation with 1 concurrency combination each:
- * Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN (optional)
- * concurrent iface operations.
- * Mode 2 (AP mode): Will support 1 AP iface operation.
- *
- * If Aware is enabled, the concurrency combination will be modified to support either
- * P2P or NAN in place of just P2P.
- */
-// clang-format off
-#ifdef WIFI_HAL_INTERFACE_COMBINATIONS
-constexpr ChipModeId kMainModeId = chip_mode_ids::kV3;
-#elif defined(WIFI_HIDL_FEATURE_DUAL_INTERFACE)
-// former V2 (fixed dual interface) setup expressed as V3
-constexpr ChipModeId kMainModeId = chip_mode_ids::kV3;
-# ifdef WIFI_HIDL_FEATURE_DISABLE_AP
-# ifdef WIFI_HIDL_FEATURE_AWARE
-// 1 STA + 1 of (P2P or NAN)
-# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}}
-# else
-// 1 STA + 1 P2P
-# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
-# endif
-# else
-# ifdef WIFI_HIDL_FEATURE_AWARE
-// (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
-# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
- {{{STA}, 1}, {{P2P, NAN}, 1}}
-# else
-// (1 STA + 1 AP) or (1 STA + 1 P2P)
-# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
- {{{STA}, 1}, {{P2P}, 1}}
-# endif
-# endif
-#else
-// V1 (fixed single interface, dual-mode chip)
-constexpr ChipModeId kMainModeId = chip_mode_ids::kV1Sta;
-# ifdef WIFI_HIDL_FEATURE_AWARE
-// 1 STA + 1 of (P2P or NAN)
-# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}}
-# else
-// 1 STA + 1 P2P
-# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
-# endif
-
-# ifndef WIFI_HIDL_FEATURE_DISABLE_AP
-# define WIFI_HAL_INTERFACE_COMBINATIONS_AP {{{AP}, 1}}
-# endif
-#endif
-// clang-format on
-
-/**
- * Helper class to convert a collection of combination limits to a combination.
- *
- * The main point here is to simplify the syntax required by
- * WIFI_HAL_INTERFACE_COMBINATIONS.
- */
-struct ChipConcurrencyCombination
- : public hidl_vec<V1_6::IWifiChip::ChipConcurrencyCombinationLimit> {
- ChipConcurrencyCombination(
- const std::initializer_list<V1_6::IWifiChip::ChipConcurrencyCombinationLimit> list)
- : hidl_vec(list) {}
-
- operator V1_6::IWifiChip::ChipConcurrencyCombination() const { return {*this}; }
-
- static hidl_vec<V1_6::IWifiChip::ChipConcurrencyCombination> make_vec(
- const std::initializer_list<ChipConcurrencyCombination> list) {
- return hidl_vec<V1_6::IWifiChip::ChipConcurrencyCombination>( //
- std::begin(list), std::end(list));
- }
-};
-
-#define STA IfaceConcurrencyType::STA
-#define AP IfaceConcurrencyType::AP
-#define AP_BRIDGED IfaceConcurrencyType::AP_BRIDGED
-#define P2P IfaceConcurrencyType::P2P
-#define NAN IfaceConcurrencyType::NAN
-static const std::vector<V1_6::IWifiChip::ChipMode> kChipModesPrimary{
- {kMainModeId, ChipConcurrencyCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS})},
-#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_AP
- {chip_mode_ids::kV1Ap,
- ChipConcurrencyCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_AP})},
-#endif
-};
-
-static const std::vector<V1_6::IWifiChip::ChipMode> kChipModesSecondary{
-#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP
- {chip_mode_ids::kV3,
- ChipConcurrencyCombination::make_vec({WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP})},
-#endif
-};
-
-constexpr char kDebugPresetInterfaceCombinationIdxProperty[] =
- "persist.vendor.debug.wifi.hal.preset_interface_combination_idx";
-// List of pre-defined concurrency combinations that can be enabled at runtime via
-// setting the property: "kDebugPresetInterfaceCombinationIdxProperty" to the
-// corresponding index value.
-static const std::vector<std::pair<std::string, std::vector<V1_6::IWifiChip::ChipMode>>>
- kDebugChipModes{// Legacy combination - No STA/AP concurrencies.
- // 0 - (1 AP) or (1 STA + 1 of (P2P or NAN))
- {"No STA/AP Concurrency",
- {{kMainModeId, ChipConcurrencyCombination::make_vec(
- {{{{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
-
- // STA + AP concurrency
- // 1 - (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
- {"STA + AP Concurrency",
- {{kMainModeId,
- ChipConcurrencyCombination::make_vec(
- {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
-
- // STA + STA concurrency
- // 2 - (1 STA + 1 AP) or (2 STA + 1 of (P2P or NAN))
- {"Dual STA Concurrency",
- {{kMainModeId,
- ChipConcurrencyCombination::make_vec(
- {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}},
-
- // AP + AP + STA concurrency
- // 3 - (1 STA + 2 AP) or (1 STA + 1 of (P2P or NAN))
- {"Dual AP Concurrency",
- {{kMainModeId,
- ChipConcurrencyCombination::make_vec(
- {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
-
- // STA + STA concurrency and AP + AP + STA concurrency
- // 4 - (1 STA + 2 AP) or (2 STA + 1 of (P2P or NAN))
- {"Dual STA & Dual AP Concurrency",
- {{kMainModeId,
- ChipConcurrencyCombination::make_vec(
- {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}},
-
- // STA + STA concurrency
- // 5 - (1 STA + 1 AP (bridged or single) | P2P | NAN), or (2 STA))
- {"Dual STA or STA plus single other interface",
- {{kMainModeId, ChipConcurrencyCombination::make_vec(
- {{{{STA}, 1}, {{P2P, NAN, AP, AP_BRIDGED}, 1}},
- {{{STA}, 2}}})}}}};
-
-#undef STA
-#undef AP
-#undef P2P
-#undef NAN
-
-#ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
-#pragma message \
- "WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION is deprecated; override " \
- "'config_wifi_ap_randomization_supported' in " \
- "frameworks/base/core/res/res/values/config.xml in the device overlay " \
- "instead"
-#endif // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
-
-WifiFeatureFlags::WifiFeatureFlags() {}
-
-std::vector<V1_6::IWifiChip::ChipMode> WifiFeatureFlags::getChipModesForPrimary() {
- std::array<char, PROPERTY_VALUE_MAX> buffer;
- auto res = property_get(kDebugPresetInterfaceCombinationIdxProperty, buffer.data(), nullptr);
- // Debug property not set, use the device preset concurrency combination.
- if (res <= 0) return kChipModesPrimary;
-
- // Debug property set, use one of the debug preset concurrency combination.
- unsigned long idx = std::stoul(buffer.data());
- if (idx >= kDebugChipModes.size()) {
- LOG(ERROR) << "Invalid index set in property: "
- << kDebugPresetInterfaceCombinationIdxProperty;
- return kChipModesPrimary;
- }
- std::string name;
- std::vector<V1_6::IWifiChip::ChipMode> chip_modes;
- std::tie(name, chip_modes) = kDebugChipModes[idx];
- LOG(INFO) << "Using debug chip mode: <" << name
- << "> set via property: " << kDebugPresetInterfaceCombinationIdxProperty;
- return chip_modes;
-}
-
-std::vector<V1_6::IWifiChip::ChipMode> WifiFeatureFlags::getChipModes(bool is_primary) {
- return (is_primary) ? getChipModesForPrimary() : kChipModesSecondary;
-}
-
-} // namespace feature_flags
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_feature_flags.h b/wifi/1.6/default/wifi_feature_flags.h
deleted file mode 100644
index 1635341..0000000
--- a/wifi/1.6/default/wifi_feature_flags.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_FEATURE_FLAGS_H_
-#define WIFI_FEATURE_FLAGS_H_
-
-#include <android/hardware/wifi/1.6/IWifiChip.h>
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace feature_flags {
-
-namespace chip_mode_ids {
-// These mode ID's should be unique (even across combo versions). Refer to
-// handleChipConfiguration() for it's usage.
-constexpr V1_0::ChipModeId kInvalid = UINT32_MAX;
-// Mode ID's for V1
-constexpr V1_0::ChipModeId kV1Sta = 0;
-constexpr V1_0::ChipModeId kV1Ap = 1;
-// Mode ID for V3
-constexpr V1_0::ChipModeId kV3 = 3;
-} // namespace chip_mode_ids
-
-class WifiFeatureFlags {
- public:
- WifiFeatureFlags();
- virtual ~WifiFeatureFlags() = default;
-
- virtual std::vector<V1_6::IWifiChip::ChipMode> getChipModes(bool is_primary);
-
- private:
- std::vector<V1_6::IWifiChip::ChipMode> getChipModesForPrimary();
-};
-
-} // namespace feature_flags
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_FEATURE_FLAGS_H_
diff --git a/wifi/1.6/default/wifi_iface_util.cpp b/wifi/1.6/default/wifi_iface_util.cpp
deleted file mode 100644
index d55e4f8..0000000
--- a/wifi/1.6/default/wifi_iface_util.cpp
+++ /dev/null
@@ -1,176 +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 <net/if.h>
-#include <cstddef>
-#include <iostream>
-#include <limits>
-#include <random>
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <private/android_filesystem_config.h>
-
-#undef NAN
-#include "wifi_iface_util.h"
-
-namespace {
-// Constants to set the local bit & clear the multicast bit.
-constexpr uint8_t kMacAddressMulticastMask = 0x01;
-constexpr uint8_t kMacAddressLocallyAssignedMask = 0x02;
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace iface_util {
-
-WifiIfaceUtil::WifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
- : iface_tool_(iface_tool),
- legacy_hal_(legacy_hal),
- random_mac_address_(nullptr),
- event_handlers_map_() {}
-
-std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(const std::string& iface_name) {
- return iface_tool_.lock()->GetFactoryMacAddress(iface_name.c_str());
-}
-
-bool WifiIfaceUtil::setMacAddress(const std::string& iface_name,
- const std::array<uint8_t, 6>& mac) {
-#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
- legacy_hal::wifi_error legacy_status;
- uint64_t legacy_feature_set;
- std::tie(legacy_status, legacy_feature_set) =
- legacy_hal_.lock()->getSupportedFeatureSet(iface_name);
-
- if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) &&
- !iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
- LOG(ERROR) << "SetUpState(false) failed.";
- return false;
- }
-#endif
- bool success = iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac);
-#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
- if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) &&
- !iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
- LOG(ERROR) << "SetUpState(true) failed. Wait for driver ready.";
- // Wait for driver ready and try to set iface UP again
- if (legacy_hal_.lock()->waitForDriverReady() != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "SetUpState(true) wait for driver ready failed.";
- return false;
- }
- if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
- LOG(ERROR) << "SetUpState(true) failed after retry.";
- return false;
- }
- }
-#endif
- IfaceEventHandlers event_handlers = {};
- const auto it = event_handlers_map_.find(iface_name);
- if (it != event_handlers_map_.end()) {
- event_handlers = it->second;
- }
- if (event_handlers.on_state_toggle_off_on != nullptr) {
- event_handlers.on_state_toggle_off_on(iface_name);
- }
- if (!success) {
- LOG(ERROR) << "SetMacAddress failed on " << iface_name;
- } else {
- LOG(DEBUG) << "SetMacAddress succeeded on " << iface_name;
- }
- return success;
-}
-
-std::array<uint8_t, 6> WifiIfaceUtil::getOrCreateRandomMacAddress() {
- if (random_mac_address_) {
- return *random_mac_address_.get();
- }
- random_mac_address_ = std::make_unique<std::array<uint8_t, 6>>(createRandomMacAddress());
- return *random_mac_address_.get();
-}
-
-void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name,
- IfaceEventHandlers handlers) {
- event_handlers_map_[iface_name] = handlers;
-}
-
-void WifiIfaceUtil::unregisterIfaceEventHandlers(const std::string& iface_name) {
- event_handlers_map_.erase(iface_name);
-}
-
-std::array<uint8_t, 6> WifiIfaceUtil::createRandomMacAddress() {
- std::array<uint8_t, 6> address = {};
- std::random_device rd;
- std::default_random_engine engine(rd());
- std::uniform_int_distribution<uint8_t> dist(std::numeric_limits<uint8_t>::min(),
- std::numeric_limits<uint8_t>::max());
- for (size_t i = 0; i < address.size(); i++) {
- address[i] = dist(engine);
- }
- // Set the local bit and clear the multicast bit.
- address[0] |= kMacAddressLocallyAssignedMask;
- address[0] &= ~kMacAddressMulticastMask;
- return address;
-}
-
-bool WifiIfaceUtil::setUpState(const std::string& iface_name, bool request_up) {
- if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), request_up)) {
- LOG(ERROR) << "SetUpState to " << request_up << " failed";
- return false;
- }
- return true;
-}
-
-unsigned WifiIfaceUtil::ifNameToIndex(const std::string& iface_name) {
- return if_nametoindex(iface_name.c_str());
-}
-
-bool WifiIfaceUtil::createBridge(const std::string& br_name) {
- if (!iface_tool_.lock()->createBridge(br_name)) {
- return false;
- }
-
- if (!iface_tool_.lock()->SetUpState(br_name.c_str(), true)) {
- LOG(ERROR) << "bridge SetUpState(true) failed.";
- }
- return true;
-}
-
-bool WifiIfaceUtil::deleteBridge(const std::string& br_name) {
- if (!iface_tool_.lock()->SetUpState(br_name.c_str(), false)) {
- LOG(INFO) << "SetUpState(false) failed for bridge=" << br_name.c_str();
- }
-
- return iface_tool_.lock()->deleteBridge(br_name);
-}
-
-bool WifiIfaceUtil::addIfaceToBridge(const std::string& br_name, const std::string& if_name) {
- return iface_tool_.lock()->addIfaceToBridge(br_name, if_name);
-}
-
-bool WifiIfaceUtil::removeIfaceFromBridge(const std::string& br_name, const std::string& if_name) {
- return iface_tool_.lock()->removeIfaceFromBridge(br_name, if_name);
-}
-
-} // namespace iface_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_iface_util.h b/wifi/1.6/default/wifi_iface_util.h
deleted file mode 100644
index c5db5de..0000000
--- a/wifi/1.6/default/wifi_iface_util.h
+++ /dev/null
@@ -1,87 +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.
- */
-
-#ifndef WIFI_IFACE_UTIL_H_
-#define WIFI_IFACE_UTIL_H_
-
-#include <wifi_system/interface_tool.h>
-
-#include <android/hardware/wifi/1.0/IWifi.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace iface_util {
-
-// Iface event handlers.
-struct IfaceEventHandlers {
- // Callback to be invoked when the iface is set down & up for MAC address
- // change.
- std::function<void(const std::string& iface_name)> on_state_toggle_off_on;
-};
-
-/**
- * Util class for common iface operations.
- */
-class WifiIfaceUtil {
- public:
- WifiIfaceUtil(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
- virtual ~WifiIfaceUtil() = default;
-
- virtual std::array<uint8_t, 6> getFactoryMacAddress(const std::string& iface_name);
- virtual bool setMacAddress(const std::string& iface_name, const std::array<uint8_t, 6>& mac);
- // Get or create a random MAC address. The MAC address returned from
- // this method will remain the same throughout the lifetime of the HAL
- // daemon. (So, changes on every reboot)
- virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress();
-
- // Register for any iface event callbacks for the provided interface.
- virtual void registerIfaceEventHandlers(const std::string& iface_name,
- IfaceEventHandlers handlers);
- virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
- virtual bool setUpState(const std::string& iface_name, bool request_up);
- virtual unsigned ifNameToIndex(const std::string& iface_name);
-
- virtual bool createBridge(const std::string& br_name);
-
- virtual bool deleteBridge(const std::string& br_name);
-
- virtual bool addIfaceToBridge(const std::string& br_name, const std::string& if_name);
-
- virtual bool removeIfaceFromBridge(const std::string& br_name, const std::string& if_name);
- // Get a random MAC address.
- virtual std::array<uint8_t, 6> createRandomMacAddress();
-
- private:
- std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
- std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
- std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;
- std::map<std::string, IfaceEventHandlers> event_handlers_map_;
-};
-
-} // namespace iface_util
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_IFACE_UTIL_H_
diff --git a/wifi/1.6/default/wifi_legacy_hal.cpp b/wifi/1.6/default/wifi_legacy_hal.cpp
deleted file mode 100644
index c9bcdc5..0000000
--- a/wifi/1.6/default/wifi_legacy_hal.cpp
+++ /dev/null
@@ -1,1635 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <array>
-#include <chrono>
-
-#include <android-base/logging.h>
-#include <cutils/properties.h>
-#include <net/if.h>
-
-#include "hidl_sync_util.h"
-#include "wifi_legacy_hal.h"
-#include "wifi_legacy_hal_stubs.h"
-
-namespace {
-// Constants ported over from the legacy HAL calling code
-// (com_android_server_wifi_WifiNative.cpp). This will all be thrown
-// away when this shim layer is replaced by the real vendor
-// implementation.
-static constexpr uint32_t kMaxVersionStringLength = 256;
-static constexpr uint32_t kMaxCachedGscanResults = 64;
-static constexpr uint32_t kMaxGscanFrequenciesForBand = 64;
-static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
-static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
-static constexpr uint32_t kMaxRingBuffers = 10;
-static constexpr uint32_t kMaxWifiUsableChannels = 256;
-static constexpr uint32_t kMaxSupportedRadioCombinationsMatrixLength = 256;
-// need a long timeout (1000ms) for chips that unload their driver.
-static constexpr uint32_t kMaxStopCompleteWaitMs = 1000;
-static constexpr char kDriverPropName[] = "wlan.driver.status";
-
-// Helper function to create a non-const char* for legacy Hal API's.
-std::vector<char> makeCharVec(const std::string& str) {
- std::vector<char> vec(str.size() + 1);
- vec.assign(str.begin(), str.end());
- vec.push_back('\0');
- return vec;
-}
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace legacy_hal {
-
-// Legacy HAL functions accept "C" style function pointers, so use global
-// functions to pass to the legacy HAL function and store the corresponding
-// std::function methods to be invoked.
-//
-// Callback to be invoked once |stop| is complete
-std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
-void onAsyncStopComplete(wifi_handle handle) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_stop_complete_internal_callback) {
- on_stop_complete_internal_callback(handle);
- // Invalidate this callback since we don't want this firing again.
- on_stop_complete_internal_callback = nullptr;
- }
-}
-
-// Callback to be invoked for driver dump.
-std::function<void(char*, int)> on_driver_memory_dump_internal_callback;
-void onSyncDriverMemoryDump(char* buffer, int buffer_size) {
- if (on_driver_memory_dump_internal_callback) {
- on_driver_memory_dump_internal_callback(buffer, buffer_size);
- }
-}
-
-// Callback to be invoked for firmware dump.
-std::function<void(char*, int)> on_firmware_memory_dump_internal_callback;
-void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) {
- if (on_firmware_memory_dump_internal_callback) {
- on_firmware_memory_dump_internal_callback(buffer, buffer_size);
- }
-}
-
-// Callback to be invoked for Gscan events.
-std::function<void(wifi_request_id, wifi_scan_event)> on_gscan_event_internal_callback;
-void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_gscan_event_internal_callback) {
- on_gscan_event_internal_callback(id, event);
- }
-}
-
-// Callback to be invoked for Gscan full results.
-std::function<void(wifi_request_id, wifi_scan_result*, uint32_t)>
- on_gscan_full_result_internal_callback;
-void onAsyncGscanFullResult(wifi_request_id id, wifi_scan_result* result,
- uint32_t buckets_scanned) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_gscan_full_result_internal_callback) {
- on_gscan_full_result_internal_callback(id, result, buckets_scanned);
- }
-}
-
-// Callback to be invoked for link layer stats results.
-std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))>
- on_link_layer_stats_result_internal_callback;
-void onSyncLinkLayerStatsResult(wifi_request_id id, wifi_iface_stat* iface_stat, int num_radios,
- wifi_radio_stat* radio_stat) {
- if (on_link_layer_stats_result_internal_callback) {
- on_link_layer_stats_result_internal_callback(id, iface_stat, num_radios, radio_stat);
- }
-}
-
-// Callback to be invoked for rssi threshold breach.
-std::function<void((wifi_request_id, uint8_t*, int8_t))>
- on_rssi_threshold_breached_internal_callback;
-void onAsyncRssiThresholdBreached(wifi_request_id id, uint8_t* bssid, int8_t rssi) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_rssi_threshold_breached_internal_callback) {
- on_rssi_threshold_breached_internal_callback(id, bssid, rssi);
- }
-}
-
-// Callback to be invoked for ring buffer data indication.
-std::function<void(char*, char*, int, wifi_ring_buffer_status*)>
- on_ring_buffer_data_internal_callback;
-void onAsyncRingBufferData(char* ring_name, char* buffer, int buffer_size,
- wifi_ring_buffer_status* status) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_ring_buffer_data_internal_callback) {
- on_ring_buffer_data_internal_callback(ring_name, buffer, buffer_size, status);
- }
-}
-
-// Callback to be invoked for error alert indication.
-std::function<void(wifi_request_id, char*, int, int)> on_error_alert_internal_callback;
-void onAsyncErrorAlert(wifi_request_id id, char* buffer, int buffer_size, int err_code) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_error_alert_internal_callback) {
- on_error_alert_internal_callback(id, buffer, buffer_size, err_code);
- }
-}
-
-// Callback to be invoked for radio mode change indication.
-std::function<void(wifi_request_id, uint32_t, wifi_mac_info*)>
- on_radio_mode_change_internal_callback;
-void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs, wifi_mac_info* mac_infos) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_radio_mode_change_internal_callback) {
- on_radio_mode_change_internal_callback(id, num_macs, mac_infos);
- }
-}
-
-// Callback to be invoked to report subsystem restart
-std::function<void(const char*)> on_subsystem_restart_internal_callback;
-void onAsyncSubsystemRestart(const char* error) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_subsystem_restart_internal_callback) {
- on_subsystem_restart_internal_callback(error);
- }
-}
-
-// Callback to be invoked for rtt results results.
-std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result* rtt_results[])>
- on_rtt_results_internal_callback;
-void onAsyncRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_results[]) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_rtt_results_internal_callback) {
- on_rtt_results_internal_callback(id, num_results, rtt_results);
- on_rtt_results_internal_callback = nullptr;
- }
-}
-
-// Callbacks for the various NAN operations.
-// NOTE: These have very little conversions to perform before invoking the user
-// callbacks.
-// So, handle all of them here directly to avoid adding an unnecessary layer.
-std::function<void(transaction_id, const NanResponseMsg&)> on_nan_notify_response_user_callback;
-void onAysncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_notify_response_user_callback && msg) {
- on_nan_notify_response_user_callback(id, *msg);
- }
-}
-
-std::function<void(const NanPublishRepliedInd&)> on_nan_event_publish_replied_user_callback;
-void onAysncNanEventPublishReplied(NanPublishRepliedInd* /* event */) {
- LOG(ERROR) << "onAysncNanEventPublishReplied triggered";
-}
-
-std::function<void(const NanPublishTerminatedInd&)> on_nan_event_publish_terminated_user_callback;
-void onAysncNanEventPublishTerminated(NanPublishTerminatedInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_publish_terminated_user_callback && event) {
- on_nan_event_publish_terminated_user_callback(*event);
- }
-}
-
-std::function<void(const NanMatchInd&)> on_nan_event_match_user_callback;
-void onAysncNanEventMatch(NanMatchInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_match_user_callback && event) {
- on_nan_event_match_user_callback(*event);
- }
-}
-
-std::function<void(const NanMatchExpiredInd&)> on_nan_event_match_expired_user_callback;
-void onAysncNanEventMatchExpired(NanMatchExpiredInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_match_expired_user_callback && event) {
- on_nan_event_match_expired_user_callback(*event);
- }
-}
-
-std::function<void(const NanSubscribeTerminatedInd&)>
- on_nan_event_subscribe_terminated_user_callback;
-void onAysncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_subscribe_terminated_user_callback && event) {
- on_nan_event_subscribe_terminated_user_callback(*event);
- }
-}
-
-std::function<void(const NanFollowupInd&)> on_nan_event_followup_user_callback;
-void onAysncNanEventFollowup(NanFollowupInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_followup_user_callback && event) {
- on_nan_event_followup_user_callback(*event);
- }
-}
-
-std::function<void(const NanDiscEngEventInd&)> on_nan_event_disc_eng_event_user_callback;
-void onAysncNanEventDiscEngEvent(NanDiscEngEventInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_disc_eng_event_user_callback && event) {
- on_nan_event_disc_eng_event_user_callback(*event);
- }
-}
-
-std::function<void(const NanDisabledInd&)> on_nan_event_disabled_user_callback;
-void onAysncNanEventDisabled(NanDisabledInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_disabled_user_callback && event) {
- on_nan_event_disabled_user_callback(*event);
- }
-}
-
-std::function<void(const NanTCAInd&)> on_nan_event_tca_user_callback;
-void onAysncNanEventTca(NanTCAInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_tca_user_callback && event) {
- on_nan_event_tca_user_callback(*event);
- }
-}
-
-std::function<void(const NanBeaconSdfPayloadInd&)> on_nan_event_beacon_sdf_payload_user_callback;
-void onAysncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_beacon_sdf_payload_user_callback && event) {
- on_nan_event_beacon_sdf_payload_user_callback(*event);
- }
-}
-
-std::function<void(const NanDataPathRequestInd&)> on_nan_event_data_path_request_user_callback;
-void onAysncNanEventDataPathRequest(NanDataPathRequestInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_data_path_request_user_callback && event) {
- on_nan_event_data_path_request_user_callback(*event);
- }
-}
-std::function<void(const NanDataPathConfirmInd&)> on_nan_event_data_path_confirm_user_callback;
-void onAysncNanEventDataPathConfirm(NanDataPathConfirmInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_data_path_confirm_user_callback && event) {
- on_nan_event_data_path_confirm_user_callback(*event);
- }
-}
-
-std::function<void(const NanDataPathEndInd&)> on_nan_event_data_path_end_user_callback;
-void onAysncNanEventDataPathEnd(NanDataPathEndInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_data_path_end_user_callback && event) {
- on_nan_event_data_path_end_user_callback(*event);
- }
-}
-
-std::function<void(const NanTransmitFollowupInd&)> on_nan_event_transmit_follow_up_user_callback;
-void onAysncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_transmit_follow_up_user_callback && event) {
- on_nan_event_transmit_follow_up_user_callback(*event);
- }
-}
-
-std::function<void(const NanRangeRequestInd&)> on_nan_event_range_request_user_callback;
-void onAysncNanEventRangeRequest(NanRangeRequestInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_range_request_user_callback && event) {
- on_nan_event_range_request_user_callback(*event);
- }
-}
-
-std::function<void(const NanRangeReportInd&)> on_nan_event_range_report_user_callback;
-void onAysncNanEventRangeReport(NanRangeReportInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_range_report_user_callback && event) {
- on_nan_event_range_report_user_callback(*event);
- }
-}
-
-std::function<void(const NanDataPathScheduleUpdateInd&)> on_nan_event_schedule_update_user_callback;
-void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_nan_event_schedule_update_user_callback && event) {
- on_nan_event_schedule_update_user_callback(*event);
- }
-}
-
-// Callbacks for the various TWT operations.
-std::function<void(const TwtSetupResponse&)> on_twt_event_setup_response_callback;
-void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_twt_event_setup_response_callback && event) {
- on_twt_event_setup_response_callback(*event);
- }
-}
-
-std::function<void(const TwtTeardownCompletion&)> on_twt_event_teardown_completion_callback;
-void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_twt_event_teardown_completion_callback && event) {
- on_twt_event_teardown_completion_callback(*event);
- }
-}
-
-std::function<void(const TwtInfoFrameReceived&)> on_twt_event_info_frame_received_callback;
-void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_twt_event_info_frame_received_callback && event) {
- on_twt_event_info_frame_received_callback(*event);
- }
-}
-
-std::function<void(const TwtDeviceNotify&)> on_twt_event_device_notify_callback;
-void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_twt_event_device_notify_callback && event) {
- on_twt_event_device_notify_callback(*event);
- }
-}
-
-// Callback to report current CHRE NAN state
-std::function<void(chre_nan_rtt_state)> on_chre_nan_rtt_internal_callback;
-void onAsyncChreNanRttState(chre_nan_rtt_state state) {
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (on_chre_nan_rtt_internal_callback) {
- on_chre_nan_rtt_internal_callback(state);
- }
-}
-
-// End of the free-standing "C" style callbacks.
-
-WifiLegacyHal::WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool,
- const wifi_hal_fn& fn, bool is_primary)
- : global_func_table_(fn),
- global_handle_(nullptr),
- awaiting_event_loop_termination_(false),
- is_started_(false),
- iface_tool_(iface_tool),
- is_primary_(is_primary) {}
-
-wifi_error WifiLegacyHal::initialize() {
- LOG(DEBUG) << "Initialize legacy HAL";
- // this now does nothing, since HAL function table is provided
- // to the constructor
- return WIFI_SUCCESS;
-}
-
-wifi_error WifiLegacyHal::start() {
- // Ensure that we're starting in a good state.
- CHECK(global_func_table_.wifi_initialize && !global_handle_ && iface_name_to_handle_.empty() &&
- !awaiting_event_loop_termination_);
- if (is_started_) {
- LOG(DEBUG) << "Legacy HAL already started";
- return WIFI_SUCCESS;
- }
- LOG(DEBUG) << "Waiting for the driver ready";
- wifi_error status = global_func_table_.wifi_wait_for_driver_ready();
- if (status == WIFI_ERROR_TIMED_OUT || status == WIFI_ERROR_UNKNOWN) {
- LOG(ERROR) << "Failed or timed out awaiting driver ready";
- return status;
- }
-
- if (is_primary_) {
- property_set(kDriverPropName, "ok");
-
- if (!iface_tool_.lock()->SetWifiUpState(true)) {
- LOG(ERROR) << "Failed to set WiFi interface up";
- return WIFI_ERROR_UNKNOWN;
- }
- }
-
- LOG(DEBUG) << "Starting legacy HAL";
- status = global_func_table_.wifi_initialize(&global_handle_);
- if (status != WIFI_SUCCESS || !global_handle_) {
- LOG(ERROR) << "Failed to retrieve global handle";
- return status;
- }
- std::thread(&WifiLegacyHal::runEventLoop, this).detach();
- status = retrieveIfaceHandles();
- if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) {
- LOG(ERROR) << "Failed to retrieve wlan interface handle";
- return status;
- }
- LOG(DEBUG) << "Legacy HAL start complete";
- is_started_ = true;
- return WIFI_SUCCESS;
-}
-
-wifi_error WifiLegacyHal::stop(
- /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
- const std::function<void()>& on_stop_complete_user_callback) {
- if (!is_started_) {
- LOG(DEBUG) << "Legacy HAL already stopped";
- on_stop_complete_user_callback();
- return WIFI_SUCCESS;
- }
- LOG(DEBUG) << "Stopping legacy HAL";
- on_stop_complete_internal_callback = [on_stop_complete_user_callback,
- this](wifi_handle handle) {
- CHECK_EQ(global_handle_, handle) << "Handle mismatch";
- LOG(INFO) << "Legacy HAL stop complete callback received";
- // Invalidate all the internal pointers now that the HAL is
- // stopped.
- invalidate();
- if (is_primary_) iface_tool_.lock()->SetWifiUpState(false);
- on_stop_complete_user_callback();
- is_started_ = false;
- };
- awaiting_event_loop_termination_ = true;
- global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
- const auto status =
- stop_wait_cv_.wait_for(*lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
- [this] { return !awaiting_event_loop_termination_; });
- if (!status) {
- LOG(ERROR) << "Legacy HAL stop failed or timed out";
- return WIFI_ERROR_UNKNOWN;
- }
- LOG(DEBUG) << "Legacy HAL stop complete";
- return WIFI_SUCCESS;
-}
-
-bool WifiLegacyHal::isStarted() {
- return is_started_;
-}
-
-wifi_error WifiLegacyHal::waitForDriverReady() {
- return global_func_table_.wifi_wait_for_driver_ready();
-}
-
-std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion(const std::string& iface_name) {
- std::array<char, kMaxVersionStringLength> buffer;
- buffer.fill(0);
- wifi_error status = global_func_table_.wifi_get_driver_version(getIfaceHandle(iface_name),
- buffer.data(), buffer.size());
- return {status, buffer.data()};
-}
-
-std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion(
- const std::string& iface_name) {
- std::array<char, kMaxVersionStringLength> buffer;
- buffer.fill(0);
- wifi_error status = global_func_table_.wifi_get_firmware_version(getIfaceHandle(iface_name),
- buffer.data(), buffer.size());
- return {status, buffer.data()};
-}
-
-std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestDriverMemoryDump(
- const std::string& iface_name) {
- std::vector<uint8_t> driver_dump;
- on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer, int buffer_size) {
- driver_dump.insert(driver_dump.end(), reinterpret_cast<uint8_t*>(buffer),
- reinterpret_cast<uint8_t*>(buffer) + buffer_size);
- };
- wifi_error status = global_func_table_.wifi_get_driver_memory_dump(getIfaceHandle(iface_name),
- {onSyncDriverMemoryDump});
- on_driver_memory_dump_internal_callback = nullptr;
- return {status, std::move(driver_dump)};
-}
-
-std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestFirmwareMemoryDump(
- const std::string& iface_name) {
- std::vector<uint8_t> firmware_dump;
- on_firmware_memory_dump_internal_callback = [&firmware_dump](char* buffer, int buffer_size) {
- firmware_dump.insert(firmware_dump.end(), reinterpret_cast<uint8_t*>(buffer),
- reinterpret_cast<uint8_t*>(buffer) + buffer_size);
- };
- wifi_error status = global_func_table_.wifi_get_firmware_memory_dump(
- getIfaceHandle(iface_name), {onSyncFirmwareMemoryDump});
- on_firmware_memory_dump_internal_callback = nullptr;
- return {status, std::move(firmware_dump)};
-}
-
-std::pair<wifi_error, uint64_t> WifiLegacyHal::getSupportedFeatureSet(
- const std::string& iface_name) {
- feature_set set = 0, chip_set = 0;
- wifi_error status = WIFI_SUCCESS;
-
- static_assert(sizeof(set) == sizeof(uint64_t),
- "Some feature_flags can not be represented in output");
- wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
-
- global_func_table_.wifi_get_chip_feature_set(
- global_handle_, &chip_set); /* ignore error, chip_set will stay 0 */
-
- if (iface_handle) {
- status = global_func_table_.wifi_get_supported_feature_set(iface_handle, &set);
- }
- return {status, static_cast<uint64_t>(set | chip_set)};
-}
-
-std::pair<wifi_error, PacketFilterCapabilities> WifiLegacyHal::getPacketFilterCapabilities(
- const std::string& iface_name) {
- PacketFilterCapabilities caps;
- wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
- getIfaceHandle(iface_name), &caps.version, &caps.max_len);
- return {status, caps};
-}
-
-wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name,
- const std::vector<uint8_t>& program) {
- return global_func_table_.wifi_set_packet_filter(getIfaceHandle(iface_name), program.data(),
- program.size());
-}
-
-std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::readApfPacketFilterData(
- const std::string& iface_name) {
- PacketFilterCapabilities caps;
- wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
- getIfaceHandle(iface_name), &caps.version, &caps.max_len);
- if (status != WIFI_SUCCESS) {
- return {status, {}};
- }
-
- // Size the buffer to read the entire program & work memory.
- std::vector<uint8_t> buffer(caps.max_len);
-
- status = global_func_table_.wifi_read_packet_filter(
- getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(), buffer.size());
- return {status, std::move(buffer)};
-}
-
-std::pair<wifi_error, wifi_gscan_capabilities> WifiLegacyHal::getGscanCapabilities(
- const std::string& iface_name) {
- wifi_gscan_capabilities caps;
- wifi_error status =
- global_func_table_.wifi_get_gscan_capabilities(getIfaceHandle(iface_name), &caps);
- return {status, caps};
-}
-
-wifi_error WifiLegacyHal::startGscan(
- const std::string& iface_name, wifi_request_id id, const wifi_scan_cmd_params& params,
- const std::function<void(wifi_request_id)>& on_failure_user_callback,
- const on_gscan_results_callback& on_results_user_callback,
- const on_gscan_full_result_callback& on_full_result_user_callback) {
- // If there is already an ongoing background scan, reject new scan requests.
- if (on_gscan_event_internal_callback || on_gscan_full_result_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
-
- // This callback will be used to either trigger |on_results_user_callback|
- // or |on_failure_user_callback|.
- on_gscan_event_internal_callback = [iface_name, on_failure_user_callback,
- on_results_user_callback,
- this](wifi_request_id id, wifi_scan_event event) {
- switch (event) {
- case WIFI_SCAN_RESULTS_AVAILABLE:
- case WIFI_SCAN_THRESHOLD_NUM_SCANS:
- case WIFI_SCAN_THRESHOLD_PERCENT: {
- wifi_error status;
- std::vector<wifi_cached_scan_results> cached_scan_results;
- std::tie(status, cached_scan_results) = getGscanCachedResults(iface_name);
- if (status == WIFI_SUCCESS) {
- on_results_user_callback(id, cached_scan_results);
- return;
- }
- FALLTHROUGH_INTENDED;
- }
- // Fall through if failed. Failure to retrieve cached scan
- // results should trigger a background scan failure.
- case WIFI_SCAN_FAILED:
- on_failure_user_callback(id);
- on_gscan_event_internal_callback = nullptr;
- on_gscan_full_result_internal_callback = nullptr;
- return;
- }
- LOG(FATAL) << "Unexpected gscan event received: " << event;
- };
-
- on_gscan_full_result_internal_callback = [on_full_result_user_callback](
- wifi_request_id id, wifi_scan_result* result,
- uint32_t buckets_scanned) {
- if (result) {
- on_full_result_user_callback(id, result, buckets_scanned);
- }
- };
-
- wifi_scan_result_handler handler = {onAsyncGscanFullResult, onAsyncGscanEvent};
- wifi_error status =
- global_func_table_.wifi_start_gscan(id, getIfaceHandle(iface_name), params, handler);
- if (status != WIFI_SUCCESS) {
- on_gscan_event_internal_callback = nullptr;
- on_gscan_full_result_internal_callback = nullptr;
- }
- return status;
-}
-
-wifi_error WifiLegacyHal::stopGscan(const std::string& iface_name, wifi_request_id id) {
- // If there is no an ongoing background scan, reject stop requests.
- // TODO(b/32337212): This needs to be handled by the HIDL object because we
- // need to return the NOT_STARTED error code.
- if (!on_gscan_event_internal_callback && !on_gscan_full_result_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- wifi_error status = global_func_table_.wifi_stop_gscan(id, getIfaceHandle(iface_name));
- // If the request Id is wrong, don't stop the ongoing background scan. Any
- // other error should be treated as the end of background scan.
- if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
- on_gscan_event_internal_callback = nullptr;
- on_gscan_full_result_internal_callback = nullptr;
- }
- return status;
-}
-
-std::pair<wifi_error, std::vector<uint32_t>> WifiLegacyHal::getValidFrequenciesForBand(
- const std::string& iface_name, wifi_band band) {
- static_assert(sizeof(uint32_t) >= sizeof(wifi_channel),
- "Wifi Channel cannot be represented in output");
- std::vector<uint32_t> freqs;
- freqs.resize(kMaxGscanFrequenciesForBand);
- int32_t num_freqs = 0;
- wifi_error status = global_func_table_.wifi_get_valid_channels(
- getIfaceHandle(iface_name), band, freqs.size(),
- reinterpret_cast<wifi_channel*>(freqs.data()), &num_freqs);
- CHECK(num_freqs >= 0 && static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand);
- freqs.resize(num_freqs);
- return {status, std::move(freqs)};
-}
-
-wifi_error WifiLegacyHal::setDfsFlag(const std::string& iface_name, bool dfs_on) {
- return global_func_table_.wifi_set_nodfs_flag(getIfaceHandle(iface_name), dfs_on ? 0 : 1);
-}
-
-wifi_error WifiLegacyHal::enableLinkLayerStats(const std::string& iface_name, bool debug) {
- wifi_link_layer_params params;
- params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold;
- params.aggressive_statistics_gathering = debug;
- return global_func_table_.wifi_set_link_stats(getIfaceHandle(iface_name), params);
-}
-
-wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) {
- // TODO: Do we care about these responses?
- uint32_t clear_mask_rsp;
- uint8_t stop_rsp;
- return global_func_table_.wifi_clear_link_stats(getIfaceHandle(iface_name), 0xFFFFFFFF,
- &clear_mask_rsp, 1, &stop_rsp);
-}
-
-std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats(
- const std::string& iface_name) {
- LinkLayerStats link_stats{};
- LinkLayerStats* link_stats_ptr = &link_stats;
-
- on_link_layer_stats_result_internal_callback = [&link_stats_ptr](
- wifi_request_id /* id */,
- wifi_iface_stat* iface_stats_ptr,
- int num_radios,
- wifi_radio_stat* radio_stats_ptr) {
- wifi_radio_stat* l_radio_stats_ptr;
- wifi_peer_info* l_peer_info_stats_ptr;
-
- if (iface_stats_ptr != nullptr) {
- link_stats_ptr->iface = *iface_stats_ptr;
- l_peer_info_stats_ptr = iface_stats_ptr->peer_info;
- for (uint32_t i = 0; i < iface_stats_ptr->num_peers; i++) {
- WifiPeerInfo peer;
- peer.peer_info = *l_peer_info_stats_ptr;
- if (l_peer_info_stats_ptr->num_rate > 0) {
- /* Copy the rate stats */
- peer.rate_stats.assign(
- l_peer_info_stats_ptr->rate_stats,
- l_peer_info_stats_ptr->rate_stats + l_peer_info_stats_ptr->num_rate);
- }
- peer.peer_info.num_rate = 0;
- link_stats_ptr->peers.push_back(peer);
- l_peer_info_stats_ptr =
- (wifi_peer_info*)((u8*)l_peer_info_stats_ptr + sizeof(wifi_peer_info) +
- (sizeof(wifi_rate_stat) *
- l_peer_info_stats_ptr->num_rate));
- }
- link_stats_ptr->iface.num_peers = 0;
- } else {
- LOG(ERROR) << "Invalid iface stats in link layer stats";
- }
- if (num_radios <= 0 || radio_stats_ptr == nullptr) {
- LOG(ERROR) << "Invalid radio stats in link layer stats";
- return;
- }
- l_radio_stats_ptr = radio_stats_ptr;
- for (int i = 0; i < num_radios; i++) {
- LinkLayerRadioStats radio;
-
- radio.stats = *l_radio_stats_ptr;
- // Copy over the tx level array to the separate vector.
- if (l_radio_stats_ptr->num_tx_levels > 0 &&
- l_radio_stats_ptr->tx_time_per_levels != nullptr) {
- radio.tx_time_per_levels.assign(
- l_radio_stats_ptr->tx_time_per_levels,
- l_radio_stats_ptr->tx_time_per_levels + l_radio_stats_ptr->num_tx_levels);
- }
- radio.stats.num_tx_levels = 0;
- radio.stats.tx_time_per_levels = nullptr;
- /* Copy over the channel stat to separate vector */
- if (l_radio_stats_ptr->num_channels > 0) {
- /* Copy the channel stats */
- radio.channel_stats.assign(
- l_radio_stats_ptr->channels,
- l_radio_stats_ptr->channels + l_radio_stats_ptr->num_channels);
- }
- link_stats_ptr->radios.push_back(radio);
- l_radio_stats_ptr =
- (wifi_radio_stat*)((u8*)l_radio_stats_ptr + sizeof(wifi_radio_stat) +
- (sizeof(wifi_channel_stat) *
- l_radio_stats_ptr->num_channels));
- }
- };
-
- wifi_error status = global_func_table_.wifi_get_link_stats(0, getIfaceHandle(iface_name),
- {onSyncLinkLayerStatsResult});
- on_link_layer_stats_result_internal_callback = nullptr;
- return {status, link_stats};
-}
-
-wifi_error WifiLegacyHal::startRssiMonitoring(
- const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi,
- const on_rssi_threshold_breached_callback& on_threshold_breached_user_callback) {
- if (on_rssi_threshold_breached_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- on_rssi_threshold_breached_internal_callback = [on_threshold_breached_user_callback](
- wifi_request_id id, uint8_t* bssid_ptr,
- int8_t rssi) {
- if (!bssid_ptr) {
- return;
- }
- std::array<uint8_t, 6> bssid_arr;
- // |bssid_ptr| pointer is assumed to have 6 bytes for the mac
- // address.
- std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr));
- on_threshold_breached_user_callback(id, bssid_arr, rssi);
- };
- wifi_error status = global_func_table_.wifi_start_rssi_monitoring(
- id, getIfaceHandle(iface_name), max_rssi, min_rssi, {onAsyncRssiThresholdBreached});
- if (status != WIFI_SUCCESS) {
- on_rssi_threshold_breached_internal_callback = nullptr;
- }
- return status;
-}
-
-wifi_error WifiLegacyHal::stopRssiMonitoring(const std::string& iface_name, wifi_request_id id) {
- if (!on_rssi_threshold_breached_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- wifi_error status =
- global_func_table_.wifi_stop_rssi_monitoring(id, getIfaceHandle(iface_name));
- // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any
- // other error should be treated as the end of background scan.
- if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
- on_rssi_threshold_breached_internal_callback = nullptr;
- }
- return status;
-}
-
-std::pair<wifi_error, wifi_roaming_capabilities> WifiLegacyHal::getRoamingCapabilities(
- const std::string& iface_name) {
- wifi_roaming_capabilities caps;
- wifi_error status =
- global_func_table_.wifi_get_roaming_capabilities(getIfaceHandle(iface_name), &caps);
- return {status, caps};
-}
-
-wifi_error WifiLegacyHal::configureRoaming(const std::string& iface_name,
- const wifi_roaming_config& config) {
- wifi_roaming_config config_internal = config;
- return global_func_table_.wifi_configure_roaming(getIfaceHandle(iface_name), &config_internal);
-}
-
-wifi_error WifiLegacyHal::enableFirmwareRoaming(const std::string& iface_name,
- fw_roaming_state_t state) {
- return global_func_table_.wifi_enable_firmware_roaming(getIfaceHandle(iface_name), state);
-}
-
-wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name, bool enable) {
- return global_func_table_.wifi_configure_nd_offload(getIfaceHandle(iface_name), enable);
-}
-
-wifi_error WifiLegacyHal::startSendingOffloadedPacket(const std::string& iface_name,
- uint32_t cmd_id, uint16_t ether_type,
- const std::vector<uint8_t>& ip_packet_data,
- const std::array<uint8_t, 6>& src_address,
- const std::array<uint8_t, 6>& dst_address,
- uint32_t period_in_ms) {
- std::vector<uint8_t> ip_packet_data_internal(ip_packet_data);
- std::vector<uint8_t> src_address_internal(src_address.data(),
- src_address.data() + src_address.size());
- std::vector<uint8_t> dst_address_internal(dst_address.data(),
- dst_address.data() + dst_address.size());
- return global_func_table_.wifi_start_sending_offloaded_packet(
- cmd_id, getIfaceHandle(iface_name), ether_type, ip_packet_data_internal.data(),
- ip_packet_data_internal.size(), src_address_internal.data(),
- dst_address_internal.data(), period_in_ms);
-}
-
-wifi_error WifiLegacyHal::stopSendingOffloadedPacket(const std::string& iface_name,
- uint32_t cmd_id) {
- return global_func_table_.wifi_stop_sending_offloaded_packet(cmd_id,
- getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name,
- wifi_power_scenario scenario) {
- return global_func_table_.wifi_select_tx_power_scenario(getIfaceHandle(iface_name), scenario);
-}
-
-wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) {
- return global_func_table_.wifi_reset_tx_power_scenario(getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::setLatencyMode(const std::string& iface_name, wifi_latency_mode mode) {
- return global_func_table_.wifi_set_latency_mode(getIfaceHandle(iface_name), mode);
-}
-
-wifi_error WifiLegacyHal::setThermalMitigationMode(wifi_thermal_mode mode,
- uint32_t completion_window) {
- return global_func_table_.wifi_set_thermal_mitigation_mode(global_handle_, mode,
- completion_window);
-}
-
-wifi_error WifiLegacyHal::setDscpToAccessCategoryMapping(uint32_t start, uint32_t end,
- uint32_t access_category) {
- return global_func_table_.wifi_map_dscp_access_category(global_handle_, start, end,
- access_category);
-}
-
-wifi_error WifiLegacyHal::resetDscpToAccessCategoryMapping() {
- return global_func_table_.wifi_reset_dscp_mapping(global_handle_);
-}
-
-std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet(
- const std::string& iface_name) {
- uint32_t supported_feature_flags = 0;
- wifi_error status = WIFI_SUCCESS;
-
- wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
-
- if (iface_handle) {
- status = global_func_table_.wifi_get_logger_supported_feature_set(iface_handle,
- &supported_feature_flags);
- }
- return {status, supported_feature_flags};
-}
-
-wifi_error WifiLegacyHal::startPktFateMonitoring(const std::string& iface_name) {
- return global_func_table_.wifi_start_pkt_fate_monitoring(getIfaceHandle(iface_name));
-}
-
-std::pair<wifi_error, std::vector<wifi_tx_report>> WifiLegacyHal::getTxPktFates(
- const std::string& iface_name) {
- std::vector<wifi_tx_report> tx_pkt_fates;
- tx_pkt_fates.resize(MAX_FATE_LOG_LEN);
- size_t num_fates = 0;
- wifi_error status = global_func_table_.wifi_get_tx_pkt_fates(
- getIfaceHandle(iface_name), tx_pkt_fates.data(), tx_pkt_fates.size(), &num_fates);
- CHECK(num_fates <= MAX_FATE_LOG_LEN);
- tx_pkt_fates.resize(num_fates);
- return {status, std::move(tx_pkt_fates)};
-}
-
-std::pair<wifi_error, std::vector<wifi_rx_report>> WifiLegacyHal::getRxPktFates(
- const std::string& iface_name) {
- std::vector<wifi_rx_report> rx_pkt_fates;
- rx_pkt_fates.resize(MAX_FATE_LOG_LEN);
- size_t num_fates = 0;
- wifi_error status = global_func_table_.wifi_get_rx_pkt_fates(
- getIfaceHandle(iface_name), rx_pkt_fates.data(), rx_pkt_fates.size(), &num_fates);
- CHECK(num_fates <= MAX_FATE_LOG_LEN);
- rx_pkt_fates.resize(num_fates);
- return {status, std::move(rx_pkt_fates)};
-}
-
-std::pair<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats(
- const std::string& iface_name) {
- WakeReasonStats stats;
- stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
- stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
-
- // This legacy struct needs separate memory to store the variable sized wake
- // reason types.
- stats.wake_reason_cnt.cmd_event_wake_cnt =
- reinterpret_cast<int32_t*>(stats.cmd_event_wake_cnt.data());
- stats.wake_reason_cnt.cmd_event_wake_cnt_sz = stats.cmd_event_wake_cnt.size();
- stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0;
- stats.wake_reason_cnt.driver_fw_local_wake_cnt =
- reinterpret_cast<int32_t*>(stats.driver_fw_local_wake_cnt.data());
- stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz = stats.driver_fw_local_wake_cnt.size();
- stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0;
-
- wifi_error status = global_func_table_.wifi_get_wake_reason_stats(getIfaceHandle(iface_name),
- &stats.wake_reason_cnt);
-
- CHECK(stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 &&
- static_cast<uint32_t>(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <=
- kMaxWakeReasonStatsArraySize);
- stats.cmd_event_wake_cnt.resize(stats.wake_reason_cnt.cmd_event_wake_cnt_used);
- stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr;
-
- CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 &&
- static_cast<uint32_t>(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <=
- kMaxWakeReasonStatsArraySize);
- stats.driver_fw_local_wake_cnt.resize(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used);
- stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr;
-
- return {status, stats};
-}
-
-wifi_error WifiLegacyHal::registerRingBufferCallbackHandler(
- const std::string& iface_name, const on_ring_buffer_data_callback& on_user_data_callback) {
- if (on_ring_buffer_data_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- on_ring_buffer_data_internal_callback = [on_user_data_callback](
- char* ring_name, char* buffer, int buffer_size,
- wifi_ring_buffer_status* status) {
- if (status && buffer) {
- std::vector<uint8_t> buffer_vector(reinterpret_cast<uint8_t*>(buffer),
- reinterpret_cast<uint8_t*>(buffer) + buffer_size);
- on_user_data_callback(ring_name, buffer_vector, *status);
- }
- };
- wifi_error status = global_func_table_.wifi_set_log_handler(0, getIfaceHandle(iface_name),
- {onAsyncRingBufferData});
- if (status != WIFI_SUCCESS) {
- on_ring_buffer_data_internal_callback = nullptr;
- }
- return status;
-}
-
-wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler(const std::string& iface_name) {
- if (!on_ring_buffer_data_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- on_ring_buffer_data_internal_callback = nullptr;
- return global_func_table_.wifi_reset_log_handler(0, getIfaceHandle(iface_name));
-}
-
-std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> WifiLegacyHal::getRingBuffersStatus(
- const std::string& iface_name) {
- std::vector<wifi_ring_buffer_status> ring_buffers_status;
- ring_buffers_status.resize(kMaxRingBuffers);
- uint32_t num_rings = kMaxRingBuffers;
- wifi_error status = global_func_table_.wifi_get_ring_buffers_status(
- getIfaceHandle(iface_name), &num_rings, ring_buffers_status.data());
- CHECK(num_rings <= kMaxRingBuffers);
- ring_buffers_status.resize(num_rings);
- return {status, std::move(ring_buffers_status)};
-}
-
-wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& iface_name,
- const std::string& ring_name,
- uint32_t verbose_level, uint32_t max_interval_sec,
- uint32_t min_data_size) {
- return global_func_table_.wifi_start_logging(getIfaceHandle(iface_name), verbose_level, 0,
- max_interval_sec, min_data_size,
- makeCharVec(ring_name).data());
-}
-
-wifi_error WifiLegacyHal::getRingBufferData(const std::string& iface_name,
- const std::string& ring_name) {
- return global_func_table_.wifi_get_ring_data(getIfaceHandle(iface_name),
- makeCharVec(ring_name).data());
-}
-
-wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler(
- const std::string& iface_name, const on_error_alert_callback& on_user_alert_callback) {
- if (on_error_alert_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- on_error_alert_internal_callback = [on_user_alert_callback](wifi_request_id id, char* buffer,
- int buffer_size, int err_code) {
- if (buffer) {
- CHECK(id == 0);
- on_user_alert_callback(
- err_code,
- std::vector<uint8_t>(reinterpret_cast<uint8_t*>(buffer),
- reinterpret_cast<uint8_t*>(buffer) + buffer_size));
- }
- };
- wifi_error status = global_func_table_.wifi_set_alert_handler(0, getIfaceHandle(iface_name),
- {onAsyncErrorAlert});
- if (status != WIFI_SUCCESS) {
- on_error_alert_internal_callback = nullptr;
- }
- return status;
-}
-
-wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler(const std::string& iface_name) {
- if (!on_error_alert_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- on_error_alert_internal_callback = nullptr;
- return global_func_table_.wifi_reset_alert_handler(0, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler(
- const std::string& iface_name,
- const on_radio_mode_change_callback& on_user_change_callback) {
- if (on_radio_mode_change_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- on_radio_mode_change_internal_callback = [on_user_change_callback](
- wifi_request_id /* id */, uint32_t num_macs,
- wifi_mac_info* mac_infos_arr) {
- if (num_macs > 0 && mac_infos_arr) {
- std::vector<WifiMacInfo> mac_infos_vec;
- for (uint32_t i = 0; i < num_macs; i++) {
- WifiMacInfo mac_info;
- mac_info.wlan_mac_id = mac_infos_arr[i].wlan_mac_id;
- mac_info.mac_band = mac_infos_arr[i].mac_band;
- for (int32_t j = 0; j < mac_infos_arr[i].num_iface; j++) {
- WifiIfaceInfo iface_info;
- iface_info.name = mac_infos_arr[i].iface_info[j].iface_name;
- iface_info.channel = mac_infos_arr[i].iface_info[j].channel;
- mac_info.iface_infos.push_back(iface_info);
- }
- mac_infos_vec.push_back(mac_info);
- }
- on_user_change_callback(mac_infos_vec);
- }
- };
- wifi_error status = global_func_table_.wifi_set_radio_mode_change_handler(
- 0, getIfaceHandle(iface_name), {onAsyncRadioModeChange});
- if (status != WIFI_SUCCESS) {
- on_radio_mode_change_internal_callback = nullptr;
- }
- return status;
-}
-
-wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler(
- const on_subsystem_restart_callback& on_restart_callback) {
- if (on_subsystem_restart_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- on_subsystem_restart_internal_callback = [on_restart_callback](const char* error) {
- on_restart_callback(error);
- };
- wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler(
- global_handle_, {onAsyncSubsystemRestart});
- if (status != WIFI_SUCCESS) {
- on_subsystem_restart_internal_callback = nullptr;
- }
- return status;
-}
-
-wifi_error WifiLegacyHal::startRttRangeRequest(
- const std::string& iface_name, wifi_request_id id,
- const std::vector<wifi_rtt_config>& rtt_configs,
- const on_rtt_results_callback& on_results_user_callback) {
- if (on_rtt_results_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
-
- on_rtt_results_internal_callback = [on_results_user_callback](wifi_request_id id,
- unsigned num_results,
- wifi_rtt_result* rtt_results[]) {
- if (num_results > 0 && !rtt_results) {
- LOG(ERROR) << "Unexpected nullptr in RTT results";
- return;
- }
- std::vector<const wifi_rtt_result*> rtt_results_vec;
- std::copy_if(rtt_results, rtt_results + num_results, back_inserter(rtt_results_vec),
- [](wifi_rtt_result* rtt_result) { return rtt_result != nullptr; });
- on_results_user_callback(id, rtt_results_vec);
- };
-
- std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs);
- wifi_error status = global_func_table_.wifi_rtt_range_request(
- id, getIfaceHandle(iface_name), rtt_configs.size(), rtt_configs_internal.data(),
- {onAsyncRttResults});
- if (status != WIFI_SUCCESS) {
- on_rtt_results_internal_callback = nullptr;
- }
- return status;
-}
-
-wifi_error WifiLegacyHal::cancelRttRangeRequest(
- const std::string& iface_name, wifi_request_id id,
- const std::vector<std::array<uint8_t, 6>>& mac_addrs) {
- if (!on_rtt_results_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
- static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, 6>), "MAC address size mismatch");
- // TODO: How do we handle partial cancels (i.e only a subset of enabled mac
- // addressed are cancelled).
- std::vector<std::array<uint8_t, 6>> mac_addrs_internal(mac_addrs);
- wifi_error status = global_func_table_.wifi_rtt_range_cancel(
- id, getIfaceHandle(iface_name), mac_addrs.size(),
- reinterpret_cast<mac_addr*>(mac_addrs_internal.data()));
- // If the request Id is wrong, don't stop the ongoing range request. Any
- // other error should be treated as the end of rtt ranging.
- if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
- on_rtt_results_internal_callback = nullptr;
- }
- return status;
-}
-
-std::pair<wifi_error, wifi_rtt_capabilities> WifiLegacyHal::getRttCapabilities(
- const std::string& iface_name) {
- wifi_rtt_capabilities rtt_caps;
- wifi_error status =
- global_func_table_.wifi_get_rtt_capabilities(getIfaceHandle(iface_name), &rtt_caps);
- return {status, rtt_caps};
-}
-
-std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo(
- const std::string& iface_name) {
- wifi_rtt_responder rtt_responder;
- wifi_error status = global_func_table_.wifi_rtt_get_responder_info(getIfaceHandle(iface_name),
- &rtt_responder);
- return {status, rtt_responder};
-}
-
-wifi_error WifiLegacyHal::enableRttResponder(const std::string& iface_name, wifi_request_id id,
- const wifi_channel_info& channel_hint,
- uint32_t max_duration_secs,
- const wifi_rtt_responder& info) {
- wifi_rtt_responder info_internal(info);
- return global_func_table_.wifi_enable_responder(id, getIfaceHandle(iface_name), channel_hint,
- max_duration_secs, &info_internal);
-}
-
-wifi_error WifiLegacyHal::disableRttResponder(const std::string& iface_name, wifi_request_id id) {
- return global_func_table_.wifi_disable_responder(id, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::setRttLci(const std::string& iface_name, wifi_request_id id,
- const wifi_lci_information& info) {
- wifi_lci_information info_internal(info);
- return global_func_table_.wifi_set_lci(id, getIfaceHandle(iface_name), &info_internal);
-}
-
-wifi_error WifiLegacyHal::setRttLcr(const std::string& iface_name, wifi_request_id id,
- const wifi_lcr_information& info) {
- wifi_lcr_information info_internal(info);
- return global_func_table_.wifi_set_lcr(id, getIfaceHandle(iface_name), &info_internal);
-}
-
-wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(const std::string& iface_name,
- const NanCallbackHandlers& user_callbacks) {
- on_nan_notify_response_user_callback = user_callbacks.on_notify_response;
- on_nan_event_publish_terminated_user_callback = user_callbacks.on_event_publish_terminated;
- on_nan_event_match_user_callback = user_callbacks.on_event_match;
- on_nan_event_match_expired_user_callback = user_callbacks.on_event_match_expired;
- on_nan_event_subscribe_terminated_user_callback = user_callbacks.on_event_subscribe_terminated;
- on_nan_event_followup_user_callback = user_callbacks.on_event_followup;
- on_nan_event_disc_eng_event_user_callback = user_callbacks.on_event_disc_eng_event;
- on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled;
- on_nan_event_tca_user_callback = user_callbacks.on_event_tca;
- on_nan_event_beacon_sdf_payload_user_callback = user_callbacks.on_event_beacon_sdf_payload;
- on_nan_event_data_path_request_user_callback = user_callbacks.on_event_data_path_request;
- on_nan_event_data_path_confirm_user_callback = user_callbacks.on_event_data_path_confirm;
- on_nan_event_data_path_end_user_callback = user_callbacks.on_event_data_path_end;
- on_nan_event_transmit_follow_up_user_callback = user_callbacks.on_event_transmit_follow_up;
- on_nan_event_range_request_user_callback = user_callbacks.on_event_range_request;
- on_nan_event_range_report_user_callback = user_callbacks.on_event_range_report;
- on_nan_event_schedule_update_user_callback = user_callbacks.on_event_schedule_update;
-
- return global_func_table_.wifi_nan_register_handler(
- getIfaceHandle(iface_name),
- {onAysncNanNotifyResponse, onAysncNanEventPublishReplied,
- onAysncNanEventPublishTerminated, onAysncNanEventMatch, onAysncNanEventMatchExpired,
- onAysncNanEventSubscribeTerminated, onAysncNanEventFollowup,
- onAysncNanEventDiscEngEvent, onAysncNanEventDisabled, onAysncNanEventTca,
- onAysncNanEventBeaconSdfPayload, onAysncNanEventDataPathRequest,
- onAysncNanEventDataPathConfirm, onAysncNanEventDataPathEnd,
- onAysncNanEventTransmitFollowUp, onAysncNanEventRangeRequest,
- onAysncNanEventRangeReport, onAsyncNanEventScheduleUpdate});
-}
-
-wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name, transaction_id id,
- const NanEnableRequest& msg) {
- NanEnableRequest msg_internal(msg);
- return global_func_table_.wifi_nan_enable_request(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanDisableRequest(const std::string& iface_name, transaction_id id) {
- return global_func_table_.wifi_nan_disable_request(id, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::nanPublishRequest(const std::string& iface_name, transaction_id id,
- const NanPublishRequest& msg) {
- NanPublishRequest msg_internal(msg);
- return global_func_table_.wifi_nan_publish_request(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanPublishCancelRequest(const std::string& iface_name, transaction_id id,
- const NanPublishCancelRequest& msg) {
- NanPublishCancelRequest msg_internal(msg);
- return global_func_table_.wifi_nan_publish_cancel_request(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanSubscribeRequest(const std::string& iface_name, transaction_id id,
- const NanSubscribeRequest& msg) {
- NanSubscribeRequest msg_internal(msg);
- return global_func_table_.wifi_nan_subscribe_request(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanSubscribeCancelRequest(const std::string& iface_name,
- transaction_id id,
- const NanSubscribeCancelRequest& msg) {
- NanSubscribeCancelRequest msg_internal(msg);
- return global_func_table_.wifi_nan_subscribe_cancel_request(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanTransmitFollowupRequest(const std::string& iface_name,
- transaction_id id,
- const NanTransmitFollowupRequest& msg) {
- NanTransmitFollowupRequest msg_internal(msg);
- return global_func_table_.wifi_nan_transmit_followup_request(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanStatsRequest(const std::string& iface_name, transaction_id id,
- const NanStatsRequest& msg) {
- NanStatsRequest msg_internal(msg);
- return global_func_table_.wifi_nan_stats_request(id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanConfigRequest(const std::string& iface_name, transaction_id id,
- const NanConfigRequest& msg) {
- NanConfigRequest msg_internal(msg);
- return global_func_table_.wifi_nan_config_request(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanTcaRequest(const std::string& iface_name, transaction_id id,
- const NanTCARequest& msg) {
- NanTCARequest msg_internal(msg);
- return global_func_table_.wifi_nan_tca_request(id, getIfaceHandle(iface_name), &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest(const std::string& iface_name,
- transaction_id id,
- const NanBeaconSdfPayloadRequest& msg) {
- NanBeaconSdfPayloadRequest msg_internal(msg);
- return global_func_table_.wifi_nan_beacon_sdf_payload_request(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-std::pair<wifi_error, NanVersion> WifiLegacyHal::nanGetVersion() {
- NanVersion version;
- wifi_error status = global_func_table_.wifi_nan_get_version(global_handle_, &version);
- return {status, version};
-}
-
-wifi_error WifiLegacyHal::nanGetCapabilities(const std::string& iface_name, transaction_id id) {
- return global_func_table_.wifi_nan_get_capabilities(id, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::nanDataInterfaceCreate(const std::string& iface_name, transaction_id id,
- const std::string& data_iface_name) {
- return global_func_table_.wifi_nan_data_interface_create(id, getIfaceHandle(iface_name),
- makeCharVec(data_iface_name).data());
-}
-
-wifi_error WifiLegacyHal::nanDataInterfaceDelete(const std::string& iface_name, transaction_id id,
- const std::string& data_iface_name) {
- return global_func_table_.wifi_nan_data_interface_delete(id, getIfaceHandle(iface_name),
- makeCharVec(data_iface_name).data());
-}
-
-wifi_error WifiLegacyHal::nanDataRequestInitiator(const std::string& iface_name, transaction_id id,
- const NanDataPathInitiatorRequest& msg) {
- NanDataPathInitiatorRequest msg_internal(msg);
- return global_func_table_.wifi_nan_data_request_initiator(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-wifi_error WifiLegacyHal::nanDataIndicationResponse(const std::string& iface_name,
- transaction_id id,
- const NanDataPathIndicationResponse& msg) {
- NanDataPathIndicationResponse msg_internal(msg);
- return global_func_table_.wifi_nan_data_indication_response(id, getIfaceHandle(iface_name),
- &msg_internal);
-}
-
-typedef struct {
- u8 num_ndp_instances;
- NanDataPathId ndp_instance_id;
-} NanDataPathEndSingleNdpIdRequest;
-
-wifi_error WifiLegacyHal::nanDataEnd(const std::string& iface_name, transaction_id id,
- uint32_t ndpInstanceId) {
- NanDataPathEndSingleNdpIdRequest msg;
- msg.num_ndp_instances = 1;
- msg.ndp_instance_id = ndpInstanceId;
- wifi_error status = global_func_table_.wifi_nan_data_end(id, getIfaceHandle(iface_name),
- (NanDataPathEndRequest*)&msg);
- return status;
-}
-
-wifi_error WifiLegacyHal::setCountryCode(const std::string& iface_name,
- std::array<int8_t, 2> code) {
- std::string code_str(code.data(), code.data() + code.size());
- return global_func_table_.wifi_set_country_code(getIfaceHandle(iface_name), code_str.c_str());
-}
-
-wifi_error WifiLegacyHal::retrieveIfaceHandles() {
- wifi_interface_handle* iface_handles = nullptr;
- int num_iface_handles = 0;
- wifi_error status =
- global_func_table_.wifi_get_ifaces(global_handle_, &num_iface_handles, &iface_handles);
- if (status != WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to enumerate interface handles";
- return status;
- }
- iface_name_to_handle_.clear();
- for (int i = 0; i < num_iface_handles; ++i) {
- std::array<char, IFNAMSIZ> iface_name_arr = {};
- status = global_func_table_.wifi_get_iface_name(iface_handles[i], iface_name_arr.data(),
- iface_name_arr.size());
- if (status != WIFI_SUCCESS) {
- LOG(WARNING) << "Failed to get interface handle name";
- continue;
- }
- // Assuming the interface name is null terminated since the legacy HAL
- // API does not return a size.
- std::string iface_name(iface_name_arr.data());
- LOG(INFO) << "Adding interface handle for " << iface_name;
- iface_name_to_handle_[iface_name] = iface_handles[i];
- }
- return WIFI_SUCCESS;
-}
-
-wifi_interface_handle WifiLegacyHal::getIfaceHandle(const std::string& iface_name) {
- const auto iface_handle_iter = iface_name_to_handle_.find(iface_name);
- if (iface_handle_iter == iface_name_to_handle_.end()) {
- LOG(ERROR) << "Unknown iface name: " << iface_name;
- return nullptr;
- }
- return iface_handle_iter->second;
-}
-
-void WifiLegacyHal::runEventLoop() {
- LOG(DEBUG) << "Starting legacy HAL event loop";
- global_func_table_.wifi_event_loop(global_handle_);
- const auto lock = hidl_sync_util::acquireGlobalLock();
- if (!awaiting_event_loop_termination_) {
- LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
- }
- LOG(DEBUG) << "Legacy HAL event loop terminated";
- awaiting_event_loop_termination_ = false;
- stop_wait_cv_.notify_one();
-}
-
-std::pair<wifi_error, std::vector<wifi_cached_scan_results>> WifiLegacyHal::getGscanCachedResults(
- const std::string& iface_name) {
- std::vector<wifi_cached_scan_results> cached_scan_results;
- cached_scan_results.resize(kMaxCachedGscanResults);
- int32_t num_results = 0;
- wifi_error status = global_func_table_.wifi_get_cached_gscan_results(
- getIfaceHandle(iface_name), true /* always flush */, cached_scan_results.size(),
- cached_scan_results.data(), &num_results);
- CHECK(num_results >= 0 && static_cast<uint32_t>(num_results) <= kMaxCachedGscanResults);
- cached_scan_results.resize(num_results);
- // Check for invalid IE lengths in these cached scan results and correct it.
- for (auto& cached_scan_result : cached_scan_results) {
- int num_scan_results = cached_scan_result.num_results;
- for (int i = 0; i < num_scan_results; i++) {
- auto& scan_result = cached_scan_result.results[i];
- if (scan_result.ie_length > 0) {
- LOG(DEBUG) << "Cached scan result has non-zero IE length " << scan_result.ie_length;
- scan_result.ie_length = 0;
- }
- }
- }
- return {status, std::move(cached_scan_results)};
-}
-
-wifi_error WifiLegacyHal::createVirtualInterface(const std::string& ifname,
- wifi_interface_type iftype) {
- // Create the interface if it doesn't exist. If interface already exist,
- // Vendor Hal should return WIFI_SUCCESS.
- wifi_error status = global_func_table_.wifi_virtual_interface_create(global_handle_,
- ifname.c_str(), iftype);
- return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
-}
-
-wifi_error WifiLegacyHal::deleteVirtualInterface(const std::string& ifname) {
- // Delete the interface if it was created dynamically.
- wifi_error status =
- global_func_table_.wifi_virtual_interface_delete(global_handle_, ifname.c_str());
- return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
-}
-
-wifi_error WifiLegacyHal::handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname,
- wifi_error status) {
- if (status == WIFI_SUCCESS) {
- // refresh list of handlers now.
- status = retrieveIfaceHandles();
- } else if (status == WIFI_ERROR_NOT_SUPPORTED) {
- // Vendor hal does not implement this API. Such vendor implementations
- // are expected to create / delete interface by other means.
-
- // check if interface exists.
- if (if_nametoindex(ifname.c_str())) {
- status = retrieveIfaceHandles();
- }
- }
- return status;
-}
-
-wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type, std::string& ifname) {
- std::array<char, IFNAMSIZ> buffer;
-
- wifi_error res = global_func_table_.wifi_get_supported_iface_name(
- global_handle_, (uint32_t)iface_type, buffer.data(), buffer.size());
- if (res == WIFI_SUCCESS) ifname = buffer.data();
-
- return res;
-}
-
-wifi_error WifiLegacyHal::multiStaSetPrimaryConnection(const std::string& ifname) {
- return global_func_table_.wifi_multi_sta_set_primary_connection(global_handle_,
- getIfaceHandle(ifname));
-}
-
-wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) {
- return global_func_table_.wifi_multi_sta_set_use_case(global_handle_, use_case);
-}
-
-wifi_error WifiLegacyHal::setCoexUnsafeChannels(
- std::vector<wifi_coex_unsafe_channel> unsafe_channels, uint32_t restrictions) {
- return global_func_table_.wifi_set_coex_unsafe_channels(global_handle_, unsafe_channels.size(),
- unsafe_channels.data(), restrictions);
-}
-
-wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name, wifi_voip_mode mode) {
- return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name), mode);
-}
-
-wifi_error WifiLegacyHal::twtRegisterHandler(const std::string& iface_name,
- const TwtCallbackHandlers& user_callbacks) {
- on_twt_event_setup_response_callback = user_callbacks.on_setup_response;
- on_twt_event_teardown_completion_callback = user_callbacks.on_teardown_completion;
- on_twt_event_info_frame_received_callback = user_callbacks.on_info_frame_received;
- on_twt_event_device_notify_callback = user_callbacks.on_device_notify;
-
- return global_func_table_.wifi_twt_register_handler(
- getIfaceHandle(iface_name),
- {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion,
- onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify});
-}
-
-std::pair<wifi_error, TwtCapabilitySet> WifiLegacyHal::twtGetCapability(
- const std::string& iface_name) {
- TwtCapabilitySet capSet;
- wifi_error status =
- global_func_table_.wifi_twt_get_capability(getIfaceHandle(iface_name), &capSet);
- return {status, capSet};
-}
-
-wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name,
- const TwtSetupRequest& msg) {
- TwtSetupRequest msgInternal(msg);
- return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name), &msgInternal);
-}
-
-wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name,
- const TwtTeardownRequest& msg) {
- TwtTeardownRequest msgInternal(msg);
- return global_func_table_.wifi_twt_teardown_request(getIfaceHandle(iface_name), &msgInternal);
-}
-
-wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name,
- const TwtInfoFrameRequest& msg) {
- TwtInfoFrameRequest msgInternal(msg);
- return global_func_table_.wifi_twt_info_frame_request(getIfaceHandle(iface_name), &msgInternal);
-}
-
-std::pair<wifi_error, TwtStats> WifiLegacyHal::twtGetStats(const std::string& iface_name,
- uint8_t configId) {
- TwtStats stats;
- wifi_error status =
- global_func_table_.wifi_twt_get_stats(getIfaceHandle(iface_name), configId, &stats);
- return {status, stats};
-}
-
-wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name, uint8_t configId) {
- return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name), configId);
-}
-
-wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, uint32_t multiplier) {
- return global_func_table_.wifi_set_dtim_config(getIfaceHandle(iface_name), multiplier);
-}
-
-std::pair<wifi_error, std::vector<wifi_usable_channel>> WifiLegacyHal::getUsableChannels(
- uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask) {
- std::vector<wifi_usable_channel> channels;
- channels.resize(kMaxWifiUsableChannels);
- uint32_t size = 0;
- wifi_error status = global_func_table_.wifi_get_usable_channels(
- global_handle_, band_mask, iface_mode_mask, filter_mask, channels.size(), &size,
- reinterpret_cast<wifi_usable_channel*>(channels.data()));
- CHECK(size >= 0 && size <= kMaxWifiUsableChannels);
- channels.resize(size);
- return {status, std::move(channels)};
-}
-
-wifi_error WifiLegacyHal::triggerSubsystemRestart() {
- return global_func_table_.wifi_trigger_subsystem_restart(global_handle_);
-}
-
-wifi_error WifiLegacyHal::setIndoorState(bool isIndoor) {
- return global_func_table_.wifi_set_indoor_state(global_handle_, isIndoor);
-}
-
-std::pair<wifi_error, wifi_radio_combination_matrix*>
-WifiLegacyHal::getSupportedRadioCombinationsMatrix() {
- char* buffer = new char[kMaxSupportedRadioCombinationsMatrixLength];
- std::fill(buffer, buffer + kMaxSupportedRadioCombinationsMatrixLength, 0);
- uint32_t size = 0;
- wifi_radio_combination_matrix* radio_combination_matrix_ptr =
- reinterpret_cast<wifi_radio_combination_matrix*>(buffer);
- wifi_error status = global_func_table_.wifi_get_supported_radio_combinations_matrix(
- global_handle_, kMaxSupportedRadioCombinationsMatrixLength, &size,
- radio_combination_matrix_ptr);
- CHECK(size >= 0 && size <= kMaxSupportedRadioCombinationsMatrixLength);
- return {status, radio_combination_matrix_ptr};
-}
-
-wifi_error WifiLegacyHal::chreNanRttRequest(const std::string& iface_name, bool enable) {
- if (enable)
- return global_func_table_.wifi_nan_rtt_chre_enable_request(0, getIfaceHandle(iface_name),
- NULL);
- else
- return global_func_table_.wifi_nan_rtt_chre_disable_request(0, getIfaceHandle(iface_name));
-}
-
-wifi_error WifiLegacyHal::chreRegisterHandler(const std::string& iface_name,
- const ChreCallbackHandlers& handler) {
- if (on_chre_nan_rtt_internal_callback) {
- return WIFI_ERROR_NOT_AVAILABLE;
- }
-
- on_chre_nan_rtt_internal_callback = handler.on_wifi_chre_nan_rtt_state;
-
- wifi_error status = global_func_table_.wifi_chre_register_handler(getIfaceHandle(iface_name),
- {onAsyncChreNanRttState});
- if (status != WIFI_SUCCESS) {
- on_chre_nan_rtt_internal_callback = nullptr;
- }
- return status;
-}
-
-wifi_error WifiLegacyHal::enableWifiTxPowerLimits(const std::string& iface_name, bool enable) {
- return global_func_table_.wifi_enable_tx_power_limits(getIfaceHandle(iface_name), enable);
-}
-
-void WifiLegacyHal::invalidate() {
- global_handle_ = nullptr;
- iface_name_to_handle_.clear();
- on_driver_memory_dump_internal_callback = nullptr;
- on_firmware_memory_dump_internal_callback = nullptr;
- on_gscan_event_internal_callback = nullptr;
- on_gscan_full_result_internal_callback = nullptr;
- on_link_layer_stats_result_internal_callback = nullptr;
- on_rssi_threshold_breached_internal_callback = nullptr;
- on_ring_buffer_data_internal_callback = nullptr;
- on_error_alert_internal_callback = nullptr;
- on_radio_mode_change_internal_callback = nullptr;
- on_subsystem_restart_internal_callback = nullptr;
- on_rtt_results_internal_callback = nullptr;
- on_nan_notify_response_user_callback = nullptr;
- on_nan_event_publish_terminated_user_callback = nullptr;
- on_nan_event_match_user_callback = nullptr;
- on_nan_event_match_expired_user_callback = nullptr;
- on_nan_event_subscribe_terminated_user_callback = nullptr;
- on_nan_event_followup_user_callback = nullptr;
- on_nan_event_disc_eng_event_user_callback = nullptr;
- on_nan_event_disabled_user_callback = nullptr;
- on_nan_event_tca_user_callback = nullptr;
- on_nan_event_beacon_sdf_payload_user_callback = nullptr;
- on_nan_event_data_path_request_user_callback = nullptr;
- on_nan_event_data_path_confirm_user_callback = nullptr;
- on_nan_event_data_path_end_user_callback = nullptr;
- on_nan_event_transmit_follow_up_user_callback = nullptr;
- on_nan_event_range_request_user_callback = nullptr;
- on_nan_event_range_report_user_callback = nullptr;
- on_nan_event_schedule_update_user_callback = nullptr;
- on_twt_event_setup_response_callback = nullptr;
- on_twt_event_teardown_completion_callback = nullptr;
- on_twt_event_info_frame_received_callback = nullptr;
- on_twt_event_device_notify_callback = nullptr;
- on_chre_nan_rtt_internal_callback = nullptr;
-}
-
-} // namespace legacy_hal
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_legacy_hal.h b/wifi/1.6/default/wifi_legacy_hal.h
deleted file mode 100644
index 2b923b4..0000000
--- a/wifi/1.6/default/wifi_legacy_hal.h
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_LEGACY_HAL_H_
-#define WIFI_LEGACY_HAL_H_
-
-#include <condition_variable>
-#include <functional>
-#include <map>
-#include <thread>
-#include <vector>
-
-#include <hardware_legacy/wifi_hal.h>
-#include <wifi_system/interface_tool.h>
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-// This is in a separate namespace to prevent typename conflicts between
-// the legacy HAL types and the HIDL interface types.
-namespace legacy_hal {
-// Import all the types defined inside the legacy HAL header files into this
-// namespace.
-using ::chre_nan_rtt_state;
-using ::frame_info;
-using ::frame_type;
-using ::FRAME_TYPE_80211_MGMT;
-using ::FRAME_TYPE_ETHERNET_II;
-using ::FRAME_TYPE_UNKNOWN;
-using ::fw_roaming_state_t;
-using ::mac_addr;
-using ::NAN_CHANNEL_24G_BAND;
-using ::NAN_CHANNEL_5G_BAND_HIGH;
-using ::NAN_CHANNEL_5G_BAND_LOW;
-using ::NAN_DISABLE_RANGE_REPORT;
-using ::NAN_DO_NOT_USE_SRF;
-using ::NAN_DP_CHANNEL_NOT_REQUESTED;
-using ::NAN_DP_CONFIG_NO_SECURITY;
-using ::NAN_DP_CONFIG_SECURITY;
-using ::NAN_DP_END;
-using ::NAN_DP_FORCE_CHANNEL_SETUP;
-using ::NAN_DP_INITIATOR_RESPONSE;
-using ::NAN_DP_INTERFACE_CREATE;
-using ::NAN_DP_INTERFACE_DELETE;
-using ::NAN_DP_REQUEST_ACCEPT;
-using ::NAN_DP_REQUEST_CHANNEL_SETUP;
-using ::NAN_DP_REQUEST_REJECT;
-using ::NAN_DP_RESPONDER_RESPONSE;
-using ::NAN_GET_CAPABILITIES;
-using ::NAN_MATCH_ALG_MATCH_CONTINUOUS;
-using ::NAN_MATCH_ALG_MATCH_NEVER;
-using ::NAN_MATCH_ALG_MATCH_ONCE;
-using ::NAN_PUBLISH_TYPE_SOLICITED;
-using ::NAN_PUBLISH_TYPE_UNSOLICITED;
-using ::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
-using ::NAN_RANGING_AUTO_RESPONSE_DISABLE;
-using ::NAN_RANGING_AUTO_RESPONSE_ENABLE;
-using ::NAN_RANGING_DISABLE;
-using ::NAN_RANGING_ENABLE;
-using ::NAN_RESPONSE_BEACON_SDF_PAYLOAD;
-using ::NAN_RESPONSE_CONFIG;
-using ::NAN_RESPONSE_DISABLED;
-using ::NAN_RESPONSE_ENABLED;
-using ::NAN_RESPONSE_ERROR;
-using ::NAN_RESPONSE_PUBLISH;
-using ::NAN_RESPONSE_PUBLISH_CANCEL;
-using ::NAN_RESPONSE_STATS;
-using ::NAN_RESPONSE_SUBSCRIBE;
-using ::NAN_RESPONSE_SUBSCRIBE_CANCEL;
-using ::NAN_RESPONSE_TCA;
-using ::NAN_RESPONSE_TRANSMIT_FOLLOWUP;
-using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
-using ::NAN_SECURITY_KEY_INPUT_PMK;
-using ::NAN_SERVICE_ACCEPT_POLICY_ALL;
-using ::NAN_SERVICE_ACCEPT_POLICY_NONE;
-using ::NAN_SRF_ATTR_BLOOM_FILTER;
-using ::NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
-using ::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
-using ::NAN_SRF_INCLUDE_RESPOND;
-using ::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
-using ::NAN_SSI_REQUIRED_IN_MATCH_IND;
-using ::NAN_STATUS_ALREADY_ENABLED;
-using ::NAN_STATUS_FOLLOWUP_QUEUE_FULL;
-using ::NAN_STATUS_INTERNAL_FAILURE;
-using ::NAN_STATUS_INVALID_NDP_ID;
-using ::NAN_STATUS_INVALID_PARAM;
-using ::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
-using ::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID;
-using ::NAN_STATUS_NAN_NOT_ALLOWED;
-using ::NAN_STATUS_NO_OTA_ACK;
-using ::NAN_STATUS_NO_RESOURCE_AVAILABLE;
-using ::NAN_STATUS_PROTOCOL_FAILURE;
-using ::NAN_STATUS_SUCCESS;
-using ::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
-using ::NAN_SUBSCRIBE_TYPE_ACTIVE;
-using ::NAN_SUBSCRIBE_TYPE_PASSIVE;
-using ::NAN_TRANSMIT_IN_DW;
-using ::NAN_TRANSMIT_IN_FAW;
-using ::NAN_TX_PRIORITY_HIGH;
-using ::NAN_TX_PRIORITY_NORMAL;
-using ::NAN_TX_TYPE_BROADCAST;
-using ::NAN_TX_TYPE_UNICAST;
-using ::NAN_USE_SRF;
-using ::NanBeaconSdfPayloadInd;
-using ::NanCapabilities;
-using ::NanChannelInfo;
-using ::NanConfigRequest;
-using ::NanDataPathChannelCfg;
-using ::NanDataPathConfirmInd;
-using ::NanDataPathEndInd;
-using ::NanDataPathIndicationResponse;
-using ::NanDataPathInitiatorRequest;
-using ::NanDataPathRequestInd;
-using ::NanDataPathScheduleUpdateInd;
-using ::NanDisabledInd;
-using ::NanDiscEngEventInd;
-using ::NanEnableRequest;
-using ::NanFollowupInd;
-using ::NanMatchAlg;
-using ::NanMatchExpiredInd;
-using ::NanMatchInd;
-using ::NanPublishCancelRequest;
-using ::NanPublishRequest;
-using ::NanPublishTerminatedInd;
-using ::NanPublishType;
-using ::NanRangeReportInd;
-using ::NanRangeRequestInd;
-using ::NanResponseMsg;
-using ::NanSRFType;
-using ::NanStatusType;
-using ::NanSubscribeCancelRequest;
-using ::NanSubscribeRequest;
-using ::NanSubscribeTerminatedInd;
-using ::NanSubscribeType;
-using ::NanTransmitFollowupInd;
-using ::NanTransmitFollowupRequest;
-using ::NanTxType;
-using ::ROAMING_DISABLE;
-using ::ROAMING_ENABLE;
-using ::RTT_PEER_AP;
-using ::RTT_PEER_NAN;
-using ::RTT_PEER_P2P_CLIENT;
-using ::RTT_PEER_P2P_GO;
-using ::RTT_PEER_STA;
-using ::rtt_peer_type;
-using ::RTT_STATUS_ABORTED;
-using ::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL;
-using ::RTT_STATUS_FAIL_BUSY_TRY_LATER;
-using ::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE;
-using ::RTT_STATUS_FAIL_INVALID_TS;
-using ::RTT_STATUS_FAIL_NO_CAPABILITY;
-using ::RTT_STATUS_FAIL_NO_RSP;
-using ::RTT_STATUS_FAIL_NOT_SCHEDULED_YET;
-using ::RTT_STATUS_FAIL_PROTOCOL;
-using ::RTT_STATUS_FAIL_REJECTED;
-using ::RTT_STATUS_FAIL_SCHEDULE;
-using ::RTT_STATUS_FAIL_TM_TIMEOUT;
-using ::RTT_STATUS_FAILURE;
-using ::RTT_STATUS_INVALID_REQ;
-using ::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED;
-using ::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE;
-using ::RTT_STATUS_NO_WIFI;
-using ::RTT_STATUS_SUCCESS;
-using ::RTT_TYPE_1_SIDED;
-using ::RTT_TYPE_2_SIDED;
-using ::RX_PKT_FATE_DRV_DROP_FILTER;
-using ::RX_PKT_FATE_DRV_DROP_INVALID;
-using ::RX_PKT_FATE_DRV_DROP_NOBUFS;
-using ::RX_PKT_FATE_DRV_DROP_OTHER;
-using ::RX_PKT_FATE_DRV_QUEUED;
-using ::RX_PKT_FATE_FW_DROP_FILTER;
-using ::RX_PKT_FATE_FW_DROP_INVALID;
-using ::RX_PKT_FATE_FW_DROP_NOBUFS;
-using ::RX_PKT_FATE_FW_DROP_OTHER;
-using ::RX_PKT_FATE_FW_QUEUED;
-using ::RX_PKT_FATE_SUCCESS;
-using ::ssid_t;
-using ::transaction_id;
-using ::TX_PKT_FATE_ACKED;
-using ::TX_PKT_FATE_DRV_DROP_INVALID;
-using ::TX_PKT_FATE_DRV_DROP_NOBUFS;
-using ::TX_PKT_FATE_DRV_DROP_OTHER;
-using ::TX_PKT_FATE_DRV_QUEUED;
-using ::TX_PKT_FATE_FW_DROP_INVALID;
-using ::TX_PKT_FATE_FW_DROP_NOBUFS;
-using ::TX_PKT_FATE_FW_DROP_OTHER;
-using ::TX_PKT_FATE_FW_QUEUED;
-using ::TX_PKT_FATE_SENT;
-using ::WIFI_AC_BE;
-using ::WIFI_AC_BK;
-using ::WIFI_AC_VI;
-using ::WIFI_AC_VO;
-using ::WIFI_ANTENNA_1X1;
-using ::WIFI_ANTENNA_2X2;
-using ::WIFI_ANTENNA_3X3;
-using ::WIFI_ANTENNA_4X4;
-using ::WIFI_ANTENNA_UNSPECIFIED;
-using ::wifi_band;
-using ::WIFI_BAND_A;
-using ::WIFI_BAND_A_DFS;
-using ::WIFI_BAND_A_WITH_DFS;
-using ::WIFI_BAND_ABG;
-using ::WIFI_BAND_ABG_WITH_DFS;
-using ::WIFI_BAND_BG;
-using ::WIFI_BAND_UNSPECIFIED;
-using ::wifi_cached_scan_results;
-using ::WIFI_CHAN_WIDTH_10;
-using ::WIFI_CHAN_WIDTH_160;
-using ::WIFI_CHAN_WIDTH_20;
-using ::WIFI_CHAN_WIDTH_320;
-using ::WIFI_CHAN_WIDTH_40;
-using ::WIFI_CHAN_WIDTH_5;
-using ::WIFI_CHAN_WIDTH_80;
-using ::WIFI_CHAN_WIDTH_80P80;
-using ::WIFI_CHAN_WIDTH_INVALID;
-using ::wifi_channel_info;
-using ::wifi_channel_stat;
-using ::wifi_channel_width;
-using ::wifi_coex_restriction;
-using ::wifi_coex_unsafe_channel;
-using ::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED;
-using ::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY;
-using ::wifi_error;
-using ::WIFI_ERROR_BUSY;
-using ::WIFI_ERROR_INVALID_ARGS;
-using ::WIFI_ERROR_INVALID_REQUEST_ID;
-using ::WIFI_ERROR_NONE;
-using ::WIFI_ERROR_NOT_AVAILABLE;
-using ::WIFI_ERROR_NOT_SUPPORTED;
-using ::WIFI_ERROR_OUT_OF_MEMORY;
-using ::WIFI_ERROR_TIMED_OUT;
-using ::WIFI_ERROR_TOO_MANY_REQUESTS;
-using ::WIFI_ERROR_UNINITIALIZED;
-using ::WIFI_ERROR_UNKNOWN;
-using ::wifi_gscan_capabilities;
-using ::wifi_hal_fn;
-using ::wifi_information_element;
-using ::WIFI_INTERFACE_IBSS;
-using ::WIFI_INTERFACE_MESH;
-using ::wifi_interface_mode;
-using ::WIFI_INTERFACE_NAN;
-using ::WIFI_INTERFACE_P2P_CLIENT;
-using ::WIFI_INTERFACE_P2P_GO;
-using ::WIFI_INTERFACE_SOFTAP;
-using ::WIFI_INTERFACE_STA;
-using ::WIFI_INTERFACE_TDLS;
-using ::wifi_interface_type;
-using ::WIFI_INTERFACE_TYPE_AP;
-using ::WIFI_INTERFACE_TYPE_NAN;
-using ::WIFI_INTERFACE_TYPE_P2P;
-using ::WIFI_INTERFACE_TYPE_STA;
-using ::WIFI_INTERFACE_UNKNOWN;
-using ::wifi_latency_mode;
-using ::WIFI_LATENCY_MODE_LOW;
-using ::WIFI_LATENCY_MODE_NORMAL;
-using ::wifi_lci_information;
-using ::wifi_lcr_information;
-using ::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
-using ::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
-using ::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
-using ::WIFI_LOGGER_PACKET_FATE_SUPPORTED;
-using ::WIFI_LOGGER_POWER_EVENT_SUPPORTED;
-using ::WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
-using ::WIFI_MOTION_EXPECTED;
-using ::WIFI_MOTION_NOT_EXPECTED;
-using ::wifi_motion_pattern;
-using ::WIFI_MOTION_UNKNOWN;
-using ::wifi_multi_sta_use_case;
-using ::wifi_power_scenario;
-using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF;
-using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON;
-using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF;
-using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON;
-using ::WIFI_POWER_SCENARIO_VOICE_CALL;
-using ::wifi_radio_combination;
-using ::wifi_radio_combination_matrix;
-using ::wifi_radio_configuration;
-using ::wifi_rate;
-using ::wifi_request_id;
-using ::wifi_ring_buffer_status;
-using ::wifi_roaming_capabilities;
-using ::wifi_roaming_config;
-using ::wifi_rtt_bw;
-using ::WIFI_RTT_BW_10;
-using ::WIFI_RTT_BW_160;
-using ::WIFI_RTT_BW_20;
-using ::WIFI_RTT_BW_320;
-using ::WIFI_RTT_BW_40;
-using ::WIFI_RTT_BW_5;
-using ::WIFI_RTT_BW_80;
-using ::wifi_rtt_capabilities;
-using ::wifi_rtt_config;
-using ::wifi_rtt_preamble;
-using ::WIFI_RTT_PREAMBLE_EHT;
-using ::WIFI_RTT_PREAMBLE_HE;
-using ::WIFI_RTT_PREAMBLE_HT;
-using ::WIFI_RTT_PREAMBLE_LEGACY;
-using ::WIFI_RTT_PREAMBLE_VHT;
-using ::wifi_rtt_responder;
-using ::wifi_rtt_result;
-using ::wifi_rtt_status;
-using ::wifi_rtt_type;
-using ::wifi_rx_packet_fate;
-using ::wifi_rx_report;
-using ::wifi_scan_bucket_spec;
-using ::wifi_scan_cmd_params;
-using ::WIFI_SCAN_FLAG_INTERRUPTED;
-using ::wifi_scan_result;
-using ::WIFI_SUCCESS;
-using ::wifi_tx_packet_fate;
-using ::wifi_tx_report;
-using ::wifi_usable_channel;
-using ::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE;
-using ::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY;
-using ::WLAN_MAC_2_4_BAND;
-using ::WLAN_MAC_5_0_BAND;
-using ::WLAN_MAC_60_0_BAND;
-using ::WLAN_MAC_6_0_BAND;
-
-// APF capabilities supported by the iface.
-struct PacketFilterCapabilities {
- uint32_t version;
- uint32_t max_len;
-};
-
-// WARNING: We don't care about the variable sized members of either
-// |wifi_iface_stat|, |wifi_radio_stat| structures. So, using the pragma
-// to escape the compiler warnings regarding this.
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wgnu-variable-sized-type-not-at-end"
-// The |wifi_radio_stat.tx_time_per_levels| stats is provided as a pointer in
-// |wifi_radio_stat| structure in the legacy HAL API. Separate that out
-// into a separate return element to avoid passing pointers around.
-struct LinkLayerRadioStats {
- wifi_radio_stat stats;
- std::vector<uint32_t> tx_time_per_levels;
- std::vector<wifi_channel_stat> channel_stats;
-};
-
-struct WifiPeerInfo {
- wifi_peer_info peer_info;
- std::vector<wifi_rate_stat> rate_stats;
-};
-
-struct LinkLayerStats {
- wifi_iface_stat iface;
- std::vector<LinkLayerRadioStats> radios;
- std::vector<WifiPeerInfo> peers;
-};
-#pragma GCC diagnostic pop
-
-// The |WLAN_DRIVER_WAKE_REASON_CNT.cmd_event_wake_cnt| and
-// |WLAN_DRIVER_WAKE_REASON_CNT.driver_fw_local_wake_cnt| stats is provided
-// as a pointer in |WLAN_DRIVER_WAKE_REASON_CNT| structure in the legacy HAL
-// API. Separate that out into a separate return elements to avoid passing
-// pointers around.
-struct WakeReasonStats {
- WLAN_DRIVER_WAKE_REASON_CNT wake_reason_cnt;
- std::vector<uint32_t> cmd_event_wake_cnt;
- std::vector<uint32_t> driver_fw_local_wake_cnt;
-};
-
-// NAN response and event callbacks struct.
-struct NanCallbackHandlers {
- // NotifyResponse invoked to notify the status of the Request.
- std::function<void(transaction_id, const NanResponseMsg&)> on_notify_response;
- // Various event callbacks.
- std::function<void(const NanPublishTerminatedInd&)> on_event_publish_terminated;
- std::function<void(const NanMatchInd&)> on_event_match;
- std::function<void(const NanMatchExpiredInd&)> on_event_match_expired;
- std::function<void(const NanSubscribeTerminatedInd&)> on_event_subscribe_terminated;
- std::function<void(const NanFollowupInd&)> on_event_followup;
- std::function<void(const NanDiscEngEventInd&)> on_event_disc_eng_event;
- std::function<void(const NanDisabledInd&)> on_event_disabled;
- std::function<void(const NanTCAInd&)> on_event_tca;
- std::function<void(const NanBeaconSdfPayloadInd&)> on_event_beacon_sdf_payload;
- std::function<void(const NanDataPathRequestInd&)> on_event_data_path_request;
- std::function<void(const NanDataPathConfirmInd&)> on_event_data_path_confirm;
- std::function<void(const NanDataPathEndInd&)> on_event_data_path_end;
- std::function<void(const NanTransmitFollowupInd&)> on_event_transmit_follow_up;
- std::function<void(const NanRangeRequestInd&)> on_event_range_request;
- std::function<void(const NanRangeReportInd&)> on_event_range_report;
- std::function<void(const NanDataPathScheduleUpdateInd&)> on_event_schedule_update;
-};
-
-// Full scan results contain IE info and are hence passed by reference, to
-// preserve the variable length array member |ie_data|. Callee must not retain
-// the pointer.
-using on_gscan_full_result_callback =
- std::function<void(wifi_request_id, const wifi_scan_result*, uint32_t)>;
-// These scan results don't contain any IE info, so no need to pass by
-// reference.
-using on_gscan_results_callback =
- std::function<void(wifi_request_id, const std::vector<wifi_cached_scan_results>&)>;
-
-// Invoked when the rssi value breaches the thresholds set.
-using on_rssi_threshold_breached_callback =
- std::function<void(wifi_request_id, std::array<uint8_t, 6>, int8_t)>;
-
-// Callback for RTT range request results.
-// Rtt results contain IE info and are hence passed by reference, to
-// preserve the |LCI| and |LCR| pointers. Callee must not retain
-// the pointer.
-using on_rtt_results_callback =
- std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result*>&)>;
-
-// Callback for ring buffer data.
-using on_ring_buffer_data_callback = std::function<void(
- const std::string&, const std::vector<uint8_t>&, const wifi_ring_buffer_status&)>;
-
-// Callback for alerts.
-using on_error_alert_callback = std::function<void(int32_t, const std::vector<uint8_t>&)>;
-
-// Callback for subsystem restart
-using on_subsystem_restart_callback = std::function<void(const std::string&)>;
-
-// Struct for the mac info from the legacy HAL. This is a cleaner version
-// of the |wifi_mac_info| & |wifi_iface_info|.
-typedef struct {
- std::string name;
- wifi_channel channel;
-} WifiIfaceInfo;
-
-typedef struct {
- uint32_t wlan_mac_id;
- /* BIT MASK of BIT(WLAN_MAC*) as represented by wlan_mac_band */
- uint32_t mac_band;
- /* Represents the connected Wi-Fi interfaces associated with each MAC */
- std::vector<WifiIfaceInfo> iface_infos;
-} WifiMacInfo;
-
-// Callback for radio mode change
-using on_radio_mode_change_callback = std::function<void(const std::vector<WifiMacInfo>&)>;
-
-// TWT response and event callbacks struct.
-struct TwtCallbackHandlers {
- // Callback for TWT setup response
- std::function<void(const TwtSetupResponse&)> on_setup_response;
- // Callback for TWT teardown completion
- std::function<void(const TwtTeardownCompletion&)> on_teardown_completion;
- // Callback for TWT info frame received event
- std::function<void(const TwtInfoFrameReceived&)> on_info_frame_received;
- // Callback for TWT notification from the device
- std::function<void(const TwtDeviceNotify&)> on_device_notify;
-};
-
-// CHRE response and event callbacks struct.
-struct ChreCallbackHandlers {
- // Callback for CHRE NAN RTT
- std::function<void(chre_nan_rtt_state)> on_wifi_chre_nan_rtt_state;
-};
-
-/**
- * Class that encapsulates all legacy HAL interactions.
- * This class manages the lifetime of the event loop thread used by legacy HAL.
- *
- * Note: There will only be a single instance of this class created in the Wifi
- * object and will be valid for the lifetime of the process.
- */
-class WifiLegacyHal {
- public:
- WifiLegacyHal(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool, const wifi_hal_fn& fn,
- bool is_primary);
- virtual ~WifiLegacyHal() = default;
-
- // Initialize the legacy HAL function table.
- virtual wifi_error initialize();
- // Start the legacy HAL and the event looper thread.
- virtual wifi_error start();
- // Deinitialize the legacy HAL and wait for the event loop thread to exit
- // using a predefined timeout.
- virtual wifi_error stop(std::unique_lock<std::recursive_mutex>* lock,
- const std::function<void()>& on_complete_callback);
- virtual wifi_error waitForDriverReady();
- // Checks if legacy HAL has successfully started
- bool isStarted();
- // Wrappers for all the functions in the legacy HAL function table.
- virtual std::pair<wifi_error, std::string> getDriverVersion(const std::string& iface_name);
- virtual std::pair<wifi_error, std::string> getFirmwareVersion(const std::string& iface_name);
- std::pair<wifi_error, std::vector<uint8_t>> requestDriverMemoryDump(
- const std::string& iface_name);
- std::pair<wifi_error, std::vector<uint8_t>> requestFirmwareMemoryDump(
- const std::string& iface_name);
- virtual std::pair<wifi_error, uint64_t> getSupportedFeatureSet(const std::string& iface_name);
- // APF functions.
- std::pair<wifi_error, PacketFilterCapabilities> getPacketFilterCapabilities(
- const std::string& iface_name);
- wifi_error setPacketFilter(const std::string& iface_name, const std::vector<uint8_t>& program);
- std::pair<wifi_error, std::vector<uint8_t>> readApfPacketFilterData(
- const std::string& iface_name);
- // Gscan functions.
- std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities(
- const std::string& iface_name);
- // These API's provides a simplified interface over the legacy Gscan API's:
- // a) All scan events from the legacy HAL API other than the
- // |WIFI_SCAN_FAILED| are treated as notification of results.
- // This method then retrieves the cached scan results from the legacy
- // HAL API and triggers the externally provided
- // |on_results_user_callback| on success.
- // b) |WIFI_SCAN_FAILED| scan event or failure to retrieve cached scan
- // results
- // triggers the externally provided |on_failure_user_callback|.
- // c) Full scan result event triggers the externally provided
- // |on_full_result_user_callback|.
- wifi_error startGscan(const std::string& iface_name, wifi_request_id id,
- const wifi_scan_cmd_params& params,
- const std::function<void(wifi_request_id)>& on_failure_callback,
- const on_gscan_results_callback& on_results_callback,
- const on_gscan_full_result_callback& on_full_result_callback);
- wifi_error stopGscan(const std::string& iface_name, wifi_request_id id);
- std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForBand(
- const std::string& iface_name, wifi_band band);
- virtual wifi_error setDfsFlag(const std::string& iface_name, bool dfs_on);
- // Link layer stats functions.
- wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug);
- wifi_error disableLinkLayerStats(const std::string& iface_name);
- std::pair<wifi_error, LinkLayerStats> getLinkLayerStats(const std::string& iface_name);
- // RSSI monitor functions.
- wifi_error startRssiMonitoring(
- const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi,
- const on_rssi_threshold_breached_callback& on_threshold_breached_callback);
- wifi_error stopRssiMonitoring(const std::string& iface_name, wifi_request_id id);
- std::pair<wifi_error, wifi_roaming_capabilities> getRoamingCapabilities(
- const std::string& iface_name);
- wifi_error configureRoaming(const std::string& iface_name, const wifi_roaming_config& config);
- wifi_error enableFirmwareRoaming(const std::string& iface_name, fw_roaming_state_t state);
- wifi_error configureNdOffload(const std::string& iface_name, bool enable);
- wifi_error startSendingOffloadedPacket(const std::string& iface_name, uint32_t cmd_id,
- uint16_t ether_type,
- const std::vector<uint8_t>& ip_packet_data,
- const std::array<uint8_t, 6>& src_address,
- const std::array<uint8_t, 6>& dst_address,
- uint32_t period_in_ms);
- wifi_error stopSendingOffloadedPacket(const std::string& iface_name, uint32_t cmd_id);
- virtual wifi_error selectTxPowerScenario(const std::string& iface_name,
- wifi_power_scenario scenario);
- virtual wifi_error resetTxPowerScenario(const std::string& iface_name);
- wifi_error setLatencyMode(const std::string& iface_name, wifi_latency_mode mode);
- wifi_error setThermalMitigationMode(wifi_thermal_mode mode, uint32_t completion_window);
- wifi_error setDscpToAccessCategoryMapping(uint32_t start, uint32_t end,
- uint32_t access_category);
- wifi_error resetDscpToAccessCategoryMapping();
- // Logger/debug functions.
- std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet(const std::string& iface_name);
- wifi_error startPktFateMonitoring(const std::string& iface_name);
- std::pair<wifi_error, std::vector<wifi_tx_report>> getTxPktFates(const std::string& iface_name);
- std::pair<wifi_error, std::vector<wifi_rx_report>> getRxPktFates(const std::string& iface_name);
- std::pair<wifi_error, WakeReasonStats> getWakeReasonStats(const std::string& iface_name);
- wifi_error registerRingBufferCallbackHandler(
- const std::string& iface_name, const on_ring_buffer_data_callback& on_data_callback);
- wifi_error deregisterRingBufferCallbackHandler(const std::string& iface_name);
- virtual wifi_error registerSubsystemRestartCallbackHandler(
- const on_subsystem_restart_callback& on_restart_callback);
- std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> getRingBuffersStatus(
- const std::string& iface_name);
- wifi_error startRingBufferLogging(const std::string& iface_name, const std::string& ring_name,
- uint32_t verbose_level, uint32_t max_interval_sec,
- uint32_t min_data_size);
- wifi_error getRingBufferData(const std::string& iface_name, const std::string& ring_name);
- wifi_error registerErrorAlertCallbackHandler(const std::string& iface_name,
- const on_error_alert_callback& on_alert_callback);
- wifi_error deregisterErrorAlertCallbackHandler(const std::string& iface_name);
- // Radio mode functions.
- virtual wifi_error registerRadioModeChangeCallbackHandler(
- const std::string& iface_name,
- const on_radio_mode_change_callback& on_user_change_callback);
- // RTT functions.
- wifi_error startRttRangeRequest(const std::string& iface_name, wifi_request_id id,
- const std::vector<wifi_rtt_config>& rtt_configs,
- const on_rtt_results_callback& on_results_callback);
- wifi_error cancelRttRangeRequest(const std::string& iface_name, wifi_request_id id,
- const std::vector<std::array<uint8_t, 6>>& mac_addrs);
- std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities(const std::string& iface_name);
- std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo(const std::string& iface_name);
- wifi_error enableRttResponder(const std::string& iface_name, wifi_request_id id,
- const wifi_channel_info& channel_hint, uint32_t max_duration_secs,
- const wifi_rtt_responder& info);
- wifi_error disableRttResponder(const std::string& iface_name, wifi_request_id id);
- wifi_error setRttLci(const std::string& iface_name, wifi_request_id id,
- const wifi_lci_information& info);
- wifi_error setRttLcr(const std::string& iface_name, wifi_request_id id,
- const wifi_lcr_information& info);
- // NAN functions.
- virtual wifi_error nanRegisterCallbackHandlers(const std::string& iface_name,
- const NanCallbackHandlers& callbacks);
- wifi_error nanEnableRequest(const std::string& iface_name, transaction_id id,
- const NanEnableRequest& msg);
- virtual wifi_error nanDisableRequest(const std::string& iface_name, transaction_id id);
- wifi_error nanPublishRequest(const std::string& iface_name, transaction_id id,
- const NanPublishRequest& msg);
- wifi_error nanPublishCancelRequest(const std::string& iface_name, transaction_id id,
- const NanPublishCancelRequest& msg);
- wifi_error nanSubscribeRequest(const std::string& iface_name, transaction_id id,
- const NanSubscribeRequest& msg);
- wifi_error nanSubscribeCancelRequest(const std::string& iface_name, transaction_id id,
- const NanSubscribeCancelRequest& msg);
- wifi_error nanTransmitFollowupRequest(const std::string& iface_name, transaction_id id,
- const NanTransmitFollowupRequest& msg);
- wifi_error nanStatsRequest(const std::string& iface_name, transaction_id id,
- const NanStatsRequest& msg);
- wifi_error nanConfigRequest(const std::string& iface_name, transaction_id id,
- const NanConfigRequest& msg);
- wifi_error nanTcaRequest(const std::string& iface_name, transaction_id id,
- const NanTCARequest& msg);
- wifi_error nanBeaconSdfPayloadRequest(const std::string& iface_name, transaction_id id,
- const NanBeaconSdfPayloadRequest& msg);
- std::pair<wifi_error, NanVersion> nanGetVersion();
- wifi_error nanGetCapabilities(const std::string& iface_name, transaction_id id);
- wifi_error nanDataInterfaceCreate(const std::string& iface_name, transaction_id id,
- const std::string& data_iface_name);
- virtual wifi_error nanDataInterfaceDelete(const std::string& iface_name, transaction_id id,
- const std::string& data_iface_name);
- wifi_error nanDataRequestInitiator(const std::string& iface_name, transaction_id id,
- const NanDataPathInitiatorRequest& msg);
- wifi_error nanDataIndicationResponse(const std::string& iface_name, transaction_id id,
- const NanDataPathIndicationResponse& msg);
- wifi_error nanDataEnd(const std::string& iface_name, transaction_id id, uint32_t ndpInstanceId);
- // AP functions.
- wifi_error setCountryCode(const std::string& iface_name, std::array<int8_t, 2> code);
-
- // interface functions.
- virtual wifi_error createVirtualInterface(const std::string& ifname,
- wifi_interface_type iftype);
- virtual wifi_error deleteVirtualInterface(const std::string& ifname);
- virtual wifi_error getSupportedIfaceName(uint32_t iface_type, std::string& ifname);
-
- // STA + STA functions
- virtual wifi_error multiStaSetPrimaryConnection(const std::string& ifname);
- virtual wifi_error multiStaSetUseCase(wifi_multi_sta_use_case use_case);
-
- // Coex functions.
- virtual wifi_error setCoexUnsafeChannels(std::vector<wifi_coex_unsafe_channel> unsafe_channels,
- uint32_t restrictions);
-
- wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode);
-
- wifi_error twtRegisterHandler(const std::string& iface_name,
- const TwtCallbackHandlers& handler);
-
- std::pair<wifi_error, TwtCapabilitySet> twtGetCapability(const std::string& iface_name);
-
- wifi_error twtSetupRequest(const std::string& iface_name, const TwtSetupRequest& msg);
-
- wifi_error twtTearDownRequest(const std::string& iface_name, const TwtTeardownRequest& msg);
-
- wifi_error twtInfoFrameRequest(const std::string& iface_name, const TwtInfoFrameRequest& msg);
-
- std::pair<wifi_error, TwtStats> twtGetStats(const std::string& iface_name, uint8_t configId);
-
- wifi_error twtClearStats(const std::string& iface_name, uint8_t configId);
-
- wifi_error setDtimConfig(const std::string& iface_name, uint32_t multiplier);
-
- // Retrieve the list of usable channels in the requested bands
- // for the requested modes
- std::pair<wifi_error, std::vector<wifi_usable_channel>> getUsableChannels(
- uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask);
-
- wifi_error triggerSubsystemRestart();
-
- wifi_error setIndoorState(bool isIndoor);
-
- std::pair<wifi_error, wifi_radio_combination_matrix*> getSupportedRadioCombinationsMatrix();
-
- // CHRE NAN RTT function
- wifi_error chreNanRttRequest(const std::string& iface_name, bool enable);
-
- wifi_error chreRegisterHandler(const std::string& iface_name,
- const ChreCallbackHandlers& handler);
-
- wifi_error enableWifiTxPowerLimits(const std::string& iface_name, bool enable);
-
- private:
- // Retrieve interface handles for all the available interfaces.
- wifi_error retrieveIfaceHandles();
- wifi_interface_handle getIfaceHandle(const std::string& iface_name);
- // Run the legacy HAL event loop thread.
- void runEventLoop();
- // Retrieve the cached gscan results to pass the results back to the
- // external callbacks.
- std::pair<wifi_error, std::vector<wifi_cached_scan_results>> getGscanCachedResults(
- const std::string& iface_name);
- void invalidate();
- // Handles wifi (error) status of Virtual interface create/delete
- wifi_error handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname,
- wifi_error status);
-
- // Global function table of legacy HAL.
- wifi_hal_fn global_func_table_;
- // Opaque handle to be used for all global operations.
- wifi_handle global_handle_;
- // Map of interface name to handle that is to be used for all interface
- // specific operations.
- std::map<std::string, wifi_interface_handle> iface_name_to_handle_;
- // Flag to indicate if we have initiated the cleanup of legacy HAL.
- std::atomic<bool> awaiting_event_loop_termination_;
- std::condition_variable_any stop_wait_cv_;
- // Flag to indicate if the legacy HAL has been started.
- bool is_started_;
- std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
- // flag to indicate if this HAL is for the primary chip. This is used
- // in order to avoid some hard-coded behavior used with older HALs,
- // such as bring wlan0 interface up/down on start/stop HAL.
- // it may be removed once vendor HALs are updated.
- bool is_primary_;
-};
-
-} // namespace legacy_hal
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_LEGACY_HAL_H_
diff --git a/wifi/1.6/default/wifi_legacy_hal_factory.cpp b/wifi/1.6/default/wifi_legacy_hal_factory.cpp
deleted file mode 100644
index 147bf4d..0000000
--- a/wifi/1.6/default/wifi_legacy_hal_factory.cpp
+++ /dev/null
@@ -1,254 +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 <dirent.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <android-base/logging.h>
-#include <dlfcn.h>
-#include <libxml/parser.h>
-#include <libxml/tree.h>
-#include <libxml/xmlmemory.h>
-
-#include "wifi_legacy_hal_factory.h"
-#include "wifi_legacy_hal_stubs.h"
-
-namespace {
-static constexpr char kVendorHalsDescPath[] = "/vendor/etc/wifi/vendor_hals";
-static constexpr char kVendorHalsDescExt[] = ".xml";
-static constexpr uint32_t kVendorHalsDescVersion = 1;
-
-bool isDirectory(struct dirent* entryPtr) {
- bool isDir = false;
- if (entryPtr->d_type != DT_UNKNOWN && entryPtr->d_type != DT_LNK) {
- isDir = (entryPtr->d_type == DT_DIR);
- } else {
- struct stat entryStat;
- stat(entryPtr->d_name, &entryStat);
- isDir = S_ISDIR(entryStat.st_mode);
- }
- return isDir;
-}
-
-bool isFileExtension(const char* name, const char* ext) {
- if (name == NULL) return false;
- if (ext == NULL) return false;
-
- size_t extLen = strlen(ext);
- size_t nameLen = strlen(name);
-
- if (extLen > nameLen) return false;
-
- if (strncmp(name + nameLen - extLen, ext, extLen) != 0) return false;
-
- return true;
-}
-}; // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace legacy_hal {
-
-WifiLegacyHalFactory::WifiLegacyHalFactory(
- const std::weak_ptr<wifi_system::InterfaceTool> iface_tool)
- : iface_tool_(iface_tool) {}
-
-std::vector<std::shared_ptr<WifiLegacyHal>> WifiLegacyHalFactory::getHals() {
- if (legacy_hals_.empty()) {
- if (!initVendorHalDescriptorFromLinked()) initVendorHalsDescriptorList();
- for (auto& desc : descs_) {
- std::shared_ptr<WifiLegacyHal> hal =
- std::make_shared<WifiLegacyHal>(iface_tool_, desc.fn, desc.primary);
- legacy_hals_.push_back(hal);
- }
- }
-
- return legacy_hals_;
-}
-
-bool WifiLegacyHalFactory::initVendorHalDescriptorFromLinked() {
- wifi_hal_lib_desc desc;
-
- if (!initLinkedHalFunctionTable(&desc.fn)) return false;
-
- desc.primary = true;
- desc.handle = NULL;
- descs_.push_back(desc);
- return true;
-}
-
-bool WifiLegacyHalFactory::initLinkedHalFunctionTable(wifi_hal_fn* hal_fn) {
- init_wifi_vendor_hal_func_table_t initfn;
-
- initfn = (init_wifi_vendor_hal_func_table_t)dlsym(RTLD_DEFAULT,
- "init_wifi_vendor_hal_func_table");
- if (!initfn) {
- LOG(INFO) << "no vendor HAL library linked, will try dynamic load";
- return false;
- }
-
- if (!initHalFuncTableWithStubs(hal_fn)) {
- LOG(ERROR) << "Can not initialize the basic function pointer table";
- return false;
- }
-
- if (initfn(hal_fn) != WIFI_SUCCESS) {
- LOG(ERROR) << "Can not initialize the vendor function pointer table";
- return false;
- }
-
- return true;
-}
-
-/*
- * Overall structure of the HAL descriptor XML schema
- *
- * <?xml version="1.0" encoding="UTF-8"?>
- * <WifiVendorHal version="1">
- * <path>/vendor/lib64/libwifi-hal-qcom.so</path>
- * <primary>1</primary>
- * </WifiVendorHal>
- */
-void WifiLegacyHalFactory::initVendorHalsDescriptorList() {
- xmlDocPtr xml;
- xmlNodePtr node, cnode;
- char* version;
- std::string path;
- xmlChar* value;
- wifi_hal_lib_desc desc;
-
- LOG(INFO) << "processing vendor HALs descriptions in " << kVendorHalsDescPath;
- DIR* dirPtr = ::opendir(kVendorHalsDescPath);
- if (dirPtr == NULL) {
- LOG(ERROR) << "failed to open " << kVendorHalsDescPath;
- return;
- }
- for (struct dirent* entryPtr = ::readdir(dirPtr); entryPtr != NULL;
- entryPtr = ::readdir(dirPtr)) {
- if (isDirectory(entryPtr)) continue;
-
- if (!isFileExtension(entryPtr->d_name, kVendorHalsDescExt))
- continue; // only process .xml files
-
- LOG(INFO) << "processing config file: " << entryPtr->d_name;
-
- std::string fullPath(kVendorHalsDescPath);
- fullPath.append("/");
- fullPath.append(entryPtr->d_name);
- xml = xmlReadFile(fullPath.c_str(), "UTF-8", XML_PARSE_RECOVER);
- if (!xml) {
- LOG(ERROR) << "failed to parse: " << entryPtr->d_name << " skipping...";
- continue;
- }
- node = xmlDocGetRootElement(xml);
- if (!node) {
- LOG(ERROR) << "empty config file: " << entryPtr->d_name << " skipping...";
- goto skip;
- }
- if (xmlStrcmp(node->name, BAD_CAST "WifiVendorHal")) {
- LOG(ERROR) << "bad config, root element not WifiVendorHal: " << entryPtr->d_name
- << " skipping...";
- goto skip;
- }
- version = (char*)xmlGetProp(node, BAD_CAST "version");
- if (!version || strtoul(version, NULL, 0) != kVendorHalsDescVersion) {
- LOG(ERROR) << "conf file: " << entryPtr->d_name
- << "must have version: " << kVendorHalsDescVersion << ", skipping...";
- goto skip;
- }
- cnode = node->children;
- path.clear();
- desc.primary = false;
- while (cnode) {
- if (!xmlStrcmp(cnode->name, BAD_CAST "path")) {
- value = xmlNodeListGetString(xml, cnode->children, 1);
- if (value) path = (char*)value;
- xmlFree(value);
- } else if (!xmlStrcmp(cnode->name, BAD_CAST "primary")) {
- value = xmlNodeListGetString(xml, cnode->children, 1);
- desc.primary = !xmlStrcmp(value, BAD_CAST "1");
- xmlFree(value);
- }
- cnode = cnode->next;
- }
- if (path.empty()) {
- LOG(ERROR) << "hal library path not provided in: " << entryPtr->d_name
- << ", skipping...";
- goto skip;
- }
- if (loadVendorHalLib(path, desc)) {
- if (desc.primary)
- descs_.insert(descs_.begin(), desc);
- else
- descs_.push_back(desc);
- }
- skip:
- xmlFreeDoc(xml);
- }
- ::closedir(dirPtr);
-}
-
-bool WifiLegacyHalFactory::loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc) {
- void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
- init_wifi_vendor_hal_func_table_t initfn;
- wifi_error res;
-
- if (!h) {
- LOG(ERROR) << "failed to open vendor hal library: " << path;
- return false;
- }
- initfn = (init_wifi_vendor_hal_func_table_t)dlsym(h, "init_wifi_vendor_hal_func_table");
- if (!initfn) {
- LOG(ERROR) << "init_wifi_vendor_hal_func_table not found in: " << path;
- goto out_err;
- }
-
- if (!initHalFuncTableWithStubs(&desc.fn)) {
- LOG(ERROR) << "Can not initialize the basic function pointer table";
- goto out_err;
- }
- res = initfn(&desc.fn);
- if (res != WIFI_SUCCESS) {
- LOG(ERROR) << "failed to initialize the vendor func table in: " << path
- << " error: " << res;
- goto out_err;
- }
-
- res = desc.fn.wifi_early_initialize();
- // vendor HALs which do not implement early_initialize will return
- // WIFI_ERROR_NOT_SUPPORTED, treat this as success.
- if (res != WIFI_SUCCESS && res != WIFI_ERROR_NOT_SUPPORTED) {
- LOG(ERROR) << "early initialization failed in: " << path << " error: " << res;
- goto out_err;
- }
-
- desc.handle = h;
- return true;
-out_err:
- dlclose(h);
- return false;
-}
-
-} // namespace legacy_hal
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_legacy_hal_factory.h b/wifi/1.6/default/wifi_legacy_hal_factory.h
deleted file mode 100644
index 9f4423e..0000000
--- a/wifi/1.6/default/wifi_legacy_hal_factory.h
+++ /dev/null
@@ -1,66 +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 WIFI_LEGACY_HAL_FACTORY_H_
-#define WIFI_LEGACY_HAL_FACTORY_H_
-
-#include <wifi_system/interface_tool.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-// This is in a separate namespace to prevent typename conflicts between
-// the legacy HAL types and the HIDL interface types.
-namespace legacy_hal {
-/**
- * Class that creates WifiLegacyHal objects for vendor HALs in the system.
- */
-class WifiLegacyHalFactory {
- public:
- WifiLegacyHalFactory(const std::weak_ptr<wifi_system::InterfaceTool> iface_tool);
- virtual ~WifiLegacyHalFactory() = default;
-
- std::vector<std::shared_ptr<WifiLegacyHal>> getHals();
-
- private:
- typedef struct {
- wifi_hal_fn fn;
- bool primary;
- void* handle;
- } wifi_hal_lib_desc;
-
- bool initVendorHalDescriptorFromLinked();
- void initVendorHalsDescriptorList();
- bool initLinkedHalFunctionTable(wifi_hal_fn* hal_fn);
- bool loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc);
-
- std::weak_ptr<wifi_system::InterfaceTool> iface_tool_;
- std::vector<wifi_hal_lib_desc> descs_;
- std::vector<std::shared_ptr<WifiLegacyHal>> legacy_hals_;
-};
-
-} // namespace legacy_hal
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_LEGACY_HAL_FACTORY_H_
diff --git a/wifi/1.6/default/wifi_legacy_hal_stubs.cpp b/wifi/1.6/default/wifi_legacy_hal_stubs.cpp
deleted file mode 100644
index b3bd373..0000000
--- a/wifi/1.6/default/wifi_legacy_hal_stubs.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "wifi_legacy_hal_stubs.h"
-
-// TODO: Remove these stubs from HalTool in libwifi-system.
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace legacy_hal {
-template <typename>
-struct stubFunction;
-
-template <typename R, typename... Args>
-struct stubFunction<R (*)(Args...)> {
- static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; }
-};
-template <typename... Args>
-struct stubFunction<void (*)(Args...)> {
- static constexpr void invoke(Args...) {}
-};
-
-template <typename T>
-void populateStubFor(T* val) {
- *val = &stubFunction<T>::invoke;
-}
-
-bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) {
- if (hal_fn == nullptr) {
- return false;
- }
- populateStubFor(&hal_fn->wifi_initialize);
- populateStubFor(&hal_fn->wifi_wait_for_driver_ready);
- populateStubFor(&hal_fn->wifi_cleanup);
- populateStubFor(&hal_fn->wifi_event_loop);
- populateStubFor(&hal_fn->wifi_get_error_info);
- populateStubFor(&hal_fn->wifi_get_supported_feature_set);
- populateStubFor(&hal_fn->wifi_get_concurrency_matrix);
- populateStubFor(&hal_fn->wifi_set_scanning_mac_oui);
- populateStubFor(&hal_fn->wifi_get_supported_channels);
- populateStubFor(&hal_fn->wifi_is_epr_supported);
- populateStubFor(&hal_fn->wifi_get_ifaces);
- populateStubFor(&hal_fn->wifi_get_iface_name);
- populateStubFor(&hal_fn->wifi_set_iface_event_handler);
- populateStubFor(&hal_fn->wifi_reset_iface_event_handler);
- populateStubFor(&hal_fn->wifi_start_gscan);
- populateStubFor(&hal_fn->wifi_stop_gscan);
- populateStubFor(&hal_fn->wifi_get_cached_gscan_results);
- populateStubFor(&hal_fn->wifi_set_bssid_hotlist);
- populateStubFor(&hal_fn->wifi_reset_bssid_hotlist);
- populateStubFor(&hal_fn->wifi_set_significant_change_handler);
- populateStubFor(&hal_fn->wifi_reset_significant_change_handler);
- populateStubFor(&hal_fn->wifi_get_gscan_capabilities);
- populateStubFor(&hal_fn->wifi_set_link_stats);
- populateStubFor(&hal_fn->wifi_get_link_stats);
- populateStubFor(&hal_fn->wifi_clear_link_stats);
- populateStubFor(&hal_fn->wifi_get_valid_channels);
- populateStubFor(&hal_fn->wifi_rtt_range_request);
- populateStubFor(&hal_fn->wifi_rtt_range_cancel);
- populateStubFor(&hal_fn->wifi_get_rtt_capabilities);
- populateStubFor(&hal_fn->wifi_rtt_get_responder_info);
- populateStubFor(&hal_fn->wifi_enable_responder);
- populateStubFor(&hal_fn->wifi_disable_responder);
- populateStubFor(&hal_fn->wifi_set_nodfs_flag);
- populateStubFor(&hal_fn->wifi_start_logging);
- populateStubFor(&hal_fn->wifi_set_epno_list);
- populateStubFor(&hal_fn->wifi_reset_epno_list);
- populateStubFor(&hal_fn->wifi_set_country_code);
- populateStubFor(&hal_fn->wifi_get_firmware_memory_dump);
- populateStubFor(&hal_fn->wifi_set_log_handler);
- populateStubFor(&hal_fn->wifi_reset_log_handler);
- populateStubFor(&hal_fn->wifi_set_alert_handler);
- populateStubFor(&hal_fn->wifi_reset_alert_handler);
- populateStubFor(&hal_fn->wifi_get_firmware_version);
- populateStubFor(&hal_fn->wifi_get_ring_buffers_status);
- populateStubFor(&hal_fn->wifi_get_logger_supported_feature_set);
- populateStubFor(&hal_fn->wifi_get_ring_data);
- populateStubFor(&hal_fn->wifi_enable_tdls);
- populateStubFor(&hal_fn->wifi_disable_tdls);
- populateStubFor(&hal_fn->wifi_get_tdls_status);
- populateStubFor(&hal_fn->wifi_get_tdls_capabilities);
- populateStubFor(&hal_fn->wifi_get_driver_version);
- populateStubFor(&hal_fn->wifi_set_passpoint_list);
- populateStubFor(&hal_fn->wifi_reset_passpoint_list);
- populateStubFor(&hal_fn->wifi_set_lci);
- populateStubFor(&hal_fn->wifi_set_lcr);
- populateStubFor(&hal_fn->wifi_start_sending_offloaded_packet);
- populateStubFor(&hal_fn->wifi_stop_sending_offloaded_packet);
- populateStubFor(&hal_fn->wifi_start_rssi_monitoring);
- populateStubFor(&hal_fn->wifi_stop_rssi_monitoring);
- populateStubFor(&hal_fn->wifi_get_wake_reason_stats);
- populateStubFor(&hal_fn->wifi_configure_nd_offload);
- populateStubFor(&hal_fn->wifi_get_driver_memory_dump);
- populateStubFor(&hal_fn->wifi_start_pkt_fate_monitoring);
- populateStubFor(&hal_fn->wifi_get_tx_pkt_fates);
- populateStubFor(&hal_fn->wifi_get_rx_pkt_fates);
- populateStubFor(&hal_fn->wifi_nan_enable_request);
- populateStubFor(&hal_fn->wifi_nan_disable_request);
- populateStubFor(&hal_fn->wifi_nan_publish_request);
- populateStubFor(&hal_fn->wifi_nan_publish_cancel_request);
- populateStubFor(&hal_fn->wifi_nan_subscribe_request);
- populateStubFor(&hal_fn->wifi_nan_subscribe_cancel_request);
- populateStubFor(&hal_fn->wifi_nan_transmit_followup_request);
- populateStubFor(&hal_fn->wifi_nan_stats_request);
- populateStubFor(&hal_fn->wifi_nan_config_request);
- populateStubFor(&hal_fn->wifi_nan_tca_request);
- populateStubFor(&hal_fn->wifi_nan_beacon_sdf_payload_request);
- populateStubFor(&hal_fn->wifi_nan_register_handler);
- populateStubFor(&hal_fn->wifi_nan_get_version);
- populateStubFor(&hal_fn->wifi_nan_get_capabilities);
- populateStubFor(&hal_fn->wifi_nan_data_interface_create);
- populateStubFor(&hal_fn->wifi_nan_data_interface_delete);
- populateStubFor(&hal_fn->wifi_nan_data_request_initiator);
- populateStubFor(&hal_fn->wifi_nan_data_indication_response);
- populateStubFor(&hal_fn->wifi_nan_data_end);
- populateStubFor(&hal_fn->wifi_get_packet_filter_capabilities);
- populateStubFor(&hal_fn->wifi_set_packet_filter);
- populateStubFor(&hal_fn->wifi_read_packet_filter);
- populateStubFor(&hal_fn->wifi_get_roaming_capabilities);
- populateStubFor(&hal_fn->wifi_enable_firmware_roaming);
- populateStubFor(&hal_fn->wifi_configure_roaming);
- populateStubFor(&hal_fn->wifi_select_tx_power_scenario);
- populateStubFor(&hal_fn->wifi_reset_tx_power_scenario);
- populateStubFor(&hal_fn->wifi_set_radio_mode_change_handler);
- populateStubFor(&hal_fn->wifi_set_latency_mode);
- populateStubFor(&hal_fn->wifi_set_thermal_mitigation_mode);
- populateStubFor(&hal_fn->wifi_virtual_interface_create);
- populateStubFor(&hal_fn->wifi_virtual_interface_delete);
- populateStubFor(&hal_fn->wifi_map_dscp_access_category);
- populateStubFor(&hal_fn->wifi_reset_dscp_mapping);
- populateStubFor(&hal_fn->wifi_set_subsystem_restart_handler);
- populateStubFor(&hal_fn->wifi_get_supported_iface_name);
- populateStubFor(&hal_fn->wifi_early_initialize);
- populateStubFor(&hal_fn->wifi_get_chip_feature_set);
- populateStubFor(&hal_fn->wifi_multi_sta_set_primary_connection);
- populateStubFor(&hal_fn->wifi_multi_sta_set_use_case);
- populateStubFor(&hal_fn->wifi_set_coex_unsafe_channels);
- populateStubFor(&hal_fn->wifi_set_voip_mode);
- populateStubFor(&hal_fn->wifi_twt_register_handler);
- populateStubFor(&hal_fn->wifi_twt_get_capability);
- populateStubFor(&hal_fn->wifi_twt_setup_request);
- populateStubFor(&hal_fn->wifi_twt_teardown_request);
- populateStubFor(&hal_fn->wifi_twt_info_frame_request);
- populateStubFor(&hal_fn->wifi_twt_get_stats);
- populateStubFor(&hal_fn->wifi_twt_clear_stats);
- populateStubFor(&hal_fn->wifi_set_dtim_config);
- populateStubFor(&hal_fn->wifi_get_usable_channels);
- populateStubFor(&hal_fn->wifi_trigger_subsystem_restart);
- populateStubFor(&hal_fn->wifi_set_indoor_state);
- populateStubFor(&hal_fn->wifi_get_supported_radio_combinations_matrix);
- populateStubFor(&hal_fn->wifi_nan_rtt_chre_enable_request);
- populateStubFor(&hal_fn->wifi_nan_rtt_chre_disable_request);
- populateStubFor(&hal_fn->wifi_chre_register_handler);
- populateStubFor(&hal_fn->wifi_enable_tx_power_limits);
- return true;
-}
-} // namespace legacy_hal
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_legacy_hal_stubs.h b/wifi/1.6/default/wifi_legacy_hal_stubs.h
deleted file mode 100644
index c9a03bf..0000000
--- a/wifi/1.6/default/wifi_legacy_hal_stubs.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_LEGACY_HAL_STUBS_H_
-#define WIFI_LEGACY_HAL_STUBS_H_
-
-#include <hardware_legacy/wifi_hal.h>
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace legacy_hal {
-
-bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn);
-} // namespace legacy_hal
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_LEGACY_HAL_STUBS_H_
diff --git a/wifi/1.6/default/wifi_mode_controller.cpp b/wifi/1.6/default/wifi_mode_controller.cpp
deleted file mode 100644
index 4b8ac7d..0000000
--- a/wifi/1.6/default/wifi_mode_controller.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-#include <android-base/macros.h>
-#include <private/android_filesystem_config.h>
-
-#include "wifi_mode_controller.h"
-
-using android::hardware::wifi::V1_0::IfaceType;
-using android::wifi_hal::DriverTool;
-
-namespace {
-int convertIfaceTypeToFirmwareMode(IfaceType type) {
- int mode;
- switch (type) {
- case IfaceType::AP:
- mode = DriverTool::kFirmwareModeAp;
- break;
- case IfaceType::P2P:
- mode = DriverTool::kFirmwareModeP2p;
- break;
- case IfaceType::NAN:
- // NAN is exposed in STA mode currently.
- mode = DriverTool::kFirmwareModeSta;
- break;
- case IfaceType::STA:
- mode = DriverTool::kFirmwareModeSta;
- break;
- }
- return mode;
-}
-} // namespace
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace mode_controller {
-
-WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {}
-
-bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) {
- return driver_tool_->IsFirmwareModeChangeNeeded(convertIfaceTypeToFirmwareMode(type));
-}
-
-bool WifiModeController::initialize() {
- if (!driver_tool_->LoadDriver()) {
- LOG(ERROR) << "Failed to load WiFi driver";
- return false;
- }
- return true;
-}
-
-bool WifiModeController::changeFirmwareMode(IfaceType type) {
- if (!driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))) {
- LOG(ERROR) << "Failed to change firmware mode";
- return false;
- }
- return true;
-}
-
-bool WifiModeController::deinitialize() {
- if (!driver_tool_->UnloadDriver()) {
- LOG(ERROR) << "Failed to unload WiFi driver";
- return false;
- }
- return true;
-}
-} // namespace mode_controller
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_mode_controller.h b/wifi/1.6/default/wifi_mode_controller.h
deleted file mode 100644
index fee2b66..0000000
--- a/wifi/1.6/default/wifi_mode_controller.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_MODE_CONTROLLER_H_
-#define WIFI_MODE_CONTROLLER_H_
-
-#include <wifi_hal/driver_tool.h>
-
-#include <android/hardware/wifi/1.0/IWifi.h>
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-namespace mode_controller {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * Class that encapsulates all firmware mode configuration.
- * This class will perform the necessary firmware reloads to put the chip in the
- * required state (essentially a wrapper over DriverTool).
- */
-class WifiModeController {
- public:
- WifiModeController();
- virtual ~WifiModeController() = default;
-
- // Checks if a firmware mode change is necessary to support the specified
- // iface type operations.
- virtual bool isFirmwareModeChangeNeeded(IfaceType type);
- virtual bool initialize();
- // Change the firmware mode to support the specified iface type operations.
- virtual bool changeFirmwareMode(IfaceType type);
- // Unload the driver. This should be invoked whenever |IWifi.stop()| is
- // invoked.
- virtual bool deinitialize();
-
- private:
- std::unique_ptr<wifi_hal::DriverTool> driver_tool_;
-};
-
-} // namespace mode_controller
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_MODE_CONTROLLER_H_
diff --git a/wifi/1.6/default/wifi_nan_iface.cpp b/wifi/1.6/default/wifi_nan_iface.cpp
deleted file mode 100644
index ac2ebc9..0000000
--- a/wifi/1.6/default/wifi_nan_iface.cpp
+++ /dev/null
@@ -1,1016 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_nan_iface.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiNanIface::WifiNanIface(const std::string& ifname, bool is_dedicated_iface,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
- const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
- : ifname_(ifname),
- is_dedicated_iface_(is_dedicated_iface),
- legacy_hal_(legacy_hal),
- iface_util_(iface_util),
- is_valid_(true) {
- if (is_dedicated_iface_) {
- // If using a dedicated iface, set the iface up first.
- if (!iface_util_.lock()->setUpState(ifname_, true)) {
- // Fatal failure, invalidate the iface object.
- invalidate();
- return;
- }
- }
- // Register all the callbacks here. these should be valid for the lifetime
- // of the object. Whenever the mode changes legacy HAL will remove
- // all of these callbacks.
- legacy_hal::NanCallbackHandlers callback_handlers;
- android::wp<WifiNanIface> weak_ptr_this(this);
-
- // Callback for response.
- callback_handlers.on_notify_response = [weak_ptr_this](legacy_hal::transaction_id id,
- const legacy_hal::NanResponseMsg& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- WifiNanStatus wifiNanStatus;
- if (!hidl_struct_util::convertLegacyNanResponseHeaderToHidl(msg, &wifiNanStatus)) {
- LOG(ERROR) << "Failed to convert nan response header";
- return;
- }
-
- switch (msg.response_type) {
- case legacy_hal::NAN_RESPONSE_ENABLED: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyEnableResponse(id, wifiNanStatus).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_RESPONSE_DISABLED: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyDisableResponse(id, wifiNanStatus).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_RESPONSE_PUBLISH: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyStartPublishResponse(id, wifiNanStatus,
- msg.body.publish_response.publish_id)
- .isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyStopPublishResponse(id, wifiNanStatus).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyTransmitFollowupResponse(id, wifiNanStatus).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_RESPONSE_SUBSCRIBE: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyStartSubscribeResponse(
- id, wifiNanStatus,
- msg.body.subscribe_response.subscribe_id)
- .isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyStopSubscribeResponse(id, wifiNanStatus).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_RESPONSE_CONFIG: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyConfigResponse(id, wifiNanStatus).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_GET_CAPABILITIES: {
- V1_6::NanCapabilities hidl_struct;
- if (!hidl_struct_util::convertLegacyNanCapabilitiesResponseToHidl(
- msg.body.nan_capabilities, &hidl_struct)) {
- LOG(ERROR) << "Failed to convert nan capabilities response";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks_1_6()) {
- if (!callback->notifyCapabilitiesResponse_1_6(id, wifiNanStatus, hidl_struct)
- .isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_DP_INTERFACE_CREATE: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyCreateDataInterfaceResponse(id, wifiNanStatus).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_DP_INTERFACE_DELETE: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyDeleteDataInterfaceResponse(id, wifiNanStatus).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_DP_INITIATOR_RESPONSE: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyInitiateDataPathResponse(
- id, wifiNanStatus,
- msg.body.data_request_response.ndp_instance_id)
- .isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_DP_RESPONDER_RESPONSE: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyRespondToDataPathIndicationResponse(id, wifiNanStatus)
- .isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_DP_END: {
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->notifyTerminateDataPathResponse(id, wifiNanStatus).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- break;
- }
- case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD:
- /* fall through */
- case legacy_hal::NAN_RESPONSE_TCA:
- /* fall through */
- case legacy_hal::NAN_RESPONSE_STATS:
- /* fall through */
- case legacy_hal::NAN_RESPONSE_ERROR:
- /* fall through */
- default:
- LOG(ERROR) << "Unknown or unhandled response type: " << msg.response_type;
- return;
- }
- };
-
- callback_handlers.on_event_disc_eng_event =
- [weak_ptr_this](const legacy_hal::NanDiscEngEventInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- NanClusterEventInd hidl_struct;
- // event types defined identically - hence can be cast
- hidl_struct.eventType = (NanClusterEventType)msg.event_type;
- hidl_struct.addr = msg.data.mac_addr.addr;
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->eventClusterEvent(hidl_struct).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_disabled = [weak_ptr_this](const legacy_hal::NanDisabledInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- WifiNanStatus status;
- hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
- &status);
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->eventDisabled(status).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_publish_terminated =
- [weak_ptr_this](const legacy_hal::NanPublishTerminatedInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- WifiNanStatus status;
- hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason,
- sizeof(msg.nan_reason), &status);
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->eventPublishTerminated(msg.publish_id, status).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_subscribe_terminated =
- [weak_ptr_this](const legacy_hal::NanSubscribeTerminatedInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- WifiNanStatus status;
- hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason,
- sizeof(msg.nan_reason), &status);
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->eventSubscribeTerminated(msg.subscribe_id, status).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_match = [weak_ptr_this](const legacy_hal::NanMatchInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- V1_6::NanMatchInd hidl_struct;
- if (!hidl_struct_util::convertLegacyNanMatchIndToHidl(msg, &hidl_struct)) {
- LOG(ERROR) << "Failed to convert nan capabilities response";
- return;
- }
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks_1_6()) {
- if (!callback->eventMatch_1_6(hidl_struct).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_match_expired = [weak_ptr_this](
- const legacy_hal::NanMatchExpiredInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->eventMatchExpired(msg.publish_subscribe_id, msg.requestor_instance_id)
- .isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_followup = [weak_ptr_this](const legacy_hal::NanFollowupInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- NanFollowupReceivedInd hidl_struct;
- if (!hidl_struct_util::convertLegacyNanFollowupIndToHidl(msg, &hidl_struct)) {
- LOG(ERROR) << "Failed to convert nan capabilities response";
- return;
- }
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->eventFollowupReceived(hidl_struct).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_transmit_follow_up =
- [weak_ptr_this](const legacy_hal::NanTransmitFollowupInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- WifiNanStatus status;
- hidl_struct_util::convertToWifiNanStatus(msg.reason, msg.nan_reason,
- sizeof(msg.nan_reason), &status);
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->eventTransmitFollowup(msg.id, status).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_data_path_request =
- [weak_ptr_this](const legacy_hal::NanDataPathRequestInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- NanDataPathRequestInd hidl_struct;
- if (!hidl_struct_util::convertLegacyNanDataPathRequestIndToHidl(msg,
- &hidl_struct)) {
- LOG(ERROR) << "Failed to convert nan capabilities response";
- return;
- }
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->eventDataPathRequest(hidl_struct).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_data_path_confirm =
- [weak_ptr_this](const legacy_hal::NanDataPathConfirmInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- V1_6::NanDataPathConfirmInd hidl_struct;
- if (!hidl_struct_util::convertLegacyNanDataPathConfirmIndToHidl(msg,
- &hidl_struct)) {
- LOG(ERROR) << "Failed to convert nan capabilities response";
- return;
- }
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks_1_6()) {
- if (!callback->eventDataPathConfirm_1_6(hidl_struct).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- callback_handlers.on_event_data_path_end =
- [weak_ptr_this](const legacy_hal::NanDataPathEndInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- for (int i = 0; i < msg.num_ndp_instances; ++i) {
- if (!callback->eventDataPathTerminated(msg.ndp_instance_id[i]).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- }
- };
-
- callback_handlers.on_event_beacon_sdf_payload =
- [weak_ptr_this](const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) {
- LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called";
- };
-
- callback_handlers.on_event_range_request =
- [weak_ptr_this](const legacy_hal::NanRangeRequestInd& /* msg */) {
- LOG(ERROR) << "on_event_range_request - should not be called";
- };
-
- callback_handlers.on_event_range_report =
- [weak_ptr_this](const legacy_hal::NanRangeReportInd& /* msg */) {
- LOG(ERROR) << "on_event_range_report - should not be called";
- };
-
- callback_handlers.on_event_schedule_update =
- [weak_ptr_this](const legacy_hal::NanDataPathScheduleUpdateInd& msg) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- V1_6::NanDataPathScheduleUpdateInd hidl_struct;
- if (!hidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToHidl(
- msg, &hidl_struct)) {
- LOG(ERROR) << "Failed to convert nan capabilities response";
- return;
- }
-
- for (const auto& callback : shared_ptr_this->getEventCallbacks_1_6()) {
- if (!callback->eventDataPathScheduleUpdate_1_6(hidl_struct).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
-
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_, callback_handlers);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
- invalidate();
- }
-
- // Register for iface state toggle events.
- iface_util::IfaceEventHandlers event_handlers = {};
- event_handlers.on_state_toggle_off_on = [weak_ptr_this](const std::string& /* iface_name */) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- // Tell framework that NAN has been disabled.
- WifiNanStatus status = {NanStatusType::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->eventDisabled(status).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
- iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers);
-}
-
-void WifiNanIface::invalidate() {
- if (!isValid()) {
- return;
- }
- // send commands to HAL to actually disable and destroy interfaces
- legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF);
- legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0");
- legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1");
- iface_util_.lock()->unregisterIfaceEventHandlers(ifname_);
- legacy_hal_.reset();
- event_cb_handler_.invalidate();
- event_cb_handler_1_2_.invalidate();
- event_cb_handler_1_5_.invalidate();
- is_valid_ = false;
- if (is_dedicated_iface_) {
- // If using a dedicated iface, set the iface down.
- iface_util_.lock()->setUpState(ifname_, false);
- }
-}
-
-bool WifiNanIface::isValid() {
- return is_valid_;
-}
-
-std::string WifiNanIface::getName() {
- return ifname_;
-}
-
-std::set<sp<V1_0::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks() {
- return event_cb_handler_.getCallbacks();
-}
-
-std::set<sp<V1_2::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks_1_2() {
- return event_cb_handler_1_2_.getCallbacks();
-}
-
-std::set<sp<V1_5::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks_1_5() {
- return event_cb_handler_1_5_.getCallbacks();
-}
-
-std::set<sp<V1_6::IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks_1_6() {
- return event_cb_handler_1_6_.getCallbacks();
-}
-
-Return<void> WifiNanIface::getName(getName_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::getNameInternal, hidl_status_cb);
-}
-
-Return<void> WifiNanIface::getType(getType_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::getTypeInternal, hidl_status_cb);
-}
-
-Return<void> WifiNanIface::registerEventCallback(
- const sp<V1_0::IWifiNanIfaceEventCallback>& callback,
- registerEventCallback_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::registerEventCallbackInternal, hidl_status_cb, callback);
-}
-
-Return<void> WifiNanIface::getCapabilitiesRequest(uint16_t cmd_id,
- getCapabilitiesRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::getCapabilitiesRequestInternal, hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiNanIface::enableRequest(uint16_t cmd_id, const V1_0::NanEnableRequest& msg,
- enableRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::enableRequestInternal, hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::configRequest(uint16_t cmd_id, const V1_0::NanConfigRequest& msg,
- configRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::configRequestInternal, hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::disableRequest(uint16_t cmd_id, disableRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::disableRequestInternal, hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiNanIface::startPublishRequest(uint16_t cmd_id, const V1_0::NanPublishRequest& msg,
- startPublishRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::startPublishRequestInternal, hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::stopPublishRequest(uint16_t cmd_id, uint8_t sessionId,
- stopPublishRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::stopPublishRequestInternal, hidl_status_cb, cmd_id,
- sessionId);
-}
-
-Return<void> WifiNanIface::startSubscribeRequest(uint16_t cmd_id,
- const V1_0::NanSubscribeRequest& msg,
- startSubscribeRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::startSubscribeRequestInternal, hidl_status_cb, cmd_id,
- msg);
-}
-
-Return<void> WifiNanIface::stopSubscribeRequest(uint16_t cmd_id, uint8_t sessionId,
- stopSubscribeRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::stopSubscribeRequestInternal, hidl_status_cb, cmd_id,
- sessionId);
-}
-
-Return<void> WifiNanIface::transmitFollowupRequest(uint16_t cmd_id,
- const NanTransmitFollowupRequest& msg,
- transmitFollowupRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::transmitFollowupRequestInternal, hidl_status_cb, cmd_id,
- msg);
-}
-
-Return<void> WifiNanIface::createDataInterfaceRequest(
- uint16_t cmd_id, const hidl_string& iface_name,
- createDataInterfaceRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::createDataInterfaceRequestInternal, hidl_status_cb,
- cmd_id, iface_name);
-}
-
-Return<void> WifiNanIface::deleteDataInterfaceRequest(
- uint16_t cmd_id, const hidl_string& iface_name,
- deleteDataInterfaceRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::deleteDataInterfaceRequestInternal, hidl_status_cb,
- cmd_id, iface_name);
-}
-
-Return<void> WifiNanIface::initiateDataPathRequest(uint16_t cmd_id,
- const V1_0::NanInitiateDataPathRequest& msg,
- initiateDataPathRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::initiateDataPathRequestInternal, hidl_status_cb, cmd_id,
- msg);
-}
-
-Return<void> WifiNanIface::respondToDataPathIndicationRequest(
- uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg,
- respondToDataPathIndicationRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::respondToDataPathIndicationRequestInternal,
- hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::terminateDataPathRequest(uint16_t cmd_id, uint32_t ndpInstanceId,
- terminateDataPathRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::terminateDataPathRequestInternal, hidl_status_cb, cmd_id,
- ndpInstanceId);
-}
-
-Return<void> WifiNanIface::registerEventCallback_1_2(
- const sp<V1_2::IWifiNanIfaceEventCallback>& callback,
- registerEventCallback_1_2_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::registerEventCallback_1_2Internal, hidl_status_cb,
- callback);
-}
-
-Return<void> WifiNanIface::enableRequest_1_2(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2,
- enableRequest_1_2_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::enableRequest_1_2Internal, hidl_status_cb, cmd_id, msg1,
- msg2);
-}
-
-Return<void> WifiNanIface::configRequest_1_2(uint16_t cmd_id, const V1_0::NanConfigRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2,
- configRequest_1_2_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::configRequest_1_2Internal, hidl_status_cb, cmd_id, msg1,
- msg2);
-}
-
-Return<void> WifiNanIface::enableRequest_1_4(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2,
- enableRequest_1_4_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::enableRequest_1_4Internal, hidl_status_cb, cmd_id, msg1,
- msg2);
-}
-
-Return<void> WifiNanIface::configRequest_1_4(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2,
- configRequest_1_4_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::configRequest_1_4Internal, hidl_status_cb, cmd_id, msg1,
- msg2);
-}
-
-Return<void> WifiNanIface::registerEventCallback_1_5(
- const sp<V1_5::IWifiNanIfaceEventCallback>& callback,
- registerEventCallback_1_5_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::registerEventCallback_1_5Internal, hidl_status_cb,
- callback);
-}
-
-Return<void> WifiNanIface::enableRequest_1_5(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
- const V1_5::NanConfigRequestSupplemental& msg2,
- enableRequest_1_5_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::enableRequest_1_5Internal, hidl_status_cb, cmd_id, msg1,
- msg2);
-}
-
-Return<void> WifiNanIface::configRequest_1_5(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
- const V1_5::NanConfigRequestSupplemental& msg2,
- configRequest_1_5_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::configRequest_1_5Internal, hidl_status_cb, cmd_id, msg1,
- msg2);
-}
-
-Return<void> WifiNanIface::getCapabilitiesRequest_1_5(
- uint16_t cmd_id, getCapabilitiesRequest_1_5_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::getCapabilitiesRequest_1_5Internal, hidl_status_cb,
- cmd_id);
-}
-
-Return<void> WifiNanIface::enableRequest_1_6(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
- const V1_6::NanConfigRequestSupplemental& msg2,
- enableRequest_1_5_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::enableRequest_1_6Internal, hidl_status_cb, cmd_id, msg1,
- msg2);
-}
-
-Return<void> WifiNanIface::configRequest_1_6(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
- const V1_6::NanConfigRequestSupplemental& msg2,
- configRequest_1_5_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::configRequest_1_6Internal, hidl_status_cb, cmd_id, msg1,
- msg2);
-}
-
-Return<void> WifiNanIface::initiateDataPathRequest_1_6(uint16_t cmd_id,
- const V1_6::NanInitiateDataPathRequest& msg,
- initiateDataPathRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::initiateDataPathRequest_1_6Internal, hidl_status_cb,
- cmd_id, msg);
-}
-
-Return<void> WifiNanIface::respondToDataPathIndicationRequest_1_6(
- uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg,
- respondToDataPathIndicationRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::respondToDataPathIndicationRequest_1_6Internal,
- hidl_status_cb, cmd_id, msg);
-}
-
-Return<void> WifiNanIface::startPublishRequest_1_6(uint16_t cmd_id,
- const V1_6::NanPublishRequest& msg,
- startPublishRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::startPublishRequest_1_6Internal, hidl_status_cb, cmd_id,
- msg);
-}
-
-std::pair<WifiStatus, std::string> WifiNanIface::getNameInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
-}
-
-std::pair<WifiStatus, IfaceType> WifiNanIface::getTypeInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::NAN};
-}
-
-Return<void> WifiNanIface::registerEventCallback_1_6(
- const sp<V1_6::IWifiNanIfaceEventCallback>& callback,
- registerEventCallback_1_6_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiNanIface::registerEventCallback_1_6Internal, hidl_status_cb,
- callback);
-}
-
-WifiStatus WifiNanIface::registerEventCallbackInternal(
- const sp<V1_0::IWifiNanIfaceEventCallback>& callback) {
- if (!event_cb_handler_.addCallback(callback)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiNanIface::getCapabilitiesRequestInternal(uint16_t /* cmd_id */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::enableRequestInternal(uint16_t /* cmd_id */,
- const V1_0::NanEnableRequest& /* msg */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::configRequestInternal(uint16_t /* cmd_id */,
- const V1_0::NanConfigRequest& /* msg */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::disableRequestInternal(uint16_t cmd_id) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanDisableRequest(ifname_, cmd_id);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::startPublishRequestInternal(uint16_t /* cmd_id */,
- const V1_0::NanPublishRequest& /* msg */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId) {
- legacy_hal::NanPublishCancelRequest legacy_msg;
- legacy_msg.publish_id = sessionId;
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanPublishCancelRequest(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::startSubscribeRequestInternal(uint16_t cmd_id,
- const V1_0::NanSubscribeRequest& msg) {
- legacy_hal::NanSubscribeRequest legacy_msg;
- if (!hidl_struct_util::convertHidlNanSubscribeRequestToLegacy(msg, &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanSubscribeRequest(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId) {
- legacy_hal::NanSubscribeCancelRequest legacy_msg;
- legacy_msg.subscribe_id = sessionId;
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanSubscribeCancelRequest(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::transmitFollowupRequestInternal(uint16_t cmd_id,
- const NanTransmitFollowupRequest& msg) {
- legacy_hal::NanTransmitFollowupRequest legacy_msg;
- if (!hidl_struct_util::convertHidlNanTransmitFollowupRequestToLegacy(msg, &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanTransmitFollowupRequest(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::createDataInterfaceRequestInternal(uint16_t cmd_id,
- const std::string& iface_name) {
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanDataInterfaceCreate(ifname_, cmd_id, iface_name);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::deleteDataInterfaceRequestInternal(uint16_t cmd_id,
- const std::string& iface_name) {
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, cmd_id, iface_name);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::initiateDataPathRequestInternal(
- uint16_t cmd_id, const V1_0::NanInitiateDataPathRequest& msg) {
- legacy_hal::NanDataPathInitiatorRequest legacy_msg;
- if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequestToLegacy(msg, &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::respondToDataPathIndicationRequestInternal(
- uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg) {
- legacy_hal::NanDataPathIndicationResponse legacy_msg;
- if (!hidl_struct_util::convertHidlNanDataPathIndicationResponseToLegacy(msg, &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-WifiStatus WifiNanIface::terminateDataPathRequestInternal(uint16_t cmd_id, uint32_t ndpInstanceId) {
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanDataEnd(ifname_, cmd_id, ndpInstanceId);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::registerEventCallback_1_2Internal(
- const sp<V1_2::IWifiNanIfaceEventCallback>& callback) {
- sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback;
- if (!event_cb_handler_.addCallback(callback_1_0)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- if (!event_cb_handler_1_2_.addCallback(callback)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiNanIface::enableRequest_1_2Internal(
- uint16_t /* cmd_id */, const V1_0::NanEnableRequest& /* msg1 */,
- const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::configRequest_1_2Internal(
- uint16_t /* cmd_id */, const V1_0::NanConfigRequest& /* msg1 */,
- const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::enableRequest_1_4Internal(
- uint16_t /* cmd_id */, const V1_4::NanEnableRequest& /* msg1 */,
- const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::configRequest_1_4Internal(
- uint16_t /* cmd_id */, const V1_4::NanConfigRequest& /* msg1 */,
- const V1_2::NanConfigRequestSupplemental& /* msg2 */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::registerEventCallback_1_5Internal(
- const sp<V1_5::IWifiNanIfaceEventCallback>& callback) {
- sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback;
- if (!event_cb_handler_.addCallback(callback_1_0)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- sp<V1_2::IWifiNanIfaceEventCallback> callback_1_2 = callback;
- if (!event_cb_handler_1_2_.addCallback(callback_1_2)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- if (!event_cb_handler_1_5_.addCallback(callback)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiNanIface::getCapabilitiesRequest_1_5Internal(uint16_t cmd_id) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::enableRequest_1_5Internal(
- uint16_t /* cmd_id */, const V1_4::NanEnableRequest& /* msg1 */,
- const V1_5::NanConfigRequestSupplemental& /* msg2 */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::configRequest_1_5Internal(
- uint16_t /* cmd_id */, const V1_4::NanConfigRequest& /* msg1 */,
- const V1_5::NanConfigRequestSupplemental& /* msg2 */) {
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiNanIface::enableRequest_1_6Internal(uint16_t cmd_id,
- const V1_4::NanEnableRequest& msg1,
- const V1_6::NanConfigRequestSupplemental& msg2) {
- legacy_hal::NanEnableRequest legacy_msg;
- if (!hidl_struct_util::convertHidlNanEnableRequest_1_6ToLegacy(msg1, msg2, &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::configRequest_1_6Internal(uint16_t cmd_id,
- const V1_4::NanConfigRequest& msg1,
- const V1_6::NanConfigRequestSupplemental& msg2) {
- legacy_hal::NanConfigRequest legacy_msg;
- if (!hidl_struct_util::convertHidlNanConfigRequest_1_6ToLegacy(msg1, msg2, &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::initiateDataPathRequest_1_6Internal(
- uint16_t cmd_id, const V1_6::NanInitiateDataPathRequest& msg) {
- legacy_hal::NanDataPathInitiatorRequest legacy_msg;
- if (!hidl_struct_util::convertHidlNanDataPathInitiatorRequest_1_6ToLegacy(msg, &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::respondToDataPathIndicationRequest_1_6Internal(
- uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg) {
- legacy_hal::NanDataPathIndicationResponse legacy_msg;
- if (!hidl_struct_util::convertHidlNanDataPathIndicationResponse_1_6ToLegacy(msg, &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::startPublishRequest_1_6Internal(uint16_t cmd_id,
- const V1_6::NanPublishRequest& msg) {
- legacy_hal::NanPublishRequest legacy_msg;
- if (!hidl_struct_util::convertHidlNanPublishRequestToLegacy(msg, &legacy_msg)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->nanPublishRequest(ifname_, cmd_id, legacy_msg);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiNanIface::registerEventCallback_1_6Internal(
- const sp<V1_6::IWifiNanIfaceEventCallback>& callback) {
- sp<V1_0::IWifiNanIfaceEventCallback> callback_1_0 = callback;
- if (!event_cb_handler_.addCallback(callback_1_0)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- sp<V1_2::IWifiNanIfaceEventCallback> callback_1_2 = callback;
- if (!event_cb_handler_1_2_.addCallback(callback_1_2)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- sp<V1_5::IWifiNanIfaceEventCallback> callback_1_5 = callback;
- if (!event_cb_handler_1_5_.addCallback(callback_1_5)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- if (!event_cb_handler_1_6_.addCallback(callback)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_nan_iface.h b/wifi/1.6/default/wifi_nan_iface.h
deleted file mode 100644
index 15bf572..0000000
--- a/wifi/1.6/default/wifi_nan_iface.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_NAN_IFACE_H_
-#define WIFI_NAN_IFACE_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.6/IWifiNanIface.h>
-#include <android/hardware/wifi/1.6/IWifiNanIfaceEventCallback.h>
-
-#include "hidl_callback_util.h"
-#include "wifi_iface_util.h"
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-using namespace android::hardware::wifi::V1_2;
-using namespace android::hardware::wifi::V1_4;
-using namespace android::hardware::wifi::V1_6;
-
-/**
- * HIDL interface object used to control a NAN Iface instance.
- */
-class WifiNanIface : public V1_6::IWifiNanIface {
- public:
- WifiNanIface(const std::string& ifname, bool is_dedicated_iface,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
- const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
- // Refer to |WifiChip::invalidate()|.
- void invalidate();
- bool isValid();
- std::string getName();
-
- // HIDL methods exposed.
- Return<void> getName(getName_cb hidl_status_cb) override;
- Return<void> getType(getType_cb hidl_status_cb) override;
- Return<void> registerEventCallback(const sp<V1_0::IWifiNanIfaceEventCallback>& callback,
- registerEventCallback_cb hidl_status_cb) override;
- Return<void> getCapabilitiesRequest(uint16_t cmd_id,
- getCapabilitiesRequest_cb hidl_status_cb) override;
- Return<void> enableRequest(uint16_t cmd_id, const V1_0::NanEnableRequest& msg,
- enableRequest_cb hidl_status_cb) override;
- Return<void> configRequest(uint16_t cmd_id, const V1_0::NanConfigRequest& msg,
- configRequest_cb hidl_status_cb) override;
- Return<void> disableRequest(uint16_t cmd_id, disableRequest_cb hidl_status_cb) override;
- Return<void> startPublishRequest(uint16_t cmd_id, const V1_0::NanPublishRequest& msg,
- startPublishRequest_cb hidl_status_cb) override;
- Return<void> stopPublishRequest(uint16_t cmd_id, uint8_t sessionId,
- stopPublishRequest_cb hidl_status_cb) override;
- Return<void> startSubscribeRequest(uint16_t cmd_id, const V1_0::NanSubscribeRequest& msg,
- startSubscribeRequest_cb hidl_status_cb) override;
- Return<void> stopSubscribeRequest(uint16_t cmd_id, uint8_t sessionId,
- stopSubscribeRequest_cb hidl_status_cb) override;
- Return<void> transmitFollowupRequest(uint16_t cmd_id, const NanTransmitFollowupRequest& msg,
- transmitFollowupRequest_cb hidl_status_cb) override;
- Return<void> createDataInterfaceRequest(uint16_t cmd_id, const hidl_string& iface_name,
- createDataInterfaceRequest_cb hidl_status_cb) override;
- Return<void> deleteDataInterfaceRequest(uint16_t cmd_id, const hidl_string& iface_name,
- deleteDataInterfaceRequest_cb hidl_status_cb) override;
- Return<void> initiateDataPathRequest(uint16_t cmd_id,
- const V1_0::NanInitiateDataPathRequest& msg,
- initiateDataPathRequest_cb hidl_status_cb) override;
- Return<void> respondToDataPathIndicationRequest(
- uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg,
- respondToDataPathIndicationRequest_cb hidl_status_cb) override;
- Return<void> terminateDataPathRequest(uint16_t cmd_id, uint32_t ndpInstanceId,
- terminateDataPathRequest_cb hidl_status_cb) override;
-
- Return<void> registerEventCallback_1_2(const sp<V1_2::IWifiNanIfaceEventCallback>& callback,
- registerEventCallback_1_2_cb hidl_status_cb) override;
- Return<void> enableRequest_1_2(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2,
- enableRequest_1_2_cb hidl_status_cb) override;
- Return<void> configRequest_1_2(uint16_t cmd_id, const V1_0::NanConfigRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2,
- configRequest_1_2_cb hidl_status_cb) override;
- Return<void> enableRequest_1_4(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2,
- enableRequest_1_4_cb hidl_status_cb) override;
- Return<void> configRequest_1_4(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2,
- configRequest_1_4_cb hidl_status_cb) override;
- Return<void> registerEventCallback_1_5(const sp<V1_5::IWifiNanIfaceEventCallback>& callback,
- registerEventCallback_1_5_cb hidl_status_cb) override;
- Return<void> enableRequest_1_5(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
- const V1_5::NanConfigRequestSupplemental& msg2,
- enableRequest_1_5_cb hidl_status_cb) override;
- Return<void> configRequest_1_5(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
- const V1_5::NanConfigRequestSupplemental& msg2,
- configRequest_1_5_cb hidl_status_cb) override;
- Return<void> getCapabilitiesRequest_1_5(uint16_t cmd_id,
- getCapabilitiesRequest_cb hidl_status_cb) override;
- Return<void> registerEventCallback_1_6(const sp<V1_6::IWifiNanIfaceEventCallback>& callback,
- registerEventCallback_1_6_cb hidl_status_cb) override;
- Return<void> initiateDataPathRequest_1_6(
- uint16_t cmd_id, const V1_6::NanInitiateDataPathRequest& msg,
- initiateDataPathRequest_1_6_cb hidl_status_cb) override;
- Return<void> respondToDataPathIndicationRequest_1_6(
- uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg,
- respondToDataPathIndicationRequest_1_6_cb hidl_status_cb) override;
- Return<void> enableRequest_1_6(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
- const V1_6::NanConfigRequestSupplemental& msg2,
- enableRequest_1_6_cb hidl_status_cb) override;
- Return<void> configRequest_1_6(uint16_t cmd_id, const V1_4::NanConfigRequest& msg1,
- const V1_6::NanConfigRequestSupplemental& msg2,
- configRequest_1_6_cb hidl_status_cb) override;
- Return<void> startPublishRequest_1_6(uint16_t cmd_id, const V1_6::NanPublishRequest& msg,
- startPublishRequest_cb hidl_status_cb) override;
-
- private:
- // Corresponding worker functions for the HIDL methods.
- std::pair<WifiStatus, std::string> getNameInternal();
- std::pair<WifiStatus, IfaceType> getTypeInternal();
- WifiStatus registerEventCallbackInternal(const sp<V1_0::IWifiNanIfaceEventCallback>& callback);
- WifiStatus getCapabilitiesRequestInternal(uint16_t cmd_id);
- WifiStatus enableRequestInternal(uint16_t cmd_id, const V1_0::NanEnableRequest& msg);
- WifiStatus configRequestInternal(uint16_t cmd_id, const V1_0::NanConfigRequest& msg);
- WifiStatus disableRequestInternal(uint16_t cmd_id);
- WifiStatus startPublishRequestInternal(uint16_t cmd_id, const V1_0::NanPublishRequest& msg);
- WifiStatus stopPublishRequestInternal(uint16_t cmd_id, uint8_t sessionId);
- WifiStatus startSubscribeRequestInternal(uint16_t cmd_id, const V1_0::NanSubscribeRequest& msg);
- WifiStatus stopSubscribeRequestInternal(uint16_t cmd_id, uint8_t sessionId);
- WifiStatus transmitFollowupRequestInternal(uint16_t cmd_id,
- const NanTransmitFollowupRequest& msg);
- WifiStatus createDataInterfaceRequestInternal(uint16_t cmd_id, const std::string& iface_name);
- WifiStatus deleteDataInterfaceRequestInternal(uint16_t cmd_id, const std::string& iface_name);
- WifiStatus initiateDataPathRequestInternal(uint16_t cmd_id,
- const V1_0::NanInitiateDataPathRequest& msg);
- WifiStatus respondToDataPathIndicationRequestInternal(
- uint16_t cmd_id, const V1_0::NanRespondToDataPathIndicationRequest& msg);
- WifiStatus terminateDataPathRequestInternal(uint16_t cmd_id, uint32_t ndpInstanceId);
-
- WifiStatus registerEventCallback_1_2Internal(
- const sp<V1_2::IWifiNanIfaceEventCallback>& callback);
- WifiStatus enableRequest_1_2Internal(uint16_t cmd_id, const V1_0::NanEnableRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2);
- WifiStatus configRequest_1_2Internal(uint16_t cmd_id, const V1_0::NanConfigRequest& msg,
- const V1_2::NanConfigRequestSupplemental& msg2);
- WifiStatus enableRequest_1_4Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
- const V1_2::NanConfigRequestSupplemental& msg2);
- WifiStatus configRequest_1_4Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg,
- const V1_2::NanConfigRequestSupplemental& msg2);
- WifiStatus registerEventCallback_1_5Internal(
- const sp<V1_5::IWifiNanIfaceEventCallback>& callback);
- WifiStatus enableRequest_1_5Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
- const V1_5::NanConfigRequestSupplemental& msg2);
- WifiStatus configRequest_1_5Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg,
- const V1_5::NanConfigRequestSupplemental& msg2);
- WifiStatus getCapabilitiesRequest_1_5Internal(uint16_t cmd_id);
- WifiStatus registerEventCallback_1_6Internal(
- const sp<V1_6::IWifiNanIfaceEventCallback>& callback);
-
- WifiStatus enableRequest_1_6Internal(uint16_t cmd_id, const V1_4::NanEnableRequest& msg1,
- const V1_6::NanConfigRequestSupplemental& msg2);
- WifiStatus configRequest_1_6Internal(uint16_t cmd_id, const V1_4::NanConfigRequest& msg,
- const V1_6::NanConfigRequestSupplemental& msg2);
- WifiStatus startPublishRequest_1_6Internal(uint16_t cmd_id, const V1_6::NanPublishRequest& msg);
- WifiStatus initiateDataPathRequest_1_6Internal(uint16_t cmd_id,
- const V1_6::NanInitiateDataPathRequest& msg);
- WifiStatus respondToDataPathIndicationRequest_1_6Internal(
- uint16_t cmd_id, const V1_6::NanRespondToDataPathIndicationRequest& msg);
-
- // all 1_0 and descendant callbacks
- std::set<sp<V1_0::IWifiNanIfaceEventCallback>> getEventCallbacks();
- // all 1_2 and descendant callbacks
- std::set<sp<V1_2::IWifiNanIfaceEventCallback>> getEventCallbacks_1_2();
- // all 1_5 and descendant callbacks
- std::set<sp<V1_5::IWifiNanIfaceEventCallback>> getEventCallbacks_1_5();
- // all 1_6 and descendant callbacks
- std::set<sp<V1_6::IWifiNanIfaceEventCallback>> getEventCallbacks_1_6();
-
- std::string ifname_;
- bool is_dedicated_iface_;
- std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
- std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
- bool is_valid_;
- hidl_callback_util::HidlCallbackHandler<V1_0::IWifiNanIfaceEventCallback> event_cb_handler_;
- hidl_callback_util::HidlCallbackHandler<V1_2::IWifiNanIfaceEventCallback> event_cb_handler_1_2_;
- hidl_callback_util::HidlCallbackHandler<V1_5::IWifiNanIfaceEventCallback> event_cb_handler_1_5_;
- hidl_callback_util::HidlCallbackHandler<V1_6::IWifiNanIfaceEventCallback> event_cb_handler_1_6_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiNanIface);
-};
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_NAN_IFACE_H_
diff --git a/wifi/1.6/default/wifi_p2p_iface.cpp b/wifi/1.6/default/wifi_p2p_iface.cpp
deleted file mode 100644
index d4b1fca..0000000
--- a/wifi/1.6/default/wifi_p2p_iface.cpp
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "wifi_p2p_iface.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiP2pIface::WifiP2pIface(const std::string& ifname,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
- : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}
-
-void WifiP2pIface::invalidate() {
- legacy_hal_.reset();
- is_valid_ = false;
-}
-
-bool WifiP2pIface::isValid() {
- return is_valid_;
-}
-
-std::string WifiP2pIface::getName() {
- return ifname_;
-}
-
-Return<void> WifiP2pIface::getName(getName_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiP2pIface::getNameInternal, hidl_status_cb);
-}
-
-Return<void> WifiP2pIface::getType(getType_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiP2pIface::getTypeInternal, hidl_status_cb);
-}
-
-std::pair<WifiStatus, std::string> WifiP2pIface::getNameInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
-}
-
-std::pair<WifiStatus, IfaceType> WifiP2pIface::getTypeInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::P2P};
-}
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_p2p_iface.h b/wifi/1.6/default/wifi_p2p_iface.h
deleted file mode 100644
index 0089443..0000000
--- a/wifi/1.6/default/wifi_p2p_iface.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_P2P_IFACE_H_
-#define WIFI_P2P_IFACE_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiP2pIface.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * HIDL interface object used to control a P2P Iface instance.
- */
-class WifiP2pIface : public V1_0::IWifiP2pIface {
- public:
- WifiP2pIface(const std::string& ifname,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
- // Refer to |WifiChip::invalidate()|.
- void invalidate();
- bool isValid();
- std::string getName();
-
- // HIDL methods exposed.
- Return<void> getName(getName_cb hidl_status_cb) override;
- Return<void> getType(getType_cb hidl_status_cb) override;
-
- private:
- // Corresponding worker functions for the HIDL methods.
- std::pair<WifiStatus, std::string> getNameInternal();
- std::pair<WifiStatus, IfaceType> getTypeInternal();
-
- std::string ifname_;
- std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
- bool is_valid_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiP2pIface);
-};
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_P2P_IFACE_H_
diff --git a/wifi/1.6/default/wifi_rtt_controller.cpp b/wifi/1.6/default/wifi_rtt_controller.cpp
deleted file mode 100644
index aa9ee2f..0000000
--- a/wifi/1.6/default/wifi_rtt_controller.cpp
+++ /dev/null
@@ -1,377 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_rtt_controller.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiRttController::WifiRttController(const std::string& iface_name,
- const sp<IWifiIface>& bound_iface,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
- : ifname_(iface_name), bound_iface_(bound_iface), legacy_hal_(legacy_hal), is_valid_(true) {}
-
-void WifiRttController::invalidate() {
- legacy_hal_.reset();
- event_callbacks_.clear();
- is_valid_ = false;
-}
-
-bool WifiRttController::isValid() {
- return is_valid_;
-}
-
-std::vector<sp<V1_6::IWifiRttControllerEventCallback>> WifiRttController::getEventCallbacks() {
- return event_callbacks_;
-}
-
-std::string WifiRttController::getIfaceName() {
- return ifname_;
-}
-
-Return<void> WifiRttController::getBoundIface(getBoundIface_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::getBoundIfaceInternal, hidl_status_cb);
-}
-
-Return<void> WifiRttController::registerEventCallback(
- const sp<V1_0::IWifiRttControllerEventCallback>& callback,
- registerEventCallback_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::registerEventCallbackInternal, hidl_status_cb,
- callback);
-}
-
-Return<void> WifiRttController::rangeRequest(uint32_t cmd_id,
- const hidl_vec<V1_0::RttConfig>& rtt_configs,
- rangeRequest_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::rangeRequestInternal, hidl_status_cb, cmd_id,
- rtt_configs);
-}
-
-Return<void> WifiRttController::rangeCancel(uint32_t cmd_id,
- const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
- rangeCancel_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::rangeCancelInternal, hidl_status_cb, cmd_id, addrs);
-}
-
-Return<void> WifiRttController::getCapabilities(getCapabilities_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::getCapabilitiesInternal, hidl_status_cb);
-}
-
-Return<void> WifiRttController::setLci(uint32_t cmd_id, const RttLciInformation& lci,
- setLci_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::setLciInternal, hidl_status_cb, cmd_id, lci);
-}
-
-Return<void> WifiRttController::setLcr(uint32_t cmd_id, const RttLcrInformation& lcr,
- setLcr_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::setLcrInternal, hidl_status_cb, cmd_id, lcr);
-}
-
-Return<void> WifiRttController::getResponderInfo(getResponderInfo_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::getResponderInfoInternal, hidl_status_cb);
-}
-
-Return<void> WifiRttController::enableResponder(uint32_t cmd_id,
- const V1_0::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds,
- const V1_0::RttResponder& info,
- enableResponder_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::enableResponderInternal, hidl_status_cb, cmd_id,
- channel_hint, max_duration_seconds, info);
-}
-
-Return<void> WifiRttController::disableResponder(uint32_t cmd_id,
- disableResponder_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::disableResponderInternal, hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiRttController::registerEventCallback_1_4(
- const sp<V1_4::IWifiRttControllerEventCallback>& callback,
- registerEventCallback_1_4_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::registerEventCallbackInternal_1_4, hidl_status_cb,
- callback);
-}
-
-Return<void> WifiRttController::rangeRequest_1_4(uint32_t cmd_id,
- const hidl_vec<V1_4::RttConfig>& rtt_configs,
- rangeRequest_1_4_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::rangeRequestInternal_1_4, hidl_status_cb, cmd_id,
- rtt_configs);
-}
-
-Return<void> WifiRttController::getCapabilities_1_4(getCapabilities_1_4_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::getCapabilitiesInternal_1_4, hidl_status_cb);
-}
-
-Return<void> WifiRttController::getResponderInfo_1_4(getResponderInfo_1_4_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::getResponderInfoInternal_1_4, hidl_status_cb);
-}
-
-Return<void> WifiRttController::enableResponder_1_4(uint32_t cmd_id,
- const V1_0::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds,
- const V1_4::RttResponder& info,
- enableResponder_1_4_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::enableResponderInternal_1_4, hidl_status_cb, cmd_id,
- channel_hint, max_duration_seconds, info);
-}
-
-Return<void> WifiRttController::registerEventCallback_1_6(
- const sp<V1_6::IWifiRttControllerEventCallback>& callback,
- registerEventCallback_1_6_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::registerEventCallbackInternal_1_6, hidl_status_cb,
- callback);
-}
-
-Return<void> WifiRttController::rangeRequest_1_6(uint32_t cmd_id,
- const hidl_vec<V1_6::RttConfig>& rtt_configs,
- rangeRequest_1_6_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::rangeRequestInternal_1_6, hidl_status_cb, cmd_id,
- rtt_configs);
-}
-
-Return<void> WifiRttController::getCapabilities_1_6(getCapabilities_1_6_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::getCapabilitiesInternal_1_6, hidl_status_cb);
-}
-
-Return<void> WifiRttController::getResponderInfo_1_6(getResponderInfo_1_6_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::getResponderInfoInternal_1_6, hidl_status_cb);
-}
-
-Return<void> WifiRttController::enableResponder_1_6(uint32_t cmd_id,
- const V1_6::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds,
- const V1_6::RttResponder& info,
- enableResponder_1_6_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
- &WifiRttController::enableResponderInternal_1_6, hidl_status_cb, cmd_id,
- channel_hint, max_duration_seconds, info);
-}
-
-std::pair<WifiStatus, sp<IWifiIface>> WifiRttController::getBoundIfaceInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), bound_iface_};
-}
-
-WifiStatus WifiRttController::registerEventCallbackInternal(
- const sp<V1_0::IWifiRttControllerEventCallback>& /* callback */) {
- // Deprecated support for this api
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiRttController::rangeRequestInternal(
- uint32_t /* cmd_id */, const std::vector<V1_0::RttConfig>& /* rtt_configs */) {
- // Deprecated support for this api
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiRttController::rangeCancelInternal(
- uint32_t cmd_id, const std::vector<hidl_array<uint8_t, 6>>& addrs) {
- std::vector<std::array<uint8_t, 6>> legacy_addrs;
- for (const auto& addr : addrs) {
- legacy_addrs.push_back(addr);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->cancelRttRangeRequest(ifname_, cmd_id, legacy_addrs);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, V1_0::RttCapabilities> WifiRttController::getCapabilitiesInternal() {
- // Deprecated support for this api
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-WifiStatus WifiRttController::setLciInternal(uint32_t cmd_id, const RttLciInformation& lci) {
- legacy_hal::wifi_lci_information legacy_lci;
- if (!hidl_struct_util::convertHidlRttLciInformationToLegacy(lci, &legacy_lci)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->setRttLci(ifname_, cmd_id, legacy_lci);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiRttController::setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr) {
- legacy_hal::wifi_lcr_information legacy_lcr;
- if (!hidl_struct_util::convertHidlRttLcrInformationToLegacy(lcr, &legacy_lcr)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->setRttLcr(ifname_, cmd_id, legacy_lcr);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, V1_0::RttResponder> WifiRttController::getResponderInfoInternal() {
- // Deprecated support for this api
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-WifiStatus WifiRttController::enableResponderInternal(
- uint32_t /* cmd_id */, const V1_0::WifiChannelInfo& /* channel_hint */,
- uint32_t /* max_duration_seconds */, const V1_0::RttResponder& /* info */) {
- // Deprecated support for this api
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED)};
-}
-
-WifiStatus WifiRttController::disableResponderInternal(uint32_t cmd_id) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableRttResponder(ifname_, cmd_id);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiRttController::registerEventCallbackInternal_1_4(
- const sp<V1_4::IWifiRttControllerEventCallback>& /* callback */) {
- // Deprecated support for this api
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiRttController::rangeRequestInternal_1_4(
- uint32_t /* cmd_id */, const std::vector<V1_4::RttConfig>& /* rtt_configs */) {
- // Deprecated support for this api
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-std::pair<WifiStatus, V1_4::RttCapabilities> WifiRttController::getCapabilitiesInternal_1_4() {
- // Deprecated support for this api
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-std::pair<WifiStatus, V1_4::RttResponder> WifiRttController::getResponderInfoInternal_1_4() {
- // Deprecated support for this api
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-WifiStatus WifiRttController::enableResponderInternal_1_4(
- uint32_t /* cmd_id */, const V1_0::WifiChannelInfo& /* channel_hint */,
- uint32_t /* max_duration_seconds */, const V1_4::RttResponder& /* info */) {
- // Deprecated support for this api
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED)};
-}
-
-WifiStatus WifiRttController::registerEventCallbackInternal_1_6(
- const sp<V1_6::IWifiRttControllerEventCallback>& callback) {
- // TODO(b/31632518): remove the callback when the client is destroyed
- event_callbacks_.emplace_back(callback);
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-WifiStatus WifiRttController::rangeRequestInternal_1_6(
- uint32_t cmd_id, const std::vector<V1_6::RttConfig>& rtt_configs) {
- std::vector<legacy_hal::wifi_rtt_config> legacy_configs;
- if (!hidl_struct_util::convertHidlVectorOfRttConfigToLegacy(rtt_configs, &legacy_configs)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- android::wp<WifiRttController> weak_ptr_this(this);
- const auto& on_results_callback =
- [weak_ptr_this](legacy_hal::wifi_request_id id,
- const std::vector<const legacy_hal::wifi_rtt_result*>& results) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- std::vector<V1_6::RttResult> hidl_results;
- if (!hidl_struct_util::convertLegacyVectorOfRttResultToHidl(results,
- &hidl_results)) {
- LOG(ERROR) << "Failed to convert rtt results to HIDL structs";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->onResults_1_6(id, hidl_results).isOk()) {
- LOG(ERROR) << "Failed to invoke the callback";
- }
- }
- };
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequest(
- ifname_, cmd_id, legacy_configs, on_results_callback);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, V1_6::RttCapabilities> WifiRttController::getCapabilitiesInternal_1_6() {
- legacy_hal::wifi_error legacy_status;
- legacy_hal::wifi_rtt_capabilities legacy_caps;
- std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRttCapabilities(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- V1_6::RttCapabilities hidl_caps;
- if (!hidl_struct_util::convertLegacyRttCapabilitiesToHidl(legacy_caps, &hidl_caps)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, V1_6::RttResponder> WifiRttController::getResponderInfoInternal_1_6() {
- legacy_hal::wifi_error legacy_status;
- legacy_hal::wifi_rtt_responder legacy_responder;
- std::tie(legacy_status, legacy_responder) = legacy_hal_.lock()->getRttResponderInfo(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- V1_6::RttResponder hidl_responder;
- if (!hidl_struct_util::convertLegacyRttResponderToHidl(legacy_responder, &hidl_responder)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_responder};
-}
-
-WifiStatus WifiRttController::enableResponderInternal_1_6(uint32_t cmd_id,
- const V1_6::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds,
- const V1_6::RttResponder& info) {
- legacy_hal::wifi_channel_info legacy_channel_info;
- if (!hidl_struct_util::convertHidlWifiChannelInfoToLegacy(channel_hint, &legacy_channel_info)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_rtt_responder legacy_responder;
- if (!hidl_struct_util::convertHidlRttResponderToLegacy(info, &legacy_responder)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableRttResponder(
- ifname_, cmd_id, legacy_channel_info, max_duration_seconds, legacy_responder);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_rtt_controller.h b/wifi/1.6/default/wifi_rtt_controller.h
deleted file mode 100644
index fd5f68b..0000000
--- a/wifi/1.6/default/wifi_rtt_controller.h
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_RTT_CONTROLLER_H_
-#define WIFI_RTT_CONTROLLER_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiIface.h>
-#include <android/hardware/wifi/1.6/IWifiRttController.h>
-#include <android/hardware/wifi/1.6/IWifiRttControllerEventCallback.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-
-/**
- * HIDL interface object used to control all RTT operations.
- */
-class WifiRttController : public V1_6::IWifiRttController {
- public:
- WifiRttController(const std::string& iface_name, const sp<IWifiIface>& bound_iface,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
- // Refer to |WifiChip::invalidate()|.
- void invalidate();
- bool isValid();
- std::vector<sp<V1_6::IWifiRttControllerEventCallback>> getEventCallbacks();
- std::string getIfaceName();
-
- // HIDL methods exposed.
- Return<void> getBoundIface(getBoundIface_cb hidl_status_cb) override;
- Return<void> registerEventCallback(const sp<V1_0::IWifiRttControllerEventCallback>& callback,
- registerEventCallback_cb hidl_status_cb) override;
- Return<void> rangeRequest(uint32_t cmd_id, const hidl_vec<V1_0::RttConfig>& rtt_configs,
- rangeRequest_cb hidl_status_cb) override;
- Return<void> rangeCancel(uint32_t cmd_id, const hidl_vec<hidl_array<uint8_t, 6>>& addrs,
- rangeCancel_cb hidl_status_cb) override;
- Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
- Return<void> setLci(uint32_t cmd_id, const RttLciInformation& lci,
- setLci_cb hidl_status_cb) override;
- Return<void> setLcr(uint32_t cmd_id, const RttLcrInformation& lcr,
- setLcr_cb hidl_status_cb) override;
- Return<void> getResponderInfo(getResponderInfo_cb hidl_status_cb) override;
- Return<void> enableResponder(uint32_t cmd_id, const V1_0::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds, const V1_0::RttResponder& info,
- enableResponder_cb hidl_status_cb) override;
- Return<void> disableResponder(uint32_t cmd_id, disableResponder_cb hidl_status_cb) override;
- Return<void> registerEventCallback_1_4(
- const sp<V1_4::IWifiRttControllerEventCallback>& callback,
- registerEventCallback_1_4_cb hidl_status_cb) override;
- Return<void> rangeRequest_1_4(uint32_t cmd_id, const hidl_vec<V1_4::RttConfig>& rtt_configs,
- rangeRequest_1_4_cb hidl_status_cb) override;
- Return<void> getCapabilities_1_4(getCapabilities_1_4_cb hidl_status_cb) override;
- Return<void> getResponderInfo_1_4(getResponderInfo_1_4_cb hidl_status_cb) override;
- Return<void> enableResponder_1_4(uint32_t cmd_id, const V1_0::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds, const V1_4::RttResponder& info,
- enableResponder_1_4_cb hidl_status_cb) override;
- Return<void> registerEventCallback_1_6(
- const sp<V1_6::IWifiRttControllerEventCallback>& callback,
- registerEventCallback_1_6_cb hidl_status_cb) override;
- Return<void> rangeRequest_1_6(uint32_t cmd_id, const hidl_vec<V1_6::RttConfig>& rtt_configs,
- rangeRequest_1_6_cb hidl_status_cb) override;
- Return<void> getCapabilities_1_6(getCapabilities_1_6_cb hidl_status_cb) override;
- Return<void> getResponderInfo_1_6(getResponderInfo_1_6_cb hidl_status_cb) override;
- Return<void> enableResponder_1_6(uint32_t cmd_id, const V1_6::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds, const V1_6::RttResponder& info,
- enableResponder_1_6_cb hidl_status_cb) override;
-
- private:
- // Corresponding worker functions for the HIDL methods.
- std::pair<WifiStatus, sp<IWifiIface>> getBoundIfaceInternal();
- WifiStatus registerEventCallbackInternal(
- const sp<V1_0::IWifiRttControllerEventCallback>& callback);
- WifiStatus rangeRequestInternal(uint32_t cmd_id,
- const std::vector<V1_0::RttConfig>& rtt_configs);
- WifiStatus rangeCancelInternal(uint32_t cmd_id,
- const std::vector<hidl_array<uint8_t, 6>>& addrs);
- std::pair<WifiStatus, V1_0::RttCapabilities> getCapabilitiesInternal();
- WifiStatus setLciInternal(uint32_t cmd_id, const RttLciInformation& lci);
- WifiStatus setLcrInternal(uint32_t cmd_id, const RttLcrInformation& lcr);
- std::pair<WifiStatus, V1_0::RttResponder> getResponderInfoInternal();
- WifiStatus enableResponderInternal(uint32_t cmd_id, const V1_0::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds,
- const V1_0::RttResponder& info);
- WifiStatus disableResponderInternal(uint32_t cmd_id);
- WifiStatus registerEventCallbackInternal_1_4(
- const sp<V1_4::IWifiRttControllerEventCallback>& callback);
- WifiStatus rangeRequestInternal_1_4(uint32_t cmd_id,
- const std::vector<V1_4::RttConfig>& rtt_configs);
- std::pair<WifiStatus, V1_4::RttCapabilities> getCapabilitiesInternal_1_4();
- std::pair<WifiStatus, V1_4::RttResponder> getResponderInfoInternal_1_4();
- WifiStatus enableResponderInternal_1_4(uint32_t cmd_id,
- const V1_0::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds,
- const V1_4::RttResponder& info);
- WifiStatus registerEventCallbackInternal_1_6(
- const sp<V1_6::IWifiRttControllerEventCallback>& callback);
- WifiStatus rangeRequestInternal_1_6(uint32_t cmd_id,
- const std::vector<V1_6::RttConfig>& rtt_configs);
- std::pair<WifiStatus, V1_6::RttCapabilities> getCapabilitiesInternal_1_6();
- std::pair<WifiStatus, V1_6::RttResponder> getResponderInfoInternal_1_6();
- WifiStatus enableResponderInternal_1_6(uint32_t cmd_id,
- const V1_6::WifiChannelInfo& channel_hint,
- uint32_t max_duration_seconds,
- const V1_6::RttResponder& info);
-
- std::string ifname_;
- sp<IWifiIface> bound_iface_;
- std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
- std::vector<sp<V1_6::IWifiRttControllerEventCallback>> event_callbacks_;
- bool is_valid_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiRttController);
-};
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_RTT_CONTROLLER_H_
diff --git a/wifi/1.6/default/wifi_sta_iface.cpp b/wifi/1.6/default/wifi_sta_iface.cpp
deleted file mode 100644
index dd11839..0000000
--- a/wifi/1.6/default/wifi_sta_iface.cpp
+++ /dev/null
@@ -1,592 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <android-base/logging.h>
-
-#include "hidl_return_util.h"
-#include "hidl_struct_util.h"
-#include "wifi_sta_iface.h"
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using hidl_return_util::validateAndCall;
-
-WifiStaIface::WifiStaIface(const std::string& ifname,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
- const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
- : ifname_(ifname), legacy_hal_(legacy_hal), iface_util_(iface_util), is_valid_(true) {
- // Turn on DFS channel usage for STA iface.
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setDfsFlag(ifname_, true);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- LOG(ERROR) << "Failed to set DFS flag; DFS channels may be unavailable.";
- }
-}
-
-void WifiStaIface::invalidate() {
- legacy_hal_.reset();
- event_cb_handler_.invalidate();
- is_valid_ = false;
-}
-
-bool WifiStaIface::isValid() {
- return is_valid_;
-}
-
-std::string WifiStaIface::getName() {
- return ifname_;
-}
-
-std::set<sp<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
- return event_cb_handler_.getCallbacks();
-}
-
-Return<void> WifiStaIface::getName(getName_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getNameInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getType(getType_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getTypeInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::registerEventCallback(const sp<IWifiStaIfaceEventCallback>& callback,
- registerEventCallback_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::registerEventCallbackInternal, hidl_status_cb, callback);
-}
-
-Return<void> WifiStaIface::getCapabilities(getCapabilities_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getCapabilitiesInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getApfPacketFilterCapabilities(
- getApfPacketFilterCapabilities_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getApfPacketFilterCapabilitiesInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::installApfPacketFilter(uint32_t cmd_id, const hidl_vec<uint8_t>& program,
- installApfPacketFilter_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::installApfPacketFilterInternal, hidl_status_cb, cmd_id,
- program);
-}
-
-Return<void> WifiStaIface::readApfPacketFilterData(readApfPacketFilterData_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::readApfPacketFilterDataInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getBackgroundScanCapabilities(
- getBackgroundScanCapabilities_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getBackgroundScanCapabilitiesInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getValidFrequenciesForBand(
- V1_0::WifiBand band, getValidFrequenciesForBand_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getValidFrequenciesForBandInternal, hidl_status_cb, band);
-}
-
-Return<void> WifiStaIface::startBackgroundScan(uint32_t cmd_id,
- const StaBackgroundScanParameters& params,
- startBackgroundScan_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::startBackgroundScanInternal, hidl_status_cb, cmd_id,
- params);
-}
-
-Return<void> WifiStaIface::stopBackgroundScan(uint32_t cmd_id,
- stopBackgroundScan_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::stopBackgroundScanInternal, hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiStaIface::enableLinkLayerStatsCollection(
- bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::enableLinkLayerStatsCollectionInternal, hidl_status_cb,
- debug);
-}
-
-Return<void> WifiStaIface::disableLinkLayerStatsCollection(
- disableLinkLayerStatsCollection_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::disableLinkLayerStatsCollectionInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getLinkLayerStatsInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getLinkLayerStats_1_3(getLinkLayerStats_1_3_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getLinkLayerStatsInternal_1_3, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getLinkLayerStats_1_5(getLinkLayerStats_1_5_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getLinkLayerStatsInternal_1_5, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getLinkLayerStats_1_6(getLinkLayerStats_1_6_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getLinkLayerStatsInternal_1_6, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::startRssiMonitoring(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
- startRssiMonitoring_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::startRssiMonitoringInternal, hidl_status_cb, cmd_id,
- max_rssi, min_rssi);
-}
-
-Return<void> WifiStaIface::stopRssiMonitoring(uint32_t cmd_id,
- stopRssiMonitoring_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::stopRssiMonitoringInternal, hidl_status_cb, cmd_id);
-}
-
-Return<void> WifiStaIface::getRoamingCapabilities(getRoamingCapabilities_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getRoamingCapabilitiesInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::configureRoaming(const StaRoamingConfig& config,
- configureRoaming_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::configureRoamingInternal, hidl_status_cb, config);
-}
-
-Return<void> WifiStaIface::setRoamingState(StaRoamingState state,
- setRoamingState_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::setRoamingStateInternal, hidl_status_cb, state);
-}
-
-Return<void> WifiStaIface::enableNdOffload(bool enable, enableNdOffload_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::enableNdOffloadInternal, hidl_status_cb, enable);
-}
-
-Return<void> WifiStaIface::startSendingKeepAlivePackets(
- uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data, uint16_t ether_type,
- const hidl_array<uint8_t, 6>& src_address, const hidl_array<uint8_t, 6>& dst_address,
- uint32_t period_in_ms, startSendingKeepAlivePackets_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::startSendingKeepAlivePacketsInternal, hidl_status_cb,
- cmd_id, ip_packet_data, ether_type, src_address, dst_address,
- period_in_ms);
-}
-
-Return<void> WifiStaIface::stopSendingKeepAlivePackets(
- uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::stopSendingKeepAlivePacketsInternal, hidl_status_cb,
- cmd_id);
-}
-
-Return<void> WifiStaIface::setScanningMacOui(const hidl_array<uint8_t, 3>& oui,
- setScanningMacOui_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::setScanningMacOuiInternal, hidl_status_cb, oui);
-}
-
-Return<void> WifiStaIface::startDebugPacketFateMonitoring(
- startDebugPacketFateMonitoring_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::startDebugPacketFateMonitoringInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getDebugTxPacketFates(getDebugTxPacketFates_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getDebugTxPacketFatesInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::getDebugRxPacketFates(getDebugRxPacketFates_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getDebugRxPacketFatesInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::setMacAddress(const hidl_array<uint8_t, 6>& mac,
- setMacAddress_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::setMacAddressInternal, hidl_status_cb, mac);
-}
-
-Return<void> WifiStaIface::getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::getFactoryMacAddressInternal, hidl_status_cb);
-}
-
-Return<void> WifiStaIface::setScanMode(bool enable, setScanMode_cb hidl_status_cb) {
- return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
- &WifiStaIface::setScanModeInternal, hidl_status_cb, enable);
-}
-
-std::pair<WifiStatus, std::string> WifiStaIface::getNameInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), ifname_};
-}
-
-std::pair<WifiStatus, IfaceType> WifiStaIface::getTypeInternal() {
- return {createWifiStatus(WifiStatusCode::SUCCESS), IfaceType::STA};
-}
-
-WifiStatus WifiStaIface::registerEventCallbackInternal(
- const sp<IWifiStaIfaceEventCallback>& callback) {
- if (!event_cb_handler_.addCallback(callback)) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, uint32_t> WifiStaIface::getCapabilitiesInternal() {
- legacy_hal::wifi_error legacy_status;
- uint64_t legacy_feature_set;
- std::tie(legacy_status, legacy_feature_set) =
- legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), 0};
- }
- uint32_t legacy_logger_feature_set;
- std::tie(legacy_status, legacy_logger_feature_set) =
- legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- // some devices don't support querying logger feature set
- legacy_logger_feature_set = 0;
- }
- uint32_t hidl_caps;
- if (!hidl_struct_util::convertLegacyFeaturesToHidlStaCapabilities(
- legacy_feature_set, legacy_logger_feature_set, &hidl_caps)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), 0};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, StaApfPacketFilterCapabilities>
-WifiStaIface::getApfPacketFilterCapabilitiesInternal() {
- legacy_hal::wifi_error legacy_status;
- legacy_hal::PacketFilterCapabilities legacy_caps;
- std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getPacketFilterCapabilities(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- StaApfPacketFilterCapabilities hidl_caps;
- if (!hidl_struct_util::convertLegacyApfCapabilitiesToHidl(legacy_caps, &hidl_caps)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-WifiStatus WifiStaIface::installApfPacketFilterInternal(uint32_t /* cmd_id */,
- const std::vector<uint8_t>& program) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setPacketFilter(ifname_, program);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, std::vector<uint8_t>> WifiStaIface::readApfPacketFilterDataInternal() {
- const std::pair<legacy_hal::wifi_error, std::vector<uint8_t>> legacy_status_and_data =
- legacy_hal_.lock()->readApfPacketFilterData(ifname_);
- return {createWifiStatusFromLegacyError(legacy_status_and_data.first),
- std::move(legacy_status_and_data.second)};
-}
-
-std::pair<WifiStatus, StaBackgroundScanCapabilities>
-WifiStaIface::getBackgroundScanCapabilitiesInternal() {
- legacy_hal::wifi_error legacy_status;
- legacy_hal::wifi_gscan_capabilities legacy_caps;
- std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getGscanCapabilities(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- StaBackgroundScanCapabilities hidl_caps;
- if (!hidl_struct_util::convertLegacyGscanCapabilitiesToHidl(legacy_caps, &hidl_caps)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-std::pair<WifiStatus, std::vector<WifiChannelInMhz>>
-WifiStaIface::getValidFrequenciesForBandInternal(V1_0::WifiBand band) {
- static_assert(sizeof(WifiChannelInMhz) == sizeof(uint32_t), "Size mismatch");
- legacy_hal::wifi_error legacy_status;
- std::vector<uint32_t> valid_frequencies;
- std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand(
- ifname_, hidl_struct_util::convertHidlWifiBandToLegacy(band));
- return {createWifiStatusFromLegacyError(legacy_status), valid_frequencies};
-}
-
-WifiStatus WifiStaIface::startBackgroundScanInternal(uint32_t cmd_id,
- const StaBackgroundScanParameters& params) {
- legacy_hal::wifi_scan_cmd_params legacy_params;
- if (!hidl_struct_util::convertHidlGscanParamsToLegacy(params, &legacy_params)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- android::wp<WifiStaIface> weak_ptr_this(this);
- const auto& on_failure_callback = [weak_ptr_this](legacy_hal::wifi_request_id id) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->onBackgroundScanFailure(id).isOk()) {
- LOG(ERROR) << "Failed to invoke onBackgroundScanFailure callback";
- }
- }
- };
- const auto& on_results_callback =
- [weak_ptr_this](legacy_hal::wifi_request_id id,
- const std::vector<legacy_hal::wifi_cached_scan_results>& results) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- std::vector<StaScanData> hidl_scan_datas;
- if (!hidl_struct_util::convertLegacyVectorOfCachedGscanResultsToHidl(
- results, &hidl_scan_datas)) {
- LOG(ERROR) << "Failed to convert scan results to HIDL structs";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->onBackgroundScanResults(id, hidl_scan_datas).isOk()) {
- LOG(ERROR) << "Failed to invoke onBackgroundScanResults callback";
- }
- }
- };
- const auto& on_full_result_callback = [weak_ptr_this](
- legacy_hal::wifi_request_id id,
- const legacy_hal::wifi_scan_result* result,
- uint32_t buckets_scanned) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- StaScanResult hidl_scan_result;
- if (!hidl_struct_util::convertLegacyGscanResultToHidl(*result, true, &hidl_scan_result)) {
- LOG(ERROR) << "Failed to convert full scan results to HIDL structs";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->onBackgroundFullScanResult(id, buckets_scanned, hidl_scan_result)
- .isOk()) {
- LOG(ERROR) << "Failed to invoke onBackgroundFullScanResult callback";
- }
- }
- };
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->startGscan(ifname_, cmd_id, legacy_params, on_failure_callback,
- on_results_callback, on_full_result_callback);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::stopBackgroundScanInternal(uint32_t cmd_id) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopGscan(ifname_, cmd_id);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableLinkLayerStats(ifname_, debug);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableLinkLayerStats(ifname_);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, V1_0::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal() {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-std::pair<WifiStatus, V1_3::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal_1_3() {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-std::pair<WifiStatus, V1_5::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal_1_5() {
- return {createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED), {}};
-}
-
-std::pair<WifiStatus, V1_6::StaLinkLayerStats> WifiStaIface::getLinkLayerStatsInternal_1_6() {
- legacy_hal::wifi_error legacy_status;
- legacy_hal::LinkLayerStats legacy_stats;
- std::tie(legacy_status, legacy_stats) = legacy_hal_.lock()->getLinkLayerStats(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- V1_6::StaLinkLayerStats hidl_stats;
- if (!hidl_struct_util::convertLegacyLinkLayerStatsToHidl(legacy_stats, &hidl_stats)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_stats};
-}
-
-WifiStatus WifiStaIface::startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi,
- int32_t min_rssi) {
- android::wp<WifiStaIface> weak_ptr_this(this);
- const auto& on_threshold_breached_callback = [weak_ptr_this](legacy_hal::wifi_request_id id,
- std::array<uint8_t, 6> bssid,
- int8_t rssi) {
- const auto shared_ptr_this = weak_ptr_this.promote();
- if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
- LOG(ERROR) << "Callback invoked on an invalid object";
- return;
- }
- for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
- if (!callback->onRssiThresholdBreached(id, bssid, rssi).isOk()) {
- LOG(ERROR) << "Failed to invoke onRssiThresholdBreached callback";
- }
- }
- };
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRssiMonitoring(
- ifname_, cmd_id, max_rssi, min_rssi, on_threshold_breached_callback);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::stopRssiMonitoringInternal(uint32_t cmd_id) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopRssiMonitoring(ifname_, cmd_id);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, StaRoamingCapabilities> WifiStaIface::getRoamingCapabilitiesInternal() {
- legacy_hal::wifi_error legacy_status;
- legacy_hal::wifi_roaming_capabilities legacy_caps;
- std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRoamingCapabilities(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- StaRoamingCapabilities hidl_caps;
- if (!hidl_struct_util::convertLegacyRoamingCapabilitiesToHidl(legacy_caps, &hidl_caps)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_caps};
-}
-
-WifiStatus WifiStaIface::configureRoamingInternal(const StaRoamingConfig& config) {
- legacy_hal::wifi_roaming_config legacy_config;
- if (!hidl_struct_util::convertHidlRoamingConfigToLegacy(config, &legacy_config)) {
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
- }
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->configureRoaming(ifname_, legacy_config);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableFirmwareRoaming(
- ifname_, hidl_struct_util::convertHidlRoamingStateToLegacy(state));
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::enableNdOffloadInternal(bool enable) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->configureNdOffload(ifname_, enable);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::startSendingKeepAlivePacketsInternal(
- uint32_t cmd_id, const std::vector<uint8_t>& ip_packet_data, uint16_t ether_type,
- const std::array<uint8_t, 6>& src_address, const std::array<uint8_t, 6>& dst_address,
- uint32_t period_in_ms) {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startSendingOffloadedPacket(
- ifname_, cmd_id, ether_type, ip_packet_data, src_address, dst_address, period_in_ms);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(uint32_t cmd_id) {
- legacy_hal::wifi_error legacy_status =
- legacy_hal_.lock()->stopSendingOffloadedPacket(ifname_, cmd_id);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-WifiStatus WifiStaIface::setScanningMacOuiInternal(const std::array<uint8_t, 3>& /* oui */) {
- // deprecated.
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-WifiStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
- legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startPktFateMonitoring(ifname_);
- return createWifiStatusFromLegacyError(legacy_status);
-}
-
-std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>>
-WifiStaIface::getDebugTxPacketFatesInternal() {
- legacy_hal::wifi_error legacy_status;
- std::vector<legacy_hal::wifi_tx_report> legacy_fates;
- std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getTxPktFates(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- std::vector<WifiDebugTxPacketFateReport> hidl_fates;
- if (!hidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToHidl(legacy_fates,
- &hidl_fates)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
-}
-
-std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>>
-WifiStaIface::getDebugRxPacketFatesInternal() {
- legacy_hal::wifi_error legacy_status;
- std::vector<legacy_hal::wifi_rx_report> legacy_fates;
- std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getRxPktFates(ifname_);
- if (legacy_status != legacy_hal::WIFI_SUCCESS) {
- return {createWifiStatusFromLegacyError(legacy_status), {}};
- }
- std::vector<WifiDebugRxPacketFateReport> hidl_fates;
- if (!hidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToHidl(legacy_fates,
- &hidl_fates)) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), {}};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), hidl_fates};
-}
-
-WifiStatus WifiStaIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) {
- bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
- if (!status) {
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
- }
- return createWifiStatus(WifiStatusCode::SUCCESS);
-}
-
-std::pair<WifiStatus, std::array<uint8_t, 6>> WifiStaIface::getFactoryMacAddressInternal() {
- std::array<uint8_t, 6> mac = iface_util_.lock()->getFactoryMacAddress(ifname_);
- if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) {
- return {createWifiStatus(WifiStatusCode::ERROR_UNKNOWN), mac};
- }
- return {createWifiStatus(WifiStatusCode::SUCCESS), mac};
-}
-
-WifiStatus WifiStaIface::setScanModeInternal(bool enable) {
- // OEM's need to implement this on their devices if needed.
- LOG(WARNING) << "setScanModeInternal(" << enable << ") not supported";
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
-}
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_sta_iface.h b/wifi/1.6/default/wifi_sta_iface.h
deleted file mode 100644
index c01c50b..0000000
--- a/wifi/1.6/default/wifi_sta_iface.h
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_STA_IFACE_H_
-#define WIFI_STA_IFACE_H_
-
-#include <android-base/macros.h>
-#include <android/hardware/wifi/1.0/IWifiStaIfaceEventCallback.h>
-#include <android/hardware/wifi/1.6/IWifiStaIface.h>
-
-#include "hidl_callback_util.h"
-#include "wifi_iface_util.h"
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-/**
- * HIDL interface object used to control a STA Iface instance.
- */
-class WifiStaIface : public V1_6::IWifiStaIface {
- public:
- WifiStaIface(const std::string& ifname,
- const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
- const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
- // Refer to |WifiChip::invalidate()|.
- void invalidate();
- bool isValid();
- std::set<sp<IWifiStaIfaceEventCallback>> getEventCallbacks();
- std::string getName();
-
- // HIDL methods exposed.
- Return<void> getName(getName_cb hidl_status_cb) override;
- Return<void> getType(getType_cb hidl_status_cb) override;
- Return<void> registerEventCallback(const sp<IWifiStaIfaceEventCallback>& callback,
- registerEventCallback_cb hidl_status_cb) override;
- Return<void> getCapabilities(getCapabilities_cb hidl_status_cb) override;
- Return<void> getApfPacketFilterCapabilities(
- getApfPacketFilterCapabilities_cb hidl_status_cb) override;
- Return<void> installApfPacketFilter(uint32_t cmd_id, const hidl_vec<uint8_t>& program,
- installApfPacketFilter_cb hidl_status_cb) override;
- Return<void> readApfPacketFilterData(readApfPacketFilterData_cb hidl_status_cb) override;
- Return<void> getBackgroundScanCapabilities(
- getBackgroundScanCapabilities_cb hidl_status_cb) override;
- Return<void> getValidFrequenciesForBand(V1_0::WifiBand band,
- getValidFrequenciesForBand_cb hidl_status_cb) override;
- Return<void> startBackgroundScan(uint32_t cmd_id, const StaBackgroundScanParameters& params,
- startBackgroundScan_cb hidl_status_cb) override;
- Return<void> stopBackgroundScan(uint32_t cmd_id, stopBackgroundScan_cb hidl_status_cb) override;
- Return<void> enableLinkLayerStatsCollection(
- bool debug, enableLinkLayerStatsCollection_cb hidl_status_cb) override;
- Return<void> disableLinkLayerStatsCollection(
- disableLinkLayerStatsCollection_cb hidl_status_cb) override;
- Return<void> getLinkLayerStats(getLinkLayerStats_cb hidl_status_cb) override;
- Return<void> getLinkLayerStats_1_3(getLinkLayerStats_1_3_cb hidl_status_cb) override;
- Return<void> getLinkLayerStats_1_5(getLinkLayerStats_1_5_cb hidl_status_cb) override;
- Return<void> getLinkLayerStats_1_6(getLinkLayerStats_1_6_cb hidl_status_cb) override;
- Return<void> startRssiMonitoring(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi,
- startRssiMonitoring_cb hidl_status_cb) override;
- Return<void> stopRssiMonitoring(uint32_t cmd_id, stopRssiMonitoring_cb hidl_status_cb) override;
- Return<void> getRoamingCapabilities(getRoamingCapabilities_cb hidl_status_cb) override;
- Return<void> configureRoaming(const StaRoamingConfig& config,
- configureRoaming_cb hidl_status_cb) override;
- Return<void> setRoamingState(StaRoamingState state, setRoamingState_cb hidl_status_cb) override;
- Return<void> enableNdOffload(bool enable, enableNdOffload_cb hidl_status_cb) override;
- Return<void> startSendingKeepAlivePackets(
- uint32_t cmd_id, const hidl_vec<uint8_t>& ip_packet_data, uint16_t ether_type,
- const hidl_array<uint8_t, 6>& src_address, const hidl_array<uint8_t, 6>& dst_address,
- uint32_t period_in_ms, startSendingKeepAlivePackets_cb hidl_status_cb) override;
- Return<void> stopSendingKeepAlivePackets(
- uint32_t cmd_id, stopSendingKeepAlivePackets_cb hidl_status_cb) override;
- Return<void> setScanningMacOui(const hidl_array<uint8_t, 3>& oui,
- setScanningMacOui_cb hidl_status_cb) override;
- Return<void> startDebugPacketFateMonitoring(
- startDebugPacketFateMonitoring_cb hidl_status_cb) override;
- Return<void> getDebugTxPacketFates(getDebugTxPacketFates_cb hidl_status_cb) override;
- Return<void> getDebugRxPacketFates(getDebugRxPacketFates_cb hidl_status_cb) override;
- Return<void> setMacAddress(const hidl_array<uint8_t, 6>& mac,
- setMacAddress_cb hidl_status_cb) override;
- Return<void> getFactoryMacAddress(getFactoryMacAddress_cb hidl_status_cb) override;
- Return<void> setScanMode(bool enable, setScanMode_cb hidl_status_cb) override;
-
- private:
- // Corresponding worker functions for the HIDL methods.
- std::pair<WifiStatus, std::string> getNameInternal();
- std::pair<WifiStatus, IfaceType> getTypeInternal();
- WifiStatus registerEventCallbackInternal(const sp<IWifiStaIfaceEventCallback>& callback);
- std::pair<WifiStatus, uint32_t> getCapabilitiesInternal();
- std::pair<WifiStatus, StaApfPacketFilterCapabilities> getApfPacketFilterCapabilitiesInternal();
- WifiStatus installApfPacketFilterInternal(uint32_t cmd_id, const std::vector<uint8_t>& program);
- std::pair<WifiStatus, std::vector<uint8_t>> readApfPacketFilterDataInternal();
- std::pair<WifiStatus, StaBackgroundScanCapabilities> getBackgroundScanCapabilitiesInternal();
- std::pair<WifiStatus, std::vector<WifiChannelInMhz>> getValidFrequenciesForBandInternal(
- V1_0::WifiBand band);
- WifiStatus startBackgroundScanInternal(uint32_t cmd_id,
- const StaBackgroundScanParameters& params);
- WifiStatus stopBackgroundScanInternal(uint32_t cmd_id);
- WifiStatus enableLinkLayerStatsCollectionInternal(bool debug);
- WifiStatus disableLinkLayerStatsCollectionInternal();
- std::pair<WifiStatus, V1_0::StaLinkLayerStats> getLinkLayerStatsInternal();
- std::pair<WifiStatus, V1_3::StaLinkLayerStats> getLinkLayerStatsInternal_1_3();
- std::pair<WifiStatus, V1_5::StaLinkLayerStats> getLinkLayerStatsInternal_1_5();
- std::pair<WifiStatus, V1_6::StaLinkLayerStats> getLinkLayerStatsInternal_1_6();
- WifiStatus startRssiMonitoringInternal(uint32_t cmd_id, int32_t max_rssi, int32_t min_rssi);
- WifiStatus stopRssiMonitoringInternal(uint32_t cmd_id);
- std::pair<WifiStatus, StaRoamingCapabilities> getRoamingCapabilitiesInternal();
- WifiStatus configureRoamingInternal(const StaRoamingConfig& config);
- WifiStatus setRoamingStateInternal(StaRoamingState state);
- WifiStatus enableNdOffloadInternal(bool enable);
- WifiStatus startSendingKeepAlivePacketsInternal(uint32_t cmd_id,
- const std::vector<uint8_t>& ip_packet_data,
- uint16_t ether_type,
- const std::array<uint8_t, 6>& src_address,
- const std::array<uint8_t, 6>& dst_address,
- uint32_t period_in_ms);
- WifiStatus stopSendingKeepAlivePacketsInternal(uint32_t cmd_id);
- WifiStatus setScanningMacOuiInternal(const std::array<uint8_t, 3>& oui);
- WifiStatus startDebugPacketFateMonitoringInternal();
- std::pair<WifiStatus, std::vector<WifiDebugTxPacketFateReport>> getDebugTxPacketFatesInternal();
- std::pair<WifiStatus, std::vector<WifiDebugRxPacketFateReport>> getDebugRxPacketFatesInternal();
- WifiStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
- std::pair<WifiStatus, std::array<uint8_t, 6>> getFactoryMacAddressInternal();
- WifiStatus setScanModeInternal(bool enable);
-
- std::string ifname_;
- std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
- std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
- bool is_valid_;
- hidl_callback_util::HidlCallbackHandler<IWifiStaIfaceEventCallback> event_cb_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(WifiStaIface);
-};
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_STA_IFACE_H_
diff --git a/wifi/1.6/default/wifi_status_util.cpp b/wifi/1.6/default/wifi_status_util.cpp
deleted file mode 100644
index 3b18e53..0000000
--- a/wifi/1.6/default/wifi_status_util.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "wifi_status_util.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-
-std::string legacyErrorToString(legacy_hal::wifi_error error) {
- switch (error) {
- case legacy_hal::WIFI_SUCCESS:
- return "SUCCESS";
- case legacy_hal::WIFI_ERROR_UNINITIALIZED:
- return "UNINITIALIZED";
- case legacy_hal::WIFI_ERROR_NOT_AVAILABLE:
- return "NOT_AVAILABLE";
- case legacy_hal::WIFI_ERROR_NOT_SUPPORTED:
- return "NOT_SUPPORTED";
- case legacy_hal::WIFI_ERROR_INVALID_ARGS:
- return "INVALID_ARGS";
- case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID:
- return "INVALID_REQUEST_ID";
- case legacy_hal::WIFI_ERROR_TIMED_OUT:
- return "TIMED_OUT";
- case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS:
- return "TOO_MANY_REQUESTS";
- case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY:
- return "OUT_OF_MEMORY";
- case legacy_hal::WIFI_ERROR_BUSY:
- return "BUSY";
- case legacy_hal::WIFI_ERROR_UNKNOWN:
- return "UNKNOWN";
- default:
- return "UNKNOWN ERROR";
- }
-}
-
-WifiStatus createWifiStatus(WifiStatusCode code, const std::string& description) {
- return {code, description};
-}
-
-WifiStatus createWifiStatus(WifiStatusCode code) {
- return createWifiStatus(code, "");
-}
-
-WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error, const std::string& desc) {
- switch (error) {
- case legacy_hal::WIFI_ERROR_UNINITIALIZED:
- case legacy_hal::WIFI_ERROR_NOT_AVAILABLE:
- return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, desc);
-
- case legacy_hal::WIFI_ERROR_NOT_SUPPORTED:
- return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED, desc);
-
- case legacy_hal::WIFI_ERROR_INVALID_ARGS:
- case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID:
- return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS, desc);
-
- case legacy_hal::WIFI_ERROR_TIMED_OUT:
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", timed out");
-
- case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS:
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", too many requests");
-
- case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY:
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", out of memory");
-
- case legacy_hal::WIFI_ERROR_BUSY:
- return createWifiStatus(WifiStatusCode::ERROR_BUSY);
-
- case legacy_hal::WIFI_ERROR_NONE:
- return createWifiStatus(WifiStatusCode::SUCCESS, desc);
-
- case legacy_hal::WIFI_ERROR_UNKNOWN:
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown");
-
- default:
- return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown error");
- }
-}
-
-WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) {
- return createWifiStatusFromLegacyError(error, "");
-}
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
diff --git a/wifi/1.6/default/wifi_status_util.h b/wifi/1.6/default/wifi_status_util.h
deleted file mode 100644
index ea1c294..0000000
--- a/wifi/1.6/default/wifi_status_util.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef WIFI_STATUS_UTIL_H_
-#define WIFI_STATUS_UTIL_H_
-
-#include <android/hardware/wifi/1.4/IWifi.h>
-
-#include "wifi_legacy_hal.h"
-
-namespace android {
-namespace hardware {
-namespace wifi {
-namespace V1_6 {
-namespace implementation {
-using namespace android::hardware::wifi::V1_0;
-
-std::string legacyErrorToString(legacy_hal::wifi_error error);
-WifiStatus createWifiStatus(WifiStatusCode code, const std::string& description);
-WifiStatus createWifiStatus(WifiStatusCode code);
-WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error,
- const std::string& description);
-WifiStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error);
-
-} // namespace implementation
-} // namespace V1_6
-} // namespace wifi
-} // namespace hardware
-} // namespace android
-
-#endif // WIFI_STATUS_UTIL_H_
diff --git a/wifi/1.6/vts/OWNERS b/wifi/1.6/vts/OWNERS
deleted file mode 100644
index 294fc82..0000000
--- a/wifi/1.6/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.0/vts/OWNERS
diff --git a/wifi/OWNERS b/wifi/OWNERS
new file mode 100644
index 0000000..c10bbab
--- /dev/null
+++ b/wifi/OWNERS
@@ -0,0 +1,10 @@
+# Bug component: 33618
+
+# Please assign all bugs related to /hardware/interfaces/wifi to the team alias:
+#
+# android-wifi-team@google.com
+#
+# This will get them auto-assigned to the on-call triage engineer, ensuring quickest response.
+#
+arabawy@google.com
+etancohen@google.com
diff --git a/wifi/aidl/default/Android.bp b/wifi/aidl/default/Android.bp
new file mode 100644
index 0000000..441d461
--- /dev/null
+++ b/wifi/aidl/default/Android.bp
@@ -0,0 +1,214 @@
+// 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"],
+}
+
+soong_config_module_type {
+ name: "wifi_hal_cc_defaults",
+ module_type: "cc_defaults",
+ config_namespace: "wifi",
+ bool_variables: [
+ "hidl_feature_aware", // WIFI_HIDL_FEATURE_AWARE
+ "hidl_feature_dual_interface", // WIFI_HIDL_FEATURE_DUAL_INTERFACE
+ "hidl_feature_disable_ap", // WIFI_HIDL_FEATURE_DISABLE_AP
+ "hidl_feature_disable_ap_mac_randomization", // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
+ "avoid_iface_reset_mac_change", // WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+ ],
+ value_variables: [
+ "hal_interface_combinations", // WIFI_HAL_INTERFACE_COMBINATIONS
+ ],
+ properties: [
+ "cppflags",
+ ],
+}
+
+wifi_hal_cc_defaults {
+ name: "android.hardware.wifi-service-cppflags-defaults",
+ soong_config_variables: {
+ hidl_feature_aware: {
+ cppflags: ["-DWIFI_HIDL_FEATURE_AWARE"],
+ },
+ hidl_feature_dual_interface: {
+ cppflags: ["-DWIFI_HIDL_FEATURE_DUAL_INTERFACE"],
+ },
+ hidl_feature_disable_ap: {
+ cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP"],
+ },
+ hidl_feature_disable_ap_mac_randomization: {
+ cppflags: ["-DWIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION"],
+ },
+ avoid_iface_reset_mac_change: {
+ cppflags: ["-DWIFI_AVOID_IFACE_RESET_MAC_CHANGE"],
+ },
+ hal_interface_combinations: {
+ cppflags: ["-DWIFI_HAL_INTERFACE_COMBINATIONS=%s"],
+ },
+ },
+}
+
+cc_library_static {
+ name: "android.hardware.wifi-service-lib",
+ defaults: ["android.hardware.wifi-service-cppflags-defaults"],
+ proprietary: true,
+ compile_multilib: "first",
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ // Allow implicit fallthroughs in wifi_legacy_hal.cpp until they are fixed.
+ cflags: ["-Wno-error=implicit-fallthrough"],
+ srcs: [
+ "aidl_struct_util.cpp",
+ "aidl_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",
+ ],
+
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libnl",
+ "libutils",
+ "libwifi-hal",
+ "libwifi-system-iface",
+ "libxml2",
+ "android.hardware.wifi-V1-ndk",
+ ],
+
+ export_include_dirs: ["."],
+}
+
+cc_binary {
+ name: "android.hardware.wifi-service",
+ vintf_fragments: ["android.hardware.wifi-service.xml"],
+ relative_install_path: "hw",
+ proprietary: true,
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ srcs: ["service.cpp"],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libnl",
+ "libutils",
+ "libwifi-hal",
+ "libwifi-system-iface",
+ "libxml2",
+ "android.hardware.wifi-V1-ndk",
+ ],
+ static_libs: ["android.hardware.wifi-service-lib"],
+ init_rc: ["android.hardware.wifi-service.rc"],
+}
+
+cc_binary {
+ name: "android.hardware.wifi-service-lazy",
+ vintf_fragments: ["android.hardware.wifi-service.xml"],
+ overrides: ["android.hardware.wifi-service"],
+ cflags: ["-DLAZY_SERVICE"],
+ relative_install_path: "hw",
+ proprietary: true,
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ srcs: ["service.cpp"],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libnl",
+ "libutils",
+ "libwifi-hal",
+ "libwifi-system-iface",
+ "libxml2",
+ "android.hardware.wifi-V1-ndk",
+ ],
+ static_libs: ["android.hardware.wifi-service-lib"],
+ init_rc: ["android.hardware.wifi-service-lazy.rc"],
+}
+
+cc_test {
+ name: "android.hardware.wifi-service-tests",
+ proprietary: true,
+ compile_multilib: "first",
+ cppflags: [
+ "-Wall",
+ "-Werror",
+ "-Wextra",
+ ],
+ srcs: [
+ "tests/aidl_struct_util_unit_tests.cpp",
+ "tests/main.cpp",
+ "tests/mock_interface_tool.cpp",
+ "tests/mock_wifi_feature_flags.cpp",
+ "tests/mock_wifi_iface_util.cpp",
+ "tests/mock_wifi_legacy_hal.cpp",
+ "tests/mock_wifi_mode_controller.cpp",
+ "tests/ringbuffer_unit_tests.cpp",
+ "tests/wifi_nan_iface_unit_tests.cpp",
+ "tests/wifi_chip_unit_tests.cpp",
+ "tests/wifi_iface_util_unit_tests.cpp",
+ ],
+ static_libs: [
+ "libgmock",
+ "libgtest",
+ "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi-service-lib",
+ ],
+ shared_libs: [
+ "libbase",
+ "libbinder_ndk",
+ "libcutils",
+ "liblog",
+ "libnl",
+ "libutils",
+ "libwifi-hal",
+ "libwifi-system-iface",
+ ],
+}
+
+filegroup {
+ name: "default-android.hardware.wifi-service.rc",
+ srcs: ["android.hardware.wifi-service.rc"],
+}
+
+filegroup {
+ name: "default-android.hardware.wifi-service.xml",
+ srcs: ["android.hardware.wifi-service.xml"],
+}
diff --git a/wifi/aidl/default/THREADING.README b/wifi/aidl/default/THREADING.README
new file mode 100644
index 0000000..45679da
--- /dev/null
+++ b/wifi/aidl/default/THREADING.README
@@ -0,0 +1,35 @@
+Vendor HAL Threading Model
+==========================
+The vendor HAL service has two threads:
+1. AIDL thread: This is the main thread which processes all the incoming AIDL
+RPC's.
+2. Legacy HAL event loop thread: This is the thread forked off for processing
+the legacy HAL event loop (wifi_event_loop()). This thread is used to process
+any asynchronous netlink events posted by the driver. Any asynchronous
+callbacks passed to the legacy HAL API's are invoked on this thread.
+
+Synchronization Concerns
+========================
+wifi_legacy_hal.cpp has a bunch of global "C" style functions to handle the
+legacy callbacks. Each of these "C" style functions invokes a corresponding
+"std::function" version of the callback which does the actual processing.
+The variables holding these "std::function" callbacks are reset from the AIDL
+thread when they are no longer used. For example: stopGscan() will reset the
+corresponding "on_gscan_*" callback variables which were set when startGscan()
+was invoked. This is not thread safe since these callback variables are
+accesed from the legacy hal event loop thread as well.
+
+Synchronization Solution
+========================
+Adding a global lock seems to be the most trivial solution to the problem.
+a) All of the asynchronous "C" style callbacks will acquire the global lock
+before invoking the corresponding "std::function" callback variables.
+b) All of the AIDL methods will also acquire the global lock before processing
+(in aidl_return_util::validateAndCall()).
+
+Note: It's important that we only acquire the global lock for asynchronous
+callbacks, because there is no guarantee (or documentation to clarify) that the
+synchronous callbacks are invoked on the same invocation thread. If that is not
+the case in some implementation, we will end up deadlocking the system since the
+AIDL thread would have acquired the global lock which is needed by the
+synchronous callback executed on the legacy hal event loop thread.
diff --git a/wifi/aidl/default/aidl_callback_util.h b/wifi/aidl/default/aidl_callback_util.h
new file mode 100644
index 0000000..41d70a5
--- /dev/null
+++ b/wifi/aidl/default/aidl_callback_util.h
@@ -0,0 +1,140 @@
+/*
+ * 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 AIDL_CALLBACK_UTIL_H_
+#define AIDL_CALLBACK_UTIL_H_
+
+#include <android-base/logging.h>
+
+#include <set>
+#include <unordered_map>
+
+namespace {
+std::unordered_map<void* /* callback */, void* /* handler */> callback_handler_map_;
+}
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace aidl_callback_util {
+
+// Provides a class to manage callbacks for the various AIDL interfaces and
+// handle the death of the process hosting each callback.
+template <typename CallbackType>
+class AidlCallbackHandler {
+ public:
+ AidlCallbackHandler() {
+ death_handler_ = AIBinder_DeathRecipient_new(AidlCallbackHandler::onCallbackDeath);
+ }
+ ~AidlCallbackHandler() { invalidate(); }
+
+ bool addCallback(const std::shared_ptr<CallbackType>& cb) {
+ void* cbPtr = reinterpret_cast<void*>(cb->asBinder().get());
+ const auto& cbPosition = findCbInSet(cbPtr);
+ if (cbPosition != cb_set_.end()) {
+ LOG(WARNING) << "Duplicate death notification registration";
+ return true;
+ }
+
+ if (AIBinder_linkToDeath(cb->asBinder().get(), death_handler_, cbPtr /* cookie */) !=
+ STATUS_OK) {
+ LOG(ERROR) << "Failed to register death notification";
+ return false;
+ }
+
+ callback_handler_map_[cbPtr] = reinterpret_cast<void*>(this);
+ cb_set_.insert(cb);
+ return true;
+ }
+
+ const std::set<std::shared_ptr<CallbackType>>& getCallbacks() { return cb_set_; }
+
+ void invalidate() {
+ for (auto cb : cb_set_) {
+ void* cookie = reinterpret_cast<void*>(cb->asBinder().get());
+ if (AIBinder_unlinkToDeath(cb->asBinder().get(), death_handler_, cookie) != STATUS_OK) {
+ LOG(ERROR) << "Failed to deregister death notification";
+ }
+ if (!removeCbFromHandlerMap(cookie)) {
+ LOG(ERROR) << "Failed to remove callback from handler map";
+ }
+ }
+ cb_set_.clear();
+ }
+
+ // Entry point for the death handling logic. AIBinder_DeathRecipient
+ // can only call a static function, so use the cookie to find the
+ // proper handler and route the request there.
+ static void onCallbackDeath(void* cookie) {
+ auto cbQuery = callback_handler_map_.find(cookie);
+ if (cbQuery == callback_handler_map_.end()) {
+ LOG(ERROR) << "Invalid death cookie received";
+ return;
+ }
+
+ AidlCallbackHandler* cbHandler = reinterpret_cast<AidlCallbackHandler*>(cbQuery->second);
+ if (cbHandler == nullptr) {
+ LOG(ERROR) << "Handler mapping contained an invalid handler";
+ return;
+ }
+ cbHandler->handleCallbackDeath(cbQuery->first);
+ }
+
+ private:
+ std::set<std::shared_ptr<CallbackType>> cb_set_;
+ AIBinder_DeathRecipient* death_handler_;
+
+ typename std::set<std::shared_ptr<CallbackType>>::iterator findCbInSet(void* cbPtr) {
+ const auto& cbPosition = std::find_if(
+ cb_set_.begin(), cb_set_.end(), [cbPtr](const std::shared_ptr<CallbackType>& p) {
+ return cbPtr == reinterpret_cast<void*>(p->asBinder().get());
+ });
+ return cbPosition;
+ }
+
+ bool removeCbFromHandlerMap(void* cbPtr) {
+ auto cbQuery = callback_handler_map_.find(cbPtr);
+ if (cbQuery != callback_handler_map_.end()) {
+ callback_handler_map_.erase(cbQuery);
+ return true;
+ }
+ return false;
+ }
+
+ void handleCallbackDeath(void* cbPtr) {
+ const auto& cbPosition = findCbInSet(cbPtr);
+ if (cbPosition == cb_set_.end()) {
+ LOG(ERROR) << "Unknown callback death notification received";
+ return;
+ }
+ cb_set_.erase(cbPosition);
+
+ if (!removeCbFromHandlerMap(cbPtr)) {
+ LOG(ERROR) << "Callback was not in callback handler map";
+ }
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(AidlCallbackHandler);
+};
+
+} // namespace aidl_callback_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // AIDL_CALLBACK_UTIL_H_
diff --git a/wifi/aidl/default/aidl_return_util.h b/wifi/aidl/default/aidl_return_util.h
new file mode 100644
index 0000000..9a49a22
--- /dev/null
+++ b/wifi/aidl/default/aidl_return_util.h
@@ -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.
+ */
+
+#ifndef AIDL_RETURN_UTIL_H_
+#define AIDL_RETURN_UTIL_H_
+
+#include "aidl_sync_util.h"
+#include "wifi_status_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace aidl_return_util {
+using aidl::android::hardware::wifi::WifiStatusCode;
+using aidl::android::hardware::wifi::aidl_sync_util::acquireGlobalLock;
+
+/**
+ * These utility functions are used to invoke a method on the provided
+ * AIDL interface object.
+ * These functions checks if the provided AIDL interface object is valid.
+ * a) If valid, Invokes the corresponding internal implementation function of
+ * the AIDL method.
+ * b) If invalid, return without calling the internal implementation function.
+ */
+
+// Use for AIDL methods which return only an AIDL status.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+::ndk::ScopedAStatus validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid,
+ WorkFuncT&& work, Args&&... args) {
+ const auto lock = acquireGlobalLock();
+ if (obj->isValid()) {
+ return (obj->*work)(std::forward<Args>(args)...);
+ } else {
+ return createWifiStatus(status_code_if_invalid);
+ }
+}
+
+// Use for AIDL methods which return only an AIDL status.
+// This version passes the global lock acquired to the body of the method.
+template <typename ObjT, typename WorkFuncT, typename... Args>
+::ndk::ScopedAStatus validateAndCallWithLock(ObjT* obj, WifiStatusCode status_code_if_invalid,
+ WorkFuncT&& work, Args&&... args) {
+ auto lock = acquireGlobalLock();
+ if (obj->isValid()) {
+ return (obj->*work)(&lock, std::forward<Args>(args)...);
+ } else {
+ return createWifiStatus(status_code_if_invalid);
+ }
+}
+
+// Use for AIDL methods which have a return value along with the AIDL status
+template <typename ObjT, typename WorkFuncT, typename ReturnT, typename... Args>
+::ndk::ScopedAStatus validateAndCall(ObjT* obj, WifiStatusCode status_code_if_invalid,
+ WorkFuncT&& work, ReturnT* ret_val, Args&&... args) {
+ const auto lock = acquireGlobalLock();
+ if (obj->isValid()) {
+ auto call_pair = (obj->*work)(std::forward<Args>(args)...);
+ *ret_val = call_pair.first;
+ return std::forward<::ndk::ScopedAStatus>(call_pair.second);
+ } else {
+ return ndk::ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(status_code_if_invalid));
+ }
+}
+
+} // namespace aidl_return_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+#endif // AIDL_RETURN_UTIL_H_
diff --git a/wifi/aidl/default/aidl_struct_util.cpp b/wifi/aidl/default/aidl_struct_util.cpp
new file mode 100644
index 0000000..07612b6
--- /dev/null
+++ b/wifi/aidl/default/aidl_struct_util.cpp
@@ -0,0 +1,2775 @@
+/*
+ * 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-base/logging.h>
+#include <utils/SystemClock.h>
+
+#include "aidl_struct_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace aidl_struct_util {
+
+WifiChannelWidthInMhz convertLegacyWifiChannelWidthToAidl(legacy_hal::wifi_channel_width type);
+
+std::string safeConvertChar(const char* str, size_t max_len) {
+ const char* c = str;
+ size_t size = 0;
+ while (*c && (unsigned char)*c < 128 && size < max_len) {
+ ++size;
+ ++c;
+ }
+ return std::string(str, size);
+}
+
+inline std::vector<int32_t> uintToIntVec(const std::vector<uint32_t>& in) {
+ return std::vector<int32_t>(in.begin(), in.end());
+}
+
+IWifiChip::ChipCapabilityMask convertLegacyLoggerFeatureToAidlChipCapability(uint32_t feature) {
+ switch (feature) {
+ case legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED:
+ return IWifiChip::ChipCapabilityMask::DEBUG_MEMORY_FIRMWARE_DUMP;
+ case legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED:
+ return IWifiChip::ChipCapabilityMask::DEBUG_MEMORY_DRIVER_DUMP;
+ case legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED:
+ return IWifiChip::ChipCapabilityMask::DEBUG_RING_BUFFER_CONNECT_EVENT;
+ case legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED:
+ return IWifiChip::ChipCapabilityMask::DEBUG_RING_BUFFER_POWER_EVENT;
+ case legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED:
+ return IWifiChip::ChipCapabilityMask::DEBUG_RING_BUFFER_WAKELOCK_EVENT;
+ };
+ CHECK(false) << "Unknown legacy feature: " << feature;
+ return {};
+}
+
+IWifiStaIface::StaIfaceCapabilityMask convertLegacyLoggerFeatureToAidlStaIfaceCapability(
+ uint32_t feature) {
+ switch (feature) {
+ case legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED:
+ return IWifiStaIface::StaIfaceCapabilityMask::DEBUG_PACKET_FATE;
+ };
+ CHECK(false) << "Unknown legacy feature: " << feature;
+ return {};
+}
+
+IWifiChip::ChipCapabilityMask convertLegacyFeatureToAidlChipCapability(uint64_t feature) {
+ switch (feature) {
+ case WIFI_FEATURE_SET_TX_POWER_LIMIT:
+ return IWifiChip::ChipCapabilityMask::SET_TX_POWER_LIMIT;
+ case WIFI_FEATURE_USE_BODY_HEAD_SAR:
+ return IWifiChip::ChipCapabilityMask::USE_BODY_HEAD_SAR;
+ case WIFI_FEATURE_D2D_RTT:
+ return IWifiChip::ChipCapabilityMask::D2D_RTT;
+ case WIFI_FEATURE_D2AP_RTT:
+ return IWifiChip::ChipCapabilityMask::D2AP_RTT;
+ case WIFI_FEATURE_INFRA_60G:
+ return IWifiChip::ChipCapabilityMask::WIGIG;
+ case WIFI_FEATURE_SET_LATENCY_MODE:
+ return IWifiChip::ChipCapabilityMask::SET_LATENCY_MODE;
+ case WIFI_FEATURE_P2P_RAND_MAC:
+ return IWifiChip::ChipCapabilityMask::P2P_RAND_MAC;
+ };
+ CHECK(false) << "Unknown legacy feature: " << feature;
+ return {};
+}
+
+IWifiStaIface::StaIfaceCapabilityMask convertLegacyFeatureToAidlStaIfaceCapability(
+ uint64_t feature) {
+ switch (feature) {
+ case WIFI_FEATURE_GSCAN:
+ return IWifiStaIface::StaIfaceCapabilityMask::BACKGROUND_SCAN;
+ case WIFI_FEATURE_LINK_LAYER_STATS:
+ return IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS;
+ case WIFI_FEATURE_RSSI_MONITOR:
+ return IWifiStaIface::StaIfaceCapabilityMask::RSSI_MONITOR;
+ case WIFI_FEATURE_CONTROL_ROAMING:
+ return IWifiStaIface::StaIfaceCapabilityMask::CONTROL_ROAMING;
+ case WIFI_FEATURE_IE_WHITELIST:
+ return IWifiStaIface::StaIfaceCapabilityMask::PROBE_IE_ALLOWLIST;
+ case WIFI_FEATURE_SCAN_RAND:
+ return IWifiStaIface::StaIfaceCapabilityMask::SCAN_RAND;
+ case WIFI_FEATURE_INFRA_5G:
+ return IWifiStaIface::StaIfaceCapabilityMask::STA_5G;
+ case WIFI_FEATURE_HOTSPOT:
+ return IWifiStaIface::StaIfaceCapabilityMask::HOTSPOT;
+ case WIFI_FEATURE_PNO:
+ return IWifiStaIface::StaIfaceCapabilityMask::PNO;
+ case WIFI_FEATURE_TDLS:
+ return IWifiStaIface::StaIfaceCapabilityMask::TDLS;
+ case WIFI_FEATURE_TDLS_OFFCHANNEL:
+ return IWifiStaIface::StaIfaceCapabilityMask::TDLS_OFFCHANNEL;
+ case WIFI_FEATURE_CONFIG_NDO:
+ return IWifiStaIface::StaIfaceCapabilityMask::ND_OFFLOAD;
+ case WIFI_FEATURE_MKEEP_ALIVE:
+ return IWifiStaIface::StaIfaceCapabilityMask::KEEP_ALIVE;
+ };
+ CHECK(false) << "Unknown legacy feature: " << feature;
+ return {};
+}
+
+bool convertLegacyFeaturesToAidlChipCapabilities(uint64_t legacy_feature_set,
+ uint32_t legacy_logger_feature_set,
+ uint32_t* aidl_caps) {
+ if (!aidl_caps) {
+ return false;
+ }
+ *aidl_caps = {};
+ for (const auto feature : {legacy_hal::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED,
+ legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED,
+ legacy_hal::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED,
+ legacy_hal::WIFI_LOGGER_POWER_EVENT_SUPPORTED,
+ legacy_hal::WIFI_LOGGER_WAKE_LOCK_SUPPORTED}) {
+ if (feature & legacy_logger_feature_set) {
+ *aidl_caps |=
+ static_cast<uint32_t>(convertLegacyLoggerFeatureToAidlChipCapability(feature));
+ }
+ }
+ std::vector<uint64_t> features = {WIFI_FEATURE_SET_TX_POWER_LIMIT,
+ WIFI_FEATURE_USE_BODY_HEAD_SAR,
+ WIFI_FEATURE_D2D_RTT,
+ WIFI_FEATURE_D2AP_RTT,
+ WIFI_FEATURE_INFRA_60G,
+ WIFI_FEATURE_SET_LATENCY_MODE,
+ WIFI_FEATURE_P2P_RAND_MAC};
+ for (const auto feature : features) {
+ if (feature & legacy_feature_set) {
+ *aidl_caps |= static_cast<uint32_t>(convertLegacyFeatureToAidlChipCapability(feature));
+ }
+ }
+
+ // There are no flags for these 3 in the legacy feature set. Adding them to
+ // the set because all the current devices support it.
+ *aidl_caps |=
+ static_cast<uint32_t>(IWifiChip::ChipCapabilityMask::DEBUG_RING_BUFFER_VENDOR_DATA);
+ *aidl_caps |=
+ static_cast<uint32_t>(IWifiChip::ChipCapabilityMask::DEBUG_HOST_WAKE_REASON_STATS);
+ *aidl_caps |= static_cast<uint32_t>(IWifiChip::ChipCapabilityMask::DEBUG_ERROR_ALERTS);
+ return true;
+}
+
+WifiDebugRingBufferFlags convertLegacyDebugRingBufferFlagsToAidl(uint32_t flag) {
+ switch (flag) {
+ case WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES:
+ return WifiDebugRingBufferFlags::HAS_BINARY_ENTRIES;
+ case WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES:
+ return WifiDebugRingBufferFlags::HAS_ASCII_ENTRIES;
+ };
+ CHECK(false) << "Unknown legacy flag: " << flag;
+ return {};
+}
+
+bool convertLegacyDebugRingBufferStatusToAidl(
+ const legacy_hal::wifi_ring_buffer_status& legacy_status,
+ WifiDebugRingBufferStatus* aidl_status) {
+ if (!aidl_status) {
+ return false;
+ }
+ *aidl_status = {};
+ aidl_status->ringName = safeConvertChar(reinterpret_cast<const char*>(legacy_status.name),
+ sizeof(legacy_status.name));
+ aidl_status->flags = 0;
+ for (const auto flag :
+ {WIFI_RING_BUFFER_FLAG_HAS_BINARY_ENTRIES, WIFI_RING_BUFFER_FLAG_HAS_ASCII_ENTRIES}) {
+ if (flag & legacy_status.flags) {
+ aidl_status->flags |= static_cast<std::underlying_type<WifiDebugRingBufferFlags>::type>(
+ convertLegacyDebugRingBufferFlagsToAidl(flag));
+ }
+ }
+ aidl_status->ringId = legacy_status.ring_id;
+ aidl_status->sizeInBytes = legacy_status.ring_buffer_byte_size;
+ // Calculate free size of the ring the buffer. We don't need to send the
+ // exact read/write pointers that were there in the legacy HAL interface.
+ if (legacy_status.written_bytes >= legacy_status.read_bytes) {
+ aidl_status->freeSizeInBytes = legacy_status.ring_buffer_byte_size -
+ (legacy_status.written_bytes - legacy_status.read_bytes);
+ } else {
+ aidl_status->freeSizeInBytes = legacy_status.read_bytes - legacy_status.written_bytes;
+ }
+ aidl_status->verboseLevel = legacy_status.verbose_level;
+ return true;
+}
+
+bool convertLegacyVectorOfDebugRingBufferStatusToAidl(
+ const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
+ std::vector<WifiDebugRingBufferStatus>* aidl_status_vec) {
+ if (!aidl_status_vec) {
+ return false;
+ }
+ *aidl_status_vec = {};
+ for (const auto& legacy_status : legacy_status_vec) {
+ WifiDebugRingBufferStatus aidl_status;
+ if (!convertLegacyDebugRingBufferStatusToAidl(legacy_status, &aidl_status)) {
+ return false;
+ }
+ aidl_status_vec->push_back(aidl_status);
+ }
+ return true;
+}
+
+bool convertLegacyWakeReasonStatsToAidl(const legacy_hal::WakeReasonStats& legacy_stats,
+ WifiDebugHostWakeReasonStats* aidl_stats) {
+ if (!aidl_stats) {
+ return false;
+ }
+ *aidl_stats = {};
+ aidl_stats->totalCmdEventWakeCnt = legacy_stats.wake_reason_cnt.total_cmd_event_wake;
+ aidl_stats->cmdEventWakeCntPerType = uintToIntVec(legacy_stats.cmd_event_wake_cnt);
+ aidl_stats->totalDriverFwLocalWakeCnt = legacy_stats.wake_reason_cnt.total_driver_fw_local_wake;
+ aidl_stats->driverFwLocalWakeCntPerType = uintToIntVec(legacy_stats.driver_fw_local_wake_cnt);
+ aidl_stats->totalRxPacketWakeCnt = legacy_stats.wake_reason_cnt.total_rx_data_wake;
+ aidl_stats->rxPktWakeDetails.rxUnicastCnt =
+ legacy_stats.wake_reason_cnt.rx_wake_details.rx_unicast_cnt;
+ aidl_stats->rxPktWakeDetails.rxMulticastCnt =
+ legacy_stats.wake_reason_cnt.rx_wake_details.rx_multicast_cnt;
+ aidl_stats->rxPktWakeDetails.rxBroadcastCnt =
+ legacy_stats.wake_reason_cnt.rx_wake_details.rx_broadcast_cnt;
+ aidl_stats->rxMulticastPkWakeDetails.ipv4RxMulticastAddrCnt =
+ legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.ipv4_rx_multicast_addr_cnt;
+ aidl_stats->rxMulticastPkWakeDetails.ipv6RxMulticastAddrCnt =
+ legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.ipv6_rx_multicast_addr_cnt;
+ aidl_stats->rxMulticastPkWakeDetails.otherRxMulticastAddrCnt =
+ legacy_stats.wake_reason_cnt.rx_multicast_wake_pkt_info.other_rx_multicast_addr_cnt;
+ aidl_stats->rxIcmpPkWakeDetails.icmpPkt =
+ legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp_pkt;
+ aidl_stats->rxIcmpPkWakeDetails.icmp6Pkt =
+ legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_pkt;
+ aidl_stats->rxIcmpPkWakeDetails.icmp6Ra =
+ legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ra;
+ aidl_stats->rxIcmpPkWakeDetails.icmp6Na =
+ legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_na;
+ aidl_stats->rxIcmpPkWakeDetails.icmp6Ns =
+ legacy_stats.wake_reason_cnt.rx_wake_pkt_classification_info.icmp6_ns;
+ return true;
+}
+
+legacy_hal::wifi_power_scenario convertAidlTxPowerScenarioToLegacy(
+ IWifiChip::TxPowerScenario aidl_scenario) {
+ switch (aidl_scenario) {
+ case IWifiChip::TxPowerScenario::VOICE_CALL:
+ return legacy_hal::WIFI_POWER_SCENARIO_VOICE_CALL;
+ case IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF:
+ return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF;
+ case IWifiChip::TxPowerScenario::ON_HEAD_CELL_ON:
+ return legacy_hal::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON;
+ case IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF:
+ return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF;
+ case IWifiChip::TxPowerScenario::ON_BODY_CELL_ON:
+ return legacy_hal::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON;
+ };
+ CHECK(false);
+}
+
+legacy_hal::wifi_latency_mode convertAidlLatencyModeToLegacy(
+ IWifiChip::LatencyMode aidl_latency_mode) {
+ switch (aidl_latency_mode) {
+ case IWifiChip::LatencyMode::NORMAL:
+ return legacy_hal::WIFI_LATENCY_MODE_NORMAL;
+ case IWifiChip::LatencyMode::LOW:
+ return legacy_hal::WIFI_LATENCY_MODE_LOW;
+ }
+ CHECK(false);
+}
+
+bool convertLegacyWifiMacInfoToAidl(const legacy_hal::WifiMacInfo& legacy_mac_info,
+ IWifiChipEventCallback::RadioModeInfo* aidl_radio_mode_info) {
+ if (!aidl_radio_mode_info) {
+ return false;
+ }
+ *aidl_radio_mode_info = {};
+
+ aidl_radio_mode_info->radioId = legacy_mac_info.wlan_mac_id;
+ // Convert from bitmask of bands in the legacy HAL to enum value in
+ // the AIDL interface.
+ if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND &&
+ legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND &&
+ legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) {
+ aidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ_6GHZ;
+ } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND &&
+ legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
+ aidl_radio_mode_info->bandInfo = WifiBand::BAND_5GHZ_6GHZ;
+ } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_6_0_BAND) {
+ aidl_radio_mode_info->bandInfo = WifiBand::BAND_6GHZ;
+ } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND &&
+ legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
+ aidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ_5GHZ;
+ } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_2_4_BAND) {
+ aidl_radio_mode_info->bandInfo = WifiBand::BAND_24GHZ;
+ } else if (legacy_mac_info.mac_band & legacy_hal::WLAN_MAC_5_0_BAND) {
+ aidl_radio_mode_info->bandInfo = WifiBand::BAND_5GHZ;
+ } else {
+ aidl_radio_mode_info->bandInfo = WifiBand::BAND_UNSPECIFIED;
+ }
+ std::vector<IWifiChipEventCallback::IfaceInfo> iface_info_vec;
+ for (const auto& legacy_iface_info : legacy_mac_info.iface_infos) {
+ IWifiChipEventCallback::IfaceInfo iface_info;
+ iface_info.name = legacy_iface_info.name;
+ iface_info.channel = legacy_iface_info.channel;
+ iface_info_vec.push_back(iface_info);
+ }
+ aidl_radio_mode_info->ifaceInfos = iface_info_vec;
+ return true;
+}
+
+uint32_t convertAidlWifiBandToLegacyMacBand(WifiBand aidl_band) {
+ switch (aidl_band) {
+ case WifiBand::BAND_24GHZ:
+ return legacy_hal::WLAN_MAC_2_4_BAND;
+ case WifiBand::BAND_5GHZ:
+ case WifiBand::BAND_5GHZ_DFS:
+ case WifiBand::BAND_5GHZ_WITH_DFS:
+ return legacy_hal::WLAN_MAC_5_0_BAND;
+ case WifiBand::BAND_24GHZ_5GHZ:
+ case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
+ return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND);
+ case WifiBand::BAND_6GHZ:
+ return legacy_hal::WLAN_MAC_6_0_BAND;
+ case WifiBand::BAND_5GHZ_6GHZ:
+ return (legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_6_0_BAND);
+ case WifiBand::BAND_24GHZ_5GHZ_6GHZ:
+ case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS_6GHZ:
+ return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND |
+ legacy_hal::WLAN_MAC_6_0_BAND);
+ case WifiBand::BAND_60GHZ:
+ return legacy_hal::WLAN_MAC_60_0_BAND;
+ default:
+ return (legacy_hal::WLAN_MAC_2_4_BAND | legacy_hal::WLAN_MAC_5_0_BAND |
+ legacy_hal::WLAN_MAC_6_0_BAND | legacy_hal::WLAN_MAC_60_0_BAND);
+ }
+}
+
+WifiBand convertLegacyMacBandToAidlWifiBand(uint32_t band) {
+ switch (band) {
+ case legacy_hal::WLAN_MAC_2_4_BAND:
+ return WifiBand::BAND_24GHZ;
+ case legacy_hal::WLAN_MAC_5_0_BAND:
+ return WifiBand::BAND_5GHZ;
+ case legacy_hal::WLAN_MAC_6_0_BAND:
+ return WifiBand::BAND_6GHZ;
+ case legacy_hal::WLAN_MAC_60_0_BAND:
+ return WifiBand::BAND_60GHZ;
+ default:
+ return WifiBand::BAND_UNSPECIFIED;
+ }
+}
+
+uint32_t convertAidlWifiIfaceModeToLegacy(uint32_t aidl_iface_mask) {
+ uint32_t legacy_iface_mask = 0;
+ if (aidl_iface_mask & static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_STA)) {
+ legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_STA);
+ }
+ if (aidl_iface_mask & static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_SOFTAP)) {
+ legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_SOFTAP);
+ }
+ if (aidl_iface_mask & static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_P2P_CLIENT)) {
+ legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT);
+ }
+ if (aidl_iface_mask & static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_P2P_GO)) {
+ legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_P2P_GO);
+ }
+ if (aidl_iface_mask & static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_NAN)) {
+ legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_NAN);
+ }
+ if (aidl_iface_mask & static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_TDLS)) {
+ legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_TDLS);
+ }
+ if (aidl_iface_mask & static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_MESH)) {
+ legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_MESH);
+ }
+ if (aidl_iface_mask & static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_IBSS)) {
+ legacy_iface_mask |= (1 << legacy_hal::WIFI_INTERFACE_IBSS);
+ }
+ return legacy_iface_mask;
+}
+
+uint32_t convertLegacyWifiInterfaceModeToAidl(uint32_t legacy_iface_mask) {
+ uint32_t aidl_iface_mask = 0;
+ if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_STA)) {
+ aidl_iface_mask |= static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_STA);
+ }
+ if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_SOFTAP)) {
+ aidl_iface_mask |= static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_SOFTAP);
+ }
+ if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_CLIENT)) {
+ aidl_iface_mask |= static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_P2P_CLIENT);
+ }
+ if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_P2P_GO)) {
+ aidl_iface_mask |= static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_P2P_GO);
+ }
+ if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_NAN)) {
+ aidl_iface_mask |= static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_NAN);
+ }
+ if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_TDLS)) {
+ aidl_iface_mask |= static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_TDLS);
+ }
+ if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_MESH)) {
+ aidl_iface_mask |= static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_MESH);
+ }
+ if (legacy_iface_mask & (1 << legacy_hal::WIFI_INTERFACE_IBSS)) {
+ aidl_iface_mask |= static_cast<int32_t>(WifiIfaceMode::IFACE_MODE_IBSS);
+ }
+ return aidl_iface_mask;
+}
+
+uint32_t convertAidlUsableChannelFilterToLegacy(uint32_t aidl_filter_mask) {
+ uint32_t legacy_filter_mask = 0;
+ if (aidl_filter_mask &
+ static_cast<int32_t>(IWifiChip::UsableChannelFilter::CELLULAR_COEXISTENCE)) {
+ legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE;
+ }
+ if (aidl_filter_mask & static_cast<int32_t>(IWifiChip::UsableChannelFilter::CONCURRENCY)) {
+ legacy_filter_mask |= legacy_hal::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY;
+ }
+ if (aidl_filter_mask & static_cast<int32_t>(IWifiChip::UsableChannelFilter::NAN_INSTANT_MODE)) {
+ legacy_filter_mask |= WIFI_USABLE_CHANNEL_FILTER_NAN_INSTANT_MODE;
+ }
+ return legacy_filter_mask;
+}
+
+bool convertLegacyWifiUsableChannelToAidl(
+ const legacy_hal::wifi_usable_channel& legacy_usable_channel,
+ WifiUsableChannel* aidl_usable_channel) {
+ if (!aidl_usable_channel) {
+ return false;
+ }
+ *aidl_usable_channel = {};
+ aidl_usable_channel->channel = legacy_usable_channel.freq;
+ aidl_usable_channel->channelBandwidth =
+ convertLegacyWifiChannelWidthToAidl(legacy_usable_channel.width);
+ aidl_usable_channel->ifaceModeMask = static_cast<WifiIfaceMode>(
+ convertLegacyWifiInterfaceModeToAidl(legacy_usable_channel.iface_mode_mask));
+
+ return true;
+}
+
+bool convertLegacyWifiUsableChannelsToAidl(
+ const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
+ std::vector<WifiUsableChannel>* aidl_usable_channels) {
+ if (!aidl_usable_channels) {
+ return false;
+ }
+ *aidl_usable_channels = {};
+ for (const auto& legacy_usable_channel : legacy_usable_channels) {
+ WifiUsableChannel aidl_usable_channel;
+ if (!convertLegacyWifiUsableChannelToAidl(legacy_usable_channel, &aidl_usable_channel)) {
+ return false;
+ }
+ aidl_usable_channels->push_back(aidl_usable_channel);
+ }
+ return true;
+}
+
+bool convertLegacyWifiMacInfosToAidl(
+ const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
+ std::vector<IWifiChipEventCallback::RadioModeInfo>* aidl_radio_mode_infos) {
+ if (!aidl_radio_mode_infos) {
+ return false;
+ }
+ *aidl_radio_mode_infos = {};
+
+ for (const auto& legacy_mac_info : legacy_mac_infos) {
+ IWifiChipEventCallback::RadioModeInfo aidl_radio_mode_info;
+ if (!convertLegacyWifiMacInfoToAidl(legacy_mac_info, &aidl_radio_mode_info)) {
+ return false;
+ }
+ aidl_radio_mode_infos->push_back(aidl_radio_mode_info);
+ }
+ return true;
+}
+
+bool convertLegacyFeaturesToAidlStaCapabilities(uint64_t legacy_feature_set,
+ uint32_t legacy_logger_feature_set,
+ uint32_t* aidl_caps) {
+ if (!aidl_caps) {
+ return false;
+ }
+ *aidl_caps = {};
+ for (const auto feature : {legacy_hal::WIFI_LOGGER_PACKET_FATE_SUPPORTED}) {
+ if (feature & legacy_logger_feature_set) {
+ *aidl_caps |= static_cast<uint32_t>(
+ convertLegacyLoggerFeatureToAidlStaIfaceCapability(feature));
+ }
+ }
+ for (const auto feature :
+ {WIFI_FEATURE_GSCAN, WIFI_FEATURE_LINK_LAYER_STATS, WIFI_FEATURE_RSSI_MONITOR,
+ WIFI_FEATURE_CONTROL_ROAMING, WIFI_FEATURE_IE_WHITELIST, WIFI_FEATURE_SCAN_RAND,
+ WIFI_FEATURE_INFRA_5G, WIFI_FEATURE_HOTSPOT, WIFI_FEATURE_PNO, WIFI_FEATURE_TDLS,
+ WIFI_FEATURE_TDLS_OFFCHANNEL, WIFI_FEATURE_CONFIG_NDO, WIFI_FEATURE_MKEEP_ALIVE}) {
+ if (feature & legacy_feature_set) {
+ *aidl_caps |=
+ static_cast<uint32_t>(convertLegacyFeatureToAidlStaIfaceCapability(feature));
+ }
+ }
+ // There is no flag for this one in the legacy feature set. Adding it to the
+ // set because all the current devices support it.
+ *aidl_caps |= static_cast<uint32_t>(IWifiStaIface::StaIfaceCapabilityMask::APF);
+ return true;
+}
+
+bool convertLegacyApfCapabilitiesToAidl(const legacy_hal::PacketFilterCapabilities& legacy_caps,
+ StaApfPacketFilterCapabilities* aidl_caps) {
+ if (!aidl_caps) {
+ return false;
+ }
+ *aidl_caps = {};
+ aidl_caps->version = legacy_caps.version;
+ aidl_caps->maxLength = legacy_caps.max_len;
+ return true;
+}
+
+uint8_t convertAidlGscanReportEventFlagToLegacy(
+ StaBackgroundScanBucketEventReportSchemeMask aidl_flag) {
+ using AidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
+ switch (aidl_flag) {
+ case AidlFlag::EACH_SCAN:
+ return REPORT_EVENTS_EACH_SCAN;
+ case AidlFlag::FULL_RESULTS:
+ return REPORT_EVENTS_FULL_RESULTS;
+ case AidlFlag::NO_BATCH:
+ return REPORT_EVENTS_NO_BATCH;
+ };
+ CHECK(false);
+}
+
+StaScanDataFlagMask convertLegacyGscanDataFlagToAidl(uint8_t legacy_flag) {
+ switch (legacy_flag) {
+ case legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED:
+ return StaScanDataFlagMask::INTERRUPTED;
+ };
+ CHECK(false) << "Unknown legacy flag: " << legacy_flag;
+ // To silence the compiler warning about reaching the end of non-void
+ // function.
+ return {};
+}
+
+bool convertLegacyGscanCapabilitiesToAidl(const legacy_hal::wifi_gscan_capabilities& legacy_caps,
+ StaBackgroundScanCapabilities* aidl_caps) {
+ if (!aidl_caps) {
+ return false;
+ }
+ *aidl_caps = {};
+ aidl_caps->maxCacheSize = legacy_caps.max_scan_cache_size;
+ aidl_caps->maxBuckets = legacy_caps.max_scan_buckets;
+ aidl_caps->maxApCachePerScan = legacy_caps.max_ap_cache_per_scan;
+ aidl_caps->maxReportingThreshold = legacy_caps.max_scan_reporting_threshold;
+ return true;
+}
+
+legacy_hal::wifi_band convertAidlWifiBandToLegacy(WifiBand band) {
+ switch (band) {
+ case WifiBand::BAND_UNSPECIFIED:
+ return legacy_hal::WIFI_BAND_UNSPECIFIED;
+ case WifiBand::BAND_24GHZ:
+ return legacy_hal::WIFI_BAND_BG;
+ case WifiBand::BAND_5GHZ:
+ return legacy_hal::WIFI_BAND_A;
+ case WifiBand::BAND_5GHZ_DFS:
+ return legacy_hal::WIFI_BAND_A_DFS;
+ case WifiBand::BAND_5GHZ_WITH_DFS:
+ return legacy_hal::WIFI_BAND_A_WITH_DFS;
+ case WifiBand::BAND_24GHZ_5GHZ:
+ return legacy_hal::WIFI_BAND_ABG;
+ case WifiBand::BAND_24GHZ_5GHZ_WITH_DFS:
+ return legacy_hal::WIFI_BAND_ABG_WITH_DFS;
+ default:
+ CHECK(false);
+ return {};
+ };
+}
+
+bool convertAidlGscanParamsToLegacy(const StaBackgroundScanParameters& aidl_scan_params,
+ legacy_hal::wifi_scan_cmd_params* legacy_scan_params) {
+ if (!legacy_scan_params) {
+ return false;
+ }
+ *legacy_scan_params = {};
+ legacy_scan_params->base_period = aidl_scan_params.basePeriodInMs;
+ legacy_scan_params->max_ap_per_scan = aidl_scan_params.maxApPerScan;
+ legacy_scan_params->report_threshold_percent = aidl_scan_params.reportThresholdPercent;
+ legacy_scan_params->report_threshold_num_scans = aidl_scan_params.reportThresholdNumScans;
+ if (aidl_scan_params.buckets.size() > MAX_BUCKETS) {
+ return false;
+ }
+ legacy_scan_params->num_buckets = aidl_scan_params.buckets.size();
+ for (uint32_t bucket_idx = 0; bucket_idx < aidl_scan_params.buckets.size(); bucket_idx++) {
+ const StaBackgroundScanBucketParameters& aidl_bucket_spec =
+ aidl_scan_params.buckets[bucket_idx];
+ legacy_hal::wifi_scan_bucket_spec& legacy_bucket_spec =
+ legacy_scan_params->buckets[bucket_idx];
+ if (aidl_bucket_spec.bucketIdx >= MAX_BUCKETS) {
+ return false;
+ }
+ legacy_bucket_spec.bucket = aidl_bucket_spec.bucketIdx;
+ legacy_bucket_spec.band = convertAidlWifiBandToLegacy(aidl_bucket_spec.band);
+ legacy_bucket_spec.period = aidl_bucket_spec.periodInMs;
+ legacy_bucket_spec.max_period = aidl_bucket_spec.exponentialMaxPeriodInMs;
+ legacy_bucket_spec.base = aidl_bucket_spec.exponentialBase;
+ legacy_bucket_spec.step_count = aidl_bucket_spec.exponentialStepCount;
+ legacy_bucket_spec.report_events = 0;
+ using AidlFlag = StaBackgroundScanBucketEventReportSchemeMask;
+ for (const auto flag : {AidlFlag::EACH_SCAN, AidlFlag::FULL_RESULTS, AidlFlag::NO_BATCH}) {
+ if (static_cast<int32_t>(aidl_bucket_spec.eventReportScheme) &
+ static_cast<std::underlying_type<AidlFlag>::type>(flag)) {
+ legacy_bucket_spec.report_events |= convertAidlGscanReportEventFlagToLegacy(flag);
+ }
+ }
+ if (aidl_bucket_spec.frequencies.size() > MAX_CHANNELS) {
+ return false;
+ }
+ legacy_bucket_spec.num_channels = aidl_bucket_spec.frequencies.size();
+ for (uint32_t freq_idx = 0; freq_idx < aidl_bucket_spec.frequencies.size(); freq_idx++) {
+ legacy_bucket_spec.channels[freq_idx].channel = aidl_bucket_spec.frequencies[freq_idx];
+ }
+ }
+ return true;
+}
+
+bool convertLegacyIeToAidl(const legacy_hal::wifi_information_element& legacy_ie,
+ WifiInformationElement* aidl_ie) {
+ if (!aidl_ie) {
+ return false;
+ }
+ *aidl_ie = {};
+ aidl_ie->id = legacy_ie.id;
+ aidl_ie->data = std::vector<uint8_t>(legacy_ie.data, legacy_ie.data + legacy_ie.len);
+ return true;
+}
+
+bool convertLegacyIeBlobToAidl(const uint8_t* ie_blob, uint32_t ie_blob_len,
+ std::vector<WifiInformationElement>* aidl_ies) {
+ if (!ie_blob || !aidl_ies) {
+ return false;
+ }
+ *aidl_ies = {};
+ const uint8_t* ies_begin = ie_blob;
+ const uint8_t* ies_end = ie_blob + ie_blob_len;
+ const uint8_t* next_ie = ies_begin;
+ using wifi_ie = legacy_hal::wifi_information_element;
+ constexpr size_t kIeHeaderLen = sizeof(wifi_ie);
+ // Each IE should at least have the header (i.e |id| & |len| fields).
+ while (next_ie + kIeHeaderLen <= ies_end) {
+ const wifi_ie& legacy_ie = (*reinterpret_cast<const wifi_ie*>(next_ie));
+ uint32_t curr_ie_len = kIeHeaderLen + legacy_ie.len;
+ if (next_ie + curr_ie_len > ies_end) {
+ LOG(ERROR) << "Error parsing IE blob. Next IE: " << (void*)next_ie
+ << ", Curr IE len: " << curr_ie_len << ", IEs End: " << (void*)ies_end;
+ break;
+ }
+ WifiInformationElement aidl_ie;
+ if (!convertLegacyIeToAidl(legacy_ie, &aidl_ie)) {
+ LOG(ERROR) << "Error converting IE. Id: " << legacy_ie.id << ", len: " << legacy_ie.len;
+ break;
+ }
+ aidl_ies->push_back(std::move(aidl_ie));
+ next_ie += curr_ie_len;
+ }
+ // Check if the blob has been fully consumed.
+ if (next_ie != ies_end) {
+ LOG(ERROR) << "Failed to fully parse IE blob. Next IE: " << (void*)next_ie
+ << ", IEs End: " << (void*)ies_end;
+ }
+ return true;
+}
+
+bool convertLegacyGscanResultToAidl(const legacy_hal::wifi_scan_result& legacy_scan_result,
+ bool has_ie_data, StaScanResult* aidl_scan_result) {
+ if (!aidl_scan_result) {
+ return false;
+ }
+ *aidl_scan_result = {};
+ aidl_scan_result->timeStampInUs = legacy_scan_result.ts;
+ aidl_scan_result->ssid = std::vector<uint8_t>(
+ legacy_scan_result.ssid,
+ legacy_scan_result.ssid +
+ strnlen(legacy_scan_result.ssid, sizeof(legacy_scan_result.ssid) - 1));
+ aidl_scan_result->bssid = std::array<uint8_t, 6>();
+ std::copy(legacy_scan_result.bssid, legacy_scan_result.bssid + 6,
+ std::begin(aidl_scan_result->bssid));
+ aidl_scan_result->frequency = legacy_scan_result.channel;
+ aidl_scan_result->rssi = legacy_scan_result.rssi;
+ aidl_scan_result->beaconPeriodInMs = legacy_scan_result.beacon_period;
+ aidl_scan_result->capability = legacy_scan_result.capability;
+ if (has_ie_data) {
+ std::vector<WifiInformationElement> ies;
+ if (!convertLegacyIeBlobToAidl(reinterpret_cast<const uint8_t*>(legacy_scan_result.ie_data),
+ legacy_scan_result.ie_length, &ies)) {
+ return false;
+ }
+ aidl_scan_result->informationElements = std::move(ies);
+ }
+ return true;
+}
+
+bool convertLegacyCachedGscanResultsToAidl(
+ const legacy_hal::wifi_cached_scan_results& legacy_cached_scan_result,
+ StaScanData* aidl_scan_data) {
+ if (!aidl_scan_data) {
+ return false;
+ }
+ *aidl_scan_data = {};
+ int32_t flags = 0;
+ for (const auto flag : {legacy_hal::WIFI_SCAN_FLAG_INTERRUPTED}) {
+ if (legacy_cached_scan_result.flags & flag) {
+ flags |= static_cast<std::underlying_type<StaScanDataFlagMask>::type>(
+ convertLegacyGscanDataFlagToAidl(flag));
+ }
+ }
+ aidl_scan_data->flags = static_cast<StaScanDataFlagMask>(flags);
+ aidl_scan_data->bucketsScanned = legacy_cached_scan_result.buckets_scanned;
+
+ CHECK(legacy_cached_scan_result.num_results >= 0 &&
+ legacy_cached_scan_result.num_results <= MAX_AP_CACHE_PER_SCAN);
+ std::vector<StaScanResult> aidl_scan_results;
+ for (int32_t result_idx = 0; result_idx < legacy_cached_scan_result.num_results; result_idx++) {
+ StaScanResult aidl_scan_result;
+ if (!convertLegacyGscanResultToAidl(legacy_cached_scan_result.results[result_idx], false,
+ &aidl_scan_result)) {
+ return false;
+ }
+ aidl_scan_results.push_back(aidl_scan_result);
+ }
+ aidl_scan_data->results = std::move(aidl_scan_results);
+ return true;
+}
+
+bool convertLegacyVectorOfCachedGscanResultsToAidl(
+ const std::vector<legacy_hal::wifi_cached_scan_results>& legacy_cached_scan_results,
+ std::vector<StaScanData>* aidl_scan_datas) {
+ if (!aidl_scan_datas) {
+ return false;
+ }
+ *aidl_scan_datas = {};
+ for (const auto& legacy_cached_scan_result : legacy_cached_scan_results) {
+ StaScanData aidl_scan_data;
+ if (!convertLegacyCachedGscanResultsToAidl(legacy_cached_scan_result, &aidl_scan_data)) {
+ return false;
+ }
+ aidl_scan_datas->push_back(aidl_scan_data);
+ }
+ return true;
+}
+
+WifiDebugTxPacketFate convertLegacyDebugTxPacketFateToAidl(legacy_hal::wifi_tx_packet_fate fate) {
+ switch (fate) {
+ case legacy_hal::TX_PKT_FATE_ACKED:
+ return WifiDebugTxPacketFate::ACKED;
+ case legacy_hal::TX_PKT_FATE_SENT:
+ return WifiDebugTxPacketFate::SENT;
+ case legacy_hal::TX_PKT_FATE_FW_QUEUED:
+ return WifiDebugTxPacketFate::FW_QUEUED;
+ case legacy_hal::TX_PKT_FATE_FW_DROP_INVALID:
+ return WifiDebugTxPacketFate::FW_DROP_INVALID;
+ case legacy_hal::TX_PKT_FATE_FW_DROP_NOBUFS:
+ return WifiDebugTxPacketFate::FW_DROP_NOBUFS;
+ case legacy_hal::TX_PKT_FATE_FW_DROP_OTHER:
+ return WifiDebugTxPacketFate::FW_DROP_OTHER;
+ case legacy_hal::TX_PKT_FATE_DRV_QUEUED:
+ return WifiDebugTxPacketFate::DRV_QUEUED;
+ case legacy_hal::TX_PKT_FATE_DRV_DROP_INVALID:
+ return WifiDebugTxPacketFate::DRV_DROP_INVALID;
+ case legacy_hal::TX_PKT_FATE_DRV_DROP_NOBUFS:
+ return WifiDebugTxPacketFate::DRV_DROP_NOBUFS;
+ case legacy_hal::TX_PKT_FATE_DRV_DROP_OTHER:
+ return WifiDebugTxPacketFate::DRV_DROP_OTHER;
+ };
+ CHECK(false) << "Unknown legacy fate type: " << fate;
+}
+
+WifiDebugRxPacketFate convertLegacyDebugRxPacketFateToAidl(legacy_hal::wifi_rx_packet_fate fate) {
+ switch (fate) {
+ case legacy_hal::RX_PKT_FATE_SUCCESS:
+ return WifiDebugRxPacketFate::SUCCESS;
+ case legacy_hal::RX_PKT_FATE_FW_QUEUED:
+ return WifiDebugRxPacketFate::FW_QUEUED;
+ case legacy_hal::RX_PKT_FATE_FW_DROP_FILTER:
+ return WifiDebugRxPacketFate::FW_DROP_FILTER;
+ case legacy_hal::RX_PKT_FATE_FW_DROP_INVALID:
+ return WifiDebugRxPacketFate::FW_DROP_INVALID;
+ case legacy_hal::RX_PKT_FATE_FW_DROP_NOBUFS:
+ return WifiDebugRxPacketFate::FW_DROP_NOBUFS;
+ case legacy_hal::RX_PKT_FATE_FW_DROP_OTHER:
+ return WifiDebugRxPacketFate::FW_DROP_OTHER;
+ case legacy_hal::RX_PKT_FATE_DRV_QUEUED:
+ return WifiDebugRxPacketFate::DRV_QUEUED;
+ case legacy_hal::RX_PKT_FATE_DRV_DROP_FILTER:
+ return WifiDebugRxPacketFate::DRV_DROP_FILTER;
+ case legacy_hal::RX_PKT_FATE_DRV_DROP_INVALID:
+ return WifiDebugRxPacketFate::DRV_DROP_INVALID;
+ case legacy_hal::RX_PKT_FATE_DRV_DROP_NOBUFS:
+ return WifiDebugRxPacketFate::DRV_DROP_NOBUFS;
+ case legacy_hal::RX_PKT_FATE_DRV_DROP_OTHER:
+ return WifiDebugRxPacketFate::DRV_DROP_OTHER;
+ };
+ CHECK(false) << "Unknown legacy fate type: " << fate;
+}
+
+WifiDebugPacketFateFrameType convertLegacyDebugPacketFateFrameTypeToAidl(
+ legacy_hal::frame_type type) {
+ switch (type) {
+ case legacy_hal::FRAME_TYPE_UNKNOWN:
+ return WifiDebugPacketFateFrameType::UNKNOWN;
+ case legacy_hal::FRAME_TYPE_ETHERNET_II:
+ return WifiDebugPacketFateFrameType::ETHERNET_II;
+ case legacy_hal::FRAME_TYPE_80211_MGMT:
+ return WifiDebugPacketFateFrameType::MGMT_80211;
+ };
+ CHECK(false) << "Unknown legacy frame type: " << type;
+}
+
+bool convertLegacyDebugPacketFateFrameToAidl(const legacy_hal::frame_info& legacy_frame,
+ WifiDebugPacketFateFrameInfo* aidl_frame) {
+ if (!aidl_frame) {
+ return false;
+ }
+ *aidl_frame = {};
+ aidl_frame->frameType = convertLegacyDebugPacketFateFrameTypeToAidl(legacy_frame.payload_type);
+ aidl_frame->frameLen = legacy_frame.frame_len;
+ aidl_frame->driverTimestampUsec = legacy_frame.driver_timestamp_usec;
+ aidl_frame->firmwareTimestampUsec = legacy_frame.firmware_timestamp_usec;
+ const uint8_t* frame_begin =
+ reinterpret_cast<const uint8_t*>(legacy_frame.frame_content.ethernet_ii_bytes);
+ aidl_frame->frameContent =
+ std::vector<uint8_t>(frame_begin, frame_begin + legacy_frame.frame_len);
+ return true;
+}
+
+bool convertLegacyDebugTxPacketFateToAidl(const legacy_hal::wifi_tx_report& legacy_fate,
+ WifiDebugTxPacketFateReport* aidl_fate) {
+ if (!aidl_fate) {
+ return false;
+ }
+ *aidl_fate = {};
+ aidl_fate->fate = convertLegacyDebugTxPacketFateToAidl(legacy_fate.fate);
+ return convertLegacyDebugPacketFateFrameToAidl(legacy_fate.frame_inf, &aidl_fate->frameInfo);
+}
+
+bool convertLegacyVectorOfDebugTxPacketFateToAidl(
+ const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
+ std::vector<WifiDebugTxPacketFateReport>* aidl_fates) {
+ if (!aidl_fates) {
+ return false;
+ }
+ *aidl_fates = {};
+ for (const auto& legacy_fate : legacy_fates) {
+ WifiDebugTxPacketFateReport aidl_fate;
+ if (!convertLegacyDebugTxPacketFateToAidl(legacy_fate, &aidl_fate)) {
+ return false;
+ }
+ aidl_fates->push_back(aidl_fate);
+ }
+ return true;
+}
+
+bool convertLegacyDebugRxPacketFateToAidl(const legacy_hal::wifi_rx_report& legacy_fate,
+ WifiDebugRxPacketFateReport* aidl_fate) {
+ if (!aidl_fate) {
+ return false;
+ }
+ *aidl_fate = {};
+ aidl_fate->fate = convertLegacyDebugRxPacketFateToAidl(legacy_fate.fate);
+ return convertLegacyDebugPacketFateFrameToAidl(legacy_fate.frame_inf, &aidl_fate->frameInfo);
+}
+
+bool convertLegacyVectorOfDebugRxPacketFateToAidl(
+ const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
+ std::vector<WifiDebugRxPacketFateReport>* aidl_fates) {
+ if (!aidl_fates) {
+ return false;
+ }
+ *aidl_fates = {};
+ for (const auto& legacy_fate : legacy_fates) {
+ WifiDebugRxPacketFateReport aidl_fate;
+ if (!convertLegacyDebugRxPacketFateToAidl(legacy_fate, &aidl_fate)) {
+ return false;
+ }
+ aidl_fates->push_back(aidl_fate);
+ }
+ return true;
+}
+
+bool convertLegacyLinkLayerRadioStatsToAidl(
+ const legacy_hal::LinkLayerRadioStats& legacy_radio_stat,
+ StaLinkLayerRadioStats* aidl_radio_stat) {
+ if (!aidl_radio_stat) {
+ return false;
+ }
+ *aidl_radio_stat = {};
+
+ aidl_radio_stat->radioId = legacy_radio_stat.stats.radio;
+ aidl_radio_stat->onTimeInMs = legacy_radio_stat.stats.on_time;
+ aidl_radio_stat->txTimeInMs = legacy_radio_stat.stats.tx_time;
+ aidl_radio_stat->rxTimeInMs = legacy_radio_stat.stats.rx_time;
+ aidl_radio_stat->onTimeInMsForScan = legacy_radio_stat.stats.on_time_scan;
+ aidl_radio_stat->txTimeInMsPerLevel = uintToIntVec(legacy_radio_stat.tx_time_per_levels);
+ aidl_radio_stat->onTimeInMsForNanScan = legacy_radio_stat.stats.on_time_nbd;
+ aidl_radio_stat->onTimeInMsForBgScan = legacy_radio_stat.stats.on_time_gscan;
+ aidl_radio_stat->onTimeInMsForRoamScan = legacy_radio_stat.stats.on_time_roam_scan;
+ aidl_radio_stat->onTimeInMsForPnoScan = legacy_radio_stat.stats.on_time_pno_scan;
+ aidl_radio_stat->onTimeInMsForHs20Scan = legacy_radio_stat.stats.on_time_hs20;
+
+ std::vector<WifiChannelStats> aidl_channel_stats;
+
+ for (const auto& channel_stat : legacy_radio_stat.channel_stats) {
+ WifiChannelStats aidl_channel_stat;
+ aidl_channel_stat.onTimeInMs = channel_stat.on_time;
+ aidl_channel_stat.ccaBusyTimeInMs = channel_stat.cca_busy_time;
+ aidl_channel_stat.channel.width = WifiChannelWidthInMhz::WIDTH_20;
+ aidl_channel_stat.channel.centerFreq = channel_stat.channel.center_freq;
+ aidl_channel_stat.channel.centerFreq0 = channel_stat.channel.center_freq0;
+ aidl_channel_stat.channel.centerFreq1 = channel_stat.channel.center_freq1;
+ aidl_channel_stats.push_back(aidl_channel_stat);
+ }
+
+ aidl_radio_stat->channelStats = aidl_channel_stats;
+
+ return true;
+}
+
+bool convertLegacyLinkLayerStatsToAidl(const legacy_hal::LinkLayerStats& legacy_stats,
+ StaLinkLayerStats* aidl_stats) {
+ if (!aidl_stats) {
+ return false;
+ }
+ *aidl_stats = {};
+ // iface legacy_stats conversion.
+ aidl_stats->iface.beaconRx = legacy_stats.iface.beacon_rx;
+ aidl_stats->iface.avgRssiMgmt = legacy_stats.iface.rssi_mgmt;
+ aidl_stats->iface.wmeBePktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu;
+ aidl_stats->iface.wmeBePktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu;
+ aidl_stats->iface.wmeBePktStats.lostMpdu =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost;
+ aidl_stats->iface.wmeBePktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries;
+ aidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMinInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min;
+ aidl_stats->iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max;
+ aidl_stats->iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg;
+ aidl_stats->iface.wmeBeContentionTimeStats.contentionNumSamples =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples;
+ aidl_stats->iface.wmeBkPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu;
+ aidl_stats->iface.wmeBkPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu;
+ aidl_stats->iface.wmeBkPktStats.lostMpdu =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost;
+ aidl_stats->iface.wmeBkPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries;
+ aidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMinInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min;
+ aidl_stats->iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max;
+ aidl_stats->iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg;
+ aidl_stats->iface.wmeBkContentionTimeStats.contentionNumSamples =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples;
+ aidl_stats->iface.wmeViPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu;
+ aidl_stats->iface.wmeViPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu;
+ aidl_stats->iface.wmeViPktStats.lostMpdu =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost;
+ aidl_stats->iface.wmeViPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries;
+ aidl_stats->iface.wmeViContentionTimeStats.contentionTimeMinInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min;
+ aidl_stats->iface.wmeViContentionTimeStats.contentionTimeMaxInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max;
+ aidl_stats->iface.wmeViContentionTimeStats.contentionTimeAvgInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg;
+ aidl_stats->iface.wmeViContentionTimeStats.contentionNumSamples =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples;
+ aidl_stats->iface.wmeVoPktStats.rxMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu;
+ aidl_stats->iface.wmeVoPktStats.txMpdu = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu;
+ aidl_stats->iface.wmeVoPktStats.lostMpdu =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost;
+ aidl_stats->iface.wmeVoPktStats.retries = legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries;
+ aidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMinInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min;
+ aidl_stats->iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max;
+ aidl_stats->iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg;
+ aidl_stats->iface.wmeVoContentionTimeStats.contentionNumSamples =
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples;
+ aidl_stats->iface.timeSliceDutyCycleInPercent =
+ legacy_stats.iface.info.time_slicing_duty_cycle_percent;
+ // peer info legacy_stats conversion.
+ std::vector<StaPeerInfo> aidl_peers_info_stats;
+ for (const auto& legacy_peer_info_stats : legacy_stats.peers) {
+ StaPeerInfo aidl_peer_info_stats;
+ if (!convertLegacyPeerInfoStatsToAidl(legacy_peer_info_stats, &aidl_peer_info_stats)) {
+ return false;
+ }
+ aidl_peers_info_stats.push_back(aidl_peer_info_stats);
+ }
+ aidl_stats->iface.peers = aidl_peers_info_stats;
+ // radio legacy_stats conversion.
+ std::vector<StaLinkLayerRadioStats> aidl_radios_stats;
+ for (const auto& legacy_radio_stats : legacy_stats.radios) {
+ StaLinkLayerRadioStats aidl_radio_stats;
+ if (!convertLegacyLinkLayerRadioStatsToAidl(legacy_radio_stats, &aidl_radio_stats)) {
+ return false;
+ }
+ aidl_radios_stats.push_back(aidl_radio_stats);
+ }
+ aidl_stats->radios = aidl_radios_stats;
+ aidl_stats->timeStampInMs = ::android::uptimeMillis();
+ return true;
+}
+
+bool convertLegacyPeerInfoStatsToAidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats,
+ StaPeerInfo* aidl_peer_info_stats) {
+ if (!aidl_peer_info_stats) {
+ return false;
+ }
+ *aidl_peer_info_stats = {};
+ aidl_peer_info_stats->staCount = legacy_peer_info_stats.peer_info.bssload.sta_count;
+ aidl_peer_info_stats->chanUtil = legacy_peer_info_stats.peer_info.bssload.chan_util;
+
+ std::vector<StaRateStat> aidlRateStats;
+ for (const auto& legacy_rate_stats : legacy_peer_info_stats.rate_stats) {
+ StaRateStat rateStat;
+ if (!convertLegacyWifiRateInfoToAidl(legacy_rate_stats.rate, &rateStat.rateInfo)) {
+ return false;
+ }
+ rateStat.txMpdu = legacy_rate_stats.tx_mpdu;
+ rateStat.rxMpdu = legacy_rate_stats.rx_mpdu;
+ rateStat.mpduLost = legacy_rate_stats.mpdu_lost;
+ rateStat.retries = legacy_rate_stats.retries;
+ aidlRateStats.push_back(rateStat);
+ }
+ aidl_peer_info_stats->rateStats = aidlRateStats;
+ return true;
+}
+
+bool convertLegacyRoamingCapabilitiesToAidl(
+ const legacy_hal::wifi_roaming_capabilities& legacy_caps,
+ StaRoamingCapabilities* aidl_caps) {
+ if (!aidl_caps) {
+ return false;
+ }
+ *aidl_caps = {};
+ aidl_caps->maxBlocklistSize = legacy_caps.max_blacklist_size;
+ aidl_caps->maxAllowlistSize = legacy_caps.max_whitelist_size;
+ return true;
+}
+
+bool convertAidlRoamingConfigToLegacy(const StaRoamingConfig& aidl_config,
+ legacy_hal::wifi_roaming_config* legacy_config) {
+ if (!legacy_config) {
+ return false;
+ }
+ *legacy_config = {};
+ if (aidl_config.bssidBlocklist.size() > MAX_BLACKLIST_BSSID ||
+ aidl_config.ssidAllowlist.size() > MAX_WHITELIST_SSID) {
+ return false;
+ }
+ legacy_config->num_blacklist_bssid = aidl_config.bssidBlocklist.size();
+ uint32_t i = 0;
+ for (const auto& bssid : aidl_config.bssidBlocklist) {
+ CHECK(bssid.data.size() == sizeof(legacy_hal::mac_addr));
+ memcpy(legacy_config->blacklist_bssid[i++], bssid.data.data(), bssid.data.size());
+ }
+ legacy_config->num_whitelist_ssid = aidl_config.ssidAllowlist.size();
+ i = 0;
+ for (const auto& ssid : aidl_config.ssidAllowlist) {
+ CHECK(ssid.data.size() <= sizeof(legacy_hal::ssid_t::ssid_str));
+ legacy_config->whitelist_ssid[i].length = ssid.data.size();
+ memcpy(legacy_config->whitelist_ssid[i].ssid_str, ssid.data.data(), ssid.data.size());
+ i++;
+ }
+ return true;
+}
+
+legacy_hal::fw_roaming_state_t convertAidlRoamingStateToLegacy(StaRoamingState state) {
+ switch (state) {
+ case StaRoamingState::ENABLED:
+ return legacy_hal::ROAMING_ENABLE;
+ case StaRoamingState::DISABLED:
+ return legacy_hal::ROAMING_DISABLE;
+ };
+ CHECK(false);
+}
+
+legacy_hal::NanMatchAlg convertAidlNanMatchAlgToLegacy(NanMatchAlg type) {
+ switch (type) {
+ case NanMatchAlg::MATCH_ONCE:
+ return legacy_hal::NAN_MATCH_ALG_MATCH_ONCE;
+ case NanMatchAlg::MATCH_CONTINUOUS:
+ return legacy_hal::NAN_MATCH_ALG_MATCH_CONTINUOUS;
+ case NanMatchAlg::MATCH_NEVER:
+ return legacy_hal::NAN_MATCH_ALG_MATCH_NEVER;
+ }
+ CHECK(false);
+}
+
+legacy_hal::NanPublishType convertAidlNanPublishTypeToLegacy(NanPublishType type) {
+ switch (type) {
+ case NanPublishType::UNSOLICITED:
+ return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED;
+ case NanPublishType::SOLICITED:
+ return legacy_hal::NAN_PUBLISH_TYPE_SOLICITED;
+ case NanPublishType::UNSOLICITED_SOLICITED:
+ return legacy_hal::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
+ }
+ CHECK(false);
+}
+
+legacy_hal::NanTxType convertAidlNanTxTypeToLegacy(NanTxType type) {
+ switch (type) {
+ case NanTxType::BROADCAST:
+ return legacy_hal::NAN_TX_TYPE_BROADCAST;
+ case NanTxType::UNICAST:
+ return legacy_hal::NAN_TX_TYPE_UNICAST;
+ }
+ CHECK(false);
+}
+
+legacy_hal::NanSubscribeType convertAidlNanSubscribeTypeToLegacy(NanSubscribeType type) {
+ switch (type) {
+ case NanSubscribeType::PASSIVE:
+ return legacy_hal::NAN_SUBSCRIBE_TYPE_PASSIVE;
+ case NanSubscribeType::ACTIVE:
+ return legacy_hal::NAN_SUBSCRIBE_TYPE_ACTIVE;
+ }
+ CHECK(false);
+}
+
+legacy_hal::NanSRFType convertAidlNanSrfTypeToLegacy(NanSrfType type) {
+ switch (type) {
+ case NanSrfType::BLOOM_FILTER:
+ return legacy_hal::NAN_SRF_ATTR_BLOOM_FILTER;
+ case NanSrfType::PARTIAL_MAC_ADDR:
+ return legacy_hal::NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
+ }
+ CHECK(false);
+}
+
+legacy_hal::NanDataPathChannelCfg convertAidlNanDataPathChannelCfgToLegacy(
+ NanDataPathChannelCfg type) {
+ switch (type) {
+ case NanDataPathChannelCfg::CHANNEL_NOT_REQUESTED:
+ return legacy_hal::NAN_DP_CHANNEL_NOT_REQUESTED;
+ case NanDataPathChannelCfg::REQUEST_CHANNEL_SETUP:
+ return legacy_hal::NAN_DP_REQUEST_CHANNEL_SETUP;
+ case NanDataPathChannelCfg::FORCE_CHANNEL_SETUP:
+ return legacy_hal::NAN_DP_FORCE_CHANNEL_SETUP;
+ }
+ CHECK(false);
+}
+
+NanStatusCode convertLegacyNanStatusTypeToAidl(legacy_hal::NanStatusType type) {
+ switch (type) {
+ case legacy_hal::NAN_STATUS_SUCCESS:
+ return NanStatusCode::SUCCESS;
+ case legacy_hal::NAN_STATUS_INTERNAL_FAILURE:
+ return NanStatusCode::INTERNAL_FAILURE;
+ case legacy_hal::NAN_STATUS_PROTOCOL_FAILURE:
+ return NanStatusCode::PROTOCOL_FAILURE;
+ case legacy_hal::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID:
+ return NanStatusCode::INVALID_SESSION_ID;
+ case legacy_hal::NAN_STATUS_NO_RESOURCE_AVAILABLE:
+ return NanStatusCode::NO_RESOURCES_AVAILABLE;
+ case legacy_hal::NAN_STATUS_INVALID_PARAM:
+ return NanStatusCode::INVALID_ARGS;
+ case legacy_hal::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID:
+ return NanStatusCode::INVALID_PEER_ID;
+ case legacy_hal::NAN_STATUS_INVALID_NDP_ID:
+ return NanStatusCode::INVALID_NDP_ID;
+ case legacy_hal::NAN_STATUS_NAN_NOT_ALLOWED:
+ return NanStatusCode::NAN_NOT_ALLOWED;
+ case legacy_hal::NAN_STATUS_NO_OTA_ACK:
+ return NanStatusCode::NO_OTA_ACK;
+ case legacy_hal::NAN_STATUS_ALREADY_ENABLED:
+ return NanStatusCode::ALREADY_ENABLED;
+ case legacy_hal::NAN_STATUS_FOLLOWUP_QUEUE_FULL:
+ return NanStatusCode::FOLLOWUP_TX_QUEUE_FULL;
+ case legacy_hal::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED:
+ return NanStatusCode::UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
+ }
+ CHECK(false);
+}
+
+void convertToNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
+ NanStatus* nanStatus) {
+ nanStatus->status = convertLegacyNanStatusTypeToAidl(type);
+ nanStatus->description = safeConvertChar(str, max_len);
+}
+
+bool convertAidlNanEnableRequestToLegacy(const NanEnableRequest& aidl_request1,
+ const NanConfigRequestSupplemental& aidl_request2,
+ legacy_hal::NanEnableRequest* legacy_request) {
+ if (!legacy_request) {
+ LOG(ERROR) << "convertAidlNanEnableRequestToLegacy: null legacy_request";
+ return false;
+ }
+ *legacy_request = {};
+
+ legacy_request->config_2dot4g_support = 1;
+ legacy_request->support_2dot4g_val =
+ aidl_request1.operateInBand[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+ legacy_request->config_support_5g = 1;
+ legacy_request->support_5g_val =
+ aidl_request1.operateInBand[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+ legacy_request->config_hop_count_limit = 1;
+ legacy_request->hop_count_limit_val = aidl_request1.hopCountMax;
+ legacy_request->master_pref = aidl_request1.configParams.masterPref;
+ legacy_request->discovery_indication_cfg = 0;
+ legacy_request->discovery_indication_cfg |=
+ aidl_request1.configParams.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
+ legacy_request->discovery_indication_cfg |=
+ aidl_request1.configParams.disableStartedClusterIndication ? 0x2 : 0x0;
+ legacy_request->discovery_indication_cfg |=
+ aidl_request1.configParams.disableJoinedClusterIndication ? 0x4 : 0x0;
+ legacy_request->config_sid_beacon = 1;
+ if (aidl_request1.configParams.numberOfPublishServiceIdsInBeacon < 0) {
+ LOG(ERROR) << "convertAidlNanEnableRequestToLegacy: "
+ "numberOfPublishServiceIdsInBeacon < 0";
+ return false;
+ }
+ legacy_request->sid_beacon_val =
+ (aidl_request1.configParams.includePublishServiceIdsInBeacon ? 0x1 : 0x0) |
+ (aidl_request1.configParams.numberOfPublishServiceIdsInBeacon << 1);
+ legacy_request->config_subscribe_sid_beacon = 1;
+ if (aidl_request1.configParams.numberOfSubscribeServiceIdsInBeacon < 0) {
+ LOG(ERROR) << "convertAidlNanEnableRequestToLegacy: "
+ "numberOfSubscribeServiceIdsInBeacon < 0";
+ return false;
+ }
+ legacy_request->subscribe_sid_beacon_val =
+ (aidl_request1.configParams.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) |
+ (aidl_request1.configParams.numberOfSubscribeServiceIdsInBeacon << 1);
+ legacy_request->config_rssi_window_size = 1;
+ legacy_request->rssi_window_size_val = aidl_request1.configParams.rssiWindowSize;
+ legacy_request->config_disc_mac_addr_randomization = 1;
+ legacy_request->disc_mac_addr_rand_interval_sec =
+ aidl_request1.configParams.macAddressRandomizationIntervalSec;
+ legacy_request->config_2dot4g_rssi_close = 1;
+ if (aidl_request1.configParams.bandSpecificConfig.size() != 3) {
+ LOG(ERROR) << "convertAidlNanEnableRequestToLegacy: "
+ "bandSpecificConfig.size() != 3";
+ return false;
+ }
+ legacy_request->rssi_close_2dot4g_val =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+ .rssiClose;
+ legacy_request->config_2dot4g_rssi_middle = 1;
+ legacy_request->rssi_middle_2dot4g_val =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+ .rssiMiddle;
+ legacy_request->config_2dot4g_rssi_proximity = 1;
+ legacy_request->rssi_proximity_2dot4g_val =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+ .rssiCloseProximity;
+ legacy_request->config_scan_params = 1;
+ legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+ .dwellTimeMs;
+ legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+ .scanPeriodSec;
+ legacy_request->config_dw.config_2dot4g_dw_band =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+ .validDiscoveryWindowIntervalVal;
+ legacy_request->config_dw.dw_2dot4g_interval_val =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+ .discoveryWindowIntervalVal;
+ legacy_request->config_5g_rssi_close = 1;
+ legacy_request->rssi_close_5g_val =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .rssiClose;
+ legacy_request->config_5g_rssi_middle = 1;
+ legacy_request->rssi_middle_5g_val =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .rssiMiddle;
+ legacy_request->config_5g_rssi_close_proximity = 1;
+ legacy_request->rssi_close_proximity_5g_val =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .rssiCloseProximity;
+ legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .dwellTimeMs;
+ legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .scanPeriodSec;
+ legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .dwellTimeMs;
+ legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .scanPeriodSec;
+ legacy_request->config_dw.config_5g_dw_band =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .validDiscoveryWindowIntervalVal;
+ legacy_request->config_dw.dw_5g_interval_val =
+ aidl_request1.configParams.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .discoveryWindowIntervalVal;
+ if (aidl_request1.debugConfigs.validClusterIdVals) {
+ legacy_request->cluster_low = aidl_request1.debugConfigs.clusterIdBottomRangeVal;
+ legacy_request->cluster_high = aidl_request1.debugConfigs.clusterIdTopRangeVal;
+ } else { // need 'else' since not configurable in legacy HAL
+ legacy_request->cluster_low = 0x0000;
+ legacy_request->cluster_high = 0xFFFF;
+ }
+ legacy_request->config_intf_addr = aidl_request1.debugConfigs.validIntfAddrVal;
+ memcpy(legacy_request->intf_addr_val, aidl_request1.debugConfigs.intfAddrVal.data(), 6);
+ legacy_request->config_oui = aidl_request1.debugConfigs.validOuiVal;
+ legacy_request->oui_val = aidl_request1.debugConfigs.ouiVal;
+ legacy_request->config_random_factor_force =
+ aidl_request1.debugConfigs.validRandomFactorForceVal;
+ legacy_request->random_factor_force_val = aidl_request1.debugConfigs.randomFactorForceVal;
+ legacy_request->config_hop_count_force = aidl_request1.debugConfigs.validHopCountForceVal;
+ legacy_request->hop_count_force_val = aidl_request1.debugConfigs.hopCountForceVal;
+ legacy_request->config_24g_channel = aidl_request1.debugConfigs.validDiscoveryChannelVal;
+ legacy_request->channel_24g_val =
+ aidl_request1.debugConfigs.discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+ legacy_request->config_5g_channel = aidl_request1.debugConfigs.validDiscoveryChannelVal;
+ legacy_request->channel_5g_val =
+ aidl_request1.debugConfigs.discoveryChannelMhzVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+ legacy_request->config_2dot4g_beacons = aidl_request1.debugConfigs.validUseBeaconsInBandVal;
+ legacy_request->beacon_2dot4g_val =
+ aidl_request1.debugConfigs.useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+ legacy_request->config_5g_beacons = aidl_request1.debugConfigs.validUseBeaconsInBandVal;
+ legacy_request->beacon_5g_val =
+ aidl_request1.debugConfigs.useBeaconsInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+ legacy_request->config_2dot4g_sdf = aidl_request1.debugConfigs.validUseSdfInBandVal;
+ legacy_request->sdf_2dot4g_val =
+ aidl_request1.debugConfigs.useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_24GHZ];
+ legacy_request->config_5g_sdf = aidl_request1.debugConfigs.validUseSdfInBandVal;
+ legacy_request->sdf_5g_val =
+ aidl_request1.debugConfigs.useSdfInBandVal[(size_t)NanBandIndex::NAN_BAND_5GHZ];
+
+ legacy_request->config_discovery_beacon_int = 1;
+ legacy_request->discovery_beacon_interval = aidl_request2.discoveryBeaconIntervalMs;
+ legacy_request->config_nss = 1;
+ legacy_request->nss = aidl_request2.numberOfSpatialStreamsInDiscovery;
+ legacy_request->config_dw_early_termination = 1;
+ legacy_request->enable_dw_termination = aidl_request2.enableDiscoveryWindowEarlyTermination;
+ legacy_request->config_enable_ranging = 1;
+ legacy_request->enable_ranging = aidl_request2.enableRanging;
+
+ legacy_request->config_enable_instant_mode = 1;
+ legacy_request->enable_instant_mode = aidl_request2.enableInstantCommunicationMode;
+ legacy_request->config_instant_mode_channel = 1;
+ legacy_request->instant_mode_channel = aidl_request2.instantModeChannel;
+
+ return true;
+}
+
+bool convertAidlNanConfigRequestToLegacy(const NanConfigRequest& aidl_request1,
+ const NanConfigRequestSupplemental& aidl_request2,
+ legacy_hal::NanConfigRequest* legacy_request) {
+ if (!legacy_request) {
+ LOG(ERROR) << "convertAidlNanConfigRequestToLegacy: null legacy_request";
+ return false;
+ }
+ *legacy_request = {};
+
+ legacy_request->master_pref = aidl_request1.masterPref;
+ legacy_request->discovery_indication_cfg = 0;
+ legacy_request->discovery_indication_cfg |=
+ aidl_request1.disableDiscoveryAddressChangeIndication ? 0x1 : 0x0;
+ legacy_request->discovery_indication_cfg |=
+ aidl_request1.disableStartedClusterIndication ? 0x2 : 0x0;
+ legacy_request->discovery_indication_cfg |=
+ aidl_request1.disableJoinedClusterIndication ? 0x4 : 0x0;
+ legacy_request->config_sid_beacon = 1;
+ if (aidl_request1.numberOfPublishServiceIdsInBeacon < 0) {
+ LOG(ERROR) << "convertAidlNanConfigRequestToLegacy: "
+ "numberOfPublishServiceIdsInBeacon < 0";
+ return false;
+ }
+ legacy_request->sid_beacon = (aidl_request1.includePublishServiceIdsInBeacon ? 0x1 : 0x0) |
+ (aidl_request1.numberOfPublishServiceIdsInBeacon << 1);
+ legacy_request->config_subscribe_sid_beacon = 1;
+ if (aidl_request1.numberOfSubscribeServiceIdsInBeacon < 0) {
+ LOG(ERROR) << "convertAidlNanConfigRequestToLegacy: "
+ "numberOfSubscribeServiceIdsInBeacon < 0";
+ return false;
+ }
+ legacy_request->subscribe_sid_beacon_val =
+ (aidl_request1.includeSubscribeServiceIdsInBeacon ? 0x1 : 0x0) |
+ (aidl_request1.numberOfSubscribeServiceIdsInBeacon << 1);
+ legacy_request->config_rssi_window_size = 1;
+ legacy_request->rssi_window_size_val = aidl_request1.rssiWindowSize;
+ legacy_request->config_disc_mac_addr_randomization = 1;
+ legacy_request->disc_mac_addr_rand_interval_sec =
+ aidl_request1.macAddressRandomizationIntervalSec;
+
+ legacy_request->config_scan_params = 1;
+ legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_24G_BAND] =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ].dwellTimeMs;
+ legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_24G_BAND] =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ].scanPeriodSec;
+ legacy_request->config_dw.config_2dot4g_dw_band =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+ .validDiscoveryWindowIntervalVal;
+ legacy_request->config_dw.dw_2dot4g_interval_val =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_24GHZ]
+ .discoveryWindowIntervalVal;
+
+ legacy_request->config_5g_rssi_close_proximity = 1;
+ legacy_request->rssi_close_proximity_5g_val =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .rssiCloseProximity;
+ legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
+ legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_LOW] =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
+ legacy_request->scan_params_val.dwell_time[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].dwellTimeMs;
+ legacy_request->scan_params_val.scan_period[legacy_hal::NAN_CHANNEL_5G_BAND_HIGH] =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ].scanPeriodSec;
+ legacy_request->config_dw.config_5g_dw_band =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .validDiscoveryWindowIntervalVal;
+ legacy_request->config_dw.dw_5g_interval_val =
+ aidl_request1.bandSpecificConfig[(size_t)NanBandIndex::NAN_BAND_5GHZ]
+ .discoveryWindowIntervalVal;
+
+ legacy_request->config_discovery_beacon_int = 1;
+ legacy_request->discovery_beacon_interval = aidl_request2.discoveryBeaconIntervalMs;
+ legacy_request->config_nss = 1;
+ legacy_request->nss = aidl_request2.numberOfSpatialStreamsInDiscovery;
+ legacy_request->config_dw_early_termination = 1;
+ legacy_request->enable_dw_termination = aidl_request2.enableDiscoveryWindowEarlyTermination;
+ legacy_request->config_enable_ranging = 1;
+ legacy_request->enable_ranging = aidl_request2.enableRanging;
+
+ legacy_request->config_enable_instant_mode = 1;
+ legacy_request->enable_instant_mode = aidl_request2.enableInstantCommunicationMode;
+ legacy_request->config_instant_mode_channel = 1;
+ legacy_request->instant_mode_channel = aidl_request2.instantModeChannel;
+
+ return true;
+}
+
+bool convertAidlNanPublishRequestToLegacy(const NanPublishRequest& aidl_request,
+ legacy_hal::NanPublishRequest* legacy_request) {
+ if (!legacy_request) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: null legacy_request";
+ return false;
+ }
+ *legacy_request = {};
+
+ legacy_request->publish_id = aidl_request.baseConfigs.sessionId;
+ legacy_request->ttl = aidl_request.baseConfigs.ttlSec;
+ legacy_request->period = aidl_request.baseConfigs.discoveryWindowPeriod;
+ legacy_request->publish_count = aidl_request.baseConfigs.discoveryCount;
+ legacy_request->service_name_len = aidl_request.baseConfigs.serviceName.size();
+ if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: service_name_len "
+ "too large";
+ return false;
+ }
+ memcpy(legacy_request->service_name, aidl_request.baseConfigs.serviceName.data(),
+ legacy_request->service_name_len);
+ legacy_request->publish_match_indicator =
+ convertAidlNanMatchAlgToLegacy(aidl_request.baseConfigs.discoveryMatchIndicator);
+ legacy_request->service_specific_info_len = aidl_request.baseConfigs.serviceSpecificInfo.size();
+ if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: "
+ "service_specific_info_len too large";
+ return false;
+ }
+ memcpy(legacy_request->service_specific_info,
+ aidl_request.baseConfigs.serviceSpecificInfo.data(),
+ legacy_request->service_specific_info_len);
+ legacy_request->sdea_service_specific_info_len =
+ aidl_request.baseConfigs.extendedServiceSpecificInfo.size();
+ if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: "
+ "sdea_service_specific_info_len too large";
+ return false;
+ }
+ memcpy(legacy_request->sdea_service_specific_info,
+ aidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
+ legacy_request->sdea_service_specific_info_len);
+ legacy_request->rx_match_filter_len = aidl_request.baseConfigs.rxMatchFilter.size();
+ if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: "
+ "rx_match_filter_len too large";
+ return false;
+ }
+ memcpy(legacy_request->rx_match_filter, aidl_request.baseConfigs.rxMatchFilter.data(),
+ legacy_request->rx_match_filter_len);
+ legacy_request->tx_match_filter_len = aidl_request.baseConfigs.txMatchFilter.size();
+ if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: "
+ "tx_match_filter_len too large";
+ return false;
+ }
+ memcpy(legacy_request->tx_match_filter, aidl_request.baseConfigs.txMatchFilter.data(),
+ legacy_request->tx_match_filter_len);
+ legacy_request->rssi_threshold_flag = aidl_request.baseConfigs.useRssiThreshold;
+ legacy_request->recv_indication_cfg = 0;
+ legacy_request->recv_indication_cfg |=
+ aidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0;
+ legacy_request->recv_indication_cfg |=
+ aidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
+ legacy_request->recv_indication_cfg |=
+ aidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
+ legacy_request->recv_indication_cfg |= 0x8;
+ legacy_request->cipher_type = (unsigned int)aidl_request.baseConfigs.securityConfig.cipherType;
+
+ legacy_request->scid_len = aidl_request.baseConfigs.securityConfig.scid.size();
+ if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: scid_len too large";
+ return false;
+ }
+ memcpy(legacy_request->scid, aidl_request.baseConfigs.securityConfig.scid.data(),
+ legacy_request->scid_len);
+
+ if (aidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+ legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+ legacy_request->key_info.body.pmk_info.pmk_len =
+ aidl_request.baseConfigs.securityConfig.pmk.size();
+ if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: invalid pmk_len";
+ return false;
+ }
+ memcpy(legacy_request->key_info.body.pmk_info.pmk,
+ aidl_request.baseConfigs.securityConfig.pmk.data(),
+ legacy_request->key_info.body.pmk_info.pmk_len);
+ }
+ if (aidl_request.baseConfigs.securityConfig.securityType ==
+ NanDataPathSecurityType::PASSPHRASE) {
+ legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+ legacy_request->key_info.body.passphrase_info.passphrase_len =
+ aidl_request.baseConfigs.securityConfig.passphrase.size();
+ if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+ NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: "
+ "passphrase_len too small";
+ return false;
+ }
+ if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+ NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ LOG(ERROR) << "convertAidlNanPublishRequestToLegacy: "
+ "passphrase_len too large";
+ return false;
+ }
+ memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+ aidl_request.baseConfigs.securityConfig.passphrase.data(),
+ legacy_request->key_info.body.passphrase_info.passphrase_len);
+ }
+ legacy_request->sdea_params.security_cfg =
+ (aidl_request.baseConfigs.securityConfig.securityType != NanDataPathSecurityType::OPEN)
+ ? legacy_hal::NAN_DP_CONFIG_SECURITY
+ : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+
+ legacy_request->sdea_params.ranging_state = aidl_request.baseConfigs.rangingRequired
+ ? legacy_hal::NAN_RANGING_ENABLE
+ : legacy_hal::NAN_RANGING_DISABLE;
+ legacy_request->ranging_cfg.ranging_interval_msec = aidl_request.baseConfigs.rangingIntervalMs;
+ legacy_request->ranging_cfg.config_ranging_indications =
+ static_cast<uint32_t>(aidl_request.baseConfigs.configRangingIndications);
+ legacy_request->ranging_cfg.distance_ingress_mm =
+ aidl_request.baseConfigs.distanceIngressCm * 10;
+ legacy_request->ranging_cfg.distance_egress_mm = aidl_request.baseConfigs.distanceEgressCm * 10;
+ legacy_request->ranging_auto_response = aidl_request.baseConfigs.rangingRequired
+ ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
+ : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
+ legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT;
+ legacy_request->publish_type = convertAidlNanPublishTypeToLegacy(aidl_request.publishType);
+ legacy_request->tx_type = convertAidlNanTxTypeToLegacy(aidl_request.txType);
+ legacy_request->service_responder_policy = aidl_request.autoAcceptDataPathRequests
+ ? legacy_hal::NAN_SERVICE_ACCEPT_POLICY_ALL
+ : legacy_hal::NAN_SERVICE_ACCEPT_POLICY_NONE;
+
+ return true;
+}
+
+bool convertAidlNanSubscribeRequestToLegacy(const NanSubscribeRequest& aidl_request,
+ legacy_hal::NanSubscribeRequest* legacy_request) {
+ if (!legacy_request) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: legacy_request is null";
+ return false;
+ }
+ *legacy_request = {};
+
+ legacy_request->subscribe_id = aidl_request.baseConfigs.sessionId;
+ legacy_request->ttl = aidl_request.baseConfigs.ttlSec;
+ legacy_request->period = aidl_request.baseConfigs.discoveryWindowPeriod;
+ legacy_request->subscribe_count = aidl_request.baseConfigs.discoveryCount;
+ legacy_request->service_name_len = aidl_request.baseConfigs.serviceName.size();
+ if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: "
+ "service_name_len too large";
+ return false;
+ }
+ memcpy(legacy_request->service_name, aidl_request.baseConfigs.serviceName.data(),
+ legacy_request->service_name_len);
+ legacy_request->subscribe_match_indicator =
+ convertAidlNanMatchAlgToLegacy(aidl_request.baseConfigs.discoveryMatchIndicator);
+ legacy_request->service_specific_info_len = aidl_request.baseConfigs.serviceSpecificInfo.size();
+ if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: "
+ "service_specific_info_len too large";
+ return false;
+ }
+ memcpy(legacy_request->service_specific_info,
+ aidl_request.baseConfigs.serviceSpecificInfo.data(),
+ legacy_request->service_specific_info_len);
+ legacy_request->sdea_service_specific_info_len =
+ aidl_request.baseConfigs.extendedServiceSpecificInfo.size();
+ if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: "
+ "sdea_service_specific_info_len too large";
+ return false;
+ }
+ memcpy(legacy_request->sdea_service_specific_info,
+ aidl_request.baseConfigs.extendedServiceSpecificInfo.data(),
+ legacy_request->sdea_service_specific_info_len);
+ legacy_request->rx_match_filter_len = aidl_request.baseConfigs.rxMatchFilter.size();
+ if (legacy_request->rx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: "
+ "rx_match_filter_len too large";
+ return false;
+ }
+ memcpy(legacy_request->rx_match_filter, aidl_request.baseConfigs.rxMatchFilter.data(),
+ legacy_request->rx_match_filter_len);
+ legacy_request->tx_match_filter_len = aidl_request.baseConfigs.txMatchFilter.size();
+ if (legacy_request->tx_match_filter_len > NAN_MAX_MATCH_FILTER_LEN) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: "
+ "tx_match_filter_len too large";
+ return false;
+ }
+ memcpy(legacy_request->tx_match_filter, aidl_request.baseConfigs.txMatchFilter.data(),
+ legacy_request->tx_match_filter_len);
+ legacy_request->rssi_threshold_flag = aidl_request.baseConfigs.useRssiThreshold;
+ legacy_request->recv_indication_cfg = 0;
+ legacy_request->recv_indication_cfg |=
+ aidl_request.baseConfigs.disableDiscoveryTerminationIndication ? 0x1 : 0x0;
+ legacy_request->recv_indication_cfg |=
+ aidl_request.baseConfigs.disableMatchExpirationIndication ? 0x2 : 0x0;
+ legacy_request->recv_indication_cfg |=
+ aidl_request.baseConfigs.disableFollowupReceivedIndication ? 0x4 : 0x0;
+ legacy_request->cipher_type = (unsigned int)aidl_request.baseConfigs.securityConfig.cipherType;
+ if (aidl_request.baseConfigs.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+ legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+ legacy_request->key_info.body.pmk_info.pmk_len =
+ aidl_request.baseConfigs.securityConfig.pmk.size();
+ if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: invalid pmk_len";
+ return false;
+ }
+ memcpy(legacy_request->key_info.body.pmk_info.pmk,
+ aidl_request.baseConfigs.securityConfig.pmk.data(),
+ legacy_request->key_info.body.pmk_info.pmk_len);
+ }
+ if (aidl_request.baseConfigs.securityConfig.securityType ==
+ NanDataPathSecurityType::PASSPHRASE) {
+ legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+ legacy_request->key_info.body.passphrase_info.passphrase_len =
+ aidl_request.baseConfigs.securityConfig.passphrase.size();
+ if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+ NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: "
+ "passphrase_len too small";
+ return false;
+ }
+ if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+ NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: "
+ "passphrase_len too large";
+ return false;
+ }
+ memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+ aidl_request.baseConfigs.securityConfig.passphrase.data(),
+ legacy_request->key_info.body.passphrase_info.passphrase_len);
+ }
+ legacy_request->sdea_params.security_cfg =
+ (aidl_request.baseConfigs.securityConfig.securityType != NanDataPathSecurityType::OPEN)
+ ? legacy_hal::NAN_DP_CONFIG_SECURITY
+ : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+ legacy_request->sdea_params.ranging_state = aidl_request.baseConfigs.rangingRequired
+ ? legacy_hal::NAN_RANGING_ENABLE
+ : legacy_hal::NAN_RANGING_DISABLE;
+ legacy_request->ranging_cfg.ranging_interval_msec = aidl_request.baseConfigs.rangingIntervalMs;
+ legacy_request->ranging_cfg.config_ranging_indications =
+ static_cast<uint32_t>(aidl_request.baseConfigs.configRangingIndications);
+ legacy_request->ranging_cfg.distance_ingress_mm =
+ aidl_request.baseConfigs.distanceIngressCm * 10;
+ legacy_request->ranging_cfg.distance_egress_mm = aidl_request.baseConfigs.distanceEgressCm * 10;
+ legacy_request->ranging_auto_response = aidl_request.baseConfigs.rangingRequired
+ ? legacy_hal::NAN_RANGING_AUTO_RESPONSE_ENABLE
+ : legacy_hal::NAN_RANGING_AUTO_RESPONSE_DISABLE;
+ legacy_request->sdea_params.range_report = legacy_hal::NAN_DISABLE_RANGE_REPORT;
+ legacy_request->subscribe_type =
+ convertAidlNanSubscribeTypeToLegacy(aidl_request.subscribeType);
+ legacy_request->serviceResponseFilter = convertAidlNanSrfTypeToLegacy(aidl_request.srfType);
+ legacy_request->serviceResponseInclude = aidl_request.srfRespondIfInAddressSet
+ ? legacy_hal::NAN_SRF_INCLUDE_RESPOND
+ : legacy_hal::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
+ legacy_request->useServiceResponseFilter =
+ aidl_request.shouldUseSrf ? legacy_hal::NAN_USE_SRF : legacy_hal::NAN_DO_NOT_USE_SRF;
+ legacy_request->ssiRequiredForMatchIndication =
+ aidl_request.isSsiRequiredForMatch ? legacy_hal::NAN_SSI_REQUIRED_IN_MATCH_IND
+ : legacy_hal::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
+ legacy_request->num_intf_addr_present = aidl_request.intfAddr.size();
+ if (legacy_request->num_intf_addr_present > NAN_MAX_SUBSCRIBE_MAX_ADDRESS) {
+ LOG(ERROR) << "convertAidlNanSubscribeRequestToLegacy: "
+ "num_intf_addr_present - too many";
+ return false;
+ }
+ for (int i = 0; i < legacy_request->num_intf_addr_present; i++) {
+ memcpy(legacy_request->intf_addr[i], aidl_request.intfAddr[i].data.data(), 6);
+ }
+
+ return true;
+}
+
+bool convertAidlNanTransmitFollowupRequestToLegacy(
+ const NanTransmitFollowupRequest& aidl_request,
+ legacy_hal::NanTransmitFollowupRequest* legacy_request) {
+ if (!legacy_request) {
+ LOG(ERROR) << "convertAidlNanTransmitFollowupRequestToLegacy: "
+ "legacy_request is null";
+ return false;
+ }
+ *legacy_request = {};
+
+ legacy_request->publish_subscribe_id = aidl_request.discoverySessionId;
+ legacy_request->requestor_instance_id = aidl_request.peerId;
+ memcpy(legacy_request->addr, aidl_request.addr.data(), 6);
+ legacy_request->priority = aidl_request.isHighPriority ? legacy_hal::NAN_TX_PRIORITY_HIGH
+ : legacy_hal::NAN_TX_PRIORITY_NORMAL;
+ legacy_request->dw_or_faw = aidl_request.shouldUseDiscoveryWindow
+ ? legacy_hal::NAN_TRANSMIT_IN_DW
+ : legacy_hal::NAN_TRANSMIT_IN_FAW;
+ legacy_request->service_specific_info_len = aidl_request.serviceSpecificInfo.size();
+ if (legacy_request->service_specific_info_len > NAN_MAX_SERVICE_SPECIFIC_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanTransmitFollowupRequestToLegacy: "
+ "service_specific_info_len too large";
+ return false;
+ }
+ memcpy(legacy_request->service_specific_info, aidl_request.serviceSpecificInfo.data(),
+ legacy_request->service_specific_info_len);
+ legacy_request->sdea_service_specific_info_len =
+ aidl_request.extendedServiceSpecificInfo.size();
+ if (legacy_request->sdea_service_specific_info_len > NAN_MAX_SDEA_SERVICE_SPECIFIC_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanTransmitFollowupRequestToLegacy: "
+ "sdea_service_specific_info_len too large";
+ return false;
+ }
+ memcpy(legacy_request->sdea_service_specific_info,
+ aidl_request.extendedServiceSpecificInfo.data(),
+ legacy_request->sdea_service_specific_info_len);
+ legacy_request->recv_indication_cfg = aidl_request.disableFollowupResultIndication ? 0x1 : 0x0;
+
+ return true;
+}
+
+bool convertAidlNanDataPathInitiatorRequestToLegacy(
+ const NanInitiateDataPathRequest& aidl_request,
+ legacy_hal::NanDataPathInitiatorRequest* legacy_request) {
+ if (!legacy_request) {
+ LOG(ERROR) << "convertAidlNanDataPathInitiatorRequestToLegacy: "
+ "legacy_request is null";
+ return false;
+ }
+ *legacy_request = {};
+
+ legacy_request->requestor_instance_id = aidl_request.peerId;
+ memcpy(legacy_request->peer_disc_mac_addr, aidl_request.peerDiscMacAddr.data(), 6);
+ legacy_request->channel_request_type =
+ convertAidlNanDataPathChannelCfgToLegacy(aidl_request.channelRequestType);
+ legacy_request->channel = aidl_request.channel;
+ if (strnlen(aidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
+ LOG(ERROR) << "convertAidlNanDataPathInitiatorRequestToLegacy: "
+ "ifaceName too long";
+ return false;
+ }
+ strlcpy(legacy_request->ndp_iface, aidl_request.ifaceName.c_str(), IFNAMSIZ + 1);
+ legacy_request->ndp_cfg.security_cfg =
+ (aidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN)
+ ? legacy_hal::NAN_DP_CONFIG_SECURITY
+ : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+ legacy_request->app_info.ndp_app_info_len = aidl_request.appInfo.size();
+ if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathInitiatorRequestToLegacy: "
+ "ndp_app_info_len too large";
+ return false;
+ }
+ memcpy(legacy_request->app_info.ndp_app_info, aidl_request.appInfo.data(),
+ legacy_request->app_info.ndp_app_info_len);
+ legacy_request->cipher_type = (unsigned int)aidl_request.securityConfig.cipherType;
+ if (aidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+ legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+ legacy_request->key_info.body.pmk_info.pmk_len = aidl_request.securityConfig.pmk.size();
+ if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathInitiatorRequestToLegacy: "
+ "invalid pmk_len";
+ return false;
+ }
+ memcpy(legacy_request->key_info.body.pmk_info.pmk, aidl_request.securityConfig.pmk.data(),
+ legacy_request->key_info.body.pmk_info.pmk_len);
+ }
+ if (aidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
+ legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+ legacy_request->key_info.body.passphrase_info.passphrase_len =
+ aidl_request.securityConfig.passphrase.size();
+ if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+ NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathInitiatorRequestToLegacy: "
+ "passphrase_len too small";
+ return false;
+ }
+ if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+ NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathInitiatorRequestToLegacy: "
+ "passphrase_len too large";
+ return false;
+ }
+ memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+ aidl_request.securityConfig.passphrase.data(),
+ legacy_request->key_info.body.passphrase_info.passphrase_len);
+ }
+ legacy_request->service_name_len = aidl_request.serviceNameOutOfBand.size();
+ if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathInitiatorRequestToLegacy: "
+ "service_name_len too large";
+ return false;
+ }
+ memcpy(legacy_request->service_name, aidl_request.serviceNameOutOfBand.data(),
+ legacy_request->service_name_len);
+ legacy_request->scid_len = aidl_request.securityConfig.scid.size();
+ if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathInitiatorRequestToLegacy: scid_len too large";
+ return false;
+ }
+ memcpy(legacy_request->scid, aidl_request.securityConfig.scid.data(), legacy_request->scid_len);
+
+ return true;
+}
+
+bool convertAidlNanDataPathIndicationResponseToLegacy(
+ const NanRespondToDataPathIndicationRequest& aidl_request,
+ legacy_hal::NanDataPathIndicationResponse* legacy_request) {
+ if (!legacy_request) {
+ LOG(ERROR) << "convertAidlNanDataPathIndicationResponseToLegacy: "
+ "legacy_request is null";
+ return false;
+ }
+ *legacy_request = {};
+
+ legacy_request->rsp_code = aidl_request.acceptRequest ? legacy_hal::NAN_DP_REQUEST_ACCEPT
+ : legacy_hal::NAN_DP_REQUEST_REJECT;
+ legacy_request->ndp_instance_id = aidl_request.ndpInstanceId;
+ if (strnlen(aidl_request.ifaceName.c_str(), IFNAMSIZ + 1) == IFNAMSIZ + 1) {
+ LOG(ERROR) << "convertAidlNanDataPathIndicationResponseToLegacy: "
+ "ifaceName too long";
+ return false;
+ }
+ strlcpy(legacy_request->ndp_iface, aidl_request.ifaceName.c_str(), IFNAMSIZ + 1);
+ legacy_request->ndp_cfg.security_cfg =
+ (aidl_request.securityConfig.securityType != NanDataPathSecurityType::OPEN)
+ ? legacy_hal::NAN_DP_CONFIG_SECURITY
+ : legacy_hal::NAN_DP_CONFIG_NO_SECURITY;
+ legacy_request->app_info.ndp_app_info_len = aidl_request.appInfo.size();
+ if (legacy_request->app_info.ndp_app_info_len > NAN_DP_MAX_APP_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathIndicationResponseToLegacy: "
+ "ndp_app_info_len too large";
+ return false;
+ }
+ memcpy(legacy_request->app_info.ndp_app_info, aidl_request.appInfo.data(),
+ legacy_request->app_info.ndp_app_info_len);
+ legacy_request->cipher_type = (unsigned int)aidl_request.securityConfig.cipherType;
+ if (aidl_request.securityConfig.securityType == NanDataPathSecurityType::PMK) {
+ legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PMK;
+ legacy_request->key_info.body.pmk_info.pmk_len = aidl_request.securityConfig.pmk.size();
+ if (legacy_request->key_info.body.pmk_info.pmk_len != NAN_PMK_INFO_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathIndicationResponseToLegacy: "
+ "invalid pmk_len";
+ return false;
+ }
+ memcpy(legacy_request->key_info.body.pmk_info.pmk, aidl_request.securityConfig.pmk.data(),
+ legacy_request->key_info.body.pmk_info.pmk_len);
+ }
+ if (aidl_request.securityConfig.securityType == NanDataPathSecurityType::PASSPHRASE) {
+ legacy_request->key_info.key_type = legacy_hal::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+ legacy_request->key_info.body.passphrase_info.passphrase_len =
+ aidl_request.securityConfig.passphrase.size();
+ if (legacy_request->key_info.body.passphrase_info.passphrase_len <
+ NAN_SECURITY_MIN_PASSPHRASE_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathIndicationResponseToLegacy: "
+ "passphrase_len too small";
+ return false;
+ }
+ if (legacy_request->key_info.body.passphrase_info.passphrase_len >
+ NAN_SECURITY_MAX_PASSPHRASE_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathIndicationResponseToLegacy: "
+ "passphrase_len too large";
+ return false;
+ }
+ memcpy(legacy_request->key_info.body.passphrase_info.passphrase,
+ aidl_request.securityConfig.passphrase.data(),
+ legacy_request->key_info.body.passphrase_info.passphrase_len);
+ }
+ legacy_request->service_name_len = aidl_request.serviceNameOutOfBand.size();
+ if (legacy_request->service_name_len > NAN_MAX_SERVICE_NAME_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathIndicationResponseToLegacy: "
+ "service_name_len too large";
+ return false;
+ }
+ memcpy(legacy_request->service_name, aidl_request.serviceNameOutOfBand.data(),
+ legacy_request->service_name_len);
+ legacy_request->scid_len = aidl_request.securityConfig.scid.size();
+ if (legacy_request->scid_len > NAN_MAX_SCID_BUF_LEN) {
+ LOG(ERROR) << "convertAidlNanDataPathIndicationResponseToLegacy: scid_len too large";
+ return false;
+ }
+ memcpy(legacy_request->scid, aidl_request.securityConfig.scid.data(), legacy_request->scid_len);
+
+ return true;
+}
+
+bool convertLegacyNanResponseHeaderToAidl(const legacy_hal::NanResponseMsg& legacy_response,
+ NanStatus* nanStatus) {
+ if (!nanStatus) {
+ LOG(ERROR) << "convertLegacyNanResponseHeaderToAidl: nanStatus is null";
+ return false;
+ }
+ *nanStatus = {};
+
+ convertToNanStatus(legacy_response.status, legacy_response.nan_error,
+ sizeof(legacy_response.nan_error), nanStatus);
+ return true;
+}
+
+bool convertLegacyNanCapabilitiesResponseToAidl(const legacy_hal::NanCapabilities& legacy_response,
+ NanCapabilities* aidl_response) {
+ if (!aidl_response) {
+ LOG(ERROR) << "convertLegacyNanCapabilitiesResponseToAidl: "
+ "aidl_response is null";
+ return false;
+ }
+ *aidl_response = {};
+
+ aidl_response->maxConcurrentClusters = legacy_response.max_concurrent_nan_clusters;
+ aidl_response->maxPublishes = legacy_response.max_publishes;
+ aidl_response->maxSubscribes = legacy_response.max_subscribes;
+ aidl_response->maxServiceNameLen = legacy_response.max_service_name_len;
+ aidl_response->maxMatchFilterLen = legacy_response.max_match_filter_len;
+ aidl_response->maxTotalMatchFilterLen = legacy_response.max_total_match_filter_len;
+ aidl_response->maxServiceSpecificInfoLen = legacy_response.max_service_specific_info_len;
+ aidl_response->maxExtendedServiceSpecificInfoLen =
+ legacy_response.max_sdea_service_specific_info_len;
+ aidl_response->maxNdiInterfaces = legacy_response.max_ndi_interfaces;
+ aidl_response->maxNdpSessions = legacy_response.max_ndp_sessions;
+ aidl_response->maxAppInfoLen = legacy_response.max_app_info_len;
+ aidl_response->maxQueuedTransmitFollowupMsgs =
+ legacy_response.max_queued_transmit_followup_msgs;
+ aidl_response->maxSubscribeInterfaceAddresses = legacy_response.max_subscribe_address;
+ aidl_response->supportedCipherSuites =
+ static_cast<NanCipherSuiteType>(legacy_response.cipher_suites_supported);
+ aidl_response->instantCommunicationModeSupportFlag = legacy_response.is_instant_mode_supported;
+
+ return true;
+}
+
+bool convertLegacyNanMatchIndToAidl(const legacy_hal::NanMatchInd& legacy_ind,
+ NanMatchInd* aidl_ind) {
+ if (!aidl_ind) {
+ LOG(ERROR) << "convertLegacyNanMatchIndToAidl: aidl_ind is null";
+ return false;
+ }
+ *aidl_ind = {};
+
+ aidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
+ aidl_ind->peerId = legacy_ind.requestor_instance_id;
+ aidl_ind->addr = std::array<uint8_t, 6>();
+ std::copy(legacy_ind.addr, legacy_ind.addr + 6, std::begin(aidl_ind->addr));
+ aidl_ind->serviceSpecificInfo = std::vector<uint8_t>(
+ legacy_ind.service_specific_info,
+ legacy_ind.service_specific_info + legacy_ind.service_specific_info_len);
+ aidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>(
+ legacy_ind.sdea_service_specific_info,
+ legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len);
+ aidl_ind->matchFilter =
+ std::vector<uint8_t>(legacy_ind.sdf_match_filter,
+ legacy_ind.sdf_match_filter + legacy_ind.sdf_match_filter_len);
+ aidl_ind->matchOccurredInBeaconFlag = legacy_ind.match_occured_flag == 1; // NOTYPO
+ aidl_ind->outOfResourceFlag = legacy_ind.out_of_resource_flag == 1;
+ aidl_ind->rssiValue = legacy_ind.rssi_value;
+ aidl_ind->peerCipherType = (NanCipherSuiteType)legacy_ind.peer_cipher_type;
+ aidl_ind->peerRequiresSecurityEnabledInNdp =
+ legacy_ind.peer_sdea_params.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
+ aidl_ind->peerRequiresRanging =
+ legacy_ind.peer_sdea_params.ranging_state == legacy_hal::NAN_RANGING_ENABLE;
+ aidl_ind->rangingMeasurementInMm = legacy_ind.range_info.range_measurement_mm;
+ aidl_ind->rangingIndicationType =
+ static_cast<NanRangingIndication>(legacy_ind.range_info.ranging_event_type);
+ aidl_ind->scid = std::vector<uint8_t>(legacy_ind.scid, legacy_ind.scid + legacy_ind.scid_len);
+ return true;
+}
+
+bool convertLegacyNanFollowupIndToAidl(const legacy_hal::NanFollowupInd& legacy_ind,
+ NanFollowupReceivedInd* aidl_ind) {
+ if (!aidl_ind) {
+ LOG(ERROR) << "convertLegacyNanFollowupIndToAidl: aidl_ind is null";
+ return false;
+ }
+ *aidl_ind = {};
+
+ aidl_ind->discoverySessionId = legacy_ind.publish_subscribe_id;
+ aidl_ind->peerId = legacy_ind.requestor_instance_id;
+ aidl_ind->addr = std::array<uint8_t, 6>();
+ std::copy(legacy_ind.addr, legacy_ind.addr + 6, std::begin(aidl_ind->addr));
+ aidl_ind->receivedInFaw = legacy_ind.dw_or_faw == 1;
+ aidl_ind->serviceSpecificInfo = std::vector<uint8_t>(
+ legacy_ind.service_specific_info,
+ legacy_ind.service_specific_info + legacy_ind.service_specific_info_len);
+ aidl_ind->extendedServiceSpecificInfo = std::vector<uint8_t>(
+ legacy_ind.sdea_service_specific_info,
+ legacy_ind.sdea_service_specific_info + legacy_ind.sdea_service_specific_info_len);
+
+ return true;
+}
+
+bool convertLegacyNanDataPathRequestIndToAidl(const legacy_hal::NanDataPathRequestInd& legacy_ind,
+ NanDataPathRequestInd* aidl_ind) {
+ if (!aidl_ind) {
+ LOG(ERROR) << "convertLegacyNanDataPathRequestIndToAidl: aidl_ind is null";
+ return false;
+ }
+ *aidl_ind = {};
+
+ aidl_ind->discoverySessionId = legacy_ind.service_instance_id;
+ aidl_ind->peerDiscMacAddr = std::array<uint8_t, 6>();
+ std::copy(legacy_ind.peer_disc_mac_addr, legacy_ind.peer_disc_mac_addr + 6,
+ std::begin(aidl_ind->peerDiscMacAddr));
+ aidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
+ aidl_ind->securityRequired =
+ legacy_ind.ndp_cfg.security_cfg == legacy_hal::NAN_DP_CONFIG_SECURITY;
+ aidl_ind->appInfo = std::vector<uint8_t>(
+ legacy_ind.app_info.ndp_app_info,
+ legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len);
+
+ return true;
+}
+
+bool convertLegacyNdpChannelInfoToAidl(const legacy_hal::NanChannelInfo& legacy_struct,
+ NanDataPathChannelInfo* aidl_struct) {
+ if (!aidl_struct) {
+ LOG(ERROR) << "convertLegacyNdpChannelInfoToAidl: aidl_struct is null";
+ return false;
+ }
+ *aidl_struct = {};
+
+ aidl_struct->channelFreq = legacy_struct.channel;
+ aidl_struct->channelBandwidth = convertLegacyWifiChannelWidthToAidl(
+ (legacy_hal::wifi_channel_width)legacy_struct.bandwidth);
+ aidl_struct->numSpatialStreams = legacy_struct.nss;
+
+ return true;
+}
+
+bool convertLegacyNanDataPathConfirmIndToAidl(const legacy_hal::NanDataPathConfirmInd& legacy_ind,
+ NanDataPathConfirmInd* aidl_ind) {
+ if (!aidl_ind) {
+ LOG(ERROR) << "convertLegacyNanDataPathConfirmIndToAidl: aidl_ind is null";
+ return false;
+ }
+ *aidl_ind = {};
+
+ aidl_ind->ndpInstanceId = legacy_ind.ndp_instance_id;
+ aidl_ind->dataPathSetupSuccess = legacy_ind.rsp_code == legacy_hal::NAN_DP_REQUEST_ACCEPT;
+ aidl_ind->peerNdiMacAddr = std::array<uint8_t, 6>();
+ std::copy(legacy_ind.peer_ndi_mac_addr, legacy_ind.peer_ndi_mac_addr + 6,
+ std::begin(aidl_ind->peerNdiMacAddr));
+ aidl_ind->appInfo = std::vector<uint8_t>(
+ legacy_ind.app_info.ndp_app_info,
+ legacy_ind.app_info.ndp_app_info + legacy_ind.app_info.ndp_app_info_len);
+ aidl_ind->status.status = convertLegacyNanStatusTypeToAidl(legacy_ind.reason_code);
+ aidl_ind->status.description = "";
+
+ std::vector<NanDataPathChannelInfo> channelInfo;
+ for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
+ NanDataPathChannelInfo aidl_struct;
+ if (!convertLegacyNdpChannelInfoToAidl(legacy_ind.channel_info[i], &aidl_struct)) {
+ return false;
+ }
+ channelInfo.push_back(aidl_struct);
+ }
+ aidl_ind->channelInfo = channelInfo;
+
+ return true;
+}
+
+bool convertLegacyNanDataPathScheduleUpdateIndToAidl(
+ const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
+ NanDataPathScheduleUpdateInd* aidl_ind) {
+ if (!aidl_ind) {
+ LOG(ERROR) << "convertLegacyNanDataPathScheduleUpdateIndToAidl: "
+ "aidl_ind is null";
+ return false;
+ }
+ *aidl_ind = {};
+
+ aidl_ind->peerDiscoveryAddress = std::array<uint8_t, 6>();
+ std::copy(legacy_ind.peer_mac_addr, legacy_ind.peer_mac_addr + 6,
+ std::begin(aidl_ind->peerDiscoveryAddress));
+ std::vector<NanDataPathChannelInfo> channelInfo;
+ for (unsigned int i = 0; i < legacy_ind.num_channels; ++i) {
+ NanDataPathChannelInfo aidl_struct;
+ if (!convertLegacyNdpChannelInfoToAidl(legacy_ind.channel_info[i], &aidl_struct)) {
+ return false;
+ }
+ channelInfo.push_back(aidl_struct);
+ }
+ aidl_ind->channelInfo = channelInfo;
+ std::vector<uint32_t> ndpInstanceIds;
+ for (unsigned int i = 0; i < legacy_ind.num_ndp_instances; ++i) {
+ ndpInstanceIds.push_back(legacy_ind.ndp_instance_id[i]);
+ }
+ aidl_ind->ndpInstanceIds = uintToIntVec(ndpInstanceIds);
+
+ return true;
+}
+
+legacy_hal::wifi_rtt_type convertAidlRttTypeToLegacy(RttType type) {
+ switch (type) {
+ case RttType::ONE_SIDED:
+ return legacy_hal::RTT_TYPE_1_SIDED;
+ case RttType::TWO_SIDED:
+ return legacy_hal::RTT_TYPE_2_SIDED;
+ };
+ CHECK(false);
+}
+
+RttType convertLegacyRttTypeToAidl(legacy_hal::wifi_rtt_type type) {
+ switch (type) {
+ case legacy_hal::RTT_TYPE_1_SIDED:
+ return RttType::ONE_SIDED;
+ case legacy_hal::RTT_TYPE_2_SIDED:
+ return RttType::TWO_SIDED;
+ };
+ CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::rtt_peer_type convertAidlRttPeerTypeToLegacy(RttPeerType type) {
+ switch (type) {
+ case RttPeerType::AP:
+ return legacy_hal::RTT_PEER_AP;
+ case RttPeerType::STA:
+ return legacy_hal::RTT_PEER_STA;
+ case RttPeerType::P2P_GO:
+ return legacy_hal::RTT_PEER_P2P_GO;
+ case RttPeerType::P2P_CLIENT:
+ return legacy_hal::RTT_PEER_P2P_CLIENT;
+ case RttPeerType::NAN_TYPE:
+ return legacy_hal::RTT_PEER_NAN;
+ };
+ CHECK(false);
+}
+
+legacy_hal::wifi_channel_width convertAidlWifiChannelWidthToLegacy(WifiChannelWidthInMhz type) {
+ switch (type) {
+ case WifiChannelWidthInMhz::WIDTH_20:
+ return legacy_hal::WIFI_CHAN_WIDTH_20;
+ case WifiChannelWidthInMhz::WIDTH_40:
+ return legacy_hal::WIFI_CHAN_WIDTH_40;
+ case WifiChannelWidthInMhz::WIDTH_80:
+ return legacy_hal::WIFI_CHAN_WIDTH_80;
+ case WifiChannelWidthInMhz::WIDTH_160:
+ return legacy_hal::WIFI_CHAN_WIDTH_160;
+ case WifiChannelWidthInMhz::WIDTH_80P80:
+ return legacy_hal::WIFI_CHAN_WIDTH_80P80;
+ case WifiChannelWidthInMhz::WIDTH_5:
+ return legacy_hal::WIFI_CHAN_WIDTH_5;
+ case WifiChannelWidthInMhz::WIDTH_10:
+ return legacy_hal::WIFI_CHAN_WIDTH_10;
+ case WifiChannelWidthInMhz::WIDTH_320:
+ return legacy_hal::WIFI_CHAN_WIDTH_320;
+ case WifiChannelWidthInMhz::WIDTH_INVALID:
+ return legacy_hal::WIFI_CHAN_WIDTH_INVALID;
+ };
+ CHECK(false);
+}
+
+WifiChannelWidthInMhz convertLegacyWifiChannelWidthToAidl(legacy_hal::wifi_channel_width type) {
+ switch (type) {
+ case legacy_hal::WIFI_CHAN_WIDTH_20:
+ return WifiChannelWidthInMhz::WIDTH_20;
+ case legacy_hal::WIFI_CHAN_WIDTH_40:
+ return WifiChannelWidthInMhz::WIDTH_40;
+ case legacy_hal::WIFI_CHAN_WIDTH_80:
+ return WifiChannelWidthInMhz::WIDTH_80;
+ case legacy_hal::WIFI_CHAN_WIDTH_160:
+ return WifiChannelWidthInMhz::WIDTH_160;
+ case legacy_hal::WIFI_CHAN_WIDTH_80P80:
+ return WifiChannelWidthInMhz::WIDTH_80P80;
+ case legacy_hal::WIFI_CHAN_WIDTH_5:
+ return WifiChannelWidthInMhz::WIDTH_5;
+ case legacy_hal::WIFI_CHAN_WIDTH_10:
+ return WifiChannelWidthInMhz::WIDTH_10;
+ case legacy_hal::WIFI_CHAN_WIDTH_320:
+ return WifiChannelWidthInMhz::WIDTH_320;
+ default:
+ return WifiChannelWidthInMhz::WIDTH_INVALID;
+ };
+}
+
+legacy_hal::wifi_rtt_preamble convertAidlRttPreambleToLegacy(RttPreamble type) {
+ switch (type) {
+ case RttPreamble::LEGACY:
+ return legacy_hal::WIFI_RTT_PREAMBLE_LEGACY;
+ case RttPreamble::HT:
+ return legacy_hal::WIFI_RTT_PREAMBLE_HT;
+ case RttPreamble::VHT:
+ return legacy_hal::WIFI_RTT_PREAMBLE_VHT;
+ case RttPreamble::HE:
+ return legacy_hal::WIFI_RTT_PREAMBLE_HE;
+ case RttPreamble::EHT:
+ return legacy_hal::WIFI_RTT_PREAMBLE_EHT;
+ };
+ CHECK(false);
+}
+
+RttPreamble convertLegacyRttPreambleToAidl(legacy_hal::wifi_rtt_preamble type) {
+ switch (type) {
+ case legacy_hal::WIFI_RTT_PREAMBLE_LEGACY:
+ return RttPreamble::LEGACY;
+ case legacy_hal::WIFI_RTT_PREAMBLE_HT:
+ return RttPreamble::HT;
+ case legacy_hal::WIFI_RTT_PREAMBLE_VHT:
+ return RttPreamble::VHT;
+ case legacy_hal::WIFI_RTT_PREAMBLE_HE:
+ return RttPreamble::HE;
+ case legacy_hal::WIFI_RTT_PREAMBLE_EHT:
+ return RttPreamble::EHT;
+ };
+ CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::wifi_rtt_bw convertAidlRttBwToLegacy(RttBw type) {
+ switch (type) {
+ case RttBw::BW_5MHZ:
+ return legacy_hal::WIFI_RTT_BW_5;
+ case RttBw::BW_10MHZ:
+ return legacy_hal::WIFI_RTT_BW_10;
+ case RttBw::BW_20MHZ:
+ return legacy_hal::WIFI_RTT_BW_20;
+ case RttBw::BW_40MHZ:
+ return legacy_hal::WIFI_RTT_BW_40;
+ case RttBw::BW_80MHZ:
+ return legacy_hal::WIFI_RTT_BW_80;
+ case RttBw::BW_160MHZ:
+ return legacy_hal::WIFI_RTT_BW_160;
+ case RttBw::BW_320MHZ:
+ return legacy_hal::WIFI_RTT_BW_320;
+ };
+ CHECK(false);
+}
+
+RttBw convertLegacyRttBwToAidl(legacy_hal::wifi_rtt_bw type) {
+ switch (type) {
+ case legacy_hal::WIFI_RTT_BW_5:
+ return RttBw::BW_5MHZ;
+ case legacy_hal::WIFI_RTT_BW_10:
+ return RttBw::BW_10MHZ;
+ case legacy_hal::WIFI_RTT_BW_20:
+ return RttBw::BW_20MHZ;
+ case legacy_hal::WIFI_RTT_BW_40:
+ return RttBw::BW_40MHZ;
+ case legacy_hal::WIFI_RTT_BW_80:
+ return RttBw::BW_80MHZ;
+ case legacy_hal::WIFI_RTT_BW_160:
+ return RttBw::BW_160MHZ;
+ case legacy_hal::WIFI_RTT_BW_320:
+ return RttBw::BW_320MHZ;
+ };
+ CHECK(false) << "Unknown legacy type: " << type;
+}
+
+legacy_hal::wifi_motion_pattern convertAidlRttMotionPatternToLegacy(RttMotionPattern type) {
+ switch (type) {
+ case RttMotionPattern::NOT_EXPECTED:
+ return legacy_hal::WIFI_MOTION_NOT_EXPECTED;
+ case RttMotionPattern::EXPECTED:
+ return legacy_hal::WIFI_MOTION_EXPECTED;
+ case RttMotionPattern::UNKNOWN:
+ return legacy_hal::WIFI_MOTION_UNKNOWN;
+ };
+ CHECK(false);
+}
+
+WifiRatePreamble convertLegacyWifiRatePreambleToAidl(uint8_t preamble) {
+ switch (preamble) {
+ case 0:
+ return WifiRatePreamble::OFDM;
+ case 1:
+ return WifiRatePreamble::CCK;
+ case 2:
+ return WifiRatePreamble::HT;
+ case 3:
+ return WifiRatePreamble::VHT;
+ case 4:
+ return WifiRatePreamble::HE;
+ case 5:
+ return WifiRatePreamble::EHT;
+ default:
+ return WifiRatePreamble::RESERVED;
+ };
+ CHECK(false) << "Unknown legacy preamble: " << preamble;
+}
+
+WifiRateNss convertLegacyWifiRateNssToAidl(uint8_t nss) {
+ switch (nss) {
+ case 0:
+ return WifiRateNss::NSS_1x1;
+ case 1:
+ return WifiRateNss::NSS_2x2;
+ case 2:
+ return WifiRateNss::NSS_3x3;
+ case 3:
+ return WifiRateNss::NSS_4x4;
+ };
+ CHECK(false) << "Unknown legacy nss: " << nss;
+ return {};
+}
+
+RttStatus convertLegacyRttStatusToAidl(legacy_hal::wifi_rtt_status status) {
+ switch (status) {
+ case legacy_hal::RTT_STATUS_SUCCESS:
+ return RttStatus::SUCCESS;
+ case legacy_hal::RTT_STATUS_FAILURE:
+ return RttStatus::FAILURE;
+ case legacy_hal::RTT_STATUS_FAIL_NO_RSP:
+ return RttStatus::FAIL_NO_RSP;
+ case legacy_hal::RTT_STATUS_FAIL_REJECTED:
+ return RttStatus::FAIL_REJECTED;
+ case legacy_hal::RTT_STATUS_FAIL_NOT_SCHEDULED_YET:
+ return RttStatus::FAIL_NOT_SCHEDULED_YET;
+ case legacy_hal::RTT_STATUS_FAIL_TM_TIMEOUT:
+ return RttStatus::FAIL_TM_TIMEOUT;
+ case legacy_hal::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL:
+ return RttStatus::FAIL_AP_ON_DIFF_CHANNEL;
+ case legacy_hal::RTT_STATUS_FAIL_NO_CAPABILITY:
+ return RttStatus::FAIL_NO_CAPABILITY;
+ case legacy_hal::RTT_STATUS_ABORTED:
+ return RttStatus::ABORTED;
+ case legacy_hal::RTT_STATUS_FAIL_INVALID_TS:
+ return RttStatus::FAIL_INVALID_TS;
+ case legacy_hal::RTT_STATUS_FAIL_PROTOCOL:
+ return RttStatus::FAIL_PROTOCOL;
+ case legacy_hal::RTT_STATUS_FAIL_SCHEDULE:
+ return RttStatus::FAIL_SCHEDULE;
+ case legacy_hal::RTT_STATUS_FAIL_BUSY_TRY_LATER:
+ return RttStatus::FAIL_BUSY_TRY_LATER;
+ case legacy_hal::RTT_STATUS_INVALID_REQ:
+ return RttStatus::INVALID_REQ;
+ case legacy_hal::RTT_STATUS_NO_WIFI:
+ return RttStatus::NO_WIFI;
+ case legacy_hal::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE:
+ return RttStatus::FAIL_FTM_PARAM_OVERRIDE;
+ case legacy_hal::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE:
+ return RttStatus::NAN_RANGING_PROTOCOL_FAILURE;
+ case legacy_hal::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED:
+ return RttStatus::NAN_RANGING_CONCURRENCY_NOT_SUPPORTED;
+ };
+ CHECK(false) << "Unknown legacy status: " << status;
+}
+
+bool convertAidlWifiChannelInfoToLegacy(const WifiChannelInfo& aidl_info,
+ legacy_hal::wifi_channel_info* legacy_info) {
+ if (!legacy_info) {
+ return false;
+ }
+ *legacy_info = {};
+ legacy_info->width = convertAidlWifiChannelWidthToLegacy(aidl_info.width);
+ legacy_info->center_freq = aidl_info.centerFreq;
+ legacy_info->center_freq0 = aidl_info.centerFreq0;
+ legacy_info->center_freq1 = aidl_info.centerFreq1;
+ return true;
+}
+
+bool convertLegacyWifiChannelInfoToAidl(const legacy_hal::wifi_channel_info& legacy_info,
+ WifiChannelInfo* aidl_info) {
+ if (!aidl_info) {
+ return false;
+ }
+ *aidl_info = {};
+ aidl_info->width = convertLegacyWifiChannelWidthToAidl(legacy_info.width);
+ aidl_info->centerFreq = legacy_info.center_freq;
+ aidl_info->centerFreq0 = legacy_info.center_freq0;
+ aidl_info->centerFreq1 = legacy_info.center_freq1;
+ return true;
+}
+
+bool convertAidlRttConfigToLegacy(const RttConfig& aidl_config,
+ legacy_hal::wifi_rtt_config* legacy_config) {
+ if (!legacy_config) {
+ return false;
+ }
+ *legacy_config = {};
+ CHECK(aidl_config.addr.size() == sizeof(legacy_config->addr));
+ memcpy(legacy_config->addr, aidl_config.addr.data(), aidl_config.addr.size());
+ legacy_config->type = convertAidlRttTypeToLegacy(aidl_config.type);
+ legacy_config->peer = convertAidlRttPeerTypeToLegacy(aidl_config.peer);
+ if (!convertAidlWifiChannelInfoToLegacy(aidl_config.channel, &legacy_config->channel)) {
+ return false;
+ }
+ legacy_config->burst_period = aidl_config.burstPeriod;
+ legacy_config->num_burst = aidl_config.numBurst;
+ legacy_config->num_frames_per_burst = aidl_config.numFramesPerBurst;
+ legacy_config->num_retries_per_rtt_frame = aidl_config.numRetriesPerRttFrame;
+ legacy_config->num_retries_per_ftmr = aidl_config.numRetriesPerFtmr;
+ legacy_config->LCI_request = aidl_config.mustRequestLci;
+ legacy_config->LCR_request = aidl_config.mustRequestLcr;
+ legacy_config->burst_duration = aidl_config.burstDuration;
+ legacy_config->preamble = convertAidlRttPreambleToLegacy(aidl_config.preamble);
+ legacy_config->bw = convertAidlRttBwToLegacy(aidl_config.bw);
+ return true;
+}
+
+bool convertAidlVectorOfRttConfigToLegacy(
+ const std::vector<RttConfig>& aidl_configs,
+ std::vector<legacy_hal::wifi_rtt_config>* legacy_configs) {
+ if (!legacy_configs) {
+ return false;
+ }
+ *legacy_configs = {};
+ for (const auto& aidl_config : aidl_configs) {
+ legacy_hal::wifi_rtt_config legacy_config;
+ if (!convertAidlRttConfigToLegacy(aidl_config, &legacy_config)) {
+ return false;
+ }
+ legacy_configs->push_back(legacy_config);
+ }
+ return true;
+}
+
+bool convertAidlRttLciInformationToLegacy(const RttLciInformation& aidl_info,
+ legacy_hal::wifi_lci_information* legacy_info) {
+ if (!legacy_info) {
+ return false;
+ }
+ *legacy_info = {};
+ legacy_info->latitude = aidl_info.latitude;
+ legacy_info->longitude = aidl_info.longitude;
+ legacy_info->altitude = aidl_info.altitude;
+ legacy_info->latitude_unc = aidl_info.latitudeUnc;
+ legacy_info->longitude_unc = aidl_info.longitudeUnc;
+ legacy_info->altitude_unc = aidl_info.altitudeUnc;
+ legacy_info->motion_pattern = convertAidlRttMotionPatternToLegacy(aidl_info.motionPattern);
+ legacy_info->floor = aidl_info.floor;
+ legacy_info->height_above_floor = aidl_info.heightAboveFloor;
+ legacy_info->height_unc = aidl_info.heightUnc;
+ return true;
+}
+
+bool convertAidlRttLcrInformationToLegacy(const RttLcrInformation& aidl_info,
+ legacy_hal::wifi_lcr_information* legacy_info) {
+ if (!legacy_info) {
+ return false;
+ }
+ *legacy_info = {};
+ CHECK(aidl_info.countryCode.size() == sizeof(legacy_info->country_code));
+ memcpy(legacy_info->country_code, aidl_info.countryCode.data(), aidl_info.countryCode.size());
+ if (aidl_info.civicInfo.size() > sizeof(legacy_info->civic_info)) {
+ return false;
+ }
+ legacy_info->length = aidl_info.civicInfo.size();
+ memcpy(legacy_info->civic_info, aidl_info.civicInfo.c_str(), aidl_info.civicInfo.size());
+ return true;
+}
+
+bool convertAidlRttResponderToLegacy(const RttResponder& aidl_responder,
+ legacy_hal::wifi_rtt_responder* legacy_responder) {
+ if (!legacy_responder) {
+ return false;
+ }
+ *legacy_responder = {};
+ if (!convertAidlWifiChannelInfoToLegacy(aidl_responder.channel, &legacy_responder->channel)) {
+ return false;
+ }
+ legacy_responder->preamble = convertAidlRttPreambleToLegacy(aidl_responder.preamble);
+ return true;
+}
+
+bool convertLegacyRttResponderToAidl(const legacy_hal::wifi_rtt_responder& legacy_responder,
+ RttResponder* aidl_responder) {
+ if (!aidl_responder) {
+ return false;
+ }
+ *aidl_responder = {};
+ if (!convertLegacyWifiChannelInfoToAidl(legacy_responder.channel, &aidl_responder->channel)) {
+ return false;
+ }
+ aidl_responder->preamble = convertLegacyRttPreambleToAidl(legacy_responder.preamble);
+ return true;
+}
+
+bool convertLegacyRttCapabilitiesToAidl(
+ const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
+ RttCapabilities* aidl_capabilities) {
+ if (!aidl_capabilities) {
+ return false;
+ }
+ *aidl_capabilities = {};
+ aidl_capabilities->rttOneSidedSupported = legacy_capabilities.rtt_one_sided_supported;
+ aidl_capabilities->rttFtmSupported = legacy_capabilities.rtt_ftm_supported;
+ aidl_capabilities->lciSupported = legacy_capabilities.lci_support;
+ aidl_capabilities->lcrSupported = legacy_capabilities.lcr_support;
+ aidl_capabilities->responderSupported = legacy_capabilities.responder_supported;
+ int32_t preambleSupport = 0;
+ for (const auto flag : {legacy_hal::WIFI_RTT_PREAMBLE_LEGACY, legacy_hal::WIFI_RTT_PREAMBLE_HT,
+ legacy_hal::WIFI_RTT_PREAMBLE_VHT, legacy_hal::WIFI_RTT_PREAMBLE_HE,
+ legacy_hal::WIFI_RTT_PREAMBLE_EHT}) {
+ if (legacy_capabilities.preamble_support & flag) {
+ preambleSupport |= static_cast<std::underlying_type<RttPreamble>::type>(
+ convertLegacyRttPreambleToAidl(flag));
+ }
+ }
+ aidl_capabilities->preambleSupport = static_cast<RttPreamble>(preambleSupport);
+ int32_t bwSupport = 0;
+ for (const auto flag :
+ {legacy_hal::WIFI_RTT_BW_5, legacy_hal::WIFI_RTT_BW_10, legacy_hal::WIFI_RTT_BW_20,
+ legacy_hal::WIFI_RTT_BW_40, legacy_hal::WIFI_RTT_BW_80, legacy_hal::WIFI_RTT_BW_160,
+ legacy_hal::WIFI_RTT_BW_320}) {
+ if (legacy_capabilities.bw_support & flag) {
+ bwSupport |=
+ static_cast<std::underlying_type<RttBw>::type>(convertLegacyRttBwToAidl(flag));
+ }
+ }
+ aidl_capabilities->bwSupport = static_cast<RttBw>(bwSupport);
+ aidl_capabilities->mcVersion = legacy_capabilities.mc_version;
+ return true;
+}
+
+bool convertLegacyWifiRateInfoToAidl(const legacy_hal::wifi_rate& legacy_rate,
+ WifiRateInfo* aidl_rate) {
+ if (!aidl_rate) {
+ return false;
+ }
+ *aidl_rate = {};
+ aidl_rate->preamble = convertLegacyWifiRatePreambleToAidl(legacy_rate.preamble);
+ aidl_rate->nss = convertLegacyWifiRateNssToAidl(legacy_rate.nss);
+ aidl_rate->bw = convertLegacyWifiChannelWidthToAidl(
+ static_cast<legacy_hal::wifi_channel_width>(legacy_rate.bw));
+ aidl_rate->rateMcsIdx = legacy_rate.rateMcsIdx;
+ aidl_rate->bitRateInKbps = legacy_rate.bitrate;
+ return true;
+}
+
+bool convertLegacyRttResultToAidl(const legacy_hal::wifi_rtt_result& legacy_result,
+ RttResult* aidl_result) {
+ if (!aidl_result) {
+ return false;
+ }
+ *aidl_result = {};
+ aidl_result->addr = std::array<uint8_t, 6>();
+ CHECK(sizeof(legacy_result.addr) == aidl_result->addr.size());
+ std::copy(legacy_result.addr, legacy_result.addr + 6, std::begin(aidl_result->addr));
+ aidl_result->burstNum = legacy_result.burst_num;
+ aidl_result->measurementNumber = legacy_result.measurement_number;
+ aidl_result->successNumber = legacy_result.success_number;
+ aidl_result->numberPerBurstPeer = legacy_result.number_per_burst_peer;
+ aidl_result->status = convertLegacyRttStatusToAidl(legacy_result.status);
+ aidl_result->retryAfterDuration = legacy_result.retry_after_duration;
+ aidl_result->type = convertLegacyRttTypeToAidl(legacy_result.type);
+ aidl_result->rssi = legacy_result.rssi;
+ aidl_result->rssiSpread = legacy_result.rssi_spread;
+ if (!convertLegacyWifiRateInfoToAidl(legacy_result.tx_rate, &aidl_result->txRate)) {
+ return false;
+ }
+ if (!convertLegacyWifiRateInfoToAidl(legacy_result.rx_rate, &aidl_result->rxRate)) {
+ return false;
+ }
+ aidl_result->rtt = legacy_result.rtt;
+ aidl_result->rttSd = legacy_result.rtt_sd;
+ aidl_result->rttSpread = legacy_result.rtt_spread;
+ aidl_result->distanceInMm = legacy_result.distance_mm;
+ aidl_result->distanceSdInMm = legacy_result.distance_sd_mm;
+ aidl_result->distanceSpreadInMm = legacy_result.distance_spread_mm;
+ aidl_result->timeStampInUs = legacy_result.ts;
+ aidl_result->burstDurationInMs = legacy_result.burst_duration;
+ aidl_result->negotiatedBurstNum = legacy_result.negotiated_burst_num;
+ if (legacy_result.LCI && !convertLegacyIeToAidl(*legacy_result.LCI, &aidl_result->lci)) {
+ return false;
+ }
+ if (legacy_result.LCR && !convertLegacyIeToAidl(*legacy_result.LCR, &aidl_result->lcr)) {
+ return false;
+ }
+ return true;
+}
+
+bool convertLegacyVectorOfRttResultToAidl(
+ const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
+ std::vector<RttResult>* aidl_results) {
+ if (!aidl_results) {
+ return false;
+ }
+ *aidl_results = {};
+ for (const auto legacy_result : legacy_results) {
+ RttResult aidl_result;
+ if (!convertLegacyRttResultToAidl(*legacy_result, &aidl_result)) {
+ return false;
+ }
+ aidl_results->push_back(aidl_result);
+ }
+ return true;
+}
+
+legacy_hal::wifi_interface_type convertAidlIfaceTypeToLegacy(IfaceType aidl_interface_type) {
+ switch (aidl_interface_type) {
+ case IfaceType::STA:
+ return legacy_hal::WIFI_INTERFACE_TYPE_STA;
+ case IfaceType::AP:
+ return legacy_hal::WIFI_INTERFACE_TYPE_AP;
+ case IfaceType::P2P:
+ return legacy_hal::WIFI_INTERFACE_TYPE_P2P;
+ case IfaceType::NAN_IFACE:
+ return legacy_hal::WIFI_INTERFACE_TYPE_NAN;
+ }
+ CHECK(false);
+}
+
+legacy_hal::wifi_multi_sta_use_case convertAidlMultiStaUseCaseToLegacy(
+ IWifiChip::MultiStaUseCase use_case) {
+ switch (use_case) {
+ case IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY:
+ return legacy_hal::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY;
+ case IWifiChip::MultiStaUseCase::DUAL_STA_NON_TRANSIENT_UNBIASED:
+ return legacy_hal::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED;
+ }
+ CHECK(false);
+}
+
+bool convertAidlCoexUnsafeChannelToLegacy(
+ const IWifiChip::CoexUnsafeChannel& aidl_unsafe_channel,
+ legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel) {
+ if (!legacy_unsafe_channel) {
+ return false;
+ }
+ *legacy_unsafe_channel = {};
+ switch (aidl_unsafe_channel.band) {
+ case WifiBand::BAND_24GHZ:
+ legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_2_4_BAND;
+ break;
+ case WifiBand::BAND_5GHZ:
+ legacy_unsafe_channel->band = legacy_hal::WLAN_MAC_5_0_BAND;
+ break;
+ default:
+ return false;
+ };
+ legacy_unsafe_channel->channel = aidl_unsafe_channel.channel;
+ legacy_unsafe_channel->power_cap_dbm = aidl_unsafe_channel.powerCapDbm;
+ return true;
+}
+
+bool convertAidlVectorOfCoexUnsafeChannelToLegacy(
+ const std::vector<IWifiChip::CoexUnsafeChannel>& aidl_unsafe_channels,
+ std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels) {
+ if (!legacy_unsafe_channels) {
+ return false;
+ }
+ *legacy_unsafe_channels = {};
+ for (const auto& aidl_unsafe_channel : aidl_unsafe_channels) {
+ legacy_hal::wifi_coex_unsafe_channel legacy_unsafe_channel;
+ if (!aidl_struct_util::convertAidlCoexUnsafeChannelToLegacy(aidl_unsafe_channel,
+ &legacy_unsafe_channel)) {
+ return false;
+ }
+ legacy_unsafe_channels->push_back(legacy_unsafe_channel);
+ }
+ return true;
+}
+
+WifiAntennaMode convertLegacyAntennaConfigurationToAidl(uint32_t antenna_cfg) {
+ switch (antenna_cfg) {
+ case legacy_hal::WIFI_ANTENNA_1X1:
+ return WifiAntennaMode::WIFI_ANTENNA_MODE_1X1;
+ case legacy_hal::WIFI_ANTENNA_2X2:
+ return WifiAntennaMode::WIFI_ANTENNA_MODE_2X2;
+ case legacy_hal::WIFI_ANTENNA_3X3:
+ return WifiAntennaMode::WIFI_ANTENNA_MODE_3X3;
+ case legacy_hal::WIFI_ANTENNA_4X4:
+ return WifiAntennaMode::WIFI_ANTENNA_MODE_4X4;
+ default:
+ return WifiAntennaMode::WIFI_ANTENNA_MODE_UNSPECIFIED;
+ }
+}
+
+bool convertLegacyWifiRadioConfigurationToAidl(
+ legacy_hal::wifi_radio_configuration* radio_configuration,
+ WifiRadioConfiguration* aidl_radio_configuration) {
+ if (!aidl_radio_configuration) {
+ return false;
+ }
+ *aidl_radio_configuration = {};
+ aidl_radio_configuration->bandInfo =
+ aidl_struct_util::convertLegacyMacBandToAidlWifiBand(radio_configuration->band);
+ if (aidl_radio_configuration->bandInfo == WifiBand::BAND_UNSPECIFIED) {
+ LOG(ERROR) << "Unspecified band";
+ return false;
+ }
+ aidl_radio_configuration->antennaMode =
+ aidl_struct_util::convertLegacyAntennaConfigurationToAidl(
+ radio_configuration->antenna_cfg);
+ return true;
+}
+
+bool convertLegacyRadioCombinationsMatrixToAidl(
+ legacy_hal::wifi_radio_combination_matrix* legacy_matrix,
+ WifiRadioCombinationMatrix* aidl_matrix) {
+ if (!aidl_matrix || !legacy_matrix) {
+ return false;
+ }
+ *aidl_matrix = {};
+
+ int num_combinations = legacy_matrix->num_radio_combinations;
+ std::vector<WifiRadioCombination> radio_combinations_vec;
+ if (!num_combinations) {
+ LOG(ERROR) << "zero radio combinations";
+ return false;
+ }
+ wifi_radio_combination* l_radio_combinations_ptr = legacy_matrix->radio_combinations;
+ for (int i = 0; i < num_combinations; i++) {
+ int num_configurations = l_radio_combinations_ptr->num_radio_configurations;
+ WifiRadioCombination radioCombination;
+ std::vector<WifiRadioConfiguration> radio_configurations_vec;
+ if (!num_configurations) {
+ LOG(ERROR) << "zero radio configurations";
+ return false;
+ }
+ for (int j = 0; j < num_configurations; j++) {
+ WifiRadioConfiguration radioConfiguration;
+ wifi_radio_configuration* l_radio_configurations_ptr =
+ &l_radio_combinations_ptr->radio_configurations[j];
+ if (!aidl_struct_util::convertLegacyWifiRadioConfigurationToAidl(
+ l_radio_configurations_ptr, &radioConfiguration)) {
+ LOG(ERROR) << "Error converting wifi radio configuration";
+ return false;
+ }
+ radio_configurations_vec.push_back(radioConfiguration);
+ }
+ radioCombination.radioConfigurations = radio_configurations_vec;
+ radio_combinations_vec.push_back(radioCombination);
+ l_radio_combinations_ptr =
+ (wifi_radio_combination*)((u8*)l_radio_combinations_ptr +
+ sizeof(wifi_radio_combination) +
+ (sizeof(wifi_radio_configuration) * num_configurations));
+ }
+ aidl_matrix->radioCombinations = radio_combinations_vec;
+ return true;
+}
+
+} // namespace aidl_struct_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/aidl_struct_util.h b/wifi/aidl/default/aidl_struct_util.h
new file mode 100644
index 0000000..4ebfc10
--- /dev/null
+++ b/wifi/aidl/default/aidl_struct_util.h
@@ -0,0 +1,180 @@
+/*
+ * 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 AIDL_STRUCT_UTIL_H_
+#define AIDL_STRUCT_UTIL_H_
+
+#include <aidl/android/hardware/wifi/IWifiChip.h>
+#include <aidl/android/hardware/wifi/IWifiChipEventCallback.h>
+#include <aidl/android/hardware/wifi/NanBandIndex.h>
+#include <aidl/android/hardware/wifi/WifiDebugRingBufferFlags.h>
+
+#include <vector>
+
+#include "wifi_legacy_hal.h"
+
+/**
+ * This file contains a bunch of functions to convert structs from the legacy
+ * HAL to AIDL and vice versa.
+ */
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace aidl_struct_util {
+
+// Chip conversion methods.
+bool convertLegacyFeaturesToAidlChipCapabilities(uint64_t legacy_feature_set,
+ uint32_t legacy_logger_feature_set,
+ uint32_t* aidl_caps);
+bool convertLegacyDebugRingBufferStatusToAidl(
+ const legacy_hal::wifi_ring_buffer_status& legacy_status,
+ WifiDebugRingBufferStatus* aidl_status);
+bool convertLegacyVectorOfDebugRingBufferStatusToAidl(
+ const std::vector<legacy_hal::wifi_ring_buffer_status>& legacy_status_vec,
+ std::vector<WifiDebugRingBufferStatus>* aidl_status_vec);
+bool convertLegacyWakeReasonStatsToAidl(const legacy_hal::WakeReasonStats& legacy_stats,
+ WifiDebugHostWakeReasonStats* aidl_stats);
+legacy_hal::wifi_power_scenario convertAidlTxPowerScenarioToLegacy(
+ IWifiChip::TxPowerScenario aidl_scenario);
+legacy_hal::wifi_latency_mode convertAidlLatencyModeToLegacy(
+ IWifiChip::LatencyMode aidl_latency_mode);
+bool convertLegacyWifiMacInfosToAidl(
+ const std::vector<legacy_hal::WifiMacInfo>& legacy_mac_infos,
+ std::vector<IWifiChipEventCallback::RadioModeInfo>* aidl_radio_mode_infos);
+legacy_hal::wifi_interface_type convertAidlIfaceTypeToLegacy(IfaceType aidl_interface_type);
+legacy_hal::wifi_multi_sta_use_case convertAidlMultiStaUseCaseToLegacy(
+ IWifiChip::MultiStaUseCase use_case);
+bool convertAidlCoexUnsafeChannelToLegacy(
+ const IWifiChip::CoexUnsafeChannel& aidl_unsafe_channel,
+ legacy_hal::wifi_coex_unsafe_channel* legacy_unsafe_channel);
+bool convertAidlVectorOfCoexUnsafeChannelToLegacy(
+ const std::vector<IWifiChip::CoexUnsafeChannel>& aidl_unsafe_channels,
+ std::vector<legacy_hal::wifi_coex_unsafe_channel>* legacy_unsafe_channels);
+bool convertLegacyRadioCombinationsMatrixToAidl(
+ legacy_hal::wifi_radio_combination_matrix* legacy_matrix,
+ WifiRadioCombinationMatrix* aidl_matrix);
+WifiBand convertLegacyMacBandToAidlWifiBand(uint32_t band);
+WifiAntennaMode convertLegacyAntennaConfigurationToAidl(uint32_t antenna_cfg);
+
+// STA iface conversion methods.
+bool convertLegacyFeaturesToAidlStaCapabilities(uint64_t legacy_feature_set,
+ uint32_t legacy_logger_feature_set,
+ uint32_t* aidl_caps);
+bool convertLegacyApfCapabilitiesToAidl(const legacy_hal::PacketFilterCapabilities& legacy_caps,
+ StaApfPacketFilterCapabilities* aidl_caps);
+bool convertLegacyGscanCapabilitiesToAidl(const legacy_hal::wifi_gscan_capabilities& legacy_caps,
+ StaBackgroundScanCapabilities* aidl_caps);
+legacy_hal::wifi_band convertAidlWifiBandToLegacy(WifiBand band);
+bool convertAidlGscanParamsToLegacy(const StaBackgroundScanParameters& aidl_scan_params,
+ legacy_hal::wifi_scan_cmd_params* legacy_scan_params);
+// |has_ie_data| indicates whether or not the wifi_scan_result includes 802.11
+// Information Elements (IEs)
+bool convertLegacyGscanResultToAidl(const legacy_hal::wifi_scan_result& legacy_scan_result,
+ bool has_ie_data, StaScanResult* aidl_scan_result);
+// |cached_results| is assumed to not include IEs.
+bool convertLegacyVectorOfCachedGscanResultsToAidl(
+ const std::vector<legacy_hal::wifi_cached_scan_results>& legacy_cached_scan_results,
+ std::vector<StaScanData>* aidl_scan_datas);
+bool convertLegacyLinkLayerStatsToAidl(const legacy_hal::LinkLayerStats& legacy_stats,
+ StaLinkLayerStats* aidl_stats);
+bool convertLegacyRoamingCapabilitiesToAidl(
+ const legacy_hal::wifi_roaming_capabilities& legacy_caps,
+ StaRoamingCapabilities* aidl_caps);
+bool convertAidlRoamingConfigToLegacy(const StaRoamingConfig& aidl_config,
+ legacy_hal::wifi_roaming_config* legacy_config);
+legacy_hal::fw_roaming_state_t convertAidlRoamingStateToLegacy(StaRoamingState state);
+bool convertLegacyVectorOfDebugTxPacketFateToAidl(
+ const std::vector<legacy_hal::wifi_tx_report>& legacy_fates,
+ std::vector<WifiDebugTxPacketFateReport>* aidl_fates);
+bool convertLegacyVectorOfDebugRxPacketFateToAidl(
+ const std::vector<legacy_hal::wifi_rx_report>& legacy_fates,
+ std::vector<WifiDebugRxPacketFateReport>* aidl_fates);
+
+// NAN iface conversion methods.
+void convertToNanStatus(legacy_hal::NanStatusType type, const char* str, size_t max_len,
+ NanStatus* nanStatus);
+bool convertAidlNanEnableRequestToLegacy(const NanEnableRequest& aidl_request1,
+ const NanConfigRequestSupplemental& aidl_request2,
+ legacy_hal::NanEnableRequest* legacy_request);
+bool convertAidlNanConfigRequestToLegacy(const NanConfigRequest& aidl_request1,
+ const NanConfigRequestSupplemental& aidl_request2,
+ legacy_hal::NanConfigRequest* legacy_request);
+bool convertAidlNanPublishRequestToLegacy(const NanPublishRequest& aidl_request,
+ legacy_hal::NanPublishRequest* legacy_request);
+bool convertAidlNanSubscribeRequestToLegacy(const NanSubscribeRequest& aidl_request,
+ legacy_hal::NanSubscribeRequest* legacy_request);
+bool convertAidlNanTransmitFollowupRequestToLegacy(
+ const NanTransmitFollowupRequest& aidl_request,
+ legacy_hal::NanTransmitFollowupRequest* legacy_request);
+bool convertAidlNanDataPathInitiatorRequestToLegacy(
+ const NanInitiateDataPathRequest& aidl_request,
+ legacy_hal::NanDataPathInitiatorRequest* legacy_request);
+bool convertAidlNanDataPathIndicationResponseToLegacy(
+ const NanRespondToDataPathIndicationRequest& aidl_response,
+ legacy_hal::NanDataPathIndicationResponse* legacy_response);
+bool convertLegacyNanResponseHeaderToAidl(const legacy_hal::NanResponseMsg& legacy_response,
+ NanStatus* nanStatus);
+bool convertLegacyNanCapabilitiesResponseToAidl(const legacy_hal::NanCapabilities& legacy_response,
+ NanCapabilities* aidl_response);
+bool convertLegacyNanMatchIndToAidl(const legacy_hal::NanMatchInd& legacy_ind,
+ NanMatchInd* aidl_ind);
+bool convertLegacyNanFollowupIndToAidl(const legacy_hal::NanFollowupInd& legacy_ind,
+ NanFollowupReceivedInd* aidl_ind);
+bool convertLegacyNanDataPathRequestIndToAidl(const legacy_hal::NanDataPathRequestInd& legacy_ind,
+ NanDataPathRequestInd* aidl_ind);
+bool convertLegacyNanDataPathConfirmIndToAidl(const legacy_hal::NanDataPathConfirmInd& legacy_ind,
+ NanDataPathConfirmInd* aidl_ind);
+bool convertLegacyNanDataPathScheduleUpdateIndToAidl(
+ const legacy_hal::NanDataPathScheduleUpdateInd& legacy_ind,
+ NanDataPathScheduleUpdateInd* aidl_ind);
+
+// RTT controller conversion methods.
+bool convertAidlVectorOfRttConfigToLegacy(const std::vector<RttConfig>& aidl_configs,
+ std::vector<legacy_hal::wifi_rtt_config>* legacy_configs);
+bool convertAidlRttLciInformationToLegacy(const RttLciInformation& aidl_info,
+ legacy_hal::wifi_lci_information* legacy_info);
+bool convertAidlRttLcrInformationToLegacy(const RttLcrInformation& aidl_info,
+ legacy_hal::wifi_lcr_information* legacy_info);
+bool convertAidlRttResponderToLegacy(const RttResponder& aidl_responder,
+ legacy_hal::wifi_rtt_responder* legacy_responder);
+bool convertAidlWifiChannelInfoToLegacy(const WifiChannelInfo& aidl_info,
+ legacy_hal::wifi_channel_info* legacy_info);
+bool convertLegacyRttResponderToAidl(const legacy_hal::wifi_rtt_responder& legacy_responder,
+ RttResponder* aidl_responder);
+bool convertLegacyRttCapabilitiesToAidl(
+ const legacy_hal::wifi_rtt_capabilities& legacy_capabilities,
+ RttCapabilities* aidl_capabilities);
+bool convertLegacyVectorOfRttResultToAidl(
+ const std::vector<const legacy_hal::wifi_rtt_result*>& legacy_results,
+ std::vector<RttResult>* aidl_results);
+uint32_t convertAidlWifiBandToLegacyMacBand(WifiBand band);
+uint32_t convertAidlWifiIfaceModeToLegacy(uint32_t aidl_iface_mask);
+uint32_t convertAidlUsableChannelFilterToLegacy(uint32_t aidl_filter_mask);
+bool convertLegacyWifiUsableChannelsToAidl(
+ const std::vector<legacy_hal::wifi_usable_channel>& legacy_usable_channels,
+ std::vector<WifiUsableChannel>* aidl_usable_channels);
+bool convertLegacyPeerInfoStatsToAidl(const legacy_hal::WifiPeerInfo& legacy_peer_info_stats,
+ StaPeerInfo* aidl_peer_info_stats);
+bool convertLegacyWifiRateInfoToAidl(const legacy_hal::wifi_rate& legacy_rate,
+ WifiRateInfo* aidl_rate);
+} // namespace aidl_struct_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // AIDL_STRUCT_UTIL_H_
diff --git a/wifi/aidl/default/aidl_sync_util.cpp b/wifi/aidl/default/aidl_sync_util.cpp
new file mode 100644
index 0000000..d81eb81
--- /dev/null
+++ b/wifi/aidl/default/aidl_sync_util.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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_sync_util.h"
+
+namespace {
+std::recursive_mutex g_mutex;
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace aidl_sync_util {
+
+std::unique_lock<std::recursive_mutex> acquireGlobalLock() {
+ return std::unique_lock<std::recursive_mutex>{g_mutex};
+}
+
+} // namespace aidl_sync_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/aidl_sync_util.h b/wifi/aidl/default/aidl_sync_util.h
new file mode 100644
index 0000000..a61cd3f
--- /dev/null
+++ b/wifi/aidl/default/aidl_sync_util.h
@@ -0,0 +1,35 @@
+/*
+ * 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 AIDL_SYNC_UTIL_H_
+#define AIDL_SYNC_UTIL_H_
+
+#include <mutex>
+
+// Utility that provides a global lock to synchronize access between
+// the AIDL thread and the legacy HAL's event loop.
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace aidl_sync_util {
+std::unique_lock<std::recursive_mutex> acquireGlobalLock();
+} // namespace aidl_sync_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+#endif // AIDL_SYNC_UTIL_H_
diff --git a/wifi/aidl/default/android.hardware.wifi-service-lazy.rc b/wifi/aidl/default/android.hardware.wifi-service-lazy.rc
new file mode 100644
index 0000000..12d3ff7
--- /dev/null
+++ b/wifi/aidl/default/android.hardware.wifi-service-lazy.rc
@@ -0,0 +1,8 @@
+service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi-service-lazy
+ interface aidl android.hardware.wifi.IWifi/default
+ oneshot
+ disabled
+ class hal
+ capabilities NET_ADMIN NET_RAW SYS_MODULE
+ user wifi
+ group wifi gps
diff --git a/wifi/aidl/default/android.hardware.wifi-service.rc b/wifi/aidl/default/android.hardware.wifi-service.rc
new file mode 100644
index 0000000..ec8acf5
--- /dev/null
+++ b/wifi/aidl/default/android.hardware.wifi-service.rc
@@ -0,0 +1,6 @@
+service vendor.wifi_hal_legacy /vendor/bin/hw/android.hardware.wifi-service
+ interface aidl android.hardware.wifi.IWifi/default
+ class hal
+ capabilities NET_ADMIN NET_RAW SYS_MODULE
+ user wifi
+ group wifi gps
diff --git a/wifi/aidl/default/android.hardware.wifi-service.xml b/wifi/aidl/default/android.hardware.wifi-service.xml
new file mode 100644
index 0000000..5398ee7
--- /dev/null
+++ b/wifi/aidl/default/android.hardware.wifi-service.xml
@@ -0,0 +1,6 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.wifi</name>
+ <fqname>IWifi/default</fqname>
+ </hal>
+</manifest>
diff --git a/wifi/aidl/default/ringbuffer.cpp b/wifi/aidl/default/ringbuffer.cpp
new file mode 100644
index 0000000..9d08a73
--- /dev/null
+++ b/wifi/aidl/default/ringbuffer.cpp
@@ -0,0 +1,62 @@
+/*
+ * 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 "ringbuffer.h"
+
+#include <android-base/logging.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+Ringbuffer::Ringbuffer(size_t maxSize) : size_(0), maxSize_(maxSize) {}
+
+enum Ringbuffer::AppendStatus Ringbuffer::append(const std::vector<uint8_t>& input) {
+ if (input.size() == 0) {
+ return AppendStatus::FAIL_IP_BUFFER_ZERO;
+ }
+ if (input.size() > maxSize_) {
+ LOG(INFO) << "Oversized message of " << input.size() << " bytes is dropped";
+ return AppendStatus::FAIL_IP_BUFFER_EXCEEDED_MAXSIZE;
+ }
+ data_.push_back(input);
+ size_ += input.size() * sizeof(input[0]);
+ while (size_ > maxSize_) {
+ if (data_.front().size() <= 0 || data_.front().size() > maxSize_) {
+ LOG(ERROR) << "First buffer in the ring buffer is Invalid. Size: "
+ << data_.front().size();
+ return AppendStatus::FAIL_RING_BUFFER_CORRUPTED;
+ }
+ size_ -= data_.front().size() * sizeof(data_.front()[0]);
+ data_.pop_front();
+ }
+ return AppendStatus::SUCCESS;
+}
+
+const std::list<std::vector<uint8_t>>& Ringbuffer::getData() const {
+ return data_;
+}
+
+void Ringbuffer::clear() {
+ data_.clear();
+ size_ = 0;
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/ringbuffer.h b/wifi/aidl/default/ringbuffer.h
new file mode 100644
index 0000000..80c0c11
--- /dev/null
+++ b/wifi/aidl/default/ringbuffer.h
@@ -0,0 +1,60 @@
+/*
+ * 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 RINGBUFFER_H_
+#define RINGBUFFER_H_
+
+#include <list>
+#include <vector>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+/**
+ * Ringbuffer object used to store debug data.
+ */
+class Ringbuffer {
+ public:
+ // Error codes for the append ring buffer operation
+ enum AppendStatus {
+ SUCCESS,
+ FAIL_GENERIC,
+ FAIL_IP_BUFFER_ZERO,
+ FAIL_IP_BUFFER_EXCEEDED_MAXSIZE,
+ FAIL_RING_BUFFER_CORRUPTED
+ };
+ explicit Ringbuffer(size_t maxSize);
+
+ // Appends the data buffer and deletes from the front until buffer is
+ // within |maxSize_|.
+ enum AppendStatus append(const std::vector<uint8_t>& input);
+ const std::list<std::vector<uint8_t>>& getData() const;
+ void clear();
+
+ private:
+ std::list<std::vector<uint8_t>> data_;
+ size_t size_;
+ size_t maxSize_;
+};
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // RINGBUFFER_H_
diff --git a/wifi/aidl/default/service.cpp b/wifi/aidl/default/service.cpp
new file mode 100644
index 0000000..789a7a5
--- /dev/null
+++ b/wifi/aidl/default/service.cpp
@@ -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.
+ */
+
+#include <android-base/logging.h>
+#include <android/binder_manager.h>
+#include <android/binder_process.h>
+#include <signal.h>
+
+#include "wifi.h"
+#include "wifi_feature_flags.h"
+#include "wifi_legacy_hal.h"
+#include "wifi_legacy_hal_factory.h"
+#include "wifi_mode_controller.h"
+
+using aidl::android::hardware::wifi::feature_flags::WifiFeatureFlags;
+using aidl::android::hardware::wifi::legacy_hal::WifiLegacyHal;
+using aidl::android::hardware::wifi::legacy_hal::WifiLegacyHalFactory;
+using aidl::android::hardware::wifi::mode_controller::WifiModeController;
+
+#ifdef LAZY_SERVICE
+const bool kLazyService = true;
+#else
+const bool kLazyService = false;
+#endif
+
+int main(int /*argc*/, char** argv) {
+ signal(SIGPIPE, SIG_IGN);
+ android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
+ LOG(INFO) << "Wifi Hal is booting up...";
+
+ // Prepare the RPC-serving thread pool. Allocate 1 thread in the pool,
+ // which our main thread will join below.
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+
+ const auto iface_tool = std::make_shared<::android::wifi_system::InterfaceTool>();
+ const auto legacy_hal_factory = std::make_shared<WifiLegacyHalFactory>(iface_tool);
+
+ // Setup binder service
+ std::shared_ptr<aidl::android::hardware::wifi::Wifi> service =
+ ndk::SharedRefBase::make<aidl::android::hardware::wifi::Wifi>(
+ iface_tool, legacy_hal_factory, std::make_shared<WifiModeController>(),
+ std::make_shared<WifiFeatureFlags>());
+ std::string instance =
+ std::string() + aidl::android::hardware::wifi::Wifi::descriptor + "/default";
+ if (kLazyService) {
+ auto result =
+ AServiceManager_registerLazyService(service->asBinder().get(), instance.c_str());
+ CHECK_EQ(result, STATUS_OK) << "Failed to register lazy wifi HAL";
+ } else {
+ auto result = AServiceManager_addService(service->asBinder().get(), instance.c_str());
+ CHECK_EQ(result, STATUS_OK) << "Failed to register wifi HAL";
+ }
+
+ ABinderProcess_startThreadPool();
+ LOG(INFO) << "Joining RPC thread pool";
+ ABinderProcess_joinThreadPool();
+
+ LOG(INFO) << "Wifi Hal is terminating...";
+ return 0;
+}
diff --git a/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
new file mode 100644
index 0000000..4a69c24
--- /dev/null
+++ b/wifi/aidl/default/tests/aidl_struct_util_unit_tests.cpp
@@ -0,0 +1,485 @@
+/*
+ * 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-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#include "aidl_struct_util.h"
+
+using testing::Test;
+
+namespace {
+constexpr uint32_t kMacId1 = 1;
+constexpr uint32_t kMacId2 = 2;
+constexpr uint32_t kIfaceChannel1 = 3;
+constexpr uint32_t kIfaceChannel2 = 5;
+constexpr char kIfaceName1[] = "wlan0";
+constexpr char kIfaceName2[] = "wlan1";
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+class AidlStructUtilTest : public Test {};
+
+TEST_F(AidlStructUtilTest, CanConvertLegacyWifiMacInfosToAidlWithOneMac) {
+ std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
+ legacy_hal::WifiMacInfo legacy_mac_info1 = {
+ .wlan_mac_id = kMacId1,
+ .mac_band = legacy_hal::WLAN_MAC_5_0_BAND | legacy_hal::WLAN_MAC_2_4_BAND};
+ legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1, .channel = kIfaceChannel1};
+ legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2, .channel = kIfaceChannel2};
+ legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
+ legacy_mac_info1.iface_infos.push_back(legacy_iface_info2);
+ legacy_mac_infos.push_back(legacy_mac_info1);
+
+ std::vector<IWifiChipEventCallback::RadioModeInfo> aidl_radio_mode_infos;
+ ASSERT_TRUE(aidl_struct_util::convertLegacyWifiMacInfosToAidl(legacy_mac_infos,
+ &aidl_radio_mode_infos));
+
+ ASSERT_EQ(1u, aidl_radio_mode_infos.size());
+ auto aidl_radio_mode_info1 = aidl_radio_mode_infos[0];
+ EXPECT_EQ(legacy_mac_info1.wlan_mac_id, (uint32_t)aidl_radio_mode_info1.radioId);
+ EXPECT_EQ(WifiBand::BAND_24GHZ_5GHZ, aidl_radio_mode_info1.bandInfo);
+ ASSERT_EQ(2u, aidl_radio_mode_info1.ifaceInfos.size());
+ auto aidl_iface_info1 = aidl_radio_mode_info1.ifaceInfos[0];
+ EXPECT_EQ(legacy_iface_info1.name, aidl_iface_info1.name);
+ EXPECT_EQ(static_cast<int32_t>(legacy_iface_info1.channel), aidl_iface_info1.channel);
+ auto aidl_iface_info2 = aidl_radio_mode_info1.ifaceInfos[1];
+ EXPECT_EQ(legacy_iface_info2.name, aidl_iface_info2.name);
+ EXPECT_EQ(static_cast<int32_t>(legacy_iface_info2.channel), aidl_iface_info2.channel);
+}
+
+TEST_F(AidlStructUtilTest, CanConvertLegacyWifiMacInfosToAidlWithTwoMac) {
+ std::vector<legacy_hal::WifiMacInfo> legacy_mac_infos;
+ legacy_hal::WifiMacInfo legacy_mac_info1 = {.wlan_mac_id = kMacId1,
+ .mac_band = legacy_hal::WLAN_MAC_5_0_BAND};
+ legacy_hal::WifiIfaceInfo legacy_iface_info1 = {.name = kIfaceName1, .channel = kIfaceChannel1};
+ legacy_hal::WifiMacInfo legacy_mac_info2 = {.wlan_mac_id = kMacId2,
+ .mac_band = legacy_hal::WLAN_MAC_2_4_BAND};
+ legacy_hal::WifiIfaceInfo legacy_iface_info2 = {.name = kIfaceName2, .channel = kIfaceChannel2};
+ legacy_mac_info1.iface_infos.push_back(legacy_iface_info1);
+ legacy_mac_infos.push_back(legacy_mac_info1);
+ legacy_mac_info2.iface_infos.push_back(legacy_iface_info2);
+ legacy_mac_infos.push_back(legacy_mac_info2);
+
+ std::vector<IWifiChipEventCallback::RadioModeInfo> aidl_radio_mode_infos;
+ ASSERT_TRUE(aidl_struct_util::convertLegacyWifiMacInfosToAidl(legacy_mac_infos,
+ &aidl_radio_mode_infos));
+
+ ASSERT_EQ(2u, aidl_radio_mode_infos.size());
+
+ // Find mac info 1.
+ const auto aidl_radio_mode_info1 =
+ std::find_if(aidl_radio_mode_infos.begin(), aidl_radio_mode_infos.end(),
+ [&legacy_mac_info1](const IWifiChipEventCallback::RadioModeInfo& x) {
+ return (uint32_t)x.radioId == legacy_mac_info1.wlan_mac_id;
+ });
+ ASSERT_NE(aidl_radio_mode_infos.end(), aidl_radio_mode_info1);
+ EXPECT_EQ(WifiBand::BAND_5GHZ, aidl_radio_mode_info1->bandInfo);
+ ASSERT_EQ(1u, aidl_radio_mode_info1->ifaceInfos.size());
+ auto aidl_iface_info1 = aidl_radio_mode_info1->ifaceInfos[0];
+ EXPECT_EQ(legacy_iface_info1.name, aidl_iface_info1.name);
+ EXPECT_EQ(static_cast<int32_t>(legacy_iface_info1.channel), aidl_iface_info1.channel);
+
+ // Find mac info 2.
+ const auto aidl_radio_mode_info2 =
+ std::find_if(aidl_radio_mode_infos.begin(), aidl_radio_mode_infos.end(),
+ [&legacy_mac_info2](const IWifiChipEventCallback::RadioModeInfo& x) {
+ return (uint32_t)x.radioId == legacy_mac_info2.wlan_mac_id;
+ });
+ ASSERT_NE(aidl_radio_mode_infos.end(), aidl_radio_mode_info2);
+ EXPECT_EQ(WifiBand::BAND_24GHZ, aidl_radio_mode_info2->bandInfo);
+ ASSERT_EQ(1u, aidl_radio_mode_info2->ifaceInfos.size());
+ auto aidl_iface_info2 = aidl_radio_mode_info2->ifaceInfos[0];
+ EXPECT_EQ(legacy_iface_info2.name, aidl_iface_info2.name);
+ EXPECT_EQ(static_cast<int32_t>(legacy_iface_info2.channel), aidl_iface_info2.channel);
+}
+
+TEST_F(AidlStructUtilTest, canConvertLegacyLinkLayerStatsToAidl) {
+ legacy_hal::LinkLayerStats legacy_stats{};
+ legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+ legacy_stats.radios.push_back(legacy_hal::LinkLayerRadioStats{});
+ legacy_stats.peers.push_back(legacy_hal::WifiPeerInfo{});
+ legacy_stats.peers.push_back(legacy_hal::WifiPeerInfo{});
+ legacy_stats.iface.beacon_rx = rand();
+ legacy_stats.iface.rssi_mgmt = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples = rand();
+
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples = rand();
+
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples = rand();
+
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg = rand();
+ legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples = rand();
+
+ legacy_stats.iface.info.time_slicing_duty_cycle_percent = rand();
+ legacy_stats.iface.num_peers = 1;
+
+ for (auto& radio : legacy_stats.radios) {
+ radio.stats.radio = rand();
+ radio.stats.on_time = rand();
+ radio.stats.tx_time = rand();
+ radio.stats.rx_time = rand();
+ radio.stats.on_time_scan = rand();
+ radio.stats.on_time_nbd = rand();
+ radio.stats.on_time_gscan = rand();
+ radio.stats.on_time_roam_scan = rand();
+ radio.stats.on_time_pno_scan = rand();
+ radio.stats.on_time_hs20 = rand();
+ for (int i = 0; i < 4; i++) {
+ radio.tx_time_per_levels.push_back(rand());
+ }
+
+ legacy_hal::wifi_channel_stat channel_stat1 = {
+ .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 2437, 2437, 0},
+ .on_time = 0x1111,
+ .cca_busy_time = 0x55,
+ };
+ legacy_hal::wifi_channel_stat channel_stat2 = {
+ .channel = {legacy_hal::WIFI_CHAN_WIDTH_20, 5180, 5180, 0},
+ .on_time = 0x2222,
+ .cca_busy_time = 0x66,
+ };
+ radio.channel_stats.push_back(channel_stat1);
+ radio.channel_stats.push_back(channel_stat2);
+ }
+
+ for (auto& peer : legacy_stats.peers) {
+ peer.peer_info.bssload.sta_count = rand();
+ peer.peer_info.bssload.chan_util = rand();
+ wifi_rate_stat rate_stat1 = {
+ .rate = {3, 1, 2, 5, 0, 0},
+ .tx_mpdu = 0,
+ .rx_mpdu = 1,
+ .mpdu_lost = 2,
+ .retries = 3,
+ .retries_short = 4,
+ .retries_long = 5,
+ };
+ wifi_rate_stat rate_stat2 = {
+ .rate = {2, 2, 1, 6, 0, 1},
+ .tx_mpdu = 6,
+ .rx_mpdu = 7,
+ .mpdu_lost = 8,
+ .retries = 9,
+ .retries_short = 10,
+ .retries_long = 11,
+ };
+ peer.rate_stats.push_back(rate_stat1);
+ peer.rate_stats.push_back(rate_stat2);
+ }
+
+ StaLinkLayerStats converted{};
+ aidl_struct_util::convertLegacyLinkLayerStatsToAidl(legacy_stats, &converted);
+ EXPECT_EQ(legacy_stats.iface.beacon_rx, (uint32_t)converted.iface.beaconRx);
+ EXPECT_EQ(legacy_stats.iface.rssi_mgmt, converted.iface.avgRssiMgmt);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].rx_mpdu,
+ converted.iface.wmeBePktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].tx_mpdu,
+ converted.iface.wmeBePktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].mpdu_lost,
+ converted.iface.wmeBePktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].retries,
+ converted.iface.wmeBePktStats.retries);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_min,
+ (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionTimeMinInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_max,
+ (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionTimeMaxInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_time_avg,
+ (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionTimeAvgInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BE].contention_num_samples,
+ (uint32_t)converted.iface.wmeBeContentionTimeStats.contentionNumSamples);
+
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].rx_mpdu,
+ converted.iface.wmeBkPktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].tx_mpdu,
+ converted.iface.wmeBkPktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].mpdu_lost,
+ converted.iface.wmeBkPktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].retries,
+ converted.iface.wmeBkPktStats.retries);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_min,
+ (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionTimeMinInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_max,
+ (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionTimeMaxInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_time_avg,
+ (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionTimeAvgInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_BK].contention_num_samples,
+ (uint32_t)converted.iface.wmeBkContentionTimeStats.contentionNumSamples);
+
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].rx_mpdu,
+ converted.iface.wmeViPktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].tx_mpdu,
+ converted.iface.wmeViPktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].mpdu_lost,
+ converted.iface.wmeViPktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].retries,
+ converted.iface.wmeViPktStats.retries);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_min,
+ (uint32_t)converted.iface.wmeViContentionTimeStats.contentionTimeMinInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_max,
+ (uint32_t)converted.iface.wmeViContentionTimeStats.contentionTimeMaxInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_time_avg,
+ (uint32_t)converted.iface.wmeViContentionTimeStats.contentionTimeAvgInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VI].contention_num_samples,
+ (uint32_t)converted.iface.wmeViContentionTimeStats.contentionNumSamples);
+
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].rx_mpdu,
+ converted.iface.wmeVoPktStats.rxMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].tx_mpdu,
+ converted.iface.wmeVoPktStats.txMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].mpdu_lost,
+ converted.iface.wmeVoPktStats.lostMpdu);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].retries,
+ converted.iface.wmeVoPktStats.retries);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_min,
+ (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionTimeMinInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_max,
+ (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionTimeMaxInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_time_avg,
+ (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionTimeAvgInUsec);
+ EXPECT_EQ(legacy_stats.iface.ac[legacy_hal::WIFI_AC_VO].contention_num_samples,
+ (uint32_t)converted.iface.wmeVoContentionTimeStats.contentionNumSamples);
+
+ EXPECT_EQ(legacy_stats.iface.info.time_slicing_duty_cycle_percent,
+ converted.iface.timeSliceDutyCycleInPercent);
+
+ EXPECT_EQ(legacy_stats.radios.size(), converted.radios.size());
+ for (size_t i = 0; i < legacy_stats.radios.size(); i++) {
+ EXPECT_EQ(legacy_stats.radios[i].stats.radio, converted.radios[i].radioId);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time, (uint32_t)converted.radios[i].onTimeInMs);
+ EXPECT_EQ(legacy_stats.radios[i].stats.tx_time, (uint32_t)converted.radios[i].txTimeInMs);
+ EXPECT_EQ(legacy_stats.radios[i].stats.rx_time, (uint32_t)converted.radios[i].rxTimeInMs);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_scan,
+ (uint32_t)converted.radios[i].onTimeInMsForScan);
+ EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels.size(),
+ converted.radios[i].txTimeInMsPerLevel.size());
+ for (size_t j = 0; j < legacy_stats.radios[i].tx_time_per_levels.size(); j++) {
+ EXPECT_EQ(legacy_stats.radios[i].tx_time_per_levels[j],
+ (uint32_t)converted.radios[i].txTimeInMsPerLevel[j]);
+ }
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_nbd,
+ (uint32_t)converted.radios[i].onTimeInMsForNanScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_gscan,
+ (uint32_t)converted.radios[i].onTimeInMsForBgScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_roam_scan,
+ (uint32_t)converted.radios[i].onTimeInMsForRoamScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_pno_scan,
+ (uint32_t)converted.radios[i].onTimeInMsForPnoScan);
+ EXPECT_EQ(legacy_stats.radios[i].stats.on_time_hs20,
+ (uint32_t)converted.radios[i].onTimeInMsForHs20Scan);
+ EXPECT_EQ(legacy_stats.radios[i].channel_stats.size(),
+ converted.radios[i].channelStats.size());
+ for (size_t k = 0; k < legacy_stats.radios[i].channel_stats.size(); k++) {
+ auto& legacy_channel_st = legacy_stats.radios[i].channel_stats[k];
+ EXPECT_EQ(WifiChannelWidthInMhz::WIDTH_20,
+ converted.radios[i].channelStats[k].channel.width);
+ EXPECT_EQ(legacy_channel_st.channel.center_freq,
+ converted.radios[i].channelStats[k].channel.centerFreq);
+ EXPECT_EQ(legacy_channel_st.channel.center_freq0,
+ converted.radios[i].channelStats[k].channel.centerFreq0);
+ EXPECT_EQ(legacy_channel_st.channel.center_freq1,
+ converted.radios[i].channelStats[k].channel.centerFreq1);
+ EXPECT_EQ(legacy_channel_st.cca_busy_time,
+ (uint32_t)converted.radios[i].channelStats[k].ccaBusyTimeInMs);
+ EXPECT_EQ(legacy_channel_st.on_time,
+ (uint32_t)converted.radios[i].channelStats[k].onTimeInMs);
+ }
+ }
+
+ EXPECT_EQ(legacy_stats.peers.size(), converted.iface.peers.size());
+ for (size_t i = 0; i < legacy_stats.peers.size(); i++) {
+ EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.sta_count,
+ converted.iface.peers[i].staCount);
+ EXPECT_EQ(legacy_stats.peers[i].peer_info.bssload.chan_util,
+ converted.iface.peers[i].chanUtil);
+ for (size_t j = 0; j < legacy_stats.peers[i].rate_stats.size(); j++) {
+ EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.preamble,
+ (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.preamble);
+ EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.nss,
+ (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.nss);
+ EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.bw,
+ (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.bw);
+ EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rate.rateMcsIdx,
+ (uint32_t)converted.iface.peers[i].rateStats[j].rateInfo.rateMcsIdx);
+ EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].tx_mpdu,
+ (uint32_t)converted.iface.peers[i].rateStats[j].txMpdu);
+ EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].rx_mpdu,
+ (uint32_t)converted.iface.peers[i].rateStats[j].rxMpdu);
+ EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].mpdu_lost,
+ (uint32_t)converted.iface.peers[i].rateStats[j].mpduLost);
+ EXPECT_EQ(legacy_stats.peers[i].rate_stats[j].retries,
+ (uint32_t)converted.iface.peers[i].rateStats[j].retries);
+ }
+ }
+}
+
+TEST_F(AidlStructUtilTest, CanConvertLegacyFeaturesToAidl) {
+ using AidlChipCaps = IWifiChip::ChipCapabilityMask;
+
+ uint32_t aidl_caps;
+
+ uint32_t legacy_feature_set = WIFI_FEATURE_D2D_RTT | WIFI_FEATURE_SET_LATENCY_MODE;
+ uint32_t legacy_logger_feature_set = legacy_hal::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
+
+ ASSERT_TRUE(aidl_struct_util::convertLegacyFeaturesToAidlChipCapabilities(
+ legacy_feature_set, legacy_logger_feature_set, &aidl_caps));
+
+ EXPECT_EQ((uint32_t)AidlChipCaps::DEBUG_RING_BUFFER_VENDOR_DATA |
+ (uint32_t)AidlChipCaps::DEBUG_HOST_WAKE_REASON_STATS |
+ (uint32_t)AidlChipCaps::DEBUG_ERROR_ALERTS | (uint32_t)AidlChipCaps::D2D_RTT |
+ (uint32_t)AidlChipCaps::SET_LATENCY_MODE |
+ (uint32_t)AidlChipCaps::DEBUG_MEMORY_DRIVER_DUMP,
+ aidl_caps);
+}
+
+void insertRadioCombination(legacy_hal::wifi_radio_combination* dst_radio_combination_ptr,
+ int num_radio_configurations,
+ legacy_hal::wifi_radio_configuration* radio_configuration) {
+ dst_radio_combination_ptr->num_radio_configurations = num_radio_configurations;
+ memcpy(dst_radio_combination_ptr->radio_configurations, radio_configuration,
+ num_radio_configurations * sizeof(legacy_hal::wifi_radio_configuration));
+}
+
+void verifyRadioCombination(WifiRadioCombination* radioCombination, size_t num_radio_configurations,
+ legacy_hal::wifi_radio_configuration* radio_configuration) {
+ EXPECT_EQ(num_radio_configurations, radioCombination->radioConfigurations.size());
+ for (size_t i = 0; i < num_radio_configurations; i++) {
+ EXPECT_EQ(aidl_struct_util::convertLegacyMacBandToAidlWifiBand(radio_configuration->band),
+ radioCombination->radioConfigurations[i].bandInfo);
+ EXPECT_EQ(aidl_struct_util::convertLegacyAntennaConfigurationToAidl(
+ radio_configuration->antenna_cfg),
+ radioCombination->radioConfigurations[i].antennaMode);
+ radio_configuration++;
+ }
+}
+
+TEST_F(AidlStructUtilTest, canConvertLegacyRadioCombinationsMatrixToAidl) {
+ legacy_hal::wifi_radio_configuration radio_configurations_array1[] = {
+ {.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_1X1},
+ };
+ legacy_hal::wifi_radio_configuration radio_configurations_array2[] = {
+ {.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_2X2},
+ {.band = legacy_hal::WLAN_MAC_5_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_3X3},
+ };
+ legacy_hal::wifi_radio_configuration radio_configurations_array3[] = {
+ {.band = legacy_hal::WLAN_MAC_2_4_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_2X2},
+ {.band = legacy_hal::WLAN_MAC_6_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_1X1},
+ {.band = legacy_hal::WLAN_MAC_5_0_BAND, .antenna_cfg = legacy_hal::WIFI_ANTENNA_4X4},
+ };
+
+ int num_radio_configs = 0;
+ int num_combinations = 0;
+ std::array<char, 256> buffer;
+ buffer.fill(0);
+ legacy_hal::wifi_radio_combination_matrix* legacy_matrix =
+ reinterpret_cast<wifi_radio_combination_matrix*>(buffer.data());
+ legacy_hal::wifi_radio_combination* radio_combinations;
+
+ // Prepare a legacy wifi_radio_combination_matrix
+ legacy_matrix->num_radio_combinations = 3;
+ // Insert first combination
+ radio_combinations =
+ (legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations);
+ insertRadioCombination(
+ radio_combinations,
+ sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]),
+ radio_configurations_array1);
+ num_combinations++;
+ num_radio_configs +=
+ sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]);
+
+ // Insert second combination
+ radio_combinations =
+ (legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations +
+ (num_combinations *
+ sizeof(legacy_hal::wifi_radio_combination)) +
+ (num_radio_configs *
+ sizeof(wifi_radio_configuration)));
+ insertRadioCombination(
+ radio_combinations,
+ sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]),
+ radio_configurations_array2);
+ num_combinations++;
+ num_radio_configs +=
+ sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]);
+
+ // Insert third combination
+ radio_combinations =
+ (legacy_hal::wifi_radio_combination*)((char*)legacy_matrix->radio_combinations +
+ (num_combinations *
+ sizeof(legacy_hal::wifi_radio_combination)) +
+ (num_radio_configs *
+ sizeof(wifi_radio_configuration)));
+ insertRadioCombination(
+ radio_combinations,
+ sizeof(radio_configurations_array3) / sizeof(radio_configurations_array3[0]),
+ radio_configurations_array3);
+
+ WifiRadioCombinationMatrix converted_matrix{};
+ aidl_struct_util::convertLegacyRadioCombinationsMatrixToAidl(legacy_matrix, &converted_matrix);
+
+ // Verify the conversion
+ EXPECT_EQ(legacy_matrix->num_radio_combinations, converted_matrix.radioCombinations.size());
+ verifyRadioCombination(
+ &converted_matrix.radioCombinations[0],
+ sizeof(radio_configurations_array1) / sizeof(radio_configurations_array1[0]),
+ radio_configurations_array1);
+ verifyRadioCombination(
+ &converted_matrix.radioCombinations[1],
+ sizeof(radio_configurations_array2) / sizeof(radio_configurations_array2[0]),
+ radio_configurations_array2);
+ verifyRadioCombination(
+ &converted_matrix.radioCombinations[2],
+ sizeof(radio_configurations_array3) / sizeof(radio_configurations_array3[0]),
+ radio_configurations_array3);
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/tests/main.cpp b/wifi/aidl/default/tests/main.cpp
new file mode 100644
index 0000000..767422c
--- /dev/null
+++ b/wifi/aidl/default/tests/main.cpp
@@ -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.
+ */
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include <android-base/logging.h>
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ ::testing::InitGoogleMock(&argc, argv);
+ // Force ourselves to always log to stderr
+ android::base::InitLogging(argv, android::base::StderrLogger);
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/aidl/default/tests/mock_interface_tool.cpp b/wifi/aidl/default/tests/mock_interface_tool.cpp
new file mode 100644
index 0000000..79f3d1e
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_interface_tool.cpp
@@ -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.
+ */
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#include "mock_interface_tool.h"
+
+namespace android {
+namespace wifi_system {
+
+MockInterfaceTool::MockInterfaceTool() {}
+
+} // namespace wifi_system
+} // namespace android
diff --git a/wifi/aidl/default/tests/mock_interface_tool.h b/wifi/aidl/default/tests/mock_interface_tool.h
new file mode 100644
index 0000000..9795de8
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_interface_tool.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.
+ */
+
+#ifndef MOCK_INTERFACE_TOOL_H
+#define MOCK_INTERFACE_TOOL_H
+
+#include <gmock/gmock.h>
+#include <wifi_system/interface_tool.h>
+
+namespace android {
+namespace wifi_system {
+
+class MockInterfaceTool : public InterfaceTool {
+ public:
+ MockInterfaceTool();
+
+ MOCK_METHOD1(GetUpState, bool(const char* if_name));
+ MOCK_METHOD2(SetUpState, bool(const char* if_name, bool request_up));
+ MOCK_METHOD1(SetWifiUpState, bool(bool request_up));
+ MOCK_METHOD2(SetMacAddress,
+ bool(const char* if_name, const std::array<uint8_t, ETH_ALEN>& address));
+ MOCK_METHOD1(GetFactoryMacAddress, std::array<uint8_t, ETH_ALEN>(const char* if_name));
+
+}; // class MockInterfaceTool
+
+} // namespace wifi_system
+} // namespace android
+
+#endif // MOCK_INTERFACE_TOOL_H
diff --git a/wifi/aidl/default/tests/mock_wifi_feature_flags.cpp b/wifi/aidl/default/tests/mock_wifi_feature_flags.cpp
new file mode 100644
index 0000000..0c4e59d
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_wifi_feature_flags.cpp
@@ -0,0 +1,33 @@
+/*
+ * 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 <gmock/gmock.h>
+
+#include "mock_wifi_feature_flags.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace feature_flags {
+
+MockWifiFeatureFlags::MockWifiFeatureFlags() {}
+
+} // namespace feature_flags
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/tests/mock_wifi_feature_flags.h b/wifi/aidl/default/tests/mock_wifi_feature_flags.h
new file mode 100644
index 0000000..9143d15
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_wifi_feature_flags.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.
+ */
+
+#ifndef MOCK_WIFI_FEATURE_FLAGS_H_
+#define MOCK_WIFI_FEATURE_FLAGS_H_
+
+#include <gmock/gmock.h>
+
+#include "wifi_feature_flags.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace feature_flags {
+
+class MockWifiFeatureFlags : public WifiFeatureFlags {
+ public:
+ MockWifiFeatureFlags();
+
+ MOCK_METHOD1(getChipModes, std::vector<IWifiChip::ChipMode>(bool is_primary));
+ MOCK_METHOD0(isApMacRandomizationDisabled, bool());
+};
+
+} // namespace feature_flags
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // MOCK_WIFI_FEATURE_FLAGS_H_
diff --git a/wifi/aidl/default/tests/mock_wifi_iface_util.cpp b/wifi/aidl/default/tests/mock_wifi_iface_util.cpp
new file mode 100644
index 0000000..0f787f2
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_wifi_iface_util.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.
+ */
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#include "mock_wifi_iface_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace iface_util {
+
+MockWifiIfaceUtil::MockWifiIfaceUtil(
+ const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+ : WifiIfaceUtil(iface_tool, legacy_hal) {}
+
+} // namespace iface_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/tests/mock_wifi_iface_util.h b/wifi/aidl/default/tests/mock_wifi_iface_util.h
new file mode 100644
index 0000000..49a8636
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_wifi_iface_util.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.
+ */
+
+#ifndef MOCK_WIFI_IFACE_UTIL_H_
+#define MOCK_WIFI_IFACE_UTIL_H_
+
+#include <gmock/gmock.h>
+
+#include "wifi_iface_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace iface_util {
+
+class MockWifiIfaceUtil : public iface_util::WifiIfaceUtil {
+ public:
+ MockWifiIfaceUtil(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+ MOCK_METHOD1(getFactoryMacAddress, std::array<uint8_t, 6>(const std::string&));
+ MOCK_METHOD2(setMacAddress, bool(const std::string&, const std::array<uint8_t, 6>&));
+ MOCK_METHOD0(getOrCreateRandomMacAddress, std::array<uint8_t, 6>());
+ MOCK_METHOD2(registerIfaceEventHandlers,
+ void(const std::string&, iface_util::IfaceEventHandlers));
+ MOCK_METHOD1(unregisterIfaceEventHandlers, void(const std::string&));
+ MOCK_METHOD2(setUpState, bool(const std::string&, bool));
+ MOCK_METHOD1(ifNameToIndex, unsigned(const std::string&));
+};
+
+} // namespace iface_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // MOCK_WIFI_IFACE_UTIL_H_
diff --git a/wifi/aidl/default/tests/mock_wifi_legacy_hal.cpp b/wifi/aidl/default/tests/mock_wifi_legacy_hal.cpp
new file mode 100644
index 0000000..33b2b1c
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_wifi_legacy_hal.cpp
@@ -0,0 +1,37 @@
+/*
+ * 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-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#include "mock_wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace legacy_hal {
+
+MockWifiLegacyHal::MockWifiLegacyHal(
+ const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const wifi_hal_fn& fn, bool is_primary)
+ : WifiLegacyHal(iface_tool, fn, is_primary) {}
+} // namespace legacy_hal
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/tests/mock_wifi_legacy_hal.h b/wifi/aidl/default/tests/mock_wifi_legacy_hal.h
new file mode 100644
index 0000000..28129a9
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_wifi_legacy_hal.h
@@ -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.
+ */
+
+#ifndef MOCK_WIFI_LEGACY_HAL_H_
+#define MOCK_WIFI_LEGACY_HAL_H_
+
+#include <gmock/gmock.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace legacy_hal {
+
+class MockWifiLegacyHal : public WifiLegacyHal {
+ public:
+ MockWifiLegacyHal(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const wifi_hal_fn& fn, bool is_primary);
+ MOCK_METHOD0(initialize, wifi_error());
+ MOCK_METHOD0(start, wifi_error());
+ MOCK_METHOD2(stop,
+ wifi_error(std::unique_lock<std::recursive_mutex>*, const std::function<void()>&));
+ MOCK_METHOD2(setDfsFlag, wifi_error(const std::string&, bool));
+ MOCK_METHOD2(registerRadioModeChangeCallbackHandler,
+ wifi_error(const std::string&, const on_radio_mode_change_callback&));
+ MOCK_METHOD1(getFirmwareVersion,
+ std::pair<wifi_error, std::string>(const std::string& iface_name));
+ MOCK_METHOD1(getDriverVersion,
+ std::pair<wifi_error, std::string>(const std::string& iface_name));
+
+ MOCK_METHOD2(selectTxPowerScenario,
+ wifi_error(const std::string& iface_name, wifi_power_scenario scenario));
+ MOCK_METHOD1(resetTxPowerScenario, wifi_error(const std::string& iface_name));
+ MOCK_METHOD2(nanRegisterCallbackHandlers,
+ wifi_error(const std::string&, const NanCallbackHandlers&));
+ MOCK_METHOD2(nanDisableRequest, wifi_error(const std::string&, transaction_id));
+ MOCK_METHOD3(nanDataInterfaceDelete,
+ wifi_error(const std::string&, transaction_id, const std::string&));
+ MOCK_METHOD2(createVirtualInterface,
+ wifi_error(const std::string& ifname, wifi_interface_type iftype));
+ MOCK_METHOD1(deleteVirtualInterface, wifi_error(const std::string& ifname));
+ MOCK_METHOD0(waitForDriverReady, wifi_error());
+ MOCK_METHOD2(getSupportedIfaceName, wifi_error(uint32_t, std::string&));
+ MOCK_METHOD1(registerSubsystemRestartCallbackHandler,
+ wifi_error(const on_subsystem_restart_callback&));
+ MOCK_METHOD1(getSupportedFeatureSet, std::pair<wifi_error, uint64_t>(const std::string&));
+};
+} // namespace legacy_hal
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // MOCK_WIFI_LEGACY_HAL_H_
diff --git a/wifi/aidl/default/tests/mock_wifi_mode_controller.cpp b/wifi/aidl/default/tests/mock_wifi_mode_controller.cpp
new file mode 100644
index 0000000..f4cc4c4
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_wifi_mode_controller.cpp
@@ -0,0 +1,36 @@
+/*
+ * 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-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#undef NAN // This is weird, NAN is defined in bionic/libc/include/math.h:38
+#include "mock_wifi_mode_controller.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace mode_controller {
+
+MockWifiModeController::MockWifiModeController() : WifiModeController() {}
+
+} // namespace mode_controller
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/tests/mock_wifi_mode_controller.h b/wifi/aidl/default/tests/mock_wifi_mode_controller.h
new file mode 100644
index 0000000..f77f7d0
--- /dev/null
+++ b/wifi/aidl/default/tests/mock_wifi_mode_controller.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.
+ */
+
+#ifndef MOCK_WIFI_MODE_CONTROLLER_H_
+#define MOCK_WIFI_MODE_CONTROLLER_H_
+
+#include <gmock/gmock.h>
+
+#include "wifi_mode_controller.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace mode_controller {
+
+class MockWifiModeController : public WifiModeController {
+ public:
+ MockWifiModeController();
+ MOCK_METHOD0(initialize, bool());
+ MOCK_METHOD1(changeFirmwareMode, bool(IfaceType));
+ MOCK_METHOD1(isFirmwareModeChangeNeeded, bool(IfaceType));
+ MOCK_METHOD0(deinitialize, bool());
+};
+} // namespace mode_controller
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // MOCK_WIFI_MODE_CONTROLLER_H_
diff --git a/wifi/aidl/default/tests/ringbuffer_unit_tests.cpp b/wifi/aidl/default/tests/ringbuffer_unit_tests.cpp
new file mode 100644
index 0000000..c257100
--- /dev/null
+++ b/wifi/aidl/default/tests/ringbuffer_unit_tests.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.
+ */
+
+#include <gmock/gmock.h>
+
+#include "ringbuffer.h"
+
+using testing::Return;
+using testing::Test;
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+class RingbufferTest : public Test {
+ public:
+ const uint32_t maxBufferSize_ = 10;
+ Ringbuffer buffer_{maxBufferSize_};
+};
+
+TEST_F(RingbufferTest, CreateEmptyBuffer) {
+ ASSERT_TRUE(buffer_.getData().empty());
+}
+
+TEST_F(RingbufferTest, CanUseFullBufferCapacity) {
+ const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
+ const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
+ buffer_.append(input);
+ buffer_.append(input2);
+ ASSERT_EQ(2u, buffer_.getData().size());
+ EXPECT_EQ(input, buffer_.getData().front());
+ EXPECT_EQ(input2, buffer_.getData().back());
+}
+
+TEST_F(RingbufferTest, OldDataIsRemovedOnOverflow) {
+ const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
+ const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
+ const std::vector<uint8_t> input3 = {'G'};
+ buffer_.append(input);
+ buffer_.append(input2);
+ buffer_.append(input3);
+ ASSERT_EQ(2u, buffer_.getData().size());
+ EXPECT_EQ(input2, buffer_.getData().front());
+ EXPECT_EQ(input3, buffer_.getData().back());
+}
+
+TEST_F(RingbufferTest, MultipleOldDataIsRemovedOnOverflow) {
+ const std::vector<uint8_t> input(maxBufferSize_ / 2, '0');
+ const std::vector<uint8_t> input2(maxBufferSize_ / 2, '1');
+ const std::vector<uint8_t> input3(maxBufferSize_, '2');
+ buffer_.append(input);
+ buffer_.append(input2);
+ buffer_.append(input3);
+ ASSERT_EQ(1u, buffer_.getData().size());
+ EXPECT_EQ(input3, buffer_.getData().front());
+}
+
+TEST_F(RingbufferTest, AppendingEmptyBufferDoesNotAddGarbage) {
+ const std::vector<uint8_t> input = {};
+ buffer_.append(input);
+ ASSERT_TRUE(buffer_.getData().empty());
+}
+
+TEST_F(RingbufferTest, OversizedAppendIsDropped) {
+ const std::vector<uint8_t> input(maxBufferSize_ + 1, '0');
+ buffer_.append(input);
+ ASSERT_TRUE(buffer_.getData().empty());
+}
+
+TEST_F(RingbufferTest, OversizedAppendDoesNotDropExistingData) {
+ const std::vector<uint8_t> input(maxBufferSize_, '0');
+ const std::vector<uint8_t> input2(maxBufferSize_ + 1, '1');
+ buffer_.append(input);
+ buffer_.append(input2);
+ ASSERT_EQ(1u, buffer_.getData().size());
+ EXPECT_EQ(input, buffer_.getData().front());
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/tests/runtests.sh b/wifi/aidl/default/tests/runtests.sh
new file mode 100755
index 0000000..1f53ab8
--- /dev/null
+++ b/wifi/aidl/default/tests/runtests.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+
+# 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.
+
+if [ -z $ANDROID_BUILD_TOP ]; then
+ echo "You need to source and lunch before you can use this script"
+ exit 1
+fi
+set -e
+
+$ANDROID_BUILD_TOP/build/soong/soong_ui.bash --make-mode android.hardware.wifi-service-tests
+adb root
+adb sync data
+adb shell /data/nativetest64/vendor/android.hardware.wifi-service-tests/android.hardware.wifi-service-tests
diff --git a/wifi/aidl/default/tests/wifi_chip_unit_tests.cpp b/wifi/aidl/default/tests/wifi_chip_unit_tests.cpp
new file mode 100644
index 0000000..e66b650
--- /dev/null
+++ b/wifi/aidl/default/tests/wifi_chip_unit_tests.cpp
@@ -0,0 +1,855 @@
+/*
+ * 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-base/logging.h>
+#include <android-base/macros.h>
+#include <cutils/properties.h>
+#include <gmock/gmock.h>
+
+#include "wifi_chip.h"
+
+#include "mock_interface_tool.h"
+#include "mock_wifi_feature_flags.h"
+#include "mock_wifi_iface_util.h"
+#include "mock_wifi_legacy_hal.h"
+#include "mock_wifi_mode_controller.h"
+
+using testing::NiceMock;
+using testing::Return;
+using testing::Test;
+
+namespace {
+constexpr int kFakeChipId = 5;
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+class WifiChipTest : public Test {
+ protected:
+ void setupV1IfaceCombination() {
+ // clang-format off
+ // 1 STA + 1 P2P
+ const std::vector<IWifiChip::ChipConcurrencyCombination> combinationsSta =
+ {
+ {
+ {
+ {{IfaceConcurrencyType::STA}, 1},
+ {{IfaceConcurrencyType::P2P}, 1}
+ }
+ }
+ };
+ // 1 AP
+ const std::vector<IWifiChip::ChipConcurrencyCombination> combinationsAp =
+ {
+ {
+ {
+ {{IfaceConcurrencyType::AP}, 1}
+ }
+ }
+ };
+ const std::vector<IWifiChip::ChipMode> modes = {
+ {feature_flags::chip_mode_ids::kV1Sta, combinationsSta},
+ {feature_flags::chip_mode_ids::kV1Ap, combinationsAp}
+ };
+ // clang-format on
+ EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
+ }
+
+ void setupV1_AwareIfaceCombination() {
+ // clang-format off
+ // 1 STA + 1 of (P2P or NAN)
+ const std::vector<IWifiChip::ChipConcurrencyCombination> combinationsSta =
+ {
+ {
+ {
+ {{IfaceConcurrencyType::STA}, 1},
+ {{IfaceConcurrencyType::P2P, IfaceConcurrencyType::NAN_IFACE}, 1}
+ }
+ }
+ };
+ // 1 AP
+ const std::vector<IWifiChip::ChipConcurrencyCombination> combinationsAp =
+ {
+ {
+ {
+ {{IfaceConcurrencyType::AP}, 1}
+ }
+ }
+ };
+ const std::vector<IWifiChip::ChipMode> modes = {
+ {feature_flags::chip_mode_ids::kV1Sta, combinationsSta},
+ {feature_flags::chip_mode_ids::kV1Ap, combinationsAp}
+ };
+ // clang-format on
+ EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
+ }
+
+ void setupV1_AwareDisabledApIfaceCombination() {
+ // clang-format off
+ // 1 STA + 1 of (P2P or NAN)
+ const std::vector<IWifiChip::ChipConcurrencyCombination> combinationsSta =
+ {
+ {
+ {
+ {{IfaceConcurrencyType::STA}, 1},
+ {{IfaceConcurrencyType::P2P, IfaceConcurrencyType::NAN_IFACE}, 1}
+ }
+ }
+ };
+ const std::vector<IWifiChip::ChipMode> modes = {
+ {feature_flags::chip_mode_ids::kV1Sta, combinationsSta}
+ };
+ // clang-format on
+ EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
+ }
+
+ void setupV2_AwareIfaceCombination() {
+ // clang-format off
+ // (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
+ const std::vector<IWifiChip::ChipConcurrencyCombination> combinations =
+ {
+ {
+ {
+ {{IfaceConcurrencyType::STA}, 1},
+ {{IfaceConcurrencyType::AP}, 1}
+ }
+ },
+ {
+ {
+ {{IfaceConcurrencyType::STA}, 1},
+ {{IfaceConcurrencyType::P2P, IfaceConcurrencyType::NAN_IFACE}, 1}
+ }
+ }
+ };
+ const std::vector<IWifiChip::ChipMode> modes = {
+ {feature_flags::chip_mode_ids::kV3, combinations}
+ };
+ // clang-format on
+ EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
+ }
+
+ void setupV2_AwareDisabledApIfaceCombination() {
+ // clang-format off
+ // 1 STA + 1 of (P2P or NAN)
+ const std::vector<IWifiChip::ChipConcurrencyCombination> combinations =
+ {
+ {
+ {
+ {{IfaceConcurrencyType::STA}, 1},
+ {{IfaceConcurrencyType::P2P, IfaceConcurrencyType::NAN_IFACE}, 1}
+ }
+ }
+ };
+ const std::vector<IWifiChip::ChipMode> modes = {
+ {feature_flags::chip_mode_ids::kV3, combinations}
+ };
+ // clang-format on
+ EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
+ }
+
+ void setup_MultiIfaceCombination() {
+ // clang-format off
+ // 3 STA + 1 AP
+ const std::vector<IWifiChip::ChipConcurrencyCombination> combinations =
+ {
+ {
+ {
+ {{IfaceConcurrencyType::STA}, 3},
+ {{IfaceConcurrencyType::AP}, 1}
+ }
+ }
+ };
+ const std::vector<IWifiChip::ChipMode> modes = {
+ {feature_flags::chip_mode_ids::kV3, combinations}
+ };
+ // clang-format on
+ EXPECT_CALL(*feature_flags_, getChipModes(true)).WillRepeatedly(testing::Return(modes));
+ }
+
+ void assertNumberOfModes(uint32_t num_modes) {
+ std::vector<IWifiChip::ChipMode> modes;
+ ASSERT_TRUE(chip_->getAvailableModes(&modes).isOk());
+ // V2_Aware has 1 mode of operation.
+ ASSERT_EQ(num_modes, modes.size());
+ }
+
+ void findModeAndConfigureForIfaceType(const IfaceConcurrencyType& type) {
+ // This should be aligned with kInvalidModeId in wifi_chip.cpp
+ int32_t mode_id = INT32_MAX;
+ std::vector<IWifiChip::ChipMode> modes;
+ ASSERT_TRUE(chip_->getAvailableModes(&modes).isOk());
+
+ for (const auto& mode : modes) {
+ for (const auto& combination : mode.availableCombinations) {
+ for (const auto& limit : combination.limits) {
+ if (limit.types.end() !=
+ std::find(limit.types.begin(), limit.types.end(), type)) {
+ mode_id = mode.id;
+ }
+ }
+ }
+ }
+
+ ASSERT_NE(INT32_MAX, mode_id);
+ ASSERT_TRUE(chip_->configureChip(mode_id).isOk());
+ }
+
+ // Returns an empty string on error.
+ std::string createIface(const IfaceType& type) {
+ std::string iface_name;
+ if (type == IfaceType::AP) {
+ std::shared_ptr<IWifiApIface> iface;
+ if (!chip_->createApIface(&iface).isOk()) {
+ return "";
+ }
+ EXPECT_NE(iface.get(), nullptr);
+ EXPECT_TRUE(iface->getName(&iface_name).isOk());
+ } else if (type == IfaceType::NAN_IFACE) {
+ std::shared_ptr<IWifiNanIface> iface;
+ if (!chip_->createNanIface(&iface).isOk()) {
+ return "";
+ }
+ EXPECT_NE(iface.get(), nullptr);
+ EXPECT_TRUE(iface->getName(&iface_name).isOk());
+ } else if (type == IfaceType::P2P) {
+ std::shared_ptr<IWifiP2pIface> iface;
+ if (!chip_->createP2pIface(&iface).isOk()) {
+ return "";
+ }
+ EXPECT_NE(iface.get(), nullptr);
+ EXPECT_TRUE(iface->getName(&iface_name).isOk());
+ } else if (type == IfaceType::STA) {
+ std::shared_ptr<IWifiStaIface> iface;
+ if (!chip_->createStaIface(&iface).isOk()) {
+ return "";
+ }
+ EXPECT_NE(iface.get(), nullptr);
+ EXPECT_TRUE(iface->getName(&iface_name).isOk());
+ }
+ return iface_name;
+ }
+
+ void removeIface(const IfaceType& type, const std::string& iface_name) {
+ if (type == IfaceType::AP) {
+ ASSERT_TRUE(chip_->removeApIface(iface_name).isOk());
+ } else if (type == IfaceType::NAN_IFACE) {
+ ASSERT_TRUE(chip_->removeNanIface(iface_name).isOk());
+ } else if (type == IfaceType::P2P) {
+ ASSERT_TRUE(chip_->removeP2pIface(iface_name).isOk());
+ } else if (type == IfaceType::STA) {
+ ASSERT_TRUE(chip_->removeStaIface(iface_name).isOk());
+ }
+ }
+
+ bool createRttController() {
+ std::shared_ptr<IWifiRttController> rtt_controller;
+ auto status = chip_->createRttController(nullptr, &rtt_controller);
+ return status.isOk();
+ }
+
+ static void subsystemRestartHandler(const std::string& /*error*/) {}
+
+ std::shared_ptr<WifiChip> chip_;
+ int chip_id_ = kFakeChipId;
+ legacy_hal::wifi_hal_fn fake_func_table_;
+ std::shared_ptr<NiceMock<::android::wifi_system::MockInterfaceTool>> iface_tool_{
+ new NiceMock<::android::wifi_system::MockInterfaceTool>};
+ std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+ new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_, fake_func_table_, true)};
+ std::shared_ptr<NiceMock<mode_controller::MockWifiModeController>> mode_controller_{
+ new NiceMock<mode_controller::MockWifiModeController>};
+ std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
+ new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_, legacy_hal_)};
+ std::shared_ptr<NiceMock<feature_flags::MockWifiFeatureFlags>> feature_flags_{
+ new NiceMock<feature_flags::MockWifiFeatureFlags>};
+
+ public:
+ void SetUp() override {
+ chip_ = WifiChip::create(chip_id_, true, legacy_hal_, mode_controller_, iface_util_,
+ feature_flags_, subsystemRestartHandler);
+
+ EXPECT_CALL(*mode_controller_, changeFirmwareMode(testing::_))
+ .WillRepeatedly(testing::Return(true));
+ EXPECT_CALL(*legacy_hal_, start())
+ .WillRepeatedly(testing::Return(legacy_hal::WIFI_SUCCESS));
+ // Vendor HAL does not override the name by default.
+ EXPECT_CALL(*legacy_hal_, getSupportedIfaceName(testing::_, testing::_))
+ .WillRepeatedly(testing::Return(legacy_hal::WIFI_ERROR_UNKNOWN));
+ }
+
+ void TearDown() override {
+ // Restore default system iface names (This should ideally be using a
+ // mock).
+ property_set("wifi.interface", "wlan0");
+ property_set("wifi.concurrent.interface", "wlan1");
+ property_set("wifi.aware.interface", nullptr);
+ }
+};
+
+////////// V1 Iface Combinations ////////////
+// Mode 1 - STA + P2P
+// Mode 2 - AP
+class WifiChipV1IfaceCombinationTest : public WifiChipTest {
+ public:
+ void SetUp() override {
+ setupV1IfaceCombination();
+ WifiChipTest::SetUp();
+ // V1 has 2 modes of operation.
+ assertNumberOfModes(2);
+ }
+};
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateNan_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_TRUE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateAp_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_TRUE(createIface(IfaceType::AP).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, StaMode_CreateStaP2p_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateP2p_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1IfaceCombinationTest, ApMode_CreateNan_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_TRUE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+////////// V1 + Aware Iface Combinations ////////////
+// Mode 1 - STA + P2P/NAN
+// Mode 2 - AP
+class WifiChipV1_AwareIfaceCombinationTest : public WifiChipTest {
+ public:
+ void SetUp() override {
+ setupV1_AwareIfaceCombination();
+ WifiChipTest::SetUp();
+ // V1_Aware has 2 modes of operation.
+ assertNumberOfModes(2u);
+ }
+};
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateP2p_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateNan_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateAp_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_TRUE(createIface(IfaceType::AP).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaP2p_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaNan_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaP2PNan_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+ ASSERT_TRUE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ std::string p2p_iface_name = createIface(IfaceType::P2P);
+ ASSERT_FALSE(p2p_iface_name.empty());
+ ASSERT_TRUE(createIface(IfaceType::NAN_IFACE).empty());
+
+ // After removing P2P iface, NAN iface creation should succeed.
+ removeIface(IfaceType::P2P, p2p_iface_name);
+ ASSERT_FALSE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ std::string nan_iface_name = createIface(IfaceType::NAN_IFACE);
+ ASSERT_FALSE(nan_iface_name.empty());
+ ASSERT_TRUE(createIface(IfaceType::P2P).empty());
+
+ // After removing NAN iface, P2P iface creation should succeed.
+ removeIface(IfaceType::NAN_IFACE, nan_iface_name);
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateAp_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateSta_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateP2p_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, ApMode_CreateNan_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_TRUE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, RttControllerFlowApToSta) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ std::string ap_iface_name = createIface(IfaceType::AP);
+ ASSERT_FALSE(ap_iface_name.empty());
+ ASSERT_FALSE(createRttController());
+
+ removeIface(IfaceType::AP, ap_iface_name);
+
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ ASSERT_TRUE(chip_->selectTxPowerScenario(IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF).isOk());
+}
+
+TEST_F(WifiChipV1_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan0");
+ EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ ASSERT_TRUE(chip_->selectTxPowerScenario(IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF).isOk());
+}
+
+////////// V2 + Aware Iface Combinations ////////////
+// Mode 1 - STA + STA/AP
+// - STA + P2P/NAN
+class WifiChipV2_AwareIfaceCombinationTest : public WifiChipTest {
+ public:
+ void SetUp() override {
+ setupV2_AwareIfaceCombination();
+ WifiChipTest::SetUp();
+ // V2_Aware has 1 mode of operation.
+ assertNumberOfModes(1u);
+ }
+};
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateP2p_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNan_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateAp_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaSta_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApSta_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateSta_AfterStaApRemove_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ std::string sta_iface_name = createIface(IfaceType::STA);
+ ASSERT_FALSE(sta_iface_name.empty());
+ std::string ap_iface_name = createIface(IfaceType::AP);
+ ASSERT_FALSE(ap_iface_name.empty());
+
+ ASSERT_TRUE(createIface(IfaceType::STA).empty());
+
+ // After removing AP & STA iface, STA iface creation should succeed.
+ removeIface(IfaceType::STA, sta_iface_name);
+ removeIface(IfaceType::AP, ap_iface_name);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2p_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaNan_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2PNan_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+ ASSERT_TRUE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaNan_AfterP2pRemove_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ std::string p2p_iface_name = createIface(IfaceType::P2P);
+ ASSERT_FALSE(p2p_iface_name.empty());
+ ASSERT_TRUE(createIface(IfaceType::NAN_IFACE).empty());
+
+ // After removing P2P iface, NAN iface creation should succeed.
+ removeIface(IfaceType::P2P, p2p_iface_name);
+ ASSERT_FALSE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaP2p_AfterNanRemove_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ std::string nan_iface_name = createIface(IfaceType::NAN_IFACE);
+ ASSERT_FALSE(nan_iface_name.empty());
+ ASSERT_TRUE(createIface(IfaceType::P2P).empty());
+
+ // After removing NAN iface, P2P iface creation should succeed.
+ removeIface(IfaceType::NAN_IFACE, nan_iface_name);
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApNan_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_FALSE(createIface(IfaceType::AP).empty());
+ ASSERT_TRUE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateApP2p_ShouldFail) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_FALSE(createIface(IfaceType::AP).empty());
+ ASSERT_TRUE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, StaMode_CreateStaNan_AfterP2pRemove_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ std::string p2p_iface_name = createIface(IfaceType::P2P);
+ ASSERT_FALSE(p2p_iface_name.empty());
+ ASSERT_TRUE(createIface(IfaceType::NAN_IFACE).empty());
+
+ // After removing P2P iface, NAN iface creation should succeed.
+ removeIface(IfaceType::P2P, p2p_iface_name);
+ ASSERT_FALSE(createIface(IfaceType::NAN_IFACE).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, StaMode_CreateStaP2p_AfterNanRemove_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ std::string nan_iface_name = createIface(IfaceType::NAN_IFACE);
+ ASSERT_FALSE(nan_iface_name.empty());
+ ASSERT_TRUE(createIface(IfaceType::P2P).empty());
+
+ // After removing NAN iface, P2P iface creation should succeed.
+ removeIface(IfaceType::NAN_IFACE, nan_iface_name);
+ ASSERT_FALSE(createIface(IfaceType::P2P).empty());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateStaAp_EnsureDifferentIfaceNames) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ std::string sta_iface_name = createIface(IfaceType::STA);
+ std::string ap_iface_name = createIface(IfaceType::AP);
+ ASSERT_FALSE(sta_iface_name.empty());
+ ASSERT_FALSE(ap_iface_name.empty());
+ ASSERT_NE(sta_iface_name, ap_iface_name);
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeNoSta) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlowStaModeWithSta) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, RttControllerFlow) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::AP).empty());
+ ASSERT_TRUE(createRttController());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlySta) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan0", testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ ASSERT_TRUE(chip_->selectTxPowerScenario(IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF).isOk());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, SelectTxScenarioWithOnlyAp) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::AP);
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan1");
+ EXPECT_CALL(*legacy_hal_, selectTxPowerScenario("wlan1", testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ ASSERT_TRUE(chip_->selectTxPowerScenario(IWifiChip::TxPowerScenario::ON_HEAD_CELL_OFF).isOk());
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, InvalidateAndRemoveNanOnStaRemove) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+
+ // Create NAN iface
+ ASSERT_EQ(createIface(IfaceType::NAN_IFACE), "wlan0");
+
+ // We should have 1 nan iface.
+ std::vector<std::string> iface_names;
+ ASSERT_TRUE(chip_->getNanIfaceNames(&iface_names).isOk());
+ ASSERT_EQ(iface_names.size(), 1u);
+ ASSERT_EQ(iface_names[0], "wlan0");
+
+ // Retrieve the nan iface object.
+ std::shared_ptr<IWifiNanIface> nan_iface;
+ ASSERT_TRUE(chip_->getNanIface("wlan0", &nan_iface).isOk());
+ ASSERT_NE(nan_iface.get(), nullptr);
+
+ // Remove the STA iface. We should have 0 nan ifaces now.
+ removeIface(IfaceType::STA, "wlan0");
+ ASSERT_TRUE(chip_->getNanIfaceNames(&iface_names).isOk());
+ ASSERT_EQ(iface_names.size(), 0u);
+
+ // Any operation on the nan iface object should now return an error.
+ std::string name;
+ auto status = nan_iface->getName(&name);
+ ASSERT_EQ(status.getServiceSpecificError(),
+ static_cast<int32_t>(WifiStatusCode::ERROR_WIFI_IFACE_INVALID));
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, InvalidateAndRemoveRttControllerOnStaRemove) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+
+ // Create RTT controller
+ std::shared_ptr<IWifiRttController> rtt_controller;
+ ASSERT_TRUE(chip_->createRttController(nullptr, &rtt_controller).isOk());
+
+ // Remove the STA iface.
+ removeIface(IfaceType::STA, "wlan0");
+
+ // Any operation on the rtt controller object should now return an error.
+ std::shared_ptr<IWifiStaIface> bound_iface;
+ auto status = rtt_controller->getBoundIface(&bound_iface);
+ ASSERT_EQ(status.getServiceSpecificError(),
+ static_cast<int32_t>(WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID));
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNanWithSharedNanIface) {
+ property_set("wifi.aware.interface", nullptr);
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ ASSERT_EQ(createIface(IfaceType::NAN_IFACE), "wlan0");
+ removeIface(IfaceType::NAN_IFACE, "wlan0");
+ EXPECT_CALL(*iface_util_, setUpState(testing::_, testing::_)).Times(0);
+}
+
+TEST_F(WifiChipV2_AwareIfaceCombinationTest, CreateNanWithDedicatedNanIface) {
+ property_set("wifi.aware.interface", "aware0");
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ EXPECT_CALL(*iface_util_, ifNameToIndex("aware0")).WillOnce(testing::Return(4));
+ EXPECT_CALL(*iface_util_, setUpState("aware0", true)).WillOnce(testing::Return(true));
+ ASSERT_EQ(createIface(IfaceType::NAN_IFACE), "aware0");
+
+ EXPECT_CALL(*iface_util_, setUpState("aware0", false)).WillOnce(testing::Return(true));
+ removeIface(IfaceType::NAN_IFACE, "aware0");
+}
+
+////////// V1 Iface Combinations when AP creation is disabled //////////
+class WifiChipV1_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
+ public:
+ void SetUp() override {
+ setupV1_AwareDisabledApIfaceCombination();
+ WifiChipTest::SetUp();
+ }
+};
+
+TEST_F(WifiChipV1_AwareDisabledApIfaceCombinationTest, StaMode_CreateSta_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_TRUE(createIface(IfaceType::AP).empty());
+}
+
+////////// V2 Iface Combinations when AP creation is disabled //////////
+class WifiChipV2_AwareDisabledApIfaceCombinationTest : public WifiChipTest {
+ public:
+ void SetUp() override {
+ setupV2_AwareDisabledApIfaceCombination();
+ WifiChipTest::SetUp();
+ }
+};
+
+TEST_F(WifiChipV2_AwareDisabledApIfaceCombinationTest, CreateSta_ShouldSucceed) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_TRUE(createIface(IfaceType::AP).empty());
+}
+
+////////// Hypothetical Iface Combination with multiple ifaces //////////
+class WifiChip_MultiIfaceTest : public WifiChipTest {
+ public:
+ void SetUp() override {
+ setup_MultiIfaceCombination();
+ WifiChipTest::SetUp();
+ }
+};
+
+TEST_F(WifiChip_MultiIfaceTest, Create3Sta) {
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_FALSE(createIface(IfaceType::STA).empty());
+ ASSERT_TRUE(createIface(IfaceType::STA).empty());
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateStaWithDefaultNames) {
+ property_set("wifi.interface.0", "");
+ property_set("wifi.interface.1", "");
+ property_set("wifi.interface.2", "");
+ property_set("wifi.interface", "");
+ property_set("wifi.concurrent.interface", "");
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan1");
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomNames) {
+ property_set("wifi.interface.0", "test0");
+ property_set("wifi.interface.1", "test1");
+ property_set("wifi.interface.2", "test2");
+ property_set("wifi.interface", "bad0");
+ property_set("wifi.concurrent.interface", "bad1");
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "bad0");
+ ASSERT_EQ(createIface(IfaceType::STA), "bad1");
+ ASSERT_EQ(createIface(IfaceType::STA), "test2");
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateStaWithCustomAltNames) {
+ property_set("wifi.interface.0", "");
+ property_set("wifi.interface.1", "");
+ property_set("wifi.interface.2", "");
+ property_set("wifi.interface", "testA0");
+ property_set("wifi.concurrent.interface", "testA1");
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ ASSERT_EQ(createIface(IfaceType::STA), "testA0");
+ ASSERT_EQ(createIface(IfaceType::STA), "testA1");
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan2");
+}
+
+TEST_F(WifiChip_MultiIfaceTest, CreateApStartsWithIdx1) {
+ // WifiChip_MultiIfaceTest iface combo: STAx3 + APx1
+ // When the HAL support dual STAs, AP should start with idx 2.
+ findModeAndConfigureForIfaceType(IfaceConcurrencyType::STA);
+ // First AP will be slotted to wlan1.
+ ASSERT_EQ(createIface(IfaceType::AP), "wlan2");
+ // First STA will be slotted to wlan0.
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan0");
+ // All further STA will be slotted to the remaining free indices.
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan1");
+ ASSERT_EQ(createIface(IfaceType::STA), "wlan3");
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/tests/wifi_iface_util_unit_tests.cpp b/wifi/aidl/default/tests/wifi_iface_util_unit_tests.cpp
new file mode 100644
index 0000000..e0db6fd
--- /dev/null
+++ b/wifi/aidl/default/tests/wifi_iface_util_unit_tests.cpp
@@ -0,0 +1,94 @@
+/*
+ * 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-base/logging.h>
+#include <android-base/macros.h>
+#include <gmock/gmock.h>
+
+#include "wifi_iface_util.h"
+
+#include "mock_interface_tool.h"
+#include "mock_wifi_legacy_hal.h"
+
+using testing::NiceMock;
+using testing::Test;
+
+namespace {
+constexpr uint8_t kValidUnicastLocallyAssignedMacAddressMask = 0x02;
+constexpr uint8_t kMacAddress[] = {0x02, 0x12, 0x45, 0x56, 0xab, 0xcc};
+constexpr char kIfaceName[] = "test-wlan0";
+
+bool isValidUnicastLocallyAssignedMacAddress(const std::array<uint8_t, 6>& mac_address) {
+ uint8_t first_byte = mac_address[0];
+ return (first_byte & 0x3) == kValidUnicastLocallyAssignedMacAddressMask;
+}
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace iface_util {
+
+class WifiIfaceUtilTest : public Test {
+ protected:
+ std::shared_ptr<NiceMock<::android::wifi_system::MockInterfaceTool>> iface_tool_{
+ new NiceMock<::android::wifi_system::MockInterfaceTool>};
+ legacy_hal::wifi_hal_fn fake_func_table_;
+ std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+ new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_, fake_func_table_, true)};
+ WifiIfaceUtil* iface_util_ = new WifiIfaceUtil(iface_tool_, legacy_hal_);
+};
+
+TEST_F(WifiIfaceUtilTest, GetOrCreateRandomMacAddress) {
+ auto mac_address = iface_util_->getOrCreateRandomMacAddress();
+ ASSERT_TRUE(isValidUnicastLocallyAssignedMacAddress(mac_address));
+
+ // All further calls should return the same MAC address.
+ ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress());
+ ASSERT_EQ(mac_address, iface_util_->getOrCreateRandomMacAddress());
+}
+
+TEST_F(WifiIfaceUtilTest, IfaceEventHandlers_SetMacAddress) {
+ std::array<uint8_t, 6> mac_address = {};
+ std::copy(std::begin(kMacAddress), std::end(kMacAddress), std::begin(mac_address));
+ EXPECT_CALL(*iface_tool_, SetMacAddress(testing::_, testing::_))
+ .WillRepeatedly(testing::Return(true));
+ EXPECT_CALL(*iface_tool_, SetUpState(testing::_, testing::_))
+ .WillRepeatedly(testing::Return(true));
+
+ // Register for iface state toggle events.
+ bool callback_invoked = false;
+ iface_util::IfaceEventHandlers event_handlers = {};
+ event_handlers.on_state_toggle_off_on =
+ [&callback_invoked](const std::string& /* iface_name */) { callback_invoked = true; };
+ iface_util_->registerIfaceEventHandlers(kIfaceName, event_handlers);
+ // Invoke setMacAddress and ensure that the cb is invoked.
+ ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address));
+ ASSERT_TRUE(callback_invoked);
+
+ // Unregister for iface state toggle events.
+ callback_invoked = false;
+ iface_util_->unregisterIfaceEventHandlers(kIfaceName);
+ // Invoke setMacAddress and ensure that the cb is not invoked.
+ ASSERT_TRUE(iface_util_->setMacAddress(kIfaceName, mac_address));
+ ASSERT_FALSE(callback_invoked);
+}
+} // namespace iface_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp b/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp
new file mode 100644
index 0000000..d40801f
--- /dev/null
+++ b/wifi/aidl/default/tests/wifi_nan_iface_unit_tests.cpp
@@ -0,0 +1,168 @@
+/*
+ * 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-base/logging.h>
+#include <android-base/macros.h>
+#include <cutils/properties.h>
+#include <gmock/gmock.h>
+
+#include "wifi_nan_iface.h"
+
+#include "mock_interface_tool.h"
+#include "mock_wifi_feature_flags.h"
+#include "mock_wifi_iface_util.h"
+#include "mock_wifi_legacy_hal.h"
+
+using testing::NiceMock;
+using testing::Return;
+using testing::Test;
+
+namespace {
+constexpr char kIfaceName[] = "mockWlan0";
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+bool CaptureIfaceEventHandlers(const std::string& /* iface_name*/,
+ iface_util::IfaceEventHandlers in_iface_event_handlers,
+ iface_util::IfaceEventHandlers* out_iface_event_handlers) {
+ *out_iface_event_handlers = in_iface_event_handlers;
+ return true;
+}
+
+class MockNanIface : public WifiNanIface {
+ public:
+ MockNanIface(const std::string& ifname, bool is_dedicated_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
+ : WifiNanIface(ifname, is_dedicated_iface, legacy_hal, iface_util) {}
+
+ static std::shared_ptr<MockNanIface> createMock(
+ const std::string& ifname, bool is_dedicated_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util) {
+ std::shared_ptr<MockNanIface> ptr = ndk::SharedRefBase::make<MockNanIface>(
+ ifname, is_dedicated_iface, legacy_hal, iface_util);
+ std::weak_ptr<MockNanIface> weak_ptr_this(ptr);
+ ptr->setWeakPtr(weak_ptr_this);
+ ptr->registerCallbackHandlers();
+ return ptr;
+ }
+
+ // Override getEventCallbacks() so that we can return a mocked callback object.
+ std::set<std::shared_ptr<IWifiNanIfaceEventCallback>> getEventCallbacks() override {
+ return {callback_};
+ }
+
+ void setMockCallback(std::shared_ptr<IWifiNanIfaceEventCallback> cb) { callback_ = cb; }
+
+ private:
+ std::shared_ptr<IWifiNanIfaceEventCallback> callback_;
+};
+
+class MockNanIfaceEventCallback : public IWifiNanIfaceEventCallback {
+ public:
+ ndk::SpAIBinder asBinder() override { return ::ndk::SpAIBinder{}; }
+ bool isRemote() override { return false; }
+
+ ::ndk::ScopedAStatus getInterfaceVersion(int32_t* _aidl_return) override {
+ *_aidl_return = 1;
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus getInterfaceHash(std::string* _aidl_return) override {
+ *_aidl_return = "some_hash";
+ return ndk::ScopedAStatus::ok();
+ }
+
+ MOCK_METHOD3(notifyCapabilitiesResponse,
+ ndk::ScopedAStatus(char16_t, const NanStatus&, const NanCapabilities&));
+ MOCK_METHOD2(notifyEnableResponse, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD2(notifyConfigResponse, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD2(notifyDisableResponse, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD3(notifyStartPublishResponse,
+ ndk::ScopedAStatus(char16_t, const NanStatus&, int8_t));
+ MOCK_METHOD2(notifyStopPublishResponse, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD3(notifyStartSubscribeResponse,
+ ndk::ScopedAStatus(char16_t, const NanStatus&, int8_t));
+ MOCK_METHOD2(notifyStopSubscribeResponse, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD2(notifyTransmitFollowupResponse, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD2(notifyCreateDataInterfaceResponse, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD2(notifyDeleteDataInterfaceResponse, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD3(notifyInitiateDataPathResponse,
+ ndk::ScopedAStatus(char16_t, const NanStatus&, int32_t));
+ MOCK_METHOD2(notifyRespondToDataPathIndicationResponse,
+ ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD2(notifyTerminateDataPathResponse, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD1(eventClusterEvent, ndk::ScopedAStatus(const NanClusterEventInd&));
+ MOCK_METHOD1(eventDisabled, ndk::ScopedAStatus(const NanStatus&));
+ MOCK_METHOD2(eventPublishTerminated, ndk::ScopedAStatus(int8_t, const NanStatus&));
+ MOCK_METHOD2(eventSubscribeTerminated, ndk::ScopedAStatus(int8_t, const NanStatus&));
+ MOCK_METHOD1(eventMatch, ndk::ScopedAStatus(const NanMatchInd&));
+ MOCK_METHOD2(eventMatchExpired, ndk::ScopedAStatus(int8_t, int32_t));
+ MOCK_METHOD1(eventFollowupReceived, ndk::ScopedAStatus(const NanFollowupReceivedInd&));
+ MOCK_METHOD2(eventTransmitFollowup, ndk::ScopedAStatus(char16_t, const NanStatus&));
+ MOCK_METHOD1(eventDataPathRequest, ndk::ScopedAStatus(const NanDataPathRequestInd&));
+ MOCK_METHOD1(eventDataPathConfirm, ndk::ScopedAStatus(const NanDataPathConfirmInd&));
+ MOCK_METHOD1(eventDataPathTerminated, ndk::ScopedAStatus(int32_t));
+ MOCK_METHOD1(eventDataPathScheduleUpdate,
+ ndk::ScopedAStatus(const NanDataPathScheduleUpdateInd&));
+};
+
+class WifiNanIfaceTest : public Test {
+ protected:
+ legacy_hal::wifi_hal_fn fake_func_table_;
+ std::shared_ptr<NiceMock<::android::wifi_system::MockInterfaceTool>> iface_tool_{
+ new NiceMock<::android::wifi_system::MockInterfaceTool>};
+ std::shared_ptr<NiceMock<legacy_hal::MockWifiLegacyHal>> legacy_hal_{
+ new NiceMock<legacy_hal::MockWifiLegacyHal>(iface_tool_, fake_func_table_, true)};
+ std::shared_ptr<NiceMock<iface_util::MockWifiIfaceUtil>> iface_util_{
+ new NiceMock<iface_util::MockWifiIfaceUtil>(iface_tool_, legacy_hal_)};
+};
+
+TEST_F(WifiNanIfaceTest, IfacEventHandlers_OnStateToggleOffOn) {
+ // Ensure that event handlers are registered during nan iface creation.
+ iface_util::IfaceEventHandlers captured_iface_event_handlers = {};
+ EXPECT_CALL(*legacy_hal_, nanRegisterCallbackHandlers(testing::_, testing::_))
+ .WillOnce(testing::Return(legacy_hal::WIFI_SUCCESS));
+ EXPECT_CALL(*iface_util_, registerIfaceEventHandlers(testing::_, testing::_))
+ .WillOnce(testing::Invoke(bind(CaptureIfaceEventHandlers, std::placeholders::_1,
+ std::placeholders::_2, &captured_iface_event_handlers)));
+
+ // Create nan iface and register a callback.
+ // Note: Since we can't register a callback directly (gTest fails on
+ // AIBinder_linkToDeath), simulate the registration by overriding
+ // getEventCallbacks() to return our mock callback object.
+ std::shared_ptr<MockNanIface> mock_nan_iface =
+ MockNanIface::createMock(kIfaceName, false, legacy_hal_, iface_util_);
+ std::shared_ptr<MockNanIfaceEventCallback> mock_event_callback =
+ ndk::SharedRefBase::make<MockNanIfaceEventCallback>();
+ mock_nan_iface->setMockCallback(mock_event_callback);
+
+ // Ensure that the eventDisabled() function in the mock callback will be invoked.
+ NanStatus expected_nan_status = {NanStatusCode::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
+ EXPECT_CALL(*mock_event_callback, eventDisabled(expected_nan_status)).Times(1);
+
+ // Trigger the iface state toggle callback.
+ captured_iface_event_handlers.on_state_toggle_off_on(kIfaceName);
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi.cpp b/wifi/aidl/default/wifi.cpp
new file mode 100644
index 0000000..e30c38a
--- /dev/null
+++ b/wifi/aidl/default/wifi.cpp
@@ -0,0 +1,284 @@
+/*
+ * 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 "wifi.h"
+
+#include <android-base/logging.h>
+
+#include "aidl_return_util.h"
+#include "wifi_status_util.h"
+
+namespace {
+// Starting Chip ID, will be assigned to primary chip
+static constexpr int32_t kPrimaryChipId = 0;
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+using aidl_return_util::validateAndCall;
+using aidl_return_util::validateAndCallWithLock;
+
+Wifi::Wifi(const std::shared_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
+ const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
+ const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags)
+ : iface_tool_(iface_tool),
+ legacy_hal_factory_(legacy_hal_factory),
+ mode_controller_(mode_controller),
+ feature_flags_(feature_flags),
+ run_state_(RunState::STOPPED) {}
+
+bool Wifi::isValid() {
+ // This object is always valid.
+ return true;
+}
+
+ndk::ScopedAStatus Wifi::registerEventCallback(
+ const std::shared_ptr<IWifiEventCallback>& in_callback) {
+ return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN,
+ &Wifi::registerEventCallbackInternal, in_callback);
+}
+
+ndk::ScopedAStatus Wifi::isStarted(bool* _aidl_return) {
+ *_aidl_return = (run_state_ != RunState::STOPPED);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Wifi::start() {
+ return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::startInternal);
+}
+
+ndk::ScopedAStatus Wifi::stop() {
+ return validateAndCallWithLock(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::stopInternal);
+}
+
+ndk::ScopedAStatus Wifi::getChipIds(std::vector<int32_t>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipIdsInternal,
+ _aidl_return);
+}
+
+ndk::ScopedAStatus Wifi::getChip(int32_t in_chipId, std::shared_ptr<IWifiChip>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_UNKNOWN, &Wifi::getChipInternal,
+ _aidl_return, in_chipId);
+}
+
+binder_status_t Wifi::dump(int fd, const char** args, uint32_t numArgs) {
+ LOG(INFO) << "-----------Debug was called----------------";
+ if (chips_.size() == 0) {
+ LOG(INFO) << "No chips to display.";
+ return STATUS_OK;
+ }
+
+ for (std::shared_ptr<WifiChip> chip : chips_) {
+ if (!chip.get()) continue;
+ chip->dump(fd, args, numArgs);
+ }
+ return STATUS_OK;
+}
+
+ndk::ScopedAStatus Wifi::registerEventCallbackInternal(
+ const std::shared_ptr<IWifiEventCallback>& event_callback) {
+ if (!event_cb_handler_.addCallback(event_callback)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Wifi::startInternal() {
+ if (run_state_ == RunState::STARTED) {
+ return ndk::ScopedAStatus::ok();
+ } else if (run_state_ == RunState::STOPPING) {
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
+ }
+ ndk::ScopedAStatus wifi_status = initializeModeControllerAndLegacyHal();
+ if (wifi_status.isOk()) {
+ // Register the callback for subsystem restart
+ const auto& on_subsystem_restart_callback = [this](const std::string& error) {
+ ndk::ScopedAStatus wifi_status = createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, error);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ LOG(INFO) << "Attempting to invoke onSubsystemRestart "
+ "callback";
+ WifiStatusCode errorCode =
+ static_cast<WifiStatusCode>(wifi_status.getServiceSpecificError());
+ if (!callback->onSubsystemRestart(errorCode).isOk()) {
+ LOG(ERROR) << "Failed to invoke onSubsystemRestart callback";
+ } else {
+ LOG(INFO) << "Succeeded to invoke onSubsystemRestart "
+ "callback";
+ }
+ }
+ };
+
+ // Create the chip instance once the HAL is started.
+ int32_t chipId = kPrimaryChipId;
+ for (auto& hal : legacy_hals_) {
+ chips_.push_back(
+ WifiChip::create(chipId, chipId == kPrimaryChipId, hal, mode_controller_,
+ std::make_shared<iface_util::WifiIfaceUtil>(iface_tool_, hal),
+ feature_flags_, on_subsystem_restart_callback));
+ chipId++;
+ }
+ run_state_ = RunState::STARTED;
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onStart().isOk()) {
+ LOG(ERROR) << "Failed to invoke onStart callback";
+ };
+ }
+ LOG(INFO) << "Wifi HAL started";
+ } else {
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ WifiStatusCode errorCode =
+ static_cast<WifiStatusCode>(wifi_status.getServiceSpecificError());
+ if (!callback->onFailure(errorCode).isOk()) {
+ LOG(ERROR) << "Failed to invoke onFailure callback";
+ }
+ }
+ LOG(ERROR) << "Wifi HAL start failed";
+ // Clear the event callback objects since the HAL start failed.
+ event_cb_handler_.invalidate();
+ }
+ return wifi_status;
+}
+
+ndk::ScopedAStatus Wifi::stopInternal(
+ /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
+ if (run_state_ == RunState::STOPPED) {
+ return ndk::ScopedAStatus::ok();
+ } else if (run_state_ == RunState::STOPPING) {
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, "HAL is stopping");
+ }
+ // Clear the chip object and its child objects since the HAL is now
+ // stopped.
+ for (auto& chip : chips_) {
+ if (chip.get()) {
+ chip->invalidate();
+ chip.reset();
+ }
+ }
+ chips_.clear();
+ ndk::ScopedAStatus wifi_status = stopLegacyHalAndDeinitializeModeController(lock);
+ if (wifi_status.isOk()) {
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onStop().isOk()) {
+ LOG(ERROR) << "Failed to invoke onStop callback";
+ };
+ }
+ LOG(INFO) << "Wifi HAL stopped";
+ } else {
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ WifiStatusCode errorCode =
+ static_cast<WifiStatusCode>(wifi_status.getServiceSpecificError());
+ if (!callback->onFailure(errorCode).isOk()) {
+ LOG(ERROR) << "Failed to invoke onFailure callback";
+ }
+ }
+ LOG(ERROR) << "Wifi HAL stop failed";
+ }
+ // Clear the event callback objects since the HAL is now stopped.
+ event_cb_handler_.invalidate();
+ return wifi_status;
+}
+
+std::pair<std::vector<int32_t>, ndk::ScopedAStatus> Wifi::getChipIdsInternal() {
+ std::vector<int32_t> chip_ids;
+
+ for (auto& chip : chips_) {
+ int32_t chip_id = getChipIdFromWifiChip(chip);
+ if (chip_id != INT32_MAX) chip_ids.emplace_back(chip_id);
+ }
+ return {std::move(chip_ids), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<IWifiChip>, ndk::ScopedAStatus> Wifi::getChipInternal(int32_t chip_id) {
+ for (auto& chip : chips_) {
+ int32_t cand_id = getChipIdFromWifiChip(chip);
+ if ((cand_id != INT32_MAX) && (cand_id == chip_id)) return {chip, ndk::ScopedAStatus::ok()};
+ }
+
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
+}
+
+ndk::ScopedAStatus Wifi::initializeModeControllerAndLegacyHal() {
+ if (!mode_controller_->initialize()) {
+ LOG(ERROR) << "Failed to initialize firmware mode controller";
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+
+ legacy_hals_ = legacy_hal_factory_->getHals();
+ if (legacy_hals_.empty()) return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ int index = 0; // for failure log
+ for (auto& hal : legacy_hals_) {
+ legacy_hal::wifi_error legacy_status = hal->initialize();
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ // Currently WifiLegacyHal::initialize does not allocate extra mem,
+ // only initializes the function table. If this changes, need to
+ // implement WifiLegacyHal::deinitialize and deinitalize the
+ // HALs already initialized
+ LOG(ERROR) << "Failed to initialize legacy HAL index: " << index
+ << " error: " << legacyErrorToString(legacy_status);
+ return createWifiStatusFromLegacyError(legacy_status);
+ }
+ index++;
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Wifi::stopLegacyHalAndDeinitializeModeController(
+ /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock) {
+ legacy_hal::wifi_error legacy_status = legacy_hal::WIFI_SUCCESS;
+ int index = 0;
+
+ run_state_ = RunState::STOPPING;
+ for (auto& hal : legacy_hals_) {
+ legacy_hal::wifi_error tmp = hal->stop(lock, [&]() {});
+ if (tmp != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to stop legacy HAL index: " << index
+ << " error: " << legacyErrorToString(legacy_status);
+ legacy_status = tmp;
+ }
+ index++;
+ }
+ run_state_ = RunState::STOPPED;
+
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "One or more legacy HALs failed to stop";
+ return createWifiStatusFromLegacyError(legacy_status);
+ }
+ if (!mode_controller_->deinitialize()) {
+ LOG(ERROR) << "Failed to deinitialize firmware mode controller";
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+int32_t Wifi::getChipIdFromWifiChip(std::shared_ptr<WifiChip>& chip) {
+ int32_t chip_id = INT32_MAX;
+ if (chip.get()) {
+ ndk::ScopedAStatus status = chip->getId(&chip_id);
+ if (!status.isOk()) {
+ // Reset value if operation failed.
+ chip_id = INT32_MAX;
+ }
+ }
+ return chip_id;
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi.h b/wifi/aidl/default/wifi.h
new file mode 100644
index 0000000..9334524
--- /dev/null
+++ b/wifi/aidl/default/wifi.h
@@ -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.
+ */
+
+#ifndef WIFI_H_
+#define WIFI_H_
+
+#include <aidl/android/hardware/wifi/BnWifi.h>
+#include <android-base/macros.h>
+#include <utils/Looper.h>
+
+#include <functional>
+
+#include "aidl_callback_util.h"
+#include "wifi_chip.h"
+#include "wifi_feature_flags.h"
+#include "wifi_legacy_hal.h"
+#include "wifi_legacy_hal_factory.h"
+#include "wifi_mode_controller.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+/**
+ * Root AIDL interface object used to control the Wifi HAL.
+ */
+class Wifi : public BnWifi {
+ public:
+ Wifi(const std::shared_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory,
+ const std::shared_ptr<mode_controller::WifiModeController> mode_controller,
+ const std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags);
+
+ bool isValid();
+
+ // AIDL methods exposed.
+ ndk::ScopedAStatus registerEventCallback(
+ const std::shared_ptr<IWifiEventCallback>& in_callback) override;
+ ndk::ScopedAStatus isStarted(bool* _aidl_return) override;
+ ndk::ScopedAStatus start() override;
+ ndk::ScopedAStatus stop() override;
+ ndk::ScopedAStatus getChipIds(std::vector<int32_t>* _aidl_return) override;
+ ndk::ScopedAStatus getChip(int32_t in_chipId,
+ std::shared_ptr<IWifiChip>* _aidl_return) override;
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+ private:
+ enum class RunState { STOPPED, STARTED, STOPPING };
+
+ // Corresponding worker functions for the AIDL methods.
+ ndk::ScopedAStatus registerEventCallbackInternal(
+ const std::shared_ptr<IWifiEventCallback>& event_callback __unused);
+ ndk::ScopedAStatus startInternal();
+ ndk::ScopedAStatus stopInternal(std::unique_lock<std::recursive_mutex>* lock);
+ std::pair<std::vector<int32_t>, ndk::ScopedAStatus> getChipIdsInternal();
+ std::pair<std::shared_ptr<IWifiChip>, ndk::ScopedAStatus> getChipInternal(int32_t chip_id);
+
+ ndk::ScopedAStatus initializeModeControllerAndLegacyHal();
+ ndk::ScopedAStatus stopLegacyHalAndDeinitializeModeController(
+ std::unique_lock<std::recursive_mutex>* lock);
+ int32_t getChipIdFromWifiChip(std::shared_ptr<WifiChip>& chip);
+
+ // Instance is created in this root level |IWifi| AIDL interface object
+ // and shared with all the child AIDL interface objects.
+ std::shared_ptr<::android::wifi_system::InterfaceTool> iface_tool_;
+ std::shared_ptr<legacy_hal::WifiLegacyHalFactory> legacy_hal_factory_;
+ std::shared_ptr<mode_controller::WifiModeController> mode_controller_;
+ std::vector<std::shared_ptr<legacy_hal::WifiLegacyHal>> legacy_hals_;
+ std::shared_ptr<feature_flags::WifiFeatureFlags> feature_flags_;
+ RunState run_state_;
+ std::vector<std::shared_ptr<WifiChip>> chips_;
+ aidl_callback_util::AidlCallbackHandler<IWifiEventCallback> event_cb_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(Wifi);
+};
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_H_
diff --git a/wifi/aidl/default/wifi_ap_iface.cpp b/wifi/aidl/default/wifi_ap_iface.cpp
new file mode 100644
index 0000000..6cd932d
--- /dev/null
+++ b/wifi/aidl/default/wifi_ap_iface.cpp
@@ -0,0 +1,190 @@
+/*
+ * 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 "wifi_ap_iface.h"
+
+#include <android-base/logging.h>
+
+#include "aidl_return_util.h"
+#include "aidl_struct_util.h"
+#include "wifi_status_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+using aidl_return_util::validateAndCall;
+
+WifiApIface::WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
+ : ifname_(ifname),
+ instances_(instances),
+ legacy_hal_(legacy_hal),
+ iface_util_(iface_util),
+ is_valid_(true) {}
+
+void WifiApIface::invalidate() {
+ legacy_hal_.reset();
+ is_valid_ = false;
+}
+
+bool WifiApIface::isValid() {
+ return is_valid_;
+}
+
+std::string WifiApIface::getName() {
+ return ifname_;
+}
+
+void WifiApIface::removeInstance(std::string instance) {
+ instances_.erase(std::remove(instances_.begin(), instances_.end(), instance), instances_.end());
+}
+
+ndk::ScopedAStatus WifiApIface::getName(std::string* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiApIface::getNameInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiApIface::setCountryCode(const std::array<uint8_t, 2>& in_code) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiApIface::setCountryCodeInternal, in_code);
+}
+
+ndk::ScopedAStatus WifiApIface::getValidFrequenciesForBand(WifiBand in_band,
+ std::vector<int32_t>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiApIface::getValidFrequenciesForBandInternal, _aidl_return, in_band);
+}
+
+ndk::ScopedAStatus WifiApIface::setMacAddress(const std::array<uint8_t, 6>& in_mac) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiApIface::setMacAddressInternal, in_mac);
+}
+
+ndk::ScopedAStatus WifiApIface::getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiApIface::getFactoryMacAddressInternal, _aidl_return,
+ instances_.size() > 0 ? instances_[0] : ifname_);
+}
+
+ndk::ScopedAStatus WifiApIface::resetToFactoryMacAddress() {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiApIface::resetToFactoryMacAddressInternal);
+}
+
+ndk::ScopedAStatus WifiApIface::getBridgedInstances(std::vector<std::string>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiApIface::getBridgedInstancesInternal, _aidl_return);
+}
+
+std::pair<std::string, ndk::ScopedAStatus> WifiApIface::getNameInternal() {
+ return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiApIface::setCountryCodeInternal(const std::array<uint8_t, 2>& code) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setCountryCode(
+ instances_.size() > 0 ? instances_[0] : ifname_, code);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<std::vector<int32_t>, ndk::ScopedAStatus> WifiApIface::getValidFrequenciesForBandInternal(
+ WifiBand band) {
+ static_assert(sizeof(WifiChannelWidthInMhz) == sizeof(int32_t), "Size mismatch");
+ legacy_hal::wifi_error legacy_status;
+ std::vector<uint32_t> valid_frequencies;
+ std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand(
+ instances_.size() > 0 ? instances_[0] : ifname_,
+ aidl_struct_util::convertAidlWifiBandToLegacy(band));
+ return {std::vector<int32_t>(valid_frequencies.begin(), valid_frequencies.end()),
+ createWifiStatusFromLegacyError(legacy_status)};
+}
+
+ndk::ScopedAStatus WifiApIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) {
+ // Support random MAC up to 2 interfaces
+ if (instances_.size() == 2) {
+ int rbyte = 1;
+ for (auto const& intf : instances_) {
+ std::array<uint8_t, 6> rmac = mac;
+ // reverse the bits to avoid collision
+ rmac[rbyte] = 0xff - rmac[rbyte];
+ if (!iface_util_.lock()->setMacAddress(intf, rmac)) {
+ LOG(INFO) << "Failed to set random mac address on " << intf;
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ rbyte++;
+ }
+ }
+ // It also needs to set mac address for bridged interface, otherwise the mac
+ // address of bridged interface will be changed after one of instance
+ // down.
+ if (!iface_util_.lock()->setMacAddress(ifname_, mac)) {
+ LOG(ERROR) << "Fail to config MAC for interface " << ifname_;
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::array<uint8_t, 6>, ndk::ScopedAStatus> WifiApIface::getFactoryMacAddressInternal(
+ const std::string& ifaceName) {
+ std::array<uint8_t, 6> mac = iface_util_.lock()->getFactoryMacAddress(ifaceName);
+ if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) {
+ return {mac, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {mac, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiApIface::resetToFactoryMacAddressInternal() {
+ std::pair<std::array<uint8_t, 6>, ndk::ScopedAStatus> getMacResult;
+ if (instances_.size() == 2) {
+ for (auto const& intf : instances_) {
+ getMacResult = getFactoryMacAddressInternal(intf);
+ LOG(DEBUG) << "Reset MAC to factory MAC on " << intf;
+ if (!getMacResult.second.isOk() ||
+ !iface_util_.lock()->setMacAddress(intf, getMacResult.first)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ }
+ // We need to set mac address for bridged interface, otherwise the mac
+ // address of the bridged interface will be changed after one of the
+ // instances goes down. Thus we are generating a random MAC address for
+ // the bridged interface even if we got the request to reset the Factory
+ // MAC. This is because the bridged interface is an internal interface
+ // for the operation of bpf and other networking operations.
+ if (!iface_util_.lock()->setMacAddress(ifname_,
+ iface_util_.lock()->createRandomMacAddress())) {
+ LOG(ERROR) << "Fail to config MAC for bridged interface " << ifname_;
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ } else {
+ getMacResult = getFactoryMacAddressInternal(ifname_);
+ LOG(DEBUG) << "Reset MAC to factory MAC on " << ifname_;
+ if (!getMacResult.second.isOk() ||
+ !iface_util_.lock()->setMacAddress(ifname_, getMacResult.first)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiApIface::getBridgedInstancesInternal() {
+ return {instances_, ndk::ScopedAStatus::ok()};
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_ap_iface.h b/wifi/aidl/default/wifi_ap_iface.h
new file mode 100644
index 0000000..b5673fc
--- /dev/null
+++ b/wifi/aidl/default/wifi_ap_iface.h
@@ -0,0 +1,81 @@
+/*
+ * 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 WIFI_AP_IFACE_H_
+#define WIFI_AP_IFACE_H_
+
+#include <aidl/android/hardware/wifi/BnWifiApIface.h>
+#include <android-base/macros.h>
+
+#include "wifi_iface_util.h"
+#include "wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+/**
+ * AIDL interface object used to control an AP Iface instance.
+ */
+class WifiApIface : public BnWifiApIface {
+ public:
+ WifiApIface(const std::string& ifname, const std::vector<std::string>& instances,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
+ // Refer to |WifiChip::invalidate()|.
+ void invalidate();
+ bool isValid();
+ std::string getName();
+ void removeInstance(std::string instance);
+
+ // AIDL methods exposed.
+ ndk::ScopedAStatus getName(std::string* _aidl_return) override;
+ ndk::ScopedAStatus setCountryCode(const std::array<uint8_t, 2>& in_code) override;
+ ndk::ScopedAStatus getValidFrequenciesForBand(WifiBand in_band,
+ std::vector<int32_t>* _aidl_return) override;
+ ndk::ScopedAStatus setMacAddress(const std::array<uint8_t, 6>& in_mac) override;
+ ndk::ScopedAStatus getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) override;
+ ndk::ScopedAStatus resetToFactoryMacAddress() override;
+ ndk::ScopedAStatus getBridgedInstances(std::vector<std::string>* _aidl_return) override;
+
+ private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<std::string, ndk::ScopedAStatus> getNameInternal();
+ ndk::ScopedAStatus setCountryCodeInternal(const std::array<uint8_t, 2>& code);
+ std::pair<std::vector<int32_t>, ndk::ScopedAStatus> getValidFrequenciesForBandInternal(
+ WifiBand band);
+ ndk::ScopedAStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
+ std::pair<std::array<uint8_t, 6>, ndk::ScopedAStatus> getFactoryMacAddressInternal(
+ const std::string& ifaceName);
+ ndk::ScopedAStatus resetToFactoryMacAddressInternal();
+ std::pair<std::vector<std::string>, ndk::ScopedAStatus> getBridgedInstancesInternal();
+
+ std::string ifname_;
+ std::vector<std::string> instances_;
+ std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
+ bool is_valid_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiApIface);
+};
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_AP_IFACE_H_
diff --git a/wifi/aidl/default/wifi_chip.cpp b/wifi/aidl/default/wifi_chip.cpp
new file mode 100644
index 0000000..076f351
--- /dev/null
+++ b/wifi/aidl/default/wifi_chip.cpp
@@ -0,0 +1,1910 @@
+/*
+ * 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 "wifi_chip.h"
+
+#include <android-base/logging.h>
+#include <android-base/unique_fd.h>
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <sys/stat.h>
+#include <sys/sysmacros.h>
+
+#include "aidl_return_util.h"
+#include "aidl_struct_util.h"
+#include "wifi_status_util.h"
+
+#define P2P_MGMT_DEVICE_PREFIX "p2p-dev-"
+
+namespace {
+using aidl::android::hardware::wifi::IfaceType;
+using aidl::android::hardware::wifi::IWifiChip;
+using CoexRestriction = aidl::android::hardware::wifi::IWifiChip::CoexRestriction;
+using android::base::unique_fd;
+
+constexpr char kCpioMagic[] = "070701";
+constexpr size_t kMaxBufferSizeBytes = 1024 * 1024 * 3;
+constexpr uint32_t kMaxRingBufferFileAgeSeconds = 60 * 60 * 10;
+constexpr uint32_t kMaxRingBufferFileNum = 20;
+constexpr char kTombstoneFolderPath[] = "/data/vendor/tombstones/wifi/";
+constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface";
+constexpr char kNoActiveWlanIfaceNamePropertyValue[] = "";
+constexpr unsigned kMaxWlanIfaces = 5;
+constexpr char kApBridgeIfacePrefix[] = "ap_br_";
+
+template <typename Iface>
+void invalidateAndClear(std::vector<std::shared_ptr<Iface>>& ifaces, std::shared_ptr<Iface> iface) {
+ iface->invalidate();
+ ifaces.erase(std::remove(ifaces.begin(), ifaces.end(), iface), ifaces.end());
+}
+
+template <typename Iface>
+void invalidateAndClearAll(std::vector<std::shared_ptr<Iface>>& ifaces) {
+ for (const auto& iface : ifaces) {
+ iface->invalidate();
+ }
+ ifaces.clear();
+}
+
+template <typename Iface>
+std::vector<std::string> getNames(std::vector<std::shared_ptr<Iface>>& ifaces) {
+ std::vector<std::string> names;
+ for (const auto& iface : ifaces) {
+ names.emplace_back(iface->getName());
+ }
+ return names;
+}
+
+template <typename Iface>
+std::shared_ptr<Iface> findUsingName(std::vector<std::shared_ptr<Iface>>& ifaces,
+ const std::string& name) {
+ std::vector<std::string> names;
+ for (const auto& iface : ifaces) {
+ if (name == iface->getName()) {
+ return iface;
+ }
+ }
+ return nullptr;
+}
+
+std::string getWlanIfaceName(unsigned idx) {
+ if (idx >= kMaxWlanIfaces) {
+ CHECK(false) << "Requested interface beyond wlan" << kMaxWlanIfaces;
+ return {};
+ }
+
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ if (idx == 0 || idx == 1) {
+ const char* altPropName = (idx == 0) ? "wifi.interface" : "wifi.concurrent.interface";
+ auto res = property_get(altPropName, buffer.data(), nullptr);
+ if (res > 0) return buffer.data();
+ }
+ std::string propName = "wifi.interface." + std::to_string(idx);
+ auto res = property_get(propName.c_str(), buffer.data(), nullptr);
+ if (res > 0) return buffer.data();
+
+ return "wlan" + std::to_string(idx);
+}
+
+// Returns the dedicated iface name if defined.
+// Returns two ifaces in bridged mode.
+std::vector<std::string> getPredefinedApIfaceNames(bool is_bridged) {
+ std::vector<std::string> ifnames;
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ buffer.fill(0);
+ if (property_get("ro.vendor.wifi.sap.interface", buffer.data(), nullptr) == 0) {
+ return ifnames;
+ }
+ ifnames.push_back(buffer.data());
+ if (is_bridged) {
+ buffer.fill(0);
+ if (property_get("ro.vendor.wifi.sap.concurrent.iface", buffer.data(), nullptr) == 0) {
+ return ifnames;
+ }
+ ifnames.push_back(buffer.data());
+ }
+ return ifnames;
+}
+
+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 */
+ strlcpy(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();
+}
+
+// Returns the dedicated iface name if one is defined.
+std::string getPredefinedNanIfaceName() {
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ if (property_get("wifi.aware.interface", buffer.data(), nullptr) == 0) {
+ return {};
+ }
+ return buffer.data();
+}
+
+void setActiveWlanIfaceNameProperty(const std::string& ifname) {
+ auto res = property_set(kActiveWlanIfaceNameProperty, ifname.data());
+ if (res != 0) {
+ PLOG(ERROR) << "Failed to set active wlan iface name property";
+ }
+}
+
+// Delete files that meet either condition:
+// 1. Older than a predefined time in the wifi tombstone dir.
+// 2. Files in excess to a predefined amount, starting from the oldest ones
+bool removeOldFilesInternal() {
+ time_t now = time(0);
+ const time_t delete_files_before = now - kMaxRingBufferFileAgeSeconds;
+ std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(kTombstoneFolderPath), closedir);
+ if (!dir_dump) {
+ PLOG(ERROR) << "Failed to open directory";
+ return false;
+ }
+ struct dirent* dp;
+ bool success = true;
+ std::list<std::pair<const time_t, std::string>> valid_files;
+ while ((dp = readdir(dir_dump.get()))) {
+ if (dp->d_type != DT_REG) {
+ continue;
+ }
+ std::string cur_file_name(dp->d_name);
+ struct stat cur_file_stat;
+ std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
+ if (stat(cur_file_path.c_str(), &cur_file_stat) == -1) {
+ PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
+ success = false;
+ continue;
+ }
+ const time_t cur_file_time = cur_file_stat.st_mtime;
+ valid_files.push_back(std::pair<const time_t, std::string>(cur_file_time, cur_file_path));
+ }
+ valid_files.sort(); // sort the list of files by last modified time from
+ // small to big.
+ uint32_t cur_file_count = valid_files.size();
+ for (auto cur_file : valid_files) {
+ if (cur_file_count > kMaxRingBufferFileNum || cur_file.first < delete_files_before) {
+ if (unlink(cur_file.second.c_str()) != 0) {
+ PLOG(ERROR) << "Error deleting file";
+ success = false;
+ }
+ cur_file_count--;
+ } else {
+ break;
+ }
+ }
+ return success;
+}
+
+// Helper function for |cpioArchiveFilesInDir|
+bool cpioWriteHeader(int out_fd, struct stat& st, const char* file_name, size_t file_name_len) {
+ const int buf_size = 32 * 1024;
+ std::array<char, buf_size> read_buf;
+ ssize_t llen = snprintf(
+ read_buf.data(), buf_size, "%s%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X%08X",
+ kCpioMagic, static_cast<int>(st.st_ino), st.st_mode, st.st_uid, st.st_gid,
+ static_cast<int>(st.st_nlink), static_cast<int>(st.st_mtime),
+ static_cast<int>(st.st_size), major(st.st_dev), minor(st.st_dev), major(st.st_rdev),
+ minor(st.st_rdev), static_cast<uint32_t>(file_name_len), 0);
+ if (write(out_fd, read_buf.data(), llen < buf_size ? llen : buf_size - 1) == -1) {
+ PLOG(ERROR) << "Error writing cpio header to file " << file_name;
+ return false;
+ }
+ if (write(out_fd, file_name, file_name_len) == -1) {
+ PLOG(ERROR) << "Error writing filename to file " << file_name;
+ return false;
+ }
+
+ // NUL Pad header up to 4 multiple bytes.
+ llen = (llen + file_name_len) % 4;
+ if (llen != 0) {
+ const uint32_t zero = 0;
+ if (write(out_fd, &zero, 4 - llen) == -1) {
+ PLOG(ERROR) << "Error padding 0s to file " << file_name;
+ return false;
+ }
+ }
+ return true;
+}
+
+// Helper function for |cpioArchiveFilesInDir|
+size_t cpioWriteFileContent(int fd_read, int out_fd, struct stat& st) {
+ // writing content of file
+ std::array<char, 32 * 1024> read_buf;
+ ssize_t llen = st.st_size;
+ size_t n_error = 0;
+ while (llen > 0) {
+ ssize_t bytes_read = read(fd_read, read_buf.data(), read_buf.size());
+ if (bytes_read == -1) {
+ PLOG(ERROR) << "Error reading file";
+ return ++n_error;
+ }
+ llen -= bytes_read;
+ if (write(out_fd, read_buf.data(), bytes_read) == -1) {
+ PLOG(ERROR) << "Error writing data to file";
+ return ++n_error;
+ }
+ if (bytes_read == 0) { // this should never happen, but just in case
+ // to unstuck from while loop
+ PLOG(ERROR) << "Unexpected read result";
+ n_error++;
+ break;
+ }
+ }
+ llen = st.st_size % 4;
+ if (llen != 0) {
+ const uint32_t zero = 0;
+ if (write(out_fd, &zero, 4 - llen) == -1) {
+ PLOG(ERROR) << "Error padding 0s to file";
+ return ++n_error;
+ }
+ }
+ return n_error;
+}
+
+// Helper function for |cpioArchiveFilesInDir|
+bool cpioWriteFileTrailer(int out_fd) {
+ const int buf_size = 4096;
+ std::array<char, buf_size> read_buf;
+ read_buf.fill(0);
+ ssize_t llen = snprintf(read_buf.data(), 4096, "070701%040X%056X%08XTRAILER!!!", 1, 0x0b, 0);
+ if (write(out_fd, read_buf.data(), (llen < buf_size ? llen : buf_size - 1) + 4) == -1) {
+ PLOG(ERROR) << "Error writing trailing bytes";
+ return false;
+ }
+ return true;
+}
+
+// Archives all files in |input_dir| and writes result into |out_fd|
+// Logic obtained from //external/toybox/toys/posix/cpio.c "Output cpio archive"
+// portion
+size_t cpioArchiveFilesInDir(int out_fd, const char* input_dir) {
+ struct dirent* dp;
+ size_t n_error = 0;
+ std::unique_ptr<DIR, decltype(&closedir)> dir_dump(opendir(input_dir), closedir);
+ if (!dir_dump) {
+ PLOG(ERROR) << "Failed to open directory";
+ return ++n_error;
+ }
+ while ((dp = readdir(dir_dump.get()))) {
+ if (dp->d_type != DT_REG) {
+ continue;
+ }
+ std::string cur_file_name(dp->d_name);
+ struct stat st;
+ const std::string cur_file_path = kTombstoneFolderPath + cur_file_name;
+ if (stat(cur_file_path.c_str(), &st) == -1) {
+ PLOG(ERROR) << "Failed to get file stat for " << cur_file_path;
+ n_error++;
+ continue;
+ }
+ const int fd_read = open(cur_file_path.c_str(), O_RDONLY);
+ if (fd_read == -1) {
+ PLOG(ERROR) << "Failed to open file " << cur_file_path;
+ n_error++;
+ continue;
+ }
+ std::string file_name_with_last_modified_time =
+ cur_file_name + "-" + std::to_string(st.st_mtime);
+ // string.size() does not include the null terminator. The cpio FreeBSD
+ // file header expects the null character to be included in the length.
+ const size_t file_name_len = file_name_with_last_modified_time.size() + 1;
+ unique_fd file_auto_closer(fd_read);
+ if (!cpioWriteHeader(out_fd, st, file_name_with_last_modified_time.c_str(),
+ file_name_len)) {
+ return ++n_error;
+ }
+ size_t write_error = cpioWriteFileContent(fd_read, out_fd, st);
+ if (write_error) {
+ return n_error + write_error;
+ }
+ }
+ if (!cpioWriteFileTrailer(out_fd)) {
+ return ++n_error;
+ }
+ return n_error;
+}
+
+// Helper function to create a non-const char*.
+std::vector<char> makeCharVec(const std::string& str) {
+ std::vector<char> vec(str.size() + 1);
+ vec.assign(str.begin(), str.end());
+ vec.push_back('\0');
+ return vec;
+}
+
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+using aidl_return_util::validateAndCall;
+using aidl_return_util::validateAndCallWithLock;
+
+WifiChip::WifiChip(int32_t chip_id, bool is_primary,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
+ const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
+ const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
+ const std::function<void(const std::string&)>& handler)
+ : chip_id_(chip_id),
+ legacy_hal_(legacy_hal),
+ mode_controller_(mode_controller),
+ iface_util_(iface_util),
+ is_valid_(true),
+ current_mode_id_(feature_flags::chip_mode_ids::kInvalid),
+ modes_(feature_flags.lock()->getChipModes(is_primary)),
+ debug_ring_buffer_cb_registered_(false),
+ subsystemCallbackHandler_(handler) {
+ setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
+}
+
+std::shared_ptr<WifiChip> WifiChip::create(
+ int32_t chip_id, bool is_primary, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
+ const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
+ const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
+ const std::function<void(const std::string&)>& handler) {
+ std::shared_ptr<WifiChip> ptr = ndk::SharedRefBase::make<WifiChip>(
+ chip_id, is_primary, legacy_hal, mode_controller, iface_util, feature_flags, handler);
+ std::weak_ptr<WifiChip> weak_ptr_this(ptr);
+ ptr->setWeakPtr(weak_ptr_this);
+ return ptr;
+}
+
+void WifiChip::invalidate() {
+ if (!writeRingbufferFilesInternal()) {
+ LOG(ERROR) << "Error writing files to flash";
+ }
+ invalidateAndRemoveAllIfaces();
+ setActiveWlanIfaceNameProperty(kNoActiveWlanIfaceNamePropertyValue);
+ legacy_hal_.reset();
+ event_cb_handler_.invalidate();
+ is_valid_ = false;
+}
+
+void WifiChip::setWeakPtr(std::weak_ptr<WifiChip> ptr) {
+ weak_ptr_this_ = ptr;
+}
+
+bool WifiChip::isValid() {
+ return is_valid_;
+}
+
+std::set<std::shared_ptr<IWifiChipEventCallback>> WifiChip::getEventCallbacks() {
+ return event_cb_handler_.getCallbacks();
+}
+
+ndk::ScopedAStatus WifiChip::getId(int32_t* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID, &WifiChip::getIdInternal,
+ _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::registerEventCallback(
+ const std::shared_ptr<IWifiChipEventCallback>& event_callback) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::registerEventCallbackInternal, event_callback);
+}
+
+ndk::ScopedAStatus WifiChip::getCapabilities(IWifiChip::ChipCapabilityMask* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getCapabilitiesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::getAvailableModes(std::vector<IWifiChip::ChipMode>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getAvailableModesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::configureChip(int32_t in_modeId) {
+ return validateAndCallWithLock(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::configureChipInternal, in_modeId);
+}
+
+ndk::ScopedAStatus WifiChip::getMode(int32_t* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getModeInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::requestChipDebugInfo(IWifiChip::ChipDebugInfo* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::requestChipDebugInfoInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::requestDriverDebugDump(std::vector<uint8_t>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::requestDriverDebugDumpInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::requestFirmwareDebugDump(std::vector<uint8_t>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::requestFirmwareDebugDumpInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::createApIface(std::shared_ptr<IWifiApIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::createApIfaceInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::createBridgedApIface(std::shared_ptr<IWifiApIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::createBridgedApIfaceInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::getApIfaceNames(std::vector<std::string>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getApIfaceNamesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::getApIface(const std::string& in_ifname,
+ std::shared_ptr<IWifiApIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getApIfaceInternal, _aidl_return, in_ifname);
+}
+
+ndk::ScopedAStatus WifiChip::removeApIface(const std::string& in_ifname) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::removeApIfaceInternal, in_ifname);
+}
+
+ndk::ScopedAStatus WifiChip::removeIfaceInstanceFromBridgedApIface(
+ const std::string& in_brIfaceName, const std::string& in_ifaceInstanceName) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal, in_brIfaceName,
+ in_ifaceInstanceName);
+}
+
+ndk::ScopedAStatus WifiChip::createNanIface(std::shared_ptr<IWifiNanIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::createNanIfaceInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::getNanIfaceNames(std::vector<std::string>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getNanIfaceNamesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::getNanIface(const std::string& in_ifname,
+ std::shared_ptr<IWifiNanIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getNanIfaceInternal, _aidl_return, in_ifname);
+}
+
+ndk::ScopedAStatus WifiChip::removeNanIface(const std::string& in_ifname) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::removeNanIfaceInternal, in_ifname);
+}
+
+ndk::ScopedAStatus WifiChip::createP2pIface(std::shared_ptr<IWifiP2pIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::createP2pIfaceInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::getP2pIfaceNames(std::vector<std::string>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getP2pIfaceNamesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::getP2pIface(const std::string& in_ifname,
+ std::shared_ptr<IWifiP2pIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getP2pIfaceInternal, _aidl_return, in_ifname);
+}
+
+ndk::ScopedAStatus WifiChip::removeP2pIface(const std::string& in_ifname) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::removeP2pIfaceInternal, in_ifname);
+}
+
+ndk::ScopedAStatus WifiChip::createStaIface(std::shared_ptr<IWifiStaIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::createStaIfaceInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::getStaIfaceNames(std::vector<std::string>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getStaIfaceNamesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::getStaIface(const std::string& in_ifname,
+ std::shared_ptr<IWifiStaIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getStaIfaceInternal, _aidl_return, in_ifname);
+}
+
+ndk::ScopedAStatus WifiChip::removeStaIface(const std::string& in_ifname) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::removeStaIfaceInternal, in_ifname);
+}
+
+ndk::ScopedAStatus WifiChip::createRttController(
+ const std::shared_ptr<IWifiStaIface>& in_boundIface,
+ std::shared_ptr<IWifiRttController>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::createRttControllerInternal, _aidl_return, in_boundIface);
+}
+
+ndk::ScopedAStatus WifiChip::getDebugRingBuffersStatus(
+ std::vector<WifiDebugRingBufferStatus>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getDebugRingBuffersStatusInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::startLoggingToDebugRingBuffer(
+ const std::string& in_ringName, WifiDebugRingBufferVerboseLevel in_verboseLevel,
+ int32_t in_maxIntervalInSec, int32_t in_minDataSizeInBytes) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::startLoggingToDebugRingBufferInternal, in_ringName,
+ in_verboseLevel, in_maxIntervalInSec, in_minDataSizeInBytes);
+}
+
+ndk::ScopedAStatus WifiChip::forceDumpToDebugRingBuffer(const std::string& in_ringName) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::forceDumpToDebugRingBufferInternal, in_ringName);
+}
+
+ndk::ScopedAStatus WifiChip::flushRingBufferToFile() {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::flushRingBufferToFileInternal);
+}
+
+ndk::ScopedAStatus WifiChip::stopLoggingToDebugRingBuffer() {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::stopLoggingToDebugRingBufferInternal);
+}
+
+ndk::ScopedAStatus WifiChip::getDebugHostWakeReasonStats(
+ WifiDebugHostWakeReasonStats* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getDebugHostWakeReasonStatsInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiChip::enableDebugErrorAlerts(bool in_enable) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::enableDebugErrorAlertsInternal, in_enable);
+}
+
+ndk::ScopedAStatus WifiChip::selectTxPowerScenario(IWifiChip::TxPowerScenario in_scenario) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::selectTxPowerScenarioInternal, in_scenario);
+}
+
+ndk::ScopedAStatus WifiChip::resetTxPowerScenario() {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::resetTxPowerScenarioInternal);
+}
+
+ndk::ScopedAStatus WifiChip::setLatencyMode(IWifiChip::LatencyMode in_mode) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::setLatencyModeInternal, in_mode);
+}
+
+binder_status_t WifiChip::dump(int fd, const char**, uint32_t) {
+ {
+ std::unique_lock<std::mutex> lk(lock_t);
+ for (const auto& item : ringbuffer_map_) {
+ forceDumpToDebugRingBufferInternal(item.first);
+ }
+ // unique_lock unlocked here
+ }
+ usleep(100 * 1000); // sleep for 100 milliseconds to wait for
+ // ringbuffer updates.
+ if (!writeRingbufferFilesInternal()) {
+ LOG(ERROR) << "Error writing files to flash";
+ }
+ uint32_t n_error = cpioArchiveFilesInDir(fd, kTombstoneFolderPath);
+ if (n_error != 0) {
+ LOG(ERROR) << n_error << " errors occurred in cpio function";
+ }
+ fsync(fd);
+ return STATUS_OK;
+}
+
+ndk::ScopedAStatus WifiChip::setMultiStaPrimaryConnection(const std::string& in_ifName) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::setMultiStaPrimaryConnectionInternal, in_ifName);
+}
+
+ndk::ScopedAStatus WifiChip::setMultiStaUseCase(IWifiChip::MultiStaUseCase in_useCase) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::setMultiStaUseCaseInternal, in_useCase);
+}
+
+ndk::ScopedAStatus WifiChip::setCoexUnsafeChannels(
+ const std::vector<IWifiChip::CoexUnsafeChannel>& in_unsafeChannels,
+ CoexRestriction in_restrictions) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::setCoexUnsafeChannelsInternal, in_unsafeChannels,
+ in_restrictions);
+}
+
+ndk::ScopedAStatus WifiChip::setCountryCode(const std::array<uint8_t, 2>& in_code) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiChip::setCountryCodeInternal, in_code);
+}
+
+ndk::ScopedAStatus WifiChip::getUsableChannels(WifiBand in_band, WifiIfaceMode in_ifaceModeMask,
+ UsableChannelFilter in_filterMask,
+ std::vector<WifiUsableChannel>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getUsableChannelsInternal, _aidl_return, in_band,
+ in_ifaceModeMask, in_filterMask);
+}
+
+ndk::ScopedAStatus WifiChip::triggerSubsystemRestart() {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::triggerSubsystemRestartInternal);
+}
+
+ndk::ScopedAStatus WifiChip::getSupportedRadioCombinationsMatrix(
+ WifiRadioCombinationMatrix* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+ &WifiChip::getSupportedRadioCombinationsMatrixInternal, _aidl_return);
+}
+
+void WifiChip::invalidateAndRemoveAllIfaces() {
+ invalidateAndClearBridgedApAll();
+ invalidateAndClearAll(ap_ifaces_);
+ invalidateAndClearAll(nan_ifaces_);
+ invalidateAndClearAll(p2p_ifaces_);
+ invalidateAndClearAll(sta_ifaces_);
+ // Since all the ifaces are invalid now, all RTT controller objects
+ // using those ifaces also need to be invalidated.
+ for (const auto& rtt : rtt_controllers_) {
+ rtt->invalidate();
+ }
+ rtt_controllers_.clear();
+}
+
+void WifiChip::invalidateAndRemoveDependencies(const std::string& removed_iface_name) {
+ for (auto it = nan_ifaces_.begin(); it != nan_ifaces_.end();) {
+ auto nan_iface = *it;
+ if (nan_iface->getName() == removed_iface_name) {
+ nan_iface->invalidate();
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onIfaceRemoved(IfaceType::NAN_IFACE, removed_iface_name).isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
+ }
+ }
+ it = nan_ifaces_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+
+ for (auto it = rtt_controllers_.begin(); it != rtt_controllers_.end();) {
+ auto rtt = *it;
+ if (rtt->getIfaceName() == removed_iface_name) {
+ rtt->invalidate();
+ it = rtt_controllers_.erase(it);
+ } else {
+ ++it;
+ }
+ }
+}
+
+std::pair<int32_t, ndk::ScopedAStatus> WifiChip::getIdInternal() {
+ return {chip_id_, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::registerEventCallbackInternal(
+ const std::shared_ptr<IWifiChipEventCallback>& event_callback) {
+ if (!event_cb_handler_.addCallback(event_callback)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<IWifiChip::ChipCapabilityMask, ndk::ScopedAStatus> WifiChip::getCapabilitiesInternal() {
+ legacy_hal::wifi_error legacy_status;
+ uint64_t legacy_feature_set;
+ uint32_t legacy_logger_feature_set;
+ const auto ifname = getFirstActiveWlanIfaceName();
+ std::tie(legacy_status, legacy_feature_set) =
+ legacy_hal_.lock()->getSupportedFeatureSet(ifname);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {IWifiChip::ChipCapabilityMask{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ std::tie(legacy_status, legacy_logger_feature_set) =
+ legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ // some devices don't support querying logger feature set
+ legacy_logger_feature_set = 0;
+ }
+ uint32_t aidl_caps;
+ if (!aidl_struct_util::convertLegacyFeaturesToAidlChipCapabilities(
+ legacy_feature_set, legacy_logger_feature_set, &aidl_caps)) {
+ return {IWifiChip::ChipCapabilityMask{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {static_cast<IWifiChip::ChipCapabilityMask>(aidl_caps), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<IWifiChip::ChipMode>, ndk::ScopedAStatus>
+WifiChip::getAvailableModesInternal() {
+ return {modes_, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::configureChipInternal(
+ /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, int32_t mode_id) {
+ if (!isValidModeId(mode_id)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ if (mode_id == current_mode_id_) {
+ LOG(DEBUG) << "Already in the specified mode " << mode_id;
+ return ndk::ScopedAStatus::ok();
+ }
+ ndk::ScopedAStatus status = handleChipConfiguration(lock, mode_id);
+ if (!status.isOk()) {
+ WifiStatusCode errorCode = static_cast<WifiStatusCode>(status.getServiceSpecificError());
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onChipReconfigureFailure(errorCode).isOk()) {
+ LOG(ERROR) << "Failed to invoke onChipReconfigureFailure callback";
+ }
+ }
+ return status;
+ }
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onChipReconfigured(mode_id).isOk()) {
+ LOG(ERROR) << "Failed to invoke onChipReconfigured callback";
+ }
+ }
+ current_mode_id_ = mode_id;
+ LOG(INFO) << "Configured chip in mode " << mode_id;
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+
+ legacy_hal_.lock()->registerSubsystemRestartCallbackHandler(subsystemCallbackHandler_);
+
+ return status;
+}
+
+std::pair<int32_t, ndk::ScopedAStatus> WifiChip::getModeInternal() {
+ if (!isValidModeId(current_mode_id_)) {
+ return {current_mode_id_, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ return {current_mode_id_, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> WifiChip::requestChipDebugInfoInternal() {
+ IWifiChip::ChipDebugInfo result;
+ legacy_hal::wifi_error legacy_status;
+ std::string driver_desc;
+ const auto ifname = getFirstActiveWlanIfaceName();
+ std::tie(legacy_status, driver_desc) = legacy_hal_.lock()->getDriverVersion(ifname);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to get driver version: " << legacyErrorToString(legacy_status);
+ ndk::ScopedAStatus status =
+ createWifiStatusFromLegacyError(legacy_status, "failed to get driver version");
+ return {std::move(result), std::move(status)};
+ }
+ result.driverDescription = driver_desc.c_str();
+
+ std::string firmware_desc;
+ std::tie(legacy_status, firmware_desc) = legacy_hal_.lock()->getFirmwareVersion(ifname);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to get firmware version: " << legacyErrorToString(legacy_status);
+ ndk::ScopedAStatus status =
+ createWifiStatusFromLegacyError(legacy_status, "failed to get firmware version");
+ return {std::move(result), std::move(status)};
+ }
+ result.firmwareDescription = firmware_desc.c_str();
+
+ return {std::move(result), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> WifiChip::requestDriverDebugDumpInternal() {
+ legacy_hal::wifi_error legacy_status;
+ std::vector<uint8_t> driver_dump;
+ std::tie(legacy_status, driver_dump) =
+ legacy_hal_.lock()->requestDriverMemoryDump(getFirstActiveWlanIfaceName());
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to get driver debug dump: " << legacyErrorToString(legacy_status);
+ return {std::vector<uint8_t>(), createWifiStatusFromLegacyError(legacy_status)};
+ }
+ return {driver_dump, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> WifiChip::requestFirmwareDebugDumpInternal() {
+ legacy_hal::wifi_error legacy_status;
+ std::vector<uint8_t> firmware_dump;
+ std::tie(legacy_status, firmware_dump) =
+ legacy_hal_.lock()->requestFirmwareMemoryDump(getFirstActiveWlanIfaceName());
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to get firmware debug dump: " << legacyErrorToString(legacy_status);
+ return {std::vector<uint8_t>(), createWifiStatusFromLegacyError(legacy_status)};
+ }
+ return {firmware_dump, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) {
+ legacy_hal::wifi_error legacy_status;
+ legacy_status = legacy_hal_.lock()->createVirtualInterface(
+ apVirtIf, aidl_struct_util::convertAidlIfaceTypeToLegacy(IfaceType::AP));
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to add interface: " << apVirtIf << " "
+ << legacyErrorToString(legacy_status);
+ return createWifiStatusFromLegacyError(legacy_status);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::shared_ptr<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
+ std::vector<std::string> ap_instances;
+ for (auto const& it : br_ifaces_ap_instances_) {
+ if (it.first == ifname) {
+ ap_instances = it.second;
+ }
+ }
+ std::shared_ptr<WifiApIface> iface =
+ ndk::SharedRefBase::make<WifiApIface>(ifname, ap_instances, legacy_hal_, iface_util_);
+ ap_ifaces_.push_back(iface);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onIfaceAdded(IfaceType::AP, ifname).isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+ }
+ }
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+ return iface;
+}
+
+std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::createApIfaceInternal() {
+ if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP)) {
+ return {std::shared_ptr<WifiApIface>(),
+ createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ std::string ifname = allocateApIfaceName();
+ ndk::ScopedAStatus status = createVirtualApInterface(ifname);
+ if (!status.isOk()) {
+ return {std::shared_ptr<WifiApIface>(), std::move(status)};
+ }
+ std::shared_ptr<WifiApIface> iface = newWifiApIface(ifname);
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus>
+WifiChip::createBridgedApIfaceInternal() {
+ if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::AP_BRIDGED)) {
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ std::vector<std::string> ap_instances = allocateBridgedApInstanceNames();
+ if (ap_instances.size() < 2) {
+ LOG(ERROR) << "Fail to allocate two instances";
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ std::string br_ifname = kApBridgeIfacePrefix + ap_instances[0];
+ for (int i = 0; i < 2; i++) {
+ ndk::ScopedAStatus status = createVirtualApInterface(ap_instances[i]);
+ if (!status.isOk()) {
+ if (i != 0) { // The failure happened when creating second virtual
+ // iface.
+ legacy_hal_.lock()->deleteVirtualInterface(
+ ap_instances.front()); // Remove the first virtual iface.
+ }
+ return {nullptr, std::move(status)};
+ }
+ }
+ br_ifaces_ap_instances_[br_ifname] = ap_instances;
+ if (!iface_util_->createBridge(br_ifname)) {
+ LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
+ invalidateAndClearBridgedAp(br_ifname);
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ for (auto const& instance : ap_instances) {
+ // Bind ap instance interface to AP bridge
+ if (!iface_util_->addIfaceToBridge(br_ifname, instance)) {
+ LOG(ERROR) << "Failed add if to Bridge - if_name=" << instance.c_str();
+ invalidateAndClearBridgedAp(br_ifname);
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ }
+ std::shared_ptr<WifiApIface> iface = newWifiApIface(br_ifname);
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getApIfaceNamesInternal() {
+ if (ap_ifaces_.empty()) {
+ return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
+ }
+ return {getNames(ap_ifaces_), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> WifiChip::getApIfaceInternal(
+ const std::string& ifname) {
+ const auto iface = findUsingName(ap_ifaces_, ifname);
+ if (!iface.get()) {
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
+ }
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::removeApIfaceInternal(const std::string& ifname) {
+ const auto iface = findUsingName(ap_ifaces_, ifname);
+ if (!iface.get()) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ // Invalidate & remove any dependent objects first.
+ // Note: This is probably not required because we never create
+ // nan/rtt objects over AP iface. But, there is no harm to do it
+ // here and not make that assumption all over the place.
+ invalidateAndRemoveDependencies(ifname);
+ // Clear the bridge interface and the iface instance.
+ invalidateAndClearBridgedAp(ifname);
+ invalidateAndClear(ap_ifaces_, iface);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
+ }
+ }
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal(
+ const std::string& ifname, const std::string& ifInstanceName) {
+ const auto iface = findUsingName(ap_ifaces_, ifname);
+ if (!iface.get() || ifInstanceName.empty()) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ // Requires to remove one of the instance in bridge mode
+ for (auto const& it : br_ifaces_ap_instances_) {
+ if (it.first == ifname) {
+ std::vector<std::string> ap_instances = it.second;
+ for (auto const& iface : ap_instances) {
+ if (iface == ifInstanceName) {
+ if (!iface_util_->removeIfaceFromBridge(it.first, iface)) {
+ LOG(ERROR) << "Failed to remove interface: " << ifInstanceName << " from "
+ << ifname;
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->deleteVirtualInterface(iface);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to del interface: " << iface << " "
+ << legacyErrorToString(legacy_status);
+ return createWifiStatusFromLegacyError(legacy_status);
+ }
+ ap_instances.erase(
+ std::remove(ap_instances.begin(), ap_instances.end(), ifInstanceName),
+ ap_instances.end());
+ br_ifaces_ap_instances_[ifname] = ap_instances;
+ break;
+ }
+ }
+ break;
+ }
+ }
+ iface->removeInstance(ifInstanceName);
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<IWifiNanIface>, ndk::ScopedAStatus> WifiChip::createNanIfaceInternal() {
+ if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::NAN_IFACE)) {
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ bool is_dedicated_iface = true;
+ std::string ifname = getPredefinedNanIfaceName();
+ if (ifname.empty() || !iface_util_->ifNameToIndex(ifname)) {
+ // Use the first shared STA iface (wlan0) if a dedicated aware iface is
+ // not defined.
+ ifname = getFirstActiveWlanIfaceName();
+ is_dedicated_iface = false;
+ }
+ std::shared_ptr<WifiNanIface> iface =
+ WifiNanIface::create(ifname, is_dedicated_iface, legacy_hal_, iface_util_);
+ nan_ifaces_.push_back(iface);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onIfaceAdded(IfaceType::NAN_IFACE, ifname).isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+ }
+ }
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getNanIfaceNamesInternal() {
+ if (nan_ifaces_.empty()) {
+ return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
+ }
+ return {getNames(nan_ifaces_), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<IWifiNanIface>, ndk::ScopedAStatus> WifiChip::getNanIfaceInternal(
+ const std::string& ifname) {
+ const auto iface = findUsingName(nan_ifaces_, ifname);
+ if (!iface.get()) {
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
+ }
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::removeNanIfaceInternal(const std::string& ifname) {
+ const auto iface = findUsingName(nan_ifaces_, ifname);
+ if (!iface.get()) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ invalidateAndClear(nan_ifaces_, iface);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onIfaceRemoved(IfaceType::NAN_IFACE, ifname).isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<IWifiP2pIface>, ndk::ScopedAStatus> WifiChip::createP2pIfaceInternal() {
+ if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::P2P)) {
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ std::string ifname = getPredefinedP2pIfaceName();
+ std::shared_ptr<WifiP2pIface> iface =
+ ndk::SharedRefBase::make<WifiP2pIface>(ifname, legacy_hal_);
+ p2p_ifaces_.push_back(iface);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onIfaceAdded(IfaceType::P2P, ifname).isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+ }
+ }
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getP2pIfaceNamesInternal() {
+ if (p2p_ifaces_.empty()) {
+ return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
+ }
+ return {getNames(p2p_ifaces_), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<IWifiP2pIface>, ndk::ScopedAStatus> WifiChip::getP2pIfaceInternal(
+ const std::string& ifname) {
+ const auto iface = findUsingName(p2p_ifaces_, ifname);
+ if (!iface.get()) {
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
+ }
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::removeP2pIfaceInternal(const std::string& ifname) {
+ const auto iface = findUsingName(p2p_ifaces_, ifname);
+ if (!iface.get()) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ invalidateAndClear(p2p_ifaces_, iface);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onIfaceRemoved(IfaceType::P2P, ifname).isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
+ }
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus> WifiChip::createStaIfaceInternal() {
+ if (!canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) {
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ std::string ifname = allocateStaIfaceName();
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->createVirtualInterface(
+ ifname, aidl_struct_util::convertAidlIfaceTypeToLegacy(IfaceType::STA));
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to add interface: " << ifname << " "
+ << legacyErrorToString(legacy_status);
+ return {nullptr, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ std::shared_ptr<WifiStaIface> iface =
+ ndk::SharedRefBase::make<WifiStaIface>(ifname, legacy_hal_, iface_util_);
+ sta_ifaces_.push_back(iface);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onIfaceAdded(IfaceType::STA, ifname).isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceAdded callback";
+ }
+ }
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<std::string>, ndk::ScopedAStatus> WifiChip::getStaIfaceNamesInternal() {
+ if (sta_ifaces_.empty()) {
+ return {std::vector<std::string>(), ndk::ScopedAStatus::ok()};
+ }
+ return {getNames(sta_ifaces_), ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus> WifiChip::getStaIfaceInternal(
+ const std::string& ifname) {
+ const auto iface = findUsingName(sta_ifaces_, ifname);
+ if (!iface.get()) {
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
+ }
+ return {iface, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::removeStaIfaceInternal(const std::string& ifname) {
+ const auto iface = findUsingName(sta_ifaces_, ifname);
+ if (!iface.get()) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ // Invalidate & remove any dependent objects first.
+ invalidateAndRemoveDependencies(ifname);
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->deleteVirtualInterface(ifname);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to remove interface: " << ifname << " "
+ << legacyErrorToString(legacy_status);
+ }
+ invalidateAndClear(sta_ifaces_, iface);
+ for (const auto& callback : event_cb_handler_.getCallbacks()) {
+ if (!callback->onIfaceRemoved(IfaceType::STA, ifname).isOk()) {
+ LOG(ERROR) << "Failed to invoke onIfaceRemoved callback";
+ }
+ }
+ setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::shared_ptr<IWifiRttController>, ndk::ScopedAStatus>
+WifiChip::createRttControllerInternal(const std::shared_ptr<IWifiStaIface>& bound_iface) {
+ if (sta_ifaces_.size() == 0 &&
+ !canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType::STA)) {
+ LOG(ERROR) << "createRttControllerInternal: Chip cannot support STAs "
+ "(and RTT by extension)";
+ return {nullptr, createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE)};
+ }
+ std::shared_ptr<WifiRttController> rtt =
+ WifiRttController::create(getFirstActiveWlanIfaceName(), bound_iface, legacy_hal_);
+ rtt_controllers_.emplace_back(rtt);
+ return {rtt, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<WifiDebugRingBufferStatus>, ndk::ScopedAStatus>
+WifiChip::getDebugRingBuffersStatusInternal() {
+ legacy_hal::wifi_error legacy_status;
+ std::vector<legacy_hal::wifi_ring_buffer_status> legacy_ring_buffer_status_vec;
+ std::tie(legacy_status, legacy_ring_buffer_status_vec) =
+ legacy_hal_.lock()->getRingBuffersStatus(getFirstActiveWlanIfaceName());
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {std::vector<WifiDebugRingBufferStatus>(),
+ createWifiStatusFromLegacyError(legacy_status)};
+ }
+ std::vector<WifiDebugRingBufferStatus> aidl_ring_buffer_status_vec;
+ if (!aidl_struct_util::convertLegacyVectorOfDebugRingBufferStatusToAidl(
+ legacy_ring_buffer_status_vec, &aidl_ring_buffer_status_vec)) {
+ return {std::vector<WifiDebugRingBufferStatus>(),
+ createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_ring_buffer_status_vec, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::startLoggingToDebugRingBufferInternal(
+ const std::string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
+ uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes) {
+ ndk::ScopedAStatus status = registerDebugRingBufferCallback();
+ if (!status.isOk()) {
+ return status;
+ }
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRingBufferLogging(
+ getFirstActiveWlanIfaceName(), ring_name,
+ static_cast<std::underlying_type<WifiDebugRingBufferVerboseLevel>::type>(verbose_level),
+ max_interval_in_sec, min_data_size_in_bytes);
+ ringbuffer_map_.insert(
+ std::pair<std::string, Ringbuffer>(ring_name, Ringbuffer(kMaxBufferSizeBytes)));
+ // if verbose logging enabled, turn up HAL daemon logging as well.
+ if (verbose_level < WifiDebugRingBufferVerboseLevel::VERBOSE) {
+ ::android::base::SetMinimumLogSeverity(::android::base::DEBUG);
+ } else {
+ ::android::base::SetMinimumLogSeverity(::android::base::VERBOSE);
+ }
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::forceDumpToDebugRingBufferInternal(const std::string& ring_name) {
+ ndk::ScopedAStatus status = registerDebugRingBufferCallback();
+ if (!status.isOk()) {
+ return status;
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->getRingBufferData(getFirstActiveWlanIfaceName(), ring_name);
+
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::flushRingBufferToFileInternal() {
+ if (!writeRingbufferFilesInternal()) {
+ LOG(ERROR) << "Error writing files to flash";
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WifiChip::stopLoggingToDebugRingBufferInternal() {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->deregisterRingBufferCallbackHandler(getFirstActiveWlanIfaceName());
+ if (legacy_status == legacy_hal::WIFI_SUCCESS) {
+ debug_ring_buffer_cb_registered_ = false;
+ }
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<WifiDebugHostWakeReasonStats, ndk::ScopedAStatus>
+WifiChip::getDebugHostWakeReasonStatsInternal() {
+ legacy_hal::wifi_error legacy_status;
+ legacy_hal::WakeReasonStats legacy_stats;
+ std::tie(legacy_status, legacy_stats) =
+ legacy_hal_.lock()->getWakeReasonStats(getFirstActiveWlanIfaceName());
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {WifiDebugHostWakeReasonStats{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ WifiDebugHostWakeReasonStats aidl_stats;
+ if (!aidl_struct_util::convertLegacyWakeReasonStatsToAidl(legacy_stats, &aidl_stats)) {
+ return {WifiDebugHostWakeReasonStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_stats, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::enableDebugErrorAlertsInternal(bool enable) {
+ legacy_hal::wifi_error legacy_status;
+ if (enable) {
+ std::weak_ptr<WifiChip> weak_ptr_this = weak_ptr_this_;
+ const auto& on_alert_callback = [weak_ptr_this](int32_t error_code,
+ std::vector<uint8_t> debug_data) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onDebugErrorAlert(error_code, debug_data).isOk()) {
+ LOG(ERROR) << "Failed to invoke onDebugErrorAlert callback";
+ }
+ }
+ };
+ legacy_status = legacy_hal_.lock()->registerErrorAlertCallbackHandler(
+ getFirstActiveWlanIfaceName(), on_alert_callback);
+ } else {
+ legacy_status = legacy_hal_.lock()->deregisterErrorAlertCallbackHandler(
+ getFirstActiveWlanIfaceName());
+ }
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::selectTxPowerScenarioInternal(IWifiChip::TxPowerScenario scenario) {
+ auto legacy_status = legacy_hal_.lock()->selectTxPowerScenario(
+ getFirstActiveWlanIfaceName(),
+ aidl_struct_util::convertAidlTxPowerScenarioToLegacy(scenario));
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::resetTxPowerScenarioInternal() {
+ auto legacy_status = legacy_hal_.lock()->resetTxPowerScenario(getFirstActiveWlanIfaceName());
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::setLatencyModeInternal(IWifiChip::LatencyMode mode) {
+ auto legacy_status = legacy_hal_.lock()->setLatencyMode(
+ getFirstActiveWlanIfaceName(), aidl_struct_util::convertAidlLatencyModeToLegacy(mode));
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::setMultiStaPrimaryConnectionInternal(const std::string& ifname) {
+ auto legacy_status = legacy_hal_.lock()->multiStaSetPrimaryConnection(ifname);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::setMultiStaUseCaseInternal(IWifiChip::MultiStaUseCase use_case) {
+ auto legacy_status = legacy_hal_.lock()->multiStaSetUseCase(
+ aidl_struct_util::convertAidlMultiStaUseCaseToLegacy(use_case));
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::setCoexUnsafeChannelsInternal(
+ std::vector<IWifiChip::CoexUnsafeChannel> unsafe_channels, CoexRestriction restrictions) {
+ std::vector<legacy_hal::wifi_coex_unsafe_channel> legacy_unsafe_channels;
+ if (!aidl_struct_util::convertAidlVectorOfCoexUnsafeChannelToLegacy(unsafe_channels,
+ &legacy_unsafe_channels)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ uint32_t aidl_restrictions = static_cast<uint32_t>(restrictions);
+ uint32_t legacy_restrictions = 0;
+ if (aidl_restrictions & static_cast<uint32_t>(CoexRestriction::WIFI_DIRECT)) {
+ legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_DIRECT;
+ }
+ if (aidl_restrictions & static_cast<uint32_t>(CoexRestriction::SOFTAP)) {
+ legacy_restrictions |= legacy_hal::wifi_coex_restriction::SOFTAP;
+ }
+ if (aidl_restrictions & static_cast<uint32_t>(CoexRestriction::WIFI_AWARE)) {
+ legacy_restrictions |= legacy_hal::wifi_coex_restriction::WIFI_AWARE;
+ }
+ auto legacy_status =
+ legacy_hal_.lock()->setCoexUnsafeChannels(legacy_unsafe_channels, legacy_restrictions);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::setCountryCodeInternal(const std::array<uint8_t, 2>& code) {
+ auto legacy_status = legacy_hal_.lock()->setCountryCode(getFirstActiveWlanIfaceName(), code);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<std::vector<WifiUsableChannel>, ndk::ScopedAStatus> WifiChip::getUsableChannelsInternal(
+ WifiBand band, WifiIfaceMode ifaceModeMask, UsableChannelFilter filterMask) {
+ legacy_hal::wifi_error legacy_status;
+ std::vector<legacy_hal::wifi_usable_channel> legacy_usable_channels;
+ std::tie(legacy_status, legacy_usable_channels) = legacy_hal_.lock()->getUsableChannels(
+ aidl_struct_util::convertAidlWifiBandToLegacyMacBand(band),
+ aidl_struct_util::convertAidlWifiIfaceModeToLegacy(
+ static_cast<uint32_t>(ifaceModeMask)),
+ aidl_struct_util::convertAidlUsableChannelFilterToLegacy(
+ static_cast<uint32_t>(filterMask)));
+
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {std::vector<WifiUsableChannel>(), createWifiStatusFromLegacyError(legacy_status)};
+ }
+ std::vector<WifiUsableChannel> aidl_usable_channels;
+ if (!aidl_struct_util::convertLegacyWifiUsableChannelsToAidl(legacy_usable_channels,
+ &aidl_usable_channels)) {
+ return {std::vector<WifiUsableChannel>(), createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_usable_channels, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<WifiRadioCombinationMatrix, ndk::ScopedAStatus>
+WifiChip::getSupportedRadioCombinationsMatrixInternal() {
+ legacy_hal::wifi_error legacy_status;
+ legacy_hal::wifi_radio_combination_matrix* legacy_matrix;
+
+ std::tie(legacy_status, legacy_matrix) =
+ legacy_hal_.lock()->getSupportedRadioCombinationsMatrix();
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to get SupportedRadioCombinations matrix from legacy HAL: "
+ << legacyErrorToString(legacy_status);
+ return {WifiRadioCombinationMatrix{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+
+ WifiRadioCombinationMatrix aidl_matrix;
+ if (!aidl_struct_util::convertLegacyRadioCombinationsMatrixToAidl(legacy_matrix,
+ &aidl_matrix)) {
+ LOG(ERROR) << "Failed convertLegacyRadioCombinationsMatrixToAidl() ";
+ return {WifiRadioCombinationMatrix(), createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS)};
+ }
+ return {aidl_matrix, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiChip::triggerSubsystemRestartInternal() {
+ auto legacy_status = legacy_hal_.lock()->triggerSubsystemRestart();
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::handleChipConfiguration(
+ /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock, int32_t mode_id) {
+ // If the chip is already configured in a different mode, stop
+ // the legacy HAL and then start it after firmware mode change.
+ if (isValidModeId(current_mode_id_)) {
+ LOG(INFO) << "Reconfiguring chip from mode " << current_mode_id_ << " to mode " << mode_id;
+ invalidateAndRemoveAllIfaces();
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stop(lock, []() {});
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to stop legacy HAL: " << legacyErrorToString(legacy_status);
+ return createWifiStatusFromLegacyError(legacy_status);
+ }
+ }
+ // Firmware mode change not needed for V2 devices.
+ bool success = true;
+ if (mode_id == feature_flags::chip_mode_ids::kV1Sta) {
+ success = mode_controller_.lock()->changeFirmwareMode(IfaceType::STA);
+ } else if (mode_id == feature_flags::chip_mode_ids::kV1Ap) {
+ success = mode_controller_.lock()->changeFirmwareMode(IfaceType::AP);
+ }
+ if (!success) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->start();
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to start legacy HAL: " << legacyErrorToString(legacy_status);
+ return createWifiStatusFromLegacyError(legacy_status);
+ }
+ // Every time the HAL is restarted, we need to register the
+ // radio mode change callback.
+ ndk::ScopedAStatus status = registerRadioModeChangeCallback();
+ if (!status.isOk()) {
+ // This is probably not a critical failure?
+ LOG(ERROR) << "Failed to register radio mode change callback";
+ }
+ // Extract and save the version information into property.
+ std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> version_info;
+ version_info = WifiChip::requestChipDebugInfoInternal();
+ if (version_info.second.isOk()) {
+ property_set("vendor.wlan.firmware.version",
+ version_info.first.firmwareDescription.c_str());
+ property_set("vendor.wlan.driver.version", version_info.first.driverDescription.c_str());
+ }
+
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WifiChip::registerDebugRingBufferCallback() {
+ if (debug_ring_buffer_cb_registered_) {
+ return ndk::ScopedAStatus::ok();
+ }
+
+ std::weak_ptr<WifiChip> weak_ptr_this = weak_ptr_this_;
+ const auto& on_ring_buffer_data_callback =
+ [weak_ptr_this](const std::string& name, const std::vector<uint8_t>& data,
+ const legacy_hal::wifi_ring_buffer_status& status) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ WifiDebugRingBufferStatus aidl_status;
+ Ringbuffer::AppendStatus appendstatus;
+ if (!aidl_struct_util::convertLegacyDebugRingBufferStatusToAidl(status,
+ &aidl_status)) {
+ LOG(ERROR) << "Error converting ring buffer status";
+ return;
+ }
+ {
+ std::unique_lock<std::mutex> lk(shared_ptr_this->lock_t);
+ const auto& target = shared_ptr_this->ringbuffer_map_.find(name);
+ if (target != shared_ptr_this->ringbuffer_map_.end()) {
+ Ringbuffer& cur_buffer = target->second;
+ appendstatus = cur_buffer.append(data);
+ } else {
+ LOG(ERROR) << "Ringname " << name << " not found";
+ return;
+ }
+ // unique_lock unlocked here
+ }
+ if (appendstatus == Ringbuffer::AppendStatus::FAIL_RING_BUFFER_CORRUPTED) {
+ LOG(ERROR) << "Ringname " << name << " is corrupted. Clear the ring buffer";
+ shared_ptr_this->writeRingbufferFilesInternal();
+ return;
+ }
+ };
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->registerRingBufferCallbackHandler(
+ getFirstActiveWlanIfaceName(), on_ring_buffer_data_callback);
+
+ if (legacy_status == legacy_hal::WIFI_SUCCESS) {
+ debug_ring_buffer_cb_registered_ = true;
+ }
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiChip::registerRadioModeChangeCallback() {
+ std::weak_ptr<WifiChip> weak_ptr_this = weak_ptr_this_;
+ const auto& on_radio_mode_change_callback =
+ [weak_ptr_this](const std::vector<legacy_hal::WifiMacInfo>& mac_infos) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ std::vector<IWifiChipEventCallback::RadioModeInfo> aidl_radio_mode_infos;
+ if (!aidl_struct_util::convertLegacyWifiMacInfosToAidl(mac_infos,
+ &aidl_radio_mode_infos)) {
+ LOG(ERROR) << "Error converting wifi mac info";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onRadioModeChange(aidl_radio_mode_infos).isOk()) {
+ LOG(ERROR) << "Failed to invoke onRadioModeChange callback";
+ }
+ }
+ };
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->registerRadioModeChangeCallbackHandler(
+ getFirstActiveWlanIfaceName(), on_radio_mode_change_callback);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::vector<IWifiChip::ChipConcurrencyCombination>
+WifiChip::getCurrentModeConcurrencyCombinations() {
+ if (!isValidModeId(current_mode_id_)) {
+ LOG(ERROR) << "Chip not configured in a mode yet";
+ return std::vector<IWifiChip::ChipConcurrencyCombination>();
+ }
+ for (const auto& mode : modes_) {
+ if (mode.id == current_mode_id_) {
+ return mode.availableCombinations;
+ }
+ }
+ CHECK(0) << "Expected to find concurrency combinations for current mode!";
+ return std::vector<IWifiChip::ChipConcurrencyCombination>();
+}
+
+// Returns a map indexed by IfaceConcurrencyType with the number of ifaces currently
+// created of the corresponding concurrency type.
+std::map<IfaceConcurrencyType, size_t> WifiChip::getCurrentConcurrencyCombination() {
+ std::map<IfaceConcurrencyType, size_t> iface_counts;
+ uint32_t num_ap = 0;
+ uint32_t num_ap_bridged = 0;
+ for (const auto& ap_iface : ap_ifaces_) {
+ std::string ap_iface_name = ap_iface->getName();
+ if (br_ifaces_ap_instances_.count(ap_iface_name) > 0 &&
+ br_ifaces_ap_instances_[ap_iface_name].size() > 1) {
+ num_ap_bridged++;
+ } else {
+ num_ap++;
+ }
+ }
+ iface_counts[IfaceConcurrencyType::AP] = num_ap;
+ iface_counts[IfaceConcurrencyType::AP_BRIDGED] = num_ap_bridged;
+ iface_counts[IfaceConcurrencyType::NAN_IFACE] = nan_ifaces_.size();
+ iface_counts[IfaceConcurrencyType::P2P] = p2p_ifaces_.size();
+ iface_counts[IfaceConcurrencyType::STA] = sta_ifaces_.size();
+ return iface_counts;
+}
+
+// This expands the provided concurrency combinations to a more parseable
+// form. Returns a vector of available combinations possible with the number
+// of each concurrency type in the combination.
+// This method is a port of HalDeviceManager.expandConcurrencyCombos() from framework.
+std::vector<std::map<IfaceConcurrencyType, size_t>> WifiChip::expandConcurrencyCombinations(
+ const IWifiChip::ChipConcurrencyCombination& combination) {
+ int32_t num_expanded_combos = 1;
+ for (const auto& limit : combination.limits) {
+ for (int32_t i = 0; i < limit.maxIfaces; i++) {
+ num_expanded_combos *= limit.types.size();
+ }
+ }
+
+ // Allocate the vector of expanded combos and reset all concurrency type counts to 0
+ // in each combo.
+ std::vector<std::map<IfaceConcurrencyType, size_t>> expanded_combos;
+ expanded_combos.resize(num_expanded_combos);
+ for (auto& expanded_combo : expanded_combos) {
+ for (const auto type : {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED,
+ IfaceConcurrencyType::NAN_IFACE, IfaceConcurrencyType::P2P,
+ IfaceConcurrencyType::STA}) {
+ expanded_combo[type] = 0;
+ }
+ }
+ int32_t span = num_expanded_combos;
+ for (const auto& limit : combination.limits) {
+ for (int32_t i = 0; i < limit.maxIfaces; i++) {
+ span /= limit.types.size();
+ for (int32_t k = 0; k < num_expanded_combos; ++k) {
+ const auto iface_type = limit.types[(k / span) % limit.types.size()];
+ expanded_combos[k][iface_type]++;
+ }
+ }
+ }
+ return expanded_combos;
+}
+
+bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(
+ const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
+ IfaceConcurrencyType requested_type) {
+ const auto current_combo = getCurrentConcurrencyCombination();
+
+ // Check if we have space for 1 more iface of |type| in this combo
+ for (const auto type :
+ {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED,
+ IfaceConcurrencyType::NAN_IFACE, IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) {
+ size_t num_ifaces_needed = current_combo.at(type);
+ if (type == requested_type) {
+ num_ifaces_needed++;
+ }
+ size_t num_ifaces_allowed = expanded_combo.at(type);
+ if (num_ifaces_needed > num_ifaces_allowed) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// This method does the following:
+// a) Enumerate all possible concurrency combos by expanding the current
+// ChipConcurrencyCombination.
+// b) Check if the requested concurrency type can be added to the current mode
+// with the concurrency combination that is already active.
+bool WifiChip::canCurrentModeSupportConcurrencyTypeWithCurrentTypes(
+ IfaceConcurrencyType requested_type) {
+ if (!isValidModeId(current_mode_id_)) {
+ LOG(ERROR) << "Chip not configured in a mode yet";
+ return false;
+ }
+ const auto combinations = getCurrentModeConcurrencyCombinations();
+ for (const auto& combination : combinations) {
+ const auto expanded_combos = expandConcurrencyCombinations(combination);
+ for (const auto& expanded_combo : expanded_combos) {
+ if (canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(expanded_combo,
+ requested_type)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Note: This does not consider concurrency types already active. It only checks if the
+// provided expanded concurrency combination can support the requested combo.
+bool WifiChip::canExpandedConcurrencyComboSupportConcurrencyCombo(
+ const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
+ const std::map<IfaceConcurrencyType, size_t>& req_combo) {
+ // Check if we have space for 1 more |type| in this combo
+ for (const auto type :
+ {IfaceConcurrencyType::AP, IfaceConcurrencyType::AP_BRIDGED,
+ IfaceConcurrencyType::NAN_IFACE, IfaceConcurrencyType::P2P, IfaceConcurrencyType::STA}) {
+ if (req_combo.count(type) == 0) {
+ // Concurrency type not in the req_combo.
+ continue;
+ }
+ size_t num_ifaces_needed = req_combo.at(type);
+ size_t num_ifaces_allowed = expanded_combo.at(type);
+ if (num_ifaces_needed > num_ifaces_allowed) {
+ return false;
+ }
+ }
+ return true;
+}
+
+// This method does the following:
+// a) Enumerate all possible concurrency combos by expanding the current
+// ChipConcurrencyCombination.
+// b) Check if the requested concurrency combo can be added to the current mode.
+// Note: This does not consider concurrency types already active. It only checks if the
+// current mode can support the requested combo.
+bool WifiChip::canCurrentModeSupportConcurrencyCombo(
+ const std::map<IfaceConcurrencyType, size_t>& req_combo) {
+ if (!isValidModeId(current_mode_id_)) {
+ LOG(ERROR) << "Chip not configured in a mode yet";
+ return false;
+ }
+ const auto combinations = getCurrentModeConcurrencyCombinations();
+ for (const auto& combination : combinations) {
+ const auto expanded_combos = expandConcurrencyCombinations(combination);
+ for (const auto& expanded_combo : expanded_combos) {
+ if (canExpandedConcurrencyComboSupportConcurrencyCombo(expanded_combo, req_combo)) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// This method does the following:
+// a) Enumerate all possible concurrency combos by expanding the current
+// ChipConcurrencyCombination.
+// b) Check if the requested concurrency type can be added to the current mode.
+bool WifiChip::canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type) {
+ // Check if we can support at least 1 of the requested concurrency type.
+ std::map<IfaceConcurrencyType, size_t> req_iface_combo;
+ req_iface_combo[requested_type] = 1;
+ return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
+}
+
+bool WifiChip::isValidModeId(int32_t mode_id) {
+ for (const auto& mode : modes_) {
+ if (mode.id == mode_id) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool WifiChip::isStaApConcurrencyAllowedInCurrentMode() {
+ // Check if we can support at least 1 STA & 1 AP concurrently.
+ std::map<IfaceConcurrencyType, size_t> req_iface_combo;
+ req_iface_combo[IfaceConcurrencyType::STA] = 1;
+ req_iface_combo[IfaceConcurrencyType::AP] = 1;
+ return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
+}
+
+bool WifiChip::isDualStaConcurrencyAllowedInCurrentMode() {
+ // Check if we can support at least 2 STA concurrently.
+ std::map<IfaceConcurrencyType, size_t> req_iface_combo;
+ req_iface_combo[IfaceConcurrencyType::STA] = 2;
+ return canCurrentModeSupportConcurrencyCombo(req_iface_combo);
+}
+
+std::string WifiChip::getFirstActiveWlanIfaceName() {
+ if (sta_ifaces_.size() > 0) return sta_ifaces_[0]->getName();
+ if (ap_ifaces_.size() > 0) {
+ // If the first active wlan iface is bridged iface.
+ // Return first instance name.
+ for (auto const& it : br_ifaces_ap_instances_) {
+ if (it.first == ap_ifaces_[0]->getName()) {
+ return it.second[0];
+ }
+ }
+ return ap_ifaces_[0]->getName();
+ }
+ // This could happen if the chip call is made before any STA/AP
+ // iface is created. Default to wlan0 for such cases.
+ LOG(WARNING) << "No active wlan interfaces in use! Using default";
+ return getWlanIfaceNameWithType(IfaceType::STA, 0);
+}
+
+// Return the first wlan (wlan0, wlan1 etc.) starting from |start_idx|
+// not already in use.
+// Note: This doesn't check the actual presence of these interfaces.
+std::string WifiChip::allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx) {
+ for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
+ const auto ifname = getWlanIfaceNameWithType(type, idx);
+ if (findUsingNameFromBridgedApInstances(ifname)) continue;
+ if (findUsingName(ap_ifaces_, ifname)) continue;
+ if (findUsingName(sta_ifaces_, ifname)) continue;
+ return ifname;
+ }
+ // This should never happen. We screwed up somewhere if it did.
+ CHECK(false) << "All wlan interfaces in use already!";
+ return {};
+}
+
+uint32_t WifiChip::startIdxOfApIface() {
+ if (isDualStaConcurrencyAllowedInCurrentMode()) {
+ // When the HAL support dual STAs, AP should start with idx 2.
+ return 2;
+ } else if (isStaApConcurrencyAllowedInCurrentMode()) {
+ // When the HAL support STA + AP but it doesn't support dual STAs.
+ // AP should start with idx 1.
+ return 1;
+ }
+ // No concurrency support.
+ return 0;
+}
+
+// AP iface names start with idx 1 for modes supporting
+// concurrent STA and not dual AP, else start with idx 0.
+std::string WifiChip::allocateApIfaceName() {
+ // Check if we have a dedicated iface for AP.
+ std::vector<std::string> ifnames = getPredefinedApIfaceNames(true);
+ for (auto const& ifname : ifnames) {
+ if (findUsingName(ap_ifaces_, ifname)) continue;
+ return ifname;
+ }
+ return allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface());
+}
+
+std::vector<std::string> WifiChip::allocateBridgedApInstanceNames() {
+ // Check if we have a dedicated iface for AP.
+ std::vector<std::string> instances = getPredefinedApIfaceNames(true);
+ if (instances.size() == 2) {
+ return instances;
+ } else {
+ int num_ifaces_need_to_allocate = 2 - instances.size();
+ for (int i = 0; i < num_ifaces_need_to_allocate; i++) {
+ std::string instance_name =
+ allocateApOrStaIfaceName(IfaceType::AP, startIdxOfApIface() + i);
+ if (!instance_name.empty()) {
+ instances.push_back(instance_name);
+ }
+ }
+ }
+ return instances;
+}
+
+// STA iface names start with idx 0.
+// Primary STA iface will always be 0.
+std::string WifiChip::allocateStaIfaceName() {
+ return allocateApOrStaIfaceName(IfaceType::STA, 0);
+}
+
+bool WifiChip::writeRingbufferFilesInternal() {
+ if (!removeOldFilesInternal()) {
+ LOG(ERROR) << "Error occurred while deleting old tombstone files";
+ return false;
+ }
+ // write ringbuffers to file
+ {
+ std::unique_lock<std::mutex> lk(lock_t);
+ for (auto& item : ringbuffer_map_) {
+ Ringbuffer& cur_buffer = item.second;
+ if (cur_buffer.getData().empty()) {
+ continue;
+ }
+ const std::string file_path_raw = kTombstoneFolderPath + item.first + "XXXXXXXXXX";
+ const int dump_fd = mkstemp(makeCharVec(file_path_raw).data());
+ if (dump_fd == -1) {
+ PLOG(ERROR) << "create file failed";
+ return false;
+ }
+ unique_fd file_auto_closer(dump_fd);
+ for (const auto& cur_block : cur_buffer.getData()) {
+ if (cur_block.size() <= 0 || cur_block.size() > kMaxBufferSizeBytes) {
+ PLOG(ERROR) << "Ring buffer: " << item.first
+ << " is corrupted. Invalid block size: " << cur_block.size();
+ break;
+ }
+ if (write(dump_fd, cur_block.data(), sizeof(cur_block[0]) * cur_block.size()) ==
+ -1) {
+ PLOG(ERROR) << "Error writing to file";
+ }
+ }
+ cur_buffer.clear();
+ }
+ // unique_lock unlocked here
+ }
+ return true;
+}
+
+std::string WifiChip::getWlanIfaceNameWithType(IfaceType type, unsigned idx) {
+ std::string ifname;
+
+ // let the legacy hal override the interface name
+ legacy_hal::wifi_error err = legacy_hal_.lock()->getSupportedIfaceName((uint32_t)type, ifname);
+ if (err == legacy_hal::WIFI_SUCCESS) return ifname;
+
+ return getWlanIfaceName(idx);
+}
+
+void WifiChip::invalidateAndClearBridgedApAll() {
+ for (auto const& it : br_ifaces_ap_instances_) {
+ for (auto const& iface : it.second) {
+ iface_util_->removeIfaceFromBridge(it.first, iface);
+ legacy_hal_.lock()->deleteVirtualInterface(iface);
+ }
+ iface_util_->deleteBridge(it.first);
+ }
+ br_ifaces_ap_instances_.clear();
+}
+
+void WifiChip::invalidateAndClearBridgedAp(const std::string& br_name) {
+ if (br_name.empty()) return;
+ // delete managed interfaces
+ for (auto const& it : br_ifaces_ap_instances_) {
+ if (it.first == br_name) {
+ for (auto const& iface : it.second) {
+ iface_util_->removeIfaceFromBridge(br_name, iface);
+ legacy_hal_.lock()->deleteVirtualInterface(iface);
+ }
+ iface_util_->deleteBridge(br_name);
+ br_ifaces_ap_instances_.erase(br_name);
+ break;
+ }
+ }
+ return;
+}
+
+bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) {
+ for (auto const& it : br_ifaces_ap_instances_) {
+ if (it.first == name) {
+ return true;
+ }
+ for (auto const& iface : it.second) {
+ if (iface == name) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_chip.h b/wifi/aidl/default/wifi_chip.h
new file mode 100644
index 0000000..59eaa4a
--- /dev/null
+++ b/wifi/aidl/default/wifi_chip.h
@@ -0,0 +1,287 @@
+/*
+ * 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 WIFI_CHIP_H_
+#define WIFI_CHIP_H_
+
+#include <aidl/android/hardware/wifi/BnWifiChip.h>
+#include <aidl/android/hardware/wifi/IWifiRttController.h>
+#include <android-base/macros.h>
+
+#include <list>
+#include <map>
+#include <mutex>
+
+#include "aidl_callback_util.h"
+#include "ringbuffer.h"
+#include "wifi_ap_iface.h"
+#include "wifi_feature_flags.h"
+#include "wifi_legacy_hal.h"
+#include "wifi_mode_controller.h"
+#include "wifi_nan_iface.h"
+#include "wifi_p2p_iface.h"
+#include "wifi_rtt_controller.h"
+#include "wifi_sta_iface.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+/**
+ * AIDL interface object used to control a Wifi HAL chip instance.
+ * Since there is only a single chip instance used today, there is no
+ * identifying handle information stored here.
+ */
+class WifiChip : public BnWifiChip {
+ public:
+ WifiChip(int32_t chip_id, bool is_primary,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
+ const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
+ const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
+ const std::function<void(const std::string&)>& subsystemCallbackHandler);
+
+ // Factory method - use instead of default constructor.
+ static std::shared_ptr<WifiChip> create(
+ int32_t chip_id, bool is_primary,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<mode_controller::WifiModeController> mode_controller,
+ const std::shared_ptr<iface_util::WifiIfaceUtil> iface_util,
+ const std::weak_ptr<feature_flags::WifiFeatureFlags> feature_flags,
+ const std::function<void(const std::string&)>& subsystemCallbackHandler);
+
+ // AIDL does not provide a built-in mechanism to let the server invalidate
+ // an AIDL interface object after creation. If any client process holds onto
+ // a reference to the object in their context, any method calls on that
+ // reference will continue to be directed to the server.
+ //
+ // However Wifi HAL needs to control the lifetime of these objects. So, add
+ // a public |invalidate| method to |WifiChip| and its child objects. This
+ // will be used to mark an object invalid when either:
+ // a) Wifi HAL is stopped, or
+ // b) Wifi Chip is reconfigured.
+ //
+ // All AIDL method implementations should check if the object is still
+ // marked valid before processing them.
+ void invalidate();
+ bool isValid();
+ std::set<std::shared_ptr<IWifiChipEventCallback>> getEventCallbacks();
+
+ // AIDL methods exposed.
+ ndk::ScopedAStatus getId(int32_t* _aidl_return) override;
+ ndk::ScopedAStatus registerEventCallback(
+ const std::shared_ptr<IWifiChipEventCallback>& in_callback) override;
+ ndk::ScopedAStatus getCapabilities(IWifiChip::ChipCapabilityMask* _aidl_return) override;
+ ndk::ScopedAStatus getAvailableModes(std::vector<IWifiChip::ChipMode>* _aidl_return) override;
+ ndk::ScopedAStatus configureChip(int32_t in_modeId) override;
+ ndk::ScopedAStatus getMode(int32_t* _aidl_return) override;
+ ndk::ScopedAStatus requestChipDebugInfo(IWifiChip::ChipDebugInfo* _aidl_return) override;
+ ndk::ScopedAStatus requestDriverDebugDump(std::vector<uint8_t>* _aidl_return) override;
+ ndk::ScopedAStatus requestFirmwareDebugDump(std::vector<uint8_t>* _aidl_return) override;
+ ndk::ScopedAStatus createApIface(std::shared_ptr<IWifiApIface>* _aidl_return) override;
+ ndk::ScopedAStatus createBridgedApIface(std::shared_ptr<IWifiApIface>* _aidl_return) override;
+ ndk::ScopedAStatus getApIfaceNames(std::vector<std::string>* _aidl_return) override;
+ ndk::ScopedAStatus getApIface(const std::string& in_ifname,
+ std::shared_ptr<IWifiApIface>* _aidl_return) override;
+ ndk::ScopedAStatus removeApIface(const std::string& in_ifname) override;
+ ndk::ScopedAStatus removeIfaceInstanceFromBridgedApIface(
+ const std::string& in_brIfaceName, const std::string& in_ifaceInstanceName) override;
+ ndk::ScopedAStatus createNanIface(std::shared_ptr<IWifiNanIface>* _aidl_return) override;
+ ndk::ScopedAStatus getNanIfaceNames(std::vector<std::string>* _aidl_return) override;
+ ndk::ScopedAStatus getNanIface(const std::string& in_ifname,
+ std::shared_ptr<IWifiNanIface>* _aidl_return) override;
+ ndk::ScopedAStatus removeNanIface(const std::string& in_ifname) override;
+ ndk::ScopedAStatus createP2pIface(std::shared_ptr<IWifiP2pIface>* _aidl_return) override;
+ ndk::ScopedAStatus getP2pIfaceNames(std::vector<std::string>* _aidl_return) override;
+ ndk::ScopedAStatus getP2pIface(const std::string& in_ifname,
+ std::shared_ptr<IWifiP2pIface>* _aidl_return) override;
+ ndk::ScopedAStatus removeP2pIface(const std::string& in_ifname) override;
+ ndk::ScopedAStatus createStaIface(std::shared_ptr<IWifiStaIface>* _aidl_return) override;
+ ndk::ScopedAStatus getStaIfaceNames(std::vector<std::string>* _aidl_return) override;
+ ndk::ScopedAStatus getStaIface(const std::string& in_ifname,
+ std::shared_ptr<IWifiStaIface>* _aidl_return) override;
+ ndk::ScopedAStatus removeStaIface(const std::string& in_ifname) override;
+ ndk::ScopedAStatus createRttController(
+ const std::shared_ptr<IWifiStaIface>& in_boundIface,
+ std::shared_ptr<IWifiRttController>* _aidl_return) override;
+ ndk::ScopedAStatus getDebugRingBuffersStatus(
+ std::vector<WifiDebugRingBufferStatus>* _aidl_return) override;
+ ndk::ScopedAStatus startLoggingToDebugRingBuffer(
+ const std::string& in_ringName, WifiDebugRingBufferVerboseLevel in_verboseLevel,
+ int32_t in_maxIntervalInSec, int32_t in_minDataSizeInBytes) override;
+ ndk::ScopedAStatus forceDumpToDebugRingBuffer(const std::string& in_ringName) override;
+ ndk::ScopedAStatus flushRingBufferToFile() override;
+ ndk::ScopedAStatus stopLoggingToDebugRingBuffer() override;
+ ndk::ScopedAStatus getDebugHostWakeReasonStats(
+ WifiDebugHostWakeReasonStats* _aidl_return) override;
+ ndk::ScopedAStatus enableDebugErrorAlerts(bool in_enable) override;
+ ndk::ScopedAStatus selectTxPowerScenario(IWifiChip::TxPowerScenario in_scenario) override;
+ ndk::ScopedAStatus resetTxPowerScenario() override;
+ ndk::ScopedAStatus setLatencyMode(IWifiChip::LatencyMode in_mode) override;
+ ndk::ScopedAStatus setMultiStaPrimaryConnection(const std::string& in_ifName) override;
+ ndk::ScopedAStatus setMultiStaUseCase(IWifiChip::MultiStaUseCase in_useCase) override;
+ ndk::ScopedAStatus setCoexUnsafeChannels(
+ const std::vector<IWifiChip::CoexUnsafeChannel>& in_unsafeChannels,
+ CoexRestriction in_restrictions) override;
+ ndk::ScopedAStatus setCountryCode(const std::array<uint8_t, 2>& in_code) override;
+ ndk::ScopedAStatus getUsableChannels(WifiBand in_band, WifiIfaceMode in_ifaceModeMask,
+ UsableChannelFilter in_filterMask,
+ std::vector<WifiUsableChannel>* _aidl_return) override;
+ ndk::ScopedAStatus triggerSubsystemRestart() override;
+ ndk::ScopedAStatus getSupportedRadioCombinationsMatrix(
+ WifiRadioCombinationMatrix* _aidl_return) override;
+ binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;
+
+ private:
+ void invalidateAndRemoveAllIfaces();
+ // When a STA iface is removed any dependent NAN-ifaces/RTT-controllers are
+ // invalidated & removed.
+ void invalidateAndRemoveDependencies(const std::string& removed_iface_name);
+
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<int32_t, ndk::ScopedAStatus> getIdInternal();
+ ndk::ScopedAStatus registerEventCallbackInternal(
+ const std::shared_ptr<IWifiChipEventCallback>& event_callback);
+ std::pair<IWifiChip::ChipCapabilityMask, ndk::ScopedAStatus> getCapabilitiesInternal();
+ std::pair<std::vector<IWifiChip::ChipMode>, ndk::ScopedAStatus> getAvailableModesInternal();
+ ndk::ScopedAStatus configureChipInternal(std::unique_lock<std::recursive_mutex>* lock,
+ int32_t mode_id);
+ std::pair<int32_t, ndk::ScopedAStatus> getModeInternal();
+ std::pair<IWifiChip::ChipDebugInfo, ndk::ScopedAStatus> requestChipDebugInfoInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> requestDriverDebugDumpInternal();
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> requestFirmwareDebugDumpInternal();
+ std::shared_ptr<WifiApIface> newWifiApIface(std::string& ifname);
+ ndk::ScopedAStatus createVirtualApInterface(const std::string& apVirtIf);
+ std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createApIfaceInternal();
+ std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> createBridgedApIfaceInternal();
+ std::pair<std::vector<std::string>, ndk::ScopedAStatus> getApIfaceNamesInternal();
+ std::pair<std::shared_ptr<IWifiApIface>, ndk::ScopedAStatus> getApIfaceInternal(
+ const std::string& ifname);
+ ndk::ScopedAStatus removeApIfaceInternal(const std::string& ifname);
+ ndk::ScopedAStatus removeIfaceInstanceFromBridgedApIfaceInternal(
+ const std::string& brIfaceName, const std::string& ifInstanceName);
+ std::pair<std::shared_ptr<IWifiNanIface>, ndk::ScopedAStatus> createNanIfaceInternal();
+ std::pair<std::vector<std::string>, ndk::ScopedAStatus> getNanIfaceNamesInternal();
+ std::pair<std::shared_ptr<IWifiNanIface>, ndk::ScopedAStatus> getNanIfaceInternal(
+ const std::string& ifname);
+ ndk::ScopedAStatus removeNanIfaceInternal(const std::string& ifname);
+ std::pair<std::shared_ptr<IWifiP2pIface>, ndk::ScopedAStatus> createP2pIfaceInternal();
+ std::pair<std::vector<std::string>, ndk::ScopedAStatus> getP2pIfaceNamesInternal();
+ std::pair<std::shared_ptr<IWifiP2pIface>, ndk::ScopedAStatus> getP2pIfaceInternal(
+ const std::string& ifname);
+ ndk::ScopedAStatus removeP2pIfaceInternal(const std::string& ifname);
+ std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus> createStaIfaceInternal();
+ std::pair<std::vector<std::string>, ndk::ScopedAStatus> getStaIfaceNamesInternal();
+ std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus> getStaIfaceInternal(
+ const std::string& ifname);
+ ndk::ScopedAStatus removeStaIfaceInternal(const std::string& ifname);
+ std::pair<std::shared_ptr<IWifiRttController>, ndk::ScopedAStatus> createRttControllerInternal(
+ const std::shared_ptr<IWifiStaIface>& bound_iface);
+ std::pair<std::vector<WifiDebugRingBufferStatus>, ndk::ScopedAStatus>
+ getDebugRingBuffersStatusInternal();
+ ndk::ScopedAStatus startLoggingToDebugRingBufferInternal(
+ const std::string& ring_name, WifiDebugRingBufferVerboseLevel verbose_level,
+ uint32_t max_interval_in_sec, uint32_t min_data_size_in_bytes);
+ ndk::ScopedAStatus forceDumpToDebugRingBufferInternal(const std::string& ring_name);
+ ndk::ScopedAStatus flushRingBufferToFileInternal();
+ ndk::ScopedAStatus stopLoggingToDebugRingBufferInternal();
+ std::pair<WifiDebugHostWakeReasonStats, ndk::ScopedAStatus>
+ getDebugHostWakeReasonStatsInternal();
+ ndk::ScopedAStatus enableDebugErrorAlertsInternal(bool enable);
+ ndk::ScopedAStatus selectTxPowerScenarioInternal(IWifiChip::TxPowerScenario scenario);
+ ndk::ScopedAStatus resetTxPowerScenarioInternal();
+ ndk::ScopedAStatus setLatencyModeInternal(IWifiChip::LatencyMode mode);
+ ndk::ScopedAStatus setMultiStaPrimaryConnectionInternal(const std::string& ifname);
+ ndk::ScopedAStatus setMultiStaUseCaseInternal(IWifiChip::MultiStaUseCase use_case);
+ ndk::ScopedAStatus setCoexUnsafeChannelsInternal(
+ std::vector<IWifiChip::CoexUnsafeChannel> unsafe_channels,
+ CoexRestriction restrictions);
+ ndk::ScopedAStatus setCountryCodeInternal(const std::array<uint8_t, 2>& in_code);
+ std::pair<std::vector<WifiUsableChannel>, ndk::ScopedAStatus> getUsableChannelsInternal(
+ WifiBand band, WifiIfaceMode ifaceModeMask, UsableChannelFilter filterMask);
+ ndk::ScopedAStatus handleChipConfiguration(std::unique_lock<std::recursive_mutex>* lock,
+ int32_t mode_id);
+ ndk::ScopedAStatus registerDebugRingBufferCallback();
+ ndk::ScopedAStatus registerRadioModeChangeCallback();
+
+ std::vector<ChipConcurrencyCombination> getCurrentModeConcurrencyCombinations();
+ std::map<IfaceConcurrencyType, size_t> getCurrentConcurrencyCombination();
+ std::vector<std::map<IfaceConcurrencyType, size_t>> expandConcurrencyCombinations(
+ const ChipConcurrencyCombination& combination);
+ bool canExpandedConcurrencyComboSupportConcurrencyTypeWithCurrentTypes(
+ const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
+ IfaceConcurrencyType requested_type);
+ bool canCurrentModeSupportConcurrencyTypeWithCurrentTypes(IfaceConcurrencyType requested_type);
+ bool canExpandedConcurrencyComboSupportConcurrencyCombo(
+ const std::map<IfaceConcurrencyType, size_t>& expanded_combo,
+ const std::map<IfaceConcurrencyType, size_t>& req_combo);
+ bool canCurrentModeSupportConcurrencyCombo(
+ const std::map<IfaceConcurrencyType, size_t>& req_combo);
+ bool canCurrentModeSupportConcurrencyType(IfaceConcurrencyType requested_type);
+
+ bool isValidModeId(int32_t mode_id);
+ bool isStaApConcurrencyAllowedInCurrentMode();
+ bool isDualStaConcurrencyAllowedInCurrentMode();
+ uint32_t startIdxOfApIface();
+ std::string getFirstActiveWlanIfaceName();
+ std::string allocateApOrStaIfaceName(IfaceType type, uint32_t start_idx);
+ std::string allocateApIfaceName();
+ std::vector<std::string> allocateBridgedApInstanceNames();
+ std::string allocateStaIfaceName();
+ bool writeRingbufferFilesInternal();
+ std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
+ void invalidateAndClearBridgedApAll();
+ void invalidateAndClearBridgedAp(const std::string& br_name);
+ bool findUsingNameFromBridgedApInstances(const std::string& name);
+ ndk::ScopedAStatus triggerSubsystemRestartInternal();
+ std::pair<WifiRadioCombinationMatrix, ndk::ScopedAStatus>
+ getSupportedRadioCombinationsMatrixInternal();
+ void setWeakPtr(std::weak_ptr<WifiChip> ptr);
+
+ int32_t chip_id_;
+ std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ std::weak_ptr<mode_controller::WifiModeController> mode_controller_;
+ std::shared_ptr<iface_util::WifiIfaceUtil> iface_util_;
+ std::vector<std::shared_ptr<WifiApIface>> ap_ifaces_;
+ std::vector<std::shared_ptr<WifiNanIface>> nan_ifaces_;
+ std::vector<std::shared_ptr<WifiP2pIface>> p2p_ifaces_;
+ std::vector<std::shared_ptr<WifiStaIface>> sta_ifaces_;
+ std::vector<std::shared_ptr<WifiRttController>> rtt_controllers_;
+ std::map<std::string, Ringbuffer> ringbuffer_map_;
+ bool is_valid_;
+ // Members pertaining to chip configuration.
+ int32_t current_mode_id_;
+ std::mutex lock_t;
+ std::vector<IWifiChip::ChipMode> modes_;
+ // The legacy ring buffer callback API has only a global callback
+ // registration mechanism. Use this to check if we have already
+ // registered a callback.
+ bool debug_ring_buffer_cb_registered_;
+ aidl_callback_util::AidlCallbackHandler<IWifiChipEventCallback> event_cb_handler_;
+ std::weak_ptr<WifiChip> weak_ptr_this_;
+
+ const std::function<void(const std::string&)> subsystemCallbackHandler_;
+ std::map<std::string, std::vector<std::string>> br_ifaces_ap_instances_;
+ DISALLOW_COPY_AND_ASSIGN(WifiChip);
+};
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_CHIP_H_
diff --git a/wifi/aidl/default/wifi_feature_flags.cpp b/wifi/aidl/default/wifi_feature_flags.cpp
new file mode 100644
index 0000000..3c9f042
--- /dev/null
+++ b/wifi/aidl/default/wifi_feature_flags.cpp
@@ -0,0 +1,228 @@
+/*
+ * 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 <string>
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+
+#include "wifi_feature_flags.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace feature_flags {
+
+/* The chip may either have a single mode supporting any number of combinations,
+ * or a fixed dual-mode (so it involves firmware loading to switch between
+ * modes) setting. If there is a need to support more modes, it needs to be
+ * implemented manually in WiFi HAL (see changeFirmwareMode in
+ * WifiChip::handleChipConfiguration).
+ *
+ * Supported combinations are defined in device's makefile, for example:
+ * WIFI_HAL_INTERFACE_COMBINATIONS := {{{STA, AP}, 1}, {{P2P, NAN}, 1}},
+ * WIFI_HAL_INTERFACE_COMBINATIONS += {{{STA}, 1}, {{AP}, 2}}
+ * What this means:
+ * Interface concurrency combination 1: 1 STA or AP and 1 P2P or NAN concurrent iface
+ * operations.
+ * Interface concurrency combination 2: 1 STA and 2 AP concurrent iface operations.
+ *
+ * For backward compatibility, the following makefile flags can be used to
+ * generate combinations list:
+ * - WIFI_HIDL_FEATURE_DUAL_INTERFACE
+ * - WIFI_HIDL_FEATURE_DISABLE_AP
+ * - WIFI_HIDL_FEATURE_AWARE
+ * However, they are ignored if WIFI_HAL_INTERFACE_COMBINATIONS was provided.
+ * With WIFI_HIDL_FEATURE_DUAL_INTERFACE flag set, there is a single mode with
+ * two concurrency combinations:
+ * Interface Concurrency Combination 1: Will support 1 STA and 1 P2P or NAN (optional)
+ * concurrent iface operations.
+ * Interface Concurrency Combination 2: Will support 1 STA and 1 AP concurrent
+ * iface operations.
+ *
+ * The only dual-mode configuration supported is for alternating STA and AP
+ * mode, that may involve firmware reloading. In such case, there are 2 separate
+ * modes of operation with 1 concurrency combination each:
+ * Mode 1 (STA mode): Will support 1 STA and 1 P2P or NAN (optional)
+ * concurrent iface operations.
+ * Mode 2 (AP mode): Will support 1 AP iface operation.
+ *
+ * If Aware is enabled, the concurrency combination will be modified to support either
+ * P2P or NAN in place of just P2P.
+ */
+// clang-format off
+#ifdef WIFI_HAL_INTERFACE_COMBINATIONS
+constexpr int kMainModeId = chip_mode_ids::kV3;
+#elif defined(WIFI_HIDL_FEATURE_DUAL_INTERFACE)
+// former V2 (fixed dual interface) setup expressed as V3
+constexpr int kMainModeId = chip_mode_ids::kV3;
+# ifdef WIFI_HIDL_FEATURE_DISABLE_AP
+# ifdef WIFI_HIDL_FEATURE_AWARE
+// 1 STA + 1 of (P2P or NAN)
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}}
+# else
+// 1 STA + 1 P2P
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
+# endif
+# else
+# ifdef WIFI_HIDL_FEATURE_AWARE
+// (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+ {{{STA}, 1}, {{P2P, NAN}, 1}}
+# else
+// (1 STA + 1 AP) or (1 STA + 1 P2P)
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{AP}, 1}},\
+ {{{STA}, 1}, {{P2P}, 1}}
+# endif
+# endif
+#else
+// V1 (fixed single interface, dual-mode chip)
+constexpr int kMainModeId = chip_mode_ids::kV1Sta;
+# ifdef WIFI_HIDL_FEATURE_AWARE
+// 1 STA + 1 of (P2P or NAN)
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P, NAN}, 1}}
+# else
+// 1 STA + 1 P2P
+# define WIFI_HAL_INTERFACE_COMBINATIONS {{{STA}, 1}, {{P2P}, 1}}
+# endif
+
+# ifndef WIFI_HIDL_FEATURE_DISABLE_AP
+# define WIFI_HAL_INTERFACE_COMBINATIONS_AP {{{AP}, 1}}
+# endif
+#endif
+// clang-format on
+
+// Convert from the legacy format (used by the WIFI_HAL_INTERFACE_COMBINATIONS
+// config variable) to a list of ChipConcurrencyCombination objects.
+std::vector<IWifiChip::ChipConcurrencyCombination> legacyToChipConcurrencyComboList(
+ std::vector<std::vector<IWifiChip::ChipConcurrencyCombinationLimit>> legacyLimits) {
+ std::vector<IWifiChip::ChipConcurrencyCombination> combos;
+ for (auto& legacyLimit : legacyLimits) {
+ IWifiChip::ChipConcurrencyCombination combo = {legacyLimit};
+ combos.push_back(combo);
+ }
+ return combos;
+}
+
+#define STA IfaceConcurrencyType::STA
+#define AP IfaceConcurrencyType::AP
+#define AP_BRIDGED IfaceConcurrencyType::AP_BRIDGED
+#define P2P IfaceConcurrencyType::P2P
+#define NAN IfaceConcurrencyType::NAN_IFACE
+static const std::vector<IWifiChip::ChipMode> kChipModesPrimary{
+ {kMainModeId, legacyToChipConcurrencyComboList({WIFI_HAL_INTERFACE_COMBINATIONS})},
+#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_AP
+ {chip_mode_ids::kV1Ap,
+ legacyToChipConcurrencyComboList({WIFI_HAL_INTERFACE_COMBINATIONS_AP})},
+#endif
+};
+
+static const std::vector<IWifiChip::ChipMode> kChipModesSecondary{
+#ifdef WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP
+ {chip_mode_ids::kV3,
+ legacyToChipConcurrencyComboList({WIFI_HAL_INTERFACE_COMBINATIONS_SECONDARY_CHIP})},
+#endif
+};
+
+constexpr char kDebugPresetInterfaceCombinationIdxProperty[] =
+ "persist.vendor.debug.wifi.hal.preset_interface_combination_idx";
+// List of pre-defined concurrency combinations that can be enabled at runtime via
+// setting the property: "kDebugPresetInterfaceCombinationIdxProperty" to the
+// corresponding index value.
+static const std::vector<std::pair<std::string, std::vector<IWifiChip::ChipMode>>> kDebugChipModes{
+ // Legacy combination - No STA/AP concurrencies.
+ // 0 - (1 AP) or (1 STA + 1 of (P2P or NAN))
+ {"No STA/AP Concurrency",
+ {{kMainModeId,
+ legacyToChipConcurrencyComboList({{{{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
+
+ // STA + AP concurrency
+ // 1 - (1 STA + 1 AP) or (1 STA + 1 of (P2P or NAN))
+ {"STA + AP Concurrency",
+ {{kMainModeId, legacyToChipConcurrencyComboList(
+ {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
+
+ // STA + STA concurrency
+ // 2 - (1 STA + 1 AP) or (2 STA + 1 of (P2P or NAN))
+ {"Dual STA Concurrency",
+ {{kMainModeId, legacyToChipConcurrencyComboList(
+ {{{{STA}, 1}, {{AP}, 1}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}},
+
+ // AP + AP + STA concurrency
+ // 3 - (1 STA + 2 AP) or (1 STA + 1 of (P2P or NAN))
+ {"Dual AP Concurrency",
+ {{kMainModeId, legacyToChipConcurrencyComboList(
+ {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 1}, {{P2P, NAN}, 1}}})}}},
+
+ // STA + STA concurrency and AP + AP + STA concurrency
+ // 4 - (1 STA + 2 AP) or (2 STA + 1 of (P2P or NAN))
+ {"Dual STA & Dual AP Concurrency",
+ {{kMainModeId, legacyToChipConcurrencyComboList(
+ {{{{STA}, 1}, {{AP}, 2}}, {{{STA}, 2}, {{P2P, NAN}, 1}}})}}},
+
+ // STA + STA concurrency
+ // 5 - (1 STA + 1 AP (bridged or single) | P2P | NAN), or (2 STA))
+ {"Dual STA or STA plus single other interface",
+ {{kMainModeId, legacyToChipConcurrencyComboList(
+ {{{{STA}, 1}, {{P2P, NAN, AP, AP_BRIDGED}, 1}}, {{{STA}, 2}}})}}}};
+
+#undef STA
+#undef AP
+#undef AP_BRIDGED
+#undef P2P
+#undef NAN
+
+#ifdef WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
+#pragma message \
+ "WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION is deprecated; override " \
+ "'config_wifi_ap_randomization_supported' in " \
+ "frameworks/base/core/res/res/values/config.xml in the device overlay " \
+ "instead"
+#endif // WIFI_HIDL_FEATURE_DISABLE_AP_MAC_RANDOMIZATION
+
+WifiFeatureFlags::WifiFeatureFlags() {}
+
+std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModesForPrimary() {
+ std::array<char, PROPERTY_VALUE_MAX> buffer;
+ auto res = property_get(kDebugPresetInterfaceCombinationIdxProperty, buffer.data(), nullptr);
+ // Debug property not set, use the device preset concurrency combination.
+ if (res <= 0) return kChipModesPrimary;
+
+ // Debug property set, use one of the debug preset concurrency combination.
+ unsigned long idx = std::stoul(buffer.data());
+ if (idx >= kDebugChipModes.size()) {
+ LOG(ERROR) << "Invalid index set in property: "
+ << kDebugPresetInterfaceCombinationIdxProperty;
+ return kChipModesPrimary;
+ }
+ std::string name;
+ std::vector<IWifiChip::ChipMode> chip_modes;
+ std::tie(name, chip_modes) = kDebugChipModes[idx];
+ LOG(INFO) << "Using debug chip mode: <" << name
+ << "> set via property: " << kDebugPresetInterfaceCombinationIdxProperty;
+ return chip_modes;
+}
+
+std::vector<IWifiChip::ChipMode> WifiFeatureFlags::getChipModes(bool is_primary) {
+ return (is_primary) ? getChipModesForPrimary() : kChipModesSecondary;
+}
+
+} // namespace feature_flags
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_feature_flags.h b/wifi/aidl/default/wifi_feature_flags.h
new file mode 100644
index 0000000..af1b6a6
--- /dev/null
+++ b/wifi/aidl/default/wifi_feature_flags.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 WIFI_FEATURE_FLAGS_H_
+#define WIFI_FEATURE_FLAGS_H_
+
+#include <aidl/android/hardware/wifi/IWifiChip.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace feature_flags {
+
+namespace chip_mode_ids {
+// These mode ID's should be unique (even across combo versions). Refer to
+// handleChipConfiguration() for its usage.
+constexpr uint32_t kInvalid = UINT32_MAX;
+// Mode ID's for V1
+constexpr uint32_t kV1Sta = 0;
+constexpr uint32_t kV1Ap = 1;
+// Mode ID for V3
+constexpr uint32_t kV3 = 3;
+} // namespace chip_mode_ids
+
+class WifiFeatureFlags {
+ public:
+ WifiFeatureFlags();
+ virtual ~WifiFeatureFlags() = default;
+
+ virtual std::vector<IWifiChip::ChipMode> getChipModes(bool is_primary);
+
+ private:
+ std::vector<IWifiChip::ChipMode> getChipModesForPrimary();
+};
+
+} // namespace feature_flags
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_FEATURE_FLAGS_H_
diff --git a/wifi/aidl/default/wifi_iface_util.cpp b/wifi/aidl/default/wifi_iface_util.cpp
new file mode 100644
index 0000000..f788217
--- /dev/null
+++ b/wifi/aidl/default/wifi_iface_util.cpp
@@ -0,0 +1,174 @@
+/*
+ * 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-base/logging.h>
+#include <android-base/macros.h>
+#include <net/if.h>
+#include <private/android_filesystem_config.h>
+
+#include <cstddef>
+#include <iostream>
+#include <limits>
+#include <random>
+
+#include "wifi_iface_util.h"
+
+namespace {
+// Constants to set the local bit & clear the multicast bit.
+constexpr uint8_t kMacAddressMulticastMask = 0x01;
+constexpr uint8_t kMacAddressLocallyAssignedMask = 0x02;
+
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace iface_util {
+
+WifiIfaceUtil::WifiIfaceUtil(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+ : iface_tool_(iface_tool),
+ legacy_hal_(legacy_hal),
+ random_mac_address_(nullptr),
+ event_handlers_map_() {}
+
+std::array<uint8_t, 6> WifiIfaceUtil::getFactoryMacAddress(const std::string& iface_name) {
+ return iface_tool_.lock()->GetFactoryMacAddress(iface_name.c_str());
+}
+
+bool WifiIfaceUtil::setMacAddress(const std::string& iface_name,
+ const std::array<uint8_t, 6>& mac) {
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+ legacy_hal::wifi_error legacy_status;
+ uint64_t legacy_feature_set;
+ std::tie(legacy_status, legacy_feature_set) =
+ legacy_hal_.lock()->getSupportedFeatureSet(iface_name);
+
+ if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) &&
+ !iface_tool_.lock()->SetUpState(iface_name.c_str(), false)) {
+ LOG(ERROR) << "SetUpState(false) failed.";
+ return false;
+ }
+#endif
+ bool success = iface_tool_.lock()->SetMacAddress(iface_name.c_str(), mac);
+#ifndef WIFI_AVOID_IFACE_RESET_MAC_CHANGE
+ if (!(legacy_feature_set & WIFI_FEATURE_DYNAMIC_SET_MAC) &&
+ !iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
+ LOG(ERROR) << "SetUpState(true) failed. Wait for driver ready.";
+ // Wait for driver ready and try to set iface UP again
+ if (legacy_hal_.lock()->waitForDriverReady() != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "SetUpState(true) wait for driver ready failed.";
+ return false;
+ }
+ if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), true)) {
+ LOG(ERROR) << "SetUpState(true) failed after retry.";
+ return false;
+ }
+ }
+#endif
+ IfaceEventHandlers event_handlers = {};
+ const auto it = event_handlers_map_.find(iface_name);
+ if (it != event_handlers_map_.end()) {
+ event_handlers = it->second;
+ }
+ if (event_handlers.on_state_toggle_off_on != nullptr) {
+ event_handlers.on_state_toggle_off_on(iface_name);
+ }
+ if (!success) {
+ LOG(ERROR) << "SetMacAddress failed on " << iface_name;
+ } else {
+ LOG(DEBUG) << "SetMacAddress succeeded on " << iface_name;
+ }
+ return success;
+}
+
+std::array<uint8_t, 6> WifiIfaceUtil::getOrCreateRandomMacAddress() {
+ if (random_mac_address_) {
+ return *random_mac_address_.get();
+ }
+ random_mac_address_ = std::make_unique<std::array<uint8_t, 6>>(createRandomMacAddress());
+ return *random_mac_address_.get();
+}
+
+void WifiIfaceUtil::registerIfaceEventHandlers(const std::string& iface_name,
+ IfaceEventHandlers handlers) {
+ event_handlers_map_[iface_name] = handlers;
+}
+
+void WifiIfaceUtil::unregisterIfaceEventHandlers(const std::string& iface_name) {
+ event_handlers_map_.erase(iface_name);
+}
+
+std::array<uint8_t, 6> WifiIfaceUtil::createRandomMacAddress() {
+ std::array<uint8_t, 6> address = {};
+ std::random_device rd;
+ std::default_random_engine engine(rd());
+ std::uniform_int_distribution<uint8_t> dist(std::numeric_limits<uint8_t>::min(),
+ std::numeric_limits<uint8_t>::max());
+ for (size_t i = 0; i < address.size(); i++) {
+ address[i] = dist(engine);
+ }
+ // Set the local bit and clear the multicast bit.
+ address[0] |= kMacAddressLocallyAssignedMask;
+ address[0] &= ~kMacAddressMulticastMask;
+ return address;
+}
+
+bool WifiIfaceUtil::setUpState(const std::string& iface_name, bool request_up) {
+ if (!iface_tool_.lock()->SetUpState(iface_name.c_str(), request_up)) {
+ LOG(ERROR) << "SetUpState to " << request_up << " failed";
+ return false;
+ }
+ return true;
+}
+
+unsigned WifiIfaceUtil::ifNameToIndex(const std::string& iface_name) {
+ return if_nametoindex(iface_name.c_str());
+}
+
+bool WifiIfaceUtil::createBridge(const std::string& br_name) {
+ if (!iface_tool_.lock()->createBridge(br_name)) {
+ return false;
+ }
+
+ if (!iface_tool_.lock()->SetUpState(br_name.c_str(), true)) {
+ LOG(ERROR) << "bridge SetUpState(true) failed.";
+ }
+ return true;
+}
+
+bool WifiIfaceUtil::deleteBridge(const std::string& br_name) {
+ if (!iface_tool_.lock()->SetUpState(br_name.c_str(), false)) {
+ LOG(INFO) << "SetUpState(false) failed for bridge=" << br_name.c_str();
+ }
+
+ return iface_tool_.lock()->deleteBridge(br_name);
+}
+
+bool WifiIfaceUtil::addIfaceToBridge(const std::string& br_name, const std::string& if_name) {
+ return iface_tool_.lock()->addIfaceToBridge(br_name, if_name);
+}
+
+bool WifiIfaceUtil::removeIfaceFromBridge(const std::string& br_name, const std::string& if_name) {
+ return iface_tool_.lock()->removeIfaceFromBridge(br_name, if_name);
+}
+
+} // namespace iface_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_iface_util.h b/wifi/aidl/default/wifi_iface_util.h
new file mode 100644
index 0000000..a3236a5
--- /dev/null
+++ b/wifi/aidl/default/wifi_iface_util.h
@@ -0,0 +1,84 @@
+/*
+ * 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 WIFI_IFACE_UTIL_H_
+#define WIFI_IFACE_UTIL_H_
+
+#include <aidl/android/hardware/wifi/IWifi.h>
+#include <wifi_system/interface_tool.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace iface_util {
+
+// Iface event handlers.
+struct IfaceEventHandlers {
+ // Callback to be invoked when the iface is set down & up for MAC address
+ // change.
+ std::function<void(const std::string& iface_name)> on_state_toggle_off_on;
+};
+
+/**
+ * Util class for common iface operations.
+ */
+class WifiIfaceUtil {
+ public:
+ WifiIfaceUtil(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+ virtual ~WifiIfaceUtil() = default;
+
+ virtual std::array<uint8_t, 6> getFactoryMacAddress(const std::string& iface_name);
+ virtual bool setMacAddress(const std::string& iface_name, const std::array<uint8_t, 6>& mac);
+ // Get or create a random MAC address. The MAC address returned from
+ // this method will remain the same throughout the lifetime of the HAL
+ // daemon. (So, changes on every reboot)
+ virtual std::array<uint8_t, 6> getOrCreateRandomMacAddress();
+
+ // Register for any iface event callbacks for the provided interface.
+ virtual void registerIfaceEventHandlers(const std::string& iface_name,
+ IfaceEventHandlers handlers);
+ virtual void unregisterIfaceEventHandlers(const std::string& iface_name);
+ virtual bool setUpState(const std::string& iface_name, bool request_up);
+ virtual unsigned ifNameToIndex(const std::string& iface_name);
+
+ virtual bool createBridge(const std::string& br_name);
+
+ virtual bool deleteBridge(const std::string& br_name);
+
+ virtual bool addIfaceToBridge(const std::string& br_name, const std::string& if_name);
+
+ virtual bool removeIfaceFromBridge(const std::string& br_name, const std::string& if_name);
+ // Get a random MAC address.
+ virtual std::array<uint8_t, 6> createRandomMacAddress();
+
+ private:
+ std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool_;
+ std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ std::unique_ptr<std::array<uint8_t, 6>> random_mac_address_;
+ std::map<std::string, IfaceEventHandlers> event_handlers_map_;
+};
+
+} // namespace iface_util
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_IFACE_UTIL_H_
diff --git a/wifi/aidl/default/wifi_legacy_hal.cpp b/wifi/aidl/default/wifi_legacy_hal.cpp
new file mode 100644
index 0000000..43e73ca
--- /dev/null
+++ b/wifi/aidl/default/wifi_legacy_hal.cpp
@@ -0,0 +1,1654 @@
+/*
+ * 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 "wifi_legacy_hal.h"
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+#include <net/if.h>
+
+#include <array>
+#include <chrono>
+
+#include "aidl_sync_util.h"
+#include "wifi_legacy_hal_stubs.h"
+
+namespace {
+// Constants ported over from the legacy HAL calling code
+// (com_android_server_wifi_WifiNative.cpp). This will all be thrown
+// away when this shim layer is replaced by the real vendor
+// implementation.
+static constexpr uint32_t kMaxVersionStringLength = 256;
+static constexpr uint32_t kMaxCachedGscanResults = 64;
+static constexpr uint32_t kMaxGscanFrequenciesForBand = 64;
+static constexpr uint32_t kLinkLayerStatsDataMpduSizeThreshold = 128;
+static constexpr uint32_t kMaxWakeReasonStatsArraySize = 32;
+static constexpr uint32_t kMaxRingBuffers = 10;
+static constexpr uint32_t kMaxWifiUsableChannels = 256;
+static constexpr uint32_t kMaxSupportedRadioCombinationsMatrixLength = 256;
+// Need a long timeout (1000ms) for chips that unload their driver.
+static constexpr uint32_t kMaxStopCompleteWaitMs = 1000;
+static constexpr char kDriverPropName[] = "wlan.driver.status";
+
+// Helper function to create a non-const char* for legacy Hal API's.
+std::vector<char> makeCharVec(const std::string& str) {
+ std::vector<char> vec(str.size() + 1);
+ vec.assign(str.begin(), str.end());
+ vec.push_back('\0');
+ return vec;
+}
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace legacy_hal {
+
+// Legacy HAL functions accept "C" style function pointers, so use global
+// functions to pass to the legacy HAL function and store the corresponding
+// std::function methods to be invoked.
+//
+// Callback to be invoked once |stop| is complete
+std::function<void(wifi_handle handle)> on_stop_complete_internal_callback;
+void onAsyncStopComplete(wifi_handle handle) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_stop_complete_internal_callback) {
+ on_stop_complete_internal_callback(handle);
+ // Invalidate this callback since we don't want this firing again.
+ on_stop_complete_internal_callback = nullptr;
+ }
+}
+
+// Callback to be invoked for driver dump.
+std::function<void(char*, int)> on_driver_memory_dump_internal_callback;
+void onSyncDriverMemoryDump(char* buffer, int buffer_size) {
+ if (on_driver_memory_dump_internal_callback) {
+ on_driver_memory_dump_internal_callback(buffer, buffer_size);
+ }
+}
+
+// Callback to be invoked for firmware dump.
+std::function<void(char*, int)> on_firmware_memory_dump_internal_callback;
+void onSyncFirmwareMemoryDump(char* buffer, int buffer_size) {
+ if (on_firmware_memory_dump_internal_callback) {
+ on_firmware_memory_dump_internal_callback(buffer, buffer_size);
+ }
+}
+
+// Callback to be invoked for Gscan events.
+std::function<void(wifi_request_id, wifi_scan_event)> on_gscan_event_internal_callback;
+void onAsyncGscanEvent(wifi_request_id id, wifi_scan_event event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_gscan_event_internal_callback) {
+ on_gscan_event_internal_callback(id, event);
+ }
+}
+
+// Callback to be invoked for Gscan full results.
+std::function<void(wifi_request_id, wifi_scan_result*, uint32_t)>
+ on_gscan_full_result_internal_callback;
+void onAsyncGscanFullResult(wifi_request_id id, wifi_scan_result* result,
+ uint32_t buckets_scanned) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_gscan_full_result_internal_callback) {
+ on_gscan_full_result_internal_callback(id, result, buckets_scanned);
+ }
+}
+
+// Callback to be invoked for link layer stats results.
+std::function<void((wifi_request_id, wifi_iface_stat*, int, wifi_radio_stat*))>
+ on_link_layer_stats_result_internal_callback;
+void onSyncLinkLayerStatsResult(wifi_request_id id, wifi_iface_stat* iface_stat, int num_radios,
+ wifi_radio_stat* radio_stat) {
+ if (on_link_layer_stats_result_internal_callback) {
+ on_link_layer_stats_result_internal_callback(id, iface_stat, num_radios, radio_stat);
+ }
+}
+
+// Callback to be invoked for rssi threshold breach.
+std::function<void((wifi_request_id, uint8_t*, int8_t))>
+ on_rssi_threshold_breached_internal_callback;
+void onAsyncRssiThresholdBreached(wifi_request_id id, uint8_t* bssid, int8_t rssi) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_rssi_threshold_breached_internal_callback) {
+ on_rssi_threshold_breached_internal_callback(id, bssid, rssi);
+ }
+}
+
+// Callback to be invoked for ring buffer data indication.
+std::function<void(char*, char*, int, wifi_ring_buffer_status*)>
+ on_ring_buffer_data_internal_callback;
+void onAsyncRingBufferData(char* ring_name, char* buffer, int buffer_size,
+ wifi_ring_buffer_status* status) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_ring_buffer_data_internal_callback) {
+ on_ring_buffer_data_internal_callback(ring_name, buffer, buffer_size, status);
+ }
+}
+
+// Callback to be invoked for error alert indication.
+std::function<void(wifi_request_id, char*, int, int)> on_error_alert_internal_callback;
+void onAsyncErrorAlert(wifi_request_id id, char* buffer, int buffer_size, int err_code) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_error_alert_internal_callback) {
+ on_error_alert_internal_callback(id, buffer, buffer_size, err_code);
+ }
+}
+
+// Callback to be invoked for radio mode change indication.
+std::function<void(wifi_request_id, uint32_t, wifi_mac_info*)>
+ on_radio_mode_change_internal_callback;
+void onAsyncRadioModeChange(wifi_request_id id, uint32_t num_macs, wifi_mac_info* mac_infos) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_radio_mode_change_internal_callback) {
+ on_radio_mode_change_internal_callback(id, num_macs, mac_infos);
+ }
+}
+
+// Callback to be invoked to report subsystem restart
+std::function<void(const char*)> on_subsystem_restart_internal_callback;
+void onAsyncSubsystemRestart(const char* error) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_subsystem_restart_internal_callback) {
+ on_subsystem_restart_internal_callback(error);
+ }
+}
+
+// Callback to be invoked for rtt results results.
+std::function<void(wifi_request_id, unsigned num_results, wifi_rtt_result* rtt_results[])>
+ on_rtt_results_internal_callback;
+void onAsyncRttResults(wifi_request_id id, unsigned num_results, wifi_rtt_result* rtt_results[]) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_rtt_results_internal_callback) {
+ on_rtt_results_internal_callback(id, num_results, rtt_results);
+ on_rtt_results_internal_callback = nullptr;
+ }
+}
+
+// Callbacks for the various NAN operations.
+// NOTE: These have very little conversions to perform before invoking the user
+// callbacks.
+// So, handle all of them here directly to avoid adding an unnecessary layer.
+std::function<void(transaction_id, const NanResponseMsg&)> on_nan_notify_response_user_callback;
+void onAsyncNanNotifyResponse(transaction_id id, NanResponseMsg* msg) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_notify_response_user_callback && msg) {
+ on_nan_notify_response_user_callback(id, *msg);
+ }
+}
+
+std::function<void(const NanPublishRepliedInd&)> on_nan_event_publish_replied_user_callback;
+void onAsyncNanEventPublishReplied(NanPublishRepliedInd* /* event */) {
+ LOG(ERROR) << "onAsyncNanEventPublishReplied triggered";
+}
+
+std::function<void(const NanPublishTerminatedInd&)> on_nan_event_publish_terminated_user_callback;
+void onAsyncNanEventPublishTerminated(NanPublishTerminatedInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_publish_terminated_user_callback && event) {
+ on_nan_event_publish_terminated_user_callback(*event);
+ }
+}
+
+std::function<void(const NanMatchInd&)> on_nan_event_match_user_callback;
+void onAsyncNanEventMatch(NanMatchInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_match_user_callback && event) {
+ on_nan_event_match_user_callback(*event);
+ }
+}
+
+std::function<void(const NanMatchExpiredInd&)> on_nan_event_match_expired_user_callback;
+void onAsyncNanEventMatchExpired(NanMatchExpiredInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_match_expired_user_callback && event) {
+ on_nan_event_match_expired_user_callback(*event);
+ }
+}
+
+std::function<void(const NanSubscribeTerminatedInd&)>
+ on_nan_event_subscribe_terminated_user_callback;
+void onAsyncNanEventSubscribeTerminated(NanSubscribeTerminatedInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_subscribe_terminated_user_callback && event) {
+ on_nan_event_subscribe_terminated_user_callback(*event);
+ }
+}
+
+std::function<void(const NanFollowupInd&)> on_nan_event_followup_user_callback;
+void onAsyncNanEventFollowup(NanFollowupInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_followup_user_callback && event) {
+ on_nan_event_followup_user_callback(*event);
+ }
+}
+
+std::function<void(const NanDiscEngEventInd&)> on_nan_event_disc_eng_event_user_callback;
+void onAsyncNanEventDiscEngEvent(NanDiscEngEventInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_disc_eng_event_user_callback && event) {
+ on_nan_event_disc_eng_event_user_callback(*event);
+ }
+}
+
+std::function<void(const NanDisabledInd&)> on_nan_event_disabled_user_callback;
+void onAsyncNanEventDisabled(NanDisabledInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_disabled_user_callback && event) {
+ on_nan_event_disabled_user_callback(*event);
+ }
+}
+
+std::function<void(const NanTCAInd&)> on_nan_event_tca_user_callback;
+void onAsyncNanEventTca(NanTCAInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_tca_user_callback && event) {
+ on_nan_event_tca_user_callback(*event);
+ }
+}
+
+std::function<void(const NanBeaconSdfPayloadInd&)> on_nan_event_beacon_sdf_payload_user_callback;
+void onAsyncNanEventBeaconSdfPayload(NanBeaconSdfPayloadInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_beacon_sdf_payload_user_callback && event) {
+ on_nan_event_beacon_sdf_payload_user_callback(*event);
+ }
+}
+
+std::function<void(const NanDataPathRequestInd&)> on_nan_event_data_path_request_user_callback;
+void onAsyncNanEventDataPathRequest(NanDataPathRequestInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_data_path_request_user_callback && event) {
+ on_nan_event_data_path_request_user_callback(*event);
+ }
+}
+std::function<void(const NanDataPathConfirmInd&)> on_nan_event_data_path_confirm_user_callback;
+void onAsyncNanEventDataPathConfirm(NanDataPathConfirmInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_data_path_confirm_user_callback && event) {
+ on_nan_event_data_path_confirm_user_callback(*event);
+ }
+}
+
+std::function<void(const NanDataPathEndInd&)> on_nan_event_data_path_end_user_callback;
+void onAsyncNanEventDataPathEnd(NanDataPathEndInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_data_path_end_user_callback && event) {
+ on_nan_event_data_path_end_user_callback(*event);
+ }
+}
+
+std::function<void(const NanTransmitFollowupInd&)> on_nan_event_transmit_follow_up_user_callback;
+void onAsyncNanEventTransmitFollowUp(NanTransmitFollowupInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_transmit_follow_up_user_callback && event) {
+ on_nan_event_transmit_follow_up_user_callback(*event);
+ }
+}
+
+std::function<void(const NanRangeRequestInd&)> on_nan_event_range_request_user_callback;
+void onAsyncNanEventRangeRequest(NanRangeRequestInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_range_request_user_callback && event) {
+ on_nan_event_range_request_user_callback(*event);
+ }
+}
+
+std::function<void(const NanRangeReportInd&)> on_nan_event_range_report_user_callback;
+void onAsyncNanEventRangeReport(NanRangeReportInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_range_report_user_callback && event) {
+ on_nan_event_range_report_user_callback(*event);
+ }
+}
+
+std::function<void(const NanDataPathScheduleUpdateInd&)> on_nan_event_schedule_update_user_callback;
+void onAsyncNanEventScheduleUpdate(NanDataPathScheduleUpdateInd* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_nan_event_schedule_update_user_callback && event) {
+ on_nan_event_schedule_update_user_callback(*event);
+ }
+}
+
+// Callbacks for the various TWT operations.
+std::function<void(const TwtSetupResponse&)> on_twt_event_setup_response_callback;
+void onAsyncTwtEventSetupResponse(TwtSetupResponse* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_event_setup_response_callback && event) {
+ on_twt_event_setup_response_callback(*event);
+ }
+}
+
+std::function<void(const TwtTeardownCompletion&)> on_twt_event_teardown_completion_callback;
+void onAsyncTwtEventTeardownCompletion(TwtTeardownCompletion* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_event_teardown_completion_callback && event) {
+ on_twt_event_teardown_completion_callback(*event);
+ }
+}
+
+std::function<void(const TwtInfoFrameReceived&)> on_twt_event_info_frame_received_callback;
+void onAsyncTwtEventInfoFrameReceived(TwtInfoFrameReceived* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_event_info_frame_received_callback && event) {
+ on_twt_event_info_frame_received_callback(*event);
+ }
+}
+
+std::function<void(const TwtDeviceNotify&)> on_twt_event_device_notify_callback;
+void onAsyncTwtEventDeviceNotify(TwtDeviceNotify* event) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_twt_event_device_notify_callback && event) {
+ on_twt_event_device_notify_callback(*event);
+ }
+}
+
+// Callback to report current CHRE NAN state
+std::function<void(chre_nan_rtt_state)> on_chre_nan_rtt_internal_callback;
+void onAsyncChreNanRttState(chre_nan_rtt_state state) {
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (on_chre_nan_rtt_internal_callback) {
+ on_chre_nan_rtt_internal_callback(state);
+ }
+}
+
+// Callback to report cached scan results
+std::function<void(wifi_cached_scan_report*)> on_cached_scan_results_internal_callback;
+void onSyncCachedScanResults(wifi_cached_scan_report* cache_report) {
+ if (on_cached_scan_results_internal_callback) {
+ on_cached_scan_results_internal_callback(cache_report);
+ }
+}
+
+// End of the free-standing "C" style callbacks.
+
+WifiLegacyHal::WifiLegacyHal(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const wifi_hal_fn& fn, bool is_primary)
+ : global_func_table_(fn),
+ global_handle_(nullptr),
+ awaiting_event_loop_termination_(false),
+ is_started_(false),
+ iface_tool_(iface_tool),
+ is_primary_(is_primary) {}
+
+wifi_error WifiLegacyHal::initialize() {
+ LOG(DEBUG) << "Initialize legacy HAL";
+ // this now does nothing, since HAL function table is provided
+ // to the constructor
+ return WIFI_SUCCESS;
+}
+
+wifi_error WifiLegacyHal::start() {
+ // Ensure that we're starting in a good state.
+ CHECK(global_func_table_.wifi_initialize && !global_handle_ && iface_name_to_handle_.empty() &&
+ !awaiting_event_loop_termination_);
+ if (is_started_) {
+ LOG(DEBUG) << "Legacy HAL already started";
+ return WIFI_SUCCESS;
+ }
+ LOG(DEBUG) << "Waiting for the driver ready";
+ wifi_error status = global_func_table_.wifi_wait_for_driver_ready();
+ if (status == WIFI_ERROR_TIMED_OUT || status == WIFI_ERROR_UNKNOWN) {
+ LOG(ERROR) << "Failed or timed out awaiting driver ready";
+ return status;
+ }
+
+ if (is_primary_) {
+ property_set(kDriverPropName, "ok");
+
+ if (!iface_tool_.lock()->SetWifiUpState(true)) {
+ LOG(ERROR) << "Failed to set WiFi interface up";
+ return WIFI_ERROR_UNKNOWN;
+ }
+ }
+
+ LOG(DEBUG) << "Starting legacy HAL";
+ status = global_func_table_.wifi_initialize(&global_handle_);
+ if (status != WIFI_SUCCESS || !global_handle_) {
+ LOG(ERROR) << "Failed to retrieve global handle";
+ return status;
+ }
+ std::thread(&WifiLegacyHal::runEventLoop, this).detach();
+ status = retrieveIfaceHandles();
+ if (status != WIFI_SUCCESS || iface_name_to_handle_.empty()) {
+ LOG(ERROR) << "Failed to retrieve wlan interface handle";
+ return status;
+ }
+ LOG(DEBUG) << "Legacy HAL start complete";
+ is_started_ = true;
+ return WIFI_SUCCESS;
+}
+
+wifi_error WifiLegacyHal::stop(
+ /* NONNULL */ std::unique_lock<std::recursive_mutex>* lock,
+ const std::function<void()>& on_stop_complete_user_callback) {
+ if (!is_started_) {
+ LOG(DEBUG) << "Legacy HAL already stopped";
+ on_stop_complete_user_callback();
+ return WIFI_SUCCESS;
+ }
+ LOG(DEBUG) << "Stopping legacy HAL";
+ on_stop_complete_internal_callback = [on_stop_complete_user_callback,
+ this](wifi_handle handle) {
+ CHECK_EQ(global_handle_, handle) << "Handle mismatch";
+ LOG(INFO) << "Legacy HAL stop complete callback received";
+ // Invalidate all the internal pointers now that the HAL is
+ // stopped.
+ invalidate();
+ if (is_primary_) iface_tool_.lock()->SetWifiUpState(false);
+ on_stop_complete_user_callback();
+ is_started_ = false;
+ };
+ awaiting_event_loop_termination_ = true;
+ global_func_table_.wifi_cleanup(global_handle_, onAsyncStopComplete);
+ const auto status =
+ stop_wait_cv_.wait_for(*lock, std::chrono::milliseconds(kMaxStopCompleteWaitMs),
+ [this] { return !awaiting_event_loop_termination_; });
+ if (!status) {
+ LOG(ERROR) << "Legacy HAL stop failed or timed out";
+ return WIFI_ERROR_UNKNOWN;
+ }
+ LOG(DEBUG) << "Legacy HAL stop complete";
+ return WIFI_SUCCESS;
+}
+
+bool WifiLegacyHal::isStarted() {
+ return is_started_;
+}
+
+wifi_error WifiLegacyHal::waitForDriverReady() {
+ return global_func_table_.wifi_wait_for_driver_ready();
+}
+
+std::pair<wifi_error, std::string> WifiLegacyHal::getDriverVersion(const std::string& iface_name) {
+ std::array<char, kMaxVersionStringLength> buffer;
+ buffer.fill(0);
+ wifi_error status = global_func_table_.wifi_get_driver_version(getIfaceHandle(iface_name),
+ buffer.data(), buffer.size());
+ return {status, buffer.data()};
+}
+
+std::pair<wifi_error, std::string> WifiLegacyHal::getFirmwareVersion(
+ const std::string& iface_name) {
+ std::array<char, kMaxVersionStringLength> buffer;
+ buffer.fill(0);
+ wifi_error status = global_func_table_.wifi_get_firmware_version(getIfaceHandle(iface_name),
+ buffer.data(), buffer.size());
+ return {status, buffer.data()};
+}
+
+std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestDriverMemoryDump(
+ const std::string& iface_name) {
+ std::vector<uint8_t> driver_dump;
+ on_driver_memory_dump_internal_callback = [&driver_dump](char* buffer, int buffer_size) {
+ driver_dump.insert(driver_dump.end(), reinterpret_cast<uint8_t*>(buffer),
+ reinterpret_cast<uint8_t*>(buffer) + buffer_size);
+ };
+ wifi_error status = global_func_table_.wifi_get_driver_memory_dump(getIfaceHandle(iface_name),
+ {onSyncDriverMemoryDump});
+ on_driver_memory_dump_internal_callback = nullptr;
+ return {status, std::move(driver_dump)};
+}
+
+std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::requestFirmwareMemoryDump(
+ const std::string& iface_name) {
+ std::vector<uint8_t> firmware_dump;
+ on_firmware_memory_dump_internal_callback = [&firmware_dump](char* buffer, int buffer_size) {
+ firmware_dump.insert(firmware_dump.end(), reinterpret_cast<uint8_t*>(buffer),
+ reinterpret_cast<uint8_t*>(buffer) + buffer_size);
+ };
+ wifi_error status = global_func_table_.wifi_get_firmware_memory_dump(
+ getIfaceHandle(iface_name), {onSyncFirmwareMemoryDump});
+ on_firmware_memory_dump_internal_callback = nullptr;
+ return {status, std::move(firmware_dump)};
+}
+
+std::pair<wifi_error, uint64_t> WifiLegacyHal::getSupportedFeatureSet(
+ const std::string& iface_name) {
+ feature_set set = 0, chip_set = 0;
+ wifi_error status = WIFI_SUCCESS;
+
+ static_assert(sizeof(set) == sizeof(uint64_t),
+ "Some feature_flags can not be represented in output");
+ wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
+
+ global_func_table_.wifi_get_chip_feature_set(
+ global_handle_, &chip_set); /* ignore error, chip_set will stay 0 */
+
+ if (iface_handle) {
+ status = global_func_table_.wifi_get_supported_feature_set(iface_handle, &set);
+ }
+ return {status, static_cast<uint64_t>(set | chip_set)};
+}
+
+std::pair<wifi_error, PacketFilterCapabilities> WifiLegacyHal::getPacketFilterCapabilities(
+ const std::string& iface_name) {
+ PacketFilterCapabilities caps;
+ wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
+ getIfaceHandle(iface_name), &caps.version, &caps.max_len);
+ return {status, caps};
+}
+
+wifi_error WifiLegacyHal::setPacketFilter(const std::string& iface_name,
+ const std::vector<uint8_t>& program) {
+ return global_func_table_.wifi_set_packet_filter(getIfaceHandle(iface_name), program.data(),
+ program.size());
+}
+
+std::pair<wifi_error, std::vector<uint8_t>> WifiLegacyHal::readApfPacketFilterData(
+ const std::string& iface_name) {
+ PacketFilterCapabilities caps;
+ wifi_error status = global_func_table_.wifi_get_packet_filter_capabilities(
+ getIfaceHandle(iface_name), &caps.version, &caps.max_len);
+ if (status != WIFI_SUCCESS) {
+ return {status, {}};
+ }
+
+ // Size the buffer to read the entire program & work memory.
+ std::vector<uint8_t> buffer(caps.max_len);
+
+ status = global_func_table_.wifi_read_packet_filter(
+ getIfaceHandle(iface_name), /*src_offset=*/0, buffer.data(), buffer.size());
+ return {status, std::move(buffer)};
+}
+
+std::pair<wifi_error, wifi_gscan_capabilities> WifiLegacyHal::getGscanCapabilities(
+ const std::string& iface_name) {
+ wifi_gscan_capabilities caps;
+ wifi_error status =
+ global_func_table_.wifi_get_gscan_capabilities(getIfaceHandle(iface_name), &caps);
+ return {status, caps};
+}
+
+wifi_error WifiLegacyHal::startGscan(
+ const std::string& iface_name, wifi_request_id id, const wifi_scan_cmd_params& params,
+ const std::function<void(wifi_request_id)>& on_failure_user_callback,
+ const on_gscan_results_callback& on_results_user_callback,
+ const on_gscan_full_result_callback& on_full_result_user_callback) {
+ // If there is already an ongoing background scan, reject new scan requests.
+ if (on_gscan_event_internal_callback || on_gscan_full_result_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ // This callback will be used to either trigger |on_results_user_callback|
+ // or |on_failure_user_callback|.
+ on_gscan_event_internal_callback = [iface_name, on_failure_user_callback,
+ on_results_user_callback,
+ this](wifi_request_id id, wifi_scan_event event) {
+ switch (event) {
+ case WIFI_SCAN_RESULTS_AVAILABLE:
+ case WIFI_SCAN_THRESHOLD_NUM_SCANS:
+ case WIFI_SCAN_THRESHOLD_PERCENT: {
+ wifi_error status;
+ std::vector<wifi_cached_scan_results> cached_scan_results;
+ std::tie(status, cached_scan_results) = getGscanCachedResults(iface_name);
+ if (status == WIFI_SUCCESS) {
+ on_results_user_callback(id, cached_scan_results);
+ return;
+ }
+ FALLTHROUGH_INTENDED;
+ }
+ // Fall through if failed. Failure to retrieve cached scan
+ // results should trigger a background scan failure.
+ case WIFI_SCAN_FAILED:
+ on_failure_user_callback(id);
+ on_gscan_event_internal_callback = nullptr;
+ on_gscan_full_result_internal_callback = nullptr;
+ return;
+ }
+ LOG(FATAL) << "Unexpected gscan event received: " << event;
+ };
+
+ on_gscan_full_result_internal_callback = [on_full_result_user_callback](
+ wifi_request_id id, wifi_scan_result* result,
+ uint32_t buckets_scanned) {
+ if (result) {
+ on_full_result_user_callback(id, result, buckets_scanned);
+ }
+ };
+
+ wifi_scan_result_handler handler = {onAsyncGscanFullResult, onAsyncGscanEvent};
+ wifi_error status =
+ global_func_table_.wifi_start_gscan(id, getIfaceHandle(iface_name), params, handler);
+ if (status != WIFI_SUCCESS) {
+ on_gscan_event_internal_callback = nullptr;
+ on_gscan_full_result_internal_callback = nullptr;
+ }
+ return status;
+}
+
+wifi_error WifiLegacyHal::stopGscan(const std::string& iface_name, wifi_request_id id) {
+ // If there is no an ongoing background scan, reject stop requests.
+ // TODO(b/32337212): This needs to be handled by the HIDL object because we
+ // need to return the NOT_STARTED error code.
+ if (!on_gscan_event_internal_callback && !on_gscan_full_result_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ wifi_error status = global_func_table_.wifi_stop_gscan(id, getIfaceHandle(iface_name));
+ // If the request Id is wrong, don't stop the ongoing background scan. Any
+ // other error should be treated as the end of background scan.
+ if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+ on_gscan_event_internal_callback = nullptr;
+ on_gscan_full_result_internal_callback = nullptr;
+ }
+ return status;
+}
+
+std::pair<wifi_error, std::vector<uint32_t>> WifiLegacyHal::getValidFrequenciesForBand(
+ const std::string& iface_name, wifi_band band) {
+ static_assert(sizeof(uint32_t) >= sizeof(wifi_channel),
+ "Wifi Channel cannot be represented in output");
+ std::vector<uint32_t> freqs;
+ freqs.resize(kMaxGscanFrequenciesForBand);
+ int32_t num_freqs = 0;
+ wifi_error status = global_func_table_.wifi_get_valid_channels(
+ getIfaceHandle(iface_name), band, freqs.size(),
+ reinterpret_cast<wifi_channel*>(freqs.data()), &num_freqs);
+ CHECK(num_freqs >= 0 && static_cast<uint32_t>(num_freqs) <= kMaxGscanFrequenciesForBand);
+ freqs.resize(num_freqs);
+ return {status, std::move(freqs)};
+}
+
+wifi_error WifiLegacyHal::setDfsFlag(const std::string& iface_name, bool dfs_on) {
+ return global_func_table_.wifi_set_nodfs_flag(getIfaceHandle(iface_name), dfs_on ? 0 : 1);
+}
+
+wifi_error WifiLegacyHal::enableLinkLayerStats(const std::string& iface_name, bool debug) {
+ wifi_link_layer_params params;
+ params.mpdu_size_threshold = kLinkLayerStatsDataMpduSizeThreshold;
+ params.aggressive_statistics_gathering = debug;
+ return global_func_table_.wifi_set_link_stats(getIfaceHandle(iface_name), params);
+}
+
+wifi_error WifiLegacyHal::disableLinkLayerStats(const std::string& iface_name) {
+ // TODO: Do we care about these responses?
+ uint32_t clear_mask_rsp;
+ uint8_t stop_rsp;
+ return global_func_table_.wifi_clear_link_stats(getIfaceHandle(iface_name), 0xFFFFFFFF,
+ &clear_mask_rsp, 1, &stop_rsp);
+}
+
+std::pair<wifi_error, LinkLayerStats> WifiLegacyHal::getLinkLayerStats(
+ const std::string& iface_name) {
+ LinkLayerStats link_stats{};
+ LinkLayerStats* link_stats_ptr = &link_stats;
+
+ on_link_layer_stats_result_internal_callback = [&link_stats_ptr](
+ wifi_request_id /* id */,
+ wifi_iface_stat* iface_stats_ptr,
+ int num_radios,
+ wifi_radio_stat* radio_stats_ptr) {
+ wifi_radio_stat* l_radio_stats_ptr;
+ wifi_peer_info* l_peer_info_stats_ptr;
+
+ if (iface_stats_ptr != nullptr) {
+ link_stats_ptr->iface = *iface_stats_ptr;
+ l_peer_info_stats_ptr = iface_stats_ptr->peer_info;
+ for (uint32_t i = 0; i < iface_stats_ptr->num_peers; i++) {
+ WifiPeerInfo peer;
+ peer.peer_info = *l_peer_info_stats_ptr;
+ if (l_peer_info_stats_ptr->num_rate > 0) {
+ /* Copy the rate stats */
+ peer.rate_stats.assign(
+ l_peer_info_stats_ptr->rate_stats,
+ l_peer_info_stats_ptr->rate_stats + l_peer_info_stats_ptr->num_rate);
+ }
+ peer.peer_info.num_rate = 0;
+ link_stats_ptr->peers.push_back(peer);
+ l_peer_info_stats_ptr =
+ (wifi_peer_info*)((u8*)l_peer_info_stats_ptr + sizeof(wifi_peer_info) +
+ (sizeof(wifi_rate_stat) *
+ l_peer_info_stats_ptr->num_rate));
+ }
+ link_stats_ptr->iface.num_peers = 0;
+ } else {
+ LOG(ERROR) << "Invalid iface stats in link layer stats";
+ }
+ if (num_radios <= 0 || radio_stats_ptr == nullptr) {
+ LOG(ERROR) << "Invalid radio stats in link layer stats";
+ return;
+ }
+ l_radio_stats_ptr = radio_stats_ptr;
+ for (int i = 0; i < num_radios; i++) {
+ LinkLayerRadioStats radio;
+
+ radio.stats = *l_radio_stats_ptr;
+ // Copy over the tx level array to the separate vector.
+ if (l_radio_stats_ptr->num_tx_levels > 0 &&
+ l_radio_stats_ptr->tx_time_per_levels != nullptr) {
+ radio.tx_time_per_levels.assign(
+ l_radio_stats_ptr->tx_time_per_levels,
+ l_radio_stats_ptr->tx_time_per_levels + l_radio_stats_ptr->num_tx_levels);
+ }
+ radio.stats.num_tx_levels = 0;
+ radio.stats.tx_time_per_levels = nullptr;
+ /* Copy over the channel stat to separate vector */
+ if (l_radio_stats_ptr->num_channels > 0) {
+ /* Copy the channel stats */
+ radio.channel_stats.assign(
+ l_radio_stats_ptr->channels,
+ l_radio_stats_ptr->channels + l_radio_stats_ptr->num_channels);
+ }
+ link_stats_ptr->radios.push_back(radio);
+ l_radio_stats_ptr =
+ (wifi_radio_stat*)((u8*)l_radio_stats_ptr + sizeof(wifi_radio_stat) +
+ (sizeof(wifi_channel_stat) *
+ l_radio_stats_ptr->num_channels));
+ }
+ };
+
+ wifi_error status = global_func_table_.wifi_get_link_stats(0, getIfaceHandle(iface_name),
+ {onSyncLinkLayerStatsResult});
+ on_link_layer_stats_result_internal_callback = nullptr;
+ return {status, link_stats};
+}
+
+wifi_error WifiLegacyHal::startRssiMonitoring(
+ const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi,
+ const on_rssi_threshold_breached_callback& on_threshold_breached_user_callback) {
+ if (on_rssi_threshold_breached_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ on_rssi_threshold_breached_internal_callback = [on_threshold_breached_user_callback](
+ wifi_request_id id, uint8_t* bssid_ptr,
+ int8_t rssi) {
+ if (!bssid_ptr) {
+ return;
+ }
+ std::array<uint8_t, ETH_ALEN> bssid_arr;
+ // |bssid_ptr| pointer is assumed to have 6 bytes for the mac
+ // address.
+ std::copy(bssid_ptr, bssid_ptr + 6, std::begin(bssid_arr));
+ on_threshold_breached_user_callback(id, bssid_arr, rssi);
+ };
+ wifi_error status = global_func_table_.wifi_start_rssi_monitoring(
+ id, getIfaceHandle(iface_name), max_rssi, min_rssi, {onAsyncRssiThresholdBreached});
+ if (status != WIFI_SUCCESS) {
+ on_rssi_threshold_breached_internal_callback = nullptr;
+ }
+ return status;
+}
+
+wifi_error WifiLegacyHal::stopRssiMonitoring(const std::string& iface_name, wifi_request_id id) {
+ if (!on_rssi_threshold_breached_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ wifi_error status =
+ global_func_table_.wifi_stop_rssi_monitoring(id, getIfaceHandle(iface_name));
+ // If the request Id is wrong, don't stop the ongoing rssi monitoring. Any
+ // other error should be treated as the end of background scan.
+ if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+ on_rssi_threshold_breached_internal_callback = nullptr;
+ }
+ return status;
+}
+
+std::pair<wifi_error, wifi_roaming_capabilities> WifiLegacyHal::getRoamingCapabilities(
+ const std::string& iface_name) {
+ wifi_roaming_capabilities caps;
+ wifi_error status =
+ global_func_table_.wifi_get_roaming_capabilities(getIfaceHandle(iface_name), &caps);
+ return {status, caps};
+}
+
+wifi_error WifiLegacyHal::configureRoaming(const std::string& iface_name,
+ const wifi_roaming_config& config) {
+ wifi_roaming_config config_internal = config;
+ return global_func_table_.wifi_configure_roaming(getIfaceHandle(iface_name), &config_internal);
+}
+
+wifi_error WifiLegacyHal::enableFirmwareRoaming(const std::string& iface_name,
+ fw_roaming_state_t state) {
+ return global_func_table_.wifi_enable_firmware_roaming(getIfaceHandle(iface_name), state);
+}
+
+wifi_error WifiLegacyHal::configureNdOffload(const std::string& iface_name, bool enable) {
+ return global_func_table_.wifi_configure_nd_offload(getIfaceHandle(iface_name), enable);
+}
+
+wifi_error WifiLegacyHal::startSendingOffloadedPacket(const std::string& iface_name, int32_t cmd_id,
+ uint16_t ether_type,
+ const std::vector<uint8_t>& ip_packet_data,
+ const std::array<uint8_t, 6>& src_address,
+ const std::array<uint8_t, 6>& dst_address,
+ int32_t period_in_ms) {
+ std::vector<uint8_t> ip_packet_data_internal(ip_packet_data);
+ std::vector<uint8_t> src_address_internal(src_address.data(),
+ src_address.data() + src_address.size());
+ std::vector<uint8_t> dst_address_internal(dst_address.data(),
+ dst_address.data() + dst_address.size());
+ return global_func_table_.wifi_start_sending_offloaded_packet(
+ cmd_id, getIfaceHandle(iface_name), ether_type, ip_packet_data_internal.data(),
+ ip_packet_data_internal.size(), src_address_internal.data(),
+ dst_address_internal.data(), period_in_ms);
+}
+
+wifi_error WifiLegacyHal::stopSendingOffloadedPacket(const std::string& iface_name,
+ uint32_t cmd_id) {
+ return global_func_table_.wifi_stop_sending_offloaded_packet(cmd_id,
+ getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::selectTxPowerScenario(const std::string& iface_name,
+ wifi_power_scenario scenario) {
+ return global_func_table_.wifi_select_tx_power_scenario(getIfaceHandle(iface_name), scenario);
+}
+
+wifi_error WifiLegacyHal::resetTxPowerScenario(const std::string& iface_name) {
+ return global_func_table_.wifi_reset_tx_power_scenario(getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::setLatencyMode(const std::string& iface_name, wifi_latency_mode mode) {
+ return global_func_table_.wifi_set_latency_mode(getIfaceHandle(iface_name), mode);
+}
+
+wifi_error WifiLegacyHal::setThermalMitigationMode(wifi_thermal_mode mode,
+ uint32_t completion_window) {
+ return global_func_table_.wifi_set_thermal_mitigation_mode(global_handle_, mode,
+ completion_window);
+}
+
+wifi_error WifiLegacyHal::setDscpToAccessCategoryMapping(uint32_t start, uint32_t end,
+ uint32_t access_category) {
+ return global_func_table_.wifi_map_dscp_access_category(global_handle_, start, end,
+ access_category);
+}
+
+wifi_error WifiLegacyHal::resetDscpToAccessCategoryMapping() {
+ return global_func_table_.wifi_reset_dscp_mapping(global_handle_);
+}
+
+std::pair<wifi_error, uint32_t> WifiLegacyHal::getLoggerSupportedFeatureSet(
+ const std::string& iface_name) {
+ uint32_t supported_feature_flags = 0;
+ wifi_error status = WIFI_SUCCESS;
+
+ wifi_interface_handle iface_handle = getIfaceHandle(iface_name);
+
+ if (iface_handle) {
+ status = global_func_table_.wifi_get_logger_supported_feature_set(iface_handle,
+ &supported_feature_flags);
+ }
+ return {status, supported_feature_flags};
+}
+
+wifi_error WifiLegacyHal::startPktFateMonitoring(const std::string& iface_name) {
+ return global_func_table_.wifi_start_pkt_fate_monitoring(getIfaceHandle(iface_name));
+}
+
+std::pair<wifi_error, std::vector<wifi_tx_report>> WifiLegacyHal::getTxPktFates(
+ const std::string& iface_name) {
+ std::vector<wifi_tx_report> tx_pkt_fates;
+ tx_pkt_fates.resize(MAX_FATE_LOG_LEN);
+ size_t num_fates = 0;
+ wifi_error status = global_func_table_.wifi_get_tx_pkt_fates(
+ getIfaceHandle(iface_name), tx_pkt_fates.data(), tx_pkt_fates.size(), &num_fates);
+ CHECK(num_fates <= MAX_FATE_LOG_LEN);
+ tx_pkt_fates.resize(num_fates);
+ return {status, std::move(tx_pkt_fates)};
+}
+
+std::pair<wifi_error, std::vector<wifi_rx_report>> WifiLegacyHal::getRxPktFates(
+ const std::string& iface_name) {
+ std::vector<wifi_rx_report> rx_pkt_fates;
+ rx_pkt_fates.resize(MAX_FATE_LOG_LEN);
+ size_t num_fates = 0;
+ wifi_error status = global_func_table_.wifi_get_rx_pkt_fates(
+ getIfaceHandle(iface_name), rx_pkt_fates.data(), rx_pkt_fates.size(), &num_fates);
+ CHECK(num_fates <= MAX_FATE_LOG_LEN);
+ rx_pkt_fates.resize(num_fates);
+ return {status, std::move(rx_pkt_fates)};
+}
+
+std::pair<wifi_error, WakeReasonStats> WifiLegacyHal::getWakeReasonStats(
+ const std::string& iface_name) {
+ WakeReasonStats stats;
+ stats.cmd_event_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
+ stats.driver_fw_local_wake_cnt.resize(kMaxWakeReasonStatsArraySize);
+
+ // This legacy struct needs separate memory to store the variable sized wake
+ // reason types.
+ stats.wake_reason_cnt.cmd_event_wake_cnt =
+ reinterpret_cast<int32_t*>(stats.cmd_event_wake_cnt.data());
+ stats.wake_reason_cnt.cmd_event_wake_cnt_sz = stats.cmd_event_wake_cnt.size();
+ stats.wake_reason_cnt.cmd_event_wake_cnt_used = 0;
+ stats.wake_reason_cnt.driver_fw_local_wake_cnt =
+ reinterpret_cast<int32_t*>(stats.driver_fw_local_wake_cnt.data());
+ stats.wake_reason_cnt.driver_fw_local_wake_cnt_sz = stats.driver_fw_local_wake_cnt.size();
+ stats.wake_reason_cnt.driver_fw_local_wake_cnt_used = 0;
+
+ wifi_error status = global_func_table_.wifi_get_wake_reason_stats(getIfaceHandle(iface_name),
+ &stats.wake_reason_cnt);
+
+ CHECK(stats.wake_reason_cnt.cmd_event_wake_cnt_used >= 0 &&
+ static_cast<uint32_t>(stats.wake_reason_cnt.cmd_event_wake_cnt_used) <=
+ kMaxWakeReasonStatsArraySize);
+ stats.cmd_event_wake_cnt.resize(stats.wake_reason_cnt.cmd_event_wake_cnt_used);
+ stats.wake_reason_cnt.cmd_event_wake_cnt = nullptr;
+
+ CHECK(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used >= 0 &&
+ static_cast<uint32_t>(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used) <=
+ kMaxWakeReasonStatsArraySize);
+ stats.driver_fw_local_wake_cnt.resize(stats.wake_reason_cnt.driver_fw_local_wake_cnt_used);
+ stats.wake_reason_cnt.driver_fw_local_wake_cnt = nullptr;
+
+ return {status, stats};
+}
+
+wifi_error WifiLegacyHal::registerRingBufferCallbackHandler(
+ const std::string& iface_name, const on_ring_buffer_data_callback& on_user_data_callback) {
+ if (on_ring_buffer_data_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ on_ring_buffer_data_internal_callback = [on_user_data_callback](
+ char* ring_name, char* buffer, int buffer_size,
+ wifi_ring_buffer_status* status) {
+ if (status && buffer) {
+ std::vector<uint8_t> buffer_vector(reinterpret_cast<uint8_t*>(buffer),
+ reinterpret_cast<uint8_t*>(buffer) + buffer_size);
+ on_user_data_callback(ring_name, buffer_vector, *status);
+ }
+ };
+ wifi_error status = global_func_table_.wifi_set_log_handler(0, getIfaceHandle(iface_name),
+ {onAsyncRingBufferData});
+ if (status != WIFI_SUCCESS) {
+ on_ring_buffer_data_internal_callback = nullptr;
+ }
+ return status;
+}
+
+wifi_error WifiLegacyHal::deregisterRingBufferCallbackHandler(const std::string& iface_name) {
+ if (!on_ring_buffer_data_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ on_ring_buffer_data_internal_callback = nullptr;
+ return global_func_table_.wifi_reset_log_handler(0, getIfaceHandle(iface_name));
+}
+
+std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> WifiLegacyHal::getRingBuffersStatus(
+ const std::string& iface_name) {
+ std::vector<wifi_ring_buffer_status> ring_buffers_status;
+ ring_buffers_status.resize(kMaxRingBuffers);
+ uint32_t num_rings = kMaxRingBuffers;
+ wifi_error status = global_func_table_.wifi_get_ring_buffers_status(
+ getIfaceHandle(iface_name), &num_rings, ring_buffers_status.data());
+ CHECK(num_rings <= kMaxRingBuffers);
+ ring_buffers_status.resize(num_rings);
+ return {status, std::move(ring_buffers_status)};
+}
+
+wifi_error WifiLegacyHal::startRingBufferLogging(const std::string& iface_name,
+ const std::string& ring_name,
+ uint32_t verbose_level, uint32_t max_interval_sec,
+ uint32_t min_data_size) {
+ return global_func_table_.wifi_start_logging(getIfaceHandle(iface_name), verbose_level, 0,
+ max_interval_sec, min_data_size,
+ makeCharVec(ring_name).data());
+}
+
+wifi_error WifiLegacyHal::getRingBufferData(const std::string& iface_name,
+ const std::string& ring_name) {
+ return global_func_table_.wifi_get_ring_data(getIfaceHandle(iface_name),
+ makeCharVec(ring_name).data());
+}
+
+wifi_error WifiLegacyHal::registerErrorAlertCallbackHandler(
+ const std::string& iface_name, const on_error_alert_callback& on_user_alert_callback) {
+ if (on_error_alert_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ on_error_alert_internal_callback = [on_user_alert_callback](wifi_request_id id, char* buffer,
+ int buffer_size, int err_code) {
+ if (buffer) {
+ CHECK(id == 0);
+ on_user_alert_callback(
+ err_code,
+ std::vector<uint8_t>(reinterpret_cast<uint8_t*>(buffer),
+ reinterpret_cast<uint8_t*>(buffer) + buffer_size));
+ }
+ };
+ wifi_error status = global_func_table_.wifi_set_alert_handler(0, getIfaceHandle(iface_name),
+ {onAsyncErrorAlert});
+ if (status != WIFI_SUCCESS) {
+ on_error_alert_internal_callback = nullptr;
+ }
+ return status;
+}
+
+wifi_error WifiLegacyHal::deregisterErrorAlertCallbackHandler(const std::string& iface_name) {
+ if (!on_error_alert_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ on_error_alert_internal_callback = nullptr;
+ return global_func_table_.wifi_reset_alert_handler(0, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::registerRadioModeChangeCallbackHandler(
+ const std::string& iface_name,
+ const on_radio_mode_change_callback& on_user_change_callback) {
+ if (on_radio_mode_change_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ on_radio_mode_change_internal_callback = [on_user_change_callback](
+ wifi_request_id /* id */, uint32_t num_macs,
+ wifi_mac_info* mac_infos_arr) {
+ if (num_macs > 0 && mac_infos_arr) {
+ std::vector<WifiMacInfo> mac_infos_vec;
+ for (uint32_t i = 0; i < num_macs; i++) {
+ WifiMacInfo mac_info;
+ mac_info.wlan_mac_id = mac_infos_arr[i].wlan_mac_id;
+ mac_info.mac_band = mac_infos_arr[i].mac_band;
+ for (int32_t j = 0; j < mac_infos_arr[i].num_iface; j++) {
+ WifiIfaceInfo iface_info;
+ iface_info.name = mac_infos_arr[i].iface_info[j].iface_name;
+ iface_info.channel = mac_infos_arr[i].iface_info[j].channel;
+ mac_info.iface_infos.push_back(iface_info);
+ }
+ mac_infos_vec.push_back(mac_info);
+ }
+ on_user_change_callback(mac_infos_vec);
+ }
+ };
+ wifi_error status = global_func_table_.wifi_set_radio_mode_change_handler(
+ 0, getIfaceHandle(iface_name), {onAsyncRadioModeChange});
+ if (status != WIFI_SUCCESS) {
+ on_radio_mode_change_internal_callback = nullptr;
+ }
+ return status;
+}
+
+wifi_error WifiLegacyHal::registerSubsystemRestartCallbackHandler(
+ const on_subsystem_restart_callback& on_restart_callback) {
+ if (on_subsystem_restart_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ on_subsystem_restart_internal_callback = [on_restart_callback](const char* error) {
+ on_restart_callback(error);
+ };
+ wifi_error status = global_func_table_.wifi_set_subsystem_restart_handler(
+ global_handle_, {onAsyncSubsystemRestart});
+ if (status != WIFI_SUCCESS) {
+ on_subsystem_restart_internal_callback = nullptr;
+ }
+ return status;
+}
+
+wifi_error WifiLegacyHal::startRttRangeRequest(
+ const std::string& iface_name, wifi_request_id id,
+ const std::vector<wifi_rtt_config>& rtt_configs,
+ const on_rtt_results_callback& on_results_user_callback) {
+ if (on_rtt_results_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ on_rtt_results_internal_callback = [on_results_user_callback](wifi_request_id id,
+ unsigned num_results,
+ wifi_rtt_result* rtt_results[]) {
+ if (num_results > 0 && !rtt_results) {
+ LOG(ERROR) << "Unexpected nullptr in RTT results";
+ return;
+ }
+ std::vector<const wifi_rtt_result*> rtt_results_vec;
+ std::copy_if(rtt_results, rtt_results + num_results, back_inserter(rtt_results_vec),
+ [](wifi_rtt_result* rtt_result) { return rtt_result != nullptr; });
+ on_results_user_callback(id, rtt_results_vec);
+ };
+
+ std::vector<wifi_rtt_config> rtt_configs_internal(rtt_configs);
+ wifi_error status = global_func_table_.wifi_rtt_range_request(
+ id, getIfaceHandle(iface_name), rtt_configs.size(), rtt_configs_internal.data(),
+ {onAsyncRttResults});
+ if (status != WIFI_SUCCESS) {
+ on_rtt_results_internal_callback = nullptr;
+ }
+ return status;
+}
+
+wifi_error WifiLegacyHal::cancelRttRangeRequest(
+ const std::string& iface_name, wifi_request_id id,
+ const std::vector<std::array<uint8_t, ETH_ALEN>>& mac_addrs) {
+ if (!on_rtt_results_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+ static_assert(sizeof(mac_addr) == sizeof(std::array<uint8_t, ETH_ALEN>),
+ "MAC address size mismatch");
+ // TODO: How do we handle partial cancels (i.e only a subset of enabled mac
+ // addressed are cancelled).
+ std::vector<std::array<uint8_t, ETH_ALEN>> mac_addrs_internal(mac_addrs);
+ wifi_error status = global_func_table_.wifi_rtt_range_cancel(
+ id, getIfaceHandle(iface_name), mac_addrs.size(),
+ reinterpret_cast<mac_addr*>(mac_addrs_internal.data()));
+ // If the request Id is wrong, don't stop the ongoing range request. Any
+ // other error should be treated as the end of rtt ranging.
+ if (status != WIFI_ERROR_INVALID_REQUEST_ID) {
+ on_rtt_results_internal_callback = nullptr;
+ }
+ return status;
+}
+
+std::pair<wifi_error, wifi_rtt_capabilities> WifiLegacyHal::getRttCapabilities(
+ const std::string& iface_name) {
+ wifi_rtt_capabilities rtt_caps;
+ wifi_error status =
+ global_func_table_.wifi_get_rtt_capabilities(getIfaceHandle(iface_name), &rtt_caps);
+ return {status, rtt_caps};
+}
+
+std::pair<wifi_error, wifi_rtt_responder> WifiLegacyHal::getRttResponderInfo(
+ const std::string& iface_name) {
+ wifi_rtt_responder rtt_responder;
+ wifi_error status = global_func_table_.wifi_rtt_get_responder_info(getIfaceHandle(iface_name),
+ &rtt_responder);
+ return {status, rtt_responder};
+}
+
+wifi_error WifiLegacyHal::enableRttResponder(const std::string& iface_name, wifi_request_id id,
+ const wifi_channel_info& channel_hint,
+ uint32_t max_duration_secs,
+ const wifi_rtt_responder& info) {
+ wifi_rtt_responder info_internal(info);
+ return global_func_table_.wifi_enable_responder(id, getIfaceHandle(iface_name), channel_hint,
+ max_duration_secs, &info_internal);
+}
+
+wifi_error WifiLegacyHal::disableRttResponder(const std::string& iface_name, wifi_request_id id) {
+ return global_func_table_.wifi_disable_responder(id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::setRttLci(const std::string& iface_name, wifi_request_id id,
+ const wifi_lci_information& info) {
+ wifi_lci_information info_internal(info);
+ return global_func_table_.wifi_set_lci(id, getIfaceHandle(iface_name), &info_internal);
+}
+
+wifi_error WifiLegacyHal::setRttLcr(const std::string& iface_name, wifi_request_id id,
+ const wifi_lcr_information& info) {
+ wifi_lcr_information info_internal(info);
+ return global_func_table_.wifi_set_lcr(id, getIfaceHandle(iface_name), &info_internal);
+}
+
+wifi_error WifiLegacyHal::nanRegisterCallbackHandlers(const std::string& iface_name,
+ const NanCallbackHandlers& user_callbacks) {
+ on_nan_notify_response_user_callback = user_callbacks.on_notify_response;
+ on_nan_event_publish_terminated_user_callback = user_callbacks.on_event_publish_terminated;
+ on_nan_event_match_user_callback = user_callbacks.on_event_match;
+ on_nan_event_match_expired_user_callback = user_callbacks.on_event_match_expired;
+ on_nan_event_subscribe_terminated_user_callback = user_callbacks.on_event_subscribe_terminated;
+ on_nan_event_followup_user_callback = user_callbacks.on_event_followup;
+ on_nan_event_disc_eng_event_user_callback = user_callbacks.on_event_disc_eng_event;
+ on_nan_event_disabled_user_callback = user_callbacks.on_event_disabled;
+ on_nan_event_tca_user_callback = user_callbacks.on_event_tca;
+ on_nan_event_beacon_sdf_payload_user_callback = user_callbacks.on_event_beacon_sdf_payload;
+ on_nan_event_data_path_request_user_callback = user_callbacks.on_event_data_path_request;
+ on_nan_event_data_path_confirm_user_callback = user_callbacks.on_event_data_path_confirm;
+ on_nan_event_data_path_end_user_callback = user_callbacks.on_event_data_path_end;
+ on_nan_event_transmit_follow_up_user_callback = user_callbacks.on_event_transmit_follow_up;
+ on_nan_event_range_request_user_callback = user_callbacks.on_event_range_request;
+ on_nan_event_range_report_user_callback = user_callbacks.on_event_range_report;
+ on_nan_event_schedule_update_user_callback = user_callbacks.on_event_schedule_update;
+
+ return global_func_table_.wifi_nan_register_handler(
+ getIfaceHandle(iface_name),
+ {onAsyncNanNotifyResponse, onAsyncNanEventPublishReplied,
+ onAsyncNanEventPublishTerminated, onAsyncNanEventMatch, onAsyncNanEventMatchExpired,
+ onAsyncNanEventSubscribeTerminated, onAsyncNanEventFollowup,
+ onAsyncNanEventDiscEngEvent, onAsyncNanEventDisabled, onAsyncNanEventTca,
+ onAsyncNanEventBeaconSdfPayload, onAsyncNanEventDataPathRequest,
+ onAsyncNanEventDataPathConfirm, onAsyncNanEventDataPathEnd,
+ onAsyncNanEventTransmitFollowUp, onAsyncNanEventRangeRequest,
+ onAsyncNanEventRangeReport, onAsyncNanEventScheduleUpdate});
+}
+
+wifi_error WifiLegacyHal::nanEnableRequest(const std::string& iface_name, transaction_id id,
+ const NanEnableRequest& msg) {
+ NanEnableRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_enable_request(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanDisableRequest(const std::string& iface_name, transaction_id id) {
+ return global_func_table_.wifi_nan_disable_request(id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::nanPublishRequest(const std::string& iface_name, transaction_id id,
+ const NanPublishRequest& msg) {
+ NanPublishRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_publish_request(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanPublishCancelRequest(const std::string& iface_name, transaction_id id,
+ const NanPublishCancelRequest& msg) {
+ NanPublishCancelRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_publish_cancel_request(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanSubscribeRequest(const std::string& iface_name, transaction_id id,
+ const NanSubscribeRequest& msg) {
+ NanSubscribeRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_subscribe_request(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanSubscribeCancelRequest(const std::string& iface_name,
+ transaction_id id,
+ const NanSubscribeCancelRequest& msg) {
+ NanSubscribeCancelRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_subscribe_cancel_request(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanTransmitFollowupRequest(const std::string& iface_name,
+ transaction_id id,
+ const NanTransmitFollowupRequest& msg) {
+ NanTransmitFollowupRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_transmit_followup_request(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanStatsRequest(const std::string& iface_name, transaction_id id,
+ const NanStatsRequest& msg) {
+ NanStatsRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_stats_request(id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanConfigRequest(const std::string& iface_name, transaction_id id,
+ const NanConfigRequest& msg) {
+ NanConfigRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_config_request(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanTcaRequest(const std::string& iface_name, transaction_id id,
+ const NanTCARequest& msg) {
+ NanTCARequest msg_internal(msg);
+ return global_func_table_.wifi_nan_tca_request(id, getIfaceHandle(iface_name), &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanBeaconSdfPayloadRequest(const std::string& iface_name,
+ transaction_id id,
+ const NanBeaconSdfPayloadRequest& msg) {
+ NanBeaconSdfPayloadRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_beacon_sdf_payload_request(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+std::pair<wifi_error, NanVersion> WifiLegacyHal::nanGetVersion() {
+ NanVersion version;
+ wifi_error status = global_func_table_.wifi_nan_get_version(global_handle_, &version);
+ return {status, version};
+}
+
+wifi_error WifiLegacyHal::nanGetCapabilities(const std::string& iface_name, transaction_id id) {
+ return global_func_table_.wifi_nan_get_capabilities(id, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::nanDataInterfaceCreate(const std::string& iface_name, transaction_id id,
+ const std::string& data_iface_name) {
+ return global_func_table_.wifi_nan_data_interface_create(id, getIfaceHandle(iface_name),
+ makeCharVec(data_iface_name).data());
+}
+
+wifi_error WifiLegacyHal::nanDataInterfaceDelete(const std::string& iface_name, transaction_id id,
+ const std::string& data_iface_name) {
+ return global_func_table_.wifi_nan_data_interface_delete(id, getIfaceHandle(iface_name),
+ makeCharVec(data_iface_name).data());
+}
+
+wifi_error WifiLegacyHal::nanDataRequestInitiator(const std::string& iface_name, transaction_id id,
+ const NanDataPathInitiatorRequest& msg) {
+ NanDataPathInitiatorRequest msg_internal(msg);
+ return global_func_table_.wifi_nan_data_request_initiator(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+wifi_error WifiLegacyHal::nanDataIndicationResponse(const std::string& iface_name,
+ transaction_id id,
+ const NanDataPathIndicationResponse& msg) {
+ NanDataPathIndicationResponse msg_internal(msg);
+ return global_func_table_.wifi_nan_data_indication_response(id, getIfaceHandle(iface_name),
+ &msg_internal);
+}
+
+typedef struct {
+ u8 num_ndp_instances;
+ NanDataPathId ndp_instance_id;
+} NanDataPathEndSingleNdpIdRequest;
+
+wifi_error WifiLegacyHal::nanDataEnd(const std::string& iface_name, transaction_id id,
+ uint32_t ndpInstanceId) {
+ NanDataPathEndSingleNdpIdRequest msg;
+ msg.num_ndp_instances = 1;
+ msg.ndp_instance_id = ndpInstanceId;
+ wifi_error status = global_func_table_.wifi_nan_data_end(id, getIfaceHandle(iface_name),
+ (NanDataPathEndRequest*)&msg);
+ return status;
+}
+
+wifi_error WifiLegacyHal::setCountryCode(const std::string& iface_name,
+ const std::array<uint8_t, 2> code) {
+ std::string code_str(code.data(), code.data() + code.size());
+ return global_func_table_.wifi_set_country_code(getIfaceHandle(iface_name), code_str.c_str());
+}
+
+wifi_error WifiLegacyHal::retrieveIfaceHandles() {
+ wifi_interface_handle* iface_handles = nullptr;
+ int num_iface_handles = 0;
+ wifi_error status =
+ global_func_table_.wifi_get_ifaces(global_handle_, &num_iface_handles, &iface_handles);
+ if (status != WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to enumerate interface handles";
+ return status;
+ }
+ iface_name_to_handle_.clear();
+ for (int i = 0; i < num_iface_handles; ++i) {
+ std::array<char, IFNAMSIZ> iface_name_arr = {};
+ status = global_func_table_.wifi_get_iface_name(iface_handles[i], iface_name_arr.data(),
+ iface_name_arr.size());
+ if (status != WIFI_SUCCESS) {
+ LOG(WARNING) << "Failed to get interface handle name";
+ continue;
+ }
+ // Assuming the interface name is null terminated since the legacy HAL
+ // API does not return a size.
+ std::string iface_name(iface_name_arr.data());
+ LOG(INFO) << "Adding interface handle for " << iface_name;
+ iface_name_to_handle_[iface_name] = iface_handles[i];
+ }
+ return WIFI_SUCCESS;
+}
+
+wifi_interface_handle WifiLegacyHal::getIfaceHandle(const std::string& iface_name) {
+ const auto iface_handle_iter = iface_name_to_handle_.find(iface_name);
+ if (iface_handle_iter == iface_name_to_handle_.end()) {
+ LOG(ERROR) << "Unknown iface name: " << iface_name;
+ return nullptr;
+ }
+ return iface_handle_iter->second;
+}
+
+void WifiLegacyHal::runEventLoop() {
+ LOG(DEBUG) << "Starting legacy HAL event loop";
+ global_func_table_.wifi_event_loop(global_handle_);
+ const auto lock = aidl_sync_util::acquireGlobalLock();
+ if (!awaiting_event_loop_termination_) {
+ LOG(FATAL) << "Legacy HAL event loop terminated, but HAL was not stopping";
+ }
+ LOG(DEBUG) << "Legacy HAL event loop terminated";
+ awaiting_event_loop_termination_ = false;
+ stop_wait_cv_.notify_one();
+}
+
+std::pair<wifi_error, std::vector<wifi_cached_scan_results>> WifiLegacyHal::getGscanCachedResults(
+ const std::string& iface_name) {
+ std::vector<wifi_cached_scan_results> cached_scan_results;
+ cached_scan_results.resize(kMaxCachedGscanResults);
+ int32_t num_results = 0;
+ wifi_error status = global_func_table_.wifi_get_cached_gscan_results(
+ getIfaceHandle(iface_name), true /* always flush */, cached_scan_results.size(),
+ cached_scan_results.data(), &num_results);
+ CHECK(num_results >= 0 && static_cast<uint32_t>(num_results) <= kMaxCachedGscanResults);
+ cached_scan_results.resize(num_results);
+ // Check for invalid IE lengths in these cached scan results and correct it.
+ for (auto& cached_scan_result : cached_scan_results) {
+ int num_scan_results = cached_scan_result.num_results;
+ for (int i = 0; i < num_scan_results; i++) {
+ auto& scan_result = cached_scan_result.results[i];
+ if (scan_result.ie_length > 0) {
+ LOG(DEBUG) << "Cached scan result has non-zero IE length " << scan_result.ie_length;
+ scan_result.ie_length = 0;
+ }
+ }
+ }
+ return {status, std::move(cached_scan_results)};
+}
+
+wifi_error WifiLegacyHal::createVirtualInterface(const std::string& ifname,
+ wifi_interface_type iftype) {
+ // Create the interface if it doesn't exist. If interface already exist,
+ // Vendor Hal should return WIFI_SUCCESS.
+ wifi_error status = global_func_table_.wifi_virtual_interface_create(global_handle_,
+ ifname.c_str(), iftype);
+ return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
+}
+
+wifi_error WifiLegacyHal::deleteVirtualInterface(const std::string& ifname) {
+ // Delete the interface if it was created dynamically.
+ wifi_error status =
+ global_func_table_.wifi_virtual_interface_delete(global_handle_, ifname.c_str());
+ return handleVirtualInterfaceCreateOrDeleteStatus(ifname, status);
+}
+
+wifi_error WifiLegacyHal::handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname,
+ wifi_error status) {
+ if (status == WIFI_SUCCESS) {
+ // refresh list of handlers now.
+ status = retrieveIfaceHandles();
+ } else if (status == WIFI_ERROR_NOT_SUPPORTED) {
+ // Vendor hal does not implement this API. Such vendor implementations
+ // are expected to create / delete interface by other means.
+
+ // check if interface exists.
+ if (if_nametoindex(ifname.c_str())) {
+ status = retrieveIfaceHandles();
+ }
+ }
+ return status;
+}
+
+wifi_error WifiLegacyHal::getSupportedIfaceName(uint32_t iface_type, std::string& ifname) {
+ std::array<char, IFNAMSIZ> buffer;
+
+ wifi_error res = global_func_table_.wifi_get_supported_iface_name(
+ global_handle_, (uint32_t)iface_type, buffer.data(), buffer.size());
+ if (res == WIFI_SUCCESS) ifname = buffer.data();
+
+ return res;
+}
+
+wifi_error WifiLegacyHal::multiStaSetPrimaryConnection(const std::string& ifname) {
+ return global_func_table_.wifi_multi_sta_set_primary_connection(global_handle_,
+ getIfaceHandle(ifname));
+}
+
+wifi_error WifiLegacyHal::multiStaSetUseCase(wifi_multi_sta_use_case use_case) {
+ return global_func_table_.wifi_multi_sta_set_use_case(global_handle_, use_case);
+}
+
+wifi_error WifiLegacyHal::setCoexUnsafeChannels(
+ std::vector<wifi_coex_unsafe_channel> unsafe_channels, uint32_t restrictions) {
+ return global_func_table_.wifi_set_coex_unsafe_channels(global_handle_, unsafe_channels.size(),
+ unsafe_channels.data(), restrictions);
+}
+
+wifi_error WifiLegacyHal::setVoipMode(const std::string& iface_name, wifi_voip_mode mode) {
+ return global_func_table_.wifi_set_voip_mode(getIfaceHandle(iface_name), mode);
+}
+
+wifi_error WifiLegacyHal::twtRegisterHandler(const std::string& iface_name,
+ const TwtCallbackHandlers& user_callbacks) {
+ on_twt_event_setup_response_callback = user_callbacks.on_setup_response;
+ on_twt_event_teardown_completion_callback = user_callbacks.on_teardown_completion;
+ on_twt_event_info_frame_received_callback = user_callbacks.on_info_frame_received;
+ on_twt_event_device_notify_callback = user_callbacks.on_device_notify;
+
+ return global_func_table_.wifi_twt_register_handler(
+ getIfaceHandle(iface_name),
+ {onAsyncTwtEventSetupResponse, onAsyncTwtEventTeardownCompletion,
+ onAsyncTwtEventInfoFrameReceived, onAsyncTwtEventDeviceNotify});
+}
+
+std::pair<wifi_error, TwtCapabilitySet> WifiLegacyHal::twtGetCapability(
+ const std::string& iface_name) {
+ TwtCapabilitySet capSet;
+ wifi_error status =
+ global_func_table_.wifi_twt_get_capability(getIfaceHandle(iface_name), &capSet);
+ return {status, capSet};
+}
+
+wifi_error WifiLegacyHal::twtSetupRequest(const std::string& iface_name,
+ const TwtSetupRequest& msg) {
+ TwtSetupRequest msgInternal(msg);
+ return global_func_table_.wifi_twt_setup_request(getIfaceHandle(iface_name), &msgInternal);
+}
+
+wifi_error WifiLegacyHal::twtTearDownRequest(const std::string& iface_name,
+ const TwtTeardownRequest& msg) {
+ TwtTeardownRequest msgInternal(msg);
+ return global_func_table_.wifi_twt_teardown_request(getIfaceHandle(iface_name), &msgInternal);
+}
+
+wifi_error WifiLegacyHal::twtInfoFrameRequest(const std::string& iface_name,
+ const TwtInfoFrameRequest& msg) {
+ TwtInfoFrameRequest msgInternal(msg);
+ return global_func_table_.wifi_twt_info_frame_request(getIfaceHandle(iface_name), &msgInternal);
+}
+
+std::pair<wifi_error, TwtStats> WifiLegacyHal::twtGetStats(const std::string& iface_name,
+ uint8_t configId) {
+ TwtStats stats;
+ wifi_error status =
+ global_func_table_.wifi_twt_get_stats(getIfaceHandle(iface_name), configId, &stats);
+ return {status, stats};
+}
+
+wifi_error WifiLegacyHal::twtClearStats(const std::string& iface_name, uint8_t configId) {
+ return global_func_table_.wifi_twt_clear_stats(getIfaceHandle(iface_name), configId);
+}
+
+wifi_error WifiLegacyHal::setDtimConfig(const std::string& iface_name, uint32_t multiplier) {
+ return global_func_table_.wifi_set_dtim_config(getIfaceHandle(iface_name), multiplier);
+}
+
+std::pair<wifi_error, std::vector<wifi_usable_channel>> WifiLegacyHal::getUsableChannels(
+ uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask) {
+ std::vector<wifi_usable_channel> channels;
+ channels.resize(kMaxWifiUsableChannels);
+ uint32_t size = 0;
+ wifi_error status = global_func_table_.wifi_get_usable_channels(
+ global_handle_, band_mask, iface_mode_mask, filter_mask, channels.size(), &size,
+ reinterpret_cast<wifi_usable_channel*>(channels.data()));
+ CHECK(size >= 0 && size <= kMaxWifiUsableChannels);
+ channels.resize(size);
+ return {status, std::move(channels)};
+}
+
+wifi_error WifiLegacyHal::triggerSubsystemRestart() {
+ return global_func_table_.wifi_trigger_subsystem_restart(global_handle_);
+}
+
+wifi_error WifiLegacyHal::setIndoorState(bool isIndoor) {
+ return global_func_table_.wifi_set_indoor_state(global_handle_, isIndoor);
+}
+
+std::pair<wifi_error, wifi_radio_combination_matrix*>
+WifiLegacyHal::getSupportedRadioCombinationsMatrix() {
+ char* buffer = new char[kMaxSupportedRadioCombinationsMatrixLength];
+ std::fill(buffer, buffer + kMaxSupportedRadioCombinationsMatrixLength, 0);
+ uint32_t size = 0;
+ wifi_radio_combination_matrix* radio_combination_matrix_ptr =
+ reinterpret_cast<wifi_radio_combination_matrix*>(buffer);
+ wifi_error status = global_func_table_.wifi_get_supported_radio_combinations_matrix(
+ global_handle_, kMaxSupportedRadioCombinationsMatrixLength, &size,
+ radio_combination_matrix_ptr);
+ CHECK(size >= 0 && size <= kMaxSupportedRadioCombinationsMatrixLength);
+ return {status, radio_combination_matrix_ptr};
+}
+
+wifi_error WifiLegacyHal::chreNanRttRequest(const std::string& iface_name, bool enable) {
+ if (enable)
+ return global_func_table_.wifi_nan_rtt_chre_enable_request(0, getIfaceHandle(iface_name),
+ NULL);
+ else
+ return global_func_table_.wifi_nan_rtt_chre_disable_request(0, getIfaceHandle(iface_name));
+}
+
+wifi_error WifiLegacyHal::chreRegisterHandler(const std::string& iface_name,
+ const ChreCallbackHandlers& handler) {
+ if (on_chre_nan_rtt_internal_callback) {
+ return WIFI_ERROR_NOT_AVAILABLE;
+ }
+
+ on_chre_nan_rtt_internal_callback = handler.on_wifi_chre_nan_rtt_state;
+
+ wifi_error status = global_func_table_.wifi_chre_register_handler(getIfaceHandle(iface_name),
+ {onAsyncChreNanRttState});
+ if (status != WIFI_SUCCESS) {
+ on_chre_nan_rtt_internal_callback = nullptr;
+ }
+ return status;
+}
+
+wifi_error WifiLegacyHal::enableWifiTxPowerLimits(const std::string& iface_name, bool enable) {
+ return global_func_table_.wifi_enable_tx_power_limits(getIfaceHandle(iface_name), enable);
+}
+
+wifi_error WifiLegacyHal::getWifiCachedScanResults(
+ const std::string& iface_name, const CachedScanResultsCallbackHandlers& handler) {
+ on_cached_scan_results_internal_callback = handler.on_cached_scan_results;
+
+ wifi_error status = global_func_table_.wifi_get_cached_scan_results(getIfaceHandle(iface_name),
+ {onSyncCachedScanResults});
+
+ on_cached_scan_results_internal_callback = nullptr;
+ return status;
+}
+
+void WifiLegacyHal::invalidate() {
+ global_handle_ = nullptr;
+ iface_name_to_handle_.clear();
+ on_driver_memory_dump_internal_callback = nullptr;
+ on_firmware_memory_dump_internal_callback = nullptr;
+ on_gscan_event_internal_callback = nullptr;
+ on_gscan_full_result_internal_callback = nullptr;
+ on_link_layer_stats_result_internal_callback = nullptr;
+ on_rssi_threshold_breached_internal_callback = nullptr;
+ on_ring_buffer_data_internal_callback = nullptr;
+ on_error_alert_internal_callback = nullptr;
+ on_radio_mode_change_internal_callback = nullptr;
+ on_subsystem_restart_internal_callback = nullptr;
+ on_rtt_results_internal_callback = nullptr;
+ on_nan_notify_response_user_callback = nullptr;
+ on_nan_event_publish_terminated_user_callback = nullptr;
+ on_nan_event_match_user_callback = nullptr;
+ on_nan_event_match_expired_user_callback = nullptr;
+ on_nan_event_subscribe_terminated_user_callback = nullptr;
+ on_nan_event_followup_user_callback = nullptr;
+ on_nan_event_disc_eng_event_user_callback = nullptr;
+ on_nan_event_disabled_user_callback = nullptr;
+ on_nan_event_tca_user_callback = nullptr;
+ on_nan_event_beacon_sdf_payload_user_callback = nullptr;
+ on_nan_event_data_path_request_user_callback = nullptr;
+ on_nan_event_data_path_confirm_user_callback = nullptr;
+ on_nan_event_data_path_end_user_callback = nullptr;
+ on_nan_event_transmit_follow_up_user_callback = nullptr;
+ on_nan_event_range_request_user_callback = nullptr;
+ on_nan_event_range_report_user_callback = nullptr;
+ on_nan_event_schedule_update_user_callback = nullptr;
+ on_twt_event_setup_response_callback = nullptr;
+ on_twt_event_teardown_completion_callback = nullptr;
+ on_twt_event_info_frame_received_callback = nullptr;
+ on_twt_event_device_notify_callback = nullptr;
+ on_chre_nan_rtt_internal_callback = nullptr;
+}
+
+} // namespace legacy_hal
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_legacy_hal.h b/wifi/aidl/default/wifi_legacy_hal.h
new file mode 100644
index 0000000..cd8c0b1
--- /dev/null
+++ b/wifi/aidl/default/wifi_legacy_hal.h
@@ -0,0 +1,738 @@
+/*
+ * 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 WIFI_LEGACY_HAL_H_
+#define WIFI_LEGACY_HAL_H_
+
+#include <hardware_legacy/wifi_hal.h>
+#include <wifi_system/interface_tool.h>
+
+#include <condition_variable>
+#include <functional>
+#include <map>
+#include <mutex>
+#include <thread>
+#include <vector>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+// This is in a separate namespace to prevent typename conflicts between
+// the legacy HAL types and the AIDL interface types.
+namespace legacy_hal {
+// Import all the types defined inside the legacy HAL header files into this
+// namespace.
+using ::chre_nan_rtt_state;
+using ::frame_info;
+using ::frame_type;
+using ::FRAME_TYPE_80211_MGMT;
+using ::FRAME_TYPE_ETHERNET_II;
+using ::FRAME_TYPE_UNKNOWN;
+using ::fw_roaming_state_t;
+using ::mac_addr;
+using ::NAN_CHANNEL_24G_BAND;
+using ::NAN_CHANNEL_5G_BAND_HIGH;
+using ::NAN_CHANNEL_5G_BAND_LOW;
+using ::NAN_DISABLE_RANGE_REPORT;
+using ::NAN_DO_NOT_USE_SRF;
+using ::NAN_DP_CHANNEL_NOT_REQUESTED;
+using ::NAN_DP_CONFIG_NO_SECURITY;
+using ::NAN_DP_CONFIG_SECURITY;
+using ::NAN_DP_END;
+using ::NAN_DP_FORCE_CHANNEL_SETUP;
+using ::NAN_DP_INITIATOR_RESPONSE;
+using ::NAN_DP_INTERFACE_CREATE;
+using ::NAN_DP_INTERFACE_DELETE;
+using ::NAN_DP_REQUEST_ACCEPT;
+using ::NAN_DP_REQUEST_CHANNEL_SETUP;
+using ::NAN_DP_REQUEST_REJECT;
+using ::NAN_DP_RESPONDER_RESPONSE;
+using ::NAN_GET_CAPABILITIES;
+using ::NAN_MATCH_ALG_MATCH_CONTINUOUS;
+using ::NAN_MATCH_ALG_MATCH_NEVER;
+using ::NAN_MATCH_ALG_MATCH_ONCE;
+using ::NAN_PUBLISH_TYPE_SOLICITED;
+using ::NAN_PUBLISH_TYPE_UNSOLICITED;
+using ::NAN_PUBLISH_TYPE_UNSOLICITED_SOLICITED;
+using ::NAN_RANGING_AUTO_RESPONSE_DISABLE;
+using ::NAN_RANGING_AUTO_RESPONSE_ENABLE;
+using ::NAN_RANGING_DISABLE;
+using ::NAN_RANGING_ENABLE;
+using ::NAN_RESPONSE_BEACON_SDF_PAYLOAD;
+using ::NAN_RESPONSE_CONFIG;
+using ::NAN_RESPONSE_DISABLED;
+using ::NAN_RESPONSE_ENABLED;
+using ::NAN_RESPONSE_ERROR;
+using ::NAN_RESPONSE_PUBLISH;
+using ::NAN_RESPONSE_PUBLISH_CANCEL;
+using ::NAN_RESPONSE_STATS;
+using ::NAN_RESPONSE_SUBSCRIBE;
+using ::NAN_RESPONSE_SUBSCRIBE_CANCEL;
+using ::NAN_RESPONSE_TCA;
+using ::NAN_RESPONSE_TRANSMIT_FOLLOWUP;
+using ::NAN_SECURITY_KEY_INPUT_PASSPHRASE;
+using ::NAN_SECURITY_KEY_INPUT_PMK;
+using ::NAN_SERVICE_ACCEPT_POLICY_ALL;
+using ::NAN_SERVICE_ACCEPT_POLICY_NONE;
+using ::NAN_SRF_ATTR_BLOOM_FILTER;
+using ::NAN_SRF_ATTR_PARTIAL_MAC_ADDR;
+using ::NAN_SRF_INCLUDE_DO_NOT_RESPOND;
+using ::NAN_SRF_INCLUDE_RESPOND;
+using ::NAN_SSI_NOT_REQUIRED_IN_MATCH_IND;
+using ::NAN_SSI_REQUIRED_IN_MATCH_IND;
+using ::NAN_STATUS_ALREADY_ENABLED;
+using ::NAN_STATUS_FOLLOWUP_QUEUE_FULL;
+using ::NAN_STATUS_INTERNAL_FAILURE;
+using ::NAN_STATUS_INVALID_NDP_ID;
+using ::NAN_STATUS_INVALID_PARAM;
+using ::NAN_STATUS_INVALID_PUBLISH_SUBSCRIBE_ID;
+using ::NAN_STATUS_INVALID_REQUESTOR_INSTANCE_ID;
+using ::NAN_STATUS_NAN_NOT_ALLOWED;
+using ::NAN_STATUS_NO_OTA_ACK;
+using ::NAN_STATUS_NO_RESOURCE_AVAILABLE;
+using ::NAN_STATUS_PROTOCOL_FAILURE;
+using ::NAN_STATUS_SUCCESS;
+using ::NAN_STATUS_UNSUPPORTED_CONCURRENCY_NAN_DISABLED;
+using ::NAN_SUBSCRIBE_TYPE_ACTIVE;
+using ::NAN_SUBSCRIBE_TYPE_PASSIVE;
+using ::NAN_TRANSMIT_IN_DW;
+using ::NAN_TRANSMIT_IN_FAW;
+using ::NAN_TX_PRIORITY_HIGH;
+using ::NAN_TX_PRIORITY_NORMAL;
+using ::NAN_TX_TYPE_BROADCAST;
+using ::NAN_TX_TYPE_UNICAST;
+using ::NAN_USE_SRF;
+using ::NanBeaconSdfPayloadInd;
+using ::NanCapabilities;
+using ::NanChannelInfo;
+using ::NanConfigRequest;
+using ::NanDataPathChannelCfg;
+using ::NanDataPathConfirmInd;
+using ::NanDataPathEndInd;
+using ::NanDataPathIndicationResponse;
+using ::NanDataPathInitiatorRequest;
+using ::NanDataPathRequestInd;
+using ::NanDataPathScheduleUpdateInd;
+using ::NanDisabledInd;
+using ::NanDiscEngEventInd;
+using ::NanEnableRequest;
+using ::NanFollowupInd;
+using ::NanMatchAlg;
+using ::NanMatchExpiredInd;
+using ::NanMatchInd;
+using ::NanPublishCancelRequest;
+using ::NanPublishRequest;
+using ::NanPublishTerminatedInd;
+using ::NanPublishType;
+using ::NanRangeReportInd;
+using ::NanRangeRequestInd;
+using ::NanResponseMsg;
+using ::NanSRFType;
+using ::NanStatusType;
+using ::NanSubscribeCancelRequest;
+using ::NanSubscribeRequest;
+using ::NanSubscribeTerminatedInd;
+using ::NanSubscribeType;
+using ::NanTransmitFollowupInd;
+using ::NanTransmitFollowupRequest;
+using ::NanTxType;
+using ::ROAMING_DISABLE;
+using ::ROAMING_ENABLE;
+using ::RTT_PEER_AP;
+using ::RTT_PEER_NAN;
+using ::RTT_PEER_P2P_CLIENT;
+using ::RTT_PEER_P2P_GO;
+using ::RTT_PEER_STA;
+using ::rtt_peer_type;
+using ::RTT_STATUS_ABORTED;
+using ::RTT_STATUS_FAIL_AP_ON_DIFF_CHANNEL;
+using ::RTT_STATUS_FAIL_BUSY_TRY_LATER;
+using ::RTT_STATUS_FAIL_FTM_PARAM_OVERRIDE;
+using ::RTT_STATUS_FAIL_INVALID_TS;
+using ::RTT_STATUS_FAIL_NO_CAPABILITY;
+using ::RTT_STATUS_FAIL_NO_RSP;
+using ::RTT_STATUS_FAIL_NOT_SCHEDULED_YET;
+using ::RTT_STATUS_FAIL_PROTOCOL;
+using ::RTT_STATUS_FAIL_REJECTED;
+using ::RTT_STATUS_FAIL_SCHEDULE;
+using ::RTT_STATUS_FAIL_TM_TIMEOUT;
+using ::RTT_STATUS_FAILURE;
+using ::RTT_STATUS_INVALID_REQ;
+using ::RTT_STATUS_NAN_RANGING_CONCURRENCY_NOT_SUPPORTED;
+using ::RTT_STATUS_NAN_RANGING_PROTOCOL_FAILURE;
+using ::RTT_STATUS_NO_WIFI;
+using ::RTT_STATUS_SUCCESS;
+using ::RTT_TYPE_1_SIDED;
+using ::RTT_TYPE_2_SIDED;
+using ::RX_PKT_FATE_DRV_DROP_FILTER;
+using ::RX_PKT_FATE_DRV_DROP_INVALID;
+using ::RX_PKT_FATE_DRV_DROP_NOBUFS;
+using ::RX_PKT_FATE_DRV_DROP_OTHER;
+using ::RX_PKT_FATE_DRV_QUEUED;
+using ::RX_PKT_FATE_FW_DROP_FILTER;
+using ::RX_PKT_FATE_FW_DROP_INVALID;
+using ::RX_PKT_FATE_FW_DROP_NOBUFS;
+using ::RX_PKT_FATE_FW_DROP_OTHER;
+using ::RX_PKT_FATE_FW_QUEUED;
+using ::RX_PKT_FATE_SUCCESS;
+using ::ssid_t;
+using ::transaction_id;
+using ::TX_PKT_FATE_ACKED;
+using ::TX_PKT_FATE_DRV_DROP_INVALID;
+using ::TX_PKT_FATE_DRV_DROP_NOBUFS;
+using ::TX_PKT_FATE_DRV_DROP_OTHER;
+using ::TX_PKT_FATE_DRV_QUEUED;
+using ::TX_PKT_FATE_FW_DROP_INVALID;
+using ::TX_PKT_FATE_FW_DROP_NOBUFS;
+using ::TX_PKT_FATE_FW_DROP_OTHER;
+using ::TX_PKT_FATE_FW_QUEUED;
+using ::TX_PKT_FATE_SENT;
+using ::WIFI_AC_BE;
+using ::WIFI_AC_BK;
+using ::WIFI_AC_VI;
+using ::WIFI_AC_VO;
+using ::WIFI_ANTENNA_1X1;
+using ::WIFI_ANTENNA_2X2;
+using ::WIFI_ANTENNA_3X3;
+using ::WIFI_ANTENNA_4X4;
+using ::WIFI_ANTENNA_UNSPECIFIED;
+using ::wifi_band;
+using ::WIFI_BAND_A;
+using ::WIFI_BAND_A_DFS;
+using ::WIFI_BAND_A_WITH_DFS;
+using ::WIFI_BAND_ABG;
+using ::WIFI_BAND_ABG_WITH_DFS;
+using ::WIFI_BAND_BG;
+using ::WIFI_BAND_UNSPECIFIED;
+using ::wifi_cached_scan_report;
+using ::wifi_cached_scan_results;
+using ::WIFI_CHAN_WIDTH_10;
+using ::WIFI_CHAN_WIDTH_160;
+using ::WIFI_CHAN_WIDTH_20;
+using ::WIFI_CHAN_WIDTH_320;
+using ::WIFI_CHAN_WIDTH_40;
+using ::WIFI_CHAN_WIDTH_5;
+using ::WIFI_CHAN_WIDTH_80;
+using ::WIFI_CHAN_WIDTH_80P80;
+using ::WIFI_CHAN_WIDTH_INVALID;
+using ::wifi_channel_info;
+using ::wifi_channel_stat;
+using ::wifi_channel_width;
+using ::wifi_coex_restriction;
+using ::wifi_coex_unsafe_channel;
+using ::WIFI_DUAL_STA_NON_TRANSIENT_UNBIASED;
+using ::WIFI_DUAL_STA_TRANSIENT_PREFER_PRIMARY;
+using ::wifi_error;
+using ::WIFI_ERROR_BUSY;
+using ::WIFI_ERROR_INVALID_ARGS;
+using ::WIFI_ERROR_INVALID_REQUEST_ID;
+using ::WIFI_ERROR_NONE;
+using ::WIFI_ERROR_NOT_AVAILABLE;
+using ::WIFI_ERROR_NOT_SUPPORTED;
+using ::WIFI_ERROR_OUT_OF_MEMORY;
+using ::WIFI_ERROR_TIMED_OUT;
+using ::WIFI_ERROR_TOO_MANY_REQUESTS;
+using ::WIFI_ERROR_UNINITIALIZED;
+using ::WIFI_ERROR_UNKNOWN;
+using ::wifi_gscan_capabilities;
+using ::wifi_hal_fn;
+using ::wifi_information_element;
+using ::WIFI_INTERFACE_IBSS;
+using ::WIFI_INTERFACE_MESH;
+using ::wifi_interface_mode;
+using ::WIFI_INTERFACE_NAN;
+using ::WIFI_INTERFACE_P2P_CLIENT;
+using ::WIFI_INTERFACE_P2P_GO;
+using ::WIFI_INTERFACE_SOFTAP;
+using ::WIFI_INTERFACE_STA;
+using ::WIFI_INTERFACE_TDLS;
+using ::wifi_interface_type;
+using ::WIFI_INTERFACE_TYPE_AP;
+using ::WIFI_INTERFACE_TYPE_NAN;
+using ::WIFI_INTERFACE_TYPE_P2P;
+using ::WIFI_INTERFACE_TYPE_STA;
+using ::WIFI_INTERFACE_UNKNOWN;
+using ::wifi_latency_mode;
+using ::WIFI_LATENCY_MODE_LOW;
+using ::WIFI_LATENCY_MODE_NORMAL;
+using ::wifi_lci_information;
+using ::wifi_lcr_information;
+using ::WIFI_LOGGER_CONNECT_EVENT_SUPPORTED;
+using ::WIFI_LOGGER_DRIVER_DUMP_SUPPORTED;
+using ::WIFI_LOGGER_MEMORY_DUMP_SUPPORTED;
+using ::WIFI_LOGGER_PACKET_FATE_SUPPORTED;
+using ::WIFI_LOGGER_POWER_EVENT_SUPPORTED;
+using ::WIFI_LOGGER_WAKE_LOCK_SUPPORTED;
+using ::WIFI_MOTION_EXPECTED;
+using ::WIFI_MOTION_NOT_EXPECTED;
+using ::wifi_motion_pattern;
+using ::WIFI_MOTION_UNKNOWN;
+using ::wifi_multi_sta_use_case;
+using ::wifi_power_scenario;
+using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_OFF;
+using ::WIFI_POWER_SCENARIO_ON_BODY_CELL_ON;
+using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_OFF;
+using ::WIFI_POWER_SCENARIO_ON_HEAD_CELL_ON;
+using ::WIFI_POWER_SCENARIO_VOICE_CALL;
+using ::wifi_radio_combination;
+using ::wifi_radio_combination_matrix;
+using ::wifi_radio_configuration;
+using ::wifi_rate;
+using ::wifi_request_id;
+using ::wifi_ring_buffer_status;
+using ::wifi_roaming_capabilities;
+using ::wifi_roaming_config;
+using ::wifi_rtt_bw;
+using ::WIFI_RTT_BW_10;
+using ::WIFI_RTT_BW_160;
+using ::WIFI_RTT_BW_20;
+using ::WIFI_RTT_BW_320;
+using ::WIFI_RTT_BW_40;
+using ::WIFI_RTT_BW_5;
+using ::WIFI_RTT_BW_80;
+using ::wifi_rtt_capabilities;
+using ::wifi_rtt_config;
+using ::wifi_rtt_preamble;
+using ::WIFI_RTT_PREAMBLE_EHT;
+using ::WIFI_RTT_PREAMBLE_HE;
+using ::WIFI_RTT_PREAMBLE_HT;
+using ::WIFI_RTT_PREAMBLE_LEGACY;
+using ::WIFI_RTT_PREAMBLE_VHT;
+using ::wifi_rtt_responder;
+using ::wifi_rtt_result;
+using ::wifi_rtt_status;
+using ::wifi_rtt_type;
+using ::wifi_rx_packet_fate;
+using ::wifi_rx_report;
+using ::wifi_scan_bucket_spec;
+using ::wifi_scan_cmd_params;
+using ::WIFI_SCAN_FLAG_INTERRUPTED;
+using ::wifi_scan_result;
+using ::WIFI_SUCCESS;
+using ::wifi_tx_packet_fate;
+using ::wifi_tx_report;
+using ::wifi_usable_channel;
+using ::WIFI_USABLE_CHANNEL_FILTER_CELLULAR_COEXISTENCE;
+using ::WIFI_USABLE_CHANNEL_FILTER_CONCURRENCY;
+using ::WLAN_MAC_2_4_BAND;
+using ::WLAN_MAC_5_0_BAND;
+using ::WLAN_MAC_60_0_BAND;
+using ::WLAN_MAC_6_0_BAND;
+
+// APF capabilities supported by the iface.
+struct PacketFilterCapabilities {
+ uint32_t version;
+ uint32_t max_len;
+};
+
+// WARNING: We don't care about the variable sized members of either
+// |wifi_iface_stat|, |wifi_radio_stat| structures. So, using the pragma
+// to escape the compiler warnings regarding this.
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wgnu-variable-sized-type-not-at-end"
+// The |wifi_radio_stat.tx_time_per_levels| stats is provided as a pointer in
+// |wifi_radio_stat| structure in the legacy HAL API. Separate that out
+// into a separate return element to avoid passing pointers around.
+struct LinkLayerRadioStats {
+ wifi_radio_stat stats;
+ std::vector<uint32_t> tx_time_per_levels;
+ std::vector<wifi_channel_stat> channel_stats;
+};
+
+struct WifiPeerInfo {
+ wifi_peer_info peer_info;
+ std::vector<wifi_rate_stat> rate_stats;
+};
+
+struct LinkLayerStats {
+ wifi_iface_stat iface;
+ std::vector<LinkLayerRadioStats> radios;
+ std::vector<WifiPeerInfo> peers;
+};
+#pragma GCC diagnostic pop
+
+// The |WLAN_DRIVER_WAKE_REASON_CNT.cmd_event_wake_cnt| and
+// |WLAN_DRIVER_WAKE_REASON_CNT.driver_fw_local_wake_cnt| stats is provided
+// as a pointer in |WLAN_DRIVER_WAKE_REASON_CNT| structure in the legacy HAL
+// API. Separate that out into a separate return elements to avoid passing
+// pointers around.
+struct WakeReasonStats {
+ WLAN_DRIVER_WAKE_REASON_CNT wake_reason_cnt;
+ std::vector<uint32_t> cmd_event_wake_cnt;
+ std::vector<uint32_t> driver_fw_local_wake_cnt;
+};
+
+// NAN response and event callbacks struct.
+struct NanCallbackHandlers {
+ // NotifyResponse invoked to notify the status of the Request.
+ std::function<void(transaction_id, const NanResponseMsg&)> on_notify_response;
+ // Various event callbacks.
+ std::function<void(const NanPublishTerminatedInd&)> on_event_publish_terminated;
+ std::function<void(const NanMatchInd&)> on_event_match;
+ std::function<void(const NanMatchExpiredInd&)> on_event_match_expired;
+ std::function<void(const NanSubscribeTerminatedInd&)> on_event_subscribe_terminated;
+ std::function<void(const NanFollowupInd&)> on_event_followup;
+ std::function<void(const NanDiscEngEventInd&)> on_event_disc_eng_event;
+ std::function<void(const NanDisabledInd&)> on_event_disabled;
+ std::function<void(const NanTCAInd&)> on_event_tca;
+ std::function<void(const NanBeaconSdfPayloadInd&)> on_event_beacon_sdf_payload;
+ std::function<void(const NanDataPathRequestInd&)> on_event_data_path_request;
+ std::function<void(const NanDataPathConfirmInd&)> on_event_data_path_confirm;
+ std::function<void(const NanDataPathEndInd&)> on_event_data_path_end;
+ std::function<void(const NanTransmitFollowupInd&)> on_event_transmit_follow_up;
+ std::function<void(const NanRangeRequestInd&)> on_event_range_request;
+ std::function<void(const NanRangeReportInd&)> on_event_range_report;
+ std::function<void(const NanDataPathScheduleUpdateInd&)> on_event_schedule_update;
+};
+
+// Full scan results contain IE info and are hence passed by reference, to
+// preserve the variable length array member |ie_data|. Callee must not retain
+// the pointer.
+using on_gscan_full_result_callback =
+ std::function<void(wifi_request_id, const wifi_scan_result*, uint32_t)>;
+// These scan results don't contain any IE info, so no need to pass by
+// reference.
+using on_gscan_results_callback =
+ std::function<void(wifi_request_id, const std::vector<wifi_cached_scan_results>&)>;
+
+// Invoked when the rssi value breaches the thresholds set.
+using on_rssi_threshold_breached_callback =
+ std::function<void(wifi_request_id, std::array<uint8_t, ETH_ALEN>, int8_t)>;
+
+// Callback for RTT range request results.
+// Rtt results contain IE info and are hence passed by reference, to
+// preserve the |LCI| and |LCR| pointers. Callee must not retain
+// the pointer.
+using on_rtt_results_callback =
+ std::function<void(wifi_request_id, const std::vector<const wifi_rtt_result*>&)>;
+
+// Callback for ring buffer data.
+using on_ring_buffer_data_callback = std::function<void(
+ const std::string&, const std::vector<uint8_t>&, const wifi_ring_buffer_status&)>;
+
+// Callback for alerts.
+using on_error_alert_callback = std::function<void(int32_t, const std::vector<uint8_t>&)>;
+
+// Callback for subsystem restart
+using on_subsystem_restart_callback = std::function<void(const std::string&)>;
+
+// Struct for the mac info from the legacy HAL. This is a cleaner version
+// of the |wifi_mac_info| & |wifi_iface_info|.
+typedef struct {
+ std::string name;
+ wifi_channel channel;
+} WifiIfaceInfo;
+
+typedef struct {
+ uint32_t wlan_mac_id;
+ /* BIT MASK of BIT(WLAN_MAC*) as represented by wlan_mac_band */
+ uint32_t mac_band;
+ /* Represents the connected Wi-Fi interfaces associated with each MAC */
+ std::vector<WifiIfaceInfo> iface_infos;
+} WifiMacInfo;
+
+// Callback for radio mode change
+using on_radio_mode_change_callback = std::function<void(const std::vector<WifiMacInfo>&)>;
+
+// TWT response and event callbacks struct.
+struct TwtCallbackHandlers {
+ // Callback for TWT setup response
+ std::function<void(const TwtSetupResponse&)> on_setup_response;
+ // Callback for TWT teardown completion
+ std::function<void(const TwtTeardownCompletion&)> on_teardown_completion;
+ // Callback for TWT info frame received event
+ std::function<void(const TwtInfoFrameReceived&)> on_info_frame_received;
+ // Callback for TWT notification from the device
+ std::function<void(const TwtDeviceNotify&)> on_device_notify;
+};
+
+// CHRE response and event callbacks struct.
+struct ChreCallbackHandlers {
+ // Callback for CHRE NAN RTT
+ std::function<void(chre_nan_rtt_state)> on_wifi_chre_nan_rtt_state;
+};
+
+// Cached Scan Results response and event callbacks struct.
+struct CachedScanResultsCallbackHandlers {
+ // Callback for Cached Scan Results
+ std::function<void(wifi_cached_scan_report*)> on_cached_scan_results;
+};
+
+/**
+ * Class that encapsulates all legacy HAL interactions.
+ * This class manages the lifetime of the event loop thread used by legacy HAL.
+ *
+ * Note: There will only be a single instance of this class created in the Wifi
+ * object and will be valid for the lifetime of the process.
+ */
+class WifiLegacyHal {
+ public:
+ WifiLegacyHal(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool,
+ const wifi_hal_fn& fn, bool is_primary);
+ virtual ~WifiLegacyHal() = default;
+
+ // Initialize the legacy HAL function table.
+ virtual wifi_error initialize();
+ // Start the legacy HAL and the event looper thread.
+ virtual wifi_error start();
+ // Deinitialize the legacy HAL and wait for the event loop thread to exit
+ // using a predefined timeout.
+ virtual wifi_error stop(std::unique_lock<std::recursive_mutex>* lock,
+ const std::function<void()>& on_complete_callback);
+ virtual wifi_error waitForDriverReady();
+ // Checks if legacy HAL has successfully started
+ bool isStarted();
+ // Wrappers for all the functions in the legacy HAL function table.
+ virtual std::pair<wifi_error, std::string> getDriverVersion(const std::string& iface_name);
+ virtual std::pair<wifi_error, std::string> getFirmwareVersion(const std::string& iface_name);
+ std::pair<wifi_error, std::vector<uint8_t>> requestDriverMemoryDump(
+ const std::string& iface_name);
+ std::pair<wifi_error, std::vector<uint8_t>> requestFirmwareMemoryDump(
+ const std::string& iface_name);
+ virtual std::pair<wifi_error, uint64_t> getSupportedFeatureSet(const std::string& iface_name);
+ // APF functions.
+ std::pair<wifi_error, PacketFilterCapabilities> getPacketFilterCapabilities(
+ const std::string& iface_name);
+ wifi_error setPacketFilter(const std::string& iface_name, const std::vector<uint8_t>& program);
+ std::pair<wifi_error, std::vector<uint8_t>> readApfPacketFilterData(
+ const std::string& iface_name);
+ // Gscan functions.
+ std::pair<wifi_error, wifi_gscan_capabilities> getGscanCapabilities(
+ const std::string& iface_name);
+ // These API's provides a simplified interface over the legacy Gscan API's:
+ // a) All scan events from the legacy HAL API other than the
+ // |WIFI_SCAN_FAILED| are treated as notification of results.
+ // This method then retrieves the cached scan results from the legacy
+ // HAL API and triggers the externally provided
+ // |on_results_user_callback| on success.
+ // b) |WIFI_SCAN_FAILED| scan event or failure to retrieve cached scan
+ // results
+ // Triggers the externally provided |on_failure_user_callback|.
+ // c) Full scan result event triggers the externally provided
+ // |on_full_result_user_callback|.
+ wifi_error startGscan(const std::string& iface_name, wifi_request_id id,
+ const wifi_scan_cmd_params& params,
+ const std::function<void(wifi_request_id)>& on_failure_callback,
+ const on_gscan_results_callback& on_results_callback,
+ const on_gscan_full_result_callback& on_full_result_callback);
+ wifi_error stopGscan(const std::string& iface_name, wifi_request_id id);
+ std::pair<wifi_error, std::vector<uint32_t>> getValidFrequenciesForBand(
+ const std::string& iface_name, wifi_band band);
+ virtual wifi_error setDfsFlag(const std::string& iface_name, bool dfs_on);
+ // Link layer stats functions.
+ wifi_error enableLinkLayerStats(const std::string& iface_name, bool debug);
+ wifi_error disableLinkLayerStats(const std::string& iface_name);
+ std::pair<wifi_error, LinkLayerStats> getLinkLayerStats(const std::string& iface_name);
+ // RSSI monitor functions.
+ wifi_error startRssiMonitoring(
+ const std::string& iface_name, wifi_request_id id, int8_t max_rssi, int8_t min_rssi,
+ const on_rssi_threshold_breached_callback& on_threshold_breached_callback);
+ wifi_error stopRssiMonitoring(const std::string& iface_name, wifi_request_id id);
+ std::pair<wifi_error, wifi_roaming_capabilities> getRoamingCapabilities(
+ const std::string& iface_name);
+ wifi_error configureRoaming(const std::string& iface_name, const wifi_roaming_config& config);
+ wifi_error enableFirmwareRoaming(const std::string& iface_name, fw_roaming_state_t state);
+ wifi_error configureNdOffload(const std::string& iface_name, bool enable);
+ wifi_error startSendingOffloadedPacket(const std::string& iface_name, int32_t cmd_id,
+ uint16_t ether_type,
+ const std::vector<uint8_t>& ip_packet_data,
+ const std::array<uint8_t, 6>& src_address,
+ const std::array<uint8_t, 6>& dst_address,
+ int32_t period_in_ms);
+ wifi_error stopSendingOffloadedPacket(const std::string& iface_name, uint32_t cmd_id);
+ virtual wifi_error selectTxPowerScenario(const std::string& iface_name,
+ wifi_power_scenario scenario);
+ virtual wifi_error resetTxPowerScenario(const std::string& iface_name);
+ wifi_error setLatencyMode(const std::string& iface_name, wifi_latency_mode mode);
+ wifi_error setThermalMitigationMode(wifi_thermal_mode mode, uint32_t completion_window);
+ wifi_error setDscpToAccessCategoryMapping(uint32_t start, uint32_t end,
+ uint32_t access_category);
+ wifi_error resetDscpToAccessCategoryMapping();
+ // Logger/debug functions.
+ std::pair<wifi_error, uint32_t> getLoggerSupportedFeatureSet(const std::string& iface_name);
+ wifi_error startPktFateMonitoring(const std::string& iface_name);
+ std::pair<wifi_error, std::vector<wifi_tx_report>> getTxPktFates(const std::string& iface_name);
+ std::pair<wifi_error, std::vector<wifi_rx_report>> getRxPktFates(const std::string& iface_name);
+ std::pair<wifi_error, WakeReasonStats> getWakeReasonStats(const std::string& iface_name);
+ wifi_error registerRingBufferCallbackHandler(
+ const std::string& iface_name, const on_ring_buffer_data_callback& on_data_callback);
+ wifi_error deregisterRingBufferCallbackHandler(const std::string& iface_name);
+ virtual wifi_error registerSubsystemRestartCallbackHandler(
+ const on_subsystem_restart_callback& on_restart_callback);
+ std::pair<wifi_error, std::vector<wifi_ring_buffer_status>> getRingBuffersStatus(
+ const std::string& iface_name);
+ wifi_error startRingBufferLogging(const std::string& iface_name, const std::string& ring_name,
+ uint32_t verbose_level, uint32_t max_interval_sec,
+ uint32_t min_data_size);
+ wifi_error getRingBufferData(const std::string& iface_name, const std::string& ring_name);
+ wifi_error registerErrorAlertCallbackHandler(const std::string& iface_name,
+ const on_error_alert_callback& on_alert_callback);
+ wifi_error deregisterErrorAlertCallbackHandler(const std::string& iface_name);
+ // Radio mode functions.
+ virtual wifi_error registerRadioModeChangeCallbackHandler(
+ const std::string& iface_name,
+ const on_radio_mode_change_callback& on_user_change_callback);
+ // RTT functions.
+ wifi_error startRttRangeRequest(const std::string& iface_name, wifi_request_id id,
+ const std::vector<wifi_rtt_config>& rtt_configs,
+ const on_rtt_results_callback& on_results_callback);
+ wifi_error cancelRttRangeRequest(const std::string& iface_name, wifi_request_id id,
+ const std::vector<std::array<uint8_t, ETH_ALEN>>& mac_addrs);
+ std::pair<wifi_error, wifi_rtt_capabilities> getRttCapabilities(const std::string& iface_name);
+ std::pair<wifi_error, wifi_rtt_responder> getRttResponderInfo(const std::string& iface_name);
+ wifi_error enableRttResponder(const std::string& iface_name, wifi_request_id id,
+ const wifi_channel_info& channel_hint, uint32_t max_duration_secs,
+ const wifi_rtt_responder& info);
+ wifi_error disableRttResponder(const std::string& iface_name, wifi_request_id id);
+ wifi_error setRttLci(const std::string& iface_name, wifi_request_id id,
+ const wifi_lci_information& info);
+ wifi_error setRttLcr(const std::string& iface_name, wifi_request_id id,
+ const wifi_lcr_information& info);
+ // NAN functions.
+ virtual wifi_error nanRegisterCallbackHandlers(const std::string& iface_name,
+ const NanCallbackHandlers& callbacks);
+ wifi_error nanEnableRequest(const std::string& iface_name, transaction_id id,
+ const NanEnableRequest& msg);
+ virtual wifi_error nanDisableRequest(const std::string& iface_name, transaction_id id);
+ wifi_error nanPublishRequest(const std::string& iface_name, transaction_id id,
+ const NanPublishRequest& msg);
+ wifi_error nanPublishCancelRequest(const std::string& iface_name, transaction_id id,
+ const NanPublishCancelRequest& msg);
+ wifi_error nanSubscribeRequest(const std::string& iface_name, transaction_id id,
+ const NanSubscribeRequest& msg);
+ wifi_error nanSubscribeCancelRequest(const std::string& iface_name, transaction_id id,
+ const NanSubscribeCancelRequest& msg);
+ wifi_error nanTransmitFollowupRequest(const std::string& iface_name, transaction_id id,
+ const NanTransmitFollowupRequest& msg);
+ wifi_error nanStatsRequest(const std::string& iface_name, transaction_id id,
+ const NanStatsRequest& msg);
+ wifi_error nanConfigRequest(const std::string& iface_name, transaction_id id,
+ const NanConfigRequest& msg);
+ wifi_error nanTcaRequest(const std::string& iface_name, transaction_id id,
+ const NanTCARequest& msg);
+ wifi_error nanBeaconSdfPayloadRequest(const std::string& iface_name, transaction_id id,
+ const NanBeaconSdfPayloadRequest& msg);
+ std::pair<wifi_error, NanVersion> nanGetVersion();
+ wifi_error nanGetCapabilities(const std::string& iface_name, transaction_id id);
+ wifi_error nanDataInterfaceCreate(const std::string& iface_name, transaction_id id,
+ const std::string& data_iface_name);
+ virtual wifi_error nanDataInterfaceDelete(const std::string& iface_name, transaction_id id,
+ const std::string& data_iface_name);
+ wifi_error nanDataRequestInitiator(const std::string& iface_name, transaction_id id,
+ const NanDataPathInitiatorRequest& msg);
+ wifi_error nanDataIndicationResponse(const std::string& iface_name, transaction_id id,
+ const NanDataPathIndicationResponse& msg);
+ wifi_error nanDataEnd(const std::string& iface_name, transaction_id id, uint32_t ndpInstanceId);
+ // AP functions.
+ wifi_error setCountryCode(const std::string& iface_name, const std::array<uint8_t, 2> code);
+
+ // Interface functions.
+ virtual wifi_error createVirtualInterface(const std::string& ifname,
+ wifi_interface_type iftype);
+ virtual wifi_error deleteVirtualInterface(const std::string& ifname);
+ virtual wifi_error getSupportedIfaceName(uint32_t iface_type, std::string& ifname);
+
+ // STA + STA functions
+ virtual wifi_error multiStaSetPrimaryConnection(const std::string& ifname);
+ virtual wifi_error multiStaSetUseCase(wifi_multi_sta_use_case use_case);
+
+ // Coex functions.
+ virtual wifi_error setCoexUnsafeChannels(std::vector<wifi_coex_unsafe_channel> unsafe_channels,
+ uint32_t restrictions);
+
+ wifi_error setVoipMode(const std::string& iface_name, wifi_voip_mode mode);
+
+ wifi_error twtRegisterHandler(const std::string& iface_name,
+ const TwtCallbackHandlers& handler);
+
+ std::pair<wifi_error, TwtCapabilitySet> twtGetCapability(const std::string& iface_name);
+
+ wifi_error twtSetupRequest(const std::string& iface_name, const TwtSetupRequest& msg);
+
+ wifi_error twtTearDownRequest(const std::string& iface_name, const TwtTeardownRequest& msg);
+
+ wifi_error twtInfoFrameRequest(const std::string& iface_name, const TwtInfoFrameRequest& msg);
+
+ std::pair<wifi_error, TwtStats> twtGetStats(const std::string& iface_name, uint8_t configId);
+
+ wifi_error twtClearStats(const std::string& iface_name, uint8_t configId);
+
+ wifi_error setDtimConfig(const std::string& iface_name, uint32_t multiplier);
+
+ // Retrieve the list of usable channels in the requested bands
+ // for the requested modes
+ std::pair<wifi_error, std::vector<wifi_usable_channel>> getUsableChannels(
+ uint32_t band_mask, uint32_t iface_mode_mask, uint32_t filter_mask);
+
+ wifi_error triggerSubsystemRestart();
+
+ wifi_error setIndoorState(bool isIndoor);
+
+ std::pair<wifi_error, wifi_radio_combination_matrix*> getSupportedRadioCombinationsMatrix();
+
+ // CHRE NAN RTT function
+ wifi_error chreNanRttRequest(const std::string& iface_name, bool enable);
+
+ wifi_error chreRegisterHandler(const std::string& iface_name,
+ const ChreCallbackHandlers& handler);
+
+ wifi_error enableWifiTxPowerLimits(const std::string& iface_name, bool enable);
+ wifi_error getWifiCachedScanResults(const std::string& iface_name,
+ const CachedScanResultsCallbackHandlers& handler);
+
+ private:
+ // Retrieve interface handles for all the available interfaces.
+ wifi_error retrieveIfaceHandles();
+ wifi_interface_handle getIfaceHandle(const std::string& iface_name);
+ // Run the legacy HAL event loop thread.
+ void runEventLoop();
+ // Retrieve the cached gscan results to pass the results back to the
+ // external callbacks.
+ std::pair<wifi_error, std::vector<wifi_cached_scan_results>> getGscanCachedResults(
+ const std::string& iface_name);
+ void invalidate();
+ // Handles wifi (error) status of Virtual interface create/delete
+ wifi_error handleVirtualInterfaceCreateOrDeleteStatus(const std::string& ifname,
+ wifi_error status);
+
+ // Global function table of legacy HAL.
+ wifi_hal_fn global_func_table_;
+ // Opaque handle to be used for all global operations.
+ wifi_handle global_handle_;
+ // Map of interface name to handle that is to be used for all interface
+ // specific operations.
+ std::map<std::string, wifi_interface_handle> iface_name_to_handle_;
+ // Flag to indicate if we have initiated the cleanup of legacy HAL.
+ std::atomic<bool> awaiting_event_loop_termination_;
+ std::condition_variable_any stop_wait_cv_;
+ // Flag to indicate if the legacy HAL has been started.
+ bool is_started_;
+ std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool_;
+ // Flag to indicate if this HAL is for the primary chip. This is used
+ // in order to avoid some hard-coded behavior used with older HALs,
+ // such as bring wlan0 interface up/down on start/stop HAL.
+ // it may be removed once vendor HALs are updated.
+ bool is_primary_;
+};
+
+} // namespace legacy_hal
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_LEGACY_HAL_H_
diff --git a/wifi/aidl/default/wifi_legacy_hal_factory.cpp b/wifi/aidl/default/wifi_legacy_hal_factory.cpp
new file mode 100644
index 0000000..60f81ed
--- /dev/null
+++ b/wifi/aidl/default/wifi_legacy_hal_factory.cpp
@@ -0,0 +1,252 @@
+/*
+ * 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 "wifi_legacy_hal_factory.h"
+
+#include <android-base/logging.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xmlmemory.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "wifi_legacy_hal_stubs.h"
+
+namespace {
+static constexpr char kVendorHalsDescPath[] = "/vendor/etc/wifi/vendor_hals";
+static constexpr char kVendorHalsDescExt[] = ".xml";
+static constexpr uint32_t kVendorHalsDescVersion = 1;
+
+bool isDirectory(struct dirent* entryPtr) {
+ bool isDir = false;
+ if (entryPtr->d_type != DT_UNKNOWN && entryPtr->d_type != DT_LNK) {
+ isDir = (entryPtr->d_type == DT_DIR);
+ } else {
+ struct stat entryStat;
+ stat(entryPtr->d_name, &entryStat);
+ isDir = S_ISDIR(entryStat.st_mode);
+ }
+ return isDir;
+}
+
+bool isFileExtension(const char* name, const char* ext) {
+ if (name == NULL) return false;
+ if (ext == NULL) return false;
+
+ size_t extLen = strlen(ext);
+ size_t nameLen = strlen(name);
+
+ if (extLen > nameLen) return false;
+
+ if (strncmp(name + nameLen - extLen, ext, extLen) != 0) return false;
+
+ return true;
+}
+}; // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace legacy_hal {
+
+WifiLegacyHalFactory::WifiLegacyHalFactory(
+ const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool)
+ : iface_tool_(iface_tool) {}
+
+std::vector<std::shared_ptr<WifiLegacyHal>> WifiLegacyHalFactory::getHals() {
+ if (legacy_hals_.empty()) {
+ if (!initVendorHalDescriptorFromLinked()) initVendorHalsDescriptorList();
+ for (auto& desc : descs_) {
+ std::shared_ptr<WifiLegacyHal> hal =
+ std::make_shared<WifiLegacyHal>(iface_tool_, desc.fn, desc.primary);
+ legacy_hals_.push_back(hal);
+ }
+ }
+
+ return legacy_hals_;
+}
+
+bool WifiLegacyHalFactory::initVendorHalDescriptorFromLinked() {
+ wifi_hal_lib_desc desc;
+
+ if (!initLinkedHalFunctionTable(&desc.fn)) return false;
+
+ desc.primary = true;
+ desc.handle = NULL;
+ descs_.push_back(desc);
+ return true;
+}
+
+bool WifiLegacyHalFactory::initLinkedHalFunctionTable(wifi_hal_fn* hal_fn) {
+ init_wifi_vendor_hal_func_table_t initfn;
+
+ initfn = (init_wifi_vendor_hal_func_table_t)dlsym(RTLD_DEFAULT,
+ "init_wifi_vendor_hal_func_table");
+ if (!initfn) {
+ LOG(INFO) << "no vendor HAL library linked, will try dynamic load";
+ return false;
+ }
+
+ if (!initHalFuncTableWithStubs(hal_fn)) {
+ LOG(ERROR) << "Can not initialize the basic function pointer table";
+ return false;
+ }
+
+ if (initfn(hal_fn) != WIFI_SUCCESS) {
+ LOG(ERROR) << "Can not initialize the vendor function pointer table";
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ * Overall structure of the HAL descriptor XML schema
+ *
+ * <?xml version="1.0" encoding="UTF-8"?>
+ * <WifiVendorHal version="1">
+ * <path>/vendor/lib64/libwifi-hal-qcom.so</path>
+ * <primary>1</primary>
+ * </WifiVendorHal>
+ */
+void WifiLegacyHalFactory::initVendorHalsDescriptorList() {
+ xmlDocPtr xml;
+ xmlNodePtr node, cnode;
+ char* version;
+ std::string path;
+ xmlChar* value;
+ wifi_hal_lib_desc desc;
+
+ LOG(INFO) << "processing vendor HALs descriptions in " << kVendorHalsDescPath;
+ DIR* dirPtr = ::opendir(kVendorHalsDescPath);
+ if (dirPtr == NULL) {
+ LOG(ERROR) << "failed to open " << kVendorHalsDescPath;
+ return;
+ }
+ for (struct dirent* entryPtr = ::readdir(dirPtr); entryPtr != NULL;
+ entryPtr = ::readdir(dirPtr)) {
+ if (isDirectory(entryPtr)) continue;
+
+ if (!isFileExtension(entryPtr->d_name, kVendorHalsDescExt))
+ continue; // only process .xml files
+
+ LOG(INFO) << "processing config file: " << entryPtr->d_name;
+
+ std::string fullPath(kVendorHalsDescPath);
+ fullPath.append("/");
+ fullPath.append(entryPtr->d_name);
+ xml = xmlReadFile(fullPath.c_str(), "UTF-8", XML_PARSE_RECOVER);
+ if (!xml) {
+ LOG(ERROR) << "failed to parse: " << entryPtr->d_name << " skipping...";
+ continue;
+ }
+ node = xmlDocGetRootElement(xml);
+ if (!node) {
+ LOG(ERROR) << "empty config file: " << entryPtr->d_name << " skipping...";
+ goto skip;
+ }
+ if (xmlStrcmp(node->name, BAD_CAST "WifiVendorHal")) {
+ LOG(ERROR) << "bad config, root element not WifiVendorHal: " << entryPtr->d_name
+ << " skipping...";
+ goto skip;
+ }
+ version = (char*)xmlGetProp(node, BAD_CAST "version");
+ if (!version || strtoul(version, NULL, 0) != kVendorHalsDescVersion) {
+ LOG(ERROR) << "conf file: " << entryPtr->d_name
+ << "must have version: " << kVendorHalsDescVersion << ", skipping...";
+ goto skip;
+ }
+ cnode = node->children;
+ path.clear();
+ desc.primary = false;
+ while (cnode) {
+ if (!xmlStrcmp(cnode->name, BAD_CAST "path")) {
+ value = xmlNodeListGetString(xml, cnode->children, 1);
+ if (value) path = (char*)value;
+ xmlFree(value);
+ } else if (!xmlStrcmp(cnode->name, BAD_CAST "primary")) {
+ value = xmlNodeListGetString(xml, cnode->children, 1);
+ desc.primary = !xmlStrcmp(value, BAD_CAST "1");
+ xmlFree(value);
+ }
+ cnode = cnode->next;
+ }
+ if (path.empty()) {
+ LOG(ERROR) << "hal library path not provided in: " << entryPtr->d_name
+ << ", skipping...";
+ goto skip;
+ }
+ if (loadVendorHalLib(path, desc)) {
+ if (desc.primary)
+ descs_.insert(descs_.begin(), desc);
+ else
+ descs_.push_back(desc);
+ }
+ skip:
+ xmlFreeDoc(xml);
+ }
+ ::closedir(dirPtr);
+}
+
+bool WifiLegacyHalFactory::loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc) {
+ void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
+ init_wifi_vendor_hal_func_table_t initfn;
+ wifi_error res;
+
+ if (!h) {
+ LOG(ERROR) << "failed to open vendor hal library: " << path;
+ return false;
+ }
+ initfn = (init_wifi_vendor_hal_func_table_t)dlsym(h, "init_wifi_vendor_hal_func_table");
+ if (!initfn) {
+ LOG(ERROR) << "init_wifi_vendor_hal_func_table not found in: " << path;
+ goto out_err;
+ }
+
+ if (!initHalFuncTableWithStubs(&desc.fn)) {
+ LOG(ERROR) << "Can not initialize the basic function pointer table";
+ goto out_err;
+ }
+ res = initfn(&desc.fn);
+ if (res != WIFI_SUCCESS) {
+ LOG(ERROR) << "failed to initialize the vendor func table in: " << path
+ << " error: " << res;
+ goto out_err;
+ }
+
+ res = desc.fn.wifi_early_initialize();
+ // vendor HALs which do not implement early_initialize will return
+ // WIFI_ERROR_NOT_SUPPORTED, treat this as success.
+ if (res != WIFI_SUCCESS && res != WIFI_ERROR_NOT_SUPPORTED) {
+ LOG(ERROR) << "early initialization failed in: " << path << " error: " << res;
+ goto out_err;
+ }
+
+ desc.handle = h;
+ return true;
+out_err:
+ dlclose(h);
+ return false;
+}
+
+} // namespace legacy_hal
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_legacy_hal_factory.h b/wifi/aidl/default/wifi_legacy_hal_factory.h
new file mode 100644
index 0000000..e7b287a
--- /dev/null
+++ b/wifi/aidl/default/wifi_legacy_hal_factory.h
@@ -0,0 +1,64 @@
+/*
+ * 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 WIFI_LEGACY_HAL_FACTORY_H_
+#define WIFI_LEGACY_HAL_FACTORY_H_
+
+#include <wifi_system/interface_tool.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+// This is in a separate namespace to prevent typename conflicts between
+// the legacy HAL types and the AIDL interface types.
+namespace legacy_hal {
+/**
+ * Class that creates WifiLegacyHal objects for vendor HALs in the system.
+ */
+class WifiLegacyHalFactory {
+ public:
+ WifiLegacyHalFactory(const std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool);
+ virtual ~WifiLegacyHalFactory() = default;
+
+ std::vector<std::shared_ptr<WifiLegacyHal>> getHals();
+
+ private:
+ typedef struct {
+ wifi_hal_fn fn;
+ bool primary;
+ void* handle;
+ } wifi_hal_lib_desc;
+
+ bool initVendorHalDescriptorFromLinked();
+ void initVendorHalsDescriptorList();
+ bool initLinkedHalFunctionTable(wifi_hal_fn* hal_fn);
+ bool loadVendorHalLib(const std::string& path, wifi_hal_lib_desc& desc);
+
+ std::weak_ptr<::android::wifi_system::InterfaceTool> iface_tool_;
+ std::vector<wifi_hal_lib_desc> descs_;
+ std::vector<std::shared_ptr<WifiLegacyHal>> legacy_hals_;
+};
+
+} // namespace legacy_hal
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_LEGACY_HAL_FACTORY_H_
diff --git a/wifi/aidl/default/wifi_legacy_hal_stubs.cpp b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
new file mode 100644
index 0000000..cff7f69
--- /dev/null
+++ b/wifi/aidl/default/wifi_legacy_hal_stubs.cpp
@@ -0,0 +1,177 @@
+/*
+ * 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 "wifi_legacy_hal_stubs.h"
+
+// TODO: Remove these stubs from HalTool in libwifi-system.
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace legacy_hal {
+template <typename>
+struct stubFunction;
+
+template <typename R, typename... Args>
+struct stubFunction<R (*)(Args...)> {
+ static constexpr R invoke(Args...) { return WIFI_ERROR_NOT_SUPPORTED; }
+};
+template <typename... Args>
+struct stubFunction<void (*)(Args...)> {
+ static constexpr void invoke(Args...) {}
+};
+
+template <typename T>
+void populateStubFor(T* val) {
+ *val = &stubFunction<T>::invoke;
+}
+
+bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn) {
+ if (hal_fn == nullptr) {
+ return false;
+ }
+ populateStubFor(&hal_fn->wifi_initialize);
+ populateStubFor(&hal_fn->wifi_wait_for_driver_ready);
+ populateStubFor(&hal_fn->wifi_cleanup);
+ populateStubFor(&hal_fn->wifi_event_loop);
+ populateStubFor(&hal_fn->wifi_get_error_info);
+ populateStubFor(&hal_fn->wifi_get_supported_feature_set);
+ populateStubFor(&hal_fn->wifi_get_concurrency_matrix);
+ populateStubFor(&hal_fn->wifi_set_scanning_mac_oui);
+ populateStubFor(&hal_fn->wifi_get_supported_channels);
+ populateStubFor(&hal_fn->wifi_is_epr_supported);
+ populateStubFor(&hal_fn->wifi_get_ifaces);
+ populateStubFor(&hal_fn->wifi_get_iface_name);
+ populateStubFor(&hal_fn->wifi_set_iface_event_handler);
+ populateStubFor(&hal_fn->wifi_reset_iface_event_handler);
+ populateStubFor(&hal_fn->wifi_start_gscan);
+ populateStubFor(&hal_fn->wifi_stop_gscan);
+ populateStubFor(&hal_fn->wifi_get_cached_gscan_results);
+ populateStubFor(&hal_fn->wifi_set_bssid_hotlist);
+ populateStubFor(&hal_fn->wifi_reset_bssid_hotlist);
+ populateStubFor(&hal_fn->wifi_set_significant_change_handler);
+ populateStubFor(&hal_fn->wifi_reset_significant_change_handler);
+ populateStubFor(&hal_fn->wifi_get_gscan_capabilities);
+ populateStubFor(&hal_fn->wifi_set_link_stats);
+ populateStubFor(&hal_fn->wifi_get_link_stats);
+ populateStubFor(&hal_fn->wifi_clear_link_stats);
+ populateStubFor(&hal_fn->wifi_get_valid_channels);
+ populateStubFor(&hal_fn->wifi_rtt_range_request);
+ populateStubFor(&hal_fn->wifi_rtt_range_cancel);
+ populateStubFor(&hal_fn->wifi_get_rtt_capabilities);
+ populateStubFor(&hal_fn->wifi_rtt_get_responder_info);
+ populateStubFor(&hal_fn->wifi_enable_responder);
+ populateStubFor(&hal_fn->wifi_disable_responder);
+ populateStubFor(&hal_fn->wifi_set_nodfs_flag);
+ populateStubFor(&hal_fn->wifi_start_logging);
+ populateStubFor(&hal_fn->wifi_set_epno_list);
+ populateStubFor(&hal_fn->wifi_reset_epno_list);
+ populateStubFor(&hal_fn->wifi_set_country_code);
+ populateStubFor(&hal_fn->wifi_get_firmware_memory_dump);
+ populateStubFor(&hal_fn->wifi_set_log_handler);
+ populateStubFor(&hal_fn->wifi_reset_log_handler);
+ populateStubFor(&hal_fn->wifi_set_alert_handler);
+ populateStubFor(&hal_fn->wifi_reset_alert_handler);
+ populateStubFor(&hal_fn->wifi_get_firmware_version);
+ populateStubFor(&hal_fn->wifi_get_ring_buffers_status);
+ populateStubFor(&hal_fn->wifi_get_logger_supported_feature_set);
+ populateStubFor(&hal_fn->wifi_get_ring_data);
+ populateStubFor(&hal_fn->wifi_enable_tdls);
+ populateStubFor(&hal_fn->wifi_disable_tdls);
+ populateStubFor(&hal_fn->wifi_get_tdls_status);
+ populateStubFor(&hal_fn->wifi_get_tdls_capabilities);
+ populateStubFor(&hal_fn->wifi_get_driver_version);
+ populateStubFor(&hal_fn->wifi_set_passpoint_list);
+ populateStubFor(&hal_fn->wifi_reset_passpoint_list);
+ populateStubFor(&hal_fn->wifi_set_lci);
+ populateStubFor(&hal_fn->wifi_set_lcr);
+ populateStubFor(&hal_fn->wifi_start_sending_offloaded_packet);
+ populateStubFor(&hal_fn->wifi_stop_sending_offloaded_packet);
+ populateStubFor(&hal_fn->wifi_start_rssi_monitoring);
+ populateStubFor(&hal_fn->wifi_stop_rssi_monitoring);
+ populateStubFor(&hal_fn->wifi_get_wake_reason_stats);
+ populateStubFor(&hal_fn->wifi_configure_nd_offload);
+ populateStubFor(&hal_fn->wifi_get_driver_memory_dump);
+ populateStubFor(&hal_fn->wifi_start_pkt_fate_monitoring);
+ populateStubFor(&hal_fn->wifi_get_tx_pkt_fates);
+ populateStubFor(&hal_fn->wifi_get_rx_pkt_fates);
+ populateStubFor(&hal_fn->wifi_nan_enable_request);
+ populateStubFor(&hal_fn->wifi_nan_disable_request);
+ populateStubFor(&hal_fn->wifi_nan_publish_request);
+ populateStubFor(&hal_fn->wifi_nan_publish_cancel_request);
+ populateStubFor(&hal_fn->wifi_nan_subscribe_request);
+ populateStubFor(&hal_fn->wifi_nan_subscribe_cancel_request);
+ populateStubFor(&hal_fn->wifi_nan_transmit_followup_request);
+ populateStubFor(&hal_fn->wifi_nan_stats_request);
+ populateStubFor(&hal_fn->wifi_nan_config_request);
+ populateStubFor(&hal_fn->wifi_nan_tca_request);
+ populateStubFor(&hal_fn->wifi_nan_beacon_sdf_payload_request);
+ populateStubFor(&hal_fn->wifi_nan_register_handler);
+ populateStubFor(&hal_fn->wifi_nan_get_version);
+ populateStubFor(&hal_fn->wifi_nan_get_capabilities);
+ populateStubFor(&hal_fn->wifi_nan_data_interface_create);
+ populateStubFor(&hal_fn->wifi_nan_data_interface_delete);
+ populateStubFor(&hal_fn->wifi_nan_data_request_initiator);
+ populateStubFor(&hal_fn->wifi_nan_data_indication_response);
+ populateStubFor(&hal_fn->wifi_nan_data_end);
+ populateStubFor(&hal_fn->wifi_get_packet_filter_capabilities);
+ populateStubFor(&hal_fn->wifi_set_packet_filter);
+ populateStubFor(&hal_fn->wifi_read_packet_filter);
+ populateStubFor(&hal_fn->wifi_get_roaming_capabilities);
+ populateStubFor(&hal_fn->wifi_enable_firmware_roaming);
+ populateStubFor(&hal_fn->wifi_configure_roaming);
+ populateStubFor(&hal_fn->wifi_select_tx_power_scenario);
+ populateStubFor(&hal_fn->wifi_reset_tx_power_scenario);
+ populateStubFor(&hal_fn->wifi_set_radio_mode_change_handler);
+ populateStubFor(&hal_fn->wifi_set_latency_mode);
+ populateStubFor(&hal_fn->wifi_set_thermal_mitigation_mode);
+ populateStubFor(&hal_fn->wifi_virtual_interface_create);
+ populateStubFor(&hal_fn->wifi_virtual_interface_delete);
+ populateStubFor(&hal_fn->wifi_map_dscp_access_category);
+ populateStubFor(&hal_fn->wifi_reset_dscp_mapping);
+ populateStubFor(&hal_fn->wifi_set_subsystem_restart_handler);
+ populateStubFor(&hal_fn->wifi_get_supported_iface_name);
+ populateStubFor(&hal_fn->wifi_early_initialize);
+ populateStubFor(&hal_fn->wifi_get_chip_feature_set);
+ populateStubFor(&hal_fn->wifi_multi_sta_set_primary_connection);
+ populateStubFor(&hal_fn->wifi_multi_sta_set_use_case);
+ populateStubFor(&hal_fn->wifi_set_coex_unsafe_channels);
+ populateStubFor(&hal_fn->wifi_set_voip_mode);
+ populateStubFor(&hal_fn->wifi_twt_register_handler);
+ populateStubFor(&hal_fn->wifi_twt_get_capability);
+ populateStubFor(&hal_fn->wifi_twt_setup_request);
+ populateStubFor(&hal_fn->wifi_twt_teardown_request);
+ populateStubFor(&hal_fn->wifi_twt_info_frame_request);
+ populateStubFor(&hal_fn->wifi_twt_get_stats);
+ populateStubFor(&hal_fn->wifi_twt_clear_stats);
+ populateStubFor(&hal_fn->wifi_set_dtim_config);
+ populateStubFor(&hal_fn->wifi_get_usable_channels);
+ populateStubFor(&hal_fn->wifi_trigger_subsystem_restart);
+ populateStubFor(&hal_fn->wifi_set_indoor_state);
+ populateStubFor(&hal_fn->wifi_get_supported_radio_combinations_matrix);
+ populateStubFor(&hal_fn->wifi_nan_rtt_chre_enable_request);
+ populateStubFor(&hal_fn->wifi_nan_rtt_chre_disable_request);
+ populateStubFor(&hal_fn->wifi_chre_register_handler);
+ populateStubFor(&hal_fn->wifi_enable_tx_power_limits);
+ populateStubFor(&hal_fn->wifi_get_cached_scan_results);
+ return true;
+}
+
+} // namespace legacy_hal
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_legacy_hal_stubs.h b/wifi/aidl/default/wifi_legacy_hal_stubs.h
new file mode 100644
index 0000000..603ecf2
--- /dev/null
+++ b/wifi/aidl/default/wifi_legacy_hal_stubs.h
@@ -0,0 +1,35 @@
+/*
+ * 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 WIFI_LEGACY_HAL_STUBS_H_
+#define WIFI_LEGACY_HAL_STUBS_H_
+
+#include <hardware_legacy/wifi_hal.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace legacy_hal {
+
+bool initHalFuncTableWithStubs(wifi_hal_fn* hal_fn);
+} // namespace legacy_hal
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_LEGACY_HAL_STUBS_H_
diff --git a/wifi/aidl/default/wifi_mode_controller.cpp b/wifi/aidl/default/wifi_mode_controller.cpp
new file mode 100644
index 0000000..07cb072
--- /dev/null
+++ b/wifi/aidl/default/wifi_mode_controller.cpp
@@ -0,0 +1,88 @@
+/*
+ * 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 "wifi_mode_controller.h"
+
+#include <android-base/logging.h>
+#include <android-base/macros.h>
+#include <private/android_filesystem_config.h>
+
+namespace {
+using aidl::android::hardware::wifi::IfaceType;
+using android::wifi_hal::DriverTool;
+
+int convertIfaceTypeToFirmwareMode(IfaceType type) {
+ int mode;
+ switch (type) {
+ case IfaceType::AP:
+ mode = DriverTool::kFirmwareModeAp;
+ break;
+ case IfaceType::P2P:
+ mode = DriverTool::kFirmwareModeP2p;
+ break;
+ case IfaceType::NAN_IFACE:
+ // NAN is exposed in STA mode currently.
+ mode = DriverTool::kFirmwareModeSta;
+ break;
+ case IfaceType::STA:
+ mode = DriverTool::kFirmwareModeSta;
+ break;
+ }
+ return mode;
+}
+} // namespace
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace mode_controller {
+
+WifiModeController::WifiModeController() : driver_tool_(new DriverTool) {}
+
+bool WifiModeController::isFirmwareModeChangeNeeded(IfaceType type) {
+ return driver_tool_->IsFirmwareModeChangeNeeded(convertIfaceTypeToFirmwareMode(type));
+}
+
+bool WifiModeController::initialize() {
+ if (!driver_tool_->LoadDriver()) {
+ LOG(ERROR) << "Failed to load WiFi driver";
+ return false;
+ }
+ return true;
+}
+
+bool WifiModeController::changeFirmwareMode(IfaceType type) {
+ if (!driver_tool_->ChangeFirmwareMode(convertIfaceTypeToFirmwareMode(type))) {
+ LOG(ERROR) << "Failed to change firmware mode";
+ return false;
+ }
+ return true;
+}
+
+bool WifiModeController::deinitialize() {
+ if (!driver_tool_->UnloadDriver()) {
+ LOG(ERROR) << "Failed to unload WiFi driver";
+ return false;
+ }
+ return true;
+}
+
+} // namespace mode_controller
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_mode_controller.h b/wifi/aidl/default/wifi_mode_controller.h
new file mode 100644
index 0000000..1a9fb1a
--- /dev/null
+++ b/wifi/aidl/default/wifi_mode_controller.h
@@ -0,0 +1,59 @@
+/*
+ * 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 WIFI_MODE_CONTROLLER_H_
+#define WIFI_MODE_CONTROLLER_H_
+
+#include <aidl/android/hardware/wifi/IWifi.h>
+#include <wifi_hal/driver_tool.h>
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+namespace mode_controller {
+
+/**
+ * Class that encapsulates all firmware mode configuration.
+ * This class will perform the necessary firmware reloads to put the chip in the
+ * required state (essentially a wrapper over DriverTool).
+ */
+class WifiModeController {
+ public:
+ WifiModeController();
+ virtual ~WifiModeController() = default;
+
+ // Checks if a firmware mode change is necessary to support the specified
+ // iface type operations.
+ virtual bool isFirmwareModeChangeNeeded(IfaceType type);
+ virtual bool initialize();
+ // Change the firmware mode to support the specified iface type operations.
+ virtual bool changeFirmwareMode(IfaceType type);
+ // Unload the driver. This should be invoked whenever |IWifi.stop()| is
+ // invoked.
+ virtual bool deinitialize();
+
+ private:
+ std::unique_ptr<::android::wifi_hal::DriverTool> driver_tool_;
+};
+
+} // namespace mode_controller
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_MODE_CONTROLLER_H_
diff --git a/wifi/aidl/default/wifi_nan_iface.cpp b/wifi/aidl/default/wifi_nan_iface.cpp
new file mode 100644
index 0000000..9edef09
--- /dev/null
+++ b/wifi/aidl/default/wifi_nan_iface.cpp
@@ -0,0 +1,751 @@
+/*
+ * 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 "wifi_nan_iface.h"
+
+#include <android-base/logging.h>
+
+#include "aidl_return_util.h"
+#include "aidl_struct_util.h"
+#include "wifi_status_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+using aidl_return_util::validateAndCall;
+
+WifiNanIface::WifiNanIface(const std::string& ifname, bool is_dedicated_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
+ : ifname_(ifname),
+ is_dedicated_iface_(is_dedicated_iface),
+ legacy_hal_(legacy_hal),
+ iface_util_(iface_util),
+ is_valid_(true) {}
+
+std::shared_ptr<WifiNanIface> WifiNanIface::create(
+ const std::string& ifname, bool is_dedicated_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util) {
+ std::shared_ptr<WifiNanIface> ptr = ndk::SharedRefBase::make<WifiNanIface>(
+ ifname, is_dedicated_iface, legacy_hal, iface_util);
+ if (is_dedicated_iface) {
+ // If using a dedicated iface, set the iface up first.
+ if (!iface_util.lock()->setUpState(ifname, true)) {
+ // Fatal failure, invalidate the iface object.
+ ptr->invalidate();
+ return nullptr;
+ }
+ }
+ std::weak_ptr<WifiNanIface> weak_ptr_this(ptr);
+ ptr->setWeakPtr(weak_ptr_this);
+ ptr->registerCallbackHandlers();
+ return ptr;
+}
+
+void WifiNanIface::registerCallbackHandlers() {
+ // Register all the callbacks here. These should be valid for the lifetime
+ // of the object. Whenever the mode changes legacy HAL will remove
+ // all of these callbacks.
+ legacy_hal::NanCallbackHandlers callback_handlers;
+ std::weak_ptr<WifiNanIface> weak_ptr_this = weak_ptr_this_;
+
+ // Callback for response.
+ callback_handlers.on_notify_response = [weak_ptr_this](legacy_hal::transaction_id id,
+ const legacy_hal::NanResponseMsg& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanStatus nanStatus;
+ if (!aidl_struct_util::convertLegacyNanResponseHeaderToAidl(msg, &nanStatus)) {
+ LOG(ERROR) << "Failed to convert nan response header";
+ return;
+ }
+
+ switch (msg.response_type) {
+ case legacy_hal::NAN_RESPONSE_ENABLED: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyEnableResponse(id, nanStatus).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_RESPONSE_DISABLED: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyDisableResponse(id, nanStatus).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_RESPONSE_PUBLISH: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyStartPublishResponse(id, nanStatus,
+ msg.body.publish_response.publish_id)
+ .isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_RESPONSE_PUBLISH_CANCEL: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyStopPublishResponse(id, nanStatus).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_RESPONSE_TRANSMIT_FOLLOWUP: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyTransmitFollowupResponse(id, nanStatus).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_RESPONSE_SUBSCRIBE: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyStartSubscribeResponse(
+ id, nanStatus, msg.body.subscribe_response.subscribe_id)
+ .isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_RESPONSE_SUBSCRIBE_CANCEL: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyStopSubscribeResponse(id, nanStatus).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_RESPONSE_CONFIG: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyConfigResponse(id, nanStatus).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_GET_CAPABILITIES: {
+ NanCapabilities aidl_struct;
+ if (!aidl_struct_util::convertLegacyNanCapabilitiesResponseToAidl(
+ msg.body.nan_capabilities, &aidl_struct)) {
+ LOG(ERROR) << "Failed to convert nan capabilities response";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyCapabilitiesResponse(id, nanStatus, aidl_struct).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_DP_INTERFACE_CREATE: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyCreateDataInterfaceResponse(id, nanStatus).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_DP_INTERFACE_DELETE: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyDeleteDataInterfaceResponse(id, nanStatus).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_DP_INITIATOR_RESPONSE: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyInitiateDataPathResponse(
+ id, nanStatus,
+ msg.body.data_request_response.ndp_instance_id)
+ .isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_DP_RESPONDER_RESPONSE: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyRespondToDataPathIndicationResponse(id, nanStatus)
+ .isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_DP_END: {
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->notifyTerminateDataPathResponse(id, nanStatus).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ break;
+ }
+ case legacy_hal::NAN_RESPONSE_BEACON_SDF_PAYLOAD:
+ /* fall through */
+ case legacy_hal::NAN_RESPONSE_TCA:
+ /* fall through */
+ case legacy_hal::NAN_RESPONSE_STATS:
+ /* fall through */
+ case legacy_hal::NAN_RESPONSE_ERROR:
+ /* fall through */
+ default:
+ LOG(ERROR) << "Unknown or unhandled response type: " << msg.response_type;
+ return;
+ }
+ };
+
+ callback_handlers.on_event_disc_eng_event = [weak_ptr_this](
+ const legacy_hal::NanDiscEngEventInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanClusterEventInd aidl_struct;
+ // event types defined identically - hence can be cast
+ aidl_struct.eventType = (NanClusterEventType)msg.event_type;
+ aidl_struct.addr = std::array<uint8_t, 6>();
+ std::copy(msg.data.mac_addr.addr, msg.data.mac_addr.addr + 6, std::begin(aidl_struct.addr));
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventClusterEvent(aidl_struct).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_disabled = [weak_ptr_this](const legacy_hal::NanDisabledInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanStatus status;
+ aidl_struct_util::convertToNanStatus(msg.reason, msg.nan_reason, sizeof(msg.nan_reason),
+ &status);
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventDisabled(status).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_publish_terminated =
+ [weak_ptr_this](const legacy_hal::NanPublishTerminatedInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanStatus status;
+ aidl_struct_util::convertToNanStatus(msg.reason, msg.nan_reason,
+ sizeof(msg.nan_reason), &status);
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventPublishTerminated(msg.publish_id, status).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_subscribe_terminated =
+ [weak_ptr_this](const legacy_hal::NanSubscribeTerminatedInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanStatus status;
+ aidl_struct_util::convertToNanStatus(msg.reason, msg.nan_reason,
+ sizeof(msg.nan_reason), &status);
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventSubscribeTerminated(msg.subscribe_id, status).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_match = [weak_ptr_this](const legacy_hal::NanMatchInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanMatchInd aidl_struct;
+ if (!aidl_struct_util::convertLegacyNanMatchIndToAidl(msg, &aidl_struct)) {
+ LOG(ERROR) << "Failed to convert nan capabilities response";
+ return;
+ }
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventMatch(aidl_struct).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_match_expired = [weak_ptr_this](
+ const legacy_hal::NanMatchExpiredInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventMatchExpired(msg.publish_subscribe_id, msg.requestor_instance_id)
+ .isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_followup = [weak_ptr_this](const legacy_hal::NanFollowupInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanFollowupReceivedInd aidl_struct;
+ if (!aidl_struct_util::convertLegacyNanFollowupIndToAidl(msg, &aidl_struct)) {
+ LOG(ERROR) << "Failed to convert nan capabilities response";
+ return;
+ }
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventFollowupReceived(aidl_struct).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_transmit_follow_up =
+ [weak_ptr_this](const legacy_hal::NanTransmitFollowupInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanStatus status;
+ aidl_struct_util::convertToNanStatus(msg.reason, msg.nan_reason,
+ sizeof(msg.nan_reason), &status);
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventTransmitFollowup(msg.id, status).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_data_path_request =
+ [weak_ptr_this](const legacy_hal::NanDataPathRequestInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanDataPathRequestInd aidl_struct;
+ if (!aidl_struct_util::convertLegacyNanDataPathRequestIndToAidl(msg,
+ &aidl_struct)) {
+ LOG(ERROR) << "Failed to convert nan capabilities response";
+ return;
+ }
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventDataPathRequest(aidl_struct).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_data_path_confirm =
+ [weak_ptr_this](const legacy_hal::NanDataPathConfirmInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanDataPathConfirmInd aidl_struct;
+ if (!aidl_struct_util::convertLegacyNanDataPathConfirmIndToAidl(msg,
+ &aidl_struct)) {
+ LOG(ERROR) << "Failed to convert nan capabilities response";
+ return;
+ }
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventDataPathConfirm(aidl_struct).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ callback_handlers.on_event_data_path_end =
+ [weak_ptr_this](const legacy_hal::NanDataPathEndInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ for (int i = 0; i < msg.num_ndp_instances; ++i) {
+ if (!callback->eventDataPathTerminated(msg.ndp_instance_id[i]).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ }
+ };
+
+ callback_handlers.on_event_beacon_sdf_payload =
+ [](const legacy_hal::NanBeaconSdfPayloadInd& /* msg */) {
+ LOG(ERROR) << "on_event_beacon_sdf_payload - should not be called";
+ };
+
+ callback_handlers.on_event_range_request = [](const legacy_hal::NanRangeRequestInd& /* msg */) {
+ LOG(ERROR) << "on_event_range_request - should not be called";
+ };
+
+ callback_handlers.on_event_range_report = [](const legacy_hal::NanRangeReportInd& /* msg */) {
+ LOG(ERROR) << "on_event_range_report - should not be called";
+ };
+
+ callback_handlers.on_event_schedule_update =
+ [weak_ptr_this](const legacy_hal::NanDataPathScheduleUpdateInd& msg) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ NanDataPathScheduleUpdateInd aidl_struct;
+ if (!aidl_struct_util::convertLegacyNanDataPathScheduleUpdateIndToAidl(
+ msg, &aidl_struct)) {
+ LOG(ERROR) << "Failed to convert nan capabilities response";
+ return;
+ }
+
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventDataPathScheduleUpdate(aidl_struct).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanRegisterCallbackHandlers(ifname_, callback_handlers);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to register nan callbacks. Invalidating object";
+ invalidate();
+ }
+
+ // Register for iface state toggle events.
+ iface_util::IfaceEventHandlers event_handlers = {};
+ event_handlers.on_state_toggle_off_on = [weak_ptr_this](const std::string& /* iface_name */) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ // Tell framework that NAN has been disabled.
+ NanStatus status = {NanStatusCode::UNSUPPORTED_CONCURRENCY_NAN_DISABLED, ""};
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->eventDisabled(status).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+ iface_util_.lock()->registerIfaceEventHandlers(ifname_, event_handlers);
+}
+
+void WifiNanIface::setWeakPtr(std::weak_ptr<WifiNanIface> ptr) {
+ weak_ptr_this_ = ptr;
+}
+
+void WifiNanIface::invalidate() {
+ if (!isValid()) {
+ return;
+ }
+ // send commands to HAL to actually disable and destroy interfaces
+ legacy_hal_.lock()->nanDisableRequest(ifname_, 0xFFFF);
+ legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFE, "aware_data0");
+ legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, 0xFFFD, "aware_data1");
+ iface_util_.lock()->unregisterIfaceEventHandlers(ifname_);
+ legacy_hal_.reset();
+ event_cb_handler_.invalidate();
+ is_valid_ = false;
+ if (is_dedicated_iface_) {
+ // If using a dedicated iface, set the iface down.
+ iface_util_.lock()->setUpState(ifname_, false);
+ }
+}
+
+bool WifiNanIface::isValid() {
+ return is_valid_;
+}
+
+std::string WifiNanIface::getName() {
+ return ifname_;
+}
+
+std::set<std::shared_ptr<IWifiNanIfaceEventCallback>> WifiNanIface::getEventCallbacks() {
+ LOG(ERROR) << "Using original getEventCallbacks";
+ return event_cb_handler_.getCallbacks();
+}
+
+ndk::ScopedAStatus WifiNanIface::getName(std::string* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::getNameInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiNanIface::registerEventCallback(
+ const std::shared_ptr<IWifiNanIfaceEventCallback>& callback) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::registerEventCallbackInternal, callback);
+}
+
+ndk::ScopedAStatus WifiNanIface::getCapabilitiesRequest(char16_t in_cmdId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::getCapabilitiesRequestInternal, in_cmdId);
+}
+
+ndk::ScopedAStatus WifiNanIface::enableRequest(char16_t in_cmdId, const NanEnableRequest& in_msg1,
+ const NanConfigRequestSupplemental& in_msg2) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::enableRequestInternal, in_cmdId, in_msg1, in_msg2);
+}
+
+ndk::ScopedAStatus WifiNanIface::configRequest(char16_t in_cmdId, const NanConfigRequest& in_msg1,
+ const NanConfigRequestSupplemental& in_msg2) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::configRequestInternal, in_cmdId, in_msg1, in_msg2);
+}
+
+ndk::ScopedAStatus WifiNanIface::disableRequest(char16_t in_cmdId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::disableRequestInternal, in_cmdId);
+}
+
+ndk::ScopedAStatus WifiNanIface::startPublishRequest(char16_t in_cmdId,
+ const NanPublishRequest& in_msg) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::startPublishRequestInternal, in_cmdId, in_msg);
+}
+
+ndk::ScopedAStatus WifiNanIface::stopPublishRequest(char16_t in_cmdId, int8_t in_sessionId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::stopPublishRequestInternal, in_cmdId, in_sessionId);
+}
+
+ndk::ScopedAStatus WifiNanIface::startSubscribeRequest(char16_t in_cmdId,
+ const NanSubscribeRequest& in_msg) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::startSubscribeRequestInternal, in_cmdId, in_msg);
+}
+
+ndk::ScopedAStatus WifiNanIface::stopSubscribeRequest(char16_t in_cmdId, int8_t in_sessionId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::stopSubscribeRequestInternal, in_cmdId, in_sessionId);
+}
+
+ndk::ScopedAStatus WifiNanIface::transmitFollowupRequest(char16_t in_cmdId,
+ const NanTransmitFollowupRequest& in_msg) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::transmitFollowupRequestInternal, in_cmdId, in_msg);
+}
+
+ndk::ScopedAStatus WifiNanIface::createDataInterfaceRequest(char16_t in_cmdId,
+ const std::string& in_ifaceName) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::createDataInterfaceRequestInternal, in_cmdId,
+ in_ifaceName);
+}
+
+ndk::ScopedAStatus WifiNanIface::deleteDataInterfaceRequest(char16_t in_cmdId,
+ const std::string& in_ifaceName) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::deleteDataInterfaceRequestInternal, in_cmdId,
+ in_ifaceName);
+}
+
+ndk::ScopedAStatus WifiNanIface::initiateDataPathRequest(char16_t in_cmdId,
+ const NanInitiateDataPathRequest& in_msg) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::initiateDataPathRequestInternal, in_cmdId, in_msg);
+}
+
+ndk::ScopedAStatus WifiNanIface::respondToDataPathIndicationRequest(
+ char16_t in_cmdId, const NanRespondToDataPathIndicationRequest& in_msg) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::respondToDataPathIndicationRequestInternal, in_cmdId,
+ in_msg);
+}
+
+ndk::ScopedAStatus WifiNanIface::terminateDataPathRequest(char16_t in_cmdId,
+ int32_t in_ndpInstanceId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiNanIface::terminateDataPathRequestInternal, in_cmdId,
+ in_ndpInstanceId);
+}
+
+std::pair<std::string, ndk::ScopedAStatus> WifiNanIface::getNameInternal() {
+ return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiNanIface::registerEventCallbackInternal(
+ const std::shared_ptr<IWifiNanIfaceEventCallback>& callback) {
+ if (!event_cb_handler_.addCallback(callback)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WifiNanIface::getCapabilitiesRequestInternal(char16_t cmd_id) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanGetCapabilities(ifname_, cmd_id);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiNanIface::enableRequestInternal(char16_t cmd_id,
+ const NanEnableRequest& msg1,
+ const NanConfigRequestSupplemental& msg2) {
+ legacy_hal::NanEnableRequest legacy_msg;
+ if (!aidl_struct_util::convertAidlNanEnableRequestToLegacy(msg1, msg2, &legacy_msg)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanEnableRequest(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiNanIface::configRequestInternal(char16_t cmd_id,
+ const NanConfigRequest& msg1,
+ const NanConfigRequestSupplemental& msg2) {
+ legacy_hal::NanConfigRequest legacy_msg;
+ if (!aidl_struct_util::convertAidlNanConfigRequestToLegacy(msg1, msg2, &legacy_msg)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanConfigRequest(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiNanIface::disableRequestInternal(char16_t cmd_id) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->nanDisableRequest(ifname_, cmd_id);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiNanIface::startPublishRequestInternal(char16_t cmd_id,
+ const NanPublishRequest& msg) {
+ legacy_hal::NanPublishRequest legacy_msg;
+ if (!aidl_struct_util::convertAidlNanPublishRequestToLegacy(msg, &legacy_msg)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanPublishRequest(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiNanIface::stopPublishRequestInternal(char16_t cmd_id, int8_t sessionId) {
+ legacy_hal::NanPublishCancelRequest legacy_msg;
+ legacy_msg.publish_id = sessionId;
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanPublishCancelRequest(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiNanIface::startSubscribeRequestInternal(char16_t cmd_id,
+ const NanSubscribeRequest& msg) {
+ legacy_hal::NanSubscribeRequest legacy_msg;
+ if (!aidl_struct_util::convertAidlNanSubscribeRequestToLegacy(msg, &legacy_msg)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanSubscribeRequest(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiNanIface::stopSubscribeRequestInternal(char16_t cmd_id, int8_t sessionId) {
+ legacy_hal::NanSubscribeCancelRequest legacy_msg;
+ legacy_msg.subscribe_id = sessionId;
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanSubscribeCancelRequest(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiNanIface::transmitFollowupRequestInternal(
+ char16_t cmd_id, const NanTransmitFollowupRequest& msg) {
+ legacy_hal::NanTransmitFollowupRequest legacy_msg;
+ if (!aidl_struct_util::convertAidlNanTransmitFollowupRequestToLegacy(msg, &legacy_msg)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanTransmitFollowupRequest(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiNanIface::createDataInterfaceRequestInternal(char16_t cmd_id,
+ const std::string& iface_name) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanDataInterfaceCreate(ifname_, cmd_id, iface_name);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+ndk::ScopedAStatus WifiNanIface::deleteDataInterfaceRequestInternal(char16_t cmd_id,
+ const std::string& iface_name) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanDataInterfaceDelete(ifname_, cmd_id, iface_name);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+ndk::ScopedAStatus WifiNanIface::initiateDataPathRequestInternal(
+ char16_t cmd_id, const NanInitiateDataPathRequest& msg) {
+ legacy_hal::NanDataPathInitiatorRequest legacy_msg;
+ if (!aidl_struct_util::convertAidlNanDataPathInitiatorRequestToLegacy(msg, &legacy_msg)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanDataRequestInitiator(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+ndk::ScopedAStatus WifiNanIface::respondToDataPathIndicationRequestInternal(
+ char16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg) {
+ legacy_hal::NanDataPathIndicationResponse legacy_msg;
+ if (!aidl_struct_util::convertAidlNanDataPathIndicationResponseToLegacy(msg, &legacy_msg)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanDataIndicationResponse(ifname_, cmd_id, legacy_msg);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+ndk::ScopedAStatus WifiNanIface::terminateDataPathRequestInternal(char16_t cmd_id,
+ int32_t ndpInstanceId) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->nanDataEnd(ifname_, cmd_id, ndpInstanceId);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_nan_iface.h b/wifi/aidl/default/wifi_nan_iface.h
new file mode 100644
index 0000000..1018905
--- /dev/null
+++ b/wifi/aidl/default/wifi_nan_iface.h
@@ -0,0 +1,134 @@
+/*
+ * 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 WIFI_NAN_IFACE_H_
+#define WIFI_NAN_IFACE_H_
+
+#include <aidl/android/hardware/wifi/BnWifiNanIface.h>
+#include <aidl/android/hardware/wifi/IWifiNanIfaceEventCallback.h>
+#include <android-base/macros.h>
+
+#include "aidl_callback_util.h"
+#include "wifi_iface_util.h"
+#include "wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+/**
+ * AIDL interface object used to control a NAN Iface instance.
+ */
+class WifiNanIface : public BnWifiNanIface {
+ public:
+ WifiNanIface(const std::string& ifname, bool is_dedicated_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
+
+ // Factory method - use instead of default constructor.
+ static std::shared_ptr<WifiNanIface> create(
+ const std::string& ifname, bool is_dedicated_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
+
+ // Refer to |WifiChip::invalidate()|.
+ void invalidate();
+ bool isValid();
+ std::string getName();
+
+ // AIDL methods exposed.
+ ndk::ScopedAStatus getName(std::string* _aidl_return) override;
+ ndk::ScopedAStatus registerEventCallback(
+ const std::shared_ptr<IWifiNanIfaceEventCallback>& in_callback) override;
+ ndk::ScopedAStatus getCapabilitiesRequest(char16_t in_cmdId) override;
+ ndk::ScopedAStatus enableRequest(char16_t in_cmdId, const NanEnableRequest& in_msg1,
+ const NanConfigRequestSupplemental& in_msg2) override;
+ ndk::ScopedAStatus configRequest(char16_t in_cmdId, const NanConfigRequest& in_msg1,
+ const NanConfigRequestSupplemental& in_msg2) override;
+ ndk::ScopedAStatus disableRequest(char16_t in_cmdId) override;
+ ndk::ScopedAStatus startPublishRequest(char16_t in_cmdId,
+ const NanPublishRequest& in_msg) override;
+ ndk::ScopedAStatus stopPublishRequest(char16_t in_cmdId, int8_t in_sessionId) override;
+ ndk::ScopedAStatus startSubscribeRequest(char16_t in_cmdId,
+ const NanSubscribeRequest& in_msg) override;
+ ndk::ScopedAStatus stopSubscribeRequest(char16_t in_cmdId, int8_t in_sessionId) override;
+ ndk::ScopedAStatus transmitFollowupRequest(char16_t in_cmdId,
+ const NanTransmitFollowupRequest& in_msg) override;
+ ndk::ScopedAStatus createDataInterfaceRequest(char16_t in_cmdId,
+ const std::string& in_ifaceName) override;
+ ndk::ScopedAStatus deleteDataInterfaceRequest(char16_t in_cmdId,
+ const std::string& in_ifaceName) override;
+ ndk::ScopedAStatus initiateDataPathRequest(char16_t in_cmdId,
+ const NanInitiateDataPathRequest& in_msg) override;
+ ndk::ScopedAStatus respondToDataPathIndicationRequest(
+ char16_t in_cmdId, const NanRespondToDataPathIndicationRequest& in_msg) override;
+ ndk::ScopedAStatus terminateDataPathRequest(char16_t in_cmdId,
+ int32_t in_ndpInstanceId) override;
+
+ protected:
+ // Accessible to child class in the gTest suite.
+ void setWeakPtr(std::weak_ptr<WifiNanIface> ptr);
+ void registerCallbackHandlers();
+
+ private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<std::string, ndk::ScopedAStatus> getNameInternal();
+ ndk::ScopedAStatus registerEventCallbackInternal(
+ const std::shared_ptr<IWifiNanIfaceEventCallback>& callback);
+ ndk::ScopedAStatus getCapabilitiesRequestInternal(char16_t cmd_id);
+ ndk::ScopedAStatus enableRequestInternal(char16_t cmd_id, const NanEnableRequest& msg1,
+ const NanConfigRequestSupplemental& msg2);
+ ndk::ScopedAStatus configRequestInternal(char16_t cmd_id, const NanConfigRequest& msg1,
+ const NanConfigRequestSupplemental& msg2);
+ ndk::ScopedAStatus disableRequestInternal(char16_t cmd_id);
+ ndk::ScopedAStatus startPublishRequestInternal(char16_t cmd_id, const NanPublishRequest& msg);
+ ndk::ScopedAStatus stopPublishRequestInternal(char16_t cmd_id, int8_t sessionId);
+ ndk::ScopedAStatus startSubscribeRequestInternal(char16_t cmd_id,
+ const NanSubscribeRequest& msg);
+ ndk::ScopedAStatus stopSubscribeRequestInternal(char16_t cmd_id, int8_t sessionId);
+ ndk::ScopedAStatus transmitFollowupRequestInternal(char16_t cmd_id,
+ const NanTransmitFollowupRequest& msg);
+ ndk::ScopedAStatus createDataInterfaceRequestInternal(char16_t cmd_id,
+ const std::string& iface_name);
+ ndk::ScopedAStatus deleteDataInterfaceRequestInternal(char16_t cmd_id,
+ const std::string& iface_name);
+ ndk::ScopedAStatus initiateDataPathRequestInternal(char16_t cmd_id,
+ const NanInitiateDataPathRequest& msg);
+ ndk::ScopedAStatus respondToDataPathIndicationRequestInternal(
+ char16_t cmd_id, const NanRespondToDataPathIndicationRequest& msg);
+ ndk::ScopedAStatus terminateDataPathRequestInternal(char16_t cmd_id, int32_t ndpInstanceId);
+
+ // Overridden in the gTest suite.
+ virtual std::set<std::shared_ptr<IWifiNanIfaceEventCallback>> getEventCallbacks();
+
+ std::string ifname_;
+ bool is_dedicated_iface_;
+ std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
+ bool is_valid_;
+ std::weak_ptr<WifiNanIface> weak_ptr_this_;
+ aidl_callback_util::AidlCallbackHandler<IWifiNanIfaceEventCallback> event_cb_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiNanIface);
+};
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_NAN_IFACE_H_
diff --git a/wifi/aidl/default/wifi_p2p_iface.cpp b/wifi/aidl/default/wifi_p2p_iface.cpp
new file mode 100644
index 0000000..48ec6d6
--- /dev/null
+++ b/wifi/aidl/default/wifi_p2p_iface.cpp
@@ -0,0 +1,59 @@
+/*
+ * 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 "wifi_p2p_iface.h"
+
+#include <android-base/logging.h>
+
+#include "aidl_return_util.h"
+#include "wifi_status_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+using aidl_return_util::validateAndCall;
+
+WifiP2pIface::WifiP2pIface(const std::string& ifname,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+ : ifname_(ifname), legacy_hal_(legacy_hal), is_valid_(true) {}
+
+void WifiP2pIface::invalidate() {
+ legacy_hal_.reset();
+ is_valid_ = false;
+}
+
+bool WifiP2pIface::isValid() {
+ return is_valid_;
+}
+
+std::string WifiP2pIface::getName() {
+ return ifname_;
+}
+
+ndk::ScopedAStatus WifiP2pIface::getName(std::string* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiP2pIface::getNameInternal, _aidl_return);
+}
+
+std::pair<std::string, ndk::ScopedAStatus> WifiP2pIface::getNameInternal() {
+ return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_p2p_iface.h b/wifi/aidl/default/wifi_p2p_iface.h
new file mode 100644
index 0000000..d17470e
--- /dev/null
+++ b/wifi/aidl/default/wifi_p2p_iface.h
@@ -0,0 +1,61 @@
+/*
+ * 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 WIFI_P2P_IFACE_H_
+#define WIFI_P2P_IFACE_H_
+
+#include <aidl/android/hardware/wifi/BnWifiP2pIface.h>
+#include <android-base/macros.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+/**
+ * AIDL interface object used to control a P2P Iface instance.
+ */
+class WifiP2pIface : public BnWifiP2pIface {
+ public:
+ WifiP2pIface(const std::string& ifname,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+ // Refer to |WifiChip::invalidate()|.
+ void invalidate();
+ bool isValid();
+ std::string getName();
+
+ // AIDL methods exposed.
+ ndk::ScopedAStatus getName(std::string* _aidl_return) override;
+
+ private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<std::string, ndk::ScopedAStatus> getNameInternal();
+
+ std::string ifname_;
+ std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ bool is_valid_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiP2pIface);
+};
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_P2P_IFACE_H_
diff --git a/wifi/aidl/default/wifi_rtt_controller.cpp b/wifi/aidl/default/wifi_rtt_controller.cpp
new file mode 100644
index 0000000..856c3cd
--- /dev/null
+++ b/wifi/aidl/default/wifi_rtt_controller.cpp
@@ -0,0 +1,255 @@
+/*
+ * 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 "wifi_rtt_controller.h"
+
+#include <android-base/logging.h>
+
+#include "aidl_return_util.h"
+#include "aidl_struct_util.h"
+#include "wifi_status_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+using aidl_return_util::validateAndCall;
+
+WifiRttController::WifiRttController(const std::string& iface_name,
+ const std::shared_ptr<IWifiStaIface>& bound_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal)
+ : ifname_(iface_name), bound_iface_(bound_iface), legacy_hal_(legacy_hal), is_valid_(true) {}
+
+std::shared_ptr<WifiRttController> WifiRttController::create(
+ const std::string& iface_name, const std::shared_ptr<IWifiStaIface>& bound_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal) {
+ std::shared_ptr<WifiRttController> ptr =
+ ndk::SharedRefBase::make<WifiRttController>(iface_name, bound_iface, legacy_hal);
+ std::weak_ptr<WifiRttController> weak_ptr_this(ptr);
+ ptr->setWeakPtr(weak_ptr_this);
+ return ptr;
+}
+
+void WifiRttController::invalidate() {
+ legacy_hal_.reset();
+ event_callbacks_.clear();
+ is_valid_ = false;
+};
+
+bool WifiRttController::isValid() {
+ return is_valid_;
+}
+
+void WifiRttController::setWeakPtr(std::weak_ptr<WifiRttController> ptr) {
+ weak_ptr_this_ = ptr;
+}
+
+std::vector<std::shared_ptr<IWifiRttControllerEventCallback>>
+WifiRttController::getEventCallbacks() {
+ return event_callbacks_;
+}
+
+std::string WifiRttController::getIfaceName() {
+ return ifname_;
+}
+
+ndk::ScopedAStatus WifiRttController::getBoundIface(std::shared_ptr<IWifiStaIface>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::getBoundIfaceInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiRttController::registerEventCallback(
+ const std::shared_ptr<IWifiRttControllerEventCallback>& callback) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::registerEventCallbackInternal, callback);
+}
+
+ndk::ScopedAStatus WifiRttController::rangeRequest(int32_t in_cmdId,
+ const std::vector<RttConfig>& in_rttConfigs) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::rangeRequestInternal, in_cmdId, in_rttConfigs);
+}
+
+ndk::ScopedAStatus WifiRttController::rangeCancel(int32_t in_cmdId,
+ const std::vector<MacAddress>& in_addrs) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::rangeCancelInternal, in_cmdId, in_addrs);
+}
+
+ndk::ScopedAStatus WifiRttController::getCapabilities(RttCapabilities* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::getCapabilitiesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiRttController::setLci(int32_t in_cmdId, const RttLciInformation& in_lci) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::setLciInternal, in_cmdId, in_lci);
+}
+
+ndk::ScopedAStatus WifiRttController::setLcr(int32_t in_cmdId, const RttLcrInformation& in_lcr) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::setLcrInternal, in_cmdId, in_lcr);
+}
+
+ndk::ScopedAStatus WifiRttController::getResponderInfo(RttResponder* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::getResponderInfoInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiRttController::enableResponder(int32_t in_cmdId,
+ const WifiChannelInfo& in_channelHint,
+ int32_t in_maxDurationInSeconds,
+ const RttResponder& in_info) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::enableResponderInternal, in_cmdId, in_channelHint,
+ in_maxDurationInSeconds, in_info);
+}
+
+ndk::ScopedAStatus WifiRttController::disableResponder(int32_t in_cmdId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_RTT_CONTROLLER_INVALID,
+ &WifiRttController::disableResponderInternal, in_cmdId);
+}
+
+std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus>
+WifiRttController::getBoundIfaceInternal() {
+ return {bound_iface_, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiRttController::registerEventCallbackInternal(
+ const std::shared_ptr<IWifiRttControllerEventCallback>& callback) {
+ event_callbacks_.emplace_back(callback);
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus WifiRttController::rangeRequestInternal(
+ int32_t cmd_id, const std::vector<RttConfig>& rtt_configs) {
+ std::vector<legacy_hal::wifi_rtt_config> legacy_configs;
+ if (!aidl_struct_util::convertAidlVectorOfRttConfigToLegacy(rtt_configs, &legacy_configs)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ std::weak_ptr<WifiRttController> weak_ptr_this = weak_ptr_this_;
+ const auto& on_results_callback =
+ [weak_ptr_this](legacy_hal::wifi_request_id id,
+ const std::vector<const legacy_hal::wifi_rtt_result*>& results) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ std::vector<RttResult> aidl_results;
+ if (!aidl_struct_util::convertLegacyVectorOfRttResultToAidl(results,
+ &aidl_results)) {
+ LOG(ERROR) << "Failed to convert rtt results to AIDL structs";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onResults(id, aidl_results).isOk()) {
+ LOG(ERROR) << "Failed to invoke the callback";
+ }
+ }
+ };
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRttRangeRequest(
+ ifname_, cmd_id, legacy_configs, on_results_callback);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiRttController::rangeCancelInternal(int32_t cmd_id,
+ const std::vector<MacAddress>& addrs) {
+ std::vector<std::array<uint8_t, ETH_ALEN>> legacy_addrs;
+ for (const auto& addr : addrs) {
+ std::array<uint8_t, ETH_ALEN> addr_array;
+ std::copy_n(addr.data.begin(), ETH_ALEN, addr_array.begin());
+ legacy_addrs.push_back(addr_array);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->cancelRttRangeRequest(ifname_, cmd_id, legacy_addrs);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<RttCapabilities, ndk::ScopedAStatus> WifiRttController::getCapabilitiesInternal() {
+ legacy_hal::wifi_error legacy_status;
+ legacy_hal::wifi_rtt_capabilities legacy_caps;
+ std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRttCapabilities(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {RttCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ RttCapabilities aidl_caps;
+ if (!aidl_struct_util::convertLegacyRttCapabilitiesToAidl(legacy_caps, &aidl_caps)) {
+ return {RttCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_caps, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiRttController::setLciInternal(int32_t cmd_id, const RttLciInformation& lci) {
+ legacy_hal::wifi_lci_information legacy_lci;
+ if (!aidl_struct_util::convertAidlRttLciInformationToLegacy(lci, &legacy_lci)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->setRttLci(ifname_, cmd_id, legacy_lci);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiRttController::setLcrInternal(int32_t cmd_id, const RttLcrInformation& lcr) {
+ legacy_hal::wifi_lcr_information legacy_lcr;
+ if (!aidl_struct_util::convertAidlRttLcrInformationToLegacy(lcr, &legacy_lcr)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->setRttLcr(ifname_, cmd_id, legacy_lcr);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<RttResponder, ndk::ScopedAStatus> WifiRttController::getResponderInfoInternal() {
+ legacy_hal::wifi_error legacy_status;
+ legacy_hal::wifi_rtt_responder legacy_responder;
+ std::tie(legacy_status, legacy_responder) = legacy_hal_.lock()->getRttResponderInfo(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {RttResponder{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ RttResponder aidl_responder;
+ if (!aidl_struct_util::convertLegacyRttResponderToAidl(legacy_responder, &aidl_responder)) {
+ return {RttResponder{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_responder, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiRttController::enableResponderInternal(int32_t cmd_id,
+ const WifiChannelInfo& channel_hint,
+ int32_t max_duration_seconds,
+ const RttResponder& info) {
+ legacy_hal::wifi_channel_info legacy_channel_info;
+ if (!aidl_struct_util::convertAidlWifiChannelInfoToLegacy(channel_hint, &legacy_channel_info)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_rtt_responder legacy_responder;
+ if (!aidl_struct_util::convertAidlRttResponderToLegacy(info, &legacy_responder)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableRttResponder(
+ ifname_, cmd_id, legacy_channel_info, max_duration_seconds, legacy_responder);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiRttController::disableResponderInternal(int32_t cmd_id) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableRttResponder(ifname_, cmd_id);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_rtt_controller.h b/wifi/aidl/default/wifi_rtt_controller.h
new file mode 100644
index 0000000..db690c3
--- /dev/null
+++ b/wifi/aidl/default/wifi_rtt_controller.h
@@ -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.
+ */
+
+#ifndef WIFI_RTT_CONTROLLER_H_
+#define WIFI_RTT_CONTROLLER_H_
+
+#include <aidl/android/hardware/wifi/BnWifiRttController.h>
+#include <aidl/android/hardware/wifi/IWifiRttControllerEventCallback.h>
+#include <aidl/android/hardware/wifi/IWifiStaIface.h>
+#include <android-base/macros.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+/**
+ * AIDL interface object used to control all RTT operations.
+ */
+class WifiRttController : public BnWifiRttController {
+ public:
+ WifiRttController(const std::string& iface_name,
+ const std::shared_ptr<IWifiStaIface>& bound_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+ // Factory method - use instead of default constructor.
+ static std::shared_ptr<WifiRttController> create(
+ const std::string& iface_name, const std::shared_ptr<IWifiStaIface>& bound_iface,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal);
+
+ // Refer to |WifiChip::invalidate()|.
+ void invalidate();
+ bool isValid();
+ std::vector<std::shared_ptr<IWifiRttControllerEventCallback>> getEventCallbacks();
+ std::string getIfaceName();
+
+ // AIDL methods exposed.
+ ndk::ScopedAStatus getBoundIface(std::shared_ptr<IWifiStaIface>* _aidl_return) override;
+ ndk::ScopedAStatus registerEventCallback(
+ const std::shared_ptr<IWifiRttControllerEventCallback>& callback) override;
+ ndk::ScopedAStatus rangeRequest(int32_t in_cmdId,
+ const std::vector<RttConfig>& in_rttConfigs) override;
+ ndk::ScopedAStatus rangeCancel(int32_t in_cmdId,
+ const std::vector<MacAddress>& in_addrs) override;
+ ndk::ScopedAStatus getCapabilities(RttCapabilities* _aidl_return) override;
+ ndk::ScopedAStatus setLci(int32_t in_cmdId, const RttLciInformation& in_lci) override;
+ ndk::ScopedAStatus setLcr(int32_t in_cmdId, const RttLcrInformation& in_lcr) override;
+ ndk::ScopedAStatus getResponderInfo(RttResponder* _aidl_return) override;
+ ndk::ScopedAStatus enableResponder(int32_t in_cmdId, const WifiChannelInfo& in_channelHint,
+ int32_t in_maxDurationInSeconds,
+ const RttResponder& in_info) override;
+ ndk::ScopedAStatus disableResponder(int32_t in_cmdId) override;
+
+ private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<std::shared_ptr<IWifiStaIface>, ndk::ScopedAStatus> getBoundIfaceInternal();
+ ndk::ScopedAStatus registerEventCallbackInternal(
+ const std::shared_ptr<IWifiRttControllerEventCallback>& callback);
+ ndk::ScopedAStatus rangeRequestInternal(int32_t cmd_id,
+ const std::vector<RttConfig>& rtt_configs);
+ ndk::ScopedAStatus rangeCancelInternal(int32_t cmd_id, const std::vector<MacAddress>& addrs);
+ std::pair<RttCapabilities, ndk::ScopedAStatus> getCapabilitiesInternal();
+ ndk::ScopedAStatus setLciInternal(int32_t cmd_id, const RttLciInformation& lci);
+ ndk::ScopedAStatus setLcrInternal(int32_t cmd_id, const RttLcrInformation& lcr);
+ std::pair<RttResponder, ndk::ScopedAStatus> getResponderInfoInternal();
+ ndk::ScopedAStatus enableResponderInternal(int32_t cmd_id, const WifiChannelInfo& channel_hint,
+ int32_t max_duration_seconds,
+ const RttResponder& info);
+ ndk::ScopedAStatus disableResponderInternal(int32_t cmd_id);
+
+ void setWeakPtr(std::weak_ptr<WifiRttController> ptr);
+
+ std::string ifname_;
+ std::shared_ptr<IWifiStaIface> bound_iface_;
+ std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ std::vector<std::shared_ptr<IWifiRttControllerEventCallback>> event_callbacks_;
+ std::weak_ptr<WifiRttController> weak_ptr_this_;
+ bool is_valid_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiRttController);
+};
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_RTT_CONTROLLER_H_
diff --git a/wifi/aidl/default/wifi_sta_iface.cpp b/wifi/aidl/default/wifi_sta_iface.cpp
new file mode 100644
index 0000000..ce90349
--- /dev/null
+++ b/wifi/aidl/default/wifi_sta_iface.cpp
@@ -0,0 +1,558 @@
+/*
+ * 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 "wifi_sta_iface.h"
+
+#include <android-base/logging.h>
+
+#include "aidl_return_util.h"
+#include "aidl_struct_util.h"
+#include "wifi_status_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+using aidl_return_util::validateAndCall;
+
+WifiStaIface::WifiStaIface(const std::string& ifname,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util)
+ : ifname_(ifname), legacy_hal_(legacy_hal), iface_util_(iface_util), is_valid_(true) {
+ // Turn on DFS channel usage for STA iface.
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setDfsFlag(ifname_, true);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ LOG(ERROR) << "Failed to set DFS flag; DFS channels may be unavailable.";
+ }
+}
+
+std::shared_ptr<WifiStaIface> WifiStaIface::create(
+ const std::string& ifname, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util) {
+ std::shared_ptr<WifiStaIface> ptr =
+ ndk::SharedRefBase::make<WifiStaIface>(ifname, legacy_hal, iface_util);
+ std::weak_ptr<WifiStaIface> weak_ptr_this(ptr);
+ ptr->setWeakPtr(weak_ptr_this);
+ return ptr;
+}
+
+void WifiStaIface::invalidate() {
+ legacy_hal_.reset();
+ event_cb_handler_.invalidate();
+ is_valid_ = false;
+}
+
+void WifiStaIface::setWeakPtr(std::weak_ptr<WifiStaIface> ptr) {
+ weak_ptr_this_ = ptr;
+}
+
+bool WifiStaIface::isValid() {
+ return is_valid_;
+}
+
+std::string WifiStaIface::getName() {
+ return ifname_;
+}
+
+std::set<std::shared_ptr<IWifiStaIfaceEventCallback>> WifiStaIface::getEventCallbacks() {
+ return event_cb_handler_.getCallbacks();
+}
+
+ndk::ScopedAStatus WifiStaIface::getName(std::string* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getNameInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::registerEventCallback(
+ const std::shared_ptr<IWifiStaIfaceEventCallback>& in_callback) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::registerEventCallbackInternal, in_callback);
+}
+
+ndk::ScopedAStatus WifiStaIface::getCapabilities(
+ IWifiStaIface::StaIfaceCapabilityMask* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getCapabilitiesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::getApfPacketFilterCapabilities(
+ StaApfPacketFilterCapabilities* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getApfPacketFilterCapabilitiesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::installApfPacketFilter(const std::vector<uint8_t>& in_program) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::installApfPacketFilterInternal, in_program);
+}
+
+ndk::ScopedAStatus WifiStaIface::readApfPacketFilterData(std::vector<uint8_t>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::readApfPacketFilterDataInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::getBackgroundScanCapabilities(
+ StaBackgroundScanCapabilities* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getBackgroundScanCapabilitiesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::getValidFrequenciesForBand(WifiBand in_band,
+ std::vector<int32_t>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getValidFrequenciesForBandInternal, _aidl_return,
+ in_band);
+}
+
+ndk::ScopedAStatus WifiStaIface::startBackgroundScan(int32_t in_cmdId,
+ const StaBackgroundScanParameters& in_params) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::startBackgroundScanInternal, in_cmdId, in_params);
+}
+
+ndk::ScopedAStatus WifiStaIface::stopBackgroundScan(int32_t in_cmdId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::stopBackgroundScanInternal, in_cmdId);
+}
+
+ndk::ScopedAStatus WifiStaIface::enableLinkLayerStatsCollection(bool in_debug) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::enableLinkLayerStatsCollectionInternal, in_debug);
+}
+
+ndk::ScopedAStatus WifiStaIface::disableLinkLayerStatsCollection() {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::disableLinkLayerStatsCollectionInternal);
+}
+
+ndk::ScopedAStatus WifiStaIface::getLinkLayerStats(StaLinkLayerStats* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getLinkLayerStatsInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::startRssiMonitoring(int32_t in_cmdId, int32_t in_maxRssi,
+ int32_t in_minRssi) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::startRssiMonitoringInternal, in_cmdId, in_maxRssi,
+ in_minRssi);
+}
+
+ndk::ScopedAStatus WifiStaIface::stopRssiMonitoring(int32_t in_cmdId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::stopRssiMonitoringInternal, in_cmdId);
+}
+
+ndk::ScopedAStatus WifiStaIface::getRoamingCapabilities(StaRoamingCapabilities* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getRoamingCapabilitiesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::configureRoaming(const StaRoamingConfig& in_config) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::configureRoamingInternal, in_config);
+}
+
+ndk::ScopedAStatus WifiStaIface::setRoamingState(StaRoamingState in_state) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::setRoamingStateInternal, in_state);
+}
+
+ndk::ScopedAStatus WifiStaIface::enableNdOffload(bool in_enable) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::enableNdOffloadInternal, in_enable);
+}
+
+ndk::ScopedAStatus WifiStaIface::startSendingKeepAlivePackets(
+ int32_t in_cmdId, const std::vector<uint8_t>& in_ipPacketData, char16_t in_etherType,
+ const std::array<uint8_t, 6>& in_srcAddress, const std::array<uint8_t, 6>& in_dstAddress,
+ int32_t in_periodInMs) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::startSendingKeepAlivePacketsInternal, in_cmdId,
+ in_ipPacketData, in_etherType, in_srcAddress, in_dstAddress,
+ in_periodInMs);
+}
+
+ndk::ScopedAStatus WifiStaIface::stopSendingKeepAlivePackets(int32_t in_cmdId) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::stopSendingKeepAlivePacketsInternal, in_cmdId);
+}
+
+ndk::ScopedAStatus WifiStaIface::startDebugPacketFateMonitoring() {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::startDebugPacketFateMonitoringInternal);
+}
+
+ndk::ScopedAStatus WifiStaIface::getDebugTxPacketFates(
+ std::vector<WifiDebugTxPacketFateReport>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getDebugTxPacketFatesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::getDebugRxPacketFates(
+ std::vector<WifiDebugRxPacketFateReport>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getDebugRxPacketFatesInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::setMacAddress(const std::array<uint8_t, 6>& in_mac) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::setMacAddressInternal, in_mac);
+}
+
+ndk::ScopedAStatus WifiStaIface::getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::getFactoryMacAddressInternal, _aidl_return);
+}
+
+ndk::ScopedAStatus WifiStaIface::setScanMode(bool in_enable) {
+ return validateAndCall(this, WifiStatusCode::ERROR_WIFI_IFACE_INVALID,
+ &WifiStaIface::setScanModeInternal, in_enable);
+}
+
+std::pair<std::string, ndk::ScopedAStatus> WifiStaIface::getNameInternal() {
+ return {ifname_, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiStaIface::registerEventCallbackInternal(
+ const std::shared_ptr<IWifiStaIfaceEventCallback>& callback) {
+ if (!event_cb_handler_.addCallback(callback)) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<IWifiStaIface::StaIfaceCapabilityMask, ndk::ScopedAStatus>
+WifiStaIface::getCapabilitiesInternal() {
+ legacy_hal::wifi_error legacy_status;
+ uint64_t legacy_feature_set;
+ std::tie(legacy_status, legacy_feature_set) =
+ legacy_hal_.lock()->getSupportedFeatureSet(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {IWifiStaIface::StaIfaceCapabilityMask{},
+ createWifiStatusFromLegacyError(legacy_status)};
+ }
+ uint32_t legacy_logger_feature_set;
+ std::tie(legacy_status, legacy_logger_feature_set) =
+ legacy_hal_.lock()->getLoggerSupportedFeatureSet(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ // some devices don't support querying logger feature set
+ legacy_logger_feature_set = 0;
+ }
+ uint32_t aidl_caps;
+ if (!aidl_struct_util::convertLegacyFeaturesToAidlStaCapabilities(
+ legacy_feature_set, legacy_logger_feature_set, &aidl_caps)) {
+ return {IWifiStaIface::StaIfaceCapabilityMask{},
+ createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {static_cast<IWifiStaIface::StaIfaceCapabilityMask>(aidl_caps),
+ ndk::ScopedAStatus::ok()};
+}
+
+std::pair<StaApfPacketFilterCapabilities, ndk::ScopedAStatus>
+WifiStaIface::getApfPacketFilterCapabilitiesInternal() {
+ legacy_hal::wifi_error legacy_status;
+ legacy_hal::PacketFilterCapabilities legacy_caps;
+ std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getPacketFilterCapabilities(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {StaApfPacketFilterCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ StaApfPacketFilterCapabilities aidl_caps;
+ if (!aidl_struct_util::convertLegacyApfCapabilitiesToAidl(legacy_caps, &aidl_caps)) {
+ return {StaApfPacketFilterCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_caps, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiStaIface::installApfPacketFilterInternal(
+ const std::vector<uint8_t>& program) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->setPacketFilter(ifname_, program);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<std::vector<uint8_t>, ndk::ScopedAStatus>
+WifiStaIface::readApfPacketFilterDataInternal() {
+ const std::pair<legacy_hal::wifi_error, std::vector<uint8_t>> legacy_status_and_data =
+ legacy_hal_.lock()->readApfPacketFilterData(ifname_);
+ return {std::move(legacy_status_and_data.second),
+ createWifiStatusFromLegacyError(legacy_status_and_data.first)};
+}
+
+std::pair<StaBackgroundScanCapabilities, ndk::ScopedAStatus>
+WifiStaIface::getBackgroundScanCapabilitiesInternal() {
+ legacy_hal::wifi_error legacy_status;
+ legacy_hal::wifi_gscan_capabilities legacy_caps;
+ std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getGscanCapabilities(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {StaBackgroundScanCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ StaBackgroundScanCapabilities aidl_caps;
+ if (!aidl_struct_util::convertLegacyGscanCapabilitiesToAidl(legacy_caps, &aidl_caps)) {
+ return {StaBackgroundScanCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_caps, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<int32_t>, ndk::ScopedAStatus>
+WifiStaIface::getValidFrequenciesForBandInternal(WifiBand band) {
+ static_assert(sizeof(WifiChannelWidthInMhz) == sizeof(int32_t), "Size mismatch");
+ legacy_hal::wifi_error legacy_status;
+ std::vector<uint32_t> valid_frequencies;
+ std::tie(legacy_status, valid_frequencies) = legacy_hal_.lock()->getValidFrequenciesForBand(
+ ifname_, aidl_struct_util::convertAidlWifiBandToLegacy(band));
+ return {std::vector<int32_t>(valid_frequencies.begin(), valid_frequencies.end()),
+ createWifiStatusFromLegacyError(legacy_status)};
+}
+
+ndk::ScopedAStatus WifiStaIface::startBackgroundScanInternal(
+ int32_t cmd_id, const StaBackgroundScanParameters& params) {
+ legacy_hal::wifi_scan_cmd_params legacy_params;
+ if (!aidl_struct_util::convertAidlGscanParamsToLegacy(params, &legacy_params)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ std::weak_ptr<WifiStaIface> weak_ptr_this = weak_ptr_this_;
+ const auto& on_failure_callback = [weak_ptr_this](legacy_hal::wifi_request_id id) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onBackgroundScanFailure(id).isOk()) {
+ LOG(ERROR) << "Failed to invoke onBackgroundScanFailure callback";
+ }
+ }
+ };
+ const auto& on_results_callback =
+ [weak_ptr_this](legacy_hal::wifi_request_id id,
+ const std::vector<legacy_hal::wifi_cached_scan_results>& results) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ std::vector<StaScanData> aidl_scan_datas;
+ if (!aidl_struct_util::convertLegacyVectorOfCachedGscanResultsToAidl(
+ results, &aidl_scan_datas)) {
+ LOG(ERROR) << "Failed to convert scan results to AIDL structs";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onBackgroundScanResults(id, aidl_scan_datas).isOk()) {
+ LOG(ERROR) << "Failed to invoke onBackgroundScanResults callback";
+ }
+ }
+ };
+ const auto& on_full_result_callback = [weak_ptr_this](
+ legacy_hal::wifi_request_id id,
+ const legacy_hal::wifi_scan_result* result,
+ uint32_t buckets_scanned) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ StaScanResult aidl_scan_result;
+ if (!aidl_struct_util::convertLegacyGscanResultToAidl(*result, true, &aidl_scan_result)) {
+ LOG(ERROR) << "Failed to convert full scan results to AIDL structs";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onBackgroundFullScanResult(id, buckets_scanned, aidl_scan_result)
+ .isOk()) {
+ LOG(ERROR) << "Failed to invoke onBackgroundFullScanResult callback";
+ }
+ }
+ };
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->startGscan(ifname_, cmd_id, legacy_params, on_failure_callback,
+ on_results_callback, on_full_result_callback);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::stopBackgroundScanInternal(int32_t cmd_id) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopGscan(ifname_, cmd_id);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::enableLinkLayerStatsCollectionInternal(bool debug) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableLinkLayerStats(ifname_, debug);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::disableLinkLayerStatsCollectionInternal() {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->disableLinkLayerStats(ifname_);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<StaLinkLayerStats, ndk::ScopedAStatus> WifiStaIface::getLinkLayerStatsInternal() {
+ legacy_hal::wifi_error legacy_status;
+ legacy_hal::LinkLayerStats legacy_stats;
+ std::tie(legacy_status, legacy_stats) = legacy_hal_.lock()->getLinkLayerStats(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {StaLinkLayerStats{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ StaLinkLayerStats aidl_stats;
+ if (!aidl_struct_util::convertLegacyLinkLayerStatsToAidl(legacy_stats, &aidl_stats)) {
+ return {StaLinkLayerStats{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_stats, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiStaIface::startRssiMonitoringInternal(int32_t cmd_id, int32_t max_rssi,
+ int32_t min_rssi) {
+ std::weak_ptr<WifiStaIface> weak_ptr_this = weak_ptr_this_;
+ const auto& on_threshold_breached_callback =
+ [weak_ptr_this](legacy_hal::wifi_request_id id, std::array<uint8_t, ETH_ALEN> bssid,
+ int8_t rssi) {
+ const auto shared_ptr_this = weak_ptr_this.lock();
+ if (!shared_ptr_this.get() || !shared_ptr_this->isValid()) {
+ LOG(ERROR) << "Callback invoked on an invalid object";
+ return;
+ }
+ for (const auto& callback : shared_ptr_this->getEventCallbacks()) {
+ if (!callback->onRssiThresholdBreached(id, bssid, rssi).isOk()) {
+ LOG(ERROR) << "Failed to invoke onRssiThresholdBreached callback";
+ }
+ }
+ };
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startRssiMonitoring(
+ ifname_, cmd_id, max_rssi, min_rssi, on_threshold_breached_callback);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::stopRssiMonitoringInternal(int32_t cmd_id) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->stopRssiMonitoring(ifname_, cmd_id);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<StaRoamingCapabilities, ndk::ScopedAStatus>
+WifiStaIface::getRoamingCapabilitiesInternal() {
+ legacy_hal::wifi_error legacy_status;
+ legacy_hal::wifi_roaming_capabilities legacy_caps;
+ std::tie(legacy_status, legacy_caps) = legacy_hal_.lock()->getRoamingCapabilities(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {StaRoamingCapabilities{}, createWifiStatusFromLegacyError(legacy_status)};
+ }
+ StaRoamingCapabilities aidl_caps;
+ if (!aidl_struct_util::convertLegacyRoamingCapabilitiesToAidl(legacy_caps, &aidl_caps)) {
+ return {StaRoamingCapabilities{}, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_caps, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiStaIface::configureRoamingInternal(const StaRoamingConfig& config) {
+ legacy_hal::wifi_roaming_config legacy_config;
+ if (!aidl_struct_util::convertAidlRoamingConfigToLegacy(config, &legacy_config)) {
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+ }
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->configureRoaming(ifname_, legacy_config);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::setRoamingStateInternal(StaRoamingState state) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->enableFirmwareRoaming(
+ ifname_, aidl_struct_util::convertAidlRoamingStateToLegacy(state));
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::enableNdOffloadInternal(bool enable) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->configureNdOffload(ifname_, enable);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::startSendingKeepAlivePacketsInternal(
+ int32_t cmd_id, const std::vector<uint8_t>& ip_packet_data, char16_t ether_type,
+ const std::array<uint8_t, 6>& src_address, const std::array<uint8_t, 6>& dst_address,
+ int32_t period_in_ms) {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startSendingOffloadedPacket(
+ ifname_, cmd_id, ether_type, ip_packet_data, src_address, dst_address, period_in_ms);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::stopSendingKeepAlivePacketsInternal(int32_t cmd_id) {
+ legacy_hal::wifi_error legacy_status =
+ legacy_hal_.lock()->stopSendingOffloadedPacket(ifname_, cmd_id);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+ndk::ScopedAStatus WifiStaIface::startDebugPacketFateMonitoringInternal() {
+ legacy_hal::wifi_error legacy_status = legacy_hal_.lock()->startPktFateMonitoring(ifname_);
+ return createWifiStatusFromLegacyError(legacy_status);
+}
+
+std::pair<std::vector<WifiDebugTxPacketFateReport>, ndk::ScopedAStatus>
+WifiStaIface::getDebugTxPacketFatesInternal() {
+ legacy_hal::wifi_error legacy_status;
+ std::vector<legacy_hal::wifi_tx_report> legacy_fates;
+ std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getTxPktFates(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {std::vector<WifiDebugTxPacketFateReport>(),
+ createWifiStatusFromLegacyError(legacy_status)};
+ }
+ std::vector<WifiDebugTxPacketFateReport> aidl_fates;
+ if (!aidl_struct_util::convertLegacyVectorOfDebugTxPacketFateToAidl(legacy_fates,
+ &aidl_fates)) {
+ return {std::vector<WifiDebugTxPacketFateReport>(),
+ createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_fates, ndk::ScopedAStatus::ok()};
+}
+
+std::pair<std::vector<WifiDebugRxPacketFateReport>, ndk::ScopedAStatus>
+WifiStaIface::getDebugRxPacketFatesInternal() {
+ legacy_hal::wifi_error legacy_status;
+ std::vector<legacy_hal::wifi_rx_report> legacy_fates;
+ std::tie(legacy_status, legacy_fates) = legacy_hal_.lock()->getRxPktFates(ifname_);
+ if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+ return {std::vector<WifiDebugRxPacketFateReport>(),
+ createWifiStatusFromLegacyError(legacy_status)};
+ }
+ std::vector<WifiDebugRxPacketFateReport> aidl_fates;
+ if (!aidl_struct_util::convertLegacyVectorOfDebugRxPacketFateToAidl(legacy_fates,
+ &aidl_fates)) {
+ return {std::vector<WifiDebugRxPacketFateReport>(),
+ createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {aidl_fates, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiStaIface::setMacAddressInternal(const std::array<uint8_t, 6>& mac) {
+ bool status = iface_util_.lock()->setMacAddress(ifname_, mac);
+ if (!status) {
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN);
+ }
+ return ndk::ScopedAStatus::ok();
+}
+
+std::pair<std::array<uint8_t, 6>, ndk::ScopedAStatus> WifiStaIface::getFactoryMacAddressInternal() {
+ std::array<uint8_t, 6> mac = iface_util_.lock()->getFactoryMacAddress(ifname_);
+ if (mac[0] == 0 && mac[1] == 0 && mac[2] == 0 && mac[3] == 0 && mac[4] == 0 && mac[5] == 0) {
+ return {mac, createWifiStatus(WifiStatusCode::ERROR_UNKNOWN)};
+ }
+ return {mac, ndk::ScopedAStatus::ok()};
+}
+
+ndk::ScopedAStatus WifiStaIface::setScanModeInternal(bool enable) {
+ // OEM's need to implement this on their devices if needed.
+ LOG(WARNING) << "setScanModeInternal(" << enable << ") not supported";
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED);
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_sta_iface.h b/wifi/aidl/default/wifi_sta_iface.h
new file mode 100644
index 0000000..8ac3470
--- /dev/null
+++ b/wifi/aidl/default/wifi_sta_iface.h
@@ -0,0 +1,154 @@
+/*
+ * 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 WIFI_STA_IFACE_H_
+#define WIFI_STA_IFACE_H_
+
+#include <aidl/android/hardware/wifi/BnWifiStaIface.h>
+#include <aidl/android/hardware/wifi/IWifiStaIfaceEventCallback.h>
+#include <android-base/macros.h>
+
+#include "aidl_callback_util.h"
+#include "wifi_iface_util.h"
+#include "wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+/**
+ * AIDL interface object used to control a STA Iface instance.
+ */
+class WifiStaIface : public BnWifiStaIface {
+ public:
+ WifiStaIface(const std::string& ifname,
+ const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
+
+ // Factory method - use instead of default constructor.
+ static std::shared_ptr<WifiStaIface> create(
+ const std::string& ifname, const std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal,
+ const std::weak_ptr<iface_util::WifiIfaceUtil> iface_util);
+
+ // Refer to |WifiChip::invalidate()|.
+ void invalidate();
+ bool isValid();
+ std::set<std::shared_ptr<IWifiStaIfaceEventCallback>> getEventCallbacks();
+ std::string getName();
+
+ // AIDL methods exposed.
+ ndk::ScopedAStatus getName(std::string* _aidl_return) override;
+ ndk::ScopedAStatus registerEventCallback(
+ const std::shared_ptr<IWifiStaIfaceEventCallback>& in_callback) override;
+ ndk::ScopedAStatus getCapabilities(
+ IWifiStaIface::StaIfaceCapabilityMask* _aidl_return) override;
+ ndk::ScopedAStatus getApfPacketFilterCapabilities(
+ StaApfPacketFilterCapabilities* _aidl_return) override;
+ ndk::ScopedAStatus installApfPacketFilter(const std::vector<uint8_t>& in_program) override;
+ ndk::ScopedAStatus readApfPacketFilterData(std::vector<uint8_t>* _aidl_return) override;
+ ndk::ScopedAStatus getBackgroundScanCapabilities(
+ StaBackgroundScanCapabilities* _aidl_return) override;
+ ndk::ScopedAStatus getValidFrequenciesForBand(WifiBand in_band,
+ std::vector<int32_t>* _aidl_return) override;
+ ndk::ScopedAStatus startBackgroundScan(int32_t in_cmdId,
+ const StaBackgroundScanParameters& in_params) override;
+ ndk::ScopedAStatus stopBackgroundScan(int32_t in_cmdId) override;
+ ndk::ScopedAStatus enableLinkLayerStatsCollection(bool in_debug) override;
+ ndk::ScopedAStatus disableLinkLayerStatsCollection() override;
+ ndk::ScopedAStatus getLinkLayerStats(StaLinkLayerStats* _aidl_return) override;
+ ndk::ScopedAStatus startRssiMonitoring(int32_t in_cmdId, int32_t in_maxRssi,
+ int32_t in_minRssi) override;
+ ndk::ScopedAStatus stopRssiMonitoring(int32_t in_cmdId) override;
+ ndk::ScopedAStatus getRoamingCapabilities(StaRoamingCapabilities* _aidl_return) override;
+ ndk::ScopedAStatus configureRoaming(const StaRoamingConfig& in_config) override;
+ ndk::ScopedAStatus setRoamingState(StaRoamingState in_state) override;
+ ndk::ScopedAStatus enableNdOffload(bool in_enable) override;
+ ndk::ScopedAStatus startSendingKeepAlivePackets(int32_t in_cmdId,
+ const std::vector<uint8_t>& in_ipPacketData,
+ char16_t in_etherType,
+ const std::array<uint8_t, 6>& in_srcAddress,
+ const std::array<uint8_t, 6>& in_dstAddress,
+ int32_t in_periodInMs) override;
+ ndk::ScopedAStatus stopSendingKeepAlivePackets(int32_t in_cmdId) override;
+ ndk::ScopedAStatus startDebugPacketFateMonitoring() override;
+ ndk::ScopedAStatus getDebugTxPacketFates(
+ std::vector<WifiDebugTxPacketFateReport>* _aidl_return) override;
+ ndk::ScopedAStatus getDebugRxPacketFates(
+ std::vector<WifiDebugRxPacketFateReport>* _aidl_return) override;
+ ndk::ScopedAStatus setMacAddress(const std::array<uint8_t, 6>& in_mac) override;
+ ndk::ScopedAStatus getFactoryMacAddress(std::array<uint8_t, 6>* _aidl_return) override;
+ ndk::ScopedAStatus setScanMode(bool in_enable) override;
+
+ private:
+ // Corresponding worker functions for the AIDL methods.
+ std::pair<std::string, ndk::ScopedAStatus> getNameInternal();
+ ndk::ScopedAStatus registerEventCallbackInternal(
+ const std::shared_ptr<IWifiStaIfaceEventCallback>& callback);
+ std::pair<IWifiStaIface::StaIfaceCapabilityMask, ndk::ScopedAStatus> getCapabilitiesInternal();
+ std::pair<StaApfPacketFilterCapabilities, ndk::ScopedAStatus>
+ getApfPacketFilterCapabilitiesInternal();
+ ndk::ScopedAStatus installApfPacketFilterInternal(const std::vector<uint8_t>& program);
+ std::pair<std::vector<uint8_t>, ndk::ScopedAStatus> readApfPacketFilterDataInternal();
+ std::pair<StaBackgroundScanCapabilities, ndk::ScopedAStatus>
+ getBackgroundScanCapabilitiesInternal();
+ std::pair<std::vector<int32_t>, ndk::ScopedAStatus> getValidFrequenciesForBandInternal(
+ WifiBand band);
+ ndk::ScopedAStatus startBackgroundScanInternal(int32_t cmd_id,
+ const StaBackgroundScanParameters& params);
+ ndk::ScopedAStatus stopBackgroundScanInternal(int32_t cmd_id);
+ ndk::ScopedAStatus enableLinkLayerStatsCollectionInternal(bool debug);
+ ndk::ScopedAStatus disableLinkLayerStatsCollectionInternal();
+ std::pair<StaLinkLayerStats, ndk::ScopedAStatus> getLinkLayerStatsInternal();
+ ndk::ScopedAStatus startRssiMonitoringInternal(int32_t cmd_id, int32_t max_rssi,
+ int32_t min_rssi);
+ ndk::ScopedAStatus stopRssiMonitoringInternal(int32_t cmd_id);
+ std::pair<StaRoamingCapabilities, ndk::ScopedAStatus> getRoamingCapabilitiesInternal();
+ ndk::ScopedAStatus configureRoamingInternal(const StaRoamingConfig& config);
+ ndk::ScopedAStatus setRoamingStateInternal(StaRoamingState state);
+ ndk::ScopedAStatus enableNdOffloadInternal(bool enable);
+ ndk::ScopedAStatus startSendingKeepAlivePacketsInternal(
+ int32_t cmd_id, const std::vector<uint8_t>& ip_packet_data, char16_t ether_type,
+ const std::array<uint8_t, 6>& src_address, const std::array<uint8_t, 6>& dst_address,
+ int32_t period_in_ms);
+ ndk::ScopedAStatus stopSendingKeepAlivePacketsInternal(int32_t cmd_id);
+ ndk::ScopedAStatus startDebugPacketFateMonitoringInternal();
+ std::pair<std::vector<WifiDebugTxPacketFateReport>, ndk::ScopedAStatus>
+ getDebugTxPacketFatesInternal();
+ std::pair<std::vector<WifiDebugRxPacketFateReport>, ndk::ScopedAStatus>
+ getDebugRxPacketFatesInternal();
+ ndk::ScopedAStatus setMacAddressInternal(const std::array<uint8_t, 6>& mac);
+ std::pair<std::array<uint8_t, 6>, ndk::ScopedAStatus> getFactoryMacAddressInternal();
+ ndk::ScopedAStatus setScanModeInternal(bool enable);
+
+ void setWeakPtr(std::weak_ptr<WifiStaIface> ptr);
+
+ std::string ifname_;
+ std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
+ std::weak_ptr<iface_util::WifiIfaceUtil> iface_util_;
+ std::weak_ptr<WifiStaIface> weak_ptr_this_;
+ bool is_valid_;
+ aidl_callback_util::AidlCallbackHandler<IWifiStaIfaceEventCallback> event_cb_handler_;
+
+ DISALLOW_COPY_AND_ASSIGN(WifiStaIface);
+};
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_STA_IFACE_H_
diff --git a/wifi/aidl/default/wifi_status_util.cpp b/wifi/aidl/default/wifi_status_util.cpp
new file mode 100644
index 0000000..25ecd71
--- /dev/null
+++ b/wifi/aidl/default/wifi_status_util.cpp
@@ -0,0 +1,106 @@
+/*
+ * 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 "wifi_status_util.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+
+std::string legacyErrorToString(legacy_hal::wifi_error error) {
+ switch (error) {
+ case legacy_hal::WIFI_SUCCESS:
+ return "SUCCESS";
+ case legacy_hal::WIFI_ERROR_UNINITIALIZED:
+ return "UNINITIALIZED";
+ case legacy_hal::WIFI_ERROR_NOT_AVAILABLE:
+ return "NOT_AVAILABLE";
+ case legacy_hal::WIFI_ERROR_NOT_SUPPORTED:
+ return "NOT_SUPPORTED";
+ case legacy_hal::WIFI_ERROR_INVALID_ARGS:
+ return "INVALID_ARGS";
+ case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID:
+ return "INVALID_REQUEST_ID";
+ case legacy_hal::WIFI_ERROR_TIMED_OUT:
+ return "TIMED_OUT";
+ case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS:
+ return "TOO_MANY_REQUESTS";
+ case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY:
+ return "OUT_OF_MEMORY";
+ case legacy_hal::WIFI_ERROR_BUSY:
+ return "BUSY";
+ case legacy_hal::WIFI_ERROR_UNKNOWN:
+ return "UNKNOWN";
+ default:
+ return "UNKNOWN ERROR";
+ }
+}
+
+ndk::ScopedAStatus createWifiStatus(WifiStatusCode code, const std::string& description) {
+ return ndk::ScopedAStatus::fromServiceSpecificErrorWithMessage(static_cast<int32_t>(code),
+ description.c_str());
+}
+
+ndk::ScopedAStatus createWifiStatus(WifiStatusCode code) {
+ return ndk::ScopedAStatus::fromServiceSpecificError(static_cast<int32_t>(code));
+}
+
+ndk::ScopedAStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error,
+ const std::string& desc) {
+ switch (error) {
+ case legacy_hal::WIFI_ERROR_NONE:
+ return ndk::ScopedAStatus::ok();
+
+ case legacy_hal::WIFI_ERROR_UNINITIALIZED:
+ case legacy_hal::WIFI_ERROR_NOT_AVAILABLE:
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE, desc);
+
+ case legacy_hal::WIFI_ERROR_NOT_SUPPORTED:
+ return createWifiStatus(WifiStatusCode::ERROR_NOT_SUPPORTED, desc);
+
+ case legacy_hal::WIFI_ERROR_INVALID_ARGS:
+ case legacy_hal::WIFI_ERROR_INVALID_REQUEST_ID:
+ return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS, desc);
+
+ case legacy_hal::WIFI_ERROR_TIMED_OUT:
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", timed out");
+
+ case legacy_hal::WIFI_ERROR_TOO_MANY_REQUESTS:
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", too many requests");
+
+ case legacy_hal::WIFI_ERROR_OUT_OF_MEMORY:
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, desc + ", out of memory");
+
+ case legacy_hal::WIFI_ERROR_BUSY:
+ return createWifiStatus(WifiStatusCode::ERROR_BUSY);
+
+ case legacy_hal::WIFI_ERROR_UNKNOWN:
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown");
+
+ default:
+ return createWifiStatus(WifiStatusCode::ERROR_UNKNOWN, "unknown error");
+ }
+}
+
+ndk::ScopedAStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error) {
+ return createWifiStatusFromLegacyError(error, "");
+}
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
diff --git a/wifi/aidl/default/wifi_status_util.h b/wifi/aidl/default/wifi_status_util.h
new file mode 100644
index 0000000..633811d
--- /dev/null
+++ b/wifi/aidl/default/wifi_status_util.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.
+ */
+
+#ifndef WIFI_STATUS_UTIL_H_
+#define WIFI_STATUS_UTIL_H_
+
+#include <aidl/android/hardware/wifi/IWifi.h>
+
+#include "wifi_legacy_hal.h"
+
+namespace aidl {
+namespace android {
+namespace hardware {
+namespace wifi {
+using ::aidl::android::hardware::wifi::WifiStatusCode;
+
+std::string legacyErrorToString(legacy_hal::wifi_error error);
+ndk::ScopedAStatus createWifiStatus(WifiStatusCode code, const std::string& description);
+ndk::ScopedAStatus createWifiStatus(WifiStatusCode code);
+ndk::ScopedAStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error,
+ const std::string& description);
+ndk::ScopedAStatus createWifiStatusFromLegacyError(legacy_hal::wifi_error error);
+
+} // namespace wifi
+} // namespace hardware
+} // namespace android
+} // namespace aidl
+
+#endif // WIFI_STATUS_UTIL_H_
diff --git a/wifi/aidl/vts/functional/Android.bp b/wifi/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..1277182
--- /dev/null
+++ b/wifi/aidl/vts/functional/Android.bp
@@ -0,0 +1,169 @@
+//
+// 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_test {
+ name: "VtsHalWifiChipTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "wifi_chip_aidl_test.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "VtsHalWifiTargetTestUtil",
+ "android.hardware.wifi-V1-ndk",
+ "libwifi-system-iface",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test {
+ name: "VtsHalWifiStaIfaceTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "wifi_sta_iface_aidl_test.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "VtsHalWifiTargetTestUtil",
+ "android.hardware.wifi-V1-ndk",
+ "libwifi-system-iface",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test {
+ name: "VtsHalWifiApIfaceTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "wifi_ap_iface_aidl_test.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "VtsHalWifiTargetTestUtil",
+ "android.hardware.wifi-V1-ndk",
+ "libwifi-system-iface",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test {
+ name: "VtsHalWifiNanIfaceTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "wifi_nan_iface_aidl_test.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "VtsHalWifiTargetTestUtil",
+ "android.hardware.wifi-V1-ndk",
+ "libwifi-system-iface",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_test {
+ name: "VtsHalWifiRttControllerTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: [
+ "wifi_rtt_controller_aidl_test.cpp",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libvndksupport",
+ ],
+ static_libs: [
+ "VtsHalWifiTargetTestUtil",
+ "android.hardware.wifi-V1-ndk",
+ "libwifi-system-iface",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+}
+
+cc_library_static {
+ name: "VtsHalWifiTargetTestUtil",
+ defaults: ["VtsHalTargetTestDefaults"],
+ srcs: [
+ "wifi_aidl_test_utils.cpp",
+ ],
+ export_include_dirs: [
+ ".",
+ ],
+ shared_libs: [
+ "libbinder",
+ "libbinder_ndk",
+ "libnativehelper",
+ ],
+ static_libs: [
+ "android.hardware.wifi-V1-ndk",
+ "libwifi-system-iface",
+ ],
+}
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
new file mode 100644
index 0000000..6722f36
--- /dev/null
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
@@ -0,0 +1,216 @@
+/*
+ * 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 "wifi_aidl_test_utils.h"
+
+using ::android::wifi_system::InterfaceTool;
+
+namespace {
+bool findAnyModeSupportingConcurrencyType(IfaceConcurrencyType desired_type,
+ const std::vector<IWifiChip::ChipMode>& modes,
+ int* mode_id) {
+ for (const auto& mode : modes) {
+ for (const auto& combination : mode.availableCombinations) {
+ for (const auto& iface_limit : combination.limits) {
+ const auto& iface_types = iface_limit.types;
+ if (std::find(iface_types.begin(), iface_types.end(), desired_type) !=
+ iface_types.end()) {
+ *mode_id = mode.id;
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool configureChipToSupportConcurrencyTypeInternal(const std::shared_ptr<IWifiChip>& wifi_chip,
+ IfaceConcurrencyType type,
+ int* configured_mode_id) {
+ if (!configured_mode_id) {
+ return false;
+ }
+ std::vector<IWifiChip::ChipMode> chip_modes;
+ auto status = wifi_chip->getAvailableModes(&chip_modes);
+ if (!status.isOk()) {
+ return false;
+ }
+ if (!findAnyModeSupportingConcurrencyType(type, chip_modes, configured_mode_id)) {
+ return false;
+ }
+ if (!wifi_chip->configureChip(*configured_mode_id).isOk()) {
+ return false;
+ }
+ return true;
+}
+
+bool configureChipToSupportConcurrencyTypeInternal(const std::shared_ptr<IWifiChip>& wifi_chip,
+ IfaceConcurrencyType type) {
+ int mode_id;
+ return configureChipToSupportConcurrencyTypeInternal(wifi_chip, type, &mode_id);
+}
+} // namespace
+
+bool checkStatusCode(ndk::ScopedAStatus* status, WifiStatusCode expected_code) {
+ if (status == nullptr) {
+ return false;
+ }
+ return status->getServiceSpecificError() == static_cast<int32_t>(expected_code);
+}
+
+std::shared_ptr<IWifi> getWifi(const char* instance_name) {
+ return IWifi::fromBinder(ndk::SpAIBinder(AServiceManager_waitForService(instance_name)));
+}
+
+std::shared_ptr<IWifiChip> getWifiChip(const char* instance_name) {
+ std::shared_ptr<IWifi> wifi = getWifi(instance_name);
+ if (!wifi.get()) {
+ return nullptr;
+ }
+
+ const int retry_interval_ms = 2;
+ const int max_retries = 5;
+ int retry_count = 0;
+ auto status = wifi->start();
+ while (retry_count < max_retries && !status.isOk()) {
+ retry_count++;
+ usleep(retry_interval_ms * 1000);
+ status = wifi->start();
+ }
+ if (!status.isOk()) {
+ return nullptr;
+ }
+
+ std::vector<int> chip_ids = {};
+ status = wifi->getChipIds(&chip_ids);
+ if (!status.isOk() || chip_ids.size() == 0) {
+ return nullptr;
+ }
+ std::shared_ptr<IWifiChip> chip;
+ status = wifi->getChip(chip_ids[0], &chip);
+ if (!status.isOk()) {
+ return nullptr;
+ }
+ return chip;
+}
+
+void setupStaIface(const std::shared_ptr<IWifiStaIface>& iface) {
+ std::string iface_name;
+ auto status = iface->getName(&iface_name);
+ if (status.isOk()) {
+ InterfaceTool iface_tool;
+ iface_tool.SetUpState(iface_name.c_str(), true);
+ }
+}
+
+void setupNanIface(const std::shared_ptr<IWifiNanIface>& iface) {
+ std::string iface_name;
+ auto status = iface->getName(&iface_name);
+ if (status.isOk()) {
+ InterfaceTool iface_tool;
+ iface_tool.SetUpState(iface_name.c_str(), true);
+ }
+}
+
+std::shared_ptr<IWifiStaIface> getWifiStaIface(const char* instance_name) {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(instance_name);
+ if (!wifi_chip.get()) {
+ return nullptr;
+ }
+ if (!configureChipToSupportConcurrencyTypeInternal(wifi_chip, IfaceConcurrencyType::STA)) {
+ return nullptr;
+ }
+ std::shared_ptr<IWifiStaIface> iface;
+ auto status = wifi_chip->createStaIface(&iface);
+ if (!status.isOk()) {
+ return nullptr;
+ }
+ setupStaIface(iface);
+ return iface;
+}
+
+std::shared_ptr<IWifiNanIface> getWifiNanIface(const char* instance_name) {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(instance_name);
+ if (!wifi_chip.get()) {
+ return nullptr;
+ }
+ if (!configureChipToSupportConcurrencyTypeInternal(wifi_chip,
+ IfaceConcurrencyType::NAN_IFACE)) {
+ return nullptr;
+ }
+ std::shared_ptr<IWifiNanIface> iface;
+ auto status = wifi_chip->createNanIface(&iface);
+ if (!status.isOk()) {
+ return nullptr;
+ }
+ setupNanIface(iface);
+ return iface;
+}
+
+std::shared_ptr<IWifiApIface> getWifiApIface(const char* instance_name) {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(instance_name);
+ if (!wifi_chip.get()) {
+ return nullptr;
+ }
+ if (!configureChipToSupportConcurrencyTypeInternal(wifi_chip, IfaceConcurrencyType::AP)) {
+ return nullptr;
+ }
+ std::shared_ptr<IWifiApIface> iface;
+ auto status = wifi_chip->createApIface(&iface);
+ if (!status.isOk()) {
+ return nullptr;
+ }
+ return iface;
+}
+
+std::shared_ptr<IWifiApIface> getBridgedWifiApIface(std::shared_ptr<IWifiChip> wifi_chip) {
+ if (!wifi_chip.get()) {
+ return nullptr;
+ }
+ int mode_id;
+ std::shared_ptr<IWifiApIface> iface;
+ configureChipToSupportConcurrencyTypeInternal(wifi_chip, IfaceConcurrencyType::AP, &mode_id);
+ auto status = wifi_chip->createBridgedApIface(&iface);
+ if (!status.isOk()) {
+ return nullptr;
+ }
+ return iface;
+}
+
+std::shared_ptr<IWifiApIface> getBridgedWifiApIface(const char* instance_name) {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(instance_name);
+ return getBridgedWifiApIface(wifi_chip);
+}
+
+bool configureChipToSupportConcurrencyType(const std::shared_ptr<IWifiChip>& wifi_chip,
+ IfaceConcurrencyType type, int* configured_mode_id) {
+ return configureChipToSupportConcurrencyTypeInternal(wifi_chip, type, configured_mode_id);
+}
+
+void stopWifiService(const char* instance_name) {
+ std::shared_ptr<IWifi> wifi = getWifi(instance_name);
+ if (wifi != nullptr) {
+ wifi->stop();
+ }
+}
+
+int32_t getChipCapabilities(const std::shared_ptr<IWifiChip>& wifi_chip) {
+ IWifiChip::ChipCapabilityMask caps = {};
+ if (wifi_chip->getCapabilities(&caps).isOk()) {
+ return static_cast<int32_t>(caps);
+ }
+ return 0;
+}
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
new file mode 100644
index 0000000..ad16603
--- /dev/null
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
@@ -0,0 +1,48 @@
+/*
+ * 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 <VtsCoreUtil.h>
+
+#include <aidl/android/hardware/wifi/IWifi.h>
+#include <aidl/android/hardware/wifi/IWifiChip.h>
+#include <android/binder_manager.h>
+#include <wifi_system/interface_tool.h>
+
+using aidl::android::hardware::wifi::IfaceConcurrencyType;
+using aidl::android::hardware::wifi::IWifi;
+using aidl::android::hardware::wifi::IWifiApIface;
+using aidl::android::hardware::wifi::IWifiChip;
+using aidl::android::hardware::wifi::IWifiNanIface;
+using aidl::android::hardware::wifi::IWifiStaIface;
+using aidl::android::hardware::wifi::WifiStatusCode;
+
+// Helper functions to obtain references to the various AIDL interface objects.
+std::shared_ptr<IWifi> getWifi(const char* instance_name);
+std::shared_ptr<IWifiChip> getWifiChip(const char* instance_name);
+std::shared_ptr<IWifiStaIface> getWifiStaIface(const char* instance_name);
+std::shared_ptr<IWifiNanIface> getWifiNanIface(const char* instance_name);
+std::shared_ptr<IWifiApIface> getWifiApIface(const char* instance_name);
+std::shared_ptr<IWifiApIface> getBridgedWifiApIface(const char* instance_name);
+std::shared_ptr<IWifiApIface> getBridgedWifiApIface(std::shared_ptr<IWifiChip> wifi_chip);
+// Configure the chip in a mode to support the creation of the provided iface type.
+bool configureChipToSupportConcurrencyType(const std::shared_ptr<IWifiChip>& wifi_chip,
+ IfaceConcurrencyType type, int* configured_mode_id);
+// Used to trigger IWifi.stop() at the end of every test.
+void stopWifiService(const char* instance_name);
+int32_t getChipCapabilities(const std::shared_ptr<IWifiChip>& wifi_chip);
+bool checkStatusCode(ndk::ScopedAStatus* status, WifiStatusCode expected_code);
diff --git a/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp
new file mode 100644
index 0000000..0eaf660
--- /dev/null
+++ b/wifi/aidl/vts/functional/wifi_ap_iface_aidl_test.cpp
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Staache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <vector>
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/BnWifi.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include "wifi_aidl_test_utils.h"
+
+using aidl::android::hardware::wifi::IWifiApIface;
+using aidl::android::hardware::wifi::WifiBand;
+
+class WifiApIfaceAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ isBridgedSupport_ = testing::checkSubstringInCommandOutput(
+ "/system/bin/cmd wifi get-softap-supported-features",
+ "wifi_softap_bridged_ap_supported");
+ stopWifiService(getInstanceName());
+ }
+
+ void TearDown() override { stopWifiService(getInstanceName()); }
+
+ protected:
+ bool isBridgedSupport_ = false;
+ const char* getInstanceName() { return GetParam().c_str(); }
+};
+
+/*
+ * SetMacAddress
+ */
+TEST_P(WifiApIfaceAidlTest, SetMacAddress) {
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+ std::array<uint8_t, 6> mac = {0x12, 0x22, 0x33, 0x52, 0x10, 0x44};
+ EXPECT_TRUE(wifi_ap_iface->setMacAddress(mac).isOk());
+}
+
+/*
+ * SetCountryCode
+ */
+TEST_P(WifiApIfaceAidlTest, SetCountryCode) {
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+ const std::array<uint8_t, 2> country_code = {0x55, 0x53};
+ EXPECT_TRUE(wifi_ap_iface->setCountryCode(country_code).isOk());
+}
+
+/*
+ * GetValidFrequenciesForBand
+ * Ensures that we can retrieve valid frequencies for the 2.4 GHz band.
+ */
+TEST_P(WifiApIfaceAidlTest, GetValidFrequenciesForBand) {
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+ std::vector<int32_t> freqs;
+ EXPECT_TRUE(wifi_ap_iface->getValidFrequenciesForBand(WifiBand::BAND_24GHZ, &freqs).isOk());
+ EXPECT_NE(freqs.size(), 0);
+}
+
+/*
+ * GetFactoryMacAddress
+ */
+TEST_P(WifiApIfaceAidlTest, GetFactoryMacAddress) {
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+ std::array<uint8_t, 6> mac;
+ EXPECT_TRUE(wifi_ap_iface->getFactoryMacAddress(&mac).isOk());
+ std::array<uint8_t, 6> all_zero_mac = {0, 0, 0, 0, 0, 0};
+ EXPECT_NE(mac, all_zero_mac);
+}
+
+/**
+ * GetBridgedInstances - non-bridged mode
+ */
+TEST_P(WifiApIfaceAidlTest, GetBridgedInstances) {
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+ std::vector<std::string> instances;
+ EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances).isOk());
+ EXPECT_EQ(instances.size(), 0);
+}
+
+/**
+ * GetBridgedInstances - bridged AP mode.
+ */
+TEST_P(WifiApIfaceAidlTest, GetBridgedInstances_Bridged) {
+ if (!isBridgedSupport_) {
+ GTEST_SKIP() << "Missing Bridged AP support";
+ }
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+ std::vector<std::string> instances;
+ EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances).isOk());
+ EXPECT_EQ(instances.size(), 2);
+}
+
+/**
+ * ResetToFactoryMacAddress - non-bridged mode
+ */
+TEST_P(WifiApIfaceAidlTest, ResetToFactoryMacAddress) {
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+ EXPECT_TRUE(wifi_ap_iface->resetToFactoryMacAddress().isOk());
+}
+
+/**
+ * ResetToFactoryMacAddress - bridged AP mode
+ */
+TEST_P(WifiApIfaceAidlTest, ResetToFactoryMacAddress_Bridged) {
+ if (!isBridgedSupport_) {
+ GTEST_SKIP() << "Missing Bridged AP support";
+ }
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+ EXPECT_TRUE(wifi_ap_iface->resetToFactoryMacAddress().isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiApIfaceAidlTest);
+INSTANTIATE_TEST_SUITE_P(WifiTest, WifiApIfaceAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ android::ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
new file mode 100644
index 0000000..0806ed2
--- /dev/null
+++ b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
@@ -0,0 +1,889 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Staache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <numeric>
+#include <vector>
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/BnWifi.h>
+#include <aidl/android/hardware/wifi/BnWifiChipEventCallback.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include "wifi_aidl_test_utils.h"
+
+using aidl::android::hardware::wifi::BnWifiChipEventCallback;
+using aidl::android::hardware::wifi::IfaceType;
+using aidl::android::hardware::wifi::IWifiApIface;
+using aidl::android::hardware::wifi::IWifiChip;
+using aidl::android::hardware::wifi::IWifiNanIface;
+using aidl::android::hardware::wifi::IWifiP2pIface;
+using aidl::android::hardware::wifi::IWifiRttController;
+using aidl::android::hardware::wifi::WifiBand;
+using aidl::android::hardware::wifi::WifiDebugHostWakeReasonStats;
+using aidl::android::hardware::wifi::WifiDebugRingBufferStatus;
+using aidl::android::hardware::wifi::WifiDebugRingBufferVerboseLevel;
+using aidl::android::hardware::wifi::WifiIfaceMode;
+using aidl::android::hardware::wifi::WifiRadioCombinationMatrix;
+using aidl::android::hardware::wifi::WifiStatusCode;
+using aidl::android::hardware::wifi::WifiUsableChannel;
+
+class WifiChipAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ stopWifiService(getInstanceName());
+ wifi_chip_ = getWifiChip(getInstanceName());
+ ASSERT_NE(nullptr, wifi_chip_.get());
+ }
+
+ void TearDown() override { stopWifiService(getInstanceName()); }
+
+ protected:
+ int configureChipForConcurrencyType(IfaceConcurrencyType type) {
+ int mode_id;
+ EXPECT_TRUE(configureChipToSupportConcurrencyType(wifi_chip_, type, &mode_id));
+ return mode_id;
+ }
+
+ std::shared_ptr<IWifiStaIface> configureChipForStaAndGetIface() {
+ std::shared_ptr<IWifiStaIface> iface;
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ EXPECT_TRUE(wifi_chip_->createStaIface(&iface).isOk());
+ EXPECT_NE(nullptr, iface.get());
+ return iface;
+ }
+
+ std::shared_ptr<IWifiP2pIface> configureChipForP2pAndGetIface() {
+ std::shared_ptr<IWifiP2pIface> iface;
+ configureChipForConcurrencyType(IfaceConcurrencyType::P2P);
+ EXPECT_TRUE(wifi_chip_->createP2pIface(&iface).isOk());
+ EXPECT_NE(nullptr, iface.get());
+ return iface;
+ }
+
+ std::shared_ptr<IWifiApIface> configureChipForApAndGetIface() {
+ std::shared_ptr<IWifiApIface> iface;
+ configureChipForConcurrencyType(IfaceConcurrencyType::AP);
+ EXPECT_TRUE(wifi_chip_->createApIface(&iface).isOk());
+ EXPECT_NE(nullptr, iface.get());
+ return iface;
+ }
+
+ std::shared_ptr<IWifiNanIface> configureChipForNanAndGetIface() {
+ std::shared_ptr<IWifiNanIface> iface;
+ configureChipForConcurrencyType(IfaceConcurrencyType::NAN_IFACE);
+ EXPECT_TRUE(wifi_chip_->createNanIface(&iface).isOk());
+ EXPECT_NE(nullptr, iface.get());
+ return iface;
+ }
+
+ std::string getStaIfaceName(const std::shared_ptr<IWifiStaIface>& iface) {
+ std::string iface_name;
+ EXPECT_TRUE(iface->getName(&iface_name).isOk());
+ return iface_name;
+ }
+
+ std::string getP2pIfaceName(const std::shared_ptr<IWifiP2pIface>& iface) {
+ std::string iface_name;
+ EXPECT_TRUE(iface->getName(&iface_name).isOk());
+ return iface_name;
+ }
+
+ std::string getApIfaceName(const std::shared_ptr<IWifiApIface>& iface) {
+ std::string iface_name;
+ EXPECT_TRUE(iface->getName(&iface_name).isOk());
+ return iface_name;
+ }
+
+ std::string getNanIfaceName(const std::shared_ptr<IWifiNanIface>& iface) {
+ std::string iface_name;
+ EXPECT_TRUE(iface->getName(&iface_name).isOk());
+ return iface_name;
+ }
+
+ std::vector<std::shared_ptr<IWifiStaIface>> create2StaIfacesIfPossible() {
+ std::shared_ptr<IWifiStaIface> iface1 = configureChipForStaAndGetIface();
+
+ // Try create a create second iface.
+ std::shared_ptr<IWifiStaIface> iface2;
+ bool add_second_success = wifi_chip_->createStaIface(&iface2).isOk();
+ if (!add_second_success) {
+ return {iface1};
+ }
+ EXPECT_NE(nullptr, iface2.get());
+ return {iface1, iface2};
+ }
+
+ bool hasAnyRingBufferCapabilities(int32_t caps) {
+ return caps &
+ (static_cast<int32_t>(
+ IWifiChip::ChipCapabilityMask::DEBUG_RING_BUFFER_CONNECT_EVENT) |
+ static_cast<int32_t>(IWifiChip::ChipCapabilityMask::DEBUG_RING_BUFFER_POWER_EVENT) |
+ static_cast<int32_t>(
+ IWifiChip::ChipCapabilityMask::DEBUG_RING_BUFFER_WAKELOCK_EVENT) |
+ static_cast<int32_t>(IWifiChip::ChipCapabilityMask::DEBUG_RING_BUFFER_VENDOR_DATA));
+ }
+
+ const char* getInstanceName() { return GetParam().c_str(); }
+
+ std::shared_ptr<IWifiChip> wifi_chip_;
+};
+
+class WifiChipEventCallback : public BnWifiChipEventCallback {
+ public:
+ WifiChipEventCallback() = default;
+
+ ::ndk::ScopedAStatus onChipReconfigureFailure(WifiStatusCode /* status */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onChipReconfigured(int /* modeId */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDebugErrorAlert(int /* errorCode */,
+ const std::vector<uint8_t>& /* debugData */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onDebugRingBufferDataAvailable(
+ const WifiDebugRingBufferStatus& /* status */,
+ const std::vector<uint8_t>& /* data */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onIfaceAdded(IfaceType /* type */,
+ const std::string& /* name */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onIfaceRemoved(IfaceType /* type */,
+ const std::string& /* name */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus onRadioModeChange(
+ const std::vector<RadioModeInfo>& /* radioModeInfos */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+};
+
+/*
+ * RegisterEventCallback
+ *
+ * Note: it is not feasible to test the invocation of the callback function,
+ * since events are triggered internally in the HAL implementation and cannot be
+ * triggered from the test case.
+ */
+TEST_P(WifiChipAidlTest, RegisterEventCallback) {
+ std::shared_ptr<WifiChipEventCallback> callback =
+ ndk::SharedRefBase::make<WifiChipEventCallback>();
+ ASSERT_NE(nullptr, callback.get());
+ EXPECT_TRUE(wifi_chip_->registerEventCallback(callback).isOk());
+}
+
+/*
+ * GetCapabilities
+ */
+TEST_P(WifiChipAidlTest, GetCapabilities) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ EXPECT_NE(static_cast<int32_t>(caps), 0);
+}
+
+/*
+ * GetId
+ */
+TEST_P(WifiChipAidlTest, GetId) {
+ int id;
+ EXPECT_TRUE(wifi_chip_->getId(&id).isOk());
+}
+
+/*
+ * GetAvailableModes
+ */
+TEST_P(WifiChipAidlTest, GetAvailableModes) {
+ std::vector<IWifiChip::ChipMode> modes;
+ EXPECT_TRUE(wifi_chip_->getAvailableModes(&modes).isOk());
+ EXPECT_NE(modes.size(), 0);
+}
+
+/*
+ * GetMode
+ */
+TEST_P(WifiChipAidlTest, GetMode) {
+ int expected_mode = configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int retrieved_mode;
+ EXPECT_TRUE(wifi_chip_->getMode(&retrieved_mode).isOk());
+ EXPECT_EQ(retrieved_mode, expected_mode);
+}
+
+/*
+ * GetUsableChannels
+ */
+TEST_P(WifiChipAidlTest, GetUsableChannels) {
+ WifiBand band = WifiBand::BAND_24GHZ_5GHZ_6GHZ;
+ uint32_t ifaceModeMask = static_cast<uint32_t>(WifiIfaceMode::IFACE_MODE_P2P_CLIENT) |
+ static_cast<uint32_t>(WifiIfaceMode::IFACE_MODE_P2P_GO);
+ uint32_t filterMask =
+ static_cast<uint32_t>(IWifiChip::UsableChannelFilter::CELLULAR_COEXISTENCE) |
+ static_cast<uint32_t>(IWifiChip::UsableChannelFilter::CONCURRENCY);
+
+ std::vector<WifiUsableChannel> channels;
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ auto status = wifi_chip_->getUsableChannels(
+ band, static_cast<WifiIfaceMode>(ifaceModeMask),
+ static_cast<IWifiChip::UsableChannelFilter>(filterMask), &channels);
+ if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ GTEST_SKIP() << "getUsableChannels() is not supported by vendor.";
+ }
+ EXPECT_TRUE(status.isOk());
+}
+
+/*
+ * GetSupportedRadioCombinationsMatrix
+ */
+TEST_P(WifiChipAidlTest, GetSupportedRadioCombinationsMatrix) {
+ WifiRadioCombinationMatrix combination_matrix = {};
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ auto status = wifi_chip_->getSupportedRadioCombinationsMatrix(&combination_matrix);
+ if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ GTEST_SKIP() << "Skipping this test since getSupportedRadioCombinationsMatrix() "
+ "is not supported by vendor.";
+ }
+ EXPECT_TRUE(status.isOk());
+}
+
+/*
+ * SetCountryCode
+ */
+TEST_P(WifiChipAidlTest, SetCountryCode) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ std::array<uint8_t, 2> country_code = {0x55, 0x53};
+ EXPECT_TRUE(wifi_chip_->setCountryCode(country_code).isOk());
+}
+
+/*
+ * SetLatencyMode_normal
+ * Tests the setLatencyMode() API with Latency mode NORMAL.
+ */
+TEST_P(WifiChipAidlTest, SetLatencyMode_normal) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ auto status = wifi_chip_->setLatencyMode(IWifiChip::LatencyMode::NORMAL);
+ if (caps & static_cast<int32_t>(IWifiChip::ChipCapabilityMask::SET_LATENCY_MODE)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * SetLatencyMode_low
+ * Tests the setLatencyMode() API with Latency mode LOW.
+ */
+TEST_P(WifiChipAidlTest, SetLatencyMode_low) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ auto status = wifi_chip_->setLatencyMode(IWifiChip::LatencyMode::LOW);
+ if (caps & static_cast<int32_t>(IWifiChip::ChipCapabilityMask::SET_LATENCY_MODE)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * SetMultiStaPrimaryConnection
+ *
+ * Only runs if the device supports 2 STA ifaces.
+ */
+TEST_P(WifiChipAidlTest, SetMultiStaPrimaryConnection) {
+ auto ifaces = create2StaIfacesIfPossible();
+ if (ifaces.size() < 2) {
+ GTEST_SKIP() << "Device does not support more than 1 STA concurrently";
+ }
+
+ auto status = wifi_chip_->setMultiStaPrimaryConnection(getStaIfaceName(ifaces[0]));
+ if (!status.isOk()) {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * SetMultiStaUseCase
+ *
+ * Only runs if the device supports 2 STA ifaces.
+ */
+TEST_P(WifiChipAidlTest, setMultiStaUseCase) {
+ auto ifaces = create2StaIfacesIfPossible();
+ if (ifaces.size() < 2) {
+ GTEST_SKIP() << "Device does not support more than 1 STA concurrently";
+ }
+
+ auto status = wifi_chip_->setMultiStaUseCase(
+ IWifiChip::MultiStaUseCase::DUAL_STA_TRANSIENT_PREFER_PRIMARY);
+ if (!status.isOk()) {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * SetCoexUnsafeChannels
+ */
+TEST_P(WifiChipAidlTest, SetCoexUnsafeChannels) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+
+ // Test with an empty vector of CoexUnsafeChannels.
+ std::vector<IWifiChip::CoexUnsafeChannel> vec;
+ IWifiChip::CoexRestriction restrictions = static_cast<IWifiChip::CoexRestriction>(0);
+ auto status = wifi_chip_->setCoexUnsafeChannels(vec, restrictions);
+ if (!status.isOk()) {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+
+ // Test with a non-empty vector of CoexUnsafeChannels.
+ IWifiChip::CoexUnsafeChannel unsafeChannel24Ghz;
+ unsafeChannel24Ghz.band = WifiBand::BAND_24GHZ;
+ unsafeChannel24Ghz.channel = 6;
+ vec.push_back(unsafeChannel24Ghz);
+ IWifiChip::CoexUnsafeChannel unsafeChannel5Ghz;
+ unsafeChannel5Ghz.band = WifiBand::BAND_5GHZ;
+ unsafeChannel5Ghz.channel = 36;
+ vec.push_back(unsafeChannel5Ghz);
+ restrictions = static_cast<IWifiChip::CoexRestriction>(
+ static_cast<int32_t>(IWifiChip::CoexRestriction::WIFI_AWARE) |
+ static_cast<int32_t>(IWifiChip::CoexRestriction::SOFTAP) |
+ static_cast<int32_t>(IWifiChip::CoexRestriction::WIFI_DIRECT));
+
+ status = wifi_chip_->setCoexUnsafeChannels(vec, restrictions);
+ if (!status.isOk()) {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * SelectTxPowerScenario - Body
+ */
+TEST_P(WifiChipAidlTest, SelectTxPowerScenario_body) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ int32_t expected_caps =
+ static_cast<int32_t>(IWifiChip::ChipCapabilityMask::SET_TX_POWER_LIMIT) |
+ static_cast<int32_t>(IWifiChip::ChipCapabilityMask::USE_BODY_HEAD_SAR);
+ auto status = wifi_chip_->selectTxPowerScenario(IWifiChip::TxPowerScenario::ON_BODY_CELL_OFF);
+ if (caps & expected_caps) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * SelectTxPowerScenario - Voice Call
+ */
+TEST_P(WifiChipAidlTest, SelectTxPowerScenario_voiceCall) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ auto status = wifi_chip_->selectTxPowerScenario(IWifiChip::TxPowerScenario::VOICE_CALL);
+ if (caps & static_cast<int32_t>(IWifiChip::ChipCapabilityMask::SET_TX_POWER_LIMIT)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * ResetTxPowerScenario
+ */
+TEST_P(WifiChipAidlTest, ResetTxPowerScenario) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ auto status = wifi_chip_->resetTxPowerScenario();
+ if (caps & static_cast<int32_t>(IWifiChip::ChipCapabilityMask::SET_TX_POWER_LIMIT)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * ConfigureChip
+ */
+TEST_P(WifiChipAidlTest, ConfigureChip) {
+ std::vector<IWifiChip::ChipMode> modes;
+ EXPECT_TRUE(wifi_chip_->getAvailableModes(&modes).isOk());
+ EXPECT_NE(modes.size(), 0);
+ for (const auto& mode : modes) {
+ // configureChip() requires a fresh IWifiChip object.
+ wifi_chip_ = getWifiChip(getInstanceName());
+ ASSERT_NE(nullptr, wifi_chip_.get());
+ EXPECT_TRUE(wifi_chip_->configureChip(mode.id).isOk());
+ stopWifiService(getInstanceName());
+ // Sleep for 5 milliseconds between each wifi state toggle.
+ usleep(5000);
+ }
+}
+
+/*
+ * RequestChipDebugInfo
+ */
+TEST_P(WifiChipAidlTest, RequestChipDebugInfo) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ IWifiChip::ChipDebugInfo debug_info = {};
+ EXPECT_TRUE(wifi_chip_->requestChipDebugInfo(&debug_info).isOk());
+ EXPECT_NE(debug_info.driverDescription.size(), 0);
+ EXPECT_NE(debug_info.firmwareDescription.size(), 0);
+}
+
+/*
+ * RequestFirmwareDebugDump
+ */
+TEST_P(WifiChipAidlTest, RequestFirmwareDebugDump) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ std::vector<uint8_t> debug_dump;
+ auto status = wifi_chip_->requestFirmwareDebugDump(&debug_dump);
+ if (caps & static_cast<int32_t>(IWifiChip::ChipCapabilityMask::DEBUG_MEMORY_FIRMWARE_DUMP)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * RequestDriverDebugDump
+ */
+TEST_P(WifiChipAidlTest, RequestDriverDebugDump) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ std::vector<uint8_t> debug_dump;
+ auto status = wifi_chip_->requestDriverDebugDump(&debug_dump);
+ if (caps & static_cast<int32_t>(IWifiChip::ChipCapabilityMask::DEBUG_MEMORY_DRIVER_DUMP)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * GetDebugRingBuffersStatus
+ */
+TEST_P(WifiChipAidlTest, GetDebugRingBuffersStatus) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ std::vector<WifiDebugRingBufferStatus> ring_buffer_status;
+ auto status = wifi_chip_->getDebugRingBuffersStatus(&ring_buffer_status);
+ if (hasAnyRingBufferCapabilities(caps)) {
+ EXPECT_TRUE(status.isOk());
+ ASSERT_NE(ring_buffer_status.size(), 0);
+ for (const auto& ring_buffer : ring_buffer_status) {
+ EXPECT_NE(ring_buffer.ringName.size(), 0);
+ }
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * GetDebugHostWakeReasonStats
+ */
+TEST_P(WifiChipAidlTest, GetDebugHostWakeReasonStats) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ WifiDebugHostWakeReasonStats wake_reason_stats = {};
+ auto status = wifi_chip_->getDebugHostWakeReasonStats(&wake_reason_stats);
+ if (caps & static_cast<int32_t>(IWifiChip::ChipCapabilityMask::DEBUG_HOST_WAKE_REASON_STATS)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * StartLoggingToDebugRingBuffer
+ */
+TEST_P(WifiChipAidlTest, StartLoggingToDebugRingBuffer) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ std::string ring_name;
+ std::vector<WifiDebugRingBufferStatus> ring_buffer_status;
+ auto status = wifi_chip_->getDebugRingBuffersStatus(&ring_buffer_status);
+
+ if (hasAnyRingBufferCapabilities(caps)) {
+ EXPECT_TRUE(status.isOk());
+ ASSERT_NE(ring_buffer_status.size(), 0);
+ ring_name = ring_buffer_status[0].ringName;
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+
+ status = wifi_chip_->startLoggingToDebugRingBuffer(
+ ring_name, WifiDebugRingBufferVerboseLevel::VERBOSE, 5, 1024);
+ if (hasAnyRingBufferCapabilities(caps)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * ForceDumpToDebugRingBuffer
+ */
+TEST_P(WifiChipAidlTest, ForceDumpToDebugRingBuffer) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+ int32_t caps = getChipCapabilities(wifi_chip_);
+ std::string ring_name;
+ std::vector<WifiDebugRingBufferStatus> ring_buffer_status;
+ auto status = wifi_chip_->getDebugRingBuffersStatus(&ring_buffer_status);
+
+ if (hasAnyRingBufferCapabilities(caps)) {
+ EXPECT_TRUE(status.isOk());
+ ASSERT_NE(ring_buffer_status.size(), 0);
+ ring_name = ring_buffer_status[0].ringName;
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+
+ status = wifi_chip_->forceDumpToDebugRingBuffer(ring_name);
+ if (hasAnyRingBufferCapabilities(caps)) {
+ EXPECT_TRUE(status.isOk());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/*
+ * CreateStaIface
+ * Configures the chip in STA mode and creates an iface.
+ */
+TEST_P(WifiChipAidlTest, CreateStaIface) {
+ configureChipForStaAndGetIface();
+}
+
+/*
+ * CreateApIface
+ */
+TEST_P(WifiChipAidlTest, CreateApIface) {
+ configureChipForApAndGetIface();
+}
+
+/*
+ * CreateNanIface
+ */
+TEST_P(WifiChipAidlTest, CreateNanIface) {
+ configureChipForNanAndGetIface();
+}
+
+/*
+ * CreateP2pIface
+ */
+TEST_P(WifiChipAidlTest, CreateP2pIface) {
+ configureChipForNanAndGetIface();
+}
+
+/*
+ * GetStaIfaceNames
+ * Configures the chip in STA mode and ensures that the iface name list is
+ * empty before creating the iface. Then create the iface and ensure that
+ * iface name is returned in the iface name list.
+ */
+TEST_P(WifiChipAidlTest, GetStaIfaceNames) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+
+ std::vector<std::string> iface_names;
+ EXPECT_TRUE(wifi_chip_->getP2pIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 0);
+
+ std::shared_ptr<IWifiStaIface> iface;
+ EXPECT_TRUE(wifi_chip_->createStaIface(&iface).isOk());
+ ASSERT_NE(nullptr, iface.get());
+
+ std::string iface_name = getStaIfaceName(iface);
+ EXPECT_TRUE(wifi_chip_->getStaIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 1);
+ EXPECT_EQ(iface_name, iface_names[0]);
+
+ EXPECT_TRUE(wifi_chip_->removeStaIface(iface_name).isOk());
+ EXPECT_TRUE(wifi_chip_->getStaIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 0);
+}
+
+/*
+ * GetP2pIfaceNames
+ */
+TEST_P(WifiChipAidlTest, GetP2pIfaceNames) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::P2P);
+
+ std::vector<std::string> iface_names;
+ EXPECT_TRUE(wifi_chip_->getP2pIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 0);
+
+ std::shared_ptr<IWifiP2pIface> iface;
+ EXPECT_TRUE(wifi_chip_->createP2pIface(&iface).isOk());
+ ASSERT_NE(nullptr, iface.get());
+
+ std::string iface_name = getP2pIfaceName(iface);
+ EXPECT_TRUE(wifi_chip_->getP2pIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 1);
+ EXPECT_EQ(iface_name, iface_names[0]);
+
+ EXPECT_TRUE(wifi_chip_->removeP2pIface(iface_name).isOk());
+ EXPECT_TRUE(wifi_chip_->getP2pIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 0);
+}
+
+/*
+ * GetApIfaceNames
+ */
+TEST_P(WifiChipAidlTest, GetApIfaceNames) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::AP);
+
+ std::vector<std::string> iface_names;
+ EXPECT_TRUE(wifi_chip_->getApIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 0);
+
+ std::shared_ptr<IWifiApIface> iface;
+ EXPECT_TRUE(wifi_chip_->createApIface(&iface).isOk());
+ ASSERT_NE(nullptr, iface.get());
+
+ std::string iface_name = getApIfaceName(iface);
+ EXPECT_TRUE(wifi_chip_->getApIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 1);
+ EXPECT_EQ(iface_name, iface_names[0]);
+
+ EXPECT_TRUE(wifi_chip_->removeApIface(iface_name).isOk());
+ EXPECT_TRUE(wifi_chip_->getApIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 0);
+}
+
+/*
+ * GetNanIfaceNames
+ */
+TEST_P(WifiChipAidlTest, GetNanIfaceNames) {
+ configureChipForConcurrencyType(IfaceConcurrencyType::NAN_IFACE);
+
+ std::vector<std::string> iface_names;
+ EXPECT_TRUE(wifi_chip_->getNanIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 0);
+
+ std::shared_ptr<IWifiNanIface> iface;
+ EXPECT_TRUE(wifi_chip_->createNanIface(&iface).isOk());
+ ASSERT_NE(nullptr, iface.get());
+
+ std::string iface_name = getNanIfaceName(iface);
+ EXPECT_TRUE(wifi_chip_->getNanIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 1);
+ EXPECT_EQ(iface_name, iface_names[0]);
+
+ EXPECT_TRUE(wifi_chip_->removeNanIface(iface_name).isOk());
+ EXPECT_TRUE(wifi_chip_->getNanIfaceNames(&iface_names).isOk());
+ EXPECT_EQ(iface_names.size(), 0);
+}
+
+/*
+ * GetStaIface
+ * Configures the chip in STA mode and creates an iface. Then retrieves
+ * the iface object using its name and ensures that any other name
+ * doesn't retrieve a valid iface object.
+ */
+TEST_P(WifiChipAidlTest, GetStaIface) {
+ std::shared_ptr<IWifiStaIface> iface = configureChipForStaAndGetIface();
+ std::string iface_name = getStaIfaceName(iface);
+
+ std::shared_ptr<IWifiStaIface> retrieved_iface;
+ EXPECT_TRUE(wifi_chip_->getStaIface(iface_name, &retrieved_iface).isOk());
+ EXPECT_NE(nullptr, retrieved_iface.get());
+
+ std::string invalid_name = iface_name + "0";
+ std::shared_ptr<IWifiStaIface> invalid_iface;
+ auto status = wifi_chip_->getStaIface(invalid_name, &invalid_iface);
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ EXPECT_EQ(nullptr, invalid_iface.get());
+}
+
+/*
+ * GetP2pIface
+ */
+TEST_P(WifiChipAidlTest, GetP2pIface) {
+ std::shared_ptr<IWifiP2pIface> iface = configureChipForP2pAndGetIface();
+ std::string iface_name = getP2pIfaceName(iface);
+
+ std::shared_ptr<IWifiP2pIface> retrieved_iface;
+ EXPECT_TRUE(wifi_chip_->getP2pIface(iface_name, &retrieved_iface).isOk());
+ EXPECT_NE(nullptr, retrieved_iface.get());
+
+ std::string invalid_name = iface_name + "0";
+ std::shared_ptr<IWifiP2pIface> invalid_iface;
+ auto status = wifi_chip_->getP2pIface(invalid_name, &invalid_iface);
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ EXPECT_EQ(nullptr, invalid_iface.get());
+}
+
+/*
+ * GetApIface
+ */
+TEST_P(WifiChipAidlTest, GetApIface) {
+ std::shared_ptr<IWifiApIface> iface = configureChipForApAndGetIface();
+ std::string iface_name = getApIfaceName(iface);
+
+ std::shared_ptr<IWifiApIface> retrieved_iface;
+ EXPECT_TRUE(wifi_chip_->getApIface(iface_name, &retrieved_iface).isOk());
+ EXPECT_NE(nullptr, retrieved_iface.get());
+
+ std::string invalid_name = iface_name + "0";
+ std::shared_ptr<IWifiApIface> invalid_iface;
+ auto status = wifi_chip_->getApIface(invalid_name, &invalid_iface);
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ EXPECT_EQ(nullptr, invalid_iface.get());
+}
+
+/*
+ * GetNanIface
+ */
+TEST_P(WifiChipAidlTest, GetNanIface) {
+ std::shared_ptr<IWifiNanIface> iface = configureChipForNanAndGetIface();
+ std::string iface_name = getNanIfaceName(iface);
+
+ std::shared_ptr<IWifiNanIface> retrieved_iface;
+ EXPECT_TRUE(wifi_chip_->getNanIface(iface_name, &retrieved_iface).isOk());
+ EXPECT_NE(nullptr, retrieved_iface.get());
+
+ std::string invalid_name = iface_name + "0";
+ std::shared_ptr<IWifiNanIface> invalid_iface;
+ auto status = wifi_chip_->getNanIface(invalid_name, &invalid_iface);
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ EXPECT_EQ(nullptr, invalid_iface.get());
+}
+
+/*
+ * RemoveStaIface
+ * Configures the chip in STA mode and creates an iface. Then removes
+ * the iface object using the correct name and ensures that any other
+ * name doesn't remove the iface.
+ */
+TEST_P(WifiChipAidlTest, RemoveStaIface) {
+ std::shared_ptr<IWifiStaIface> iface = configureChipForStaAndGetIface();
+ std::string iface_name = getStaIfaceName(iface);
+
+ std::string invalid_name = iface_name + "0";
+ auto status = wifi_chip_->removeStaIface(invalid_name);
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ EXPECT_TRUE(wifi_chip_->removeStaIface(iface_name).isOk());
+
+ // No such iface exists now, so this should return failure.
+ EXPECT_FALSE(wifi_chip_->removeStaIface(iface_name).isOk());
+}
+
+/*
+ * RemoveP2pIface
+ */
+TEST_P(WifiChipAidlTest, RemoveP2pIface) {
+ std::shared_ptr<IWifiP2pIface> iface = configureChipForP2pAndGetIface();
+ std::string iface_name = getP2pIfaceName(iface);
+
+ std::string invalid_name = iface_name + "0";
+ auto status = wifi_chip_->removeP2pIface(invalid_name);
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ EXPECT_TRUE(wifi_chip_->removeP2pIface(iface_name).isOk());
+
+ // No such iface exists now, so this should return failure.
+ EXPECT_FALSE(wifi_chip_->removeP2pIface(iface_name).isOk());
+}
+
+/*
+ * RemoveApIface
+ */
+TEST_P(WifiChipAidlTest, RemoveApIface) {
+ std::shared_ptr<IWifiApIface> iface = configureChipForApAndGetIface();
+ std::string iface_name = getApIfaceName(iface);
+
+ std::string invalid_name = iface_name + "0";
+ auto status = wifi_chip_->removeApIface(invalid_name);
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ EXPECT_TRUE(wifi_chip_->removeApIface(iface_name).isOk());
+
+ // No such iface exists now, so this should return failure.
+ EXPECT_FALSE(wifi_chip_->removeApIface(iface_name).isOk());
+}
+
+/*
+ * RemoveNanIface
+ */
+TEST_P(WifiChipAidlTest, RemoveNanIface) {
+ std::shared_ptr<IWifiNanIface> iface = configureChipForNanAndGetIface();
+ std::string iface_name = getNanIfaceName(iface);
+
+ std::string invalid_name = iface_name + "0";
+ auto status = wifi_chip_->removeNanIface(invalid_name);
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ EXPECT_TRUE(wifi_chip_->removeNanIface(iface_name).isOk());
+
+ // No such iface exists now, so this should return failure.
+ EXPECT_FALSE(wifi_chip_->removeNanIface(iface_name).isOk());
+}
+
+/*
+ * CreateRttController
+ */
+TEST_P(WifiChipAidlTest, CreateRttController) {
+ std::shared_ptr<IWifiStaIface> iface = configureChipForStaAndGetIface();
+ std::shared_ptr<IWifiRttController> rtt_controller;
+ auto status = wifi_chip_->createRttController(iface, &rtt_controller);
+ if (status.isOk()) {
+ EXPECT_NE(nullptr, rtt_controller.get());
+ } else {
+ EXPECT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+ }
+}
+
+/**
+ * CreateBridgedApIface & RemoveIfaceInstanceFromBridgedApIface
+ */
+TEST_P(WifiChipAidlTest, CreateBridgedApIfaceAndremoveIfaceInstanceFromBridgedApIfaceTest) {
+ bool isBridgedSupport = testing::checkSubstringInCommandOutput(
+ "/system/bin/cmd wifi get-softap-supported-features",
+ "wifi_softap_bridged_ap_supported");
+ if (!isBridgedSupport) {
+ GTEST_SKIP() << "Missing Bridged AP support";
+ }
+
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
+ ASSERT_NE(nullptr, wifi_chip.get());
+ std::shared_ptr<IWifiApIface> wifi_ap_iface = getBridgedWifiApIface(wifi_chip);
+ ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+ std::string br_name;
+ std::vector<std::string> instances;
+ EXPECT_TRUE(wifi_ap_iface->getName(&br_name).isOk());
+ EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances).isOk());
+ EXPECT_EQ(instances.size(), 2);
+
+ std::vector<std::string> instances_after_remove;
+ EXPECT_TRUE(wifi_chip->removeIfaceInstanceFromBridgedApIface(br_name, instances[0]).isOk());
+ EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances_after_remove).isOk());
+ EXPECT_EQ(instances_after_remove.size(), 1);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipAidlTest);
+INSTANTIATE_TEST_SUITE_P(WifiTest, WifiChipAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ android::ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp
new file mode 100644
index 0000000..457d57a
--- /dev/null
+++ b/wifi/aidl/vts/functional/wifi_nan_iface_aidl_test.cpp
@@ -0,0 +1,627 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Staache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <vector>
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/BnWifi.h>
+#include <aidl/android/hardware/wifi/BnWifiNanIfaceEventCallback.h>
+#include <aidl/android/hardware/wifi/NanBandIndex.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include "wifi_aidl_test_utils.h"
+
+using aidl::android::hardware::wifi::BnWifiNanIfaceEventCallback;
+using aidl::android::hardware::wifi::IWifiNanIface;
+using aidl::android::hardware::wifi::NanBandIndex;
+using aidl::android::hardware::wifi::NanBandSpecificConfig;
+using aidl::android::hardware::wifi::NanCapabilities;
+using aidl::android::hardware::wifi::NanClusterEventInd;
+using aidl::android::hardware::wifi::NanConfigRequest;
+using aidl::android::hardware::wifi::NanConfigRequestSupplemental;
+using aidl::android::hardware::wifi::NanDataPathConfirmInd;
+using aidl::android::hardware::wifi::NanDataPathRequestInd;
+using aidl::android::hardware::wifi::NanDataPathScheduleUpdateInd;
+using aidl::android::hardware::wifi::NanDataPathSecurityType;
+using aidl::android::hardware::wifi::NanEnableRequest;
+using aidl::android::hardware::wifi::NanFollowupReceivedInd;
+using aidl::android::hardware::wifi::NanInitiateDataPathRequest;
+using aidl::android::hardware::wifi::NanMatchAlg;
+using aidl::android::hardware::wifi::NanMatchInd;
+using aidl::android::hardware::wifi::NanPublishRequest;
+using aidl::android::hardware::wifi::NanPublishType;
+using aidl::android::hardware::wifi::NanRespondToDataPathIndicationRequest;
+using aidl::android::hardware::wifi::NanStatus;
+using aidl::android::hardware::wifi::NanStatusCode;
+using aidl::android::hardware::wifi::NanTxType;
+
+#define TIMEOUT_PERIOD 10
+
+class WifiNanIfaceAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ if (!::testing::deviceSupportsFeature("android.hardware.wifi.aware"))
+ GTEST_SKIP() << "Skipping this test since NAN is not supported.";
+ stopWifiService(getInstanceName());
+
+ wifi_nan_iface_ = getWifiNanIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_nan_iface_.get());
+ std::shared_ptr<WifiNanIfaceEventCallback> callback =
+ ndk::SharedRefBase::make<WifiNanIfaceEventCallback>(*this);
+ EXPECT_TRUE(wifi_nan_iface_->registerEventCallback(callback).isOk());
+ }
+
+ void TearDown() override { stopWifiService(getInstanceName()); }
+
+ // Used as a mechanism to inform the test about data/event callbacks.
+ inline void notify() {
+ std::unique_lock<std::mutex> lock(mtx_);
+ count_++;
+ cv_.notify_one();
+ }
+
+ enum CallbackType {
+ INVALID = -2,
+ ANY_CALLBACK = -1,
+
+ NOTIFY_CAPABILITIES_RESPONSE = 0,
+ NOTIFY_ENABLE_RESPONSE,
+ NOTIFY_CONFIG_RESPONSE,
+ NOTIFY_DISABLE_RESPONSE,
+ NOTIFY_START_PUBLISH_RESPONSE,
+ NOTIFY_STOP_PUBLISH_RESPONSE,
+ NOTIFY_START_SUBSCRIBE_RESPONSE,
+ NOTIFY_STOP_SUBSCRIBE_RESPONSE,
+ NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE,
+ NOTIFY_CREATE_DATA_INTERFACE_RESPONSE,
+ NOTIFY_DELETE_DATA_INTERFACE_RESPONSE,
+ NOTIFY_INITIATE_DATA_PATH_RESPONSE,
+ NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE,
+ NOTIFY_TERMINATE_DATA_PATH_RESPONSE,
+
+ EVENT_CLUSTER_EVENT,
+ EVENT_DISABLED,
+ EVENT_PUBLISH_TERMINATED,
+ EVENT_SUBSCRIBE_TERMINATED,
+ EVENT_MATCH,
+ EVENT_MATCH_EXPIRED,
+ EVENT_FOLLOWUP_RECEIVED,
+ EVENT_TRANSMIT_FOLLOWUP,
+ EVENT_DATA_PATH_REQUEST,
+ EVENT_DATA_PATH_CONFIRM,
+ EVENT_DATA_PATH_TERMINATED,
+ EVENT_DATA_PATH_SCHEDULE_UPDATE,
+ };
+
+ // Test code calls this function to wait for data/event callback.
+ // Must set callbackType = INVALID before calling this function.
+ inline std::cv_status wait(CallbackType waitForCallbackType) {
+ std::unique_lock<std::mutex> lock(mtx_);
+ EXPECT_NE(INVALID, waitForCallbackType);
+
+ std::cv_status status = std::cv_status::no_timeout;
+ auto now = std::chrono::system_clock::now();
+ while (count_ == 0) {
+ status = cv_.wait_until(lock, now + std::chrono::seconds(TIMEOUT_PERIOD));
+ if (status == std::cv_status::timeout) return status;
+ if (waitForCallbackType != ANY_CALLBACK && callback_type_ != INVALID &&
+ callback_type_ != waitForCallbackType) {
+ count_--;
+ }
+ }
+ count_--;
+ return status;
+ }
+
+ class WifiNanIfaceEventCallback : public BnWifiNanIfaceEventCallback {
+ public:
+ WifiNanIfaceEventCallback(WifiNanIfaceAidlTest& parent) : parent_(parent){};
+
+ ::ndk::ScopedAStatus eventClusterEvent(const NanClusterEventInd& event) override {
+ parent_.callback_type_ = EVENT_CLUSTER_EVENT;
+ parent_.nan_cluster_event_ind_ = event;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventDataPathConfirm(const NanDataPathConfirmInd& event) override {
+ parent_.callback_type_ = EVENT_DATA_PATH_CONFIRM;
+ parent_.nan_data_path_confirm_ind_ = event;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventDataPathRequest(const NanDataPathRequestInd& event) override {
+ parent_.callback_type_ = EVENT_DATA_PATH_REQUEST;
+ parent_.nan_data_path_request_ind_ = event;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventDataPathScheduleUpdate(
+ const NanDataPathScheduleUpdateInd& event) override {
+ parent_.callback_type_ = EVENT_DATA_PATH_SCHEDULE_UPDATE;
+ parent_.nan_data_path_schedule_update_ind_ = event;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventDataPathTerminated(int32_t ndpInstanceId) override {
+ parent_.callback_type_ = EVENT_DATA_PATH_TERMINATED;
+ parent_.ndp_instance_id_ = ndpInstanceId;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventDisabled(const NanStatus& status) override {
+ parent_.callback_type_ = EVENT_DISABLED;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventFollowupReceived(const NanFollowupReceivedInd& event) override {
+ parent_.callback_type_ = EVENT_FOLLOWUP_RECEIVED;
+ parent_.nan_followup_received_ind_ = event;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventMatch(const NanMatchInd& event) override {
+ parent_.callback_type_ = EVENT_MATCH;
+ parent_.nan_match_ind_ = event;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventMatchExpired(int8_t discoverySessionId, int32_t peerId) override {
+ parent_.callback_type_ = EVENT_MATCH_EXPIRED;
+ parent_.session_id_ = discoverySessionId;
+ parent_.peer_id_ = peerId;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventPublishTerminated(int8_t sessionId,
+ const NanStatus& status) override {
+ parent_.callback_type_ = EVENT_PUBLISH_TERMINATED;
+ parent_.session_id_ = sessionId;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventSubscribeTerminated(int8_t sessionId,
+ const NanStatus& status) override {
+ parent_.callback_type_ = EVENT_SUBSCRIBE_TERMINATED;
+ parent_.session_id_ = sessionId;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus eventTransmitFollowup(char16_t id, const NanStatus& status) override {
+ parent_.callback_type_ = EVENT_TRANSMIT_FOLLOWUP;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyCapabilitiesResponse(
+ char16_t id, const NanStatus& status,
+ const NanCapabilities& capabilities) override {
+ parent_.callback_type_ = NOTIFY_CAPABILITIES_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.capabilities_ = capabilities;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyConfigResponse(char16_t id, const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_CONFIG_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyCreateDataInterfaceResponse(char16_t id,
+ const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_CREATE_DATA_INTERFACE_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyDeleteDataInterfaceResponse(char16_t id,
+ const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_DELETE_DATA_INTERFACE_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyDisableResponse(char16_t id, const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_DISABLE_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyEnableResponse(char16_t id, const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_ENABLE_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyInitiateDataPathResponse(char16_t id, const NanStatus& status,
+ int32_t ndpInstanceId) override {
+ parent_.callback_type_ = NOTIFY_INITIATE_DATA_PATH_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.ndp_instance_id_ = ndpInstanceId;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyRespondToDataPathIndicationResponse(
+ char16_t id, const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_RESPOND_TO_DATA_PATH_INDICATION_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyStartPublishResponse(char16_t id, const NanStatus& status,
+ int8_t sessionId) override {
+ parent_.callback_type_ = NOTIFY_START_PUBLISH_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.session_id_ = sessionId;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyStartSubscribeResponse(char16_t id, const NanStatus& status,
+ int8_t sessionId) override {
+ parent_.callback_type_ = NOTIFY_START_SUBSCRIBE_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.session_id_ = sessionId;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyStopPublishResponse(char16_t id,
+ const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_STOP_PUBLISH_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyStopSubscribeResponse(char16_t id,
+ const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_STOP_SUBSCRIBE_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyTerminateDataPathResponse(char16_t id,
+ const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_TERMINATE_DATA_PATH_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+ ::ndk::ScopedAStatus notifyTransmitFollowupResponse(char16_t id,
+ const NanStatus& status) override {
+ parent_.callback_type_ = NOTIFY_TRANSMIT_FOLLOWUP_RESPONSE;
+ parent_.id_ = id;
+ parent_.status_ = status;
+ parent_.notify();
+ return ndk::ScopedAStatus::ok();
+ }
+
+ private:
+ WifiNanIfaceAidlTest& parent_;
+ };
+
+ protected:
+ std::shared_ptr<IWifiNanIface> wifi_nan_iface_;
+ CallbackType callback_type_;
+ uint16_t id_;
+ uint8_t session_id_;
+ uint32_t ndp_instance_id_;
+ uint32_t peer_id_;
+ NanCapabilities capabilities_;
+ NanClusterEventInd nan_cluster_event_ind_;
+ NanDataPathConfirmInd nan_data_path_confirm_ind_;
+ NanDataPathRequestInd nan_data_path_request_ind_;
+ NanDataPathScheduleUpdateInd nan_data_path_schedule_update_ind_;
+ NanFollowupReceivedInd nan_followup_received_ind_;
+ NanMatchInd nan_match_ind_;
+ NanStatus status_;
+
+ const char* getInstanceName() { return GetParam().c_str(); }
+
+ private:
+ // synchronization objects
+ std::mutex mtx_;
+ std::condition_variable cv_;
+ int count_ = 0;
+};
+
+/*
+ * FailOnIfaceInvalid
+ * Ensure that API calls to an interface fail with code ERROR_WIFI_IFACE_INVALID
+ * after wifi is disabled.
+ */
+TEST_P(WifiNanIfaceAidlTest, FailOnIfaceInvalid) {
+ stopWifiService(getInstanceName());
+ sleep(5); // Ensure that all chips/interfaces are invalidated.
+ auto status = wifi_nan_iface_->getCapabilitiesRequest(0);
+ ASSERT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_WIFI_IFACE_INVALID));
+}
+
+/*
+ * EnableRequest - Invalid Args
+ */
+TEST_P(WifiNanIfaceAidlTest, EnableRequest_InvalidArgs) {
+ uint16_t inputCmdId = 10;
+ callback_type_ = INVALID;
+ NanEnableRequest nanEnableRequest = {};
+ NanConfigRequestSupplemental nanConfigRequestSupp = {};
+ auto status =
+ wifi_nan_iface_->enableRequest(inputCmdId, nanEnableRequest, nanConfigRequestSupp);
+ if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ ASSERT_TRUE(status.isOk());
+
+ // Wait for a callback.
+ ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE));
+ ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callback_type_);
+ ASSERT_EQ(id_, inputCmdId);
+ ASSERT_EQ(status_.status, NanStatusCode::INVALID_ARGS);
+ }
+}
+
+/*
+ * ConfigRequest - Invalid Args
+ */
+TEST_P(WifiNanIfaceAidlTest, ConfigRequest_InvalidArgs) {
+ uint16_t inputCmdId = 10;
+ callback_type_ = INVALID;
+ NanConfigRequest nanConfigRequest = {};
+ NanConfigRequestSupplemental nanConfigRequestSupp = {};
+ auto status =
+ wifi_nan_iface_->configRequest(inputCmdId, nanConfigRequest, nanConfigRequestSupp);
+
+ if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ ASSERT_TRUE(status.isOk());
+
+ // Wait for a callback.
+ ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CONFIG_RESPONSE));
+ ASSERT_EQ(NOTIFY_CONFIG_RESPONSE, callback_type_);
+ ASSERT_EQ(id_, inputCmdId);
+ ASSERT_EQ(status_.status, NanStatusCode::INVALID_ARGS);
+ }
+}
+
+/*
+ * EnableRequest - Invalid Args in Shim Conversion
+ */
+TEST_P(WifiNanIfaceAidlTest, EnableRequest_InvalidShimArgs) {
+ uint16_t inputCmdId = 10;
+ NanEnableRequest nanEnableRequest = {};
+ nanEnableRequest.configParams.numberOfPublishServiceIdsInBeacon = -15; // must be > 0
+ NanConfigRequestSupplemental nanConfigRequestSupp = {};
+ auto status =
+ wifi_nan_iface_->enableRequest(inputCmdId, nanEnableRequest, nanConfigRequestSupp);
+ if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ ASSERT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ }
+}
+
+/*
+ * ConfigRequest - Invalid Args in Shim Conversion
+ */
+TEST_P(WifiNanIfaceAidlTest, ConfigRequest_InvalidShimArgs) {
+ uint16_t inputCmdId = 10;
+ NanConfigRequest nanConfigRequest = {};
+ nanConfigRequest.numberOfPublishServiceIdsInBeacon = -15; // must be > 0
+ NanConfigRequestSupplemental nanConfigRequestSupp = {};
+ auto status =
+ wifi_nan_iface_->configRequest(inputCmdId, nanConfigRequest, nanConfigRequestSupp);
+ if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ ASSERT_TRUE(checkStatusCode(&status, WifiStatusCode::ERROR_INVALID_ARGS));
+ }
+}
+
+/*
+ * NotifyCapabilitiesResponse
+ */
+TEST_P(WifiNanIfaceAidlTest, NotifyCapabilitiesResponse) {
+ uint16_t inputCmdId = 10;
+ callback_type_ = INVALID;
+ EXPECT_TRUE(wifi_nan_iface_->getCapabilitiesRequest(inputCmdId).isOk());
+
+ // Wait for a callback.
+ ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_CAPABILITIES_RESPONSE));
+ ASSERT_EQ(NOTIFY_CAPABILITIES_RESPONSE, callback_type_);
+ ASSERT_EQ(id_, inputCmdId);
+ ASSERT_EQ(status_.status, NanStatusCode::SUCCESS);
+
+ // Check for reasonable capability values.
+ EXPECT_GT(capabilities_.maxConcurrentClusters, 0);
+ EXPECT_GT(capabilities_.maxPublishes, 0);
+ EXPECT_GT(capabilities_.maxSubscribes, 0);
+ EXPECT_EQ(capabilities_.maxServiceNameLen, 255);
+ EXPECT_EQ(capabilities_.maxMatchFilterLen, 255);
+ EXPECT_GT(capabilities_.maxTotalMatchFilterLen, 255);
+ EXPECT_EQ(capabilities_.maxServiceSpecificInfoLen, 255);
+ EXPECT_GE(capabilities_.maxExtendedServiceSpecificInfoLen, 255);
+ EXPECT_GT(capabilities_.maxNdiInterfaces, 0);
+ EXPECT_GT(capabilities_.maxNdpSessions, 0);
+ EXPECT_GT(capabilities_.maxAppInfoLen, 0);
+ EXPECT_GT(capabilities_.maxQueuedTransmitFollowupMsgs, 0);
+ EXPECT_GT(capabilities_.maxSubscribeInterfaceAddresses, 0);
+ EXPECT_NE(static_cast<int32_t>(capabilities_.supportedCipherSuites), 0);
+}
+
+/*
+ * StartPublishRequest
+ */
+TEST_P(WifiNanIfaceAidlTest, StartPublishRequest) {
+ uint16_t inputCmdId = 10;
+ NanBandSpecificConfig config24 = {};
+ config24.rssiClose = 60;
+ config24.rssiMiddle = 70;
+ config24.rssiCloseProximity = 60;
+ config24.dwellTimeMs = 200;
+ config24.scanPeriodSec = 20;
+ config24.validDiscoveryWindowIntervalVal = false;
+ config24.discoveryWindowIntervalVal = 0;
+
+ NanBandSpecificConfig config5 = {};
+ config5.rssiClose = 60;
+ config5.rssiMiddle = 75;
+ config5.rssiCloseProximity = 60;
+ config5.dwellTimeMs = 200;
+ config5.scanPeriodSec = 20;
+ config5.validDiscoveryWindowIntervalVal = false;
+ config5.discoveryWindowIntervalVal = 0;
+
+ NanEnableRequest req = {};
+ req.operateInBand[static_cast<int32_t>(NanBandIndex::NAN_BAND_24GHZ)] = true;
+ req.operateInBand[static_cast<int32_t>(NanBandIndex::NAN_BAND_5GHZ)] = false;
+ req.hopCountMax = 2;
+ req.configParams.masterPref = 0;
+ req.configParams.disableDiscoveryAddressChangeIndication = true;
+ req.configParams.disableStartedClusterIndication = true;
+ req.configParams.disableJoinedClusterIndication = true;
+ req.configParams.includePublishServiceIdsInBeacon = true;
+ req.configParams.numberOfPublishServiceIdsInBeacon = 0;
+ req.configParams.includeSubscribeServiceIdsInBeacon = true;
+ req.configParams.numberOfSubscribeServiceIdsInBeacon = 0;
+ req.configParams.rssiWindowSize = 8;
+ req.configParams.macAddressRandomizationIntervalSec = 1800;
+ req.configParams.bandSpecificConfig[static_cast<int32_t>(NanBandIndex::NAN_BAND_24GHZ)] =
+ config24;
+ req.configParams.bandSpecificConfig[static_cast<int32_t>(NanBandIndex::NAN_BAND_5GHZ)] =
+ config5;
+
+ req.debugConfigs.validClusterIdVals = true;
+ req.debugConfigs.clusterIdTopRangeVal = 65535;
+ req.debugConfigs.clusterIdBottomRangeVal = 0;
+ req.debugConfigs.validIntfAddrVal = false;
+ req.debugConfigs.validOuiVal = false;
+ req.debugConfigs.ouiVal = 0;
+ req.debugConfigs.validRandomFactorForceVal = false;
+ req.debugConfigs.randomFactorForceVal = 0;
+ req.debugConfigs.validHopCountForceVal = false;
+ req.debugConfigs.hopCountForceVal = 0;
+ req.debugConfigs.validDiscoveryChannelVal = false;
+ req.debugConfigs.discoveryChannelMhzVal[static_cast<int32_t>(NanBandIndex::NAN_BAND_24GHZ)] = 0;
+ req.debugConfigs.discoveryChannelMhzVal[static_cast<int32_t>(NanBandIndex::NAN_BAND_5GHZ)] = 0;
+ req.debugConfigs.validUseBeaconsInBandVal = false;
+ req.debugConfigs.useBeaconsInBandVal[static_cast<int32_t>(NanBandIndex::NAN_BAND_24GHZ)] = true;
+ req.debugConfigs.useBeaconsInBandVal[static_cast<int32_t>(NanBandIndex::NAN_BAND_5GHZ)] = true;
+ req.debugConfigs.validUseSdfInBandVal = false;
+ req.debugConfigs.useSdfInBandVal[static_cast<int32_t>(NanBandIndex::NAN_BAND_24GHZ)] = true;
+ req.debugConfigs.useSdfInBandVal[static_cast<int32_t>(NanBandIndex::NAN_BAND_5GHZ)] = true;
+
+ NanConfigRequestSupplemental nanConfigRequestSupp = {};
+ nanConfigRequestSupp.discoveryBeaconIntervalMs = 20;
+ nanConfigRequestSupp.numberOfSpatialStreamsInDiscovery = 0;
+ nanConfigRequestSupp.enableDiscoveryWindowEarlyTermination = false;
+
+ callback_type_ = INVALID;
+ auto status = wifi_nan_iface_->enableRequest(inputCmdId, req, nanConfigRequestSupp);
+ if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ ASSERT_TRUE(status.isOk());
+
+ // Wait for a callback.
+ ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_ENABLE_RESPONSE));
+ ASSERT_EQ(NOTIFY_ENABLE_RESPONSE, callback_type_);
+ ASSERT_EQ(id_, inputCmdId);
+ ASSERT_EQ(status_.status, NanStatusCode::SUCCESS);
+ }
+
+ NanPublishRequest nanPublishRequest = {};
+ nanPublishRequest.baseConfigs.sessionId = 0;
+ nanPublishRequest.baseConfigs.ttlSec = 0;
+ nanPublishRequest.baseConfigs.discoveryWindowPeriod = 1;
+ nanPublishRequest.baseConfigs.discoveryCount = 0;
+ nanPublishRequest.baseConfigs.serviceName = {97};
+ nanPublishRequest.baseConfigs.discoveryMatchIndicator = NanMatchAlg::MATCH_NEVER;
+ nanPublishRequest.baseConfigs.useRssiThreshold = false;
+ nanPublishRequest.baseConfigs.disableDiscoveryTerminationIndication = false;
+ nanPublishRequest.baseConfigs.disableMatchExpirationIndication = true;
+ nanPublishRequest.baseConfigs.disableFollowupReceivedIndication = false;
+ nanPublishRequest.baseConfigs.securityConfig.securityType = NanDataPathSecurityType::OPEN;
+ nanPublishRequest.autoAcceptDataPathRequests = false;
+ nanPublishRequest.publishType = NanPublishType::UNSOLICITED;
+ nanPublishRequest.txType = NanTxType::BROADCAST;
+
+ status = wifi_nan_iface_->startPublishRequest(inputCmdId + 1, nanPublishRequest);
+ if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ ASSERT_TRUE(status.isOk());
+
+ // Wait for a callback.
+ ASSERT_EQ(std::cv_status::no_timeout, wait(NOTIFY_START_PUBLISH_RESPONSE));
+ ASSERT_EQ(NOTIFY_START_PUBLISH_RESPONSE, callback_type_);
+ ASSERT_EQ(id_, inputCmdId + 1);
+ ASSERT_EQ(status_.status, NanStatusCode::SUCCESS);
+ }
+}
+
+/*
+ * RespondToDataPathIndicationRequest - Invalid Args
+ */
+TEST_P(WifiNanIfaceAidlTest, RespondToDataPathIndicationRequest_InvalidArgs) {
+ uint16_t inputCmdId = 10;
+ callback_type_ = INVALID;
+ NanRespondToDataPathIndicationRequest nanRespondToDataPathIndicationRequest = {};
+ nanRespondToDataPathIndicationRequest.ifaceName = "AwareInterfaceNameTooLong";
+ auto status = wifi_nan_iface_->respondToDataPathIndicationRequest(
+ inputCmdId, nanRespondToDataPathIndicationRequest);
+
+ if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ ASSERT_EQ(status.getServiceSpecificError(),
+ static_cast<int32_t>(WifiStatusCode::ERROR_INVALID_ARGS));
+ }
+}
+
+/*
+ * InitiateDataPathRequest - Invalid Args
+ */
+TEST_P(WifiNanIfaceAidlTest, InitiateDataPathRequest_InvalidArgs) {
+ uint16_t inputCmdId = 10;
+ callback_type_ = INVALID;
+ NanInitiateDataPathRequest nanInitiateDataPathRequest = {};
+ nanInitiateDataPathRequest.ifaceName = "AwareInterfaceNameTooLong";
+ auto status = wifi_nan_iface_->initiateDataPathRequest(inputCmdId, nanInitiateDataPathRequest);
+
+ if (!checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ ASSERT_EQ(status.getServiceSpecificError(),
+ static_cast<int32_t>(WifiStatusCode::ERROR_INVALID_ARGS));
+ }
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiNanIfaceAidlTest);
+INSTANTIATE_TEST_SUITE_P(WifiTest, WifiNanIfaceAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ android::ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp
new file mode 100644
index 0000000..d763fe6
--- /dev/null
+++ b/wifi/aidl/vts/functional/wifi_rtt_controller_aidl_test.cpp
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Staache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <vector>
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/BnWifi.h>
+#include <aidl/android/hardware/wifi/BnWifiRttControllerEventCallback.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include "wifi_aidl_test_utils.h"
+
+using aidl::android::hardware::wifi::BnWifiRttControllerEventCallback;
+using aidl::android::hardware::wifi::IWifiRttController;
+using aidl::android::hardware::wifi::RttBw;
+using aidl::android::hardware::wifi::RttCapabilities;
+using aidl::android::hardware::wifi::RttConfig;
+using aidl::android::hardware::wifi::RttPeerType;
+using aidl::android::hardware::wifi::RttPreamble;
+using aidl::android::hardware::wifi::RttResponder;
+using aidl::android::hardware::wifi::RttResult;
+using aidl::android::hardware::wifi::RttType;
+using aidl::android::hardware::wifi::WifiChannelInfo;
+using aidl::android::hardware::wifi::WifiChannelWidthInMhz;
+using aidl::android::hardware::wifi::WifiStatusCode;
+
+class WifiRttControllerAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ if (!::testing::deviceSupportsFeature("android.hardware.wifi.rtt"))
+ GTEST_SKIP() << "Skipping this test since RTT is not supported.";
+ stopWifiService(getInstanceName());
+ wifi_rtt_controller_ = getWifiRttController();
+ ASSERT_NE(nullptr, wifi_rtt_controller_.get());
+
+ // Check RTT support before we run the test.
+ RttCapabilities caps = {};
+ auto status = wifi_rtt_controller_->getCapabilities(&caps);
+ if (checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED)) {
+ GTEST_SKIP() << "Skipping this test since RTT is not supported.";
+ }
+ }
+
+ void TearDown() override { stopWifiService(getInstanceName()); }
+
+ protected:
+ std::shared_ptr<IWifiRttController> getWifiRttController() {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
+ EXPECT_NE(nullptr, wifi_chip.get());
+
+ std::shared_ptr<IWifiStaIface> wifi_sta_iface = getWifiStaIface(getInstanceName());
+ EXPECT_NE(nullptr, wifi_sta_iface.get());
+
+ std::shared_ptr<IWifiRttController> rtt_controller;
+ EXPECT_TRUE(wifi_chip->createRttController(wifi_sta_iface, &rtt_controller).isOk());
+ EXPECT_NE(nullptr, rtt_controller.get());
+ return rtt_controller;
+ }
+
+ std::shared_ptr<IWifiRttController> wifi_rtt_controller_;
+
+ private:
+ const char* getInstanceName() { return GetParam().c_str(); }
+};
+
+class WifiRttControllerEventCallback : public BnWifiRttControllerEventCallback {
+ public:
+ WifiRttControllerEventCallback() = default;
+
+ ::ndk::ScopedAStatus onResults(int /* cmdId */,
+ const std::vector<RttResult>& /* results */) override {
+ return ndk::ScopedAStatus::ok();
+ }
+};
+
+/*
+ * RegisterEventCallback
+ *
+ * Note: it is not feasible to test the invocation of the callback function,
+ * since events are triggered internally in the HAL implementation and cannot be
+ * triggered from the test case.
+ */
+TEST_P(WifiRttControllerAidlTest, RegisterEventCallback) {
+ std::shared_ptr<WifiRttControllerEventCallback> callback =
+ ndk::SharedRefBase::make<WifiRttControllerEventCallback>();
+ ASSERT_NE(nullptr, callback.get());
+ EXPECT_TRUE(wifi_rtt_controller_->registerEventCallback(callback).isOk());
+}
+
+/*
+ * GetCapabilities
+ */
+TEST_P(WifiRttControllerAidlTest, GetCapabilities) {
+ RttCapabilities caps = {};
+ EXPECT_TRUE(wifi_rtt_controller_->getCapabilities(&caps).isOk());
+}
+
+/*
+ * GetResponderInfo
+ */
+TEST_P(WifiRttControllerAidlTest, GetResponderInfo) {
+ RttResponder responder = {};
+ EXPECT_TRUE(wifi_rtt_controller_->getResponderInfo(&responder).isOk());
+}
+
+/*
+ * EnableResponder
+ */
+TEST_P(WifiRttControllerAidlTest, EnableResponder) {
+ int cmdId = 55;
+ WifiChannelInfo channelInfo;
+ channelInfo.width = WifiChannelWidthInMhz::WIDTH_80;
+ channelInfo.centerFreq = 5660;
+ channelInfo.centerFreq0 = 5660;
+ channelInfo.centerFreq1 = 0;
+
+ RttResponder responder = {};
+ EXPECT_TRUE(wifi_rtt_controller_->getResponderInfo(&responder).isOk());
+ EXPECT_TRUE(wifi_rtt_controller_->enableResponder(cmdId, channelInfo, 10, responder).isOk());
+}
+
+/*
+ * Request2SidedRangeMeasurement
+ * Tests the two sided ranging - 802.11mc FTM protocol.
+ */
+TEST_P(WifiRttControllerAidlTest, Request2SidedRangeMeasurement) {
+ RttCapabilities caps = {};
+ EXPECT_TRUE(wifi_rtt_controller_->getCapabilities(&caps).isOk());
+ if (!caps.rttFtmSupported) {
+ GTEST_SKIP() << "Skipping two sided RTT since driver/fw does not support";
+ }
+
+ RttConfig config;
+ config.addr = {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}};
+ config.type = RttType::TWO_SIDED;
+ config.peer = RttPeerType::AP;
+ config.channel.width = WifiChannelWidthInMhz::WIDTH_80;
+ config.channel.centerFreq = 5180;
+ config.channel.centerFreq0 = 5210;
+ config.channel.centerFreq1 = 0;
+ config.bw = RttBw::BW_20MHZ;
+ config.preamble = RttPreamble::HT;
+ config.mustRequestLci = false;
+ config.mustRequestLcr = false;
+ config.burstPeriod = 0;
+ config.numBurst = 0;
+ config.numFramesPerBurst = 8;
+ config.numRetriesPerRttFrame = 0;
+ config.numRetriesPerFtmr = 0;
+ config.burstDuration = 9;
+
+ int cmdId = 55;
+ std::vector<RttConfig> configs = {config};
+ EXPECT_TRUE(wifi_rtt_controller_->rangeRequest(cmdId, configs).isOk());
+
+ // Sleep for 2 seconds to wait for driver/firmware to complete RTT.
+ sleep(2);
+}
+
+/*
+ * RangeRequest
+ */
+TEST_P(WifiRttControllerAidlTest, RangeRequest) {
+ RttCapabilities caps = {};
+ EXPECT_TRUE(wifi_rtt_controller_->getCapabilities(&caps).isOk());
+ if (!caps.rttOneSidedSupported) {
+ GTEST_SKIP() << "Skipping one sided RTT since driver/fw does not support";
+ }
+
+ // Get the highest supported preamble.
+ int preamble = 1;
+ int caps_preamble_support = static_cast<int>(caps.preambleSupport);
+ caps_preamble_support >>= 1;
+ while (caps_preamble_support != 0) {
+ caps_preamble_support >>= 1;
+ preamble <<= 1;
+ }
+
+ RttConfig config;
+ config.addr = {{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}};
+ config.type = RttType::ONE_SIDED;
+ config.peer = RttPeerType::AP;
+ config.channel.width = WifiChannelWidthInMhz::WIDTH_80;
+ config.channel.centerFreq = 5765;
+ config.channel.centerFreq0 = 5775;
+ config.channel.centerFreq1 = 0;
+ config.bw = RttBw::BW_80MHZ;
+ config.preamble = static_cast<RttPreamble>(preamble);
+ config.mustRequestLci = false;
+ config.mustRequestLcr = false;
+ config.burstPeriod = 0;
+ config.numBurst = 0;
+ config.numFramesPerBurst = 8;
+ config.numRetriesPerRttFrame = 3;
+ config.numRetriesPerFtmr = 3;
+ config.burstDuration = 9;
+
+ int cmdId = 55;
+ std::vector<RttConfig> configs = {config};
+ EXPECT_TRUE(wifi_rtt_controller_->rangeRequest(cmdId, configs).isOk());
+
+ // Sleep for 2 seconds to wait for driver/firmware to complete RTT.
+ sleep(2);
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiRttControllerAidlTest);
+INSTANTIATE_TEST_SUITE_P(WifiTest, WifiRttControllerAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ android::ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
new file mode 100644
index 0000000..ef7e274
--- /dev/null
+++ b/wifi/aidl/vts/functional/wifi_sta_iface_aidl_test.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Staache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 <vector>
+
+#include <VtsCoreUtil.h>
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/wifi/BnWifi.h>
+#include <android/binder_manager.h>
+#include <android/binder_status.h>
+#include <binder/IServiceManager.h>
+#include <binder/ProcessState.h>
+
+#include "wifi_aidl_test_utils.h"
+
+using aidl::android::hardware::wifi::IWifi;
+using aidl::android::hardware::wifi::IWifiStaIface;
+using aidl::android::hardware::wifi::MacAddress;
+using aidl::android::hardware::wifi::Ssid;
+using aidl::android::hardware::wifi::StaApfPacketFilterCapabilities;
+using aidl::android::hardware::wifi::StaBackgroundScanCapabilities;
+using aidl::android::hardware::wifi::StaLinkLayerStats;
+using aidl::android::hardware::wifi::StaRoamingCapabilities;
+using aidl::android::hardware::wifi::StaRoamingConfig;
+using aidl::android::hardware::wifi::StaRoamingState;
+using aidl::android::hardware::wifi::WifiBand;
+using aidl::android::hardware::wifi::WifiDebugRxPacketFateReport;
+using aidl::android::hardware::wifi::WifiDebugTxPacketFateReport;
+using aidl::android::hardware::wifi::WifiStatusCode;
+
+class WifiStaIfaceAidlTest : public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ stopWifiService(getInstanceName());
+ wifi_sta_iface_ = getWifiStaIface(getInstanceName());
+ ASSERT_NE(nullptr, wifi_sta_iface_.get());
+ }
+
+ void TearDown() override { stopWifiService(getInstanceName()); }
+
+ protected:
+ bool isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask expected) {
+ IWifiStaIface::StaIfaceCapabilityMask caps = {};
+ EXPECT_TRUE(wifi_sta_iface_->getCapabilities(&caps).isOk());
+ return static_cast<uint32_t>(caps) & static_cast<uint32_t>(expected);
+ }
+
+ ndk::ScopedAStatus createStaIface(std::shared_ptr<IWifiStaIface>* sta_iface) {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
+ EXPECT_NE(nullptr, wifi_chip.get());
+ return wifi_chip->createStaIface(sta_iface);
+ }
+
+ std::shared_ptr<IWifiStaIface> wifi_sta_iface_;
+
+ private:
+ const char* getInstanceName() { return GetParam().c_str(); }
+};
+
+/*
+ * GetFactoryMacAddress
+ * Ensures that calls to getFactoryMacAddress will retrieve a non-zero MAC.
+ */
+TEST_P(WifiStaIfaceAidlTest, GetFactoryMacAddress) {
+ std::array<uint8_t, 6> mac;
+ EXPECT_TRUE(wifi_sta_iface_->getFactoryMacAddress(&mac).isOk());
+ std::array<uint8_t, 6> all_zero_mac = {0, 0, 0, 0, 0, 0};
+ EXPECT_NE(mac, all_zero_mac);
+}
+
+/*
+ * GetCapabilities
+ */
+TEST_P(WifiStaIfaceAidlTest, GetCapabilities) {
+ IWifiStaIface::StaIfaceCapabilityMask caps = {};
+ EXPECT_TRUE(wifi_sta_iface_->getCapabilities(&caps).isOk());
+ EXPECT_NE(static_cast<int32_t>(caps), 0);
+}
+
+/*
+ * GetApfPacketFilterCapabilities
+ */
+TEST_P(WifiStaIfaceAidlTest, GetApfPacketFilterCapabilities) {
+ if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::APF)) {
+ GTEST_SKIP() << "APF packet filter capabilities are not supported.";
+ }
+ StaApfPacketFilterCapabilities apf_caps = {};
+ EXPECT_TRUE(wifi_sta_iface_->getApfPacketFilterCapabilities(&apf_caps).isOk());
+}
+
+/*
+ * GetBackgroundScanCapabilities
+ */
+TEST_P(WifiStaIfaceAidlTest, GetBackgroundScanCapabilities) {
+ if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::BACKGROUND_SCAN)) {
+ GTEST_SKIP() << "Background scan capabilities are not supported.";
+ }
+ StaBackgroundScanCapabilities caps = {};
+ EXPECT_TRUE(wifi_sta_iface_->getBackgroundScanCapabilities(&caps).isOk());
+}
+
+/*
+ * GetValidFrequenciesForBand
+ * Ensures that we can retrieve valid frequencies for the 2.4 GHz band.
+ */
+TEST_P(WifiStaIfaceAidlTest, GetValidFrequenciesForBand) {
+ std::vector<int> freqs;
+ EXPECT_TRUE(wifi_sta_iface_->getValidFrequenciesForBand(WifiBand::BAND_24GHZ, &freqs).isOk());
+ EXPECT_NE(freqs.size(), 0);
+}
+
+/*
+ * GetLinkLayerStats
+ * Ensures that calls to getLinkLayerStats will retrieve a non-empty
+ * StaLinkLayerStats after link layer stats collection is enabled.
+ */
+TEST_P(WifiStaIfaceAidlTest, GetLinkLayerStats) {
+ if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
+ GTEST_SKIP() << "Skipping this test since link layer stats are not supported.";
+ }
+
+ // Enable link layer stats collection.
+ EXPECT_TRUE(wifi_sta_iface_->enableLinkLayerStatsCollection(true).isOk());
+
+ // Retrieve link layer stats.
+ StaLinkLayerStats link_layer_stats = {};
+ EXPECT_TRUE(wifi_sta_iface_->getLinkLayerStats(&link_layer_stats).isOk());
+ EXPECT_GT(link_layer_stats.timeStampInMs, 0);
+
+ // Try to create a 2nd iface. If successful, it should fill the duty cycle field.
+ std::shared_ptr<IWifiStaIface> iface;
+ auto status = createStaIface(&iface);
+ if (status.isOk()) {
+ EXPECT_GT(link_layer_stats.iface.timeSliceDutyCycleInPercent, 0);
+ }
+
+ // Disable link layer stats collection.
+ EXPECT_TRUE(wifi_sta_iface_->disableLinkLayerStatsCollection().isOk());
+}
+
+/*
+ * SetMacAddress
+ * Ensures that calls to setMacAddress will return successfully.
+ */
+TEST_P(WifiStaIfaceAidlTest, SetMacAddress) {
+ std::array<uint8_t, 6> mac = {0x12, 0x22, 0x33, 0x52, 0x10, 0x41};
+ EXPECT_TRUE(wifi_sta_iface_->setMacAddress(mac).isOk());
+}
+
+/*
+ * SetScanMode
+ */
+TEST_P(WifiStaIfaceAidlTest, SetScanMode) {
+ auto status = wifi_sta_iface_->setScanMode(true);
+ EXPECT_TRUE(status.isOk() || checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+
+ status = wifi_sta_iface_->setScanMode(false);
+ EXPECT_TRUE(status.isOk() || checkStatusCode(&status, WifiStatusCode::ERROR_NOT_SUPPORTED));
+}
+
+/*
+ * LinkLayerStatsCollection
+ */
+TEST_P(WifiStaIfaceAidlTest, LinkLayerStatsCollection) {
+ if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::LINK_LAYER_STATS)) {
+ GTEST_SKIP() << "Link layer stats collection is not supported.";
+ }
+
+ // Enable link layer stats collection.
+ EXPECT_TRUE(wifi_sta_iface_->enableLinkLayerStatsCollection(true).isOk());
+
+ // Retrieve link layer stats.
+ StaLinkLayerStats link_layer_stats = {};
+ EXPECT_TRUE(wifi_sta_iface_->getLinkLayerStats(&link_layer_stats).isOk());
+
+ // Disable link layer stats collection.
+ EXPECT_TRUE(wifi_sta_iface_->disableLinkLayerStatsCollection().isOk());
+}
+
+/*
+ * RSSIMonitoring
+ * Ensures that calls to startRssiMonitoring and stopRssiMonitoring will fail
+ * if the device is not connected to an AP.
+ */
+TEST_P(WifiStaIfaceAidlTest, RSSIMonitoring) {
+ if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::RSSI_MONITOR)) {
+ GTEST_SKIP() << "RSSI monitoring is not supported.";
+ }
+
+ const int cmd = 1;
+ const int maxRssi = -50;
+ const int minRssi = -90;
+ // Expected to fail because device is not connected to an AP.
+ EXPECT_FALSE(wifi_sta_iface_->startRssiMonitoring(cmd, maxRssi, minRssi).isOk());
+ EXPECT_FALSE(wifi_sta_iface_->stopRssiMonitoring(cmd).isOk());
+}
+
+/*
+ * RoamingControl
+ */
+TEST_P(WifiStaIfaceAidlTest, RoamingControl) {
+ if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::CONTROL_ROAMING)) {
+ GTEST_SKIP() << "Roaming control is not supported.";
+ }
+
+ // Retrieve roaming capabilities.
+ StaRoamingCapabilities caps = {};
+ EXPECT_TRUE(wifi_sta_iface_->getRoamingCapabilities(&caps).isOk());
+
+ // Set up roaming configuration based on roaming capabilities.
+ StaRoamingConfig roaming_config = {};
+ if (caps.maxBlocklistSize > 0) {
+ MacAddress block_list_entry;
+ block_list_entry.data = std::array<uint8_t, 6>{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}};
+ roaming_config.bssidBlocklist = {block_list_entry};
+ }
+ if (caps.maxAllowlistSize > 0) {
+ Ssid allow_list_entry = {};
+ allow_list_entry.data = std::array<uint8_t, 32>{{0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC}};
+ roaming_config.ssidAllowlist = {allow_list_entry};
+ }
+
+ // Configure roaming.
+ EXPECT_TRUE(wifi_sta_iface_->configureRoaming(roaming_config).isOk());
+
+ // Enable roaming.
+ EXPECT_TRUE(wifi_sta_iface_->setRoamingState(StaRoamingState::ENABLED).isOk());
+}
+
+/*
+ * EnableNDOffload
+ */
+TEST_P(WifiStaIfaceAidlTest, EnableNDOffload) {
+ if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::ND_OFFLOAD)) {
+ GTEST_SKIP() << "ND offload is not supported.";
+ }
+ EXPECT_TRUE(wifi_sta_iface_->enableNdOffload(true).isOk());
+}
+
+/*
+ * PacketFateMonitoring
+ */
+TEST_P(WifiStaIfaceAidlTest, PacketFateMonitoring) {
+ if (!isCapabilitySupported(IWifiStaIface::StaIfaceCapabilityMask::DEBUG_PACKET_FATE)) {
+ GTEST_SKIP() << "Packet fate monitoring is not supported.";
+ }
+
+ // Start packet fate monitoring.
+ EXPECT_TRUE(wifi_sta_iface_->startDebugPacketFateMonitoring().isOk());
+
+ // Retrieve packets.
+ std::vector<WifiDebugRxPacketFateReport> rx_reports;
+ std::vector<WifiDebugTxPacketFateReport> tx_reports;
+ EXPECT_TRUE(wifi_sta_iface_->getDebugRxPacketFates(&rx_reports).isOk());
+ EXPECT_TRUE(wifi_sta_iface_->getDebugTxPacketFates(&tx_reports).isOk());
+}
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiStaIfaceAidlTest);
+INSTANTIATE_TEST_SUITE_P(WifiTest, WifiStaIfaceAidlTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),
+ android::PrintInstanceNameToString);
+
+int main(int argc, char** argv) {
+ ::testing::InitGoogleTest(&argc, argv);
+ android::ProcessState::self()->setThreadPoolMaxThreadCount(1);
+ android::ProcessState::self()->startThreadPool();
+ return RUN_ALL_TESTS();
+}
diff --git a/wifi/apex/Android.bp b/wifi/apex/Android.bp
new file mode 100644
index 0000000..e1fefb9
--- /dev/null
+++ b/wifi/apex/Android.bp
@@ -0,0 +1,55 @@
+package {
+ default_applicable_licenses: ["hardware_interfaces_license"],
+}
+
+apex_key {
+ name: "com.android.hardware.wifi.key",
+ public_key: "com.android.hardware.wifi.avbpubkey",
+ private_key: "com.android.hardware.wifi.pem",
+}
+
+android_app_certificate {
+ name: "com.android.hardware.wifi.certificate",
+ certificate: "com.android.hardware.wifi",
+}
+
+genrule {
+ name: "gen-android.hardware.wifi.rc",
+ srcs: [":default-android.hardware.wifi-service.rc"],
+ out: ["com.android.hardware.wifi-service.rc"],
+ cmd: "sed -e 's@/vendor/bin/@/apex/com.android.hardware.wifi/bin/@' $(in) > $(out)",
+}
+
+prebuilt_etc {
+ name: "com.android.hardware.wifi.rc",
+ src: ":gen-android.hardware.wifi.rc",
+ installable: false,
+}
+
+prebuilt_etc {
+ name: "com.android.hardware.wifi.xml",
+ src: ":default-android.hardware.wifi-service.xml",
+ installable: false,
+}
+
+apex {
+ name: "com.android.hardware.wifi",
+ manifest: "apex_manifest.json",
+ key: "com.android.hardware.wifi.key",
+ certificate: ":com.android.hardware.wifi.certificate",
+ file_contexts: "file_contexts",
+ vintf_fragments: [":com.android.hardware.wifi.xml"],
+ use_vndk_as_stable: true,
+ updatable: false,
+ soc_specific: true,
+ binaries: [
+ "android.hardware.wifi-service",
+ ],
+ prebuilts: [
+ "com.android.hardware.wifi.rc",
+ "com.android.hardware.wifi.xml",
+ ],
+ overrides: [
+ "android.hardware.wifi-service",
+ ],
+}
diff --git a/wifi/apex/apex_manifest.json b/wifi/apex/apex_manifest.json
new file mode 100644
index 0000000..cab0814
--- /dev/null
+++ b/wifi/apex/apex_manifest.json
@@ -0,0 +1,4 @@
+{
+ "name": "com.android.hardware.wifi",
+ "version": 1
+}
diff --git a/wifi/apex/com.android.hardware.wifi.avbpubkey b/wifi/apex/com.android.hardware.wifi.avbpubkey
new file mode 100644
index 0000000..63fba77
--- /dev/null
+++ b/wifi/apex/com.android.hardware.wifi.avbpubkey
Binary files differ
diff --git a/wifi/apex/com.android.hardware.wifi.pem b/wifi/apex/com.android.hardware.wifi.pem
new file mode 100644
index 0000000..9e589ac
--- /dev/null
+++ b/wifi/apex/com.android.hardware.wifi.pem
@@ -0,0 +1,52 @@
+-----BEGIN PRIVATE KEY-----
+MIIJRAIBADANBgkqhkiG9w0BAQEFAASCCS4wggkqAgEAAoICAQCtT/vNnVVg2QVD
+eMdG+YZ8qYz/fbAQF9hnH8dE5RWHXzoYItBG7DSOuVT4T6POBVmFaVKlWDd7tDyw
+nFO3MmE2/FzhVSiBPwhMITa7UIERr3od3rWJ5g6oaTCOu4wa98L466Jp60f2fYSZ
+M9lGiKaDpLDSpxTU9hexjp7C4PfinnkYnlHBnrFXTmiO6f8AvOEwFFx73/rUNoe7
+F3TkGvjZDqHvE+pjz/nilkhXYuOl3zgSaeznJ9+TO5C/Z+Xr+zRhaJGI4v5Dkgmc
+jNy74+0hjwobXO3iWE44InQMvMh8zDKBx9l1oSsFoG3waj9ayqSYD7M74RX3PkUL
+QrhgAHZWi5iEnpu50xBzAqZB1ZDVkdZiKiGzweJ8OqltnVpvzlnW3rA3y3HtFyLm
+73C4ll9MdLaw266vBxgZfFOcjpphbbh9J9uGjOCJY1AxUzsqKygFD2CyOdb1jab3
+AC6VvRa+bLtv8fd2etp3atXv+Y9ACUX6zNK6Oa8Zktoo2Z//OLtcrk7xhgKKDkUF
+OPQrIjW9x0fdClDioIS+y7EHNUrfyRL7XPtUqGCszgz5jK2SMVGMpFaEtfbyNP1H
+BTGXdzcDP0RZdOOKTdBFgoRW5+6TH5CU9Nl4uevpxzwsTkXg0a+W1BGP+s9J7ssH
+rNPmHz+pbKZPDs/nxlpsKq+N+K8cCwIDAQABAoICAAJL943Lgnikl53DyXxGzUH0
+q0Itg7pK3prLQIRItubS2727JGB0O+QST650u7p8tql+clJvn1ib1FwQzkk0uTYV
+1RNFYiKIV89Od1+3GubFmQwxSd2Yd2RC9JpHoP0wgFx1HvNhY1RAaJPxLHVzVSWU
+dqVsAmoqErlPJwp1GcPejsNFQdcbh8Uc7GTMdA0p86AD/Q/FMZlDWbwgfPOS6e5S
+c9HrxSTqeijHDhFeZZ7qnN8dmT6c+CkG1o26zkC41QJfdOJIA8+YbVkuQrSYuilC
+MIOZUSu5ONwklL4geFWzDQ5MPDUDXEMYU6ymc817tv+u4ZSvEG/02sxh53iaOPc6
+C6im4nm6ZlRP9HzIvLAiRSbvwEb9cnLKgYpioSGXehDYg3zMPURwoqIxw+7IlIUh
+s+rhmCJV62PK1Z0nmo7m7S8r+z6j4G7aztGcbvdecocOJYOQB1VB8Zh4bNEIWp0a
+GDteG6aWXOCHoYRWAOluppDWa7Z+EgesU3Oj9Prn/ekUzzXx3V30zSTZYxRnQCO0
+vZIZ6hrlsNJcNrDpxmiWBaEOd4k5QI39pu6fDHc+UEEJMN+7eVk8d9QVA/LhrCjc
+JH1EVjtWosMUeMaMTpcmHTQKnEvmT2LO2fxGlF4JvjzDdVMloJrIP2LSQjovo2PX
+x9UXVu8Dt3kQRefZ42XxAoIBAQDkBoSYVajaFlyv9lW8oPmrQyzp93ite+TKVR8z
+PmcFQukjp5Gm8PGlGtGoH8aeE9Ev+R86aNPFy4n4ZJ7fmZYH1hxZ6dSc/56k6lLn
+uVKvTudYqwcRgBKuSZ8IDPFz3sHd+MnOBonDIri28fcBTDNv4LJP/6cAUoIOCCPm
+lQtJBfMNMDOXG4jv1Rv/1P5opGFATerRCubOxmeaFhZIDEjvN5WvLK5jmL7I8lX3
+X+gPiMHFWBQFmVTOHeVYEORDO5xFCOvHqCVB78b2xe1NkkrQ0CexpdflJVLE9IWt
+wWH43nhjxaK+eiBPrj37BliJvNaYfuxqcAj3p8c5KweFEtP7AoIBAQDCkx72K/Ja
+rFrrI0Avfo+3n6yoTMtMkiVhMuIKKPBJ2o4Opc/uixk+uLH5UH0X5GZsE51FAhUD
+L3bWMxV+vzVefWS8Iryo94ucvnfqhsN3KZXHDGoAuYv72jND8qPLKksM0dceMBfl
+aoyXSPAe8zAZeEx4iR2axgtnA0EbiXIaNVE/LF+WYdM74jvk/QtRzJ8IAAkSc5Rr
+GiTHeeP3nRnkjWjkmwKXYSJHcrEl26c/2ckeZORtblqxR9wMU5OgvJvMSzmOIpVH
+Y5lylZUOTuJCkApHFNKdRsawsSNKsy4yfY1byN/WkODb7le6Crt1gcwldMxDZAo9
+iB25FHq4zksxAoIBAQC+SBYkDO9PtnN4PycCto5B9VeokmN42bdthKT5nSxY/qIQ
+p8fquIvdzEiCdKnIxh69WrVNh6aZGyWySz0suDyzo1+bRH6w2LrpQcUXK9YtBroV
+ivrmBqsQF82G6U4f9BZxhifZLimN1g6wU7Bcu9r8lFQYX+1bXn66+N4EkAGP2VAe
+hEe45Dhccsjfrzzx06J4B81YzjEXAgf4VFAZpW7DeO4G9VE9OXyTsW49dSHwvJ1+
+ceabWX2kVtxIpiflVvwru6sNvGoC4PV2fmptXhPitqE5JHzJ8mBkjOx0t7hq9jMe
+hxEsxDrsYynDrWL65cNqFBhzJbTF/ZNJSHgI+1I7AoIBAQC7m0shJOJ61vCbA9Qh
+dzBvZn/9jn3/CHMOMxeLoEl/jEGokevZHzlqJn9D2n2jCdBPqOHc5dMIzT0R7xNs
+sERvJQx58ixh5r0wlt3cva++N9R4pdmXdVApuAvyGgQgIllWtQVr0AdaZs/EFsmf
+re/Uvw9MsThgQVBBNPwT5wSjjIEYHlrUDuKzPMFvWyUM6/Tyq8YTimmykvSfeUF7
+QHj0y/w1X9ixyTBaH5X64L10bTLkIXe2o87CXH0pTXRsaS73XhjSmTnCKaCMwPmF
+YD383BFs1AD3MITnXQSgQ//pIvGnbBmXMv38UOU5NpvlAw+pleJVoCHXjmTKTZq+
+kfohAoIBAQCrEecN8XEPjGdtY71rDYEwHGM6G4czHX0PNhlMjQos3aBVZ/YvVxPG
+pkXbms3GRXv4W92u7b2MwEKBPxcBepEdDZN9wSpe63bDFE6gpkipDhgj97JlLEUd
+s7h6oOoazdxmsRZyFho99SRQWrvyOiiKdLJCRZiqjUB4roOQmy7f9VAz6+OxyGV9
+XZigwW6bfUzMCmhx5Ss6zW8wZI+gINQh+2sDmiBiMQv14Ya5zlNYN+4/257Sk/jS
+o3QUDJITbReq/DNZ6UUzQS+AZ7ztc81rk5kRg0I33FZarRJ7TLAz+XmZZFoIOORz
+etEvMk8bJ4u7X89NWW/i2J+kQiDQg819
+-----END PRIVATE KEY-----
diff --git a/wifi/apex/com.android.hardware.wifi.pk8 b/wifi/apex/com.android.hardware.wifi.pk8
new file mode 100644
index 0000000..f4481bf
--- /dev/null
+++ b/wifi/apex/com.android.hardware.wifi.pk8
Binary files differ
diff --git a/wifi/apex/com.android.hardware.wifi.x509.pem b/wifi/apex/com.android.hardware.wifi.x509.pem
new file mode 100644
index 0000000..c942e71
--- /dev/null
+++ b/wifi/apex/com.android.hardware.wifi.x509.pem
@@ -0,0 +1,36 @@
+-----BEGIN CERTIFICATE-----
+MIIGOzCCBCOgAwIBAgIUIEueuBFEoCFmLyEvXDsKVuZeH0EwDQYJKoZIhvcNAQEL
+BQAwgasxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
+DA1Nb3VudGFpbiBWaWV3MRAwDgYDVQQKDAdBbmRyb2lkMRAwDgYDVQQLDAdBbmRy
+b2lkMScwJQYDVQQDDB5jb20uYW5kcm9pZC5oYXJkd2FyZS53aWZpLmFwZXgxIjAg
+BgkqhkiG9w0BCQEWE2FuZHJvaWRAYW5kcm9pZC5jb20wIBcNMjIxMDA2MTY1MDQy
+WhgPNDc2MDA5MDExNjUwNDJaMIGrMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs
+aWZvcm5pYTEWMBQGA1UEBwwNTW91bnRhaW4gVmlldzEQMA4GA1UECgwHQW5kcm9p
+ZDEQMA4GA1UECwwHQW5kcm9pZDEnMCUGA1UEAwweY29tLmFuZHJvaWQuaGFyZHdh
+cmUud2lmaS5hcGV4MSIwIAYJKoZIhvcNAQkBFhNhbmRyb2lkQGFuZHJvaWQuY29t
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAo4N23iL0J42qG2lt4ysD
+t6XxAKdi4sTWB6ZjFWerBm11s3yLr1KBZV82z3j2o7+EOaWa/91Mgc+aoiGYUa1f
+IweugKTrnRmrzOvtq/Wp5PGqSxsmLPPvH3wyEB/CMgAn0pqDf0WyCWJ2kAlcCkmy
+qVNFupkGFyIE6gkoc+AmJGbSTquDlL07R/8XYDicqrcgeqy9ZaCJ5FLfmbnnRb2A
+vm4Un7e5dFz5+dPaOJXf4AOMUSPUd7fuBliGYFLzcZnYQbzMktXa4XnPuSlmerwy
+EwY767L2bjRjaSgPb0Js13gZ4S4ZHZe07AV7HPlt/EzbxV/jtMgHl4xn5p0WhVnK
+MPtLsO/e7FkDPAKpT02sgUK6pVKqgBGOWm27tmTB09lscMLQeVFqwpoFq2zMUrDn
+ipDFMWRBeLrEDKx41zF3gqdPmP+SMkQYJu4OATIXOndIeo7AN9iE+N6snHkckNyE
+saCwmnzyhVAbMn/epfIQZz3zcyljA9yfOpv5jctN4es+3i0htDnoNO9ij4M5fxuP
+jtNAP3EA61nKZ5+Js0/MMQKrfwCLogPl/4vCNuuGT2rhCkhq1CLYXmb9ghvVzcPe
+BOGXNDKdB+aUTxrQUOYlHf0cRDHdU6cchrz9+QhR7t9dlibtiyCZE34xgR3klmyz
+XJ3M1r/QRihjARH7exrrwiUCAwEAAaNTMFEwHQYDVR0OBBYEFGN9tMk+4SDk7twk
+MrLjM+nRxGDJMB8GA1UdIwQYMBaAFGN9tMk+4SDk7twkMrLjM+nRxGDJMA8GA1Ud
+EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAHoTfVBRG0rVE7gkV526gwR5
+/3mXyYA57lKJhZ21fu2qfTE6WYj4DsOTZKrPIAUFv/SnzZ6Rvv7W81XV5M/1m+5R
+/1wYvWwm3FBOvvt4VDUiel0Zfc9+nwynjz1seYdXU8fNIOzBcr9hutkYdRZDkNpc
+Zcl4NG04TzyedkQ/0SyHnygmq4ZY9OUEvrNaWBFHzw2SQhYvHh8jUrqpPvoJz0Px
+avKI8bOgXTJRJ+Pk7hjXDFQY/fbE0RGivorPMLs+XHaEIb+YPyXsX4OZwowG5KL8
+txyvUsH+qZToytdPk4LCuwYBobBlr+AAg7pxOtbDW1ITDhQ9n05UFK2iUwsJecgg
+VDA0K3GuCjmGVmkw7SFRYfToCyGWah8sQCUMCCcsof7gS+dMxuWeee+sRxRJcJY+
+xR2uySe8g4ohwNjQ0zLQv7PZOKQh91yEWxRXmhPYVpiVAjpSD2zH7Vd6CJ9xji//
+5S1UrxWwQ5igvu8v5veqNAW7uXGXADnxL69HVGTLm0XDIUUOAUIG8waiVkYUo3UU
+AzAFbF7ewYMKdg7ylUYcTaMRIsKYW/3/1t3NJv2z99W4V/p8e1kRCeWMPB5C+/Lo
+b/hSWj1NF9AJ30ukBndMh6bRprq+G5NLV6OaoCLp606CMdXdT8uw9lYCt7DbQHG9
+Hw3iw61svpUwcaWfN1hI
+-----END CERTIFICATE-----
diff --git a/wifi/apex/file_contexts b/wifi/apex/file_contexts
new file mode 100644
index 0000000..6368729
--- /dev/null
+++ b/wifi/apex/file_contexts
@@ -0,0 +1,3 @@
+(/.*)? u:object_r:vendor_file:s0
+/bin/hw/android\.hardware\.wifi-service u:object_r:hal_wifi_default_exec:s0
+
diff --git a/wifi/hostapd/1.0/vts/OWNERS b/wifi/hostapd/1.0/vts/OWNERS
deleted file mode 100644
index 287152d..0000000
--- a/wifi/hostapd/1.0/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 33618
-arabawy@google.com
-etancohen@google.com
diff --git a/wifi/hostapd/1.1/vts/OWNERS b/wifi/hostapd/1.1/vts/OWNERS
deleted file mode 100644
index 294fc82..0000000
--- a/wifi/hostapd/1.1/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/1.2/vts/OWNERS b/wifi/hostapd/1.2/vts/OWNERS
deleted file mode 100644
index 294fc82..0000000
--- a/wifi/hostapd/1.2/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/1.3/vts/OWNERS b/wifi/hostapd/1.3/vts/OWNERS
deleted file mode 100644
index 294fc82..0000000
--- a/wifi/hostapd/1.3/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.0/vts/OWNERS
diff --git a/wifi/hostapd/aidl/vts/OWNERS b/wifi/hostapd/aidl/vts/OWNERS
deleted file mode 100644
index 2a7a7b0..0000000
--- a/wifi/hostapd/aidl/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-etancohen@google.com
-lzye@google.com
diff --git a/wifi/hostapd/aidl/vts/functional/Android.bp b/wifi/hostapd/aidl/vts/functional/Android.bp
index e61d397..a9fdec8 100644
--- a/wifi/hostapd/aidl/vts/functional/Android.bp
+++ b/wifi/hostapd/aidl/vts/functional/Android.bp
@@ -20,20 +20,10 @@
"libvndksupport",
],
static_libs: [
+ "android.hardware.wifi-V1-ndk",
"android.hardware.wifi.hostapd-V1-ndk",
- "VtsHalWifiV1_0TargetTestUtil",
- "VtsHalWifiV1_5TargetTestUtil",
- "VtsHalWifiHostapdV1_0TargetTestUtil",
- "android.hardware.wifi.hostapd@1.0",
- "android.hardware.wifi.hostapd@1.1",
- "android.hardware.wifi.hostapd@1.2",
- "android.hardware.wifi.hostapd@1.3",
- "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",
+ "libwifi-system-iface",
+ "VtsHalWifiTargetTestUtil",
],
test_suites: [
"general-tests",
diff --git a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
index bd2649f..65ffa7b 100644
--- a/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
+++ b/wifi/hostapd/aidl/vts/functional/VtsHalHostapdTargetTest.cpp
@@ -13,8 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-#include <android/hardware/wifi/1.0/IWifi.h>
-#include <android/hardware/wifi/hostapd/1.3/IHostapd.h>
+#include <aidl/android/hardware/wifi/IWifi.h>
#include <VtsCoreUtil.h>
#include <aidl/Gtest.h>
@@ -24,12 +23,11 @@
#include <android/binder_manager.h>
#include <binder/IServiceManager.h>
#include <binder/ProcessState.h>
-#include <hidl/ServiceManagement.h>
-#include <hostapd_hidl_call_util.h>
-#include <hostapd_hidl_test_utils.h>
-#include <wifi_hidl_test_utils.h>
-#include <wifi_hidl_test_utils_1_5.h>
+#include "wifi_aidl_test_utils.h"
+
+using aidl::android::hardware::wifi::IWifi;
+using aidl::android::hardware::wifi::IWifiApIface;
using aidl::android::hardware::wifi::hostapd::BandMask;
using aidl::android::hardware::wifi::hostapd::BnHostapdCallback;
using aidl::android::hardware::wifi::hostapd::ChannelBandwidth;
@@ -44,6 +42,8 @@
using android::ProcessState;
namespace {
+const std::string kWifiInstanceNameStr = std::string() + IWifi::descriptor + "/default";
+const char* kWifiInstanceName = kWifiInstanceNameStr.c_str();
const unsigned char kNwSsid[] = {'t', 'e', 's', 't', '1', '2', '3', '4', '5'};
const std::string kPassphrase = "test12345";
const std::string kInvalidMinPassphrase = "test";
@@ -75,17 +75,13 @@
"/system/bin/cmd wifi get-softap-supported-features",
"wifi_softap_wpa3_sae_supported");
isBridgedSupport = testing::checkSubstringInCommandOutput(
- "/system/bin/cmd wifi get-softap-supported-features",
- "wifi_softap_bridged_ap_supported");
- const std::vector<std::string> instances = android::hardware::getAllHalInstanceNames(
- ::android::hardware::wifi::V1_0::IWifi::descriptor);
- EXPECT_NE(0, instances.size());
- wifiInstanceName = instances[0];
+ "/system/bin/cmd wifi get-softap-supported-features",
+ "wifi_softap_bridged_ap_supported");
}
virtual void TearDown() override {
- if (getWifi(wifiInstanceName) != nullptr) {
- stopWifi(wifiInstanceName);
+ if (getWifi(kWifiInstanceName) != nullptr) {
+ stopWifiService(kWifiInstanceName);
}
hostapd->terminate();
// Wait 3 seconds to allow terminate to complete
@@ -93,24 +89,23 @@
}
std::shared_ptr<IHostapd> hostapd;
- std::string wifiInstanceName;
bool isAcsSupport;
bool isWpa3SaeSupport;
bool isBridgedSupport;
std::string setupApIfaceAndGetName(bool isBridged) {
- android::sp<::android::hardware::wifi::V1_0::IWifiApIface> wifi_ap_iface;
+ std::shared_ptr<IWifiApIface> wifi_ap_iface;
if (isBridged) {
- wifi_ap_iface = getBridgedWifiApIface_1_5(wifiInstanceName);
+ wifi_ap_iface = getBridgedWifiApIface(kWifiInstanceName);
} else {
- wifi_ap_iface = getWifiApIface_1_5(wifiInstanceName);
+ wifi_ap_iface = getWifiApIface(kWifiInstanceName);
}
EXPECT_NE(nullptr, wifi_ap_iface.get());
- const auto& status_and_name = HIDL_INVOKE(wifi_ap_iface, getName);
- EXPECT_EQ(android::hardware::wifi::V1_0::WifiStatusCode::SUCCESS,
- status_and_name.first.code);
- return status_and_name.second;
+ std::string ap_iface_name;
+ auto status = wifi_ap_iface->getName(&ap_iface_name);
+ EXPECT_TRUE(status.isOk());
+ return ap_iface_name;
}
IfaceParams getIfaceParamsWithoutAcs(std::string iface_name) {
diff --git a/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp
index ded9122..e84a5cf 100644
--- a/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp
+++ b/wifi/netlinkinterceptor/aidl/default/InterceptorRelay.cpp
@@ -28,7 +28,7 @@
using namespace std::chrono_literals;
static constexpr std::chrono::milliseconds kPollTimeout = 300ms;
-static constexpr bool kSuperVerbose = true;
+static constexpr bool kSuperVerbose = false;
InterceptorRelay::InterceptorRelay(uint32_t nlFamily, uint32_t clientNlPid,
const std::string& clientName)
diff --git a/wifi/netlinkinterceptor/aidl/default/OWNERS b/wifi/netlinkinterceptor/aidl/default/OWNERS
deleted file mode 100644
index b738dac..0000000
--- a/wifi/netlinkinterceptor/aidl/default/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-chrisweir@google.com
-twasilczyk@google.com
diff --git a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
index 00cae32..671cd85 100644
--- a/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
+++ b/wifi/netlinkinterceptor/libnlinterceptor/Android.bp
@@ -37,10 +37,8 @@
"libutils",
],
sanitize: {
- address: true,
undefined: true,
all_undefined: true,
- fuzzer: true,
cfi: true,
integer_overflow: true,
scs: true,
diff --git a/wifi/netlinkinterceptor/vts/OWNERS b/wifi/netlinkinterceptor/vts/OWNERS
deleted file mode 100644
index b738dac..0000000
--- a/wifi/netlinkinterceptor/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-chrisweir@google.com
-twasilczyk@google.com
diff --git a/wifi/offload/1.0/vts/OWNERS b/wifi/offload/1.0/vts/OWNERS
deleted file mode 100644
index 287152d..0000000
--- a/wifi/offload/1.0/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 33618
-arabawy@google.com
-etancohen@google.com
diff --git a/wifi/supplicant/1.0/vts/OWNERS b/wifi/supplicant/1.0/vts/OWNERS
deleted file mode 100644
index b16dc11..0000000
--- a/wifi/supplicant/1.0/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.3/vts/OWNERS
diff --git a/wifi/supplicant/1.1/vts/OWNERS b/wifi/supplicant/1.1/vts/OWNERS
deleted file mode 100644
index b16dc11..0000000
--- a/wifi/supplicant/1.1/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.3/vts/OWNERS
diff --git a/wifi/supplicant/1.2/vts/OWNERS b/wifi/supplicant/1.2/vts/OWNERS
deleted file mode 100644
index b16dc11..0000000
--- a/wifi/supplicant/1.2/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.3/vts/OWNERS
diff --git a/wifi/supplicant/1.4/vts/OWNERS b/wifi/supplicant/1.4/vts/OWNERS
deleted file mode 100644
index b16dc11..0000000
--- a/wifi/supplicant/1.4/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 33618
-include ../../1.3/vts/OWNERS
diff --git a/wifi/supplicant/OWNERS b/wifi/supplicant/OWNERS
deleted file mode 100644
index 7febd60..0000000
--- a/wifi/supplicant/OWNERS
+++ /dev/null
@@ -1,5 +0,0 @@
-# Bug component: 33618
-arabawy@google.com
-etancohen@google.com
-gbiren@google.com
-lzye@google.com
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
index 8d9f498..da3ca52 100644
--- 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
@@ -52,4 +52,5 @@
oneway void onStaDeauthorized(in byte[] srcAddress, in byte[] p2pDeviceAddress);
oneway void onGroupFrequencyChanged(in String groupIfname, in int frequency);
oneway void onDeviceFoundWithVendorElements(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, in byte[] vendorElemBytes);
+ oneway void onGroupStartedWithParams(in android.hardware.wifi.supplicant.P2pGroupStartedEventParams groupStartedEventParams);
}
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
index 25a09b4..c7dd584 100644
--- 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
@@ -63,4 +63,5 @@
oneway void onWpsEventSuccess();
oneway void onQosPolicyReset();
oneway void onQosPolicyRequest(in int qosPolicyRequestId, in android.hardware.wifi.supplicant.QosPolicyData[] qosPolicyData);
+ oneway void onStateChangedWithAkm(in android.hardware.wifi.supplicant.StaIfaceCallbackState newState, in byte[] bssid, in int id, in byte[] ssid, in boolean filsHlpSent, in android.hardware.wifi.supplicant.KeyMgmtMask keyMgmtMask);
}
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
index 0b3cb81..0bdec34 100644
--- 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
@@ -127,6 +127,7 @@
void setWepKey(in int keyIdx, in byte[] wepKey);
void setWepTxKeyIdx(in int keyIdx);
void setRoamingConsortiumSelection(in byte[] selectedRcoi);
+ void setMinimumTlsVersionEapPhase1Param(android.hardware.wifi.supplicant.TlsVersion tlsVersion);
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;
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl
new file mode 100644
index 0000000..19611a9
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl
@@ -0,0 +1,46 @@
+/*
+ * 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.wifi.supplicant;
+@VintfStability
+parcelable P2pGroupStartedEventParams {
+ String groupInterfaceName;
+ boolean isGroupOwner;
+ byte[] ssid;
+ int frequencyMHz;
+ byte[] psk;
+ String passphrase;
+ boolean isPersistent;
+ byte[] goDeviceAddress;
+ byte[] goInterfaceAddress;
+}
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/TlsVersion.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/TlsVersion.aidl
new file mode 100644
index 0000000..22a374f
--- /dev/null
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/TlsVersion.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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.wifi.supplicant;
+@Backing(type="int") @VintfStability
+enum TlsVersion {
+ TLS_V1_0 = 0,
+ TLS_V1_1 = 1,
+ TLS_V1_2 = 2,
+ TLS_V1_3 = 3,
+}
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
index 9a0a924..32e1510 100644
--- 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
@@ -39,4 +39,6 @@
SAE_PK = 4,
WFD_R2 = 8,
TRUST_ON_FIRST_USE = 16,
+ SET_TLS_MINIMUM_VERSION = 32,
+ TLS_V1_3 = 64,
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
index 7c8c1f2..9d6fa67 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantP2pIfaceCallback.aidl
@@ -17,6 +17,7 @@
package android.hardware.wifi.supplicant;
import android.hardware.wifi.supplicant.P2pGroupCapabilityMask;
+import android.hardware.wifi.supplicant.P2pGroupStartedEventParams;
import android.hardware.wifi.supplicant.P2pProvDiscStatusCode;
import android.hardware.wifi.supplicant.P2pStatusCode;
import android.hardware.wifi.supplicant.WpsConfigMethods;
@@ -243,4 +244,11 @@
in byte[] primaryDeviceType, in String deviceName, in WpsConfigMethods configMethods,
in byte deviceCapabilities, in P2pGroupCapabilityMask groupCapabilities,
in byte[] wfdDeviceInfo, in byte[] wfdR2DeviceInfo, in byte[] vendorElemBytes);
+
+ /**
+ * Used to indicate the start of a P2P group, with some parameters describing the group.
+ *
+ * @param groupStartedEventParams Parameters describing the P2P group.
+ */
+ void onGroupStartedWithParams(in P2pGroupStartedEventParams groupStartedEventParams);
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 0730a8c..c7961fa 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -27,6 +27,7 @@
import android.hardware.wifi.supplicant.DppFailureCode;
import android.hardware.wifi.supplicant.DppProgressCode;
import android.hardware.wifi.supplicant.Hs20AnqpData;
+import android.hardware.wifi.supplicant.KeyMgmtMask;
import android.hardware.wifi.supplicant.OsuMethod;
import android.hardware.wifi.supplicant.QosPolicyData;
import android.hardware.wifi.supplicant.StaIfaceCallbackState;
@@ -252,6 +253,8 @@
* 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.
+ * <p>
+ * This callback is deprecated from AIDL v2, newer HAL should call onStateChangedWithAkm().
*
* @param newState New State of the interface. This must be one of the |State|
* values above.
@@ -303,4 +306,27 @@
* @param qosPolicyData QoS policies info requested by the AP.
*/
void onQosPolicyRequest(in int qosPolicyRequestId, in QosPolicyData[] qosPolicyData);
+
+ /**
+ * Used to indicate a state change event on this particular iface. If this
+ * event is triggered by a particular network, the |id|,
+ * |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
+ * |StaIfaceCallbackState| 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 (-1) 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 Whether FILS HLP IEs were included in this association.
+ * @param keyMgmtMask current used key mgmt mask.
+ */
+ void onStateChangedWithAkm(in StaIfaceCallbackState newState, in byte[] bssid, in int id,
+ in byte[] ssid, in boolean filsHlpSent, in KeyMgmtMask keyMgmtMask);
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
index 267f1e8..44512a9 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaNetwork.aidl
@@ -31,6 +31,7 @@
import android.hardware.wifi.supplicant.PairwiseCipherMask;
import android.hardware.wifi.supplicant.ProtoMask;
import android.hardware.wifi.supplicant.SaeH2eMode;
+import android.hardware.wifi.supplicant.TlsVersion;
/**
* Interface exposed by the supplicant for each station mode network
@@ -1118,4 +1119,16 @@
* |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
*/
void setRoamingConsortiumSelection(in byte[] selectedRcoi);
+
+ /**
+ * Set the minimum TLS version for EAP phase1 param.
+ *
+ * @param tlsVersion the TLS version
+ *
+ * @throws ServiceSpecificException with one of the following values:
+ * |SupplicantStatusCode.FAILURE_ARGS_INVALID|,
+ * |SupplicantStatusCode.FAILURE_UNKNOWN|,
+ * |SupplicantStatusCode.FAILURE_NETWORK_INVALID|
+ */
+ void setMinimumTlsVersionEapPhase1Param(TlsVersion tlsVersion);
}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.aidl
new file mode 100644
index 0000000..a04153a
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/P2pGroupStartedEventParams.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.wifi.supplicant;
+
+/**
+ * Parameters passed as part of Wifi P2P group start event.
+ */
+@VintfStability
+parcelable P2pGroupStartedEventParams {
+ /** Interface name of the group (For ex: p2p-p2p0-1). */
+ String groupInterfaceName;
+
+ /** Whether this device is owner of the group. */
+ boolean isGroupOwner;
+
+ /** SSID of the group. */
+ byte[] ssid;
+
+ /** Frequency in MHz on which this group is created. */
+ int frequencyMHz;
+
+ /** PSK used to secure the group. */
+ byte[] psk;
+
+ /** PSK passphrase used to secure the group. */
+ String passphrase;
+
+ /** Whether this group is persisted or not. */
+ boolean isPersistent;
+
+ /** MAC Address of the owner of this group. */
+ byte[/* 6 */] goDeviceAddress;
+
+ /** MAC Address of the P2P interface of the owner of this group. */
+ byte[/* 6 */] goInterfaceAddress;
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/TlsVersion.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/TlsVersion.aidl
new file mode 100644
index 0000000..316e881
--- /dev/null
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/TlsVersion.aidl
@@ -0,0 +1,29 @@
+/*
+ * 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.wifi.supplicant;
+
+/**
+ * TlsVersion: TLS version.
+ */
+@VintfStability
+@Backing(type="int")
+enum TlsVersion {
+ TLS_V1_0,
+ TLS_V1_1,
+ TLS_V1_2,
+ TLS_V1_3,
+}
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
index 08006cf..a9434c4 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/WpaDriverCapabilitiesMask.aidl
@@ -42,4 +42,12 @@
* Trust On First Use
*/
TRUST_ON_FIRST_USE = 1 << 4,
+ /**
+ * TLS minimum version
+ */
+ SET_TLS_MINIMUM_VERSION = 1 << 5,
+ /**
+ * TLS V1.3
+ */
+ TLS_V1_3 = 1 << 6,
}
diff --git a/wifi/supplicant/aidl/vts/functional/Android.bp b/wifi/supplicant/aidl/vts/functional/Android.bp
index 8e142ec..937fdc7 100644
--- a/wifi/supplicant/aidl/vts/functional/Android.bp
+++ b/wifi/supplicant/aidl/vts/functional/Android.bp
@@ -36,20 +36,11 @@
"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",
+ "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.supplicant-V2-ndk",
"libwifi-system",
"libwifi-system-iface",
- "VtsHalWifiV1_0TargetTestUtil",
- "VtsHalWifiV1_5TargetTestUtil",
- "VtsHalWifiSupplicantV1_0TargetTestUtil",
+ "VtsHalWifiTargetTestUtil",
],
test_suites: [
"general-tests",
@@ -70,20 +61,11 @@
"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",
+ "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.supplicant-V2-ndk",
"libwifi-system",
"libwifi-system-iface",
- "VtsHalWifiV1_0TargetTestUtil",
- "VtsHalWifiV1_5TargetTestUtil",
- "VtsHalWifiSupplicantV1_0TargetTestUtil",
+ "VtsHalWifiTargetTestUtil",
],
test_suites: [
"general-tests",
@@ -104,20 +86,11 @@
"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",
+ "android.hardware.wifi-V1-ndk",
+ "android.hardware.wifi.supplicant-V2-ndk",
"libwifi-system",
"libwifi-system-iface",
- "VtsHalWifiV1_0TargetTestUtil",
- "VtsHalWifiV1_5TargetTestUtil",
- "VtsHalWifiSupplicantV1_0TargetTestUtil",
+ "VtsHalWifiTargetTestUtil",
],
test_suites: [
"general-tests",
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
index b7984fa..ee0eff5 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_p2p_iface_aidl_test.cpp
@@ -37,6 +37,7 @@
using aidl::android::hardware::wifi::supplicant::MiracastMode;
using aidl::android::hardware::wifi::supplicant::P2pFrameTypeMask;
using aidl::android::hardware::wifi::supplicant::P2pGroupCapabilityMask;
+using aidl::android::hardware::wifi::supplicant::P2pGroupStartedEventParams;
using aidl::android::hardware::wifi::supplicant::P2pProvDiscStatusCode;
using aidl::android::hardware::wifi::supplicant::P2pStatusCode;
using aidl::android::hardware::wifi::supplicant::SupplicantStatusCode;
@@ -177,6 +178,10 @@
const std::vector<uint8_t>& /* vendorElemBytes */) override {
return ndk::ScopedAStatus::ok();
}
+ ::ndk::ScopedAStatus onGroupStartedWithParams(
+ const P2pGroupStartedEventParams& /* groupStartedEventParams */) override {
+ return ndk::ScopedAStatus::ok();
+ }
};
class SupplicantP2pIfaceAidlTest : public testing::TestWithParam<std::string> {
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
index 272a427..d57f539 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
@@ -206,6 +206,13 @@
QosPolicyData /* qosPolicyData */>&) override {
return ndk::ScopedAStatus::ok();
}
+ ::ndk::ScopedAStatus onStateChangedWithAkm(
+ ::aidl::android::hardware::wifi::supplicant::StaIfaceCallbackState /* newState */,
+ const std::vector<uint8_t>& /* bssid */, int32_t /* id */,
+ const std::vector<uint8_t>& /* ssid */, bool /* filsHlpSent */,
+ ::aidl::android::hardware::wifi::supplicant::KeyMgmtMask /* keyMgmtMask*/) override {
+ return ndk::ScopedAStatus::ok();
+ }
};
class SupplicantStaIfaceAidlTest : public testing::TestWithParam<std::string> {
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
index b3f70da..e5d976c 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_network_aidl_test.cpp
@@ -19,6 +19,7 @@
#include <aidl/Vintf.h>
#include <aidl/android/hardware/wifi/supplicant/BnSupplicant.h>
#include <aidl/android/hardware/wifi/supplicant/BnSupplicantStaNetworkCallback.h>
+#include <aidl/android/hardware/wifi/supplicant/TlsVersion.h>
#include <android/binder_manager.h>
#include <android/binder_status.h>
#include <binder/IServiceManager.h>
@@ -51,6 +52,7 @@
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::TlsVersion;
using aidl::android::hardware::wifi::supplicant::TransitionDisableIndication;
using aidl::android::hardware::wifi::supplicant::WpaDriverCapabilitiesMask;
using android::ProcessState;
@@ -791,6 +793,13 @@
EXPECT_TRUE(sta_network_->setRoamingConsortiumSelection(testSelection).isOk());
}
+/*
+ * SetMinimumTlsVersionEapPhase1Param
+ */
+TEST_P(SupplicantStaNetworkAidlTest, SetMinimumTlsVersionEapPhase1Param) {
+ EXPECT_TRUE(sta_network_->setMinimumTlsVersionEapPhase1Param(TlsVersion::TLS_V1_3).isOk());
+}
+
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaNetworkAidlTest);
INSTANTIATE_TEST_SUITE_P(Supplicant, SupplicantStaNetworkAidlTest,
testing::ValuesIn(android::getAidlHalInstanceNames(
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h b/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h
index 31042a2..740dc9f 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_test_utils.h
@@ -14,16 +14,18 @@
* limitations under the License.
*/
-#ifndef SUPPLICANT_TEST_UTILS_H
-#define SUPPLICANT_TEST_UTILS_H
+#pragma once
#include <VtsCoreUtil.h>
+#include <aidl/android/hardware/wifi/IWifi.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>
+#include "wifi_aidl_test_utils.h"
+
+using aidl::android::hardware::wifi::IfaceConcurrencyType;
+using aidl::android::hardware::wifi::IWifi;
+using aidl::android::hardware::wifi::IWifiChip;
using aidl::android::hardware::wifi::supplicant::IfaceInfo;
using aidl::android::hardware::wifi::supplicant::ISupplicant;
using aidl::android::hardware::wifi::supplicant::ISupplicantP2pIface;
@@ -31,6 +33,90 @@
using aidl::android::hardware::wifi::supplicant::KeyMgmtMask;
using android::wifi_system::SupplicantManager;
+const std::string kWifiInstanceName = std::string() + IWifi::descriptor + "/default";
+
+// Initialize the driver and firmware to STA mode using the vendor HAL.
+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.c_str()) != nullptr) {
+ std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(wifi_instance_name.c_str());
+ int mode_id;
+ EXPECT_TRUE(configureChipToSupportConcurrencyType(wifi_chip, IfaceConcurrencyType::STA,
+ &mode_id));
+ } else {
+ LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+ }
+}
+
+// Deinitialize the driver and firmware using the vendor HAL.
+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.c_str()) != nullptr) {
+ stopWifiService(wifi_instance_name.c_str());
+ } else {
+ LOG(WARNING) << __func__ << ": Vendor HAL not supported";
+ }
+}
+
+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);
+ }
+ LOG(ERROR) << "Supplicant not " << is_running ? "running" : "stopped";
+ return false;
+}
+
+bool waitForSupplicantStart() {
+ return waitForSupplicantState(true);
+}
+
+bool waitForSupplicantStop() {
+ return waitForSupplicantState(false);
+}
+
+bool waitForWifiHalStop(const std::string& wifi_instance_name) {
+ std::shared_ptr<IWifi> wifi = getWifi(wifi_instance_name.c_str());
+ int count = 50; /* wait at most 5 seconds for completion */
+ while (count-- > 0) {
+ if (wifi != nullptr) {
+ bool started = false;
+ auto status = wifi->isStarted(&started);
+ if (status.isOk() && !started) {
+ return true;
+ }
+ }
+ usleep(100000);
+ wifi = getWifi(wifi_instance_name.c_str());
+ }
+ LOG(ERROR) << "Wifi HAL was not stopped";
+ return false;
+}
+
+bool waitForFrameworkReady() {
+ int waitCount = 15;
+ do {
+ // Check whether package service is ready or not.
+ if (!testing::checkSubstringInCommandOutput("/system/bin/service check package",
+ ": not found")) {
+ return true;
+ }
+ LOG(INFO) << "Framework is not ready";
+ sleep(1);
+ } while (waitCount-- > 0);
+ return false;
+}
+
std::string getStaIfaceName() {
std::array<char, PROPERTY_VALUE_MAX> buffer;
property_get("wifi.interface", buffer.data(), "wlan0");
@@ -43,14 +129,6 @@
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;
@@ -68,17 +146,33 @@
}
void startSupplicant() {
- initializeDriverAndFirmware(getWifiInstanceName());
+ initializeDriverAndFirmware(kWifiInstanceName);
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 stopSupplicantService() {
+ SupplicantManager supplicant_manager;
+ ASSERT_TRUE(supplicant_manager.StopSupplicant());
+ deInitializeDriverAndFirmware(kWifiInstanceName);
+ ASSERT_FALSE(supplicant_manager.IsSupplicantRunning());
+}
+
+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(const std::string& wifi_instance_name) {
+ std::system("svc wifi disable");
+ std::system("cmd wifi set-scan-always-available disabled");
+ return waitForSupplicantStop() && waitForWifiHalStop(wifi_instance_name);
+}
void initializeService() {
- ASSERT_TRUE(stopWifiFramework(getWifiInstanceName()));
+ ASSERT_TRUE(stopWifiFramework(kWifiInstanceName));
std::system("/system/bin/start");
ASSERT_TRUE(waitForFrameworkReady());
stopSupplicantService();
@@ -106,5 +200,3 @@
}
return supplicant;
}
-
-#endif // SUPPLICANT_TEST_UTILS_H
\ No newline at end of file