Merge changes from topics "BlindSpotWarningEnabled", "ForwardCollisionWarningEnabled", "LaneDepartureWarningEnabled"
* changes:
Add HAL changes for LANE_DEPARTURE_WARNING_ENABLED
Add HAL changes for BLIND_SPOT_WARNING_ENABLED
Add HAL changes for FORWARD_COLLISION_WARNING_ENABLED
diff --git a/audio/aidl/Android.bp b/audio/aidl/Android.bp
index ef51361..e69306e 100644
--- a/audio/aidl/Android.bp
+++ b/audio/aidl/Android.bp
@@ -112,6 +112,7 @@
"android/hardware/audio/core/AudioMode.aidl",
"android/hardware/audio/core/AudioPatch.aidl",
"android/hardware/audio/core/AudioRoute.aidl",
+ "android/hardware/audio/core/IBluetooth.aidl",
"android/hardware/audio/core/IConfig.aidl",
"android/hardware/audio/core/IModule.aidl",
"android/hardware/audio/core/IStreamCallback.aidl",
diff --git a/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IBluetooth.aidl b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IBluetooth.aidl
new file mode 100644
index 0000000..289c0c2
--- /dev/null
+++ b/audio/aidl/aidl_api/android.hardware.audio.core/current/android/hardware/audio/core/IBluetooth.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.
+ */
+///////////////////////////////////////////////////////////////////////////////
+// THIS FILE IS IMMUTABLE. DO NOT EDIT IN ANY CASE. //
+///////////////////////////////////////////////////////////////////////////////
+
+// This file is a snapshot of an AIDL file. Do not edit it manually. There are
+// two cases:
+// 1). this is a frozen version file - do not edit this in any case.
+// 2). this is a 'current' file. If you make a backwards compatible change to
+// the interface (from the latest frozen version), the build system will
+// prompt you to update this file with `m <name>-update-api`.
+//
+// You must not make a backward incompatible change to any AIDL file built
+// with the aidl_interface module type with versions property set. The module
+// type is used to build AIDL files in a way that they can be used across
+// independently updatable components of the system. If a device is shipped
+// with such a backward incompatible 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 IBluetooth {
+ android.hardware.audio.core.IBluetooth.ScoConfig setScoConfig(in android.hardware.audio.core.IBluetooth.ScoConfig config);
+ android.hardware.audio.core.IBluetooth.HfpConfig setHfpConfig(in android.hardware.audio.core.IBluetooth.HfpConfig config);
+ @JavaDerive(equals=true, toString=true) @VintfStability
+ parcelable ScoConfig {
+ @nullable android.media.audio.common.Boolean isEnabled;
+ @nullable android.media.audio.common.Boolean isNrecEnabled;
+ android.hardware.audio.core.IBluetooth.ScoConfig.Mode mode = android.hardware.audio.core.IBluetooth.ScoConfig.Mode.UNSPECIFIED;
+ @nullable @utf8InCpp String debugName;
+ @VintfStability
+ enum Mode {
+ UNSPECIFIED = 0,
+ SCO = 1,
+ SCO_WB = 2,
+ SCO_SWB = 3,
+ }
+ }
+ @JavaDerive(equals=true, toString=true) @VintfStability
+ parcelable HfpConfig {
+ @nullable android.media.audio.common.Boolean isEnabled;
+ @nullable android.media.audio.common.Int sampleRate;
+ @nullable android.media.audio.common.Float volume;
+ const int VOLUME_MIN = 0;
+ const int VOLUME_MAX = 1;
+ }
+}
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 a029d43..4486b66 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
@@ -36,6 +36,7 @@
interface IModule {
void setModuleDebug(in android.hardware.audio.core.ModuleDebug debug);
@nullable android.hardware.audio.core.ITelephony getTelephony();
+ @nullable android.hardware.audio.core.IBluetooth getBluetooth();
android.media.audio.common.AudioPort connectExternalDevice(in android.media.audio.common.AudioPort templateIdAndAdditionalData);
void disconnectExternalDevice(int portId);
android.hardware.audio.core.AudioPatch[] getAudioPatches();
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
index a8c58c1..77063df 100644
--- 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
@@ -36,4 +36,21 @@
interface ITelephony {
android.hardware.audio.core.AudioMode[] getSupportedAudioModes();
void switchAudioMode(android.hardware.audio.core.AudioMode mode);
+ android.hardware.audio.core.ITelephony.TelecomConfig setTelecomConfig(in android.hardware.audio.core.ITelephony.TelecomConfig config);
+ @JavaDerive(equals=true, toString=true) @VintfStability
+ parcelable TelecomConfig {
+ @nullable android.media.audio.common.Float voiceVolume;
+ android.hardware.audio.core.ITelephony.TelecomConfig.TtyMode ttyMode = android.hardware.audio.core.ITelephony.TelecomConfig.TtyMode.UNSPECIFIED;
+ @nullable android.media.audio.common.Boolean isHacEnabled;
+ const int VOICE_VOLUME_MIN = 0;
+ const int VOICE_VOLUME_MAX = 1;
+ @Backing(type="int") @VintfStability
+ enum TtyMode {
+ UNSPECIFIED = (-1),
+ OFF = 0,
+ FULL = 1,
+ HCO = 2,
+ VCO = 3,
+ }
+ }
}
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
index 40a8d72..959594b 100644
--- 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
@@ -35,7 +35,7 @@
@VintfStability
union HapticGenerator {
android.hardware.audio.effect.VendorExtension vendorExtension;
- android.hardware.audio.effect.HapticGenerator.HapticScale hapticScale;
+ android.hardware.audio.effect.HapticGenerator.HapticScale[] hapticScales;
android.hardware.audio.effect.HapticGenerator.VibratorInformation vibratorInfo;
@VintfStability
union Id {
diff --git a/audio/aidl/android/hardware/audio/core/IBluetooth.aidl b/audio/aidl/android/hardware/audio/core/IBluetooth.aidl
new file mode 100644
index 0000000..21ac8e2
--- /dev/null
+++ b/audio/aidl/android/hardware/audio/core/IBluetooth.aidl
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS 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.Boolean;
+import android.media.audio.common.Float;
+import android.media.audio.common.Int;
+
+/**
+ * An instance of IBluetooth manages settings for the Hands-Free Profile (HFP)
+ * and the SCO Link. This interface is optional to implement and provide by the
+ * vendor. It needs to be provided only if the device actually supports BT SCO
+ * or HFP.
+ */
+@VintfStability
+interface IBluetooth {
+ @JavaDerive(equals=true, toString=true)
+ @VintfStability
+ parcelable ScoConfig {
+ /**
+ * Whether BT SCO is enabled. The client might need to disable it
+ * when another profile (for example, A2DP) is activated.
+ */
+ @nullable Boolean isEnabled;
+ /**
+ * Whether BT SCO Noise Reduction and Echo Cancellation are enabled.
+ */
+ @nullable Boolean isNrecEnabled;
+ @VintfStability enum Mode { UNSPECIFIED, SCO, SCO_WB, SCO_SWB }
+ /**
+ * If set, specifies the SCO mode to use:
+ * regular, wide band (WB), or super wide band (SWB).
+ */
+ Mode mode = Mode.UNSPECIFIED;
+ /**
+ * The name of the BT SCO headset used for debugging purposes. Can be empty.
+ */
+ @nullable @utf8InCpp String debugName;
+ }
+
+ /**
+ * Set the configuration of Bluetooth SCO.
+ *
+ * In the provided parcelable, the client sets zero, one or more parameters
+ * which have to be updated on the HAL side. The parameters that are left
+ * unset must retain their current values. It is allowed to change
+ * parameters while the SCO profile is disabled (isEnabled.value == false).
+ *
+ * In the returned parcelable, all parameter fields known to the HAL module
+ * must be populated to their current values. If the SCO profile is
+ * currently disabled (isEnabled.value == false), the parameters must
+ * reflect the last values that were in use.
+ *
+ * The client can pass an uninitialized parcelable in order to retrieve the
+ * current configuration.
+ *
+ * @return The current configuration (after update). All fields known to
+ * the HAL must be populated.
+ * @param config The configuration to set. Any number of fields may be left
+ * uninitialized.
+ * @throws EX_UNSUPPORTED_OPERATION If BT SCO is not supported.
+ * @throws EX_ILLEGAL_ARGUMENT If the requested combination of parameter
+ * values is invalid.
+ */
+ ScoConfig setScoConfig(in ScoConfig config);
+
+ @JavaDerive(equals=true, toString=true)
+ @VintfStability
+ parcelable HfpConfig {
+ /**
+ * Whether BT HFP is enabled.
+ */
+ @nullable Boolean isEnabled;
+ /**
+ * The sample rate of BT HFP, in Hertz. Must be a positive number.
+ */
+ @nullable Int sampleRate;
+
+ const int VOLUME_MIN = 0;
+ const int VOLUME_MAX = 1;
+ /**
+ * The output volume of BT HFP. 1.0f means unity gain, 0.0f is muted,
+ * see VOLUME_* constants;
+ */
+ @nullable Float volume;
+ }
+
+ /**
+ * Set the configuration of Bluetooth HFP.
+ *
+ * In the provided parcelable, the client sets zero, one or more parameters
+ * which have to be updated on the HAL side. The parameters that are left
+ * unset must retain their current values. It is allowed to change
+ * parameters while the HFP profile is disabled (isEnabled.value == false).
+ *
+ * In the returned parcelable, all parameter fields known to the HAL module
+ * must be populated to their current values. If the HFP profile is
+ * currently disabled (isEnabled.value == false), the parameters must
+ * reflect the last values that were in use.
+ *
+ * The client can pass an uninitialized parcelable in order to retrieve the
+ * current configuration.
+ *
+ * @return The current configuration (after update). All fields known to
+ * the HAL must be populated.
+ * @param config The configuration to set. Any number of fields may be left
+ * uninitialized.
+ * @throws EX_UNSUPPORTED_OPERATION If BT HFP is not supported.
+ * @throws EX_ILLEGAL_ARGUMENT If the requested combination of parameter
+ * values is invalid.
+ */
+ HfpConfig setHfpConfig(in HfpConfig config);
+}
diff --git a/audio/aidl/android/hardware/audio/core/IModule.aidl b/audio/aidl/android/hardware/audio/core/IModule.aidl
index 4779f1f..7bc1b9c 100644
--- a/audio/aidl/android/hardware/audio/core/IModule.aidl
+++ b/audio/aidl/android/hardware/audio/core/IModule.aidl
@@ -21,6 +21,7 @@
import android.hardware.audio.core.AudioMode;
import android.hardware.audio.core.AudioPatch;
import android.hardware.audio.core.AudioRoute;
+import android.hardware.audio.core.IBluetooth;
import android.hardware.audio.core.IStreamCallback;
import android.hardware.audio.core.IStreamIn;
import android.hardware.audio.core.IStreamOut;
@@ -86,6 +87,20 @@
@nullable ITelephony getTelephony();
/**
+ * Retrieve the interface to control Bluetooth SCO and HFP.
+ *
+ * If the HAL module supports either the SCO Link or Hands-Free Profile
+ * functionality (or both) for Bluetooth, it must return an instance of the
+ * IBluetooth interface. The same instance must be returned during the
+ * lifetime of the HAL module. If the HAL module does not support BT SCO and
+ * HFP, a null must be returned, without throwing any errors.
+ *
+ * @return An instance of the IBluetooth interface implementation.
+ * @throws EX_ILLEGAL_STATE If there was an error creating an instance.
+ */
+ @nullable IBluetooth getBluetooth();
+
+ /**
* 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
diff --git a/audio/aidl/android/hardware/audio/core/ITelephony.aidl b/audio/aidl/android/hardware/audio/core/ITelephony.aidl
index a872c7c..a817032 100644
--- a/audio/aidl/android/hardware/audio/core/ITelephony.aidl
+++ b/audio/aidl/android/hardware/audio/core/ITelephony.aidl
@@ -17,6 +17,8 @@
package android.hardware.audio.core;
import android.hardware.audio.core.AudioMode;
+import android.media.audio.common.Boolean;
+import android.media.audio.common.Float;
/**
* An instance of ITelephony manages settings which are specific to voice calls
@@ -53,4 +55,75 @@
* @throws EX_ILLEGAL_STATE If there was an error during switching.
*/
void switchAudioMode(AudioMode mode);
+
+ @JavaDerive(equals=true, toString=true)
+ @VintfStability
+ parcelable TelecomConfig {
+ const int VOICE_VOLUME_MIN = 0;
+ const int VOICE_VOLUME_MAX = 1;
+ /**
+ * Volume of a voice call. 1.0f means unity gain, 0.0f is muted,
+ * see VOLUME_* constants.
+ */
+ @nullable Float voiceVolume;
+ /**
+ * The current mode of teletypewritter (TTY).
+ */
+ @VintfStability
+ @Backing(type="int")
+ enum TtyMode {
+ /**
+ * The default uninitialized value.
+ */
+ UNSPECIFIED = -1,
+ /**
+ * TTY mode is off.
+ */
+ OFF = 0,
+ /**
+ * TTY mode is on. The speaker is off and the microphone is muted. The
+ * user will communicate with the remote party by sending and receiving
+ * text messages.
+ */
+ FULL = 1,
+ /**
+ * TTY mode is in hearing carryover mode (HCO). The microphone is muted
+ * but the speaker is on. The user will communicate with the remote
+ * party by sending text messages and hearing an audible reply.
+ */
+ HCO = 2,
+ /**
+ * TTY mode is in voice carryover mode (VCO). The speaker is off but the
+ * microphone is still on. User will communicate with the remote party
+ * by speaking and receiving text message replies.
+ */
+ VCO = 3,
+ }
+ TtyMode ttyMode = TtyMode.UNSPECIFIED;
+ /**
+ * Whether Hearing Aid Compatibility - Telecoil (HAC-T) mode is enabled.
+ */
+ @nullable Boolean isHacEnabled;
+ }
+
+ /**
+ * Set the configuration of the telephony audio.
+ *
+ * In the provided parcelable, the client sets zero, one or more parameters
+ * which have to be updated on the HAL side. The parameters that are left
+ * unset must retain their current values.
+ *
+ * In the returned parcelable, all parameter fields known to the HAL module
+ * must be populated to their current values.The client can pass an
+ * uninitialized parcelable in order to retrieve the current configuration.
+ *
+ * @return The current configuration (after update). All fields known to
+ * the HAL must be populated.
+ * @param config The configuration to set. Any number of fields may be left
+ * uninitialized.
+ * @throws EX_UNSUPPORTED_OPERATION If telephony is not supported.
+ * @throws EX_ILLEGAL_ARGUMENT If the requested combination of parameter
+ * values is invalid.
+ */
+ TelecomConfig setTelecomConfig(in TelecomConfig config);
}
diff --git a/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl b/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl
index 944155f..3063ee3 100644
--- a/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl
+++ b/audio/aidl/android/hardware/audio/effect/HapticGenerator.aidl
@@ -90,6 +90,6 @@
float maxAmplitude;
}
- HapticScale hapticScale;
+ HapticScale[] hapticScales;
VibratorInformation vibratorInfo;
}
diff --git a/audio/aidl/default/Android.bp b/audio/aidl/default/Android.bp
index 8cd56c0..6f23636 100644
--- a/audio/aidl/default/Android.bp
+++ b/audio/aidl/default/Android.bp
@@ -62,6 +62,7 @@
export_include_dirs: ["include"],
srcs: [
"AudioPolicyConfigXmlConverter.cpp",
+ "Bluetooth.cpp",
"Config.cpp",
"Configuration.cpp",
"EngineConfigXmlConverter.cpp",
diff --git a/audio/aidl/default/Bluetooth.cpp b/audio/aidl/default/Bluetooth.cpp
new file mode 100644
index 0000000..38e0c21
--- /dev/null
+++ b/audio/aidl/default/Bluetooth.cpp
@@ -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.
+ */
+
+#define LOG_TAG "AHAL_Bluetooth"
+#include <android-base/logging.h>
+
+#include "core-impl/Bluetooth.h"
+
+using aidl::android::media::audio::common::Boolean;
+using aidl::android::media::audio::common::Float;
+using aidl::android::media::audio::common::Int;
+
+namespace aidl::android::hardware::audio::core {
+
+Bluetooth::Bluetooth() {
+ mScoConfig.isEnabled = Boolean{false};
+ mScoConfig.isNrecEnabled = Boolean{false};
+ mScoConfig.mode = ScoConfig::Mode::SCO;
+ mHfpConfig.isEnabled = Boolean{false};
+ mHfpConfig.sampleRate = Int{8000};
+ mHfpConfig.volume = Float{HfpConfig::VOLUME_MAX};
+}
+
+ndk::ScopedAStatus Bluetooth::setScoConfig(const ScoConfig& in_config, ScoConfig* _aidl_return) {
+ if (in_config.isEnabled.has_value()) {
+ mScoConfig.isEnabled = in_config.isEnabled;
+ }
+ if (in_config.isNrecEnabled.has_value()) {
+ mScoConfig.isNrecEnabled = in_config.isNrecEnabled;
+ }
+ if (in_config.mode != ScoConfig::Mode::UNSPECIFIED) {
+ mScoConfig.mode = in_config.mode;
+ }
+ if (in_config.debugName.has_value()) {
+ mScoConfig.debugName = in_config.debugName;
+ }
+ *_aidl_return = mScoConfig;
+ LOG(DEBUG) << __func__ << ": received " << in_config.toString() << ", returning "
+ << _aidl_return->toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+ndk::ScopedAStatus Bluetooth::setHfpConfig(const HfpConfig& in_config, HfpConfig* _aidl_return) {
+ if (in_config.sampleRate.has_value() && in_config.sampleRate.value().value <= 0) {
+ LOG(ERROR) << __func__ << ": invalid sample rate: " << in_config.sampleRate.value().value;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ if (in_config.volume.has_value() && (in_config.volume.value().value < HfpConfig::VOLUME_MIN ||
+ in_config.volume.value().value > HfpConfig::VOLUME_MAX)) {
+ LOG(ERROR) << __func__ << ": invalid volume: " << in_config.volume.value().value;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ if (in_config.isEnabled.has_value()) {
+ mHfpConfig.isEnabled = in_config.isEnabled;
+ }
+ if (in_config.sampleRate.has_value()) {
+ mHfpConfig.sampleRate = in_config.sampleRate;
+ }
+ if (in_config.volume.has_value()) {
+ mHfpConfig.volume = in_config.volume;
+ }
+ *_aidl_return = mHfpConfig;
+ LOG(DEBUG) << __func__ << ": received " << in_config.toString() << ", returning "
+ << _aidl_return->toString();
+ return ndk::ScopedAStatus::ok();
+}
+
+} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/Module.cpp b/audio/aidl/default/Module.cpp
index b58c562..e8b5bfc 100644
--- a/audio/aidl/default/Module.cpp
+++ b/audio/aidl/default/Module.cpp
@@ -25,6 +25,7 @@
#include <aidl/android/media/audio/common/AudioInputFlags.h>
#include <aidl/android/media/audio/common/AudioOutputFlags.h>
+#include "core-impl/Bluetooth.h"
#include "core-impl/Module.h"
#include "core-impl/SoundDose.h"
#include "core-impl/Telephony.h"
@@ -326,6 +327,18 @@
return ndk::ScopedAStatus::ok();
}
+ndk::ScopedAStatus Module::getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) {
+ if (mBluetooth == nullptr) {
+ mBluetooth = ndk::SharedRefBase::make<Bluetooth>();
+ mBluetoothBinder = mBluetooth->asBinder();
+ AIBinder_setMinSchedulerPolicy(mBluetoothBinder.get(), SCHED_NORMAL,
+ ANDROID_PRIORITY_AUDIO);
+ }
+ *_aidl_return = mBluetooth;
+ LOG(DEBUG) << __func__ << ": returning instance of IBluetooth: " << _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;
diff --git a/audio/aidl/default/Telephony.cpp b/audio/aidl/default/Telephony.cpp
index 1854b35..d873178 100644
--- a/audio/aidl/default/Telephony.cpp
+++ b/audio/aidl/default/Telephony.cpp
@@ -20,8 +20,17 @@
#include "core-impl/Telephony.h"
+using aidl::android::media::audio::common::Boolean;
+using aidl::android::media::audio::common::Float;
+
namespace aidl::android::hardware::audio::core {
+Telephony::Telephony() {
+ mTelecomConfig.voiceVolume = Float{TelecomConfig::VOICE_VOLUME_MAX};
+ mTelecomConfig.ttyMode = TelecomConfig::TtyMode::OFF;
+ mTelecomConfig.isHacEnabled = Boolean{false};
+}
+
ndk::ScopedAStatus Telephony::getSupportedAudioModes(std::vector<AudioMode>* _aidl_return) {
*_aidl_return = mSupportedAudioModes;
LOG(DEBUG) << __func__ << ": returning " << ::android::internal::ToString(*_aidl_return);
@@ -38,4 +47,28 @@
return ndk::ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
+ndk::ScopedAStatus Telephony::setTelecomConfig(const TelecomConfig& in_config,
+ TelecomConfig* _aidl_return) {
+ if (in_config.voiceVolume.has_value() &&
+ (in_config.voiceVolume.value().value < TelecomConfig::VOICE_VOLUME_MIN ||
+ in_config.voiceVolume.value().value > TelecomConfig::VOICE_VOLUME_MAX)) {
+ LOG(ERROR) << __func__
+ << ": voice volume value is invalid: " << in_config.voiceVolume.value().value;
+ return ndk::ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+ if (in_config.voiceVolume.has_value()) {
+ mTelecomConfig.voiceVolume = in_config.voiceVolume;
+ }
+ if (in_config.ttyMode != TelecomConfig::TtyMode::UNSPECIFIED) {
+ mTelecomConfig.ttyMode = in_config.ttyMode;
+ }
+ if (in_config.isHacEnabled.has_value()) {
+ mTelecomConfig.isHacEnabled = in_config.isHacEnabled;
+ }
+ *_aidl_return = mTelecomConfig;
+ LOG(DEBUG) << __func__ << ": received " << in_config.toString() << ", returning "
+ << _aidl_return->toString();
+ return ndk::ScopedAStatus::ok();
+}
+
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
index f6211c4..3c3b66f 100644
--- a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.cpp
@@ -90,8 +90,8 @@
auto tag = hgParam.getTag();
switch (tag) {
- case HapticGenerator::hapticScale: {
- RETURN_IF(mContext->setHgHapticScale(hgParam.get<HapticGenerator::hapticScale>()) !=
+ case HapticGenerator::hapticScales: {
+ RETURN_IF(mContext->setHgHapticScales(hgParam.get<HapticGenerator::hapticScales>()) !=
RetCode::SUCCESS,
EX_ILLEGAL_ARGUMENT, "HapticScaleNotSupported");
return ndk::ScopedAStatus::ok();
@@ -133,8 +133,8 @@
HapticGenerator hgParam;
switch (tag) {
- case HapticGenerator::hapticScale: {
- hgParam.set<HapticGenerator::hapticScale>(mContext->getHgHapticScale());
+ case HapticGenerator::hapticScales: {
+ hgParam.set<HapticGenerator::hapticScales>(mContext->getHgHapticScales());
break;
}
case HapticGenerator::vibratorInfo: {
@@ -183,4 +183,20 @@
return {STATUS_OK, samples, samples};
}
+RetCode HapticGeneratorSwContext::setHgHapticScales(
+ const std::vector<HapticGenerator::HapticScale>& hapticScales) {
+ // Assume any audio track ID is valid
+ for (auto& it : hapticScales) {
+ mHapticScales[it.id] = it;
+ }
+ return RetCode::SUCCESS;
+}
+
+std::vector<HapticGenerator::HapticScale> HapticGeneratorSwContext::getHgHapticScales() const {
+ std::vector<HapticGenerator::HapticScale> result;
+ std::transform(mHapticScales.begin(), mHapticScales.end(), std::back_inserter(result),
+ [](auto& scaleIt) { return scaleIt.second; });
+ return result;
+}
+
} // namespace aidl::android::hardware::audio::effect
diff --git a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
index d9ec744..7159501 100644
--- a/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
+++ b/audio/aidl/default/hapticGenerator/HapticGeneratorSw.h
@@ -33,12 +33,8 @@
LOG(DEBUG) << __func__;
}
- RetCode setHgHapticScale(const HapticGenerator::HapticScale& hapticScale) {
- // All int values are valid for ID
- mHapticScale = hapticScale;
- return RetCode::SUCCESS;
- }
- HapticGenerator::HapticScale getHgHapticScale() const { return mHapticScale; }
+ RetCode setHgHapticScales(const std::vector<HapticGenerator::HapticScale>& hapticScales);
+ std::vector<HapticGenerator::HapticScale> getHgHapticScales() const;
RetCode setHgVibratorInformation(const HapticGenerator::VibratorInformation& vibratorInfo) {
// All float values are valid for resonantFrequencyHz, qFactor, maxAmplitude
@@ -54,7 +50,7 @@
static constexpr float DEFAULT_RESONANT_FREQUENCY = 150.0f;
static constexpr float DEFAULT_Q_FACTOR = 1.0f;
static constexpr float DEFAULT_MAX_AMPLITUDE = 0.0f;
- HapticGenerator::HapticScale mHapticScale = {0, HapticGenerator::VibratorScale::MUTE};
+ std::map<int /* trackID */, HapticGenerator::HapticScale> mHapticScales;
HapticGenerator::VibratorInformation mVibratorInformation = {
DEFAULT_RESONANT_FREQUENCY, DEFAULT_Q_FACTOR, DEFAULT_MAX_AMPLITUDE};
};
diff --git a/audio/aidl/default/include/core-impl/Bluetooth.h b/audio/aidl/default/include/core-impl/Bluetooth.h
new file mode 100644
index 0000000..f2e762d
--- /dev/null
+++ b/audio/aidl/default/include/core-impl/Bluetooth.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.
+ */
+
+#pragma once
+
+#include <aidl/android/hardware/audio/core/BnBluetooth.h>
+
+namespace aidl::android::hardware::audio::core {
+
+class Bluetooth : public BnBluetooth {
+ public:
+ Bluetooth();
+
+ private:
+ ndk::ScopedAStatus setScoConfig(const ScoConfig& in_config, ScoConfig* _aidl_return) override;
+ ndk::ScopedAStatus setHfpConfig(const HfpConfig& in_config, HfpConfig* _aidl_return) override;
+
+ ScoConfig mScoConfig;
+ HfpConfig mHfpConfig;
+};
+
+} // 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 faca61e..e9f43d8 100644
--- a/audio/aidl/default/include/core-impl/Module.h
+++ b/audio/aidl/default/include/core-impl/Module.h
@@ -39,6 +39,7 @@
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 getBluetooth(std::shared_ptr<IBluetooth>* _aidl_return) override;
ndk::ScopedAStatus connectExternalDevice(
const ::aidl::android::media::audio::common::AudioPort& in_templateIdAndAdditionalData,
::aidl::android::media::audio::common::AudioPort* _aidl_return) override;
@@ -127,10 +128,12 @@
const Type mType;
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.
+ // For the interfaces requiring to return the same instance, we need to hold them
+ // via a strong pointer. The binder token is retained for a call to 'setMinSchedulerPolicy'.
std::shared_ptr<ITelephony> mTelephony;
ndk::SpAIBinder mTelephonyBinder;
+ std::shared_ptr<IBluetooth> mBluetooth;
+ ndk::SpAIBinder mBluetoothBinder;
// ids of ports created at runtime via 'connectExternalDevice'.
std::set<int32_t> mConnectedDevicePorts;
Streams mStreams;
diff --git a/audio/aidl/default/include/core-impl/Telephony.h b/audio/aidl/default/include/core-impl/Telephony.h
index 597f3d6..0936172 100644
--- a/audio/aidl/default/include/core-impl/Telephony.h
+++ b/audio/aidl/default/include/core-impl/Telephony.h
@@ -23,12 +23,18 @@
namespace aidl::android::hardware::audio::core {
class Telephony : public BnTelephony {
+ public:
+ Telephony();
+
private:
ndk::ScopedAStatus getSupportedAudioModes(std::vector<AudioMode>* _aidl_return) override;
ndk::ScopedAStatus switchAudioMode(AudioMode in_mode) override;
+ ndk::ScopedAStatus setTelecomConfig(const TelecomConfig& in_config,
+ TelecomConfig* _aidl_return) override;
const std::vector<AudioMode> mSupportedAudioModes = {::ndk::enum_range<AudioMode>().begin(),
::ndk::enum_range<AudioMode>().end()};
+ TelecomConfig mTelecomConfig;
};
} // namespace aidl::android::hardware::audio::core
diff --git a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
index 50a93ce..8da475e 100644
--- a/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalAudioCoreModuleTargetTest.cpp
@@ -56,6 +56,7 @@
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::IBluetooth;
using aidl::android::hardware::audio::core::IModule;
using aidl::android::hardware::audio::core::IStreamCommon;
using aidl::android::hardware::audio::core::IStreamIn;
@@ -84,6 +85,8 @@
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::Float;
+using aidl::android::media::audio::common::Int;
using aidl::android::media::audio::common::Void;
using android::hardware::audio::common::getChannelCount;
using android::hardware::audio::common::isBitPositionFlagSet;
@@ -1775,6 +1778,89 @@
}
}
+class AudioCoreBluetooth : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
+ public:
+ void SetUp() override {
+ ASSERT_NO_FATAL_FAILURE(SetUpImpl(GetParam()));
+ ASSERT_IS_OK(module->getBluetooth(&bluetooth));
+ }
+
+ void TearDown() override { ASSERT_NO_FATAL_FAILURE(TearDownImpl()); }
+
+ std::shared_ptr<IBluetooth> bluetooth;
+};
+
+TEST_P(AudioCoreBluetooth, SameInstance) {
+ if (bluetooth == nullptr) {
+ GTEST_SKIP() << "Bluetooth is not supported";
+ }
+ std::shared_ptr<IBluetooth> bluetooth2;
+ EXPECT_IS_OK(module->getBluetooth(&bluetooth2));
+ ASSERT_NE(nullptr, bluetooth2.get());
+ EXPECT_EQ(bluetooth->asBinder(), bluetooth2->asBinder())
+ << "getBluetooth must return the same interface instance across invocations";
+}
+
+TEST_P(AudioCoreBluetooth, ScoConfig) {
+ static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
+ if (bluetooth == nullptr) {
+ GTEST_SKIP() << "Bluetooth is not supported";
+ }
+ ndk::ScopedAStatus status;
+ IBluetooth::ScoConfig scoConfig;
+ ASSERT_STATUS(kStatuses, status = bluetooth->setScoConfig({}, &scoConfig));
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "BT SCO is not supported";
+ }
+ EXPECT_TRUE(scoConfig.isEnabled.has_value());
+ EXPECT_TRUE(scoConfig.isNrecEnabled.has_value());
+ EXPECT_NE(IBluetooth::ScoConfig::Mode::UNSPECIFIED, scoConfig.mode);
+ IBluetooth::ScoConfig scoConfig2;
+ ASSERT_IS_OK(bluetooth->setScoConfig(scoConfig, &scoConfig2));
+ EXPECT_EQ(scoConfig, scoConfig2);
+}
+
+TEST_P(AudioCoreBluetooth, HfpConfig) {
+ static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
+ if (bluetooth == nullptr) {
+ GTEST_SKIP() << "Bluetooth is not supported";
+ }
+ ndk::ScopedAStatus status;
+ IBluetooth::HfpConfig hfpConfig;
+ ASSERT_STATUS(kStatuses, status = bluetooth->setHfpConfig({}, &hfpConfig));
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "BT HFP is not supported";
+ }
+ EXPECT_TRUE(hfpConfig.isEnabled.has_value());
+ EXPECT_TRUE(hfpConfig.sampleRate.has_value());
+ EXPECT_TRUE(hfpConfig.volume.has_value());
+ IBluetooth::HfpConfig hfpConfig2;
+ ASSERT_IS_OK(bluetooth->setHfpConfig(hfpConfig, &hfpConfig2));
+ EXPECT_EQ(hfpConfig, hfpConfig2);
+}
+
+TEST_P(AudioCoreBluetooth, HfpConfigInvalid) {
+ static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
+ if (bluetooth == nullptr) {
+ GTEST_SKIP() << "Bluetooth is not supported";
+ }
+ ndk::ScopedAStatus status;
+ IBluetooth::HfpConfig hfpConfig;
+ ASSERT_STATUS(kStatuses, status = bluetooth->setHfpConfig({}, &hfpConfig));
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "BT HFP is not supported";
+ }
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+ bluetooth->setHfpConfig({.sampleRate = Int{-1}}, &hfpConfig));
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT, bluetooth->setHfpConfig({.sampleRate = Int{0}}, &hfpConfig));
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+ bluetooth->setHfpConfig({.volume = Float{IBluetooth::HfpConfig::VOLUME_MIN - 1}},
+ &hfpConfig));
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+ bluetooth->setHfpConfig({.volume = Float{IBluetooth::HfpConfig::VOLUME_MAX + 1}},
+ &hfpConfig));
+}
+
class AudioCoreTelephony : public AudioCoreModuleBase, public testing::TestWithParam<std::string> {
public:
void SetUp() override {
@@ -1787,6 +1873,17 @@
std::shared_ptr<ITelephony> telephony;
};
+TEST_P(AudioCoreTelephony, SameInstance) {
+ if (telephony == nullptr) {
+ GTEST_SKIP() << "Telephony is not supported";
+ }
+ std::shared_ptr<ITelephony> telephony2;
+ EXPECT_IS_OK(module->getTelephony(&telephony2));
+ ASSERT_NE(nullptr, telephony2.get());
+ EXPECT_EQ(telephony->asBinder(), telephony2->asBinder())
+ << "getTelephony must return the same interface instance across invocations";
+}
+
TEST_P(AudioCoreTelephony, GetSupportedAudioModes) {
if (telephony == nullptr) {
GTEST_SKIP() << "Telephony is not supported";
@@ -1828,6 +1925,46 @@
}
}
+TEST_P(AudioCoreTelephony, TelecomConfig) {
+ static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
+ if (telephony == nullptr) {
+ GTEST_SKIP() << "Telephony is not supported";
+ }
+ ndk::ScopedAStatus status;
+ ITelephony::TelecomConfig telecomConfig;
+ ASSERT_STATUS(kStatuses, status = telephony->setTelecomConfig({}, &telecomConfig));
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "Telecom is not supported";
+ }
+ EXPECT_TRUE(telecomConfig.voiceVolume.has_value());
+ EXPECT_NE(ITelephony::TelecomConfig::TtyMode::UNSPECIFIED, telecomConfig.ttyMode);
+ EXPECT_TRUE(telecomConfig.isHacEnabled.has_value());
+ ITelephony::TelecomConfig telecomConfig2;
+ ASSERT_IS_OK(telephony->setTelecomConfig(telecomConfig, &telecomConfig2));
+ EXPECT_EQ(telecomConfig, telecomConfig2);
+}
+
+TEST_P(AudioCoreTelephony, TelecomConfigInvalid) {
+ static const auto kStatuses = {EX_NONE, EX_UNSUPPORTED_OPERATION};
+ if (telephony == nullptr) {
+ GTEST_SKIP() << "Telephony is not supported";
+ }
+ ndk::ScopedAStatus status;
+ ITelephony::TelecomConfig telecomConfig;
+ ASSERT_STATUS(kStatuses, status = telephony->setTelecomConfig({}, &telecomConfig));
+ if (status.getExceptionCode() == EX_UNSUPPORTED_OPERATION) {
+ GTEST_SKIP() << "Telecom is not supported";
+ }
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+ telephony->setTelecomConfig(
+ {.voiceVolume = Float{ITelephony::TelecomConfig::VOICE_VOLUME_MIN - 1}},
+ &telecomConfig));
+ EXPECT_STATUS(EX_ILLEGAL_ARGUMENT,
+ telephony->setTelecomConfig(
+ {.voiceVolume = Float{ITelephony::TelecomConfig::VOICE_VOLUME_MAX + 1}},
+ &telecomConfig));
+}
+
using CommandSequence = std::vector<StreamDescriptor::Command>;
class StreamLogicDriverInvalidCommand : public StreamLogicDriver {
public:
@@ -2998,6 +3135,17 @@
return ndk::ScopedAStatus::ok();
}
+TEST_P(AudioCoreSoundDose, SameInstance) {
+ if (soundDose == nullptr) {
+ GTEST_SKIP() << "SoundDose is not supported";
+ }
+ std::shared_ptr<ISoundDose> soundDose2;
+ EXPECT_IS_OK(module->getSoundDose(&soundDose2));
+ ASSERT_NE(nullptr, soundDose2.get());
+ EXPECT_EQ(soundDose->asBinder(), soundDose2->asBinder())
+ << "getSoundDose must return the same interface instance across invocations";
+}
+
TEST_P(AudioCoreSoundDose, GetSetOutputRs2) {
if (soundDose == nullptr) {
GTEST_SKIP() << "SoundDose is not supported";
@@ -3044,6 +3192,10 @@
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreModule);
+INSTANTIATE_TEST_SUITE_P(AudioCoreBluetoothTest, AudioCoreBluetooth,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
+ android::PrintInstanceNameToString);
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AudioCoreBluetooth);
INSTANTIATE_TEST_SUITE_P(AudioCoreTelephonyTest, AudioCoreTelephony,
testing::ValuesIn(android::getAidlHalInstanceNames(IModule::descriptor)),
android::PrintInstanceNameToString);
diff --git a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
index d1f3b97..b8ea9c1 100644
--- a/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
+++ b/audio/aidl/vts/VtsHalHapticGeneratorTargetTest.cpp
@@ -19,7 +19,9 @@
#include <Utils.h>
#include <aidl/Vintf.h>
#include <android/binder_enums.h>
-#include <unordered_set>
+#include <map>
+#include <utility>
+#include <vector>
#include "EffectHelper.h"
@@ -87,12 +89,11 @@
ASSERT_NE(nullptr, mFactory);
ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
- Parameter::Specific specific = getDefaultParamSpecific();
Parameter::Common common = EffectHelper::createParamCommon(
0 /* session */, 1 /* ioHandle */, 44100 /* iSampleRate */, 44100 /* oSampleRate */,
kInputFrameCount /* iFrameCount */, kOutputFrameCount /* oFrameCount */);
IEffect::OpenEffectReturn ret;
- ASSERT_NO_FATAL_FAILURE(open(mEffect, common, specific, &ret, EX_NONE));
+ ASSERT_NO_FATAL_FAILURE(open(mEffect, common, std::nullopt, &ret, EX_NONE));
ASSERT_NE(nullptr, mEffect);
}
@@ -101,15 +102,6 @@
ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
}
- Parameter::Specific getDefaultParamSpecific() {
- HapticGenerator::HapticScale hapticScale = {.id = 0,
- .scale = HapticGenerator::VibratorScale::MUTE};
- HapticGenerator hg = HapticGenerator::make<HapticGenerator::hapticScale>(hapticScale);
- Parameter::Specific specific =
- Parameter::Specific::make<Parameter::Specific::hapticGenerator>(hg);
- return specific;
- }
-
static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
std::shared_ptr<IFactory> mFactory;
std::shared_ptr<IEffect> mEffect;
@@ -122,13 +114,13 @@
void SetAndGetHapticGeneratorParameters() {
for (auto& it : mTags) {
- auto& tag = it.first;
- auto& hg = it.second;
+ auto& tag = std::get<ParamTestEnum::PARAM_TEST_TAG>(it);
+ auto& setHg = std::get<ParamTestEnum::PARAM_TEST_TARGET>(it);
// set parameter
Parameter expectParam;
Parameter::Specific specific;
- specific.set<Parameter::Specific::hapticGenerator>(hg);
+ specific.set<Parameter::Specific::hapticGenerator>(setHg);
expectParam.set<Parameter::specific>(specific);
EXPECT_STATUS(EX_NONE, mEffect->setParameter(expectParam)) << expectParam.toString();
@@ -139,15 +131,16 @@
hgId.set<HapticGenerator::Id::commonTag>(tag);
id.set<Parameter::Id::hapticGeneratorTag>(hgId);
EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &getParam));
- EXPECT_EQ(expectParam, getParam);
+ EXPECT_EQ(expectParam, getParam) << expectParam.toString() << "\n"
+ << getParam.toString();
}
}
void addHapticScaleParam(int id, HapticGenerator::VibratorScale scale) {
- HapticGenerator hg;
- HapticGenerator::HapticScale hapticScale = {.id = id, .scale = scale};
- hg.set<HapticGenerator::hapticScale>(hapticScale);
- mTags.push_back({HapticGenerator::hapticScale, hg});
+ HapticGenerator setHg;
+ std::vector<HapticGenerator::HapticScale> hapticScales = {{.id = id, .scale = scale}};
+ setHg.set<HapticGenerator::hapticScales>(hapticScales);
+ mTags.push_back({HapticGenerator::hapticScales, setHg});
}
void addVibratorInformationParam(float resonantFrequencyHz, float qFactor, float maxAmplitude) {
@@ -161,7 +154,8 @@
}
private:
- std::vector<std::pair<HapticGenerator::Tag, HapticGenerator>> mTags;
+ enum ParamTestEnum { PARAM_TEST_TAG, PARAM_TEST_TARGET };
+ std::vector<std::tuple<HapticGenerator::Tag, HapticGenerator>> mTags;
void CleanUp() { mTags.clear(); }
};
@@ -171,6 +165,12 @@
SetAndGetHapticGeneratorParameters();
}
+TEST_P(HapticGeneratorParamTest, SetAndGetMultipleHapticScales) {
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(mParamHapticScaleId, mParamVibratorScale));
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(mParamHapticScaleId, mParamVibratorScale));
+ SetAndGetHapticGeneratorParameters();
+}
+
TEST_P(HapticGeneratorParamTest, SetAndGetVibratorInformation) {
EXPECT_NO_FATAL_FAILURE(addVibratorInformationParam(mParamResonantFrequency, mParamQFactor,
mParamMaxAmplitude));
@@ -212,7 +212,7 @@
::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
IFactory::descriptor, kHapticGeneratorTypeUUID)),
testing::Values(MIN_ID - 1),
- testing::Values(HapticGenerator::VibratorScale::MUTE),
+ testing::Values(HapticGenerator::VibratorScale::NONE),
testing::Values(MIN_FLOAT), testing::Values(MIN_FLOAT),
testing::Values(MIN_FLOAT)),
[](const testing::TestParamInfo<HapticGeneratorParamTest::ParamType>& info) {
@@ -236,9 +236,202 @@
name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
return name;
});
-
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorParamTest);
+// Test HapticScale[] hapticScales parameter
+using HapticGeneratorScalesTestParam = std::tuple<std::pair<std::shared_ptr<IFactory>, Descriptor>>;
+class HapticGeneratorScalesTest : public ::testing::TestWithParam<HapticGeneratorScalesTestParam>,
+ public EffectHelper {
+ public:
+ HapticGeneratorScalesTest() {
+ std::tie(mFactory, mDescriptor) = std::get<PARAM_INSTANCE_NAME>(GetParam());
+ }
+
+ void SetUp() override {
+ ASSERT_NE(nullptr, mFactory);
+ ASSERT_NO_FATAL_FAILURE(create(mFactory, mEffect, mDescriptor));
+
+ Parameter::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, std::nullopt, &ret, EX_NONE));
+ ASSERT_NE(nullptr, mEffect);
+ }
+
+ void TearDown() override {
+ ASSERT_NO_FATAL_FAILURE(close(mEffect));
+ ASSERT_NO_FATAL_FAILURE(destroy(mFactory, mEffect));
+ CleanUp();
+ }
+
+ static const long kInputFrameCount = 0x100, kOutputFrameCount = 0x100;
+ std::shared_ptr<IFactory> mFactory;
+ std::shared_ptr<IEffect> mEffect;
+ Descriptor mDescriptor;
+
+ void addHapticScaleParam(std::vector<HapticGenerator::HapticScale> scales) {
+ mHapticScales.push_back(HapticGenerator::make<HapticGenerator::hapticScales>(scales));
+ for (const auto& scale : scales) {
+ expectMap.insert_or_assign(scale.id, scale.scale);
+ }
+ }
+
+ void SetHapticScaleParameters() {
+ // std::unordered_set<HapticGenerator::HapticScale> target;
+ for (auto& it : mHapticScales) {
+ Parameter::Specific specific =
+ Parameter::Specific::make<Parameter::Specific::hapticGenerator>(it);
+ Parameter param = Parameter::make<Parameter::specific>(specific);
+ EXPECT_STATUS(EX_NONE, mEffect->setParameter(param)) << param.toString();
+ }
+ }
+
+ void checkHapticScaleParameter() {
+ // get parameter
+ Parameter targetParam;
+ HapticGenerator::Id hgId = HapticGenerator::Id::make<HapticGenerator::Id::commonTag>(
+ HapticGenerator::hapticScales);
+ Parameter::Id id = Parameter::Id::make<Parameter::Id::hapticGeneratorTag>(hgId);
+ EXPECT_STATUS(EX_NONE, mEffect->getParameter(id, &targetParam));
+ ASSERT_EQ(Parameter::specific, targetParam.getTag());
+ Parameter::Specific specific = targetParam.get<Parameter::specific>();
+ ASSERT_EQ(Parameter::Specific::hapticGenerator, specific.getTag());
+ HapticGenerator hg = specific.get<Parameter::Specific::hapticGenerator>();
+ ASSERT_EQ(HapticGenerator::hapticScales, hg.getTag());
+ std::vector<HapticGenerator::HapticScale> scales = hg.get<HapticGenerator::hapticScales>();
+ ASSERT_EQ(scales.size(), expectMap.size());
+ for (const auto& scale : scales) {
+ auto itor = expectMap.find(scale.id);
+ ASSERT_NE(expectMap.end(), itor);
+ ASSERT_EQ(scale.scale, itor->second);
+ expectMap.erase(scale.id);
+ }
+ ASSERT_EQ(0ul, expectMap.size());
+ }
+
+ const static HapticGenerator::HapticScale kHapticScaleWithMinId;
+ const static HapticGenerator::HapticScale kHapticScaleWithMinIdNew;
+ const static HapticGenerator::HapticScale kHapticScale;
+ const static HapticGenerator::HapticScale kHapticScaleNew;
+ const static HapticGenerator::HapticScale kHapticScaleWithMaxId;
+ const static HapticGenerator::HapticScale kHapticScaleWithMaxIdNew;
+
+ std::vector<HapticGenerator> mHapticScales;
+
+ void CleanUp() {
+ mHapticScales.clear();
+ expectMap.clear();
+ }
+
+ private:
+ std::map<int /* trackID */, HapticGenerator::VibratorScale> expectMap;
+};
+
+const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMinId = {
+ .id = MIN_ID, .scale = HapticGenerator::VibratorScale::MUTE};
+const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMinIdNew = {
+ .id = MIN_ID, .scale = HapticGenerator::VibratorScale::VERY_LOW};
+const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScale = {
+ .id = 1, .scale = HapticGenerator::VibratorScale::LOW};
+const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleNew = {
+ .id = 1, .scale = HapticGenerator::VibratorScale::NONE};
+const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMaxId = {
+ .id = MAX_ID, .scale = HapticGenerator::VibratorScale::VERY_HIGH};
+const HapticGenerator::HapticScale HapticGeneratorScalesTest::kHapticScaleWithMaxIdNew = {
+ .id = MAX_ID, .scale = HapticGenerator::VibratorScale::MUTE};
+
+TEST_P(HapticGeneratorScalesTest, SetAndUpdateOne) {
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScale}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleNew}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMinId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMinIdNew}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxIdNew}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+
+ EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
+}
+
+TEST_P(HapticGeneratorScalesTest, SetAndUpdateVector) {
+ EXPECT_NO_FATAL_FAILURE(
+ addHapticScaleParam({kHapticScale, kHapticScaleWithMaxId, kHapticScaleWithMinId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(
+ {kHapticScaleNew, kHapticScaleWithMaxIdNew, kHapticScaleWithMinIdNew}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+
+ EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
+}
+
+TEST_P(HapticGeneratorScalesTest, SetAndUpdateMultipleVector) {
+ EXPECT_NO_FATAL_FAILURE(
+ addHapticScaleParam({kHapticScale, kHapticScaleWithMaxId, kHapticScaleWithMinId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam(
+ {kHapticScaleNew, kHapticScaleWithMaxIdNew, kHapticScaleWithMinIdNew}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(
+ addHapticScaleParam({kHapticScale, kHapticScaleWithMaxId, kHapticScaleWithMinId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+
+ EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
+}
+
+TEST_P(HapticGeneratorScalesTest, SetOneAndAddMoreVector) {
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScale}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxId, kHapticScaleWithMinId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+
+ EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
+}
+
+TEST_P(HapticGeneratorScalesTest, SetMultipleAndAddOneVector) {
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScaleWithMaxId, kHapticScaleWithMinId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(addHapticScaleParam({kHapticScale}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+
+ EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
+}
+
+TEST_P(HapticGeneratorScalesTest, SetMultipleVectorRepeat) {
+ EXPECT_NO_FATAL_FAILURE(
+ addHapticScaleParam({kHapticScaleWithMaxId, kHapticScale, kHapticScaleWithMinId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(
+ addHapticScaleParam({kHapticScaleWithMaxId, kHapticScale, kHapticScaleWithMinId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+ EXPECT_NO_FATAL_FAILURE(
+ addHapticScaleParam({kHapticScaleWithMaxId, kHapticScale, kHapticScaleWithMinId}));
+ EXPECT_NO_FATAL_FAILURE(SetHapticScaleParameters());
+
+ EXPECT_NO_FATAL_FAILURE(checkHapticScaleParameter());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ HapticGeneratorScalesTest, HapticGeneratorScalesTest,
+ ::testing::Combine(testing::ValuesIn(EffectFactoryHelper::getAllEffectDescriptors(
+ IFactory::descriptor, kHapticGeneratorTypeUUID))),
+ [](const testing::TestParamInfo<HapticGeneratorScalesTest::ParamType>& info) {
+ auto descriptor = std::get<PARAM_INSTANCE_NAME>(info.param).second;
+ std::string name = "Implementor_" + descriptor.common.implementor + "_name_" +
+ descriptor.common.name + "_UUID_" +
+ descriptor.common.id.uuid.toString();
+ std::replace_if(
+ name.begin(), name.end(), [](const char c) { return !std::isalnum(c); }, '_');
+ return name;
+ });
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(HapticGeneratorScalesTest);
+
int main(int argc, char** argv) {
::testing::InitGoogleTest(&argc, argv);
ABinderProcess_setThreadPoolMaxThreadCount(1);
diff --git a/automotive/vehicle/2.0/types.hal b/automotive/vehicle/2.0/types.hal
index 9e4f252..83b0d94 100644
--- a/automotive/vehicle/2.0/types.hal
+++ b/automotive/vehicle/2.0/types.hal
@@ -2117,6 +2117,12 @@
| VehicleArea:SEAT),
/**
+ * DO NOT USE
+ *
+ * This property is defined as type VehicleArea:GLOBAL, which means all seats use the same
+ * value. Use SEAT_HEADREST_HEIGHT_POS_V2 instead which fixes this issue by being defined as
+ * type VehicleArea:SEAT.
+ *
* Headrest height position
*
* Sets the headrest height.
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 76a9b47..303bef4 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
@@ -155,6 +155,7 @@
SEAT_LUMBAR_SIDE_SUPPORT_POS = 356518803,
SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 356518804,
SEAT_HEADREST_HEIGHT_POS = 289409941,
+ SEAT_HEADREST_HEIGHT_POS_V2 = 356518820,
SEAT_HEADREST_HEIGHT_MOVE = 356518806,
SEAT_HEADREST_ANGLE_POS = 356518807,
SEAT_HEADREST_ANGLE_MOVE = 356518808,
@@ -195,6 +196,8 @@
CABIN_LIGHTS_SWITCH = 289410818,
READING_LIGHTS_STATE = 356519683,
READING_LIGHTS_SWITCH = 356519684,
+ STEERING_WHEEL_LIGHTS_STATE = 289410828,
+ STEERING_WHEEL_LIGHTS_SWITCH = 289410829,
SUPPORT_CUSTOMIZE_VENDOR_PERMISSION = 287313669,
DISABLED_OPTIONAL_FEATURES = 286265094,
INITIAL_USER_INFO = 299896583,
diff --git a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
index 79593eb..5afe842 100644
--- a/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
+++ b/automotive/vehicle/aidl/android/hardware/automotive/vehicle/VehicleProperty.aidl
@@ -1760,7 +1760,11 @@
SEAT_LUMBAR_SIDE_SUPPORT_MOVE = 0x0B94 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
/**
- * Headrest height position
+ * (Deprecated) Headrest height position
+ *
+ * This property is deprecated because it is defined as type VehicleArea:GLOBAL, which means all
+ * seats use the same value. Use SEAT_HEADREST_HEIGHT_POS_V2 instead which fixes this issue by
+ * being defined as type VehicleArea:SEAT.
*
* Sets the headrest height.
* Max value indicates tallest setting.
@@ -1771,6 +1775,25 @@
*/
SEAT_HEADREST_HEIGHT_POS = 0x0B95 + 0x10000000 + 0x01000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:GLOBAL,VehiclePropertyType:INT32
+
+ /**
+ * Headrest height position
+ *
+ * Sets the headrest height for supported seats. VehiclePropConfig.areaConfigs specifies which
+ * seats are supported.
+ *
+ * The maxInt32Value and minInt32Value in VehicleAreaConfig must be defined. All values between
+ * minInt32Value and maxInt32Value must be supported. The maxInt32Value indicates the tallest
+ * setting and the minInt32Value indicates the shortest setting.
+ *
+ * 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_HEADREST_HEIGHT_POS_V2 =
+ 0x0BA4 + VehiclePropertyGroup.SYSTEM + VehicleArea.SEAT + VehiclePropertyType.INT32,
+
/**
* Headrest height move
*
@@ -2414,6 +2437,48 @@
READING_LIGHTS_SWITCH = 0x0F04 + 0x10000000 + 0x05000000
+ 0x00400000, // VehiclePropertyGroup:SYSTEM,VehicleArea:SEAT,VehiclePropertyType:INT32
/**
+ * Steering wheel lights state
+ *
+ * Represents the current state of the steering wheel lights. This is different from
+ * STEERING_WHEEL_LIGHTS_SWITCH which represents the position of the switch controlling
+ * the lights. Therefore, STEERING_WHEEL_LIGHTS_STATE may not match the value of
+ * STEERING_WHEEL_LIGHTS_SWITCH (e.g. STEERING_WHEEL_LIGHTS_SWITCH=AUTOMATIC and
+ * STEERING_WHEEL_LIGHTS_STATE=ON).
+ *
+ * This property should only be implemented if STEERING_WHEEL_LIGHTS_STATE's value may be
+ * different from that of CABIN_LIGHTS_STATE.
+ *
+ * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless
+ * all enum values of VehicleLightState are supported.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ
+ * @data_enum VehicleLightState
+ */
+ STEERING_WHEEL_LIGHTS_STATE =
+ 0x0F0C + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
+ * Steering wheel lights switch
+ *
+ * Represents the position of the switch controlling the steering wheel lights. This is
+ * different from STEERING_WHEEL_LIGHTS_STATE which represents the current state of the steering
+ * wheel lights. Therefore, STEERING_WHEEL_LIGHTS_SWITCH may not match the value of
+ * STEERING_WHEEL_LIGHTS_STATE (e.g. STEERING_WHEEL_LIGHTS_SWITCH=AUTOMATIC and
+ * STEERING_WHEEL_LIGHTS_STATE=ON).
+ *
+ * This property should only be implemented if STEERING_WHEEL_LIGHTS_SWITCH's value may be
+ * different from that of CABIN_LIGHTS_SWITCH.
+ *
+ * For the global area ID (0), the VehicleAreaConfig#supportedEnumValues must be defined unless
+ * all enum values of VehicleLightSwitch are supported.
+ *
+ * @change_mode VehiclePropertyChangeMode.ON_CHANGE
+ * @access VehiclePropertyAccess.READ_WRITE
+ * @data_enum VehicleLightSwitch
+ */
+ STEERING_WHEEL_LIGHTS_SWITCH =
+ 0x0F0D + VehiclePropertyGroup.SYSTEM + VehicleArea.GLOBAL + VehiclePropertyType.INT32,
+ /**
* Support customize permissions for vendor properties
*
* Implement this property if vehicle hal support customize vendor permissions feature.
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
index f768847..34322f8 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/cpp/AccessForVehicleProperty.h
@@ -155,6 +155,7 @@
{VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_HEADREST_HEIGHT_POS, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::SEAT_HEADREST_HEIGHT_POS_V2, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_HEADREST_HEIGHT_MOVE, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_HEADREST_ANGLE_POS, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SEAT_HEADREST_ANGLE_MOVE, VehiclePropertyAccess::READ_WRITE},
@@ -195,6 +196,8 @@
{VehicleProperty::CABIN_LIGHTS_SWITCH, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::READING_LIGHTS_STATE, VehiclePropertyAccess::READ},
{VehicleProperty::READING_LIGHTS_SWITCH, VehiclePropertyAccess::READ_WRITE},
+ {VehicleProperty::STEERING_WHEEL_LIGHTS_STATE, VehiclePropertyAccess::READ},
+ {VehicleProperty::STEERING_WHEEL_LIGHTS_SWITCH, VehiclePropertyAccess::READ_WRITE},
{VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION, VehiclePropertyAccess::READ},
{VehicleProperty::DISABLED_OPTIONAL_FEATURES, VehiclePropertyAccess::READ},
{VehicleProperty::INITIAL_USER_INFO, VehiclePropertyAccess::READ_WRITE},
diff --git a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h b/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
index 4d954f4..36e1709 100644
--- a/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
+++ b/automotive/vehicle/aidl/generated_lib/cpp/ChangeModeForVehicleProperty.h
@@ -155,6 +155,7 @@
{VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_LUMBAR_SIDE_SUPPORT_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_HEADREST_HEIGHT_POS, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::SEAT_HEADREST_HEIGHT_POS_V2, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_HEADREST_HEIGHT_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_HEADREST_ANGLE_POS, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SEAT_HEADREST_ANGLE_MOVE, VehiclePropertyChangeMode::ON_CHANGE},
@@ -195,6 +196,8 @@
{VehicleProperty::CABIN_LIGHTS_SWITCH, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::READING_LIGHTS_STATE, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::READING_LIGHTS_SWITCH, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::STEERING_WHEEL_LIGHTS_STATE, VehiclePropertyChangeMode::ON_CHANGE},
+ {VehicleProperty::STEERING_WHEEL_LIGHTS_SWITCH, VehiclePropertyChangeMode::ON_CHANGE},
{VehicleProperty::SUPPORT_CUSTOMIZE_VENDOR_PERMISSION, VehiclePropertyChangeMode::STATIC},
{VehicleProperty::DISABLED_OPTIONAL_FEATURES, VehiclePropertyChangeMode::STATIC},
{VehicleProperty::INITIAL_USER_INFO, VehiclePropertyChangeMode::ON_CHANGE},
diff --git a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
index f513f02..4da920c 100644
--- a/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/java/AccessForVehicleProperty.java
@@ -147,6 +147,7 @@
Map.entry(VehicleProperty.SEAT_LUMBAR_SIDE_SUPPORT_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_LUMBAR_SIDE_SUPPORT_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_HEADREST_HEIGHT_POS, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.SEAT_HEADREST_HEIGHT_POS_V2, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_HEADREST_HEIGHT_MOVE, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_HEADREST_ANGLE_POS, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SEAT_HEADREST_ANGLE_MOVE, VehiclePropertyAccess.READ_WRITE),
@@ -187,6 +188,8 @@
Map.entry(VehicleProperty.CABIN_LIGHTS_SWITCH, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.READING_LIGHTS_STATE, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.READING_LIGHTS_SWITCH, VehiclePropertyAccess.READ_WRITE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_LIGHTS_STATE, VehiclePropertyAccess.READ),
+ Map.entry(VehicleProperty.STEERING_WHEEL_LIGHTS_SWITCH, VehiclePropertyAccess.READ_WRITE),
Map.entry(VehicleProperty.SUPPORT_CUSTOMIZE_VENDOR_PERMISSION, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.DISABLED_OPTIONAL_FEATURES, VehiclePropertyAccess.READ),
Map.entry(VehicleProperty.INITIAL_USER_INFO, VehiclePropertyAccess.READ_WRITE),
diff --git a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java b/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
index 00a826a..0aa42a4 100644
--- a/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
+++ b/automotive/vehicle/aidl/generated_lib/java/ChangeModeForVehicleProperty.java
@@ -147,6 +147,7 @@
Map.entry(VehicleProperty.SEAT_LUMBAR_SIDE_SUPPORT_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_LUMBAR_SIDE_SUPPORT_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_HEADREST_HEIGHT_POS, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.SEAT_HEADREST_HEIGHT_POS_V2, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_HEADREST_HEIGHT_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_HEADREST_ANGLE_POS, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SEAT_HEADREST_ANGLE_MOVE, VehiclePropertyChangeMode.ON_CHANGE),
@@ -187,6 +188,8 @@
Map.entry(VehicleProperty.CABIN_LIGHTS_SWITCH, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.READING_LIGHTS_STATE, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.READING_LIGHTS_SWITCH, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_LIGHTS_STATE, VehiclePropertyChangeMode.ON_CHANGE),
+ Map.entry(VehicleProperty.STEERING_WHEEL_LIGHTS_SWITCH, VehiclePropertyChangeMode.ON_CHANGE),
Map.entry(VehicleProperty.SUPPORT_CUSTOMIZE_VENDOR_PERMISSION, VehiclePropertyChangeMode.STATIC),
Map.entry(VehicleProperty.DISABLED_OPTIONAL_FEATURES, VehiclePropertyChangeMode.STATIC),
Map.entry(VehicleProperty.INITIAL_USER_INFO, VehiclePropertyChangeMode.ON_CHANGE),
diff --git a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
index 20048a2..d02e4f4 100644
--- a/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
+++ b/automotive/vehicle/aidl/impl/default_config/JsonConfigLoader/src/JsonConfigLoader.cpp
@@ -107,6 +107,7 @@
{"LIGHT_STATE_ON", LIGHT_STATE_ON},
{"LIGHT_STATE_OFF", LIGHT_STATE_OFF},
{"LIGHT_SWITCH_OFF", LIGHT_SWITCH_OFF},
+ {"LIGHT_SWITCH_ON", LIGHT_SWITCH_ON},
{"LIGHT_SWITCH_AUTO", LIGHT_SWITCH_AUTO},
{"MIRROR_DRIVER_LEFT_RIGHT",
toInt(VehicleAreaMirror::DRIVER_LEFT) | toInt(VehicleAreaMirror::DRIVER_RIGHT)},
diff --git a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
index dd20039..583bca0 100644
--- a/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
+++ b/automotive/vehicle/aidl/impl/default_config/config/DefaultProperties.json
@@ -861,6 +861,41 @@
]
},
{
+ "property": "VehicleProperty::SEAT_HEADREST_HEIGHT_POS_V2",
+ "defaultValue": {
+ "int32Values": [
+ 0
+ ]
+ },
+ "areas": [
+ {
+ "areaId": "Constants::SEAT_1_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_1_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_LEFT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_RIGHT",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ },
+ {
+ "areaId": "Constants::SEAT_2_CENTER",
+ "minInt32Value": 0,
+ "maxInt32Value": 10
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::SEAT_HEADREST_HEIGHT_MOVE",
"defaultValue": {
"int32Values": [
@@ -2707,6 +2742,23 @@
]
},
{
+ "property": "VehicleProperty::STEERING_WHEEL_LIGHTS_STATE",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_STATE_ON"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "Constants::LIGHT_STATE_OFF",
+ "Constants::LIGHT_STATE_ON"
+ ]
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::HEADLIGHTS_SWITCH",
"defaultValue": {
"int32Values": [
@@ -2780,6 +2832,24 @@
]
},
{
+ "property": "VehicleProperty::STEERING_WHEEL_LIGHTS_SWITCH",
+ "defaultValue": {
+ "int32Values": [
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ },
+ "areas": [
+ {
+ "areaId": 0,
+ "supportedEnumValues": [
+ "Constants::LIGHT_SWITCH_OFF",
+ "Constants::LIGHT_SWITCH_ON",
+ "Constants::LIGHT_SWITCH_AUTO"
+ ]
+ }
+ ]
+ },
+ {
"property": "VehicleProperty::EVS_SERVICE_REQUEST",
"defaultValue": {
"int32Values": [
diff --git a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
index bf27c95..2b2a592 100644
--- a/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
+++ b/automotive/vehicle/aidl/impl/utils/common/include/PropertyUtils.h
@@ -98,6 +98,7 @@
constexpr int LIGHT_STATE_ON = toInt(propertyutils_impl::VehicleLightState::ON);
constexpr int LIGHT_STATE_OFF = toInt(propertyutils_impl::VehicleLightState::OFF);
constexpr int LIGHT_SWITCH_OFF = toInt(propertyutils_impl::VehicleLightSwitch::OFF);
+constexpr int LIGHT_SWITCH_ON = toInt(propertyutils_impl::VehicleLightSwitch::ON);
constexpr int LIGHT_SWITCH_AUTO = toInt(propertyutils_impl::VehicleLightSwitch::AUTOMATIC);
constexpr int WHEEL_FRONT_LEFT = toInt(propertyutils_impl::VehicleAreaWheel::LEFT_FRONT);
constexpr int WHEEL_FRONT_RIGHT = toInt(propertyutils_impl::VehicleAreaWheel::RIGHT_FRONT);
diff --git a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
index 1a49796..2be409f 100644
--- a/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
+++ b/automotive/vehicle/vts/src/VtsHalAutomotiveVehicle_TargetTest.cpp
@@ -547,6 +547,18 @@
VehiclePropertyGroup::SYSTEM, VehicleArea::GLOBAL, VehiclePropertyType::BOOLEAN);
}
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySteeringWheelLightsStateConfig) {
+ verifyProperty(VehicleProperty::STEERING_WHEEL_LIGHTS_STATE, VehiclePropertyAccess::READ,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySteeringWheelLightsSwitchConfig) {
+ verifyProperty(VehicleProperty::STEERING_WHEEL_LIGHTS_SWITCH, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::GLOBAL, VehiclePropertyType::INT32);
+}
+
TEST_P(VtsHalAutomotiveVehicleTargetTest, verifyMirrorAutoFoldEnabledConfig) {
verifyProperty(VehicleProperty::MIRROR_AUTO_FOLD_ENABLED, VehiclePropertyAccess::READ_WRITE,
VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
@@ -559,6 +571,12 @@
VehicleArea::MIRROR, VehiclePropertyType::BOOLEAN);
}
+TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatHeadrestHeightPosV2Config) {
+ verifyProperty(VehicleProperty::SEAT_HEADREST_HEIGHT_POS_V2, VehiclePropertyAccess::READ_WRITE,
+ VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
+ VehicleArea::SEAT, VehiclePropertyType::INT32);
+}
+
TEST_P(VtsHalAutomotiveVehicleTargetTest, verifySeatWalkInPosConfig) {
verifyProperty(VehicleProperty::SEAT_WALK_IN_POS, VehiclePropertyAccess::READ_WRITE,
VehiclePropertyChangeMode::ON_CHANGE, VehiclePropertyGroup::SYSTEM,
diff --git a/compatibility_matrices/compatibility_matrix.current.xml b/compatibility_matrices/compatibility_matrix.current.xml
index e7bb282..c05e8c5 100644
--- a/compatibility_matrices/compatibility_matrix.current.xml
+++ b/compatibility_matrices/compatibility_matrix.current.xml
@@ -656,6 +656,13 @@
</interface>
</hal>
<hal format="aidl" optional="true">
+ <name>android.hardware.tv.earc</name>
+ <interface>
+ <name>IEArc</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+ <hal format="aidl" optional="true">
<name>android.hardware.tv.hdmi</name>
<interface>
<name>IHdmi</name>
@@ -765,4 +772,12 @@
<instance>default</instance>
</interface>
</hal>
+ <hal format="native">
+ <name>mapper</name>
+ <version>1.0</version>
+ <interface>
+ <name>I</name>
+ <regex-instance>.*</regex-instance>
+ </interface>
+ </hal>
</compatibility-matrix>
diff --git a/current.txt b/current.txt
index 0fb8b49..fbdd3fe 100644
--- a/current.txt
+++ b/current.txt
@@ -932,5 +932,6 @@
# ABI preserving changes to HALs during Android U
2aa559cda86c358c6429114ef6bc72c1b43281e98f9eb6b4df5e7073c8d05767 android.hardware.automotive.vehicle@2.0::types
42abd285a4293dadb8c89bc63b90cae2872fbffe90c4517aa3ea4965e8aecff7 android.hardware.graphics.common@1.2::types
+4f1a02d21a22104c734f71cdbba19b6f7e93d4ee107ff79f0dbdd171a8430e0e android.hardware.automotive.vehicle@2.0::types
# There will be no more HIDL HALs. Use AIDL instead.
diff --git a/security/keymint/aidl/vts/functional/Android.bp b/security/keymint/aidl/vts/functional/Android.bp
index e7f5a0f..88badc7 100644
--- a/security/keymint/aidl/vts/functional/Android.bp
+++ b/security/keymint/aidl/vts/functional/Android.bp
@@ -57,6 +57,7 @@
srcs: [
"AttestKeyTest.cpp",
"DeviceUniqueAttestationTest.cpp",
+ "KeyBlobUpgradeTest.cpp",
"KeyMintTest.cpp",
"SecureElementProvisioningTest.cpp",
],
diff --git a/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp b/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
new file mode 100644
index 0000000..c952012
--- /dev/null
+++ b/security/keymint/aidl/vts/functional/KeyBlobUpgradeTest.cpp
@@ -0,0 +1,609 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// The tests in this file are intended to be run manually, to allow testing of whether
+// keyblob upgrade works correctly. The manual procedure is roughly:
+//
+// 1) Run the "*Before*" subset of these tests with the `--keyblob_dir <dir>` command-line argument
+// so that keyblobs are saved to a directory on the device:
+//
+// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest*Before*" \
+// --keyblob_dir /data/local/tmp/keymint-blobs
+//
+// All tests should pass, and the `UpgradeKeyBlobs` test should indicate that no keyblob
+// upgrades were needed.
+//
+// 2) Copy the generated keyblobs off the device into a safe place.
+//
+// adb pull /data/local/tmp/keymint-blobs
+//
+// 3) Upgrade the device to a new version.
+//
+// 4) Push the saved keyblobs back onto the upgraded device.
+//
+// adb push keymint-blobs /data/local/tmp/keymint-blobs
+//
+// 5) Run the "*After*" subset of these tests with the `--keyblob_dir <dir>` command-line argument
+// pointing to the directory with the keyblobs:
+//
+// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest*After*" \
+// --keyblob_dir /data/local/tmp/keymint-blobs
+//
+// (Note that this skips the `CreateKeyBlobs` test, which would otherwise replace the saved
+// keyblobs with freshly generated ones.).
+//
+// All tests should pass, and the `UpgradeKeyBlobs` test should have output that matches whether
+// upgrade was expected or not.
+
+#define LOG_TAG "keymint_1_test"
+#include <cutils/log.h>
+
+#include <algorithm>
+#include <fstream>
+#include <iostream>
+
+#include <unistd.h>
+
+#include <openssl/curve25519.h>
+#include <openssl/ec.h>
+#include <openssl/evp.h>
+#include <openssl/mem.h>
+#include <openssl/x509v3.h>
+
+#include "KeyMintAidlTestBase.h"
+
+using aidl::android::hardware::security::keymint::KeyCharacteristics;
+
+namespace aidl::android::hardware::security::keymint::test {
+
+namespace {
+
+std::vector<std::string> keyblob_names_tee = {
+ "aes-key", "aes-key-rr", "des-key", "hmac-key",
+ "rsa-key", "p256-key", "ed25519-key", "x25519-key",
+ "rsa-attest-key", "p256-attest-key", "ed25519-attest-key"};
+
+std::vector<std::string> keyblob_names_sb = {"aes-key", "aes-key-rr", "des-key",
+ "hmac-key", "rsa-key", "p256-key",
+ "rsa-attest-key", "p256-attest-key"};
+
+const std::vector<std::string>& keyblob_names(SecurityLevel sec_level) {
+ if (sec_level == SecurityLevel::STRONGBOX) {
+ return keyblob_names_sb;
+ } else {
+ return keyblob_names_tee;
+ }
+}
+
+bool requires_rr(const std::string& name) {
+ return name.find("-rr") != std::string::npos;
+}
+
+bool is_asymmetric(const std::string& name) {
+ return (name.find("rsa") != std::string::npos || name.find("25519") != std::string::npos ||
+ name.find("p256") != std::string::npos);
+}
+
+std::string keyblob_subdir(const std::string& keyblob_dir, const std::string& full_name,
+ bool create) {
+ if (keyblob_dir.empty()) {
+ return "";
+ }
+
+ // Use a subdirectory for the specific instance, so two different KeyMint instances won't
+ // clash with each other.
+ size_t found = full_name.find_last_of('/');
+ std::string subdir = keyblob_dir + "/" + full_name.substr(found + 1);
+
+ if (create) {
+ mkdir(keyblob_dir.c_str(), 0777);
+ mkdir(subdir.c_str(), 0777);
+ }
+ return subdir;
+}
+
+void save_keyblob(const std::string& subdir, const std::string& name,
+ const vector<uint8_t>& keyblob,
+ const std::vector<KeyCharacteristics>& key_characteristics) {
+ // Write the keyblob out to a file.
+ std::string blobname(subdir + "/" + name + ".keyblob");
+ std::ofstream blobfile(blobname, std::ios::out | std::ios::trunc | std::ios::binary);
+ blobfile.write(reinterpret_cast<const char*>(keyblob.data()), keyblob.size());
+ blobfile.close();
+
+ // Dump the characteristics too.
+ std::string charsname(subdir + "/" + name + ".chars");
+ std::ofstream charsfile(charsname, std::ios::out | std::ios::trunc);
+ charsfile << "{\n";
+ for (const auto& characteristic : key_characteristics) {
+ charsfile << " " << characteristic.toString() << "\n";
+ }
+ charsfile << "}\n";
+ charsfile.close();
+
+ // Also write out a hexdump of the keyblob for convenience.
+ std::string hexname(subdir + "/" + name + ".hex");
+ std::ofstream hexfile(hexname, std::ios::out | std::ios::trunc);
+ hexfile << bin2hex(keyblob) << "\n";
+ hexfile.close();
+}
+
+void save_keyblob_and_cert(const std::string& subdir, const std::string& name,
+ const vector<uint8_t>& keyblob,
+ const std::vector<KeyCharacteristics>& key_characteristics,
+ const std::vector<Certificate>& cert_chain) {
+ save_keyblob(subdir, name, keyblob, key_characteristics);
+
+ if (is_asymmetric(name)) {
+ // Dump the leaf certificate as DER.
+ if (cert_chain.empty()) {
+ FAIL() << "No cert available for " << name;
+ } else {
+ const vector<uint8_t>& certdata = cert_chain[0].encodedCertificate;
+ std::string certname(subdir + "/" + name + ".cert");
+ std::ofstream certfile(certname, std::ios::out | std::ios::trunc | std::ios::binary);
+ certfile.write(reinterpret_cast<const char*>(certdata.data()), certdata.size());
+ certfile.close();
+ }
+ }
+}
+
+void delete_keyblob(const std::string& subdir, const std::string& name) {
+ std::string blobname(subdir + "/" + name + ".keyblob");
+ unlink(blobname.c_str());
+ std::string charsname(subdir + "/" + name + ".chars");
+ unlink(charsname.c_str());
+ std::string hexname(subdir + "/" + name + ".hex");
+ unlink(hexname.c_str());
+ std::string certname(subdir + "/" + name + ".cert");
+ unlink(certname.c_str());
+}
+
+std::vector<uint8_t> load_file(const std::string& subdir, const std::string& name,
+ const std::string& suffix) {
+ std::string blobname(subdir + "/" + name + suffix);
+ std::ifstream blobfile(blobname, std::ios::in | std::ios::binary);
+
+ std::vector<uint8_t> data((std::istreambuf_iterator<char>(blobfile)),
+ std::istreambuf_iterator<char>());
+ return data;
+}
+
+std::vector<uint8_t> load_keyblob(const std::string& subdir, const std::string& name) {
+ return load_file(subdir, name, ".keyblob");
+}
+
+std::vector<uint8_t> load_cert(const std::string& subdir, const std::string& name) {
+ return load_file(subdir, name, ".cert");
+}
+
+} // namespace
+
+class KeyBlobUpgradeTest : public KeyMintAidlTestBase {
+ protected:
+ void UpgradeKeyBlobs(bool expectUpgrade) {
+ std::string subdir = keyblob_subdir(keyblob_dir, GetParam(), /* create? */ false);
+ if (subdir.empty()) {
+ GTEST_SKIP() << "No keyblob directory provided";
+ }
+
+ for (std::string name : keyblob_names(SecLevel())) {
+ for (bool with_hidden : {false, true}) {
+ std::string app_id;
+ std::string app_data;
+ auto builder = AuthorizationSetBuilder();
+ if (with_hidden) {
+ // Build a variant keyblob that requires app_id/app_data
+ app_id = "appid";
+ app_data = "appdata";
+ builder.Authorization(TAG_APPLICATION_ID, "appid")
+ .Authorization(TAG_APPLICATION_DATA, "appdata");
+ name += "-hidden";
+ }
+ SCOPED_TRACE(testing::Message() << name);
+
+ // Load the old format keyblob.
+ std::vector<uint8_t> keyblob = load_keyblob(subdir, name);
+ if (keyblob.empty()) {
+ if (requires_rr(name)) {
+ std::cerr << "Skipping missing keyblob file '" << name
+ << "', assuming rollback resistance unavailable\n";
+ } else {
+ FAIL() << "Missing keyblob file '" << name << "'";
+ }
+ continue;
+ }
+
+ // An upgrade will either produce a new keyblob or no data (if upgrade isn't
+ // needed).
+ std::vector<uint8_t> upgraded_keyblob;
+ Status result =
+ keymint_->upgradeKey(keyblob, builder.vector_data(), &upgraded_keyblob);
+ ASSERT_EQ(ErrorCode::OK, GetReturnErrorCode(result));
+
+ if (upgraded_keyblob.empty()) {
+ std::cerr << "Keyblob '" << name << "' did not require upgrade\n";
+ EXPECT_TRUE(!expectUpgrade) << "Keyblob '" << name << "' unexpectedly upgraded";
+ } else {
+ // Ensure the old format keyblob is deleted (so any secure deletion data is
+ // cleaned up).
+ EXPECT_EQ(ErrorCode::OK, DeleteKey(&keyblob));
+
+ std::vector<uint8_t> app_id_v(app_id.begin(), app_id.end());
+ std::vector<uint8_t> app_data_v(app_data.begin(), app_data.end());
+ std::vector<KeyCharacteristics> key_characteristics;
+ result = keymint_->getKeyCharacteristics(upgraded_keyblob, app_id_v, app_data_v,
+ &key_characteristics);
+ ASSERT_EQ(ErrorCode::OK, GetReturnErrorCode(result))
+ << "Failed getKeyCharacteristics() after upgrade";
+
+ save_keyblob(subdir, name, upgraded_keyblob, key_characteristics);
+ // Cert file is left unchanged.
+ std::cerr << "Keyblob '" << name << "' upgraded\n";
+ EXPECT_TRUE(expectUpgrade)
+ << "Keyblob '" << name << "' unexpectedly left as-is";
+ }
+ }
+ }
+ }
+};
+
+// To save off keyblobs before upgrade, use:
+//
+// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest.CreateKeyBlobs*" \
+// --keyblob_dir /data/local/tmp/keymint-blobs
+//
+// Then copy the contents of the /data/local/tmp/keymint-blobs/ directory somewhere safe:
+//
+// adb pull /data/local/tmp/keymint-blobs/
+TEST_P(KeyBlobUpgradeTest, CreateKeyBlobsBefore) {
+ std::string subdir = keyblob_subdir(keyblob_dir, GetParam(), /* create? */ true);
+
+ std::map<const std::string, AuthorizationSetBuilder> keys_info = {
+ {"aes-key", AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_NO_AUTH_REQUIRED)},
+ {"aes-key-rr", AuthorizationSetBuilder()
+ .AesEncryptionKey(256)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_ROLLBACK_RESISTANCE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)},
+ {"des-key", AuthorizationSetBuilder()
+ .TripleDesEncryptionKey(168)
+ .BlockMode(BlockMode::ECB)
+ .Padding(PaddingMode::PKCS7)
+ .Authorization(TAG_NO_AUTH_REQUIRED)},
+ {"hmac-key", AuthorizationSetBuilder()
+ .HmacKey(128)
+ .Digest(Digest::SHA1)
+ .Authorization(TAG_MIN_MAC_LENGTH, 128)
+ .Authorization(TAG_NO_AUTH_REQUIRED)},
+ {"rsa-key", AuthorizationSetBuilder()
+ .RsaEncryptionKey(2048, 65537)
+ .Authorization(TAG_PURPOSE, KeyPurpose::SIGN)
+ .Digest(Digest::NONE)
+ .Digest(Digest::SHA1)
+ .Padding(PaddingMode::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity()},
+ {
+ "p256-key",
+ AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::P_256)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .Digest(Digest::NONE)
+ .Digest(Digest::SHA1)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ },
+ {
+ "ed25519-key",
+ AuthorizationSetBuilder()
+ .EcdsaSigningKey(EcCurve::CURVE_25519)
+ .Digest(Digest::NONE)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ },
+ {"x25519-key", AuthorizationSetBuilder()
+ .Authorization(TAG_EC_CURVE, EcCurve::CURVE_25519)
+ .Authorization(TAG_PURPOSE, KeyPurpose::AGREE_KEY)
+ .Authorization(TAG_ALGORITHM, Algorithm::EC)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity()},
+ {"rsa-attest-key", AuthorizationSetBuilder()
+ .RsaKey(2048, 65537)
+ .AttestKey()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity()},
+ {
+ "p256-attest-key",
+ AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::P_256)
+ .AttestKey()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ },
+ {
+ "ed25519-attest-key",
+ AuthorizationSetBuilder()
+ .EcdsaKey(EcCurve::CURVE_25519)
+ .AttestKey()
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .SetDefaultValidity(),
+ }};
+
+ for (std::string name : keyblob_names(SecLevel())) {
+ auto entry = keys_info.find(name);
+ ASSERT_NE(entry, keys_info.end()) << "no builder for " << name;
+ auto builder = entry->second;
+ for (bool with_hidden : {false, true}) {
+ if (with_hidden) {
+ // Build a variant keyblob that requires app_id/app_data
+ builder.Authorization(TAG_APPLICATION_ID, "appid")
+ .Authorization(TAG_APPLICATION_DATA, "appdata");
+ name += "-hidden";
+ }
+ SCOPED_TRACE(testing::Message() << name);
+
+ vector<uint8_t> keyblob;
+ vector<KeyCharacteristics> key_characteristics;
+ vector<Certificate> cert_chain;
+ auto result =
+ GenerateKey(builder, std::nullopt, &keyblob, &key_characteristics, &cert_chain);
+
+ if (requires_rr(name) && result == ErrorCode::ROLLBACK_RESISTANCE_UNAVAILABLE) {
+ // Rollback resistance support is optional.
+ std::cerr << "Skipping '" << name << "' key as rollback resistance unavailable\n";
+ continue;
+ }
+ ASSERT_EQ(ErrorCode::OK, result) << " failed for " << name;
+
+ if (!subdir.empty()) {
+ save_keyblob_and_cert(subdir, name, keyblob, key_characteristics, cert_chain);
+ }
+ }
+ }
+
+ if (!subdir.empty()) {
+ std::cerr << "Save generated keyblobs with:\n\n adb pull " << keyblob_dir << "\n\n";
+ }
+}
+
+TEST_P(KeyBlobUpgradeTest, UpgradeKeyBlobsBefore) {
+ // Check that attempting to upgrade valid keyblobs does nothing.
+ UpgradeKeyBlobs(/* expectUpgrade= */ false);
+}
+
+// To run this test:
+//
+// - save off some keyblobs before upgrade as per the CreateKeyBlobs test above.
+// - upgrade the device to a version that should trigger keyblob upgrade (e.g. different patchlevel)
+// - put the saved keyblobs back onto the upgraded device:
+//
+// adb push keymint-blobs /data/local/tmp/keymint-blobs
+//
+// - run the test with:
+//
+// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest.UpgradeKeyBlobsAfter*" \
+// --keyblob_dir /data/local/tmp/keymint-blobs
+//
+// - this replaces the keyblob contents in that directory; if needed, save the upgraded keyblobs
+// with:
+// adb pull /data/local/tmp/keymint-blobs/
+TEST_P(KeyBlobUpgradeTest, UpgradeKeyBlobsAfter) {
+ UpgradeKeyBlobs(/* expectUpgrade= */ true);
+}
+
+// To run this test:
+//
+// - save off some keyblobs before upgrade as per the CreateKeyBlobs test above
+// - if needed, upgrade the saved keyblobs as per the UpgradeKeyBlobs test above
+// - run the test with:
+//
+// VtsAidlKeyMintTargetTest --gtest_filter="*KeyBlobUpgradeTest.UseKeyBlobs*" \
+// --keyblob_dir /data/local/tmp/keymint-blobs
+TEST_P(KeyBlobUpgradeTest, UseKeyBlobsBeforeOrAfter) {
+ std::string subdir = keyblob_subdir(keyblob_dir, GetParam(), /* create? */ false);
+ if (subdir.empty()) {
+ GTEST_SKIP() << "No keyblob directory provided with (e.g.) --keyblob_dir "
+ "/data/local/tmp/keymint-blobs";
+ }
+
+ for (std::string name : keyblob_names(SecLevel())) {
+ for (bool with_hidden : {false, true}) {
+ auto builder = AuthorizationSetBuilder();
+ if (with_hidden) {
+ // Build a variant keyblob that requires app_id/app_data
+ builder.Authorization(TAG_APPLICATION_ID, "appid")
+ .Authorization(TAG_APPLICATION_DATA, "appdata");
+ name += "-hidden";
+ }
+ SCOPED_TRACE(testing::Message() << name);
+ std::vector<uint8_t> keyblob = load_keyblob(subdir, name);
+ if (keyblob.empty()) {
+ if (requires_rr(name)) {
+ std::cerr << "Skipping missing keyblob file '" << name
+ << "', assuming rollback resistance unavailable\n";
+ } else {
+ FAIL() << "Missing keyblob file '" << name << "'";
+ }
+ continue;
+ }
+
+ std::vector<uint8_t> cert;
+ if (is_asymmetric(name)) {
+ cert = load_cert(subdir, name);
+ }
+
+ // Perform an algorithm-specific operation with the keyblob.
+ string message = "Hello World!";
+ AuthorizationSet out_params;
+ if (name.find("aes-key") != std::string::npos) {
+ builder.BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ string ciphertext = EncryptMessage(keyblob, message, builder, &out_params);
+ string plaintext = DecryptMessage(keyblob, ciphertext, builder);
+ EXPECT_EQ(message, plaintext);
+ } else if (name.find("des-key") != std::string::npos) {
+ builder.BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ string ciphertext = EncryptMessage(keyblob, message, builder, &out_params);
+ string plaintext = DecryptMessage(keyblob, ciphertext, builder);
+ EXPECT_EQ(message, plaintext);
+ } else if (name.find("hmac-key") != std::string::npos) {
+ builder.Digest(Digest::SHA1);
+ auto sign_builder = builder;
+ sign_builder.Authorization(TAG_MAC_LENGTH, 128);
+ string tag = SignMessage(keyblob, message, sign_builder);
+ VerifyMessage(keyblob, message, tag, builder);
+ } else if (name.find("rsa-key") != std::string::npos) {
+ builder.Digest(Digest::NONE).Padding(PaddingMode::NONE);
+ string signature = SignMessage(keyblob, message, builder);
+ LocalVerifyMessage(cert, message, signature, builder);
+ } else if (name.find("p256-key") != std::string::npos) {
+ builder.Digest(Digest::SHA1);
+ string signature = SignMessage(keyblob, message, builder);
+ LocalVerifyMessage(cert, message, signature, builder);
+ } else if (name.find("ed25519-key") != std::string::npos) {
+ builder.Digest(Digest::NONE);
+ string signature = SignMessage(keyblob, message, builder);
+ LocalVerifyMessage(cert, message, signature, builder);
+ } else if (name.find("x25519-key") != std::string::npos) {
+ // Generate EC key on same curve locally (with access to private key material).
+ uint8_t localPrivKeyData[32];
+ uint8_t localPubKeyData[32];
+ X25519_keypair(localPubKeyData, localPrivKeyData);
+ EVP_PKEY_Ptr localPrivKey(EVP_PKEY_new_raw_private_key(
+ EVP_PKEY_X25519, nullptr, localPrivKeyData, sizeof(localPrivKeyData)));
+ // Get encoded form of the public part of the locally generated key.
+ unsigned char* p = nullptr;
+ int localPublicKeySize = i2d_PUBKEY(localPrivKey.get(), &p);
+ ASSERT_GT(localPublicKeySize, 0);
+ vector<uint8_t> localPublicKey(
+ reinterpret_cast<const uint8_t*>(p),
+ reinterpret_cast<const uint8_t*>(p + localPublicKeySize));
+ OPENSSL_free(p);
+
+ // Agree on a key between local and KeyMint.
+ string data;
+ ASSERT_EQ(ErrorCode::OK,
+ Begin(KeyPurpose::AGREE_KEY, keyblob, builder, &out_params));
+ ASSERT_EQ(ErrorCode::OK,
+ Finish(string(localPublicKey.begin(), localPublicKey.end()), &data));
+ vector<uint8_t> keymint_data(data.begin(), data.end());
+
+ // Extract the public key for the KeyMint key from the cert.
+ X509_Ptr kmKeyCert(parse_cert_blob(cert));
+ ASSERT_NE(kmKeyCert, nullptr);
+ EVP_PKEY_Ptr kmPubKey = EVP_PKEY_Ptr(X509_get_pubkey(kmKeyCert.get()));
+ ASSERT_NE(kmPubKey.get(), nullptr);
+
+ size_t kmPubKeySize = 32;
+ uint8_t kmPubKeyData[32];
+ ASSERT_EQ(1,
+ EVP_PKEY_get_raw_public_key(kmPubKey.get(), kmPubKeyData, &kmPubKeySize));
+ ASSERT_EQ(kmPubKeySize, 32);
+
+ // Agree on a key between KeyMint and local.
+ uint8_t sharedKey[32];
+ ASSERT_EQ(1, X25519(sharedKey, localPrivKeyData, kmPubKeyData));
+ vector<uint8_t> local_data(sharedKey, sharedKey + 32);
+
+ // Both ways round should agree.
+ EXPECT_EQ(keymint_data, local_data);
+ } else if (name.find("-attest-key") != std::string::npos) {
+ // Covers rsa-attest-key, p256-attest-key, ed25519-attest-key.
+
+ // Use attestation key to sign RSA signing key
+ AttestationKey attest_key;
+ attest_key.keyBlob = keyblob;
+ attest_key.attestKeyParams = builder.vector_data();
+ attest_key.issuerSubjectName = make_name_from_str("Android Keystore Key");
+ vector<uint8_t> attested_key_blob;
+ vector<KeyCharacteristics> attested_key_characteristics;
+ vector<Certificate> attested_key_cert_chain;
+ EXPECT_EQ(ErrorCode::OK,
+ GenerateKey(AuthorizationSetBuilder()
+ .RsaSigningKey(2048, 65537)
+ .Authorization(TAG_NO_AUTH_REQUIRED)
+ .AttestationChallenge("challenge")
+ .AttestationApplicationId("app-id")
+ .SetDefaultValidity(),
+ attest_key, &attested_key_blob, &attested_key_characteristics,
+ &attested_key_cert_chain));
+ CheckedDeleteKey(&attested_key_blob);
+ } else {
+ FAIL() << "Unexpected name: " << name;
+ }
+ }
+ }
+}
+
+// This test target deletes any keys from the keyblob subdirectory that have rollback resistance
+// enabled.
+TEST_P(KeyBlobUpgradeTest, DeleteRRKeyBlobsAfter) {
+ std::string subdir = keyblob_subdir(keyblob_dir, GetParam(), /* create? */ false);
+ if (subdir.empty()) {
+ GTEST_SKIP() << "No keyblob directory provided with (e.g.) --keyblob_dir "
+ "/data/local/tmp/keymint-blobs";
+ }
+
+ for (std::string name : keyblob_names(SecLevel())) {
+ for (bool with_hidden : {false, true}) {
+ auto builder = AuthorizationSetBuilder();
+ if (with_hidden) {
+ // Build a variant keyblob that requires app_id/app_data
+ builder.Authorization(TAG_APPLICATION_ID, "appid")
+ .Authorization(TAG_APPLICATION_DATA, "appdata");
+ name += "-hidden";
+ }
+ if (!requires_rr(name)) {
+ std::cerr << "Skipping keyblob file '" << name
+ << "' which does not use rollback resistance\n";
+ continue;
+ }
+ SCOPED_TRACE(testing::Message() << name);
+ std::vector<uint8_t> keyblob = load_keyblob(subdir, name);
+ if (keyblob.empty()) {
+ std::cerr << "Skipping missing keyblob file '" << name
+ << "', assuming rollback resistance unavailable\n";
+ continue;
+ }
+
+ // Delete the key
+ ASSERT_EQ(ErrorCode::OK, DeleteKey(&keyblob));
+
+ // Remove all files relating to the deleted key.
+ std::cerr << "Deleting files for deleted key '" << name << ";";
+ delete_keyblob(subdir, name);
+
+ // Attempting to use the keyblob after deletion should fail.
+ AuthorizationSet out_params;
+ if (name.find("aes-key") != std::string::npos) {
+ builder.BlockMode(BlockMode::ECB).Padding(PaddingMode::PKCS7);
+ EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
+ Begin(KeyPurpose::ENCRYPT, keyblob, builder, &out_params));
+ } else {
+ FAIL() << "Unexpected name: " << name;
+ }
+ }
+ }
+}
+
+INSTANTIATE_KEYMINT_AIDL_TEST(KeyBlobUpgradeTest);
+
+} // namespace aidl::android::hardware::security::keymint::test
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
index 43ad30a..6c012fa 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp
@@ -184,6 +184,7 @@
bool KeyMintAidlTestBase::arm_deleteAllKeys = false;
bool KeyMintAidlTestBase::dump_Attestations = false;
+std::string KeyMintAidlTestBase::keyblob_dir;
uint32_t KeyMintAidlTestBase::boot_patch_level(
const vector<KeyCharacteristics>& key_characteristics) {
@@ -946,9 +947,15 @@
const AuthorizationSet& params) {
SCOPED_TRACE("LocalVerifyMessage");
- // Retrieve the public key from the leaf certificate.
ASSERT_GT(cert_chain_.size(), 0);
- X509_Ptr key_cert(parse_cert_blob(cert_chain_[0].encodedCertificate));
+ LocalVerifyMessage(cert_chain_[0].encodedCertificate, message, signature, params);
+}
+
+void KeyMintAidlTestBase::LocalVerifyMessage(const vector<uint8_t>& der_cert, const string& message,
+ const string& signature,
+ const AuthorizationSet& params) {
+ // Retrieve the public key from the leaf certificate.
+ X509_Ptr key_cert(parse_cert_blob(der_cert));
ASSERT_TRUE(key_cert.get());
EVP_PKEY_Ptr pub_key(X509_get_pubkey(key_cert.get()));
ASSERT_TRUE(pub_key.get());
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
index 5b09ca5..908eeab 100644
--- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
+++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h
@@ -64,6 +64,10 @@
static bool arm_deleteAllKeys;
static bool dump_Attestations;
+ // Directory to store/retrieve keyblobs, using subdirectories named for the
+ // KeyMint instance in question (e.g. "./default/", "./strongbox/").
+ static std::string keyblob_dir;
+
void SetUp() override;
void TearDown() override {
if (key_blob_.size()) {
@@ -206,6 +210,8 @@
const string& signature, const AuthorizationSet& params);
void VerifyMessage(const string& message, const string& signature,
const AuthorizationSet& params);
+ void LocalVerifyMessage(const vector<uint8_t>& der_cert, const string& message,
+ const string& signature, const AuthorizationSet& params);
void LocalVerifyMessage(const string& message, const string& signature,
const AuthorizationSet& params);
diff --git a/security/keymint/aidl/vts/functional/KeyMintTest.cpp b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
index ca18082..342b926 100644
--- a/security/keymint/aidl/vts/functional/KeyMintTest.cpp
+++ b/security/keymint/aidl/vts/functional/KeyMintTest.cpp
@@ -8649,6 +8649,15 @@
// interactions.
aidl::android::hardware::security::keymint::test::check_boot_pl = false;
}
+ if (std::string(argv[i]) == "--keyblob_dir") {
+ if (i + 1 >= argc) {
+ std::cerr << "Missing argument for --keyblob_dir\n";
+ return 1;
+ }
+ aidl::android::hardware::security::keymint::test::KeyMintAidlTestBase::keyblob_dir =
+ std::string(argv[i + 1]);
+ ++i;
+ }
}
}
return RUN_ALL_TESTS();
diff --git a/sensors/1.0/default/OWNERS b/sensors/1.0/default/OWNERS
deleted file mode 100644
index 90c2330..0000000
--- a/sensors/1.0/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
diff --git a/sensors/1.0/vts/functional/OWNERS b/sensors/1.0/vts/functional/OWNERS
deleted file mode 100644
index e20125b..0000000
--- a/sensors/1.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 62965
-include ../../../common/vts/OWNERS
diff --git a/sensors/2.0/default/OWNERS b/sensors/2.0/default/OWNERS
deleted file mode 100644
index 90c2330..0000000
--- a/sensors/2.0/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
diff --git a/sensors/2.0/multihal/OWNERS b/sensors/2.0/multihal/OWNERS
deleted file mode 100644
index e955670..0000000
--- a/sensors/2.0/multihal/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
\ No newline at end of file
diff --git a/sensors/2.0/vts/functional/OWNERS b/sensors/2.0/vts/functional/OWNERS
deleted file mode 100644
index e20125b..0000000
--- a/sensors/2.0/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 62965
-include ../../../common/vts/OWNERS
diff --git a/sensors/2.1/default/OWNERS b/sensors/2.1/default/OWNERS
deleted file mode 100644
index 90c2330..0000000
--- a/sensors/2.1/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
diff --git a/sensors/2.1/multihal/OWNERS b/sensors/2.1/multihal/OWNERS
deleted file mode 100644
index e955670..0000000
--- a/sensors/2.1/multihal/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
\ No newline at end of file
diff --git a/sensors/2.1/vts/functional/OWNERS b/sensors/2.1/vts/functional/OWNERS
deleted file mode 100644
index e20125b..0000000
--- a/sensors/2.1/vts/functional/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 62965
-include ../../../common/vts/OWNERS
diff --git a/sensors/common/vts/OWNERS b/sensors/OWNERS
similarity index 83%
rename from sensors/common/vts/OWNERS
rename to sensors/OWNERS
index 1b9a2f8..e7ebd3e 100644
--- a/sensors/common/vts/OWNERS
+++ b/sensors/OWNERS
@@ -1,5 +1,5 @@
# Bug component: 62965
-# Sensors team
+
arthuri@google.com
bduddie@google.com
stange@google.com
diff --git a/sensors/aidl/default/OWNERS b/sensors/aidl/default/OWNERS
deleted file mode 100644
index e955670..0000000
--- a/sensors/aidl/default/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
\ No newline at end of file
diff --git a/sensors/aidl/multihal/OWNERS b/sensors/aidl/multihal/OWNERS
deleted file mode 100644
index e955670..0000000
--- a/sensors/aidl/multihal/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
\ No newline at end of file
diff --git a/sensors/aidl/vts/OWNERS b/sensors/aidl/vts/OWNERS
deleted file mode 100644
index 90c2330..0000000
--- a/sensors/aidl/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
diff --git a/sensors/common/default/2.X/OWNERS b/sensors/common/default/2.X/OWNERS
deleted file mode 100644
index 90c2330..0000000
--- a/sensors/common/default/2.X/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
diff --git a/sensors/common/utils/OWNERS b/sensors/common/utils/OWNERS
deleted file mode 100644
index 90c2330..0000000
--- a/sensors/common/utils/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-arthuri@google.com
-bduddie@google.com
-stange@google.com
diff --git a/sensors/common/vts/utils/OWNERS b/sensors/common/vts/utils/OWNERS
deleted file mode 100644
index 892da15..0000000
--- a/sensors/common/vts/utils/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-# Sensors team
-arthuri@google.com
-bduddie@google.com
-stange@google.com
-
-# VTS team
-trong@google.com
-yim@google.com
diff --git a/tv/earc/aidl/Android.bp b/tv/earc/aidl/Android.bp
new file mode 100644
index 0000000..5db6032
--- /dev/null
+++ b/tv/earc/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.earc",
+ vendor_available: true,
+ srcs: ["android/hardware/tv/earc/*.aidl"],
+ stability: "vintf",
+ backend: {
+ java: {
+ sdk_version: "module_current",
+ },
+ },
+}
diff --git a/tv/earc/aidl/OWNERS b/tv/earc/aidl/OWNERS
new file mode 100644
index 0000000..d9c6783
--- /dev/null
+++ b/tv/earc/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/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/IEArc.aidl b/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/IEArc.aidl
new file mode 100644
index 0000000..552bb46
--- /dev/null
+++ b/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/IEArc.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.tv.earc;
+@VintfStability
+interface IEArc {
+ void setEArcEnabled(in boolean enabled);
+ boolean isEArcEnabled();
+ void setCallback(in android.hardware.tv.earc.IEArcCallback callback);
+ android.hardware.tv.earc.IEArcStatus getState(in int portId);
+ byte[] getLastReportedAudioCapabilities(in int portId);
+}
diff --git a/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/IEArcCallback.aidl b/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/IEArcCallback.aidl
new file mode 100644
index 0000000..ef99824
--- /dev/null
+++ b/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/IEArcCallback.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.earc;
+@VintfStability
+interface IEArcCallback {
+ oneway void onStateChange(in android.hardware.tv.earc.IEArcStatus status, in int portId);
+ oneway void onCapabilitiesReported(in byte[] rawCapabilities, in int portId);
+}
diff --git a/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/IEArcStatus.aidl b/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/IEArcStatus.aidl
new file mode 100644
index 0000000..729c657
--- /dev/null
+++ b/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/IEArcStatus.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.earc;
+@Backing(type="byte") @VintfStability
+enum IEArcStatus {
+ STATUS_IDLE = 0,
+ STATUS_EARC_PENDING = 1,
+ STATUS_ARC_PENDING = 2,
+ STATUS_EARC_CONNECTED = 3,
+}
diff --git a/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/Result.aidl b/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/Result.aidl
new file mode 100644
index 0000000..3679d3b
--- /dev/null
+++ b/tv/earc/aidl/aidl_api/android.hardware.tv.earc/current/android/hardware/tv/earc/Result.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.earc;
+@VintfStability
+enum Result {
+ SUCCESS = 0,
+ FAILURE_UNKNOWN = 1,
+ FAILURE_INVALID_ARGS = 2,
+ FAILURE_NOT_SUPPORTED = 4,
+}
diff --git a/tv/earc/aidl/android/hardware/tv/earc/IEArc.aidl b/tv/earc/aidl/android/hardware/tv/earc/IEArc.aidl
new file mode 100644
index 0000000..bb8dabf
--- /dev/null
+++ b/tv/earc/aidl/android/hardware/tv/earc/IEArc.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.tv.earc;
+
+import android.hardware.tv.earc.IEArcCallback;
+import android.hardware.tv.earc.IEArcStatus;
+
+/**
+ * eARC HAL interface definition
+ */
+@VintfStability
+interface IEArc {
+ /**
+ * Function to enable or disable eARC in the device's driver and HAL. If enabled, the driver and
+ * HAL shall attempt to establish an eARC connection and inform the Android framework about
+ * updates with IEArcCallback callbacks. If disabled, the driver and HAL shall not attempt to
+ * establish an eARC connection and shall not send any IEArcCallback callbacks to the Android
+ * framework.
+ * The error status is set to
+ * {@code SUCCESS} if the setting could be changed to the value passed.
+ * {@code FAILURE_NOT_SUPPORTED} if the setting is not supported.
+ * {@code FAILURE_INVALID_ARGS} if the setting value is invalid.
+ * {@code FAILURE_UNKNOWN} if there was an unknown failure.
+ */
+ void setEArcEnabled(in boolean enabled);
+
+ /**
+ * Function to check if eARC is enabled in the device's driver and HAL.
+ */
+ boolean isEArcEnabled();
+
+ /**
+ * Function to set callback that the HAL will use to notify the system of connection state
+ * changes and capabilities of connected devices.
+ *
+ * @param callback The callback object to pass the events to the system. A previously registered
+ * callback should be replaced by this new object. If callback is {@code null} the
+ * previously registered callback should be deregistered.
+ */
+ void setCallback(in IEArcCallback callback);
+
+ /**
+ * Getter for the current eARC state of a port.
+ *
+ * @param portId The port ID for which the state is to be reported.
+ * @return The state of the port.
+ */
+ IEArcStatus getState(in int portId);
+
+ /**
+ * Getter for the most recent capabilities reported by the device connected to port.
+ *
+ * @param portId The port ID on which the device is connected.
+ * @return The raw, unparsed audio capabilities
+ */
+ byte[] getLastReportedAudioCapabilities(in int portId);
+}
diff --git a/tv/earc/aidl/android/hardware/tv/earc/IEArcCallback.aidl b/tv/earc/aidl/android/hardware/tv/earc/IEArcCallback.aidl
new file mode 100644
index 0000000..c70191f
--- /dev/null
+++ b/tv/earc/aidl/android/hardware/tv/earc/IEArcCallback.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.tv.earc;
+
+import android.hardware.tv.earc.IEArcStatus;
+
+/**
+ * eARC HAL callback methods
+ */
+@VintfStability
+oneway interface IEArcCallback {
+ /**
+ * The callback function that must be called by the eARC driver and HAL implementation to notify
+ * the Android framework of an eARC status change.
+ * @param status The new status of the port
+ * @param portId The port ID for which the state change is being reported
+ */
+ void onStateChange(in IEArcStatus status, in int portId);
+
+ /**
+ * The callback function that must be called by the eARC driver and HAL implementation to
+ * notify the Android framework of the audio capabilities reported by the connected device. On
+ * every state change to {@code STATUS_EARC_CONNECTED}, the driver shall read the capabilities
+ * reported by the eARC RX. The onStateChange callback shall always be invoked first and the
+ * onCapabilitiesReported callback shall be invoked second.
+ * @param rawCapabilities The raw unparsed audio capabilities (Ref "Section 9.5.3.6 - eARC RX
+ * Capabilities Data Structure" in HDMI 2.1 specification).
+ * @param portId The port ID for which the audio capabilities are being reported
+ */
+ void onCapabilitiesReported(in byte[] rawCapabilities, in int portId);
+}
diff --git a/tv/earc/aidl/android/hardware/tv/earc/IEArcStatus.aidl b/tv/earc/aidl/android/hardware/tv/earc/IEArcStatus.aidl
new file mode 100644
index 0000000..ecb1c85
--- /dev/null
+++ b/tv/earc/aidl/android/hardware/tv/earc/IEArcStatus.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.earc;
+
+/**
+ * eARC HAL connection states
+ */
+@VintfStability
+@Backing(type="byte")
+enum IEArcStatus {
+ STATUS_IDLE = 0,
+ STATUS_EARC_PENDING = 1,
+ STATUS_ARC_PENDING = 2,
+ STATUS_EARC_CONNECTED = 3,
+}
diff --git a/tv/earc/aidl/android/hardware/tv/earc/Result.aidl b/tv/earc/aidl/android/hardware/tv/earc/Result.aidl
new file mode 100644
index 0000000..054518a
--- /dev/null
+++ b/tv/earc/aidl/android/hardware/tv/earc/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.
+ */
+
+package android.hardware.tv.earc;
+
+/**
+ * Result enum for return values. Used by the HDMI related AIDL.
+ */
+@VintfStability
+enum Result {
+ /**
+ * The eARC enabled setting was set successfully.
+ */
+ SUCCESS = 0,
+
+ /**
+ * The eARC enabled setting could not be set because of an unknown failure.
+ */
+ FAILURE_UNKNOWN = 1,
+
+ /**
+ * The eARC enabled setting could not be set because the arguments were invalid.
+ */
+ FAILURE_INVALID_ARGS = 2,
+
+ /**
+ * The eARC enabled setting could not be set because eARC feature is not supported.
+ */
+ FAILURE_NOT_SUPPORTED = 4,
+}
diff --git a/tv/earc/aidl/default/Android.bp b/tv/earc/aidl/default/Android.bp
new file mode 100644
index 0000000..399f029
--- /dev/null
+++ b/tv/earc/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.earc-service",
+ vintf_fragments: ["android.hardware.tv.earc-service.xml"],
+ relative_install_path: "hw",
+ vendor: true,
+ cflags: [
+ "-Wall",
+ "-Wextra",
+ ],
+ init_rc: ["android.hardware.tv.earc-service.rc"],
+ srcs: [
+ "serviceMock.cpp",
+ "EArcMock.cpp",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ "liblog",
+ "libbase",
+ "libutils",
+ "libhardware",
+ "libhidlbase",
+ "android.hardware.tv.earc-V1-ndk",
+ ],
+}
+
+cc_fuzz {
+ name: "android.hardware.tv.earc-service_fuzzer",
+ defaults: ["service_fuzzer_defaults"],
+ static_libs: [
+ "android.hardware.tv.earc-V1-ndk",
+ "liblog",
+ ],
+ srcs: [
+ "fuzzer.cpp",
+ "EArcMock.cpp",
+ ],
+ fuzz_config: {
+ componentid: 826094,
+ },
+}
diff --git a/tv/earc/aidl/default/EArcMock.cpp b/tv/earc/aidl/default/EArcMock.cpp
new file mode 100644
index 0000000..9bccc18
--- /dev/null
+++ b/tv/earc/aidl/default/EArcMock.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.
+ */
+
+#define LOG_TAG "android.hardware.tv.earc"
+#include <android-base/logging.h>
+#include <fcntl.h>
+#include <utils/Log.h>
+
+#include "EArcMock.h"
+
+using ndk::ScopedAStatus;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace earc {
+namespace implementation {
+
+void EArcMock::serviceDied(void* cookie) {
+ ALOGE("EArcMock died");
+ auto eArc = static_cast<EArcMock*>(cookie);
+ eArc->mEArcEnabled = false;
+}
+
+ScopedAStatus EArcMock::setEArcEnabled(bool in_enabled) {
+ mEArcEnabled = in_enabled;
+ if (mEArcEnabled != in_enabled) {
+ return ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::FAILURE_UNKNOWN));
+ } else {
+ return ScopedAStatus::ok();
+ }
+}
+
+ScopedAStatus EArcMock::isEArcEnabled(bool* _aidl_return) {
+ *_aidl_return = mEArcEnabled;
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus EArcMock::getState(int32_t portId, IEArcStatus* _aidl_return) {
+ // Maintain port connection status and update on hotplug event
+ if (portId <= mTotalPorts && portId >= 1) {
+ *_aidl_return = mPortStatus[portId];
+ } else {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus EArcMock::getLastReportedAudioCapabilities(int32_t portId,
+ std::vector<uint8_t>* _aidl_return) {
+ if (portId <= mTotalPorts && portId >= 1) {
+ *_aidl_return = mCapabilities[portId];
+ } else {
+ return ScopedAStatus::fromExceptionCode(EX_ILLEGAL_ARGUMENT);
+ }
+
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus EArcMock::setCallback(const std::shared_ptr<IEArcCallback>& callback) {
+ if (mCallback != nullptr) {
+ mCallback = nullptr;
+ }
+
+ if (callback != nullptr) {
+ mCallback = callback;
+ AIBinder_linkToDeath(this->asBinder().get(), mDeathRecipient.get(), 0 /* cookie */);
+ }
+ return ScopedAStatus::ok();
+}
+
+ScopedAStatus EArcMock::reportCapabilities(const std::vector<uint8_t> capabilities,
+ int32_t portId) {
+ if (mCallback != nullptr) {
+ mCallback->onCapabilitiesReported(capabilities, portId);
+ return ScopedAStatus::ok();
+ } else {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
+}
+
+ScopedAStatus EArcMock::changeState(const IEArcStatus status, int32_t portId) {
+ if (mCallback != nullptr) {
+ mCallback->onStateChange(status, portId);
+ return ScopedAStatus::ok();
+ } else {
+ return ScopedAStatus::fromExceptionCode(EX_NULL_POINTER);
+ }
+}
+
+EArcMock::EArcMock() {
+ ALOGE("[halimp_aidl] Opening a virtual eARC HAL for testing and virtual machine.");
+ mCallback = nullptr;
+ mCapabilities.resize(mTotalPorts);
+ mPortStatus.resize(mTotalPorts);
+ mPortStatus[0] = IEArcStatus::STATUS_IDLE;
+ mDeathRecipient = ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(serviceDied));
+}
+
+} // namespace implementation
+} // namespace earc
+} // namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/earc/aidl/default/EArcMock.h b/tv/earc/aidl/default/EArcMock.h
new file mode 100644
index 0000000..9081950
--- /dev/null
+++ b/tv/earc/aidl/default/EArcMock.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.
+ */
+
+#include <aidl/android/hardware/tv/earc/BnEArc.h>
+#include <aidl/android/hardware/tv/earc/Result.h>
+#include <algorithm>
+#include <vector>
+
+using namespace std;
+
+namespace android {
+namespace hardware {
+namespace tv {
+namespace earc {
+namespace implementation {
+
+using ::aidl::android::hardware::tv::earc::BnEArc;
+using ::aidl::android::hardware::tv::earc::IEArc;
+using ::aidl::android::hardware::tv::earc::IEArcCallback;
+using ::aidl::android::hardware::tv::earc::IEArcStatus;
+using ::aidl::android::hardware::tv::earc::Result;
+
+struct EArcMock : public BnEArc {
+ EArcMock();
+
+ ::ndk::ScopedAStatus setEArcEnabled(bool in_enabled) override;
+ ::ndk::ScopedAStatus isEArcEnabled(bool* _aidl_return) override;
+ ::ndk::ScopedAStatus setCallback(const std::shared_ptr<IEArcCallback>& in_callback) override;
+ ::ndk::ScopedAStatus getState(int32_t in_portId, IEArcStatus* _aidl_return) override;
+ ::ndk::ScopedAStatus getLastReportedAudioCapabilities(
+ int32_t in_portId, std::vector<uint8_t>* _aidl_return) override;
+ ::ndk::ScopedAStatus reportCapabilities(const std::vector<uint8_t> capabilities,
+ int32_t portId);
+ ::ndk::ScopedAStatus changeState(const IEArcStatus status, int32_t portId);
+
+ private:
+ static void* __threadLoop(void* data);
+ void threadLoop();
+
+ private:
+ static void serviceDied(void* cookie);
+ std::shared_ptr<IEArcCallback> mCallback;
+
+ // Variables for the virtual EARC hal impl
+ std::vector<std::vector<uint8_t>> mCapabilities;
+ std::vector<IEArcStatus> mPortStatus;
+ bool mEArcEnabled = true;
+
+ // Port configuration
+ int mTotalPorts = 1;
+
+ // Testing variables
+ pthread_t mThreadId = 0;
+
+ ::ndk::ScopedAIBinder_DeathRecipient mDeathRecipient;
+};
+} // namespace implementation
+} // namespace earc
+} // Namespace tv
+} // namespace hardware
+} // namespace android
diff --git a/tv/earc/aidl/default/android.hardware.tv.earc-service.rc b/tv/earc/aidl/default/android.hardware.tv.earc-service.rc
new file mode 100644
index 0000000..0d9063e
--- /dev/null
+++ b/tv/earc/aidl/default/android.hardware.tv.earc-service.rc
@@ -0,0 +1,5 @@
+service vendor.earc-default /vendor/bin/hw/android.hardware.tv.earc-service
+ interface aidl android.hardware.tv.earc.IEArc/default
+ class hal
+ user system
+ group system
diff --git a/tv/earc/aidl/default/android.hardware.tv.earc-service.xml b/tv/earc/aidl/default/android.hardware.tv.earc-service.xml
new file mode 100644
index 0000000..4d66d98
--- /dev/null
+++ b/tv/earc/aidl/default/android.hardware.tv.earc-service.xml
@@ -0,0 +1,10 @@
+<manifest version="1.0" type="device">
+ <hal format="aidl">
+ <name>android.hardware.tv.earc</name>
+ <version>1</version>
+ <interface>
+ <name>IEArc</name>
+ <instance>default</instance>
+ </interface>
+ </hal>
+</manifest>
diff --git a/tv/earc/aidl/default/fuzzer.cpp b/tv/earc/aidl/default/fuzzer.cpp
new file mode 100644
index 0000000..5036853
--- /dev/null
+++ b/tv/earc/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 <EArcMock.h>
+#include <fuzzbinder/libbinder_ndk_driver.h>
+#include <fuzzer/FuzzedDataProvider.h>
+
+using android::fuzzService;
+using android::hardware::tv::earc::implementation::EArcMock;
+using ndk::SharedRefBase;
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ auto earcAidl = SharedRefBase::make<EArcMock>();
+
+ fuzzService(earcAidl->asBinder().get(), FuzzedDataProvider(data, size));
+
+ return 0;
+}
diff --git a/tv/earc/aidl/default/serviceMock.cpp b/tv/earc/aidl/default/serviceMock.cpp
new file mode 100644
index 0000000..1ea7262
--- /dev/null
+++ b/tv/earc/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.earc-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 "EArcMock.h"
+
+using android::hardware::tv::earc::implementation::EArcMock;
+
+int main() {
+ ABinderProcess_setThreadPoolMaxThreadCount(1);
+ ABinderProcess_startThreadPool();
+
+ std::shared_ptr<EArcMock> earcAidl = ndk::SharedRefBase::make<EArcMock>();
+ const std::string instance = std::string() + EArcMock::descriptor + "/default";
+ binder_status_t status =
+ AServiceManager_addService(earcAidl->asBinder().get(), instance.c_str());
+ CHECK_EQ(status, STATUS_OK);
+
+ ABinderProcess_joinThreadPool();
+ return 0;
+}
diff --git a/tv/earc/aidl/vts/functional/Android.bp b/tv/earc/aidl/vts/functional/Android.bp
new file mode 100644
index 0000000..797547e
--- /dev/null
+++ b/tv/earc/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: "VtsHalTvEArcAidlTargetTest",
+ defaults: [
+ "VtsHalTargetTestDefaults",
+ "use_libaidlvintf_gtest_helper_static",
+ ],
+ srcs: ["VtsHalTvEArcAidlTargetTest.cpp"],
+ static_libs: [
+ "android.hardware.tv.earc-V1-ndk",
+ ],
+ shared_libs: [
+ "libbinder_ndk",
+ ],
+ test_suites: [
+ "general-tests",
+ "vts",
+ ],
+ disable_framework: true,
+}
diff --git a/tv/earc/aidl/vts/functional/VtsHalTvEArcAidlTargetTest.cpp b/tv/earc/aidl/vts/functional/VtsHalTvEArcAidlTargetTest.cpp
new file mode 100644
index 0000000..12f48c3
--- /dev/null
+++ b/tv/earc/aidl/vts/functional/VtsHalTvEArcAidlTargetTest.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT 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 "EArc_hal_test"
+
+#include <aidl/Gtest.h>
+#include <aidl/Vintf.h>
+#include <aidl/android/hardware/tv/earc/BnEArcCallback.h>
+#include <aidl/android/hardware/tv/earc/IEArc.h>
+#include <aidl/android/hardware/tv/earc/IEArcStatus.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::earc::BnEArcCallback;
+using ::aidl::android::hardware::tv::earc::IEArc;
+using ::aidl::android::hardware::tv::earc::IEArcCallback;
+using ::aidl::android::hardware::tv::earc::IEArcStatus;
+using ::ndk::SpAIBinder;
+
+// The main test class for TV EARC HAL.
+class EArcTest : public ::testing::TestWithParam<std::string> {
+ static void serviceDied(void* /* cookie */) { ALOGE("VtsHalTvCecAidlTargetTest died"); }
+
+ public:
+ void SetUp() override {
+ eArc = IEArc::fromBinder(SpAIBinder(AServiceManager_waitForService(GetParam().c_str())));
+ ASSERT_NE(eArc, nullptr);
+ ALOGI("%s: getService() for eArc is %s", __func__, eArc->isRemote() ? "remote" : "local");
+
+ eArcCallback = ::ndk::SharedRefBase::make<EArcCallback>();
+ ASSERT_NE(eArcCallback, nullptr);
+ eArcDeathRecipient =
+ ndk::ScopedAIBinder_DeathRecipient(AIBinder_DeathRecipient_new(&serviceDied));
+ ASSERT_EQ(AIBinder_linkToDeath(eArc->asBinder().get(), eArcDeathRecipient.get(), 0),
+ STATUS_OK);
+ }
+
+ class EArcCallback : public BnEArcCallback {
+ public:
+ ::ndk::ScopedAStatus onStateChange(IEArcStatus connected __unused,
+ int32_t portId __unused) {
+ return ::ndk::ScopedAStatus::ok();
+ };
+ ::ndk::ScopedAStatus onCapabilitiesReported(
+ const std::vector<uint8_t>& capabilities __unused, int32_t portId __unused) {
+ return ::ndk::ScopedAStatus::ok();
+ };
+ };
+
+ std::shared_ptr<IEArc> eArc;
+ std::shared_ptr<IEArcCallback> eArcCallback;
+ ::ndk::ScopedAIBinder_DeathRecipient eArcDeathRecipient;
+};
+
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(EArcTest);
+INSTANTIATE_TEST_SUITE_P(PerInstance, EArcTest,
+ testing::ValuesIn(android::getAidlHalInstanceNames(IEArc::descriptor)),
+ android::PrintInstanceNameToString);
+
+TEST_P(EArcTest, setGetEArcEnabled) {
+ bool initial_state;
+ bool changed_state;
+ ASSERT_TRUE(eArc->isEArcEnabled(&initial_state).isOk());
+ ASSERT_TRUE(eArc->setEArcEnabled(!initial_state).isOk());
+ ASSERT_TRUE(eArc->isEArcEnabled(&changed_state).isOk());
+ ASSERT_TRUE(initial_state != changed_state);
+ ASSERT_TRUE(eArc->setEArcEnabled(initial_state).isOk());
+}
+
+TEST_P(EArcTest, SetCallback) {
+ ASSERT_TRUE(eArc->setCallback(eArcCallback).isOk());
+}
+
+TEST_P(EArcTest, GetState) {
+ IEArcStatus connectionStatus;
+ ASSERT_TRUE(eArc->getState(1, &connectionStatus).isOk());
+}
+
+TEST_P(EArcTest, GetLastReportedAudioCapabilities) {
+ std::vector<uint8_t> capabilities;
+ ASSERT_TRUE(eArc->getLastReportedAudioCapabilities(1, &capabilities).isOk());
+}
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HpdSignal.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HpdSignal.aidl
new file mode 100644
index 0000000..eef4025
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/HpdSignal.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 HpdSignal {
+ HDMI_HPD_PHYSICAL = 0,
+ HDMI_HPD_STATUS_BIT = 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
index 3fc7f41..809d392 100644
--- 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
@@ -37,4 +37,6 @@
android.hardware.tv.hdmi.HdmiPortInfo[] getPortInfo();
boolean isConnected(in int portId);
void setCallback(in android.hardware.tv.hdmi.IHdmiCallback callback);
+ void setHpdSignal(android.hardware.tv.hdmi.HpdSignal signal);
+ android.hardware.tv.hdmi.HpdSignal getHpdSignal();
}
diff --git a/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/Result.aidl b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/Result.aidl
new file mode 100644
index 0000000..b6b0eb3
--- /dev/null
+++ b/tv/hdmi/aidl/aidl_api/android.hardware.tv.hdmi/current/android/hardware/tv/hdmi/Result.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.tv.hdmi;
+@VintfStability
+enum Result {
+ SUCCESS = 0,
+ FAILURE_UNKNOWN = 1,
+ FAILURE_INVALID_ARGS = 2,
+ FAILURE_INVALID_STATE = 3,
+ FAILURE_NOT_SUPPORTED = 4,
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/HpdSignal.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/HpdSignal.aidl
new file mode 100644
index 0000000..05963f2
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/HpdSignal.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;
+
+/**
+ * HPD (Hotplug Detection) Signal Types
+ */
+@VintfStability
+@Backing(type="byte")
+enum HpdSignal {
+ HDMI_HPD_PHYSICAL = 0,
+ HDMI_HPD_STATUS_BIT = 1,
+}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl
index 5536846..457234d 100644
--- a/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/IHdmi.aidl
@@ -17,6 +17,7 @@
package android.hardware.tv.hdmi;
import android.hardware.tv.hdmi.HdmiPortInfo;
+import android.hardware.tv.hdmi.HpdSignal;
import android.hardware.tv.hdmi.IHdmiCallback;
/**
@@ -48,4 +49,17 @@
* setCallback(null) should deregister the callback.
*/
void setCallback(in IHdmiCallback callback);
+
+ /**
+ * Method to set the HPD (Hot Plug Detection) signal the HAL should use for HPD signaling (e.g.
+ * signaling EDID updates). By default, the HAL will use {@code HDMI_HPD_PHYSICAL} (the physical
+ * hotplug signal). When set to {@code HDMI_HPD_STATUS_BIT} the HAL should use the HDP status
+ * bit.
+ */
+ void setHpdSignal(HpdSignal signal);
+
+ /**
+ * Get the current signal the HAL is using for HPD
+ */
+ HpdSignal getHpdSignal();
}
diff --git a/tv/hdmi/aidl/android/hardware/tv/hdmi/Result.aidl b/tv/hdmi/aidl/android/hardware/tv/hdmi/Result.aidl
new file mode 100644
index 0000000..d2a1fef
--- /dev/null
+++ b/tv/hdmi/aidl/android/hardware/tv/hdmi/Result.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.tv.hdmi;
+
+/**
+ * Result enum for return values. Used by the HDMI related AIDL.
+ */
+@VintfStability
+enum Result {
+ /**
+ * The HPD Signal type was set successfully.
+ */
+ SUCCESS = 0,
+
+ /**
+ * The HPD Signal type could not be set because of an unknown failure.
+ */
+ FAILURE_UNKNOWN = 1,
+
+ /**
+ * The HPD Signal type could not be set because the arguments were invalid.
+ */
+ FAILURE_INVALID_ARGS = 2,
+
+ /**
+ * The HPD Signal type could not be set because the HAL is in an invalid state.
+ */
+ FAILURE_INVALID_STATE = 3,
+
+ /**
+ * The HPD Signal type could not be set as the signal type is not supported.
+ */
+ FAILURE_NOT_SUPPORTED = 4,
+}
diff --git a/tv/hdmi/aidl/default/HdmiMock.cpp b/tv/hdmi/aidl/default/HdmiMock.cpp
index bbc4705..7cd9bb7 100644
--- a/tv/hdmi/aidl/default/HdmiMock.cpp
+++ b/tv/hdmi/aidl/default/HdmiMock.cpp
@@ -67,6 +67,21 @@
return ScopedAStatus::ok();
}
+ScopedAStatus HdmiMock::setHpdSignal(HpdSignal signal) {
+ if (mHdmiThreadRun) {
+ mHpdSignal = signal;
+ return ScopedAStatus::ok();
+ } else {
+ return ScopedAStatus::fromServiceSpecificError(
+ static_cast<int32_t>(Result::FAILURE_INVALID_STATE));
+ }
+}
+
+ScopedAStatus HdmiMock::getHpdSignal(HpdSignal* _aidl_return) {
+ *_aidl_return = mHpdSignal;
+ return ScopedAStatus::ok();
+}
+
void* HdmiMock::__threadLoop(void* user) {
HdmiMock* const self = static_cast<HdmiMock*>(user);
self->threadLoop();
diff --git a/tv/hdmi/aidl/default/HdmiMock.h b/tv/hdmi/aidl/default/HdmiMock.h
index 05795dd..51abaff 100644
--- a/tv/hdmi/aidl/default/HdmiMock.h
+++ b/tv/hdmi/aidl/default/HdmiMock.h
@@ -15,6 +15,7 @@
*/
#include <aidl/android/hardware/tv/hdmi/BnHdmi.h>
+#include <aidl/android/hardware/tv/hdmi/Result.h>
#include <algorithm>
#include <vector>
@@ -29,8 +30,10 @@
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::HpdSignal;
using ::aidl::android::hardware::tv::hdmi::IHdmi;
using ::aidl::android::hardware::tv::hdmi::IHdmiCallback;
+using ::aidl::android::hardware::tv::hdmi::Result;
#define HDMI_MSG_IN_FIFO "/dev/hdmi_in_pipe"
#define MESSAGE_BODY_MAX_LENGTH 4
@@ -41,6 +44,8 @@
::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;
+ ::ndk::ScopedAStatus setHpdSignal(HpdSignal signal) override;
+ ::ndk::ScopedAStatus getHpdSignal(HpdSignal* _aidl_return) override;
void printEventBuf(const char* msg_buf, int len);
@@ -62,6 +67,9 @@
uint16_t mPhysicalAddress = 0xFFFF;
int mTotalPorts = 1;
+ // HPD Signal being used
+ HpdSignal mHpdSignal = HpdSignal::HDMI_HPD_PHYSICAL;
+
// Testing variables
// Input file descriptor
int mInputFile;
diff --git a/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp b/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp
index 78c2590..fd4d94f 100644
--- a/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp
+++ b/tv/hdmi/aidl/vts/functional/VtsHalTvHdmiAidlTargetTest.cpp
@@ -31,6 +31,7 @@
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::HpdSignal;
using ::aidl::android::hardware::tv::hdmi::IHdmi;
using ::aidl::android::hardware::tv::hdmi::IHdmiCallback;
using ::ndk::SpAIBinder;
@@ -101,3 +102,18 @@
ASSERT_TRUE(hdmi->isConnected(ports[i].portId, &connected).isOk());
}
}
+
+TEST_P(HdmiTest, HdpSignal) {
+ HpdSignal originalSignal;
+ HpdSignal signal = HpdSignal::HDMI_HPD_STATUS_BIT;
+ HpdSignal readSignal;
+ ASSERT_TRUE(hdmi->getHpdSignal(&originalSignal).isOk());
+ ASSERT_TRUE(hdmi->setHpdSignal(signal).isOk());
+ ASSERT_TRUE(hdmi->getHpdSignal(&readSignal).isOk());
+ EXPECT_EQ(readSignal, signal);
+ signal = HpdSignal::HDMI_HPD_PHYSICAL;
+ ASSERT_TRUE(hdmi->setHpdSignal(signal).isOk());
+ ASSERT_TRUE(hdmi->getHpdSignal(&readSignal).isOk());
+ EXPECT_EQ(readSignal, signal);
+ ASSERT_TRUE(hdmi->setHpdSignal(originalSignal).isOk());
+}
diff --git a/usb/1.0/default/OWNERS b/usb/1.0/default/OWNERS
deleted file mode 100644
index fefae56..0000000
--- a/usb/1.0/default/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-badhri@google.com
diff --git a/usb/1.0/vts/OWNERS b/usb/1.0/vts/OWNERS
deleted file mode 100644
index 54f268f..0000000
--- a/usb/1.0/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-badhri@google.com
-yim@google.com
-trong@google.com
diff --git a/usb/1.1/vts/OWNERS b/usb/1.1/vts/OWNERS
deleted file mode 100644
index 54f268f..0000000
--- a/usb/1.1/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-badhri@google.com
-yim@google.com
-trong@google.com
diff --git a/usb/1.2/vts/OWNERS b/usb/1.2/vts/OWNERS
deleted file mode 100644
index f60d39a..0000000
--- a/usb/1.2/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-badhri@google.com
-yim@google.com
diff --git a/usb/1.3/vts/OWNERS b/usb/OWNERS
similarity index 62%
rename from usb/1.3/vts/OWNERS
rename to usb/OWNERS
index a6a1e54..2b1d34d 100644
--- a/usb/1.3/vts/OWNERS
+++ b/usb/OWNERS
@@ -1,2 +1,4 @@
+# Bug component: 175220
+
albertccwang@google.com
badhri@google.com
diff --git a/usb/aidl/OWNERS b/usb/aidl/OWNERS
deleted file mode 100644
index fefae56..0000000
--- a/usb/aidl/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-badhri@google.com
diff --git a/vibrator/1.0/vts/OWNERS b/vibrator/1.0/vts/OWNERS
deleted file mode 100644
index 75b9a4b..0000000
--- a/vibrator/1.0/vts/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-# Bug component: 345036
-michaelwr@google.com
-leungv@google.com
diff --git a/vibrator/1.1/vts/OWNERS b/vibrator/1.1/vts/OWNERS
deleted file mode 100644
index 44bfe56..0000000
--- a/vibrator/1.1/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 345036
-include ../../1.0/vts/OWNERS
diff --git a/vibrator/1.2/vts/OWNERS b/vibrator/1.2/vts/OWNERS
deleted file mode 100644
index 44bfe56..0000000
--- a/vibrator/1.2/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 345036
-include ../../1.0/vts/OWNERS
diff --git a/vibrator/1.3/example/OWNERS b/vibrator/1.3/example/OWNERS
deleted file mode 100644
index 4b34968..0000000
--- a/vibrator/1.3/example/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-eliptus@google.com
-michaelwr@google.com
diff --git a/vibrator/1.3/vts/OWNERS b/vibrator/1.3/vts/OWNERS
deleted file mode 100644
index 44bfe56..0000000
--- a/vibrator/1.3/vts/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-# Bug component: 345036
-include ../../1.0/vts/OWNERS
diff --git a/vibrator/aidl/OWNERS b/vibrator/OWNERS
similarity index 68%
rename from vibrator/aidl/OWNERS
rename to vibrator/OWNERS
index 3982c7b..05e2e73 100644
--- a/vibrator/aidl/OWNERS
+++ b/vibrator/OWNERS
@@ -1,4 +1,9 @@
# Bug component: 345036
+
include platform/frameworks/base:/services/core/java/com/android/server/vibrator/OWNERS
+
chasewu@google.com
+chrispaulo@google.com
+michaelwr@google.com
+nathankulczak@google.com
taikuo@google.com