Merge "wifi: ignore SIGPIPE when dumping stats to dumpstate"
diff --git a/audio/core/all-versions/vts/functional/Android.bp b/audio/core/all-versions/vts/functional/Android.bp
index c7bfe08..a809a92 100644
--- a/audio/core/all-versions/vts/functional/Android.bp
+++ b/audio/core/all-versions/vts/functional/Android.bp
@@ -22,6 +22,8 @@
         "libxml2",
     ],
     shared_libs: [
+        "audioclient-types-aidl-unstable-cpp",
+        "libaudioclient_aidl_conversion",
         "libbinder",
         "libfmq",
     ],
diff --git a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
index 88c066c..a05fad9 100644
--- a/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
+++ b/biometrics/face/aidl/aidl_api/android.hardware.biometrics.face/current/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -42,4 +42,8 @@
   SENSOR_DIRTY = 21,
   VENDOR = 22,
   FIRST_FRAME_RECEIVED = 23,
+  DARK_GLASSES_DETECTED = 24,
+  FACE_COVERING_DETECTED = 25,
+  EYES_NOT_VISIBLE = 26,
+  MOUTH_NOT_VISIBLE = 27,
 }
diff --git a/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
index 5897cdc..56a600f 100644
--- a/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
+++ b/biometrics/face/aidl/android/hardware/biometrics/face/AcquiredInfo.aidl
@@ -218,6 +218,30 @@
     /**
      * The first frame from the camera has been received.
      */
-    FIRST_FRAME_RECEIVED = 23
+    FIRST_FRAME_RECEIVED = 23,
+
+    /**
+     * Dark glasses detected. This can be useful for providing relevant feedback to the user and
+     * enabling an alternative authentication logic if the implementation supports it.
+     */
+    DARK_GLASSES_DETECTED = 24,
+
+    /**
+     * A face mask or face covering detected. This can be useful for providing relevant feedback to
+     * the user and enabling an alternative authentication logic if the implementation supports it.
+     */
+    FACE_COVERING_DETECTED = 25,
+
+    /**
+     * Either one or both eyes are not visible in the frame. Prefer to use DARK_GLASSES_DETECTED if
+     * the eyes are not visible due to dark glasses.
+     */
+    EYES_NOT_VISIBLE = 26,
+
+    /**
+     * The mouth is not visible in the frame. Prefer to use MASK_DETECTED if the mouth is not
+     * visible due to a mask.
+     */
+    MOUTH_NOT_VISIBLE = 27,
 }
 
diff --git a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl
index fba58af..33a95fe 100644
--- a/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl
+++ b/keymint/aidl/aidl_api/android.hardware.keymint/current/android/hardware/keymint/Tag.aidl
@@ -41,7 +41,7 @@
   MIN_SECONDS_BETWEEN_OPS = 805306771,
   MAX_USES_PER_BOOT = 805306772,
   USER_ID = 805306869,
-  USER_SECURE_ID = 1073742326,
+  USER_SECURE_ID = -1610612234,
   NO_AUTH_REQUIRED = 1879048695,
   USER_AUTH_TYPE = 268435960,
   AUTH_TIMEOUT = 805306873,
diff --git a/keymint/aidl/android/hardware/keymint/Tag.aidl b/keymint/aidl/android/hardware/keymint/Tag.aidl
index e85a8f5..46da096 100644
--- a/keymint/aidl/android/hardware/keymint/Tag.aidl
+++ b/keymint/aidl/android/hardware/keymint/Tag.aidl
@@ -355,7 +355,7 @@
      *
      * Must be hardware-enforced.
      */
-    USER_SECURE_ID = (4 << 28) | 502, /* TagType:UINT_REP */
+    USER_SECURE_ID = (10 << 28) | 502, /* TagType:ULONG_REP */
 
     /**
      * Tag::NO_AUTH_REQUIRED specifies that no authentication is required to use this key.  This tag
diff --git a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
index bbd5343..a68830d 100644
--- a/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
+++ b/neuralnetworks/1.2/utils/include/nnapi/hal/1.2/Device.h
@@ -37,7 +37,6 @@
 nn::GeneralResult<std::string> initVersionString(V1_2::IDevice* device);
 nn::GeneralResult<nn::DeviceType> initDeviceType(V1_2::IDevice* device);
 nn::GeneralResult<std::vector<nn::Extension>> initExtensions(V1_2::IDevice* device);
-nn::GeneralResult<nn::Capabilities> initCapabilities(V1_2::IDevice* device);
 nn::GeneralResult<std::pair<uint32_t, uint32_t>> initNumberOfCacheFilesNeeded(
         V1_2::IDevice* device);
 
diff --git a/neuralnetworks/1.2/utils/src/Device.cpp b/neuralnetworks/1.2/utils/src/Device.cpp
index 517d61f..a9e5377 100644
--- a/neuralnetworks/1.2/utils/src/Device.cpp
+++ b/neuralnetworks/1.2/utils/src/Device.cpp
@@ -42,6 +42,30 @@
 #include <vector>
 
 namespace android::hardware::neuralnetworks::V1_2::utils {
+namespace {
+
+nn::GeneralResult<nn::Capabilities> initCapabilities(V1_2::IDevice* device) {
+    CHECK(device != nullptr);
+
+    nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+                                                 << "uninitialized";
+    const auto cb = [&result](V1_0::ErrorStatus status, const Capabilities& capabilities) {
+        if (status != V1_0::ErrorStatus::NONE) {
+            const auto canonical =
+                    validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+            result = NN_ERROR(canonical) << "getCapabilities_1_2 failed with " << toString(status);
+        } else {
+            result = validatedConvertToCanonical(capabilities);
+        }
+    };
+
+    const auto ret = device->getCapabilities_1_2(cb);
+    NN_TRY(hal::utils::handleTransportError(ret));
+
+    return result;
+}
+
+}  // namespace
 
 nn::GeneralResult<std::string> initVersionString(V1_2::IDevice* device) {
     CHECK(device != nullptr);
@@ -106,27 +130,6 @@
     return result;
 }
 
-nn::GeneralResult<nn::Capabilities> initCapabilities(V1_2::IDevice* device) {
-    CHECK(device != nullptr);
-
-    nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
-                                                 << "uninitialized";
-    const auto cb = [&result](V1_0::ErrorStatus status, const Capabilities& capabilities) {
-        if (status != V1_0::ErrorStatus::NONE) {
-            const auto canonical =
-                    validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
-            result = NN_ERROR(canonical) << "getCapabilities_1_2 failed with " << toString(status);
-        } else {
-            result = validatedConvertToCanonical(capabilities);
-        }
-    };
-
-    const auto ret = device->getCapabilities_1_2(cb);
-    NN_TRY(hal::utils::handleTransportError(ret));
-
-    return result;
-}
-
 nn::GeneralResult<std::pair<uint32_t, uint32_t>> initNumberOfCacheFilesNeeded(
         V1_2::IDevice* device) {
     CHECK(device != nullptr);
diff --git a/neuralnetworks/1.3/utils/src/Device.cpp b/neuralnetworks/1.3/utils/src/Device.cpp
index 5e3d5c2..0fa244d 100644
--- a/neuralnetworks/1.3/utils/src/Device.cpp
+++ b/neuralnetworks/1.3/utils/src/Device.cpp
@@ -71,6 +71,27 @@
     return NN_TRY(std::move(result));
 }
 
+nn::GeneralResult<nn::Capabilities> initCapabilities(V1_3::IDevice* device) {
+    CHECK(device != nullptr);
+
+    nn::GeneralResult<nn::Capabilities> result = NN_ERROR(nn::ErrorStatus::GENERAL_FAILURE)
+                                                 << "uninitialized";
+    const auto cb = [&result](ErrorStatus status, const Capabilities& capabilities) {
+        if (status != ErrorStatus::NONE) {
+            const auto canonical =
+                    validatedConvertToCanonical(status).value_or(nn::ErrorStatus::GENERAL_FAILURE);
+            result = NN_ERROR(canonical) << "getCapabilities_1_3 failed with " << toString(status);
+        } else {
+            result = validatedConvertToCanonical(capabilities);
+        }
+    };
+
+    const auto ret = device->getCapabilities_1_3(cb);
+    NN_TRY(hal::utils::handleTransportError(ret));
+
+    return result;
+}
+
 }  // namespace
 
 nn::GeneralResult<std::shared_ptr<const Device>> Device::create(std::string name,
@@ -87,7 +108,7 @@
     auto versionString = NN_TRY(V1_2::utils::initVersionString(device.get()));
     const auto deviceType = NN_TRY(V1_2::utils::initDeviceType(device.get()));
     auto extensions = NN_TRY(V1_2::utils::initExtensions(device.get()));
-    auto capabilities = NN_TRY(V1_2::utils::initCapabilities(device.get()));
+    auto capabilities = NN_TRY(initCapabilities(device.get()));
     const auto numberOfCacheFilesNeeded =
             NN_TRY(V1_2::utils::initNumberOfCacheFilesNeeded(device.get()));
 
diff --git a/radio/1.6/IRadio.hal b/radio/1.6/IRadio.hal
index c73745a..dec247e 100644
--- a/radio/1.6/IRadio.hal
+++ b/radio/1.6/IRadio.hal
@@ -217,6 +217,13 @@
      * Each subsequent request to this method is processed only after the
      * completion of the previous one.
      *
+     * When the SIM is in POWER_DOWN, the modem should send an empty vector of
+     * AppStatus in CardStatus.applications. If a SIM in the POWER_DOWN state
+     * is removed and a new SIM is inserted, the new SIM should be in POWER_UP
+     * mode by default. If the device is turned off or restarted while the SIM
+     * is in POWER_DOWN, then the SIM should turn on normally in POWER_UP mode
+     * when the device turns back on.
+     *
      * Response callback is IRadioResponse.setSimCardPowerResponse_1_6().
      * Note that this differs from setSimCardPower_1_1 in that the response
      * callback should only be sent once the device has finished executing
diff --git a/radio/1.6/IRadioResponse.hal b/radio/1.6/IRadioResponse.hal
index c545db0..36e3ee4 100644
--- a/radio/1.6/IRadioResponse.hal
+++ b/radio/1.6/IRadioResponse.hal
@@ -207,7 +207,6 @@
      * Valid errors returned:
      *   RadioError:NONE
      *   RadioError:RADIO_NOT_AVAILABLE
-     *   RadioError:REQUEST_NOT_SUPPORTED
      *   RadioError:INVALID_ARGUMENTS
      *   RadioError:SIM_ERR (indicates a timeout or other issue making the SIM unresponsive)
      *
diff --git a/radio/1.6/types.hal b/radio/1.6/types.hal
index 2cba915..556d8a3 100644
--- a/radio/1.6/types.hal
+++ b/radio/1.6/types.hal
@@ -22,6 +22,7 @@
 import @1.4::DataConnActiveStatus;
 import @1.4::PdpProtocolType;
 import @1.5::LinkAddress;
+
 import android.hidl.safe_union@1.0::Monostate;
 
 struct QosBandwidth {
diff --git a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
index 6b1ff27..75772cd 100644
--- a/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
+++ b/radio/1.6/vts/functional/radio_hidl_hal_api.cpp
@@ -321,7 +321,6 @@
     res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::THROTTLE_ANCHOR_CARRIER,
                                         60000);
     ASSERT_OK(res);
-
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
@@ -351,7 +350,6 @@
 
     res = radio_v1_6->setDataThrottling(serial, DataThrottlingAction::NO_DATA_THROTTLING, 60000);
     ASSERT_OK(res);
-
     EXPECT_EQ(std::cv_status::no_timeout, wait());
     EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
     EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
@@ -361,4 +359,50 @@
                               ::android::hardware::radio::V1_6::RadioError::MODEM_ERR,
                               ::android::hardware::radio::V1_6::RadioError::NONE,
                               ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS}));
-}
\ No newline at end of file
+}
+
+/*
+ * Test IRadio.setSimCardPower_1_6() for the response returned.
+ */
+TEST_P(RadioHidlTest_v1_6, setSimCardPower_1_6) {
+    /* Test setSimCardPower power down */
+    serial = GetRandomSerialNumber();
+    radio_v1_6->setSimCardPower_1_6(serial, CardPowerState::POWER_DOWN);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+                             {::android::hardware::radio::V1_6::RadioError::NONE,
+                              ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+                              ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
+
+    // setSimCardPower_1_6 does not return  until the request is handled, and should not trigger
+    // CardState::ABSENT when turning off power
+    if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
+        /* Wait some time for setting sim power down and then verify it */
+        updateSimCardStatus();
+        EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
+        // applications should be an empty vector of AppStatus
+        EXPECT_EQ(0, cardStatus.applications.size());
+    }
+
+    /* Test setSimCardPower power up */
+    serial = GetRandomSerialNumber();
+    radio_v1_6->setSimCardPower_1_6(serial, CardPowerState::POWER_UP);
+    EXPECT_EQ(std::cv_status::no_timeout, wait());
+    EXPECT_EQ(RadioResponseType::SOLICITED, radioRsp_v1_6->rspInfo.type);
+    EXPECT_EQ(serial, radioRsp_v1_6->rspInfo.serial);
+    ASSERT_TRUE(
+            CheckAnyOfErrors(radioRsp_v1_6->rspInfo.error,
+                             {::android::hardware::radio::V1_6::RadioError::NONE,
+                              ::android::hardware::radio::V1_6::RadioError::INVALID_ARGUMENTS,
+                              ::android::hardware::radio::V1_6::RadioError::RADIO_NOT_AVAILABLE}));
+
+    // setSimCardPower_1_6 does not return  until the request is handled. Just verify that we still
+    // have CardState::PRESENT after turning the power back on
+    if (radioRsp_v1_6->rspInfo.error == ::android::hardware::radio::V1_6::RadioError::NONE) {
+        updateSimCardStatus();
+        EXPECT_EQ(CardState::PRESENT, cardStatus.base.base.base.cardState);
+    }
+}
diff --git a/wifi/1.5/IWifiChip.hal b/wifi/1.5/IWifiChip.hal
index dcc9279..7cf81b5 100644
--- a/wifi/1.5/IWifiChip.hal
+++ b/wifi/1.5/IWifiChip.hal
@@ -17,6 +17,7 @@
 package android.hardware.wifi@1.5;
 
 import @1.0::WifiStatus;
+import @1.0::IWifiApIface;
 import @1.0::IWifiIface;
 import @1.3::IWifiChip;
 import @1.4::IWifiChip;
@@ -127,4 +128,43 @@
      *         |WifiStatusCode.ERROR_INVALID_ARGS|
      */
     setMultiStaUseCase(MultiStaUseCase useCase) generates (WifiStatus status);
+
+
+    /**
+     * Create bridged IWifiApIface.
+     *
+     * Depending on the mode the chip is configured in, the interface creation
+     * may fail (code: |ERROR_NOT_AVAILABLE|) if we've already reached the maximum
+     * allowed (specified in |ChipIfaceCombination|) number of ifaces of the AP
+     * type.
+     *
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_NOT_SUPPORTED|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
+     * @return iface HIDL interface object representing the iface if
+     *         successful, null otherwise.
+     */
+    createBridgedApIface() generates (WifiStatus status, IWifiApIface iface);
+
+    /**
+     * Removes one of the instance on the AP Iface with the provided ifaceName and
+     * ifaceInstanceName.
+     *
+     * Use the API: removeApIface with brIfaceName in the V1_0::WifiChip.hal to remove bridge Iface.
+     *
+     * @param brIfaceName Name of the bridged AP iface.
+     * @param ifaceInstanceName Name of the instance. The empty instance is
+     * invalid.
+     * @return status WifiStatus of the operation.
+     *         Possible status codes:
+     *         |WifiStatusCode.SUCCESS|,
+     *         |WifiStatusCode.ERROR_WIFI_CHIP_INVALID|,
+     *         |WifiStatusCode.ERROR_INVALID_ARGS|,
+     *         |WifiStatusCode.ERROR_NOT_AVAILABLE|
+     */
+    removeIfaceInstanceFromBridgedApIface(string brIfaceName, string ifaceInstanceName)
+        generates (WifiStatus status);
 };
diff --git a/wifi/1.5/default/wifi_chip.cpp b/wifi/1.5/default/wifi_chip.cpp
index 1c238c8..f5842fe 100644
--- a/wifi/1.5/default/wifi_chip.cpp
+++ b/wifi/1.5/default/wifi_chip.cpp
@@ -19,6 +19,7 @@
 #include <android-base/logging.h>
 #include <android-base/unique_fd.h>
 #include <cutils/properties.h>
+#include <net/if.h>
 #include <sys/stat.h>
 #include <sys/sysmacros.h>
 
@@ -44,6 +45,7 @@
 constexpr char kActiveWlanIfaceNameProperty[] = "wifi.active.interface";
 constexpr char kNoActiveWlanIfaceNamePropertyValue[] = "";
 constexpr unsigned kMaxWlanIfaces = 5;
+constexpr char kApBridgeIfacePrefix[] = "ap_br_";
 
 template <typename Iface>
 void invalidateAndClear(std::vector<sp<Iface>>& ifaces, sp<Iface> iface) {
@@ -434,6 +436,13 @@
                            &WifiChip::createApIfaceInternal, hidl_status_cb);
 }
 
+Return<void> WifiChip::createBridgedApIface(
+    createBridgedApIface_cb hidl_status_cb) {
+    return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+                           &WifiChip::createBridgedApIfaceInternal,
+                           hidl_status_cb);
+}
+
 Return<void> WifiChip::getApIfaceNames(getApIfaceNames_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
                            &WifiChip::getApIfaceNamesInternal, hidl_status_cb);
@@ -453,6 +462,15 @@
                            ifname);
 }
 
+Return<void> WifiChip::removeIfaceInstanceFromBridgedApIface(
+    const hidl_string& ifname, const hidl_string& ifInstanceName,
+    removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) {
+    return validateAndCall(
+        this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
+        &WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal,
+        hidl_status_cb, ifname, ifInstanceName);
+}
+
 Return<void> WifiChip::createNanIface(createNanIface_cb hidl_status_cb) {
     return validateAndCall(this, WifiStatusCode::ERROR_WIFI_CHIP_INVALID,
                            &WifiChip::createNanIfaceInternal, hidl_status_cb);
@@ -693,6 +711,7 @@
 }
 
 void WifiChip::invalidateAndRemoveAllIfaces() {
+    invalidateAndClearBridgedApAll();
     invalidateAndClearAll(ap_ifaces_);
     invalidateAndClearAll(nan_ifaces_);
     invalidateAndClearAll(p2p_ifaces_);
@@ -861,20 +880,20 @@
     return {createWifiStatus(WifiStatusCode::SUCCESS), firmware_dump};
 }
 
-std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
-    if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
-        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
-    }
-    std::string ifname = allocateApIfaceName();
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->createVirtualInterface(
-            ifname,
-            hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
+WifiStatus WifiChip::createVirtualApInterface(const std::string& apVirtIf) {
+    legacy_hal::wifi_error legacy_status;
+    legacy_status = legacy_hal_.lock()->createVirtualInterface(
+        apVirtIf,
+        hidl_struct_util::convertHidlIfaceTypeToLegacy(IfaceType::AP));
     if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to add interface: " << ifname << " "
+        LOG(ERROR) << "Failed to add interface: " << apVirtIf << " "
                    << legacyErrorToString(legacy_status);
-        return {createWifiStatusFromLegacyError(legacy_status), {}};
+        return createWifiStatusFromLegacyError(legacy_status);
     }
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
+sp<WifiApIface> WifiChip::newWifiApIface(std::string& ifname) {
     sp<WifiApIface> iface = new WifiApIface(ifname, legacy_hal_, iface_util_);
     ap_ifaces_.push_back(iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
@@ -883,6 +902,60 @@
         }
     }
     setActiveWlanIfaceNameProperty(getFirstActiveWlanIfaceName());
+    return iface;
+}
+
+std::pair<WifiStatus, sp<IWifiApIface>> WifiChip::createApIfaceInternal() {
+    if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
+    std::string ifname = allocateApIfaceName();
+    WifiStatus status = createVirtualApInterface(ifname);
+    if (status.code != WifiStatusCode::SUCCESS) {
+        return {status, {}};
+    }
+    sp<WifiApIface> iface = newWifiApIface(ifname);
+    return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
+}
+
+std::pair<WifiStatus, sp<IWifiApIface>>
+WifiChip::createBridgedApIfaceInternal() {
+    if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::AP)) {
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
+    std::string br_ifname = kApBridgeIfacePrefix + allocateApIfaceName();
+    std::vector<std::string> ap_instances;
+    for (int i = 0; i < 2; i++) {
+        // TODO: b/173999527, it should use idx from 2 when STA+STA support, but
+        // need to check vendor support or not.
+        std::string ifaceInstanceName = allocateApOrStaIfaceName(
+            IfaceType::AP, isStaApConcurrencyAllowedInCurrentMode() ? 1 : 0);
+        WifiStatus status = createVirtualApInterface(ifaceInstanceName);
+        if (status.code != WifiStatusCode::SUCCESS) {
+            if (ap_instances.size() != 0) {
+                legacy_hal_.lock()->deleteVirtualInterface(
+                    ap_instances.front());
+            }
+            return {status, {}};
+        }
+        ap_instances.push_back(ifaceInstanceName);
+    }
+    br_ifaces_ap_instances_[br_ifname] = ap_instances;
+    if (!iface_util_.lock()->createBridge(br_ifname)) {
+        LOG(ERROR) << "Failed createBridge - br_name=" << br_ifname.c_str();
+        invalidateAndClearBridgedAp(br_ifname);
+        return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+    }
+    for (auto const& instance : ap_instances) {
+        // Bind ap instance interface to AP bridge
+        if (!iface_util_.lock()->addIfaceToBridge(br_ifname, instance)) {
+            LOG(ERROR) << "Failed add if to Bridge - if_name="
+                       << instance.c_str();
+            invalidateAndClearBridgedAp(br_ifname);
+            return {createWifiStatus(WifiStatusCode::ERROR_NOT_AVAILABLE), {}};
+        }
+    }
+    sp<WifiApIface> iface = newWifiApIface(br_ifname);
     return {createWifiStatus(WifiStatusCode::SUCCESS), iface};
 }
 
@@ -913,12 +986,8 @@
     // nan/rtt objects over AP iface. But, there is no harm to do it
     // here and not make that assumption all over the place.
     invalidateAndRemoveDependencies(ifname);
-    legacy_hal::wifi_error legacy_status =
-        legacy_hal_.lock()->deleteVirtualInterface(ifname);
-    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
-        LOG(ERROR) << "Failed to remove interface: " << ifname << " "
-                   << legacyErrorToString(legacy_status);
-    }
+    // Clear the bridge interface and the iface instance.
+    invalidateAndClearBridgedAp(ifname);
     invalidateAndClear(ap_ifaces_, iface);
     for (const auto& callback : event_cb_handler_.getCallbacks()) {
         if (!callback->onIfaceRemoved(IfaceType::AP, ifname).isOk()) {
@@ -929,6 +998,42 @@
     return createWifiStatus(WifiStatusCode::SUCCESS);
 }
 
+WifiStatus WifiChip::removeIfaceInstanceFromBridgedApIfaceInternal(
+    const std::string& ifname, const std::string& ifInstanceName) {
+    legacy_hal::wifi_error legacy_status;
+    const auto iface = findUsingName(ap_ifaces_, ifname);
+    if (!iface.get() || !ifInstanceName.empty()) {
+        return createWifiStatus(WifiStatusCode::ERROR_INVALID_ARGS);
+    }
+    // Requires to remove one of the instance in bridge mode
+    for (auto const& it : br_ifaces_ap_instances_) {
+        if (it.first == ifname) {
+            for (auto const& iface : it.second) {
+                if (iface == ifInstanceName) {
+                    if (!iface_util_.lock()->removeIfaceFromBridge(it.first,
+                                                                   iface)) {
+                        LOG(ERROR) << "Failed to remove interface: " << iface
+                                   << " from " << ifname << ", error: "
+                                   << legacyErrorToString(legacy_status);
+                        return createWifiStatus(
+                            WifiStatusCode::ERROR_NOT_AVAILABLE);
+                    }
+                    legacy_status =
+                        legacy_hal_.lock()->deleteVirtualInterface(iface);
+                    if (legacy_status != legacy_hal::WIFI_SUCCESS) {
+                        LOG(ERROR) << "Failed to del interface: " << iface
+                                   << " " << legacyErrorToString(legacy_status);
+                        return createWifiStatusFromLegacyError(legacy_status);
+                    }
+                }
+            }
+            break;
+        }
+    }
+    br_ifaces_ap_instances_.erase(ifInstanceName);
+    return createWifiStatus(WifiStatusCode::SUCCESS);
+}
+
 std::pair<WifiStatus, sp<V1_4::IWifiNanIface>>
 WifiChip::createNanIfaceInternal() {
     if (!canCurrentModeSupportIfaceOfTypeWithCurrentIfaces(IfaceType::NAN)) {
@@ -1653,6 +1758,7 @@
                                                uint32_t start_idx) {
     for (unsigned idx = start_idx; idx < kMaxWlanIfaces; idx++) {
         const auto ifname = getWlanIfaceNameWithType(type, idx);
+        if (findUsingNameFromBridgedApInstances(ifname)) continue;
         if (findUsingName(ap_ifaces_, ifname)) continue;
         if (findUsingName(sta_ifaces_, ifname)) continue;
         return ifname;
@@ -1727,6 +1833,48 @@
     return getWlanIfaceName(idx);
 }
 
+void WifiChip::invalidateAndClearBridgedApAll() {
+    for (auto const& it : br_ifaces_ap_instances_) {
+        for (auto const& iface : it.second) {
+            iface_util_.lock()->removeIfaceFromBridge(it.first, iface);
+            legacy_hal_.lock()->deleteVirtualInterface(iface);
+        }
+        iface_util_.lock()->deleteBridge(it.first);
+    }
+    br_ifaces_ap_instances_.clear();
+}
+
+void WifiChip::invalidateAndClearBridgedAp(const std::string& br_name) {
+    if (br_name.empty()) return;
+    // delete managed interfaces
+    for (auto const& it : br_ifaces_ap_instances_) {
+        if (it.first == br_name) {
+            for (auto const& iface : it.second) {
+                iface_util_.lock()->removeIfaceFromBridge(br_name, iface);
+                legacy_hal_.lock()->deleteVirtualInterface(iface);
+            }
+            iface_util_.lock()->deleteBridge(br_name);
+            br_ifaces_ap_instances_.erase(br_name);
+            break;
+        }
+    }
+    return;
+}
+
+bool WifiChip::findUsingNameFromBridgedApInstances(const std::string& name) {
+    for (auto const& it : br_ifaces_ap_instances_) {
+        if (it.first == name) {
+            return true;
+        }
+        for (auto const& iface : it.second) {
+            if (iface == name) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
 }  // namespace implementation
 }  // namespace V1_5
 }  // namespace wifi
diff --git a/wifi/1.5/default/wifi_chip.h b/wifi/1.5/default/wifi_chip.h
index 693d480..b7a9ac8 100644
--- a/wifi/1.5/default/wifi_chip.h
+++ b/wifi/1.5/default/wifi_chip.h
@@ -94,11 +94,16 @@
     Return<void> requestFirmwareDebugDump(
         requestFirmwareDebugDump_cb hidl_status_cb) override;
     Return<void> createApIface(createApIface_cb hidl_status_cb) override;
+    Return<void> createBridgedApIface(
+        createBridgedApIface_cb hidl_status_cb) override;
     Return<void> getApIfaceNames(getApIfaceNames_cb hidl_status_cb) override;
     Return<void> getApIface(const hidl_string& ifname,
                             getApIface_cb hidl_status_cb) override;
     Return<void> removeApIface(const hidl_string& ifname,
                                removeApIface_cb hidl_status_cb) override;
+    Return<void> removeIfaceInstanceFromBridgedApIface(
+        const hidl_string& brIfaceName, const hidl_string& ifaceInstanceName,
+        removeIfaceInstanceFromBridgedApIface_cb hidl_status_cb) override;
     Return<void> createNanIface(createNanIface_cb hidl_status_cb) override;
     Return<void> getNanIfaceNames(getNanIfaceNames_cb hidl_status_cb) override;
     Return<void> getNanIface(const hidl_string& ifname,
@@ -192,11 +197,16 @@
     requestDriverDebugDumpInternal();
     std::pair<WifiStatus, std::vector<uint8_t>>
     requestFirmwareDebugDumpInternal();
+    sp<WifiApIface> newWifiApIface(std::string& ifname);
+    WifiStatus createVirtualApInterface(const std::string& apVirtIf);
     std::pair<WifiStatus, sp<IWifiApIface>> createApIfaceInternal();
+    std::pair<WifiStatus, sp<IWifiApIface>> createBridgedApIfaceInternal();
     std::pair<WifiStatus, std::vector<hidl_string>> getApIfaceNamesInternal();
     std::pair<WifiStatus, sp<IWifiApIface>> getApIfaceInternal(
         const std::string& ifname);
     WifiStatus removeApIfaceInternal(const std::string& ifname);
+    WifiStatus removeIfaceInstanceFromBridgedApIfaceInternal(
+        const std::string& brIfaceName, const std::string& ifInstanceName);
     std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> createNanIfaceInternal();
     std::pair<WifiStatus, std::vector<hidl_string>> getNanIfaceNamesInternal();
     std::pair<WifiStatus, sp<V1_4::IWifiNanIface>> getNanIfaceInternal(
@@ -272,6 +282,9 @@
     std::string allocateStaIfaceName();
     bool writeRingbufferFilesInternal();
     std::string getWlanIfaceNameWithType(IfaceType type, unsigned idx);
+    void invalidateAndClearBridgedApAll();
+    void invalidateAndClearBridgedAp(const std::string& br_name);
+    bool findUsingNameFromBridgedApInstances(const std::string& name);
 
     ChipId chip_id_;
     std::weak_ptr<legacy_hal::WifiLegacyHal> legacy_hal_;
@@ -296,7 +309,7 @@
         event_cb_handler_;
 
     const std::function<void(const std::string&)> subsystemCallbackHandler_;
-
+    std::map<std::string, std::vector<std::string>> br_ifaces_ap_instances_;
     DISALLOW_COPY_AND_ASSIGN(WifiChip);
 };
 
diff --git a/wifi/supplicant/1.4/ISupplicantStaIface.hal b/wifi/supplicant/1.4/ISupplicantStaIface.hal
index f9e4c9b..7441ba5 100644
--- a/wifi/supplicant/1.4/ISupplicantStaIface.hal
+++ b/wifi/supplicant/1.4/ISupplicantStaIface.hal
@@ -71,8 +71,7 @@
      *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
      *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
      */
-    initiateVenueUrlAnqpQuery(MacAddress macAddress)
-        generates (SupplicantStatus status);
+    initiateVenueUrlAnqpQuery(MacAddress macAddress) generates (SupplicantStatus status);
 
     /**
      * Get wpa driver capabilities.
@@ -84,4 +83,55 @@
      */
     getWpaDriverCapabilities_1_4() generates (SupplicantStatus status,
         bitfield<WpaDriverCapabilitiesMask> driverCapabilitiesMask);
+
+    /**
+     * Generates DPP bootstrap information: Bootstrap ID, DPP URI and listen
+     * channel for responder mode.
+     *
+     * @param MacAddress MAC address of the interface for the DPP operation.
+     * @param deviceInfo Device specific information.
+     *        As per DPP Specification V1.0 section 5.2,
+     *        allowed Range of ASCII characters in deviceInfo - %x20-7E
+     *        semicolon is not allowed.
+     * @param DppCurve Elliptic curve cryptography type used to generate DPP
+     * public/private key pair.
+     * @return status of operation and bootstrap info.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|
+     *         |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+     */
+    generateDppBootstrapInfoForResponder(MacAddress macAddress, string deviceInfo, DppCurve curve)
+        generates (SupplicantStatus status, DppResponderBootstrapInfo bootstrapInfo);
+
+    /**
+     * Start DPP in Enrollee-Responder mode.
+     * Framework must first call |generateDppBootstrapInfoForResponder| to generate
+     * the bootstrapping information: Bootstrap ID, DPP URI and the listen channel.
+     * Then call this API with derived listen channel to start listening for
+     * authentication request from Peer initiator.
+     *
+     * @param listenChannel DPP listen channel.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_UNKNOWN|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     *         |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+     */
+    startDppEnrolleeResponder(uint32_t listenChannel) generates (SupplicantStatus status);
+
+    /**
+     * Stop DPP Responder operation - Remove the bootstrap code and stop listening.
+     *
+     * @param ownBootstrapId Local device's URI ID obtained through
+     *        |generateDppBootstrapInfoForResponder| call.
+     * @return status Status of the operation.
+     *         Possible status codes:
+     *         |SupplicantStatusCode.SUCCESS|,
+     *         |SupplicantStatusCode.FAILURE_IFACE_INVALID|
+     *         |SupplicantStatusCode.FAILURE_UNSUPPORTED|
+     */
+    stopDppResponder(uint32_t ownBootstrapId) generates (SupplicantStatus status);
 };
diff --git a/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal b/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal
index 852696d..efcebda 100644
--- a/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal
+++ b/wifi/supplicant/1.4/ISupplicantStaIfaceCallback.hal
@@ -40,8 +40,12 @@
         /**
          * Baseline information as defined in HAL 1.0.
          */
-        @1.0::ISupplicantStaIfaceCallback.AnqpData V1_0; /* Container for v1.0 of this struct */
-        vec<uint8_t> venueUrl; /* Venue URL ANQP-element */
+        @1.0::ISupplicantStaIfaceCallback.AnqpData V1_0;
+
+        /*
+         * Container for v1.0 of this struct
+         */
+        vec<uint8_t> venueUrl;
     };
 
     /**
diff --git a/wifi/supplicant/1.4/ISupplicantStaNetwork.hal b/wifi/supplicant/1.4/ISupplicantStaNetwork.hal
index 80beedf..6bed5ab 100644
--- a/wifi/supplicant/1.4/ISupplicantStaNetwork.hal
+++ b/wifi/supplicant/1.4/ISupplicantStaNetwork.hal
@@ -17,7 +17,7 @@
 package android.hardware.wifi.supplicant@1.4;
 
 import @1.3::ISupplicantStaNetwork;
-import @1.4::ISupplicantStaNetworkCallback;
+import ISupplicantStaNetworkCallback;
 
 /**
  * Interface exposed by the supplicant for each station mode network
diff --git a/wifi/supplicant/1.4/types.hal b/wifi/supplicant/1.4/types.hal
index 18af8fe..aec61c4 100644
--- a/wifi/supplicant/1.4/types.hal
+++ b/wifi/supplicant/1.4/types.hal
@@ -18,6 +18,7 @@
 
 import @1.0::SupplicantStatusCode;
 import @1.3::ConnectionCapabilities;
+import @1.3::DppFailureCode;
 import @1.3::WpaDriverCapabilitiesMask;
 
 /**
@@ -40,6 +41,29 @@
 };
 
 /**
+ * DppFailureCode: Error codes for DPP (Easy Connect)
+ */
+enum DppFailureCode : @1.3::DppFailureCode {
+    /**
+     * Failure to generate a DPP URI.
+     */
+    URI_GENERATION,
+};
+
+/**
+ * DppCurve: Elliptic curve cryptography type used to generate DPP
+ * public/private key pair.
+ */
+enum DppCurve : uint32_t {
+    PRIME256V1,
+    SECP384R1,
+    SECP521R1,
+    BRAINPOOLP256R1,
+    BRAINPOOLP384R1,
+    BRAINPOOLP512R1,
+};
+
+/**
  * Connection Capabilities supported by current network and device
  */
 struct ConnectionCapabilities {
@@ -47,6 +71,7 @@
      * Baseline information as defined in HAL 1.3.
      */
     @1.3::ConnectionCapabilities V1_3;
+
     /**
      * detailed network mode for legacy network
      */
@@ -64,13 +89,14 @@
  * Generic structure to return the status of any supplicant operation.
  */
 struct SupplicantStatus {
-  SupplicantStatusCode code;
-  /**
-   * A vendor specific error message to provide more information beyond the
-   * status code.
-   * This will be used for debbuging purposes only.
-   */
-  string debugMessage;
+    SupplicantStatusCode code;
+
+    /**
+     * A vendor specific error message to provide more information beyond the
+     * status code.
+     * This will be used for debbuging purposes only.
+     */
+    string debugMessage;
 };
 
 /**
@@ -78,7 +104,27 @@
  */
 enum WpaDriverCapabilitiesMask : @1.3::WpaDriverCapabilitiesMask {
     /**
-     *
      */
     SAE_PK = 1 << 2,
 };
+
+/**
+ * DPP bootstrap info generated for responder mode operation
+ */
+struct DppResponderBootstrapInfo {
+    /**
+     * Generated bootstrap identifier
+     */
+    uint32_t bootstrapId;
+
+    /**
+     * The Wi-Fi channel that the DPP responder is listening on.
+     */
+    uint32_t listenChannel;
+
+    /**
+     * Bootstrapping URI per DPP specification, "section 5.2 Bootstrapping
+     * information", may contain listen channel, MAC address, public key, or other information.
+     */
+    string uri;
+};
diff --git a/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp b/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp
index c0b5a70..ccd469d 100644
--- a/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp
+++ b/wifi/supplicant/1.4/vts/functional/supplicant_sta_iface_hidl_test.cpp
@@ -19,6 +19,7 @@
 #include <android/hardware/wifi/supplicant/1.1/ISupplicant.h>
 #include <android/hardware/wifi/supplicant/1.2/types.h>
 #include <android/hardware/wifi/supplicant/1.3/ISupplicant.h>
+#include <android/hardware/wifi/supplicant/1.3/ISupplicantStaNetwork.h>
 #include <android/hardware/wifi/supplicant/1.3/types.h>
 #include <android/hardware/wifi/supplicant/1.4/ISupplicant.h>
 #include <android/hardware/wifi/supplicant/1.4/ISupplicantStaIface.h>
@@ -45,7 +46,10 @@
 using ::android::hardware::wifi::supplicant::V1_2::DppNetRole;
 using ::android::hardware::wifi::supplicant::V1_2::DppProgressCode;
 using ::android::hardware::wifi::supplicant::V1_3::DppSuccessCode;
+using ::android::hardware::wifi::supplicant::V1_3::ISupplicantStaNetwork;
 using ::android::hardware::wifi::supplicant::V1_4::ConnectionCapabilities;
+using ::android::hardware::wifi::supplicant::V1_4::DppCurve;
+using ::android::hardware::wifi::supplicant::V1_4::DppResponderBootstrapInfo;
 using ::android::hardware::wifi::supplicant::V1_4::ISupplicant;
 using ::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIface;
 using ::android::hardware::wifi::supplicant::V1_4::ISupplicantStaIfaceCallback;
@@ -74,6 +78,24 @@
     sp<ISupplicantStaIface> sta_iface_;
     // MAC address to use for various tests.
     std::array<uint8_t, 6> mac_addr_;
+
+    bool isDppSupported() {
+        uint32_t keyMgmtMask = 0;
+
+        // We need to first get the key management capabilities from the device.
+        // If DPP is not supported, we just pass the test.
+        sta_iface_->getKeyMgmtCapabilities_1_3(
+            [&](const SupplicantStatus& status, uint32_t keyMgmtMaskInternal) {
+                EXPECT_EQ(SupplicantStatusCode::SUCCESS, status.code);
+                keyMgmtMask = keyMgmtMaskInternal;
+            });
+
+        if (!(keyMgmtMask & ISupplicantStaNetwork::KeyMgmtMask::DPP)) {
+            // DPP not supported
+            return false;
+        }
+        return true;
+    }
 };
 
 class IfaceCallback : public ISupplicantStaIfaceCallback {
@@ -255,6 +277,48 @@
         });
 }
 
+/*
+ * StartDppEnrolleeResponder
+ */
+TEST_P(SupplicantStaIfaceHidlTest, StartDppEnrolleeResponder) {
+    // We need to first get the key management capabilities from the device.
+    // If DPP is not supported, we just pass the test.
+    if (!isDppSupported()) {
+        // DPP not supported
+        return;
+    }
+
+    hidl_string deviceInfo = "DPP_Responder_Mode_VTS_Test";
+    uint32_t bootstrap_id = 0;
+    uint32_t listen_channel = 0;
+    uint8_t mac_address[6] = {0x22, 0x33, 0x44, 0x55, 0x66, 0x77};
+
+    // Generate DPP bootstrap information
+    sta_iface_->generateDppBootstrapInfoForResponder(
+        mac_address, deviceInfo, DppCurve::PRIME256V1,
+        [&](const SupplicantStatusV1_4& status,
+            DppResponderBootstrapInfo bootstrapInfo) {
+            EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code);
+            EXPECT_NE(-1, bootstrapInfo.bootstrapId);
+            EXPECT_NE(0, bootstrapInfo.bootstrapId);
+            bootstrap_id = bootstrapInfo.bootstrapId;
+            listen_channel = bootstrapInfo.listenChannel;
+            EXPECT_NE(0, bootstrapInfo.listenChannel);
+        });
+
+    // Start DPP as Enrollee-Responder.
+    sta_iface_->startDppEnrolleeResponder(
+        listen_channel, [&](const SupplicantStatusV1_4& status) {
+            EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code);
+        });
+
+    // Stop DPP Enrollee-Responder mode, ie remove the URI and stop listen.
+    sta_iface_->stopDppResponder(
+        bootstrap_id, [&](const SupplicantStatusV1_4& status) {
+            EXPECT_EQ(SupplicantStatusCodeV1_4::SUCCESS, status.code);
+        });
+}
+
 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(SupplicantStaIfaceHidlTest);
 INSTANTIATE_TEST_CASE_P(
     PerInstance, SupplicantStaIfaceHidlTest,