Merge changes I61e086b4,I29fc11a0 into main

* changes:
  Fix invalid memory access in DefaultVehicleHal.
  Implement reg/unregSupportedValueChange.
diff --git a/bluetooth/OWNERS b/bluetooth/OWNERS
index f401b8c..df250c8 100644
--- a/bluetooth/OWNERS
+++ b/bluetooth/OWNERS
@@ -1,5 +1,5 @@
 # Bug component: 27441
 
+asoulier@google.com
 henrichataing@google.com
-mylesgw@google.com
 siyuanh@google.com
diff --git a/boot/aidl/default/Android.bp b/boot/aidl/default/Android.bp
index c1d3c57..2fd2dad 100644
--- a/boot/aidl/default/Android.bp
+++ b/boot/aidl/default/Android.bp
@@ -57,7 +57,7 @@
     name: "android.hardware.boot-service.default_recovery",
     defaults: ["android.hardware.boot-service_common"],
     init_rc: ["android.hardware.boot-service.default_recovery.rc"],
-    vintf_fragments: ["android.hardware.boot-service.default.xml"],
+    vintf_fragment_modules: ["android.hardware.boot-service.default.xml.recovery"],
     recovery: true,
 
     shared_libs: [
@@ -77,11 +77,16 @@
     installable: false,
 }
 
-prebuilt_etc {
+vintf_fragment {
+    name: "android.hardware.boot-service.default.xml.recovery",
+    src: "android.hardware.boot-service.default.xml",
+    recovery: true,
+}
+
+vintf_fragment {
     name: "android.hardware.boot-service.default.xml",
     src: "android.hardware.boot-service.default.xml",
-    sub_dir: "vintf",
-    installable: false,
+    vendor: true,
 }
 
 apex {
@@ -98,6 +103,8 @@
     ],
     prebuilts: [
         "android.hardware.boot-service.default.rc",
+    ],
+    vintf_fragment_modules: [
         "android.hardware.boot-service.default.xml",
     ],
 }
diff --git a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
index aa611ce..1df1a99 100644
--- a/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
+++ b/contexthub/aidl/vts/VtsAidlHalContextHubTargetTest.cpp
@@ -62,6 +62,7 @@
 // 6612b522-b717-41c8-b48d-c0b1cc64e142
 constexpr std::array<uint8_t, 16> kUuid = {0x66, 0x12, 0xb5, 0x22, 0xb7, 0x17, 0x41, 0xc8,
                                            0xb4, 0x8d, 0xc0, 0xb1, 0xcc, 0x64, 0xe1, 0x42};
+
 const String16 kName{"VtsAidlHalContextHubTargetTest"};
 
 const String16 kEchoServiceName{"android.hardware.contexthub.test.EchoService"};
@@ -72,19 +73,29 @@
         contextHub = android::waitForDeclaredService<IContextHub>(
                 String16(std::get<0>(GetParam()).c_str()));
         ASSERT_NE(contextHub, nullptr);
+    }
+
+    uint32_t getHubId() { return std::get<1>(GetParam()); }
+
+    sp<IContextHub> contextHub;
+
+    void testSettingChanged(Setting setting);
+};
+
+class ContextHubAidlWithTestMode : public ContextHubAidl {
+  public:
+    virtual void SetUp() override {
+        ContextHubAidl::SetUp();
 
         // Best effort enable test mode - this may not be supported on older HALS, so we
         // ignore the return value.
         contextHub->setTestMode(/* enable= */ true);
     }
 
-    virtual void TearDown() override { contextHub->setTestMode(/* enable= */ false); }
-
-    uint32_t getHubId() { return std::get<1>(GetParam()); }
-
-    void testSettingChanged(Setting setting);
-
-    sp<IContextHub> contextHub;
+    virtual void TearDown() override {
+        contextHub->setTestMode(/* enable= */ false);
+        ContextHubAidl::TearDown();
+    }
 };
 
 TEST_P(ContextHubAidl, TestGetHubs) {
@@ -546,7 +557,7 @@
     bool mWasOnEndpointSessionOpenCompleteCalled = false;
 };
 
-TEST_P(ContextHubAidl, RegisterEndpoint) {
+TEST_P(ContextHubAidlWithTestMode, RegisterEndpoint) {
     EndpointInfo endpointInfo;
     endpointInfo.id.id = 1;
     endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -563,7 +574,7 @@
     }
 }
 
-TEST_P(ContextHubAidl, RegisterEndpointSameNameFailure) {
+TEST_P(ContextHubAidlWithTestMode, RegisterEndpointSameNameFailure) {
     EndpointInfo endpointInfo;
     endpointInfo.id.id = 2;
     endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -589,7 +600,7 @@
     EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk());
 }
 
-TEST_P(ContextHubAidl, RegisterEndpointSameIdFailure) {
+TEST_P(ContextHubAidlWithTestMode, RegisterEndpointSameIdFailure) {
     EndpointInfo endpointInfo;
     endpointInfo.id.id = 4;
     endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -615,7 +626,7 @@
     EXPECT_FALSE(contextHub->registerEndpoint(endpointInfo2).isOk());
 }
 
-TEST_P(ContextHubAidl, UnregisterEndpoint) {
+TEST_P(ContextHubAidlWithTestMode, UnregisterEndpoint) {
     EndpointInfo endpointInfo;
     endpointInfo.id.id = 6;
     endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -634,7 +645,7 @@
     EXPECT_TRUE(contextHub->unregisterEndpoint(endpointInfo).isOk());
 }
 
-TEST_P(ContextHubAidl, UnregisterEndpointNonexistent) {
+TEST_P(ContextHubAidlWithTestMode, UnregisterEndpointNonexistent) {
     EndpointInfo endpointInfo;
     endpointInfo.id.id = 100;
     endpointInfo.id.hubId = 0xCAFECAFECAFECAFE;
@@ -651,7 +662,7 @@
     }
 }
 
-TEST_P(ContextHubAidl, RegisterCallback) {
+TEST_P(ContextHubAidlWithTestMode, RegisterEndpointCallback) {
     auto cb = sp<TestEndpointCallback>::make();
     Status status = contextHub->registerEndpointCallback(cb);
     if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
@@ -662,7 +673,7 @@
     }
 }
 
-TEST_P(ContextHubAidl, OpenEndpointSessionInvalidRange) {
+TEST_P(ContextHubAidlWithTestMode, OpenEndpointSessionInvalidRange) {
     auto cb = sp<TestEndpointCallback>::make();
     Status status = contextHub->registerEndpointCallback(cb);
     if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
@@ -713,7 +724,7 @@
                          .isOk());
 }
 
-TEST_P(ContextHubAidl, OpenEndpointSessionAndSendMessageEchoesBack) {
+TEST_P(ContextHubAidlWithTestMode, OpenEndpointSessionAndSendMessageEchoesBack) {
     auto cb = sp<TestEndpointCallback>::make();
     Status status = contextHub->registerEndpointCallback(cb);
     if (status.exceptionCode() == Status::EX_UNSUPPORTED_OPERATION ||
@@ -789,13 +800,17 @@
 INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidl, testing::ValuesIn(generateContextHubMapping()),
                          PrintGeneratedTest);
 
+GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubAidlWithTestMode);
+INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubAidlWithTestMode,
+                         testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(ContextHubTransactionTest);
 INSTANTIATE_TEST_SUITE_P(ContextHub, ContextHubTransactionTest,
                          testing::ValuesIn(generateContextHubMapping()), PrintGeneratedTest);
 
 int main(int argc, char** argv) {
     ::testing::InitGoogleTest(&argc, argv);
-    ProcessState::self()->setThreadPoolMaxThreadCount(1);
+    ProcessState::self()->setThreadPoolMaxThreadCount(2);
     ProcessState::self()->startThreadPool();
     return RUN_ALL_TESTS();
 }
diff --git a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
index 2945dab..e6d2fdf 100644
--- a/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/aidl_api/android.hardware.security.keymint/current/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -45,6 +45,9 @@
   void deleteAllKeys();
   void destroyAttestationIds();
   android.hardware.security.keymint.BeginResult begin(in android.hardware.security.keymint.KeyPurpose purpose, in byte[] keyBlob, in android.hardware.security.keymint.KeyParameter[] params, in @nullable android.hardware.security.keymint.HardwareAuthToken authToken);
+  /**
+   * @deprecated Method has never been used due to design limitations
+   */
   void deviceLocked(in boolean passwordOnly, in @nullable android.hardware.security.secureclock.TimeStampToken timestampToken);
   void earlyBootEnded();
   byte[] convertStorageKeyToEphemeral(in byte[] storageKeyBlob);
diff --git a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
index b57dd8a..cafec70 100644
--- a/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
+++ b/security/keymint/aidl/android/hardware/security/keymint/IKeyMintDevice.aidl
@@ -826,6 +826,7 @@
      *
      * @param passwordOnly N/A due to the deprecation
      * @param timestampToken N/A due to the deprecation
+     * @deprecated Method has never been used due to design limitations
      */
     void deviceLocked(in boolean passwordOnly, in @nullable TimeStampToken timestampToken);
 
@@ -964,10 +965,11 @@
      * IKeyMintDevice must ignore KeyParameters with tags not included in the following list:
      *
      * o Tag::MODULE_HASH: holds a hash that must be included in attestations in the moduleHash
-     *   field of the software enforced authorization list. If Tag::MODULE_HASH is included in more
-     *   than one setAdditionalAttestationInfo call, the implementation should compare the initial
-     *   KeyParamValue with the more recent one. If they differ, the implementation should fail with
-     *   ErrorCode::MODULE_HASH_ALREADY_SET. If they are the same, no action needs to be taken.
+     *   field of the software enforced authorization list.
+     *
+     * @return error ErrorCode::MODULE_HASH_ALREADY_SET if this is not the first time
+     *         setAdditionalAttestationInfo is called with Tag::MODULE_HASH, and the associated
+     *         KeyParamValue of the current call doesn't match the KeyParamValue of the first call.
      */
     void setAdditionalAttestationInfo(in KeyParameter[] info);
 }
diff --git a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
index b31a06c..99eb761 100644
--- a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
@@ -64,7 +64,7 @@
     int keySizeBytes;
   }
   union DerivedKeyPolicy {
-    android.hardware.security.see.hwcrypto.IHwCryptoKey.ClearKeyPolicy clearKey;
+    android.hardware.security.see.hwcrypto.IHwCryptoKey.ClearKeyPolicy clearKeyPolicy;
     byte[] opaqueKey;
   }
   parcelable DerivedKeyParameters {
diff --git a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
index 7c87dd3..3adb2f9 100644
--- a/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/hwcrypto/aidl/aidl_api/android.hardware.security.see.hwcrypto/current/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
@@ -34,5 +34,5 @@
 package android.hardware.security.see.hwcrypto;
 @VintfStability
 interface IHwCryptoOperations {
-  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations, out android.hardware.security.see.hwcrypto.CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+  android.hardware.security.see.hwcrypto.CryptoOperationResult[] processCommandList(inout android.hardware.security.see.hwcrypto.CryptoOperationSet[] operations);
 }
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
index 97a4c37..93d6cbc 100644
--- a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoKey.aidl
@@ -107,10 +107,12 @@
          * If used we will derive a clear key and pass it back as an array of bytes on
          * <code>HwCryptoKeyMaterial::explicitKey</code>.
          */
-        ClearKeyPolicy clearKey;
+        ClearKeyPolicy clearKeyPolicy;
 
         /*
          * Policy for the newly derived opaque key. Defines how the key can be used and its type.
+         * Its definition can be found in <code>KeyPolicy.cddl</code>, which is basically a CBOR
+         * serialization of the file <code>KeyPolicy.aidl</code>.
          */
         byte[] opaqueKey;
     }
@@ -154,11 +156,14 @@
      *     Key to be used to derive the new key using HKDF.
      *
      * @return:
-     *     A DiceCurrentBoundKeyResult containint the versioned key tied the current client version
+     *     A DiceCurrentBoundKeyResult containing the versioned key tied the current client version
      *     on success.
      *
      * @throws:
-     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid DeviceKeyId is requested.
+     *          - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
      */
     DiceCurrentBoundKeyResult deriveCurrentDicePolicyBoundKey(
             in DiceBoundDerivationKey derivationKey);
@@ -184,7 +189,11 @@
      *      success.
      *
      * @throws:
-     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid DeviceKeyId is requested or if dicePolicyForKeyVersion
+     *            is not a valid encrypted DICE policy.
+     *          - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
      */
     DiceBoundKeyResult deriveDicePolicyBoundKey(
             in DiceBoundDerivationKey derivationKey, in byte[] dicePolicyForKeyVersion);
@@ -197,10 +206,15 @@
      *      file for more information.
      *
      * @return:
-     *      A HwCryptoKeyMaterial containing the derived key on success.
+     *      A <code>DerivedKey</code> containing the derived key on success.
      *
      * @throws:
-     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid key policy is provided or if the key policy conflicts
+     *            with the requested key.
+     *          - SERIALIZATION_ERROR if the provided key policy is not a valid CBOR key policy.
+     *          - INVALID_KEY if an opaque key is provided that is not suitable for key derivation.
      */
     DerivedKey deriveKey(in DerivedKeyParameters parameters);
 
@@ -233,7 +247,11 @@
      *      IOpaqueKey on success.
      *
      * @throws:
-     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid Key policy is provided or if the key policy conflicts
+     *            with provided key material.
+     *          - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
      */
     IOpaqueKey importClearKey(in ExplicitKeyMaterial keyMaterial, in KeyPolicy newKeyPolicy);
 
@@ -248,7 +266,9 @@
      * passing the receiver DICE policy to insure that only that receiver can import the key.
      *
      * @return:
-     *      byte[] on success, which is the caller encrypted DICE policy.
+     *      byte[] on success, which is the caller encrypted DICE policy. The DICE policy follows
+     *      the structure defined on DicePolicy.cddl, located under
+     *      hardware/interfaces/security/authgraph/aidl/android/hardware/security/authgraph/
      */
     byte[] getCurrentDicePolicy();
 
@@ -266,10 +286,14 @@
      *      DICE policy used to seal the exported key.
      *
      * @return:
-     *      An IOpaqueKey that can be directly be used on the local HWCrypto service on success.
+     *      An IOpaqueKey that can be directly used on the local HWCrypto service on success.
      *
      * @throws:
-     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - BAD_PARAMETER if an invalid encrypted sealing DICE policy is provided.
+     *          - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
+     *          - UNAUTHORIZED if the sealingDicePolicy do not match the caller.
      */
     IOpaqueKey keyTokenImport(in OpaqueKeyToken requestedKey, in byte[] sealingDicePolicy);
 
@@ -287,8 +311,9 @@
      *      An IOpaqueKey corresponding to the requested key slot on success.
      *
      * @throws:
-     *      ServiceSpecificException <code>UNAUTHORIZED</code> if the caller cannot access the
-     *      requested key, another specific error based on <code>HalErrorCode</code> otherwise.
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - UNAUTHORIZED if the caller cannot access the requested key.
      */
     IOpaqueKey getKeyslotData(KeySlot slotId);
 }
diff --git a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
index 9df6d67..dbe4d80 100644
--- a/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
+++ b/security/see/hwcrypto/aidl/android/hardware/security/see/hwcrypto/IHwCryptoOperations.aidl
@@ -31,19 +31,21 @@
      *
      * @param operations:
      *      Parameter containing 1 or more set of commands to execute. Additionally, each set can
-     *      also contain a context on which the commands will be executed.
-     *
-     * @param additionalErrorInfo:
-     *      Structure containing additional info when errors are encountered. Only valid if the
-     *      function failed its execution.
+     *      also contain a context on which the commands will be executed. The parameter has type
+     *      inout because it can contain buffers used to write the output of the operation.
      *
      * @return:
      *      CryptoOperationResult[] on success, which can contain a context to continue executing
      *      each of the provided operations sets.
      *
      * @throws:
-     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs.
+     *      ServiceSpecificException based on <code>HalErrorCode</code> if any error occurs,
+     *      in particular:
+     *          - INVALID_KEY if the provided key is not compatible with the operation requested.
+     *          - BAD_STATE if the provided <code>CryptoOperationSet</code> contains operations that
+     *            cannot be carried out in the current server state.
+     *          - UNSUPPORTED if the requested operation is not supported by the server.
+     *          - ALLOCATION_ERROR if the system runs out of memory while carring out the operation.
      */
-    CryptoOperationResult[] processCommandList(inout CryptoOperationSet[] operations,
-            out CryptoOperationErrorAdditionalInfo additionalErrorInfo);
+    CryptoOperationResult[] processCommandList(inout CryptoOperationSet[] operations);
 }
diff --git a/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp b/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp
index f785cad..a01d4b0 100644
--- a/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp
+++ b/tv/mediaquality/aidl/vts/functional/VtsHalMediaQualityTest.cpp
@@ -35,6 +35,7 @@
 #include <android/binder_manager.h>
 #include <binder/IServiceManager.h>
 #include <binder/ProcessState.h>
+#include <log/log.h>
 #include <future>
 
 using aidl::android::hardware::graphics::common::PixelFormat;
@@ -63,6 +64,407 @@
 #define ASSERT_OK(ret) ASSERT_TRUE(ret.isOk())
 #define EXPECT_OK(ret) EXPECT_TRUE(ret.isOk())
 
+void validateParameterRange0To100(int value) {
+    EXPECT_GE(value, 0);
+    EXPECT_LE(value, 100);
+}
+
+void validateParameterRange0To2047(int value) {
+    EXPECT_GE(value, 0);
+    EXPECT_LE(value, 2047);
+}
+
+void validateColorTemperature(int value) {
+    EXPECT_GE(value, -100);
+    EXPECT_LE(value, 100);
+}
+
+void validatePictureParameter(const PictureParameter& param) {
+    switch (param.getTag()) {
+        case PictureParameter::Tag::brightness: {
+            ALOGD("[validatePictureParameter] validate brightness value");
+            float value = param.get<PictureParameter::Tag::brightness>();
+            EXPECT_TRUE(value >= 0.0f && value <= 1.0f);
+            break;
+        }
+        case PictureParameter::Tag::contrast: {
+            ALOGD("[validatePictureParameter] validate contrast value");
+            int value = param.get<PictureParameter::Tag::contrast>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::sharpness: {
+            ALOGD("[validatePictureParameter] validate sharpness value");
+            int value = param.get<PictureParameter::Tag::sharpness>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::saturation: {
+            ALOGD("[validatePictureParameter] validate saturation value");
+            int value = param.get<PictureParameter::Tag::saturation>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::hue: {
+            ALOGD("[validatePictureParameter] validate hue value");
+            int value = param.get<PictureParameter::Tag::hue>();
+            EXPECT_GE(value, -50);
+            EXPECT_LE(value, 50);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerBrightness: {
+            ALOGD("[validatePictureParameter] validate colorTunerBrightness value");
+            int value = param.get<PictureParameter::Tag::colorTunerBrightness>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerSaturation: {
+            ALOGD("[validatePictureParameter] validate colorTunerSaturation value");
+            int value = param.get<PictureParameter::Tag::colorTunerSaturation>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerHue: {
+            ALOGD("[validatePictureParameter] validate colorTunerHue value");
+            int value = param.get<PictureParameter::Tag::colorTunerHue>();
+            EXPECT_GE(value, -50);
+            EXPECT_LE(value, 50);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerRedOffset: {
+            ALOGD("[validatePictureParameter] validate colorTunerRedOffset value");
+            int value = param.get<PictureParameter::Tag::colorTunerRedOffset>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerGreenOffset: {
+            ALOGD("[validatePictureParameter] validate colorTunerGreenOffset value");
+            int value = param.get<PictureParameter::Tag::colorTunerGreenOffset>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerBlueOffset: {
+            ALOGD("[validatePictureParameter] validate colorTunerBlueOffset value");
+            int value = param.get<PictureParameter::Tag::colorTunerBlueOffset>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerRedGain: {
+            ALOGD("[validatePictureParameter] validate colorTunerRedGain value");
+            int value = param.get<PictureParameter::Tag::colorTunerRedGain>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerGreenGain: {
+            ALOGD("[validatePictureParameter] validate colorTunerGreenGain value");
+            int value = param.get<PictureParameter::Tag::colorTunerGreenGain>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerBlueGain: {
+            ALOGD("[validatePictureParameter] validate colorTunerBlueGain value");
+            int value = param.get<PictureParameter::Tag::colorTunerBlueGain>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::panelInitMaxLuminceNits: {
+            ALOGD("[validatePictureParameter] validate panelInitMaxLuminceNits value");
+            int value = param.get<PictureParameter::Tag::panelInitMaxLuminceNits>();
+            EXPECT_GE(value, 0);
+            EXPECT_LE(value, 10000);
+            break;
+        }
+        case PictureParameter::Tag::colorTemperatureRedGain: {
+            ALOGD("[validatePictureParameter] validate colorTemperatureRedGain value");
+            int value = param.get<PictureParameter::Tag::colorTemperatureRedGain>();
+            validateColorTemperature(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTemperatureGreenGain: {
+            ALOGD("[validatePictureParameter] validate colorTemperatureGreenGain value");
+            int value = param.get<PictureParameter::Tag::colorTemperatureGreenGain>();
+            validateColorTemperature(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTemperatureBlueGain: {
+            ALOGD("[validatePictureParameter] validate colorTemperatureBlueGain value");
+            int value = param.get<PictureParameter::Tag::colorTemperatureBlueGain>();
+            validateColorTemperature(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTemperatureRedOffset: {
+            ALOGD("[validatePictureParameter] validate ccolorTemperatureRedOffset value");
+            int value = param.get<PictureParameter::Tag::colorTemperatureRedOffset>();
+            validateColorTemperature(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTemperatureGreenOffset: {
+            ALOGD("[validatePictureParameter] validate colorTemperatureGreenOffset value");
+            int value = param.get<PictureParameter::Tag::colorTemperatureGreenOffset>();
+            validateColorTemperature(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTemperatureBlueOffset: {
+            ALOGD("[validatePictureParameter] validate colorTemperatureBlueOffset value");
+            int value = param.get<PictureParameter::Tag::colorTemperatureBlueOffset>();
+            validateColorTemperature(value);
+            break;
+        }
+        case PictureParameter::Tag::elevenPointRed: {
+            ALOGD("[validatePictureParameter] validate elevenPointRed value");
+            std::array<int, 11> elevenPointValues =
+                    param.get<PictureParameter::Tag::elevenPointRed>();
+            for (int value : elevenPointValues) {
+                validateParameterRange0To100(value);
+            }
+            break;
+        }
+        case PictureParameter::Tag::elevenPointGreen: {
+            ALOGD("[validatePictureParameter] validate elevenPointGreen value");
+            std::array<int, 11> elevenPointValues =
+                    param.get<PictureParameter::Tag::elevenPointGreen>();
+            for (int value : elevenPointValues) {
+                validateParameterRange0To100(value);
+            }
+            break;
+        }
+        case PictureParameter::Tag::elevenPointBlue: {
+            ALOGD("[validatePictureParameter] validate elevenPointBlue value");
+            std::array<int, 11> elevenPointValues =
+                    param.get<PictureParameter::Tag::elevenPointBlue>();
+            for (int value : elevenPointValues) {
+                validateParameterRange0To100(value);
+            }
+            break;
+        }
+        case PictureParameter::Tag::osdRedGain: {
+            ALOGD("[validatePictureParameter] validate osdRedGain value");
+            int value = param.get<PictureParameter::Tag::osdRedGain>();
+            validateParameterRange0To2047(value);
+            break;
+        }
+        case PictureParameter::Tag::osdGreenGain: {
+            ALOGD("[validatePictureParameter] validate osdGreenGain value");
+            int value = param.get<PictureParameter::Tag::osdGreenGain>();
+            validateParameterRange0To2047(value);
+            break;
+        }
+        case PictureParameter::Tag::osdBlueGain: {
+            ALOGD("[validatePictureParameter] validate osdBlueGain value");
+            int value = param.get<PictureParameter::Tag::osdBlueGain>();
+            validateParameterRange0To2047(value);
+            break;
+        }
+        case PictureParameter::Tag::osdRedOffset: {
+            ALOGD("[validatePictureParameter] validate osdRedOffset value");
+            int value = param.get<PictureParameter::Tag::osdRedOffset>();
+            validateParameterRange0To2047(value);
+            break;
+        }
+        case PictureParameter::Tag::osdGreenOffset: {
+            ALOGD("[validatePictureParameter] validate osdGreenOffset value");
+            int value = param.get<PictureParameter::Tag::osdGreenOffset>();
+            validateParameterRange0To2047(value);
+            break;
+        }
+        case PictureParameter::Tag::osdBlueOffset: {
+            ALOGD("[validatePictureParameter] validate osdBlueOffset value");
+            int value = param.get<PictureParameter::Tag::osdBlueOffset>();
+            validateParameterRange0To2047(value);
+            break;
+        }
+        case PictureParameter::Tag::osdHue: {
+            ALOGD("[validatePictureParameter] validate osdHue value");
+            int value = param.get<PictureParameter::Tag::osdHue>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::osdSaturation: {
+            ALOGD("[validatePictureParameter] validate osdSaturation value");
+            int value = param.get<PictureParameter::Tag::osdSaturation>();
+            EXPECT_GE(value, 0);
+            EXPECT_LE(value, 255);
+            break;
+        }
+        case PictureParameter::Tag::osdContrast: {
+            ALOGD("[validatePictureParameter] validate osdContrast value");
+            int value = param.get<PictureParameter::Tag::osdContrast>();
+            validateParameterRange0To2047(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerHueRed: {
+            ALOGD("[validatePictureParameter] validate colorTunerHueRed value");
+            int value = param.get<PictureParameter::Tag::colorTunerHueRed>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerHueGreen: {
+            ALOGD("[validatePictureParameter] validate colorTunerHueGreen value");
+            int value = param.get<PictureParameter::Tag::colorTunerHueGreen>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerHueBlue: {
+            ALOGD("[validatePictureParameter] validate colorTunerHueBlue value");
+            int value = param.get<PictureParameter::Tag::colorTunerHueBlue>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerHueCyan: {
+            ALOGD("[validatePictureParameter] validate colorTunerHueCyan value");
+            int value = param.get<PictureParameter::Tag::colorTunerHueCyan>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerHueMagenta: {
+            ALOGD("[validatePictureParameter] validate colorTunerHueMagenta value");
+            int value = param.get<PictureParameter::Tag::colorTunerHueMagenta>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerHueYellow: {
+            ALOGD("[validatePictureParameter] validate colorTunerHueYellow value");
+            int value = param.get<PictureParameter::Tag::colorTunerHueYellow>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerHueFlesh: {
+            ALOGD("[validatePictureParameter] validate colorTunerHueFlesh value");
+            int value = param.get<PictureParameter::Tag::colorTunerHueFlesh>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerSaturationRed: {
+            ALOGD("[validatePictureParameter] validate colorTunerSaturationRed value");
+            int value = param.get<PictureParameter::Tag::colorTunerSaturationRed>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerSaturationGreen: {
+            ALOGD("[validatePictureParameter] validate colorTunerSaturationGreen value");
+            int value = param.get<PictureParameter::Tag::colorTunerSaturationGreen>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerSaturationBlue: {
+            ALOGD("[validatePictureParameter] validate colorTunerSaturationBlue value");
+            int value = param.get<PictureParameter::Tag::colorTunerSaturationBlue>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerSaturationCyan: {
+            ALOGD("[validatePictureParameter] validate colorTunerSaturationCyan value");
+            int value = param.get<PictureParameter::Tag::colorTunerSaturationCyan>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerSaturationMagenta: {
+            ALOGD("[validatePictureParameter] validate colorTunerSaturationMagenta value");
+            int value = param.get<PictureParameter::Tag::colorTunerSaturationMagenta>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerSaturationYellow: {
+            ALOGD("[validatePictureParameter] validate colorTunerSaturationYellow value");
+            int value = param.get<PictureParameter::Tag::colorTunerSaturationYellow>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerSaturationFlesh: {
+            ALOGD("[validatePictureParameter] validate colorTunerSaturationFlesh value");
+            int value = param.get<PictureParameter::Tag::colorTunerSaturationFlesh>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerLuminanceRed: {
+            ALOGD("[validatePictureParameter] validate colorTunerLuminanceRed value");
+            int value = param.get<PictureParameter::Tag::colorTunerLuminanceRed>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerLuminanceGreen: {
+            ALOGD("[validatePictureParameter] validate colorTunerLuminanceGreen value");
+            int value = param.get<PictureParameter::Tag::colorTunerLuminanceGreen>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerLuminanceBlue: {
+            ALOGD("[validatePictureParameter] validate colorTunerLuminanceBlue value");
+            int value = param.get<PictureParameter::Tag::colorTunerLuminanceBlue>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerLuminanceCyan: {
+            ALOGD("[validatePictureParameter] validate colorTunerLuminanceCyan value");
+            int value = param.get<PictureParameter::Tag::colorTunerLuminanceCyan>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerLuminanceMagenta: {
+            ALOGD("[validatePictureParameter] validate colorTunerLuminanceMagenta value");
+            int value = param.get<PictureParameter::Tag::colorTunerLuminanceMagenta>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerLuminanceYellow: {
+            ALOGD("[validatePictureParameter] validate colorTunerLuminanceYellow value");
+            int value = param.get<PictureParameter::Tag::colorTunerLuminanceYellow>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case PictureParameter::Tag::colorTunerLuminanceFlesh: {
+            ALOGD("[validatePictureParameter] validate colorTunerLuminanceFlesh value");
+            int value = param.get<PictureParameter::Tag::colorTunerLuminanceFlesh>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        default:
+            ALOGD("Those parameters don't need to check.");
+            break;
+    }
+}
+
+void validateSoundParameter(const SoundParameter& param) {
+    switch (param.getTag()) {
+        case SoundParameter::Tag::balance: {
+            ALOGD("[validateSoundParameter] validate balance value");
+            int value = param.get<SoundParameter::Tag::balance>();
+            EXPECT_GE(value, -50);
+            EXPECT_LE(value, 50);
+            break;
+        }
+        case SoundParameter::Tag::bass: {
+            ALOGD("[validateSoundParameter] validate bass value");
+            int value = param.get<SoundParameter::Tag::bass>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case SoundParameter::Tag::treble: {
+            ALOGD("[validateSoundParameter] validate treble value");
+            int value = param.get<SoundParameter::Tag::treble>();
+            validateParameterRange0To100(value);
+            break;
+        }
+        case SoundParameter::Tag::speakersDelayMs: {
+            ALOGD("[validateSoundParameter] validate speakersDelayMs value");
+            int value = param.get<SoundParameter::Tag::speakersDelayMs>();
+            EXPECT_GE(value, 0);
+            EXPECT_LE(value, 250);
+            break;
+        }
+        case SoundParameter::Tag::digitalOutputDelayMs: {
+            ALOGD("[validateSoundParameter] validate digitalOutputDelayMs value");
+            int value = param.get<SoundParameter::Tag::digitalOutputDelayMs>();
+            EXPECT_GE(value, 0);
+            EXPECT_LE(value, 250);
+            break;
+        }
+        default:
+            ALOGD("Those parameters don't need to check.");
+            break;
+    }
+}
+
 class MediaQualityCallback : public BnMediaQualityCallback {
   public:
     explicit MediaQualityCallback(
@@ -83,7 +485,11 @@
             const std::function<void(const PictureProfile& pictureProfile)>&
                     on_hal_picture_profile_adjust)
         : on_hal_picture_profile_adjust_(on_hal_picture_profile_adjust) {}
+
     ScopedAStatus onPictureProfileAdjusted(const PictureProfile& pictureProfile) override {
+        for (const auto& param : pictureProfile.parameters.pictureParameters) {
+            validatePictureParameter(param);
+        }
         on_hal_picture_profile_adjust_(pictureProfile);
         return ScopedAStatus::ok();
     }
@@ -111,7 +517,11 @@
             const std::function<void(const SoundProfile& soundProfile)>&
                     on_hal_sound_profile_adjust)
         : on_hal_sound_profile_adjust_(on_hal_sound_profile_adjust) {}
+
     ScopedAStatus onSoundProfileAdjusted(const SoundProfile& soundProfile) override {
+        for (const auto& param : soundProfile.parameters.soundParameters) {
+            validateSoundParameter(param);
+        }
         on_hal_sound_profile_adjust_(soundProfile);
         return ScopedAStatus::ok();
     }
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
index c68d8fd..202082e 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.cpp
@@ -276,3 +276,28 @@
     }
     return std::optional<std::vector<std::optional<OuiKeyedData>>>{dataList};
 }
+
+IWifiChip::ApIfaceParams generateApIfaceParams(IfaceConcurrencyType type, bool uses_mlo,
+                                               int oui_size) {
+    IWifiChip::ApIfaceParams params;
+    params.ifaceType = type;
+    params.usesMlo = uses_mlo;
+    params.vendorData = generateOuiKeyedDataListOptional(oui_size);
+    return params;
+}
+
+std::shared_ptr<IWifiApIface> getWifiApOrBridgedApIface(std::shared_ptr<IWifiChip> wifi_chip,
+                                                        IWifiChip::ApIfaceParams params) {
+    if (!wifi_chip.get()) {
+        return nullptr;
+    }
+    std::shared_ptr<IWifiApIface> iface;
+    if (!configureChipToSupportConcurrencyTypeInternal(wifi_chip, IfaceConcurrencyType::AP)) {
+        return nullptr;
+    }
+    auto status = wifi_chip->createApOrBridgedApIfaceWithParams(params, &iface);
+    if (!status.isOk()) {
+        return nullptr;
+    }
+    return iface;
+}
diff --git a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
index 9b47a9f..6d98bf0 100644
--- a/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
+++ b/wifi/aidl/vts/functional/wifi_aidl_test_utils.h
@@ -43,6 +43,8 @@
 std::shared_ptr<IWifiApIface> getWifiApIface(std::shared_ptr<IWifiChip> wifi_chip);
 std::shared_ptr<IWifiApIface> getBridgedWifiApIface(const char* instance_name);
 std::shared_ptr<IWifiApIface> getBridgedWifiApIface(std::shared_ptr<IWifiChip> wifi_chip);
+std::shared_ptr<IWifiApIface> getWifiApOrBridgedApIface(std::shared_ptr<IWifiChip> wifi_chip,
+                                                        IWifiChip::ApIfaceParams params);
 // Configure the chip in a mode to support the creation of the provided iface type.
 bool configureChipToSupportConcurrencyType(const std::shared_ptr<IWifiChip>& wifi_chip,
                                            IfaceConcurrencyType type, int* configured_mode_id);
@@ -57,3 +59,7 @@
 // Generate test vendor data.
 std::vector<OuiKeyedData> generateOuiKeyedDataList(int size);
 std::optional<std::vector<std::optional<OuiKeyedData>>> generateOuiKeyedDataListOptional(int size);
+
+// Generate test ApIfaceParams
+IWifiChip::ApIfaceParams generateApIfaceParams(IfaceConcurrencyType type, bool uses_mlo,
+                                               int oui_size);
diff --git a/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
index a1b9ce1..b4cb030 100644
--- a/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
+++ b/wifi/aidl/vts/functional/wifi_chip_aidl_test.cpp
@@ -52,6 +52,7 @@
         stopWifiService(getInstanceName());
         wifi_chip_ = getWifiChip(getInstanceName());
         ASSERT_NE(nullptr, wifi_chip_.get());
+        ASSERT_TRUE(wifi_chip_->getInterfaceVersion(&interface_version_).isOk());
     }
 
     void TearDown() override { stopWifiService(getInstanceName()); }
@@ -139,6 +140,7 @@
     const char* getInstanceName() { return GetParam().c_str(); }
 
     std::shared_ptr<IWifiChip> wifi_chip_;
+    int interface_version_;
 };
 
 class WifiChipEventCallback : public BnWifiChipEventCallback {
@@ -902,6 +904,89 @@
     }
 }
 
+/**
+ * CreateApOrBridgedApIfaceWithParams for signal ap.
+ */
+TEST_P(WifiChipAidlTest, CreateApOrBridgedApIfaceWithParams_signal_ap) {
+    if (interface_version_ < 3) {
+        GTEST_SKIP() << "CreateApOrBridgedApIfaceWithParams is available as of WifiChip V3";
+    }
+    if (!isConcurrencyTypeSupported(IfaceConcurrencyType::AP)) {
+        GTEST_SKIP() << "AP is not supported";
+    }
+
+    std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
+    ASSERT_NE(nullptr, wifi_chip.get());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApOrBridgedApIface(
+            wifi_chip, generateApIfaceParams(IfaceConcurrencyType::AP, false, 0));
+    ASSERT_NE(nullptr, wifi_ap_iface.get());
+}
+
+/**
+ * CreateApOrBridgedApIfaceWithParams for non mlo bridged ap.
+ */
+TEST_P(WifiChipAidlTest, CreateApOrBridgedApIfaceWithParams_non_mlo_bridged_ap) {
+    if (interface_version_ < 3) {
+        GTEST_SKIP() << "CreateApOrBridgedApIfaceWithParams is available as of WifiChip V3";
+    }
+    bool isBridgedSupport = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_bridged_ap_supported");
+    if (!isBridgedSupport) {
+        GTEST_SKIP() << "Missing Bridged AP support";
+    }
+
+    std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
+    ASSERT_NE(nullptr, wifi_chip.get());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApOrBridgedApIface(
+            wifi_chip, generateApIfaceParams(IfaceConcurrencyType::AP_BRIDGED, false, 0));
+    ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+    std::string br_name;
+    std::vector<std::string> instances;
+    bool uses_mlo;
+    EXPECT_TRUE(wifi_ap_iface->getName(&br_name).isOk());
+    EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances).isOk());
+    EXPECT_TRUE(wifi_ap_iface->usesMlo(&uses_mlo).isOk());
+    EXPECT_FALSE(uses_mlo);
+    EXPECT_EQ(instances.size(), 2);
+}
+
+/**
+ * CreateApOrBridgedApIfaceWithParams for mlo bridged ap.
+ */
+TEST_P(WifiChipAidlTest, CreateApOrBridgedApIfaceWithParams_mlo_bridged_ap) {
+    if (interface_version_ < 3) {
+        GTEST_SKIP() << "CreateApOrBridgedApIfaceWithParams is available as of WifiChip V3";
+    }
+    bool isBridgedSupport = testing::checkSubstringInCommandOutput(
+            "/system/bin/cmd wifi get-softap-supported-features",
+            "wifi_softap_bridged_ap_supported");
+    if (!isBridgedSupport) {
+        GTEST_SKIP() << "Missing Bridged AP support";
+    }
+
+    configureChipForConcurrencyType(IfaceConcurrencyType::STA);
+    int32_t features = getChipFeatureSet(wifi_chip_);
+    if (!(features & static_cast<int32_t>(IWifiChip::FeatureSetMask::MLO_SAP))) {
+        GTEST_SKIP() << "MLO_SAP is not supported by vendor.";
+    }
+    std::shared_ptr<IWifiChip> wifi_chip = getWifiChip(getInstanceName());
+    ASSERT_NE(nullptr, wifi_chip.get());
+    std::shared_ptr<IWifiApIface> wifi_ap_iface = getWifiApOrBridgedApIface(
+            wifi_chip, generateApIfaceParams(IfaceConcurrencyType::AP_BRIDGED, true, 0));
+    ASSERT_NE(nullptr, wifi_ap_iface.get());
+
+    std::string br_name;
+    std::vector<std::string> instances;
+    bool uses_mlo;
+    EXPECT_TRUE(wifi_ap_iface->getName(&br_name).isOk());
+    EXPECT_TRUE(wifi_ap_iface->getBridgedInstances(&instances).isOk());
+    EXPECT_TRUE(wifi_ap_iface->usesMlo(&uses_mlo).isOk());
+    EXPECT_TRUE(uses_mlo);
+    EXPECT_EQ(instances.size(), 2);
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(WifiChipAidlTest);
 INSTANTIATE_TEST_SUITE_P(WifiTest, WifiChipAidlTest,
                          testing::ValuesIn(android::getAidlHalInstanceNames(IWifi::descriptor)),
diff --git a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 384ac9a..b0141df 100644
--- a/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/aidl_api/android.hardware.wifi.supplicant/current/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -84,8 +84,8 @@
   oneway void onPmkSaCacheAdded(in android.hardware.wifi.supplicant.PmkSaCacheData pmkSaData);
   oneway void onUsdPublishStarted(in int cmdId, in int publishId);
   oneway void onUsdSubscribeStarted(in int cmdId, in int subscribeId);
-  oneway void onUsdPublishConfigFailed(in int cmdId);
-  oneway void onUsdSubscribeConfigFailed(in int cmdId);
+  oneway void onUsdPublishConfigFailed(in int cmdId, in android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback.UsdConfigErrorCode errorCode);
+  oneway void onUsdSubscribeConfigFailed(in int cmdId, in android.hardware.wifi.supplicant.ISupplicantStaIfaceCallback.UsdConfigErrorCode errorCode);
   oneway void onUsdPublishTerminated(in int publishId, in android.hardware.wifi.supplicant.UsdTerminateReasonCode reasonCode);
   oneway void onUsdSubscribeTerminated(in int subscribeId, in android.hardware.wifi.supplicant.UsdTerminateReasonCode reasonCode);
   oneway void onUsdPublishReplied(in android.hardware.wifi.supplicant.UsdServiceDiscoveryInfo info);
@@ -97,4 +97,10 @@
     MULTI_LINK_RECONFIG_AP_REMOVAL = 1,
     MULTI_LINK_DYNAMIC_RECONFIG = 2,
   }
+  @Backing(type="int") @VintfStability
+  enum UsdConfigErrorCode {
+    FAILURE_UNKNOWN = 0,
+    FAILURE_TIMEOUT = 1,
+    FAILURE_NOT_AVAILABLE = 2,
+  }
 }
diff --git a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
index 1ee873a..efbd066 100644
--- a/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
+++ b/wifi/supplicant/aidl/android/hardware/wifi/supplicant/ISupplicantStaIfaceCallback.aidl
@@ -439,12 +439,32 @@
     void onUsdSubscribeStarted(in int cmdId, in int subscribeId);
 
     /**
+     * Error codes returned by |onUsdPublishConfigFailed| and |onUsdSubscribeConfigFailed|.
+     */
+    @VintfStability
+    @Backing(type="int")
+    enum UsdConfigErrorCode {
+        /**
+         * Unknown failure.
+         */
+        FAILURE_UNKNOWN = 0,
+        /**
+         * The requested operation timed out.
+         */
+        FAILURE_TIMEOUT = 1,
+        /**
+         * The requested operation is currently not available.
+         */
+        FAILURE_NOT_AVAILABLE = 2,
+    }
+
+    /**
      * Called in response to |ISupplicantStaIface.startUsdPublish| to indicate that the
      * publish session could not be configured.
      *
      * @param cmdId Identifier for the original request.
      */
-    void onUsdPublishConfigFailed(in int cmdId);
+    void onUsdPublishConfigFailed(in int cmdId, in UsdConfigErrorCode errorCode);
 
     /**
      * Called in response to |ISupplicantStaIface.startUsdSubscribe| to indicate that the
@@ -452,7 +472,7 @@
      *
      * @param cmdId Identifier for the original request.
      */
-    void onUsdSubscribeConfigFailed(in int cmdId);
+    void onUsdSubscribeConfigFailed(in int cmdId, in UsdConfigErrorCode errorCode);
 
     /**
      * Called in response to |ISupplicantStaIface.cancelUsdPublish| to indicate that the session
diff --git a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
index da12a82..18b8ccb 100644
--- a/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
+++ b/wifi/supplicant/aidl/vts/functional/supplicant_sta_iface_aidl_test.cpp
@@ -254,10 +254,12 @@
                                                int32_t /* subscribeId */) override {
         return ndk::ScopedAStatus::ok();
     }
-    ::ndk::ScopedAStatus onUsdPublishConfigFailed(int32_t /* cmdId */) override {
+    ::ndk::ScopedAStatus onUsdPublishConfigFailed(int32_t /* cmdId */,
+                                                  UsdConfigErrorCode /* errorCode */) override {
         return ndk::ScopedAStatus::ok();
     }
-    ::ndk::ScopedAStatus onUsdSubscribeConfigFailed(int32_t /* cmdId */) override {
+    ::ndk::ScopedAStatus onUsdSubscribeConfigFailed(int32_t /* cmdId */,
+                                                    UsdConfigErrorCode /* errorCode */) override {
         return ndk::ScopedAStatus::ok();
     }
     ::ndk::ScopedAStatus onUsdPublishTerminated(int32_t /* publishId */,