Merge tag 'android-15.0.0_r10' of https://android.googlesource.com/platform/frameworks/native into HEAD

Android 15.0.0 release 10

Change-Id: Ia1b575dea8e8276e7e84602a77fa29ca3b3e1c91

# -----BEGIN PGP SIGNATURE-----
#
# iF0EABECAB0WIQRDQNE1cO+UXoOBCWTorT+BmrEOeAUCZ32Y6wAKCRDorT+BmrEO
# eF+uAJ4ih5KzthOgb0Kd4LK/qvlPoIuQyACgiUklzqenLL/7h+KfWlr4somovr4=
# =rWiQ
# -----END PGP SIGNATURE-----
# gpg: Signature faite le mar 07 jan 2025 16:13:15 EST
# gpg:                avec la clef DSA 4340D13570EF945E83810964E8AD3F819AB10E78
# gpg: Impossible de vérifier la signature : Pas de clef publique
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 1243b21..b76892f 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -309,9 +309,9 @@
     ],
 }
 
-cc_library_shared {
-    name: "libgui",
-    vendor_available: true,
+cc_defaults {
+    name: "libgui_defaults",
+
     double_loadable: true,
 
     defaults: [
@@ -505,4 +505,16 @@
     ],
 }
 
+cc_library_shared {
+    name: "libgui",
+    vendor_available: true,
+    defaults: ["libgui_defaults"]
+}
+
+cc_library_shared {
+    name: "libgui_vendor",
+    vendor: true,
+    defaults: ["libgui_defaults"]
+}
+
 subdirs = ["tests"]
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index da74e9c..f1e5eb7 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -167,13 +167,14 @@
             return BAD_VALUE;
         }
 
-        int bufferCount = mCore->getMinUndequeuedBufferCountLocked();
-        bufferCount += maxDequeuedBuffers;
+        int minUndequedBufferCount = mCore->getMinUndequeuedBufferCountLocked();
+        int bufferCount = minUndequedBufferCount + maxDequeuedBuffers;
 
         if (bufferCount > BufferQueueDefs::NUM_BUFFER_SLOTS) {
             BQ_LOGE("setMaxDequeuedBufferCount: bufferCount %d too large "
                     "(max %d)", bufferCount, BufferQueueDefs::NUM_BUFFER_SLOTS);
-            return BAD_VALUE;
+            bufferCount = BufferQueueDefs::NUM_BUFFER_SLOTS;
+            maxDequeuedBuffers = bufferCount - minUndequedBufferCount;
         }
 
         const int minBufferSlots = mCore->getMinMaxBufferCountLocked();
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 12230f9..4664d04 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -153,6 +153,7 @@
         "android.hardware.graphics.allocator-ndk_shared",
         "android.hardware.graphics.common-ndk_shared",
         "libui-defaults",
+        "gralloc_10_usage_bits_defaults",
         // Uncomment the following line to enable VALIDATE_REGIONS traces
         //defaults: ["libui-validate-regions-defaults"],
     ],
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index a5aca99..ed6984d 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -48,6 +48,13 @@
         for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) {
             bits = bits | bit;
         }
+
+#ifdef ADDNL_GRALLOC_10_USAGE_BITS
+        uint64_t addnl_bits = static_cast<uint64_t>(ADDNL_GRALLOC_10_USAGE_BITS);
+        ALOGI("Adding additional valid usage bits: 0x%" PRIx64, addnl_bits);
+        bits = bits | addnl_bits;
+#endif
+
         return bits;
     }();
     return valid10UsageBits;
diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp
index 152b35a..27d0c60 100644
--- a/libs/ui/Gralloc3.cpp
+++ b/libs/ui/Gralloc3.cpp
@@ -47,6 +47,13 @@
              hardware::hidl_enum_range<hardware::graphics::common::V1_2::BufferUsage>()) {
             bits = bits | bit;
         }
+
+#ifdef ADDNL_GRALLOC_10_USAGE_BITS
+        uint64_t addnl_bits = static_cast<uint64_t>(ADDNL_GRALLOC_10_USAGE_BITS);
+        ALOGI("Adding additional valid usage bits: 0x%" PRIx64, addnl_bits);
+        bits = bits | addnl_bits;
+#endif
+
         return bits;
     }();
     return validUsageBits;
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index 2a60730..7289ab5 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -75,6 +75,13 @@
              hardware::hidl_enum_range<hardware::graphics::common::V1_2::BufferUsage>()) {
             bits = bits | bit;
         }
+
+#ifdef ADDNL_GRALLOC_10_USAGE_BITS
+        uint64_t addnl_bits = static_cast<uint64_t>(ADDNL_GRALLOC_10_USAGE_BITS);
+        ALOGI("Adding additional valid usage bits: 0x%" PRIx64, addnl_bits);
+        bits = bits | addnl_bits;
+#endif
+
         return bits;
     }();
     return validUsageBits | kRemovedUsageBits;
diff --git a/libs/ui/Gralloc5.cpp b/libs/ui/Gralloc5.cpp
index c9ec036..07aed29 100644
--- a/libs/ui/Gralloc5.cpp
+++ b/libs/ui/Gralloc5.cpp
@@ -190,6 +190,13 @@
         for (const auto bit : ndk::enum_range<BufferUsage>{}) {
             bits |= static_cast<int64_t>(bit);
         }
+
+        #ifdef ADDNL_GRALLOC_10_USAGE_BITS
+            uint64_t addnl_bits = static_cast<uint64_t>(ADDNL_GRALLOC_10_USAGE_BITS);
+            ALOGI("Adding additional valid usage bits: 0x%" PRIx64, addnl_bits);
+            bits = bits | addnl_bits;
+        #endif
+
         return bits;
     }();
     return validUsageBits | kRemovedUsageBits;
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index c2a9880..da57b68 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -47,6 +47,7 @@
         "libtimestats_deps",
         "libsurfaceflinger_common_deps",
         "surfaceflinger_defaults",
+        "surfaceflinger_qcom_ext_defaults",
         "libsurfaceflinger_proto_deps",
     ],
     cflags: [
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index b4ac9ba..5b1aacd 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -86,6 +86,7 @@
         "src/OutputLayer.cpp",
         "src/OutputLayerCompositionState.cpp",
         "src/RenderSurface.cpp",
+        "src/UdfpsExtension.cpp",
     ],
 }
 
@@ -94,6 +95,7 @@
     defaults: [
         "libcompositionengine_defaults",
         "libsurfaceflinger_common_deps",
+        "surfaceflinger_udfps_lib_defaults",
     ],
     srcs: [
         ":libcompositionengine_sources",
@@ -175,3 +177,11 @@
         hwaddress: true,
     },
 }
+
+cc_library_static {
+    name: "surfaceflinger_udfps_lib",
+    srcs: [
+        "src/UdfpsExtension.cpp",
+    ],
+    export_include_dirs: ["include"],
+}
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/UdfpsExtension.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/UdfpsExtension.h
new file mode 100644
index 0000000..4306cb4
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/UdfpsExtension.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021-2022 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+
+#ifndef __UDFPS_EXTENSION__H__
+#define __UDFPS_EXTENSION__H__
+
+#define UDFPS_BIOMETRIC_PROMPT_LAYER_NAME "BiometricPrompt"
+#define UDFPS_LAYER_NAME "UdfpsControllerOverlay"
+#define UDFPS_TOUCHED_LAYER_NAME "SurfaceView[UdfpsControllerOverlay](BLAST)"
+
+extern uint32_t getUdfpsZOrder(uint32_t z, bool touched);
+extern uint64_t getUdfpsUsageBits(uint64_t usageBits, bool touched);
+
+#endif /* __UDFPS_EXTENSION__H__ */
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index 2d8f98f..9c145b6 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -24,6 +24,7 @@
 #include <compositionengine/LayerFE.h>
 #include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/RenderSurface.h>
+#include <compositionengine/UdfpsExtension.h>
 #include <compositionengine/impl/HwcAsyncWorker.h>
 #include <compositionengine/impl/Output.h>
 #include <compositionengine/impl/OutputCompositionState.h>
@@ -911,7 +912,10 @@
 
 compositionengine::OutputLayer* Output::findLayerRequestingBackgroundComposition() const {
     compositionengine::OutputLayer* layerRequestingBgComposition = nullptr;
-    for (auto* layer : getOutputLayersOrderedByZ()) {
+    for (size_t i = 0; i < getOutputLayerCount(); i++) {
+        compositionengine::OutputLayer* layer = getOutputLayerOrderedByZByIndex(i);
+        compositionengine::OutputLayer* nextLayer = getOutputLayerOrderedByZByIndex(i + 1);
+
         const auto* compState = layer->getLayerFE().getCompositionState();
 
         // If any layer has a sideband stream, we will disable blurs. In that case, we don't
@@ -931,6 +935,16 @@
         if (compState->backgroundBlurRadius > 0 || compState->blurRegions.size() > 0) {
             layerRequestingBgComposition = layer;
         }
+
+        // If the next layer is the Udfps touched layer, enable client composition for it
+        // because that somehow leads to the Udfps touched layer getting device composition
+        // consistently.
+        if ((nextLayer != nullptr && layerRequestingBgComposition == nullptr) &&
+            (strncmp(nextLayer->getLayerFE().getDebugName(), UDFPS_TOUCHED_LAYER_NAME,
+                     strlen(UDFPS_TOUCHED_LAYER_NAME)) == 0)) {
+            layerRequestingBgComposition = layer;
+            break;
+        }
     }
     return layerRequestingBgComposition;
 }
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 091c207..408c58c 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -18,6 +18,7 @@
 #include <compositionengine/DisplayColorProfile.h>
 #include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/Output.h>
+#include <compositionengine/UdfpsExtension.h>
 #include <compositionengine/impl/HwcBufferCache.h>
 #include <compositionengine/impl/OutputCompositionState.h>
 #include <compositionengine/impl/OutputLayer.h>
@@ -457,7 +458,17 @@
               sourceCrop.bottom, to_string(error).c_str(), static_cast<int32_t>(error));
     }
 
-    if (auto error = hwcLayer->setZOrder(z); error != hal::Error::NONE) {
+    uint32_t z_udfps = z;
+    if ((strncmp(getLayerFE().getDebugName(), UDFPS_LAYER_NAME, strlen(UDFPS_LAYER_NAME)) == 0) ||
+        (strncmp(getLayerFE().getDebugName(), UDFPS_BIOMETRIC_PROMPT_LAYER_NAME,
+                 strlen(UDFPS_BIOMETRIC_PROMPT_LAYER_NAME)) == 0)) {
+        z_udfps = getUdfpsZOrder(z, false);
+    } else if (strncmp(getLayerFE().getDebugName(), UDFPS_TOUCHED_LAYER_NAME,
+                       strlen(UDFPS_TOUCHED_LAYER_NAME)) == 0) {
+        z_udfps = getUdfpsZOrder(z, true);
+    }
+
+    if (auto error = hwcLayer->setZOrder(z_udfps); error != hal::Error::NONE) {
         ALOGE("[%s] Failed to set Z %u: %s (%d)", getLayerFE().getDebugName(), z,
               to_string(error).c_str(), static_cast<int32_t>(error));
     }
diff --git a/services/surfaceflinger/CompositionEngine/src/UdfpsExtension.cpp b/services/surfaceflinger/CompositionEngine/src/UdfpsExtension.cpp
new file mode 100644
index 0000000..2d9d086
--- /dev/null
+++ b/services/surfaceflinger/CompositionEngine/src/UdfpsExtension.cpp
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 The LineageOS Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TARGET_PROVIDES_UDFPS_LIB
+#include <compositionengine/UdfpsExtension.h>
+
+uint32_t getUdfpsZOrder(uint32_t z, __unused bool touched) {
+    return z;
+}
+
+uint64_t getUdfpsUsageBits(uint64_t usageBits, __unused bool touched) {
+    return usageBits;
+}
+#endif
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 384f7b2..7e29bff 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -51,7 +51,7 @@
                                              const sp<IGraphicBufferProducer>& sink,
                                              const sp<IGraphicBufferProducer>& bqProducer,
                                              const sp<IGraphicBufferConsumer>& bqConsumer,
-                                             const std::string& name)
+                                             const std::string& name, bool secure)
 #if COM_ANDROID_GRAPHICS_LIBGUI_FLAGS(WB_CONSUMER_BASE_OWNS_BQ)
       : ConsumerBase(bqProducer, bqConsumer),
 #else
@@ -74,7 +74,9 @@
         mOutputFence(Fence::NO_FENCE),
         mFbProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
         mOutputProducerSlot(BufferQueue::INVALID_BUFFER_SLOT),
-        mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) {
+        mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv),
+        mSecure(secure),
+        mSinkUsage(0) {
     mSource[SOURCE_SINK] = sink;
     mSource[SOURCE_SCRATCH] = bqProducer;
 
@@ -92,6 +94,8 @@
     // on usage bits.
     int sinkUsage;
     sink->query(NATIVE_WINDOW_CONSUMER_USAGE_BITS, &sinkUsage);
+    mSinkUsage |= (GRALLOC_USAGE_HW_COMPOSER | sinkUsage);
+    setOutputUsage(mSinkUsage);
     if (sinkUsage & (GRALLOC_USAGE_SW_READ_MASK | GRALLOC_USAGE_SW_WRITE_MASK)) {
         int sinkFormat;
         sink->query(NATIVE_WINDOW_FORMAT, &sinkFormat);
@@ -124,7 +128,11 @@
     }
 
     mMustRecompose = mustRecompose;
-
+    //For WFD use cases we must always set the recompose flag in order
+    //to support pause/resume functionality
+    if (mOutputUsage & GRALLOC_USAGE_HW_VIDEO_ENCODER) {
+        mMustRecompose = true;
+    }
     VDS_LOGW_IF(mDebugState != DebugState::Idle, "Unexpected %s in %s state", __func__,
                 ftl::enum_string(mDebugState).c_str());
     mDebugState = DebugState::Begun;
@@ -161,7 +169,7 @@
     }
 
     if (mCompositionType != CompositionType::Gpu &&
-        (mOutputFormat != mDefaultOutputFormat || mOutputUsage != GRALLOC_USAGE_HW_COMPOSER)) {
+        (mOutputFormat != mDefaultOutputFormat || !(mOutputUsage & GRALLOC_USAGE_HW_COMPOSER))) {
         // We must have just switched from GPU-only to MIXED or HWC
         // composition. Stop using the format and usage requested by the GPU
         // driver; they may be suboptimal when HWC is writing to the output
@@ -173,7 +181,7 @@
         // format/usage and get a new buffer when the GPU driver calls
         // dequeueBuffer().
         mOutputFormat = mDefaultOutputFormat;
-        mOutputUsage = GRALLOC_USAGE_HW_COMPOSER;
+        setOutputUsage(GRALLOC_USAGE_HW_COMPOSER);
         refreshOutputBuffer();
     }
 
@@ -259,7 +267,7 @@
         int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
         QueueBufferOutput qbo;
         VDS_LOGV("%s: queue sink sslot=%d", __func__, sslot);
-        if (mMustRecompose) {
+        if (retireFence->isValid() && mMustRecompose) {
             status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
                     QueueBufferInput(
                         systemTime(), false /* isAutoTimestamp */,
@@ -323,6 +331,14 @@
         PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
     LOG_ALWAYS_FATAL_IF(GpuVirtualDisplayId::tryCast(mDisplayId).has_value());
 
+    // Exclude video encoder usage flag from scratch buffer usage flags.
+    if (source == SOURCE_SCRATCH) {
+        usage |= GRALLOC_USAGE_HW_FB;
+        usage &= ~(GRALLOC_USAGE_HW_VIDEO_ENCODER);
+        VDS_LOGV("%s(%s): updated scratch buffer usage flags=%#" PRIx64,
+                __func__, ftl::enum_string(source).c_str(), usage);
+    }
+
     status_t result =
             mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
                                            format, usage, nullptr, nullptr);
@@ -352,11 +368,11 @@
         }
     }
     if (result & BUFFER_NEEDS_REALLOCATION) {
-        result = mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
-        if (result < 0) {
+        auto status  = mSource[source]->requestBuffer(*sslot, &mProducerBuffers[pslot]);
+        if (status < 0) {
             mProducerBuffers[pslot].clear();
             mSource[source]->cancelBuffer(*sslot, *fence);
-            return result;
+            return status;
         }
         VDS_LOGV("%s(%s): buffers[%d]=%p fmt=%d usage=%#" PRIx64, __func__,
                  ftl::enum_string(source).c_str(), pslot, mProducerBuffers[pslot].get(),
@@ -417,7 +433,7 @@
                      __func__, w, h, format, usage, mSinkBufferWidth, mSinkBufferHeight,
                      buf->getPixelFormat(), buf->getUsage());
             mOutputFormat = format;
-            mOutputUsage = usage;
+            setOutputUsage(usage);
             result = refreshOutputBuffer();
             if (result < 0)
                 return result;
@@ -671,6 +687,21 @@
     return type == CompositionType::Unknown ? "Unknown"s : ftl::Flags(type).string();
 }
 
+/* Helper to update the output usage when the display is secure */
+
+void VirtualDisplaySurface::setOutputUsage(uint64_t /*flag*/) {
+
+    mOutputUsage = mSinkUsage;
+    if (mSecure && (mOutputUsage & GRALLOC_USAGE_HW_VIDEO_ENCODER)) {
+        /*TODO: Currently, the framework can only say whether the display
+         * and its subsequent session are secure or not. However, there is
+         * no mechanism to distinguish the different levels of security.
+         * The current solution assumes WV L3 protection.
+         */
+        mOutputUsage |= GRALLOC_USAGE_PROTECTED;
+    }
+}
+
 } // namespace android
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 90426f7..805fce9 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -77,7 +77,8 @@
 public:
     VirtualDisplaySurface(HWComposer&, VirtualDisplayId, const sp<IGraphicBufferProducer>& sink,
                           const sp<IGraphicBufferProducer>& bqProducer,
-                          const sp<IGraphicBufferConsumer>& bqConsumer, const std::string& name);
+                          const sp<IGraphicBufferConsumer>& bqConsumer,
+                          const std::string& name, bool secure);
 
     //
     // DisplaySurface interface
@@ -134,6 +135,7 @@
             sp<Fence>* outFence, float outTransformMatrix[16]) override;
     virtual status_t getUniqueId(uint64_t* outId) const override;
     virtual status_t getConsumerUsage(uint64_t* outUsage) const override;
+    virtual void setOutputUsage(uint64_t flag);
 
     //
     // Utility methods
@@ -265,6 +267,8 @@
     bool mMustRecompose = false;
 
     bool mForceHwcCopy;
+    bool mSecure;
+    int mSinkUsage;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 65a0ed3..23a2f9f 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -165,6 +165,14 @@
 #include "Utils/Dumper.h"
 #include "WindowInfosListenerInvoker.h"
 
+#ifdef QCOM_UM_FAMILY
+#if __has_include("QtiGralloc.h")
+#include "QtiGralloc.h"
+#else
+#include "gralloc_priv.h"
+#endif
+#endif
+
 #include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h>
 #include <aidl/android/hardware/graphics/composer3/DisplayCapability.h>
 #include <aidl/android/hardware/graphics/composer3/RenderIntent.h>
@@ -640,8 +648,10 @@
 }
 
 VirtualDisplayId SurfaceFlinger::acquireVirtualDisplay(ui::Size resolution,
-                                                       ui::PixelFormat format) {
-    if (auto& generator = mVirtualDisplayIdGenerators.hal) {
+                                                       ui::PixelFormat format,
+                                                       bool canAllocateHwcForVDS) {
+    auto& generator = mVirtualDisplayIdGenerators.hal;
+    if (canAllocateHwcForVDS && generator) {
         if (const auto id = generator->generateId()) {
             if (getHwComposer().allocateVirtualDisplay(*id, resolution, &format)) {
                 return *id;
@@ -899,9 +909,9 @@
 
     enableLatchUnsignaledConfig = getLatchUnsignaledConfig();
 
-    if (base::GetBoolProperty("debug.sf.enable_hwc_vds"s, false)) {
-        enableHalVirtualDisplays(true);
-    }
+    mAllowHwcForWFD = base::GetBoolProperty("vendor.display.vds_allow_hwc"s, false);
+    mAllowHwcForVDS = mAllowHwcForWFD && base::GetBoolProperty("debug.sf.enable_hwc_vds"s, false);
+    mFirstApiLevel = android::base::GetIntProperty("ro.product.first_api_level", 0);
 
     // Process hotplug for displays connected at boot.
     LOG_ALWAYS_FATAL_IF(!configureLocked(),
@@ -3657,6 +3667,11 @@
 
 void SurfaceFlinger::processDisplayAdded(const wp<IBinder>& displayToken,
                                          const DisplayDeviceState& state) {
+#ifdef QCOM_UM_FAMILY
+    bool canAllocateHwcForVDS = false;
+#else
+    bool canAllocateHwcForVDS = true;
+#endif
     ui::Size resolution(0, 0);
     ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
     if (state.physical) {
@@ -3671,6 +3686,20 @@
         status = state.surface->query(NATIVE_WINDOW_FORMAT, &format);
         ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status);
         pixelFormat = static_cast<ui::PixelFormat>(format);
+#ifdef QCOM_UM_FAMILY
+        // Check if VDS is allowed to use HWC
+        size_t maxVirtualDisplaySize = getHwComposer().getMaxVirtualDisplayDimension();
+        if (maxVirtualDisplaySize == 0 || ((uint64_t)resolution.width <= maxVirtualDisplaySize &&
+            (uint64_t)resolution.height <= maxVirtualDisplaySize)) {
+            uint64_t usage = 0;
+            // Replace with native_window_get_consumer_usage ?
+            status = state .surface->getConsumerUsage(&usage);
+            ALOGW_IF(status != NO_ERROR, "Unable to query usage (%d)", status);
+            if ((status == NO_ERROR) && canAllocateHwcDisplayIdForVDS(usage)) {
+                canAllocateHwcForVDS = true;
+            }
+        }
+#endif
     } else {
         // Virtual displays without a surface are dormant:
         // they have external state (layer stack, projection,
@@ -3682,7 +3711,7 @@
     if (const auto& physical = state.physical) {
         builder.setId(physical->id);
     } else {
-        builder.setId(acquireVirtualDisplay(resolution, pixelFormat));
+        builder.setId(acquireVirtualDisplay(resolution, pixelFormat, canAllocateHwcForVDS));
     }
 
     builder.setPixels(resolution);
@@ -3703,7 +3732,8 @@
         const auto displayId = VirtualDisplayId::tryCast(compositionDisplay->getId());
         LOG_FATAL_IF(!displayId);
         auto surface = sp<VirtualDisplaySurface>::make(getHwComposer(), *displayId, state.surface,
-                                                       bqProducer, bqConsumer, state.displayName);
+                                                       bqProducer, bqConsumer, state.displayName,
+                                                       state.isSecure);
         displaySurface = surface;
         producer = std::move(surface);
     } else {
@@ -7787,6 +7817,35 @@
 
 } // namespace
 
+#ifdef QCOM_UM_FAMILY
+bool SurfaceFlinger::canAllocateHwcDisplayIdForVDS(uint64_t usage) {
+    uint64_t flag_mask_pvt_wfd = ~0;
+    uint64_t flag_mask_hw_video = ~0;
+    // Reserve hardware acceleration for WFD use-case
+    // GRALLOC_USAGE_PRIVATE_WFD + GRALLOC_USAGE_HW_VIDEO_ENCODER = WFD using HW composer.
+    flag_mask_pvt_wfd = GRALLOC_USAGE_PRIVATE_WFD;
+    flag_mask_hw_video = GRALLOC_USAGE_HW_VIDEO_ENCODER;
+    bool isWfd = (usage & flag_mask_pvt_wfd) && (usage & flag_mask_hw_video);
+    // Enabling only the vendor property would allow WFD to use HWC
+    // Enabling both the aosp and vendor properties would allow all other VDS to use HWC
+    // Disabling both would set all virtual displays to fall back to GPU
+    // In vendor frozen targets, allow WFD to use HWC without any property settings.
+    bool canAllocate = mAllowHwcForVDS || (isWfd && mAllowHwcForWFD) || (isWfd &&
+                       mFirstApiLevel < __ANDROID_API_T__);
+
+    if (canAllocate) {
+        enableHalVirtualDisplays(true);
+    }
+
+    return canAllocate;
+
+}
+#else
+bool SurfaceFlinger::canAllocateHwcDisplayIdForVDS(uint64_t) {
+    return true;
+}
+#endif
+
 status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp<IBinder>& displayToken,
                                                     const gui::DisplayModeSpecs& specs) {
     SFTRACE_CALL();
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 3eb72cc..1ccfdc9 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -893,6 +893,8 @@
             std::vector<std::pair<Layer*, sp<LayerFE>>>& layers,
             std::vector<sp<LayerFE>>& layerFEs);
 
+    bool canAllocateHwcDisplayIdForVDS(uint64_t usage);
+
     void readPersistentProperties();
 
     uint32_t getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t uid) const;
@@ -1078,7 +1080,8 @@
     void enableHalVirtualDisplays(bool);
 
     // Virtual display lifecycle for ID generation and HAL allocation.
-    VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat) REQUIRES(mStateLock);
+    VirtualDisplayId acquireVirtualDisplay(ui::Size, ui::PixelFormat, bool canAllocateHwcForVDS)
+            REQUIRES(mStateLock);
     void releaseVirtualDisplay(VirtualDisplayId);
 
     // Returns a display other than `mActiveDisplayId` that can be activated, if any.
@@ -1406,6 +1409,10 @@
 
     const sp<WindowInfosListenerInvoker> mWindowInfosListenerInvoker;
 
+    bool mAllowHwcForVDS = false;
+    bool mAllowHwcForWFD = false;
+    int mFirstApiLevel = 0;
+
     // returns the framerate of the layer with the given sequence ID
     float getLayerFramerate(nsecs_t now, int32_t id) const {
         return mScheduler->getLayerFramerate(now, id);