Merge branch 'dev/11/fp3/security-aosp-rvc-release' into int/11/fp3

* dev/11/fp3/security-aosp-rvc-release:
  Allow sensors list to be empty

Change-Id: Icc61f345f514ade0580dad7d06cdf60d071664b5
diff --git a/cmds/dumpsys/dumpsys.cpp b/cmds/dumpsys/dumpsys.cpp
index a427c8d..8a7504f 100644
--- a/cmds/dumpsys/dumpsys.cpp
+++ b/cmds/dumpsys/dumpsys.cpp
@@ -427,7 +427,7 @@
                  << strerror(errno) << std::endl;
             status = -errno;
             break;
-        } else if (rc == 0) {
+        } else if (rc == 0 || time_left_ms() == 0) {
             status = TIMED_OUT;
             break;
         }
diff --git a/cmds/installd/InstalldNativeService.cpp b/cmds/installd/InstalldNativeService.cpp
index b9c1add..01eb3fe 100644
--- a/cmds/installd/InstalldNativeService.cpp
+++ b/cmds/installd/InstalldNativeService.cpp
@@ -940,6 +940,33 @@
 
     auto scope_guard = android::base::make_scope_guard(deleter);
 
+    if (storageFlags & FLAG_STORAGE_DE) {
+        auto from = create_data_user_de_package_path(volume_uuid, user, package_name);
+        auto to = create_data_misc_de_rollback_path(volume_uuid, user, snapshotId);
+        auto rollback_package_path = create_data_misc_de_rollback_package_path(volume_uuid, user,
+            snapshotId, package_name);
+
+        int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
+        if (rc != 0) {
+            return error(rc, "Failed to create folder " + to);
+        }
+
+        rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */);
+        if (rc != 0) {
+            return error(rc, "Failed clearing existing snapshot " + rollback_package_path);
+        }
+
+        // Check if we have data to copy.
+        if (access(from.c_str(), F_OK) == 0) {
+          rc = copy_directory_recursive(from.c_str(), to.c_str());
+        }
+        if (rc != 0) {
+            res = error(rc, "Failed copying " + from + " to " + to);
+            clear_de_on_exit = true;
+            return res;
+        }
+    }
+
     // The app may not have any data at all, in which case it's OK to skip here.
     auto from_ce = create_data_user_ce_package_path(volume_uuid, user, package_name);
     if (access(from_ce.c_str(), F_OK) != 0) {
@@ -965,30 +992,6 @@
         LOG(WARNING) << "Failed to clear code_cache of app " << packageName;
     }
 
-    if (storageFlags & FLAG_STORAGE_DE) {
-        auto from = create_data_user_de_package_path(volume_uuid, user, package_name);
-        auto to = create_data_misc_de_rollback_path(volume_uuid, user, snapshotId);
-        auto rollback_package_path = create_data_misc_de_rollback_package_path(volume_uuid, user,
-            snapshotId, package_name);
-
-        int rc = create_dir_if_needed(to.c_str(), kRollbackFolderMode);
-        if (rc != 0) {
-            return error(rc, "Failed to create folder " + to);
-        }
-
-        rc = delete_dir_contents(rollback_package_path, true /* ignore_if_missing */);
-        if (rc != 0) {
-            return error(rc, "Failed clearing existing snapshot " + rollback_package_path);
-        }
-
-        rc = copy_directory_recursive(from.c_str(), to.c_str());
-        if (rc != 0) {
-            res = error(rc, "Failed copying " + from + " to " + to);
-            clear_de_on_exit = true;
-            return res;
-        }
-    }
-
     if (storageFlags & FLAG_STORAGE_CE) {
         auto from = create_data_user_ce_package_path(volume_uuid, user, package_name);
         auto to = create_data_misc_ce_rollback_path(volume_uuid, user, snapshotId);
diff --git a/cmds/installd/QuotaUtils.cpp b/cmds/installd/QuotaUtils.cpp
index e080291..6027139 100644
--- a/cmds/installd/QuotaUtils.cpp
+++ b/cmds/installd/QuotaUtils.cpp
@@ -35,7 +35,7 @@
 /* Map of all quota mounts from target to source */
 std::unordered_map<std::string, std::string> mQuotaReverseMounts;
 
-std::string& FindQuotaDeviceForUuid(const std::string& uuid) {
+std::string FindQuotaDeviceForUuid(const std::string& uuid) {
     std::lock_guard<std::recursive_mutex> lock(mMountsLock);
     auto path = create_data_path(uuid.empty() ? nullptr : uuid.c_str());
     return mQuotaReverseMounts[path];
diff --git a/cmds/servicemanager/ServiceManager.cpp b/cmds/servicemanager/ServiceManager.cpp
index 1f9892a..e80c321 100644
--- a/cmds/servicemanager/ServiceManager.cpp
+++ b/cmds/servicemanager/ServiceManager.cpp
@@ -213,17 +213,18 @@
         return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
     }
 
-    auto entry = mNameToService.emplace(name, Service {
+    // Overwrite the old service if it exists
+    mNameToService[name] = Service {
         .binder = binder,
         .allowIsolated = allowIsolated,
         .dumpPriority = dumpPriority,
         .debugPid = ctx.debugPid,
-    });
+    };
 
     auto it = mNameToRegistrationCallback.find(name);
     if (it != mNameToRegistrationCallback.end()) {
         for (const sp<IServiceCallback>& cb : it->second) {
-            entry.first->second.guaranteeClient = true;
+            mNameToService[name].guaranteeClient = true;
             // permission checked in registerForNotifications
             cb->onRegistration(name, binder);
         }
diff --git a/cmds/servicemanager/test_sm.cpp b/cmds/servicemanager/test_sm.cpp
index 25245be..fb9f9df 100644
--- a/cmds/servicemanager/test_sm.cpp
+++ b/cmds/servicemanager/test_sm.cpp
@@ -135,6 +135,26 @@
         IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
 }
 
+TEST(AddService, OverwriteExistingService) {
+    auto sm = getPermissiveServiceManager();
+    sp<IBinder> serviceA = getBinder();
+    EXPECT_TRUE(sm->addService("foo", serviceA, false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> outA;
+    EXPECT_TRUE(sm->getService("foo", &outA).isOk());
+    EXPECT_EQ(serviceA, outA);
+
+    // serviceA should be overwritten by serviceB
+    sp<IBinder> serviceB = getBinder();
+    EXPECT_TRUE(sm->addService("foo", serviceB, false /*allowIsolated*/,
+        IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk());
+
+    sp<IBinder> outB;
+    EXPECT_TRUE(sm->getService("foo", &outB).isOk());
+    EXPECT_EQ(serviceB, outB);
+}
+
 TEST(AddService, NoPermissions) {
     std::unique_ptr<MockAccess> access = std::make_unique<NiceMock<MockAccess>>();
 
diff --git a/data/etc/car_core_hardware.xml b/data/etc/car_core_hardware.xml
index 50f117d..6ffb947 100644
--- a/data/etc/car_core_hardware.xml
+++ b/data/etc/car_core_hardware.xml
@@ -38,7 +38,6 @@
     <!-- basic system services -->
     <feature name="android.software.connectionservice" />
     <feature name="android.software.voice_recognizers" notLowRam="true" />
-    <feature name="android.software.backup" />
     <feature name="android.software.home_screen" />
     <feature name="android.software.companion_device_setup" />
     <feature name="android.software.autofill" />
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 7ca9031..f5324d1 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -367,7 +367,8 @@
      * Other errors probably indicate that the channel is broken.
      */
     status_t consume(InputEventFactoryInterface* factory, bool consumeBatches, nsecs_t frameTime,
-                     uint32_t* outSeq, InputEvent** outEvent);
+                     uint32_t* outSeq, InputEvent** outEvent,
+                     int* motionEventType, int* touchMoveNumber, bool* flag);
 
     /* Sends a finished signal to the publisher to inform it that the message
      * with the specified sequence number has finished being process and whether
@@ -412,6 +413,8 @@
     int32_t getPendingBatchSource() const;
 
 private:
+    int mTouchMoveCounter = 0;
+
     // True if touch resampling is enabled.
     const bool mResampleTouch;
 
@@ -529,7 +532,9 @@
     Vector<SeqChain> mSeqChains;
 
     status_t consumeBatch(InputEventFactoryInterface* factory,
-            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent);
+            nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent,
+            int* touchMoveNumber);
+
     status_t consumeSamples(InputEventFactoryInterface* factory,
             Batch& batch, size_t count, uint32_t* outSeq, InputEvent** outEvent);
 
diff --git a/libs/arect/Android.bp b/libs/arect/Android.bp
index 258a4e3..80aa891 100644
--- a/libs/arect/Android.bp
+++ b/libs/arect/Android.bp
@@ -22,6 +22,8 @@
 
 cc_library_headers {
     name: "libarect_headers",
+    // TODO(b/153609531): remove when no longer needed.
+    native_bridge_supported: true,
     export_include_dirs: ["include"],
 }
 
diff --git a/libs/binder/Binder.cpp b/libs/binder/Binder.cpp
index e0fb543..6ca3b16 100644
--- a/libs/binder/Binder.cpp
+++ b/libs/binder/Binder.cpp
@@ -24,6 +24,7 @@
 #include <binder/IShellCallback.h>
 #include <binder/Parcel.h>
 
+#include <linux/sched.h>
 #include <stdio.h>
 
 namespace android {
@@ -133,6 +134,8 @@
     // unlocked objects
     bool mRequestingSid = false;
     sp<IBinder> mExtension;
+    int mPolicy = SCHED_NORMAL;
+    int mPriority = 0;
 
     // for below objects
     Mutex mLock;
@@ -279,6 +282,47 @@
     return e->mExtension;
 }
 
+void BBinder::setMinSchedulerPolicy(int policy, int priority) {
+    switch (policy) {
+    case SCHED_NORMAL:
+      LOG_ALWAYS_FATAL_IF(priority < -20 || priority > 19, "Invalid priority for SCHED_NORMAL: %d", priority);
+      break;
+    case SCHED_RR:
+    case SCHED_FIFO:
+      LOG_ALWAYS_FATAL_IF(priority < 1 || priority > 99, "Invalid priority for sched %d: %d", policy, priority);
+      break;
+    default:
+      LOG_ALWAYS_FATAL("Unrecognized scheduling policy: %d", policy);
+    }
+
+    Extras* e = mExtras.load(std::memory_order_acquire);
+
+    if (e == nullptr) {
+        // Avoid allocations if called with default.
+        if (policy == SCHED_NORMAL && priority == 0) {
+            return;
+        }
+
+        e = getOrCreateExtras();
+        if (!e) return; // out of memory
+    }
+
+    e->mPolicy = policy;
+    e->mPriority = priority;
+}
+
+int BBinder::getMinSchedulerPolicy() {
+    Extras* e = mExtras.load(std::memory_order_acquire);
+    if (e == nullptr) return SCHED_NORMAL;
+    return e->mPolicy;
+}
+
+int BBinder::getMinSchedulerPriority() {
+    Extras* e = mExtras.load(std::memory_order_acquire);
+    if (e == nullptr) return 0;
+    return e->mPriority;
+}
+
 pid_t BBinder::getDebugPid() {
     return getpid();
 }
diff --git a/libs/binder/IPCThreadState.cpp b/libs/binder/IPCThreadState.cpp
index d67ce15..847b73a 100644
--- a/libs/binder/IPCThreadState.cpp
+++ b/libs/binder/IPCThreadState.cpp
@@ -860,6 +860,10 @@
             err = FAILED_TRANSACTION;
             goto finish;
 
+        case BR_FROZEN_REPLY:
+            err = FAILED_TRANSACTION;
+            goto finish;
+
         case BR_ACQUIRE_RESULT:
             {
                 ALOG_ASSERT(acquireResult != NULL, "Unexpected brACQUIRE_RESULT");
@@ -1316,6 +1320,42 @@
         }
 }
 
+status_t IPCThreadState::getProcessFreezeInfo(pid_t pid, bool *sync_received, bool *async_received)
+{
+    int ret = 0;
+    binder_frozen_status_info info;
+    info.pid = pid;
+
+#if defined(__ANDROID__)
+    if (ioctl(self()->mProcess->mDriverFD, BINDER_GET_FROZEN_INFO, &info) < 0)
+        ret = -errno;
+#endif
+    *sync_received = info.sync_recv;
+    *async_received = info.async_recv;
+
+    return ret;
+}
+
+status_t IPCThreadState::freeze(pid_t pid, bool enable, uint32_t timeout_ms) {
+    struct binder_freeze_info info;
+    int ret = 0;
+
+    info.pid = pid;
+    info.enable = enable;
+    info.timeout_ms = timeout_ms;
+
+
+#if defined(__ANDROID__)
+    if (ioctl(self()->mProcess->mDriverFD, BINDER_FREEZE, &info) < 0)
+        ret = -errno;
+#endif
+
+    //
+    // ret==-EAGAIN indicates that transactions have not drained.
+    // Call again to poll for completion.
+    //
+    return ret;
+}
 
 void IPCThreadState::freeBuffer(Parcel* parcel, const uint8_t* data,
                                 size_t /*dataSize*/,
diff --git a/libs/binder/Parcel.cpp b/libs/binder/Parcel.cpp
index efcc042..f790b88 100644
--- a/libs/binder/Parcel.cpp
+++ b/libs/binder/Parcel.cpp
@@ -20,6 +20,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
+#include <linux/sched.h>
 #include <pthread.h>
 #include <stdint.h>
 #include <stdio.h>
@@ -188,16 +189,18 @@
     return OK;
 }
 
+static constexpr inline int schedPolicyMask(int policy, int priority) {
+    return (priority & FLAT_BINDER_FLAG_PRIORITY_MASK) | ((policy & 3) << FLAT_BINDER_FLAG_SCHED_POLICY_SHIFT);
+}
+
 status_t Parcel::flattenBinder(const sp<IBinder>& binder)
 {
     flat_binder_object obj;
+    obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
 
-    if (IPCThreadState::self()->backgroundSchedulingDisabled()) {
-        /* minimum priority for all nodes is nice 0 */
-        obj.flags = FLAT_BINDER_FLAG_ACCEPTS_FDS;
-    } else {
-        /* minimum priority for all nodes is MAX_NICE(19) */
-        obj.flags = 0x13 | FLAT_BINDER_FLAG_ACCEPTS_FDS;
+    int schedBits = 0;
+    if (!IPCThreadState::self()->backgroundSchedulingDisabled()) {
+        schedBits = schedPolicyMask(SCHED_NORMAL, 19);
     }
 
     if (binder != nullptr) {
@@ -213,6 +216,13 @@
             obj.handle = handle;
             obj.cookie = 0;
         } else {
+            int policy = local->getMinSchedulerPolicy();
+            int priority = local->getMinSchedulerPriority();
+
+            if (policy != 0 || priority != 0) {
+                // override value, since it is set explicitly
+                schedBits = schedPolicyMask(policy, priority);
+            }
             if (local->isRequestingSid()) {
                 obj.flags |= FLAT_BINDER_FLAG_TXN_SECURITY_CTX;
             }
@@ -226,6 +236,8 @@
         obj.cookie = 0;
     }
 
+    obj.flags |= schedBits;
+
     return finishFlattenBinder(binder, obj);
 }
 
@@ -2468,7 +2480,7 @@
 
     releaseObjects();
 
-    if (data) {
+    if (data || desired == 0) {
         LOG_ALLOC("Parcel %p: restart from %zu to %zu capacity", this, mDataCapacity, desired);
         pthread_mutex_lock(&gParcelGlobalAllocSizeLock);
         gParcelGlobalAllocSize += desired;
diff --git a/libs/binder/include/binder/AppOpsManager.h b/libs/binder/include/binder/AppOpsManager.h
index 6afcd77..d93935a 100644
--- a/libs/binder/include/binder/AppOpsManager.h
+++ b/libs/binder/include/binder/AppOpsManager.h
@@ -131,7 +131,11 @@
         OP_DEPRECATED_1 = 96,
         OP_AUTO_REVOKE_PERMISSIONS_IF_UNUSED = 97,
         OP_AUTO_REVOKE_MANAGED_BY_INSTALLER = 98,
-        _NUM_OP = 99
+        OP_NO_ISOLATED_STORAGE = 99,
+        OP_PHONE_CALL_MICROPHONE = 100,
+        OP_PHONE_CALL_CAMERA = 101,
+        OP_RECORD_AUDIO_HOTWORD = 102,
+        _NUM_OP = 103
     };
 
     AppOpsManager();
diff --git a/libs/binder/include/binder/Binder.h b/libs/binder/include/binder/Binder.h
index 74e52db..4cf0515 100644
--- a/libs/binder/include/binder/Binder.h
+++ b/libs/binder/include/binder/Binder.h
@@ -72,6 +72,25 @@
     // This must be called before the object is sent to another process. Not thread safe.
     void                setExtension(const sp<IBinder>& extension);
 
+    // This must be called before the object is sent to another process. Not thread safe.
+    //
+    // This function will abort if improper parameters are set. This is like
+    // sched_setscheduler. However, it sets the minimum scheduling policy
+    // only for the duration that this specific binder object is handling the
+    // call in a threadpool. By default, this API is set to SCHED_NORMAL/0. In
+    // this case, the scheduling priority will not actually be modified from
+    // binder defaults. See also IPCThreadState::disableBackgroundScheduling.
+    //
+    // Appropriate values are:
+    // SCHED_NORMAL: -20 <= priority <= 19
+    // SCHED_RR/SCHED_FIFO: 1 <= priority <= 99
+    __attribute__((weak))
+    void                setMinSchedulerPolicy(int policy, int priority);
+    __attribute__((weak))
+    int                 getMinSchedulerPolicy();
+    __attribute__((weak))
+    int                 getMinSchedulerPriority();
+
     pid_t               getDebugPid();
 
 protected:
diff --git a/libs/binder/include/binder/IPCThreadState.h b/libs/binder/include/binder/IPCThreadState.h
index 4818889..8ac7165 100644
--- a/libs/binder/include/binder/IPCThreadState.h
+++ b/libs/binder/include/binder/IPCThreadState.h
@@ -34,7 +34,26 @@
 public:
     static  IPCThreadState*     self();
     static  IPCThreadState*     selfOrNull();  // self(), but won't instantiate
-    
+
+    // Freeze or unfreeze the binder interface to a specific process. When freezing, this method
+    // will block up to timeout_ms to process pending transactions directed to pid. Unfreeze
+    // is immediate. Transactions to processes frozen via this method won't be delivered and the
+    // driver will return BR_FROZEN_REPLY to the client sending them. After unfreeze,
+    // transactions will be delivered normally.
+    //
+    // pid: id for the process for which the binder interface is to be frozen
+    // enable: freeze (true) or unfreeze (false)
+    // timeout_ms: maximum time this function is allowed to block the caller waiting for pending
+    // binder transactions to be processed.
+    //
+    // returns: 0 in case of success, a value < 0 in case of error
+    __attribute__((weak))
+    static  status_t            freeze(pid_t pid, bool enabled, uint32_t timeout_ms);
+
+    // Provide information about the state of a frozen process
+    __attribute__((weak))
+    static  status_t            getProcessFreezeInfo(pid_t pid, bool *sync_received,
+                                                    bool *async_received);
             sp<ProcessState>    process();
             
             status_t            clearLastError();
diff --git a/libs/binder/include/private/binder/binder_module.h b/libs/binder/include/private/binder/binder_module.h
index c22be9f..7be8f7b 100644
--- a/libs/binder/include/private/binder/binder_module.h
+++ b/libs/binder/include/private/binder/binder_module.h
@@ -36,6 +36,60 @@
 #include <sys/ioctl.h>
 #include <linux/android/binder.h>
 
+#ifndef BR_FROZEN_REPLY
+// Temporary definition of BR_FROZEN_REPLY. For production
+// this will come from UAPI binder.h
+#define BR_FROZEN_REPLY _IO('r', 18)
+#endif //BR_FROZEN_REPLY
+
+#ifndef BINDER_FREEZE
+/*
+ * Temporary definitions for freeze support. For the final version
+ * these will be defined in the UAPI binder.h file from upstream kernel.
+ */
+#define BINDER_FREEZE _IOW('b', 14, struct binder_freeze_info)
+
+struct binder_freeze_info {
+    //
+    // Group-leader PID of process to be frozen
+    //
+    uint32_t            pid;
+    //
+    // Enable(1) / Disable(0) freeze for given PID
+    //
+    uint32_t            enable;
+    //
+    // Timeout to wait for transactions to drain.
+    // 0: don't wait (ioctl will return EAGAIN if not drained)
+    // N: number of ms to wait
+    uint32_t            timeout_ms;
+};
+#endif //BINDER_FREEZE
+
+#ifndef BINDER_GET_FROZEN_INFO
+
+#define BINDER_GET_FROZEN_INFO          _IOWR('b', 15, struct binder_frozen_status_info)
+
+struct binder_frozen_status_info {
+    //
+    // Group-leader PID of process to be queried
+    //
+    __u32            pid;
+    //
+    // Indicates whether the process has received any sync calls since last
+    // freeze (cleared at freeze/unfreeze)
+    //
+    __u32            sync_recv;
+    //
+    // Indicates whether the process has received any async calls since last
+    // freeze (cleared at freeze/unfreeze)
+    //
+    __u32            async_recv;
+};
+#endif //BINDER_GET_FROZEN_INFO
+
+
+
 #ifdef __cplusplus
 }   // namespace android
 #endif
diff --git a/libs/binder/tests/binderLibTest.cpp b/libs/binder/tests/binderLibTest.cpp
index b37b688..9caad45 100644
--- a/libs/binder/tests/binderLibTest.cpp
+++ b/libs/binder/tests/binderLibTest.cpp
@@ -16,6 +16,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <fstream>
 #include <poll.h>
 #include <pthread.h>
 #include <stdio.h>
@@ -50,6 +51,9 @@
 static char *binderserversuffix;
 static char binderserverarg[] = "--binderserver";
 
+static constexpr int kSchedPolicy = SCHED_RR;
+static constexpr int kSchedPriority = 7;
+
 static String16 binderLibTestServiceName = String16("test.binderLib");
 
 enum BinderLibTestTranscationCode {
@@ -75,6 +79,9 @@
     BINDER_LIB_TEST_GET_PTR_SIZE_TRANSACTION,
     BINDER_LIB_TEST_CREATE_BINDER_TRANSACTION,
     BINDER_LIB_TEST_GET_WORK_SOURCE_TRANSACTION,
+    BINDER_LIB_TEST_GET_SCHEDULING_POLICY,
+    BINDER_LIB_TEST_NOP_TRANSACTION_WAIT,
+    BINDER_LIB_TEST_GETPID,
     BINDER_LIB_TEST_ECHO_VECTOR,
     BINDER_LIB_TEST_REJECT_OBJECTS,
 };
@@ -395,6 +402,49 @@
     EXPECT_EQ(NO_ERROR, ret);
 }
 
+TEST_F(BinderLibTest, Freeze) {
+    status_t ret;
+    Parcel data, reply, replypid;
+    std::ifstream freezer_file("/sys/fs/cgroup/freezer/cgroup.freeze");
+
+    //Pass test on devices where the freezer is not supported
+    if (freezer_file.fail()) {
+        GTEST_SKIP();
+        return;
+    }
+
+    std::string freezer_enabled;
+    std::getline(freezer_file, freezer_enabled);
+
+    //Pass test on devices where the freezer is disabled
+    if (freezer_enabled != "1") {
+        GTEST_SKIP();
+        return;
+    }
+
+    ret = m_server->transact(BINDER_LIB_TEST_GETPID, data, &replypid);
+    int32_t pid = replypid.readInt32();
+    EXPECT_EQ(NO_ERROR, ret);
+    for (int i = 0; i < 10; i++) {
+        EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION_WAIT, data, &reply, TF_ONE_WAY));
+    }
+    EXPECT_EQ(-EAGAIN, IPCThreadState::self()->freeze(pid, 1, 0));
+    EXPECT_EQ(-EAGAIN, IPCThreadState::self()->freeze(pid, 1, 0));
+    EXPECT_EQ(NO_ERROR, IPCThreadState::self()->freeze(pid, 1, 1000));
+    EXPECT_EQ(FAILED_TRANSACTION, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply));
+
+    bool sync_received, async_received;
+
+    EXPECT_EQ(NO_ERROR, IPCThreadState::self()->getProcessFreezeInfo(pid, &sync_received,
+                &async_received));
+
+    EXPECT_EQ(sync_received, 1);
+    EXPECT_EQ(async_received, 0);
+
+    EXPECT_EQ(NO_ERROR, IPCThreadState::self()->freeze(pid, 0, 0));
+    EXPECT_EQ(NO_ERROR, m_server->transact(BINDER_LIB_TEST_NOP_TRANSACTION, data, &reply));
+}
+
 TEST_F(BinderLibTest, SetError) {
     int32_t testValue[] = { 0, -123, 123 };
     for (size_t i = 0; i < ARRAY_SIZE(testValue); i++) {
@@ -1015,6 +1065,22 @@
     EXPECT_EQ(NO_ERROR, ret2);
 }
 
+TEST_F(BinderLibTest, SchedPolicySet) {
+    sp<IBinder> server = addServer();
+    ASSERT_TRUE(server != nullptr);
+
+    Parcel data, reply;
+    status_t ret = server->transact(BINDER_LIB_TEST_GET_SCHEDULING_POLICY, data, &reply);
+    EXPECT_EQ(NO_ERROR, ret);
+
+    int policy = reply.readInt32();
+    int priority = reply.readInt32();
+
+    EXPECT_EQ(kSchedPolicy, policy & (~SCHED_RESET_ON_FORK));
+    EXPECT_EQ(kSchedPriority, priority);
+}
+
+
 TEST_F(BinderLibTest, VectorSent) {
     Parcel data, reply;
     sp<IBinder> server = addServer();
@@ -1197,6 +1263,12 @@
                 pthread_mutex_unlock(&m_serverWaitMutex);
                 return ret;
             }
+            case BINDER_LIB_TEST_GETPID:
+                reply->writeInt32(getpid());
+                return NO_ERROR;
+            case BINDER_LIB_TEST_NOP_TRANSACTION_WAIT:
+                usleep(5000);
+                return NO_ERROR;
             case BINDER_LIB_TEST_NOP_TRANSACTION:
                 return NO_ERROR;
             case BINDER_LIB_TEST_DELAYED_CALL_BACK: {
@@ -1371,6 +1443,16 @@
                 reply->writeInt32(IPCThreadState::self()->getCallingWorkSourceUid());
                 return NO_ERROR;
             }
+            case BINDER_LIB_TEST_GET_SCHEDULING_POLICY: {
+                int policy = 0;
+                sched_param param;
+                if (0 != pthread_getschedparam(pthread_self(), &policy, &param)) {
+                    return UNKNOWN_ERROR;
+                }
+                reply->writeInt32(policy);
+                reply->writeInt32(param.sched_priority);
+                return NO_ERROR;
+            }
             case BINDER_LIB_TEST_ECHO_VECTOR: {
                 std::vector<uint64_t> vector;
                 auto err = data.readUint64Vector(&vector);
@@ -1407,6 +1489,8 @@
     {
         sp<BinderLibTestService> testService = new BinderLibTestService(index);
 
+        testService->setMinSchedulerPolicy(kSchedPolicy, kSchedPriority);
+
         /*
          * Normally would also contain functionality as well, but we are only
          * testing the extension mechanism.
diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp
index 6ec1f47..516b080 100644
--- a/libs/gui/Android.bp
+++ b/libs/gui/Android.bp
@@ -38,12 +38,8 @@
     ],
 }
 
-cc_library_shared {
-    name: "libgui",
-    vendor_available: false,
-    vndk: {
-        enabled: true,
-    },
+cc_defaults {
+    name: "libgui_defaults",
     double_loadable: true,
 
     defaults: ["libgui_bufferqueue-defaults"],
@@ -273,4 +269,19 @@
     ],
 }
 
+cc_library_shared {
+    name: "libgui",
+    vendor_available: false,
+    vndk: {
+        enabled: true,
+    },
+    defaults: ["libgui_defaults"]
+}
+
+cc_library_shared {
+    name: "libgui_vendor",
+    vendor: true,
+    defaults: ["libgui_defaults"]
+}
+
 subdirs = ["tests"]
diff --git a/libs/gui/BitTube.cpp b/libs/gui/BitTube.cpp
index ef7a6f5..351af65 100644
--- a/libs/gui/BitTube.cpp
+++ b/libs/gui/BitTube.cpp
@@ -86,6 +86,10 @@
     mReceiveFd = std::move(receiveFd);
 }
 
+void BitTube::setSendFd(base::unique_fd&& sendFd) {
+    mSendFd = std::move(sendFd);
+}
+
 ssize_t BitTube::write(void const* vaddr, size_t size) {
     ssize_t err, len;
     do {
@@ -115,6 +119,11 @@
 
     status_t result = reply->writeDupFileDescriptor(mReceiveFd);
     mReceiveFd.reset();
+    if (result != NO_ERROR) {
+        return result;
+    }
+    result = reply->writeDupFileDescriptor(mSendFd);
+    mSendFd.reset();
     return result;
 }
 
@@ -126,6 +135,13 @@
         ALOGE("BitTube::readFromParcel: can't dup file descriptor (%s)", strerror(error));
         return -error;
     }
+    mSendFd.reset(dup(parcel->readFileDescriptor()));
+    if (mSendFd < 0) {
+        mSendFd.reset();
+        int error = errno;
+        ALOGE("BitTube::readFromParcel: can't dup file descriptor (%s)", strerror(error));
+        return -error;
+    }
     return NO_ERROR;
 }
 
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index da6143c..5e55d6b 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -17,6 +17,7 @@
 #include <inttypes.h>
 #include <pwd.h>
 #include <sys/types.h>
+#include <cutils/properties.h>
 
 #define LOG_TAG "BufferQueueConsumer"
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
@@ -71,7 +72,9 @@
 BufferQueueConsumer::BufferQueueConsumer(const sp<BufferQueueCore>& core) :
     mCore(core),
     mSlots(core->mSlots),
-    mConsumerName() {}
+    mConsumerName() {
+    mPreRendering = property_get_bool("ro.vendor.perf.scroll_opt", false);
+}
 
 BufferQueueConsumer::~BufferQueueConsumer() {}
 
@@ -136,7 +139,21 @@
             // the timestamps are being auto-generated by Surface. If the app isn't
             // generating timestamps explicitly, it probably doesn't want frames to
             // be discarded based on them.
-            while (mCore->mQueue.size() > 1 && !mCore->mQueue[0].mIsAutoTimestamp) {
+            while (mCore->mQueue.size() > 1 && (!mCore->mQueue[0].mIsAutoTimestamp
+                    || mPreRendering)) {
+                if (mPreRendering) {
+                    // pre-rendering feature is enabled
+                    const BufferItem& latestItem(mCore->mQueue[mCore->mQueue.size()-1]);
+                    if (!mCore->mQueue[0].mIsAutoTimestamp &&
+                            latestItem.mIsAutoTimestamp) {
+                        break;
+                    }
+                    if (mCore->mQueue[0].mIsAutoTimestamp &&
+                            mCore->mQueue[1].mIsAutoTimestamp) {
+                        break;
+                    }
+                }
+
                 const BufferItem& bufferItem(mCore->mQueue[1]);
 
                 // If dropping entry[0] would leave us with a buffer that the
diff --git a/libs/gui/DisplayEventDispatcher.cpp b/libs/gui/DisplayEventDispatcher.cpp
index b33bc9e..682fe91 100644
--- a/libs/gui/DisplayEventDispatcher.cpp
+++ b/libs/gui/DisplayEventDispatcher.cpp
@@ -89,12 +89,8 @@
     return OK;
 }
 
-void DisplayEventDispatcher::requestLatestConfig() {
-    status_t status = mReceiver.requestLatestConfig();
-    if (status) {
-        ALOGW("Failed enable config events, status=%d", status);
-        return;
-    }
+void DisplayEventDispatcher::injectEvent(const DisplayEventReceiver::Event& event) {
+    mReceiver.sendEvents(&event, 1);
 }
 
 int DisplayEventDispatcher::getFd() const {
@@ -157,6 +153,9 @@
                     dispatchConfigChanged(ev.header.timestamp, ev.header.displayId,
                                           ev.config.configId, ev.config.vsyncPeriod);
                     break;
+                case DisplayEventReceiver::DISPLAY_EVENT_NULL:
+                    dispatchNullEvent(ev.header.timestamp, ev.header.displayId);
+                    break;
                 default:
                     ALOGW("dispatcher %p ~ ignoring unknown event type %#x", this, ev.header.type);
                     break;
@@ -168,4 +167,5 @@
     }
     return gotVsync;
 }
+
 } // namespace android
diff --git a/libs/gui/DisplayEventReceiver.cpp b/libs/gui/DisplayEventReceiver.cpp
index 1fed509..f2b0962 100644
--- a/libs/gui/DisplayEventReceiver.cpp
+++ b/libs/gui/DisplayEventReceiver.cpp
@@ -79,14 +79,6 @@
     return NO_INIT;
 }
 
-status_t DisplayEventReceiver::requestLatestConfig() {
-    if (mEventConnection != nullptr) {
-        mEventConnection->requestLatestConfig();
-        return NO_ERROR;
-    }
-    return NO_INIT;
-}
-
 ssize_t DisplayEventReceiver::getEvents(DisplayEventReceiver::Event* events,
         size_t count) {
     return DisplayEventReceiver::getEvents(mDataChannel.get(), events, count);
@@ -98,6 +90,10 @@
     return gui::BitTube::recvObjects(dataChannel, events, count);
 }
 
+ssize_t DisplayEventReceiver::sendEvents(Event const* events, size_t count) {
+    return DisplayEventReceiver::sendEvents(mDataChannel.get(), events, count);
+}
+
 ssize_t DisplayEventReceiver::sendEvents(gui::BitTube* dataChannel,
         Event const* events, size_t count)
 {
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index e2ea3f9..b2a5f6b 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -382,6 +382,10 @@
     newTimestamps.requestedPresentTime = newEntry.requestedPresentTime;
     newTimestamps.acquireFence = newEntry.acquireFence;
     newTimestamps.valid = true;
+    if (mQueueOffset >= MAX_FRAME_HISTORY) {
+        ALOGE_IF(mProducerWantsEvents, "addQueue: QueueOffset is out of bound");
+        return;
+    }
     mFrames[mQueueOffset] = newTimestamps;
 
     // Note: We avoid sending the acquire fence back to the caller since
diff --git a/libs/gui/IDisplayEventConnection.cpp b/libs/gui/IDisplayEventConnection.cpp
index aa74bfd..c0e246f 100644
--- a/libs/gui/IDisplayEventConnection.cpp
+++ b/libs/gui/IDisplayEventConnection.cpp
@@ -26,8 +26,7 @@
     STEAL_RECEIVE_CHANNEL = IBinder::FIRST_CALL_TRANSACTION,
     SET_VSYNC_RATE,
     REQUEST_NEXT_VSYNC,
-    REQUEST_LATEST_CONFIG,
-    LAST = REQUEST_LATEST_CONFIG,
+    LAST = REQUEST_NEXT_VSYNC,
 };
 
 } // Anonymous namespace
@@ -54,11 +53,6 @@
         callRemoteAsync<decltype(&IDisplayEventConnection::requestNextVsync)>(
                 Tag::REQUEST_NEXT_VSYNC);
     }
-
-    void requestLatestConfig() override {
-        callRemoteAsync<decltype(&IDisplayEventConnection::requestLatestConfig)>(
-                Tag::REQUEST_LATEST_CONFIG);
-    }
 };
 
 // Out-of-line virtual method definition to trigger vtable emission in this translation unit (see
@@ -80,8 +74,6 @@
             return callLocal(data, reply, &IDisplayEventConnection::setVsyncRate);
         case Tag::REQUEST_NEXT_VSYNC:
             return callLocalAsync(data, reply, &IDisplayEventConnection::requestNextVsync);
-        case Tag::REQUEST_LATEST_CONFIG:
-            return callLocalAsync(data, reply, &IDisplayEventConnection::requestLatestConfig);
     }
 }
 
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index cf269b3..4477740 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -155,6 +155,16 @@
     return mNextFrameNumber;
 }
 
+bool Surface::isBufferAccumulated() const {
+    Mutex::Autolock lock(mMutex);
+    return mIsBufferAccumulated;
+}
+
+void Surface::setPresentTimeMode(int mode) {
+    Mutex::Autolock lock(mMutex);
+    mPresentTimeMode = mode;
+}
+
 String8 Surface::getConsumerName() const {
     return mGraphicBufferProducer->getConsumerName();
 }
@@ -732,6 +742,8 @@
         mSharedBufferHasBeenQueued = false;
     }
 
+    mDequeuedSlots.insert(buf);
+
     return OK;
 }
 
@@ -760,6 +772,8 @@
         mSharedBufferHasBeenQueued = true;
     }
 
+    mDequeuedSlots.erase(i);
+
     return OK;
 }
 
@@ -895,6 +909,8 @@
         ALOGE("queueBuffer: error queuing buffer to SurfaceTexture, %d", err);
     }
 
+    mDequeuedSlots.erase(i);
+
     if (mEnableFrameTimestamps) {
         mFrameEventHistory->applyDelta(output.frameTimestamps);
         // Update timestamps with the local acquire fence.
@@ -921,6 +937,7 @@
     }
 
     mConsumerRunningBehind = (output.numPendingBuffers >= 2);
+    mIsBufferAccumulated = mConsumerRunningBehind;
 
     if (!mConnectedToCpu) {
         // Clear surface damage back to full-buffer
@@ -970,6 +987,9 @@
     { // scope for the lock
         Mutex::Autolock lock(mMutex);
         switch (what) {
+            case NATIVE_WINDOW_PRESENT_TIME_MODE:
+                *value = mPresentTimeMode;
+                return NO_ERROR;
             case NATIVE_WINDOW_FORMAT:
                 if (mReqFormat) {
                     *value = static_cast<int>(mReqFormat);
@@ -1660,6 +1680,7 @@
         mRemovedBuffers.push_back(mSlots[attachedSlot].buffer);
     }
     mSlots[attachedSlot].buffer = graphicBuffer;
+    mDequeuedSlots.insert(attachedSlot);
 
     return NO_ERROR;
 }
@@ -1926,6 +1947,10 @@
 }
 
 void Surface::freeAllBuffers() {
+    if (!mDequeuedSlots.empty()) {
+        ALOGE("%s: %zu buffers were freed while being dequeued!",
+                __FUNCTION__, mDequeuedSlots.size());
+    }
     for (int i = 0; i < NUM_BUFFER_SLOTS; i++) {
         mSlots[i].buffer = nullptr;
     }
@@ -1947,6 +1972,10 @@
             ALOGW("%s: Discarded slot %d doesn't contain buffer!", __FUNCTION__, i);
             continue;
         }
+        // Don't flush currently dequeued buffers
+        if (mDequeuedSlots.count(i) > 0) {
+            continue;
+        }
         outBuffers->push_back(mSlots[i].buffer);
         mSlots[i].buffer = nullptr;
     }
diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp
index a332a1f..8f0ebc7 100644
--- a/libs/gui/SurfaceControl.cpp
+++ b/libs/gui/SurfaceControl.cpp
@@ -39,6 +39,8 @@
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SurfaceControl.h>
 
+#include "dlfcn.h"
+
 namespace android {
 
 // ============================================================================
@@ -195,6 +197,5 @@
                               handle.get(), interface_cast<IGraphicBufferProducer>(gbp),
                                transformHint);
 }
-
 // ----------------------------------------------------------------------------
 }; // namespace android
diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h
index 7db69ec..7fb5b8d 100644
--- a/libs/gui/include/gui/BufferQueueConsumer.h
+++ b/libs/gui/include/gui/BufferQueueConsumer.h
@@ -184,6 +184,9 @@
     // It's updated during setConsumerName.
     String8 mConsumerName;
 
+    // Value used to show whether pre-rendering feature is enabled or not
+    bool mPreRendering;
+
 }; // class BufferQueueConsumer
 
 } // namespace android
diff --git a/libs/gui/include/gui/DisplayEventDispatcher.h b/libs/gui/include/gui/DisplayEventDispatcher.h
index f210c34..eb5b004 100644
--- a/libs/gui/include/gui/DisplayEventDispatcher.h
+++ b/libs/gui/include/gui/DisplayEventDispatcher.h
@@ -31,7 +31,7 @@
     status_t initialize();
     void dispose();
     status_t scheduleVsync();
-    void requestLatestConfig();
+    void injectEvent(const DisplayEventReceiver::Event& event);
     int getFd() const;
     virtual int handleEvent(int receiveFd, int events, void* data);
 
@@ -48,6 +48,9 @@
                                  bool connected) = 0;
     virtual void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId,
                                        int32_t configId, nsecs_t vsyncPeriod) = 0;
+    // AChoreographer-specific hook for processing null-events so that looper
+    // can be properly poked.
+    virtual void dispatchNullEvent(nsecs_t timestamp, PhysicalDisplayId displayId) = 0;
 
     bool processPendingEvents(nsecs_t* outTimestamp, PhysicalDisplayId* outDisplayId,
                               uint32_t* outCount);
diff --git a/libs/gui/include/gui/DisplayEventReceiver.h b/libs/gui/include/gui/DisplayEventReceiver.h
index 8d49184..0e10d1a 100644
--- a/libs/gui/include/gui/DisplayEventReceiver.h
+++ b/libs/gui/include/gui/DisplayEventReceiver.h
@@ -53,6 +53,7 @@
         DISPLAY_EVENT_VSYNC = fourcc('v', 's', 'y', 'n'),
         DISPLAY_EVENT_HOTPLUG = fourcc('p', 'l', 'u', 'g'),
         DISPLAY_EVENT_CONFIG_CHANGED = fourcc('c', 'o', 'n', 'f'),
+        DISPLAY_EVENT_NULL = fourcc('n', 'u', 'l', 'l'),
     };
 
     struct Event {
@@ -130,6 +131,7 @@
      * sendEvents write events to the queue and returns how many events were
      * written.
      */
+    ssize_t sendEvents(Event const* events, size_t count);
     static ssize_t sendEvents(gui::BitTube* dataChannel, Event const* events, size_t count);
 
     /*
@@ -146,12 +148,6 @@
      */
     status_t requestNextVsync();
 
-    /*
-     * requestLatestConfig() force-requests the current config for the primary
-     * display.
-     */
-    status_t requestLatestConfig();
-
 private:
     sp<IDisplayEventConnection> mEventConnection;
     std::unique_ptr<gui::BitTube> mDataChannel;
diff --git a/libs/gui/include/gui/IDisplayEventConnection.h b/libs/gui/include/gui/IDisplayEventConnection.h
index 674aafd..cff22a3 100644
--- a/libs/gui/include/gui/IDisplayEventConnection.h
+++ b/libs/gui/include/gui/IDisplayEventConnection.h
@@ -51,11 +51,6 @@
      * requestNextVsync() schedules the next vsync event. It has no effect if the vsync rate is > 0.
      */
     virtual void requestNextVsync() = 0; // Asynchronous
-
-    /*
-     * requestLatestConfig() requests the config for the primary display.
-     */
-    virtual void requestLatestConfig() = 0; // Asynchronous
 };
 
 class BnDisplayEventConnection : public SafeBnInterface<IDisplayEventConnection> {
diff --git a/libs/gui/include/gui/LayerMetadata.h b/libs/gui/include/gui/LayerMetadata.h
index d58e019..1132ec9 100644
--- a/libs/gui/include/gui/LayerMetadata.h
+++ b/libs/gui/include/gui/LayerMetadata.h
@@ -27,6 +27,7 @@
     METADATA_WINDOW_TYPE = 2,
     METADATA_TASK_ID = 3,
     METADATA_MOUSE_CURSOR = 4,
+    METADATA_WINDOW_TYPE_DONT_SCREENSHOT = 5,
 };
 
 struct LayerMetadata : public Parcelable {
diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h
index 49c83da..083f36c 100644
--- a/libs/gui/include/gui/Surface.h
+++ b/libs/gui/include/gui/Surface.h
@@ -30,6 +30,7 @@
 #include <utils/RefBase.h>
 
 #include <shared_mutex>
+#include <unordered_set>
 
 namespace android {
 
@@ -132,6 +133,9 @@
     // See IGraphicBufferProducer::getNextFrameNumber
     uint64_t getNextFrameNumber() const;
 
+    bool isBufferAccumulated() const;
+    void setPresentTimeMode(int mode);
+
     /* Set the scaling mode to be used with a Surface.
      * See NATIVE_WINDOW_SET_SCALING_MODE and its parameters
      * in <system/window.h>. */
@@ -530,6 +534,9 @@
     uint64_t mNextFrameNumber = 1;
     uint64_t mLastFrameNumber = 0;
 
+    bool mIsBufferAccumulated = false;
+    int mPresentTimeMode = -1;
+
     // Mutable because ANativeWindow::query needs this class const.
     mutable bool mQueriedSupportedTimestamps;
     mutable bool mFrameTimestampsSupportsPresent;
@@ -543,8 +550,15 @@
     int mMaxBufferCount;
 
     sp<IProducerListener> mListenerProxy;
+
+    // Get and flush the buffers of given slots, if the buffer in the slot
+    // is currently dequeued then it won't be flushed and won't be returned
+    // in outBuffers.
     status_t getAndFlushBuffersFromSlots(const std::vector<int32_t>& slots,
             std::vector<sp<GraphicBuffer>>* outBuffers);
+
+    // Buffers that are successfully dequeued/attached and handed to clients
+    std::unordered_set<int> mDequeuedSlots;
 };
 
 } // namespace android
diff --git a/libs/gui/include/private/gui/BitTube.h b/libs/gui/include/private/gui/BitTube.h
index 13c0162..8048518 100644
--- a/libs/gui/include/private/gui/BitTube.h
+++ b/libs/gui/include/private/gui/BitTube.h
@@ -58,6 +58,9 @@
     // resets this BitTube's receive file descriptor to receiveFd
     void setReceiveFd(base::unique_fd&& receiveFd);
 
+    // resets this BitTube's send file descriptor to sendFd
+    void setSendFd(base::unique_fd&& sendFd);
+
     // send objects (sized blobs). All objects are guaranteed to be written or the call fails.
     template <typename T>
     static ssize_t sendObjects(BitTube* tube, T const* events, size_t count) {
@@ -85,7 +88,7 @@
     // the message, excess data is silently discarded.
     ssize_t read(void* vaddr, size_t size);
 
-    base::unique_fd mSendFd;
+    mutable base::unique_fd mSendFd;
     mutable base::unique_fd mReceiveFd;
 
     static ssize_t sendObjects(BitTube* tube, void const* events, size_t count, size_t objSize);
diff --git a/libs/gui/tests/EndToEndNativeInputTest.cpp b/libs/gui/tests/EndToEndNativeInputTest.cpp
index e3f4798..8623bf7 100644
--- a/libs/gui/tests/EndToEndNativeInputTest.cpp
+++ b/libs/gui/tests/EndToEndNativeInputTest.cpp
@@ -152,7 +152,11 @@
 
         InputEvent *ev;
         uint32_t seqId;
-        status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev);
+        int motionEventType;
+        int touchMoveNumber;
+        bool flag;
+        status_t consumed = mInputConsumer->consume(&mInputEventFactory, true, -1, &seqId, &ev,
+                                                    &motionEventType, &touchMoveNumber, &flag);
         if (consumed != OK) {
             return nullptr;
         }
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 11af23e..7b8dfb0 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -609,7 +609,8 @@
 }
 
 status_t InputConsumer::consume(InputEventFactoryInterface* factory, bool consumeBatches,
-                                nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
+                                nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent,
+                                int* motionEventType, int* touchMoveNumber, bool* flag) {
     if (DEBUG_TRANSPORT_ACTIONS) {
         ALOGD("channel '%s' consumer ~ consume: consumeBatches=%s, frameTime=%" PRId64,
               mChannel->getName().c_str(), toString(consumeBatches), frameTime);
@@ -628,10 +629,20 @@
         } else {
             // Receive a fresh message.
             status_t result = mChannel->receiveMessage(&mMsg);
+            if (result == 0) {
+                if ((mMsg.body.motion.action & AMOTION_EVENT_ACTION_MASK) == AMOTION_EVENT_ACTION_MOVE){
+                    mTouchMoveCounter++;
+                } else {
+                    mTouchMoveCounter = 0;
+                }
+                *flag = true;
+            }
+            *motionEventType = mMsg.body.motion.action & AMOTION_EVENT_ACTION_MASK;
+            *touchMoveNumber = mTouchMoveCounter;
             if (result) {
                 // Consume the next batched event unless batches are being held for later.
                 if (consumeBatches || result != WOULD_BLOCK) {
-                    result = consumeBatch(factory, frameTime, outSeq, outEvent);
+                    result = consumeBatch(factory, frameTime, outSeq, outEvent, touchMoveNumber);
                     if (*outEvent) {
                         if (DEBUG_TRANSPORT_ACTIONS) {
                             ALOGD("channel '%s' consumer ~ consumed batch event, seq=%u",
@@ -748,7 +759,7 @@
 }
 
 status_t InputConsumer::consumeBatch(InputEventFactoryInterface* factory,
-        nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent) {
+        nsecs_t frameTime, uint32_t* outSeq, InputEvent** outEvent, int* touchMoveNumber) {
     status_t result;
     for (size_t i = mBatches.size(); i > 0; ) {
         i--;
@@ -760,7 +771,7 @@
         }
 
         nsecs_t sampleTime = frameTime;
-        if (mResampleTouch) {
+        if (mResampleTouch && (*touchMoveNumber != 1)) {
             sampleTime -= RESAMPLE_LATENCY;
         }
         ssize_t split = findSampleNoLaterThan(batch, sampleTime);
diff --git a/libs/input/tests/InputPublisherAndConsumer_test.cpp b/libs/input/tests/InputPublisherAndConsumer_test.cpp
index 8e2eec8..3f41b52 100644
--- a/libs/input/tests/InputPublisherAndConsumer_test.cpp
+++ b/libs/input/tests/InputPublisherAndConsumer_test.cpp
@@ -97,7 +97,11 @@
 
     uint32_t consumeSeq;
     InputEvent* event;
-    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
+    int motionEventType;
+    int touchMoveNumber;
+    bool flag;
+    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
+                                &motionEventType, &touchMoveNumber, &flag);
     ASSERT_EQ(OK, status)
             << "consumer consume should return OK";
 
@@ -196,7 +200,11 @@
 
     uint32_t consumeSeq;
     InputEvent* event;
-    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
+    int motionEventType;
+    int touchMoveNumber;
+    bool flag;
+    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
+                                &motionEventType, &touchMoveNumber, &flag);
     ASSERT_EQ(OK, status)
             << "consumer consume should return OK";
 
@@ -290,7 +298,11 @@
 
     uint32_t consumeSeq;
     InputEvent* event;
-    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event);
+    int motionEventType;
+    int touchMoveNumber;
+    bool flag;
+    status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq, &event,
+                                &motionEventType, &touchMoveNumber, &flag);
     ASSERT_EQ(OK, status) << "consumer consume should return OK";
 
     ASSERT_TRUE(event != nullptr) << "consumer should have returned non-NULL event";
diff --git a/libs/nativedisplay/AChoreographer.cpp b/libs/nativedisplay/AChoreographer.cpp
index e458b2e..f6a95ce 100644
--- a/libs/nativedisplay/AChoreographer.cpp
+++ b/libs/nativedisplay/AChoreographer.cpp
@@ -136,6 +136,7 @@
     void dispatchHotplug(nsecs_t timestamp, PhysicalDisplayId displayId, bool connected) override;
     void dispatchConfigChanged(nsecs_t timestamp, PhysicalDisplayId displayId, int32_t configId,
                                nsecs_t vsyncPeriod) override;
+    void dispatchNullEvent(nsecs_t, PhysicalDisplayId) override;
 
     void scheduleCallbacks();
 
@@ -170,7 +171,7 @@
 
 Choreographer::Choreographer(const sp<Looper>& looper)
       : DisplayEventDispatcher(looper, ISurfaceComposer::VsyncSource::eVsyncSourceApp,
-                               ISurfaceComposer::ConfigChanged::eConfigChangedDispatch),
+                               ISurfaceComposer::ConfigChanged::eConfigChangedSuppress),
         mLooper(looper),
         mThreadId(std::this_thread::get_id()) {
     std::lock_guard<std::mutex> _l(gChoreographers.lock);
@@ -294,8 +295,14 @@
     } else {
         // If the looper thread is detached from Choreographer, then refresh rate
         // changes will be handled in AChoreographer_handlePendingEvents, so we
-        // need to redispatch a config from SF
-        requestLatestConfig();
+        // need to wake up the looper thread by writing to the write-end of the
+        // socket the looper is listening on.
+        // Fortunately, these events are small so sending packets across the
+        // socket should be atomic across processes.
+        DisplayEventReceiver::Event event;
+        event.header = DisplayEventReceiver::Event::Header{DisplayEventReceiver::DISPLAY_EVENT_NULL,
+                                                           PhysicalDisplayId(0), systemTime()};
+        injectEvent(event);
     }
 }
 
@@ -374,28 +381,15 @@
 // displays. When multi-display choreographer is properly supported, then
 // PhysicalDisplayId should no longer be ignored.
 void Choreographer::dispatchConfigChanged(nsecs_t, PhysicalDisplayId displayId, int32_t configId,
-                                          nsecs_t vsyncPeriod) {
+                                          nsecs_t) {
     ALOGV("choreographer %p ~ received config change event "
           "(displayId=%" ANDROID_PHYSICAL_DISPLAY_ID_FORMAT ", configId=%d).",
           this, displayId, configId);
+}
 
-    const nsecs_t lastPeriod = mLatestVsyncPeriod;
-    std::vector<RefreshRateCallback> callbacks{};
-    {
-        std::lock_guard<std::mutex> _l{mLock};
-        for (auto& cb : mRefreshRateCallbacks) {
-            callbacks.push_back(cb);
-            cb.firstCallbackFired = true;
-        }
-    }
-
-    for (auto& cb : callbacks) {
-        if (!cb.firstCallbackFired || (vsyncPeriod > 0 && vsyncPeriod != lastPeriod)) {
-            cb.callback(vsyncPeriod, cb.data);
-        }
-    }
-
-    mLatestVsyncPeriod = vsyncPeriod;
+void Choreographer::dispatchNullEvent(nsecs_t, PhysicalDisplayId) {
+    ALOGV("choreographer %p ~ received null event.", this);
+    handleRefreshRateUpdates();
 }
 
 void Choreographer::handleMessage(const Message& message) {
diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h
index b78fc5d..3644f24 100644
--- a/libs/nativewindow/include/system/window.h
+++ b/libs/nativewindow/include/system/window.h
@@ -63,6 +63,9 @@
 
 /* attributes queriable with query() */
 enum {
+    /* Get the mode whether to set present time when queueBuffer */
+    NATIVE_WINDOW_PRESENT_TIME_MODE = -1,
+
     NATIVE_WINDOW_WIDTH = 0,
     NATIVE_WINDOW_HEIGHT = 1,
     NATIVE_WINDOW_FORMAT = 2,
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 92e7e71..0285c2f 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -409,6 +409,23 @@
     mImageManager = std::make_unique<ImageManager>(this);
     mImageManager->initThread();
     mDrawingBuffer = createFramebuffer();
+    sp<GraphicBuffer> buf =
+            new GraphicBuffer(1, 1, PIXEL_FORMAT_RGBA_8888, 1,
+                              GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_TEXTURE, "placeholder");
+
+    const status_t err = buf->initCheck();
+    if (err != OK) {
+        ALOGE("Error allocating placeholder buffer: %d", err);
+        return;
+    }
+    mPlaceholderBuffer = buf.get();
+    EGLint attributes[] = {
+            EGL_NONE,
+    };
+    mPlaceholderImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
+                                          mPlaceholderBuffer, attributes);
+    ALOGE_IF(mPlaceholderImage == EGL_NO_IMAGE_KHR, "Failed to create placeholder image: %#x",
+             eglGetError());
 }
 
 GLESRenderEngine::~GLESRenderEngine() {
@@ -423,6 +440,7 @@
         eglDestroyImageKHR(mEGLDisplay, expired);
         DEBUG_EGL_IMAGE_TRACKER_DESTROY();
     }
+    eglDestroyImageKHR(mEGLDisplay, mPlaceholderImage);
     mImageCache.clear();
     eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
     eglTerminate(mEGLDisplay);
@@ -589,6 +607,9 @@
 }
 
 void GLESRenderEngine::deleteTextures(size_t count, uint32_t const* names) {
+    for (int i = 0; i < count; ++i) {
+        mTextureView.erase(names[i]);
+    }
     glDeleteTextures(count, names);
 }
 
@@ -646,6 +667,7 @@
         }
 
         bindExternalTextureImage(texName, *cachedImage->second);
+        mTextureView.insert_or_assign(texName, buffer->getId());
     }
 
     // Wait for the new buffer to be ready.
@@ -887,7 +909,7 @@
     glBindFramebuffer(GL_FRAMEBUFFER, 0);
 }
 
-bool GLESRenderEngine::cleanupPostRender() {
+bool GLESRenderEngine::cleanupPostRender(CleanupMode mode) {
     ATRACE_CALL();
 
     if (mPriorResourcesCleaned ||
@@ -896,6 +918,30 @@
         return false;
     }
 
+    // This is a bit of a band-aid fix for FrameCaptureProcessor, as we should
+    // not need to keep memory around if we don't need to do so.
+    if (mode == CleanupMode::CLEAN_ALL) {
+        // TODO: SurfaceFlinger memory utilization may benefit from resetting
+        // texture bindings as well. Assess if it does and there's no performance regression
+        // when rebinding the same image data to the same texture, and if so then its mode
+        // behavior can be tweaked.
+        if (mPlaceholderImage != EGL_NO_IMAGE_KHR) {
+            for (auto [textureName, bufferId] : mTextureView) {
+                if (bufferId && mPlaceholderImage != EGL_NO_IMAGE_KHR) {
+                    glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureName);
+                    glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES,
+                                                 static_cast<GLeglImageOES>(mPlaceholderImage));
+                    mTextureView[textureName] = std::nullopt;
+                    checkErrors();
+                }
+            }
+        }
+        {
+            std::lock_guard<std::mutex> lock(mRenderingMutex);
+            mImageCache.clear();
+        }
+    }
+
     // Bind the texture to dummy data so that backing image data can be freed.
     GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(getFramebufferForDrawing());
     glFramebuffer->allocateBuffers(1, 1, mPlaceholderDrawBuffer);
@@ -1616,6 +1662,16 @@
     return cachedImage != mImageCache.end();
 }
 
+bool GLESRenderEngine::isTextureNameKnownForTesting(uint32_t texName) {
+    const auto& entry = mTextureView.find(texName);
+    return entry != mTextureView.end();
+}
+
+std::optional<uint64_t> GLESRenderEngine::getBufferIdForTextureNameForTesting(uint32_t texName) {
+    const auto& entry = mTextureView.find(texName);
+    return entry != mTextureView.end() ? entry->second : std::nullopt;
+}
+
 bool GLESRenderEngine::isFramebufferImageCachedForTesting(uint64_t bufferId) {
     std::lock_guard<std::mutex> lock(mFramebufferImageCacheMutex);
     return std::any_of(mFramebufferImageCache.cbegin(), mFramebufferImageCache.cend(),
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 42b8537..d5254a8 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -75,7 +75,7 @@
                         const std::vector<const LayerSettings*>& layers,
                         ANativeWindowBuffer* buffer, const bool useFramebufferCache,
                         base::unique_fd&& bufferFence, base::unique_fd* drawFence) override;
-    bool cleanupPostRender() override;
+    bool cleanupPostRender(CleanupMode mode) override;
 
     EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
     // Creates an output image for rendering to
@@ -86,6 +86,12 @@
     // Test-only methods
     // Returns true iff mImageCache contains an image keyed by bufferId
     bool isImageCachedForTesting(uint64_t bufferId) EXCLUDES(mRenderingMutex);
+    // Returns true iff texName was previously generated by RenderEngine and was
+    // not destroyed.
+    bool isTextureNameKnownForTesting(uint32_t texName);
+    // Returns the buffer ID of the content bound to texName, or nullopt if no
+    // such mapping exists.
+    std::optional<uint64_t> getBufferIdForTextureNameForTesting(uint32_t texName);
     // Returns true iff mFramebufferImageCache contains an image keyed by bufferId
     bool isFramebufferImageCachedForTesting(uint64_t bufferId)
             EXCLUDES(mFramebufferImageCacheMutex);
@@ -224,6 +230,8 @@
 
     // Cache of GL images that we'll store per GraphicBuffer ID
     std::unordered_map<uint64_t, std::unique_ptr<Image>> mImageCache GUARDED_BY(mRenderingMutex);
+    std::unordered_map<uint32_t, std::optional<uint64_t>> mTextureView;
+
     // Mutex guarding rendering operations, so that:
     // 1. GL operations aren't interleaved, and
     // 2. Internal state related to rendering that is potentially modified by
@@ -237,6 +245,11 @@
     // ensure that we align on a word. Allocating 16 bytes will provide a
     // guarantee that we don't clobber memory.
     uint32_t mPlaceholderDrawBuffer[4];
+    // Placeholder buffer and image, similar to mPlaceholderDrawBuffer, but
+    // instead these are intended for cleaning up texture memory with the
+    // GL_TEXTURE_EXTERNAL_OES target.
+    ANativeWindowBuffer* mPlaceholderBuffer = nullptr;
+    EGLImage mPlaceholderImage = EGL_NO_IMAGE_KHR;
     sp<Fence> mLastDrawFence;
     // Store a separate boolean checking if prior resources were cleaned up, as
     // devices that don't support native sync fences can't rely on a last draw
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index e06e128..a111247 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -111,14 +111,25 @@
     // Returns NO_ERROR when binds successfully, NO_MEMORY when there's no memory for allocation.
     virtual status_t bindFrameBuffer(Framebuffer* framebuffer) = 0;
     virtual void unbindFrameBuffer(Framebuffer* framebuffer) = 0;
+
+    enum class CleanupMode {
+        CLEAN_OUTPUT_RESOURCES,
+        CLEAN_ALL,
+    };
     // Clean-up method that should be called on the main thread after the
     // drawFence returned by drawLayers fires. This method will free up
     // resources used by the most recently drawn frame. If the frame is still
     // being drawn, then this call is silently ignored.
     //
+    // If mode is CLEAN_OUTPUT_RESOURCES, then only resources related to the
+    // output framebuffer are cleaned up, including the sibling texture.
+    //
+    // If mode is CLEAN_ALL, then we also cleanup resources related to any input
+    // buffers.
+    //
     // Returns true if resources were cleaned up, and false if we didn't need to
     // do any work.
-    virtual bool cleanupPostRender() = 0;
+    virtual bool cleanupPostRender(CleanupMode mode = CleanupMode::CLEAN_OUTPUT_RESOURCES) = 0;
 
     // queries
     virtual size_t getMaxTextureSize() const = 0;
@@ -131,7 +142,7 @@
     virtual bool isProtected() const = 0;
     virtual bool supportsProtectedContent() const = 0;
     virtual bool useProtectedContext(bool useProtectedContext) = 0;
-
+    virtual void setViewportAndProjection(Rect viewPort, Rect sourceCrop) =0;
     // Renders layers for a particular display via GPU composition. This method
     // should be called for every display that needs to be rendered via the GPU.
     // @param display The display-wide settings that should be applied prior to
diff --git a/libs/renderengine/include/renderengine/mock/RenderEngine.h b/libs/renderengine/include/renderengine/mock/RenderEngine.h
index df0f17a..0a80170 100644
--- a/libs/renderengine/include/renderengine/mock/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/mock/RenderEngine.h
@@ -56,7 +56,9 @@
     MOCK_CONST_METHOD0(isProtected, bool());
     MOCK_CONST_METHOD0(supportsProtectedContent, bool());
     MOCK_METHOD1(useProtectedContext, bool(bool));
-    MOCK_METHOD0(cleanupPostRender, bool());
+    MOCK_METHOD2(setViewportAndProjection,
+                 void(Rect,  Rect));
+    MOCK_METHOD1(cleanupPostRender, bool(CleanupMode mode));
     MOCK_METHOD6(drawLayers,
                  status_t(const DisplaySettings&, const std::vector<const LayerSettings*>&,
                           ANativeWindowBuffer*, const bool, base::unique_fd&&, base::unique_fd*));
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 16a8a0d..f577eb3 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -81,6 +81,7 @@
         }
         for (uint32_t texName : mTexNames) {
             sRE->deleteTextures(1, &texName);
+            EXPECT_FALSE(sRE->isTextureNameKnownForTesting(texName));
         }
     }
 
@@ -1424,10 +1425,44 @@
     if (fd >= 0) {
         sync_wait(fd, -1);
     }
-
     // Only cleanup the first time.
-    EXPECT_TRUE(sRE->cleanupPostRender());
-    EXPECT_FALSE(sRE->cleanupPostRender());
+    EXPECT_TRUE(sRE->cleanupPostRender(
+            renderengine::RenderEngine::CleanupMode::CLEAN_OUTPUT_RESOURCES));
+    EXPECT_FALSE(sRE->cleanupPostRender(
+            renderengine::RenderEngine::CleanupMode::CLEAN_OUTPUT_RESOURCES));
+}
+
+TEST_F(RenderEngineTest, cleanupPostRender_whenCleaningAll_replacesTextureMemory) {
+    renderengine::DisplaySettings settings;
+    settings.physicalDisplay = fullscreenRect();
+    settings.clip = fullscreenRect();
+
+    std::vector<const renderengine::LayerSettings*> layers;
+    renderengine::LayerSettings layer;
+    layer.geometry.boundaries = fullscreenRect().toFloatRect();
+    BufferSourceVariant<ForceOpaqueBufferVariant>::fillColor(layer, 1.0f, 0.0f, 0.0f, this);
+    layer.alpha = 1.0;
+    layers.push_back(&layer);
+
+    base::unique_fd fence;
+    sRE->drawLayers(settings, layers, mBuffer->getNativeBuffer(), true, base::unique_fd(), &fence);
+
+    const int fd = fence.get();
+    if (fd >= 0) {
+        sync_wait(fd, -1);
+    }
+
+    uint64_t bufferId = layer.source.buffer.buffer->getId();
+    uint32_t texName = layer.source.buffer.textureName;
+    EXPECT_TRUE(sRE->isImageCachedForTesting(bufferId));
+    EXPECT_EQ(bufferId, sRE->getBufferIdForTextureNameForTesting(texName));
+
+    EXPECT_TRUE(sRE->cleanupPostRender(renderengine::RenderEngine::CleanupMode::CLEAN_ALL));
+
+    // Now check that our view of memory is good.
+    EXPECT_FALSE(sRE->isImageCachedForTesting(bufferId));
+    EXPECT_EQ(std::nullopt, sRE->getBufferIdForTextureNameForTesting(bufferId));
+    EXPECT_TRUE(sRE->isTextureNameKnownForTesting(texName));
 }
 
 } // namespace android
diff --git a/libs/ui/Fence.cpp b/libs/ui/Fence.cpp
index 33ab7c4..2d3ef2e 100644
--- a/libs/ui/Fence.cpp
+++ b/libs/ui/Fence.cpp
@@ -32,6 +32,7 @@
 #include <utils/Log.h>
 #include <utils/String8.h>
 #include <utils/Trace.h>
+#include <utils/CallStack.h>
 
 namespace android {
 
@@ -45,12 +46,32 @@
     mFenceFd(std::move(fenceFd)) {
 }
 
+static status_t dump(const base::unique_fd &fd) {
+    ATRACE_CALL();
+
+    struct sync_file_info* finfo = sync_file_info(fd);
+    struct sync_fence_info* pinfo = sync_get_fence_info(finfo);
+
+    ALOGE(" ----- Printing sync-points under fence fd:%d status:%d name:%s -----",
+            fd.get(), finfo->status, finfo->name);
+    for (size_t i = 0; i < finfo->num_fences; i++) {
+        ALOGE("status:%d driver:%s obj:%s", pinfo[i].status,
+                pinfo[i].driver_name,  pinfo[i].obj_name);
+    }
+
+    return NO_ERROR;
+}
+
 status_t Fence::wait(int timeout) {
     ATRACE_CALL();
     if (mFenceFd == -1) {
         return NO_ERROR;
     }
     int err = sync_wait(mFenceFd, timeout);
+    if (err < 0 && (timeout == TIMEOUT_NEVER || timeout >100)) {
+        ALOGE("ERROR :Fence didnt signal in %dms. Initiating dump", timeout);
+        dump(mFenceFd);
+    }
     return err < 0 ? -errno : status_t(NO_ERROR);
 }
 
@@ -64,6 +85,7 @@
     if (err < 0 && errno == ETIME) {
         ALOGE("waitForever: %s: fence %d didn't signal in %u ms", logname, mFenceFd.get(),
               warningTimeout);
+        dump(mFenceFd);
 
         struct sync_file_info* finfo = sync_file_info(mFenceFd);
         if (finfo) {
diff --git a/libs/ui/Gralloc2.cpp b/libs/ui/Gralloc2.cpp
index 040a62b..00fa94d 100644
--- a/libs/ui/Gralloc2.cpp
+++ b/libs/ui/Gralloc2.cpp
@@ -48,6 +48,8 @@
         for (const auto bit : hardware::hidl_enum_range<BufferUsage>()) {
             bits = bits | bit;
         }
+        // TODO(b/72323293, b/72703005): Remove these invalid bits from callers
+        bits = bits | ((1 << 10) | (1 << 13) | (1 << 21) | (1 << 27));
         return bits;
     }();
     return valid10UsageBits;
diff --git a/libs/ui/Gralloc3.cpp b/libs/ui/Gralloc3.cpp
index 882674f..4bba7d4 100644
--- a/libs/ui/Gralloc3.cpp
+++ b/libs/ui/Gralloc3.cpp
@@ -47,6 +47,8 @@
              hardware::hidl_enum_range<hardware::graphics::common::V1_2::BufferUsage>()) {
             bits = bits | bit;
         }
+        // TODO(b/72323293, b/72703005): Remove these invalid bits from callers
+        bits = bits | ((1 << 13) | (1 << 21));
         return bits;
     }();
     return validUsageBits;
diff --git a/libs/ui/Gralloc4.cpp b/libs/ui/Gralloc4.cpp
index f799ce4..fa5c099 100644
--- a/libs/ui/Gralloc4.cpp
+++ b/libs/ui/Gralloc4.cpp
@@ -55,6 +55,7 @@
              hardware::hidl_enum_range<hardware::graphics::common::V1_2::BufferUsage>()) {
             bits = bits | bit;
         }
+        bits = bits | ((1 << 10) | (1 << 13) | (1 << 21) | (1 << 27));
         return bits;
     }();
     return validUsageBits;
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 4b19e5e..3347ba6 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -84,12 +84,13 @@
     bumpGeneration();
 }
 
-void InputDevice::dump(std::string& dump) {
+void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) {
     InputDeviceInfo deviceInfo;
     getDeviceInfo(&deviceInfo);
 
     dump += StringPrintf(INDENT "Device %d: %s\n", deviceInfo.getId(),
                          deviceInfo.getDisplayName().c_str());
+    dump += StringPrintf(INDENT "%s", eventHubDevStr.c_str());
     dump += StringPrintf(INDENT2 "Generation: %d\n", mGeneration);
     dump += StringPrintf(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
     dump += StringPrintf(INDENT2 "AssociatedDisplayPort: ");
@@ -101,6 +102,7 @@
     dump += StringPrintf(INDENT2 "HasMic:     %s\n", toString(mHasMic));
     dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
     dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
+    dump += StringPrintf(INDENT2 "ControllerNum: %d\n", deviceInfo.getControllerNumber());
 
     const std::vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
     if (!ranges.empty()) {
@@ -200,6 +202,8 @@
 
     // insert the context into the devices set
     mDevices.insert({eventHubId, std::make_pair(std::move(contextPtr), std::move(mappers))});
+    // Must change generation to flag this device as changed
+    bumpGeneration();
 }
 
 void InputDevice::removeEventHubDevice(int32_t eventHubId) {
diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp
index 657a134..fc063f9 100644
--- a/services/inputflinger/reader/InputReader.cpp
+++ b/services/inputflinger/reader/InputReader.cpp
@@ -206,6 +206,14 @@
     }
 
     mDevices.emplace(eventHubId, device);
+    // Add device to device to EventHub ids map.
+    const auto mapIt = mDeviceToEventHubIdsMap.find(device);
+    if (mapIt == mDeviceToEventHubIdsMap.end()) {
+        std::vector<int32_t> ids = {eventHubId};
+        mDeviceToEventHubIdsMap.emplace(device, ids);
+    } else {
+        mapIt->second.push_back(eventHubId);
+    }
     bumpGenerationLocked();
 
     if (device->getClasses() & INPUT_DEVICE_CLASS_EXTERNAL_STYLUS) {
@@ -222,6 +230,17 @@
 
     std::shared_ptr<InputDevice> device = std::move(deviceIt->second);
     mDevices.erase(deviceIt);
+    // Erase device from device to EventHub ids map.
+    auto mapIt = mDeviceToEventHubIdsMap.find(device);
+    if (mapIt != mDeviceToEventHubIdsMap.end()) {
+        std::vector<int32_t>& eventHubIds = mapIt->second;
+        eventHubIds.erase(std::remove_if(eventHubIds.begin(), eventHubIds.end(),
+                                         [eventHubId](int32_t eId) { return eId == eventHubId; }),
+                          eventHubIds.end());
+        if (eventHubIds.size() == 0) {
+            mDeviceToEventHubIdsMap.erase(mapIt);
+        }
+    }
     bumpGenerationLocked();
 
     if (device->isIgnored()) {
@@ -449,8 +468,7 @@
 void InputReader::getInputDevicesLocked(std::vector<InputDeviceInfo>& outInputDevices) {
     outInputDevices.clear();
 
-    for (auto& devicePair : mDevices) {
-        std::shared_ptr<InputDevice>& device = devicePair.second;
+    for (const auto& [device, eventHubIds] : mDeviceToEventHubIdsMap) {
         if (!device->isIgnored()) {
             InputDeviceInfo info;
             device->getDeviceInfo(&info);
@@ -621,11 +639,17 @@
     mEventHub->dump(dump);
     dump += "\n";
 
-    dump += "Input Reader State:\n";
+    dump += StringPrintf("Input Reader State (Nums of device: %zu):\n",
+                         mDeviceToEventHubIdsMap.size());
 
-    for (const auto& devicePair : mDevices) {
-        const std::shared_ptr<InputDevice>& device = devicePair.second;
-        device->dump(dump);
+    for (const auto& devicePair : mDeviceToEventHubIdsMap) {
+        const std::shared_ptr<InputDevice>& device = devicePair.first;
+        std::string eventHubDevStr = INDENT "EventHub Devices: [ ";
+        for (const auto& eId : devicePair.second) {
+            eventHubDevStr += StringPrintf("%d ", eId);
+        }
+        eventHubDevStr += "] \n";
+        device->dump(dump, eventHubDevStr);
     }
 
     dump += INDENT "Configuration:\n";
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index 71313fc..a08062a 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -66,7 +66,7 @@
     bool isEnabled();
     void setEnabled(bool enabled, nsecs_t when);
 
-    void dump(std::string& dump);
+    void dump(std::string& dump, const std::string& eventHubDevStr);
     void addEventHubDevice(int32_t eventHubId, bool populateMappers = true);
     void removeEventHubDevice(int32_t eventHubId);
     void configure(nsecs_t when, const InputReaderConfiguration* config, uint32_t changes);
diff --git a/services/inputflinger/reader/include/InputReader.h b/services/inputflinger/reader/include/InputReader.h
index 693ec30..d46ec1a 100644
--- a/services/inputflinger/reader/include/InputReader.h
+++ b/services/inputflinger/reader/include/InputReader.h
@@ -141,6 +141,11 @@
     // to lookup the input device instance from the EventHub device id.
     std::unordered_map<int32_t /*eventHubId*/, std::shared_ptr<InputDevice>> mDevices;
 
+    // An input device contains one or more eventHubId, this map provides a way to lookup the
+    // EventHubIds contained in the input device from the input device instance.
+    std::unordered_map<std::shared_ptr<InputDevice>, std::vector<int32_t> /*eventHubId*/>
+            mDeviceToEventHubIdsMap;
+
     // low-level input event decoding and device management
     void processEventsLocked(const RawEvent* rawEvents, size_t count);
 
diff --git a/services/inputflinger/reader/include/TouchVideoDevice.h b/services/inputflinger/reader/include/TouchVideoDevice.h
index 5a32443..7de9b83 100644
--- a/services/inputflinger/reader/include/TouchVideoDevice.h
+++ b/services/inputflinger/reader/include/TouchVideoDevice.h
@@ -102,7 +102,7 @@
      * How many buffers to keep for the internal queue. When the internal buffer
      * exceeds this capacity, oldest frames will be dropped.
      */
-    static constexpr size_t MAX_QUEUE_SIZE = 10;
+    static constexpr size_t MAX_QUEUE_SIZE = 20;
     std::vector<TouchVideoFrame> mFrames;
 
     /**
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 6842e6c..fc65a8e 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -617,12 +617,15 @@
     std::optional<uint32_t> receiveEvent(InputEvent** outEvent = nullptr) {
         uint32_t consumeSeq;
         InputEvent* event;
+        int motionEventType;
+        int touchMoveNumber;
+        bool flag;
 
         std::chrono::time_point start = std::chrono::steady_clock::now();
         status_t status = WOULD_BLOCK;
         while (status == WOULD_BLOCK) {
             status = mConsumer->consume(&mEventFactory, true /*consumeBatches*/, -1, &consumeSeq,
-                                        &event);
+                                        &event, &motionEventType, &touchMoveNumber, &flag);
             std::chrono::duration elapsed = std::chrono::steady_clock::now() - start;
             if (elapsed > 100ms) {
                 break;
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 8a282e2..e355594 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -153,12 +153,18 @@
                                     SensorDeviceUtils::defaultResolutionForType(sensor.type);
                         }
 
-                        double promotedResolution = sensor.resolution;
-                        double promotedMaxRange = sensor.maxRange;
-                        if (fmod(promotedMaxRange, promotedResolution) != 0) {
-                            ALOGW("%s's max range %f is not a multiple of the resolution %f",
-                                    sensor.name, sensor.maxRange, sensor.resolution);
-                            SensorDeviceUtils::quantizeValue(&sensor.maxRange, promotedResolution);
+                        // Some sensors don't have a default resolution and will be left at 0.
+                        // Don't crash in this case since CTS will verify that devices don't go to
+                        // production with a resolution of 0.
+                        if (sensor.resolution != 0) {
+                            double promotedResolution = sensor.resolution;
+                            double promotedMaxRange = sensor.maxRange;
+                            if (fmod(promotedMaxRange, promotedResolution) != 0) {
+                                ALOGW("%s's max range %f is not a multiple of the resolution %f",
+                                        sensor.name, sensor.maxRange, sensor.resolution);
+                                SensorDeviceUtils::quantizeValue(
+                                        &sensor.maxRange, promotedResolution);
+                            }
                         }
                     }
 
diff --git a/services/sensorservice/SensorEventConnection.cpp b/services/sensorservice/SensorEventConnection.cpp
index 6c86712..3cccaf9 100644
--- a/services/sensorservice/SensorEventConnection.cpp
+++ b/services/sensorservice/SensorEventConnection.cpp
@@ -29,6 +29,12 @@
 #define UNUSED(x) (void)(x)
 
 namespace android {
+namespace {
+
+// Used as the default value for the target SDK until it's obtained via getTargetSdkVersion.
+constexpr int kTargetSdkUnknown = 0;
+
+}  // namespace
 
 SensorService::SensorEventConnection::SensorEventConnection(
         const sp<SensorService>& service, uid_t uid, String8 packageName, bool isDataInjectionMode,
@@ -36,9 +42,9 @@
     : mService(service), mUid(uid), mWakeLockRefCount(0), mHasLooperCallbacks(false),
       mDead(false), mDataInjectionMode(isDataInjectionMode), mEventCache(nullptr),
       mCacheSize(0), mMaxCacheSize(0), mTimeOfLastEventDrop(0), mEventsDropped(0),
-      mPackageName(packageName), mOpPackageName(opPackageName), mDestroyed(false) {
+      mPackageName(packageName), mOpPackageName(opPackageName), mTargetSdk(kTargetSdkUnknown),
+      mDestroyed(false) {
     mChannel = new BitTube(mService->mSocketBufferSize);
-    mTargetSdk = SensorService::getTargetSdkVersion(opPackageName);
 #if DEBUG_CONNECTIONS
     mEventsReceived = mEventsSentFromCache = mEventsSent = 0;
     mTotalAcksNeeded = mTotalAcksReceived = 0;
@@ -439,6 +445,14 @@
     bool success = true;
     const auto iter = mHandleToAppOp.find(event.sensor);
     if (iter != mHandleToAppOp.end()) {
+        if (mTargetSdk == kTargetSdkUnknown) {
+            // getTargetSdkVersion returns -1 if it fails so this operation should only be run once
+            // per connection and then cached. Perform this here as opposed to in the constructor to
+            // avoid log spam for NDK/VNDK clients that don't use sensors guarded with permissions
+            // and pass in invalid op package names.
+            mTargetSdk = SensorService::getTargetSdkVersion(mOpPackageName);
+        }
+
         // Special handling for step count/detect backwards compatibility: if the app's target SDK
         // is pre-Q, still permit delivering events to the app even if permission isn't granted
         // (since this permission was only introduced in Q)
diff --git a/services/sensorservice/SensorService.cpp b/services/sensorservice/SensorService.cpp
index 60f9cd9..3ca34bb 100644
--- a/services/sensorservice/SensorService.cpp
+++ b/services/sensorservice/SensorService.cpp
@@ -79,6 +79,8 @@
 bool SensorService::sHmacGlobalKeyIsValid = false;
 std::map<String16, int> SensorService::sPackageTargetVersion;
 Mutex SensorService::sPackageTargetVersionLock;
+String16 SensorService::sSensorInterfaceDescriptorPrefix =
+        String16("android.frameworks.sensorservice@");
 AppOpsManager SensorService::sAppOpsManager;
 
 #define SENSOR_SERVICE_DIR "/data/system/sensor_service"
@@ -1847,6 +1849,13 @@
 }
 
 int SensorService::getTargetSdkVersion(const String16& opPackageName) {
+    // Don't query the SDK version for the ISensorManager descriptor as it doesn't have one. This
+    // descriptor tends to be used for VNDK clients, but can technically be set by anyone so don't
+    // give it elevated privileges.
+    if (opPackageName.startsWith(sSensorInterfaceDescriptorPrefix)) {
+        return -1;
+    }
+
     Mutex::Autolock packageLock(sPackageTargetVersionLock);
     int targetSdkVersion = -1;
     auto entry = sPackageTargetVersion.find(opPackageName);
diff --git a/services/sensorservice/SensorService.h b/services/sensorservice/SensorService.h
index 3bb8421..052cbfe 100644
--- a/services/sensorservice/SensorService.h
+++ b/services/sensorservice/SensorService.h
@@ -424,6 +424,7 @@
     static AppOpsManager sAppOpsManager;
     static std::map<String16, int> sPackageTargetVersion;
     static Mutex sPackageTargetVersionLock;
+    static String16 sSensorInterfaceDescriptorPrefix;
 };
 
 } // namespace android
diff --git a/services/stats/StatsHal.cpp b/services/stats/StatsHal.cpp
index 80c3b65..ae0a984 100644
--- a/services/stats/StatsHal.cpp
+++ b/services/stats/StatsHal.cpp
@@ -58,7 +58,7 @@
     std::vector<int32_t> buckets = chargeCycles.cycleBucket;
     int initialSize = buckets.size();
     for (int i = 0; i < 10 - initialSize; i++) {
-        buckets.push_back(-1); // Push -1 for buckets that do not exist.
+        buckets.push_back(0); // Push 0 for buckets that do not exist.
     }
     android::util::stats_write(android::util::CHARGE_CYCLES_REPORTED, buckets[0], buckets[1],
             buckets[2], buckets[3], buckets[4], buckets[5], buckets[6], buckets[7], buckets[8],
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index a790d0b..22957ca 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -1,3 +1,30 @@
+soong_config_module_type {
+      name: "libdisplayconfig_cc_defaults",
+      module_type: "cc_defaults",
+      config_namespace: "qtidisplaycommonsys",
+      bool_variables: [
+          "displayconfig_enabled",
+      ],
+      properties: [
+          "cflags",
+          "srcs",
+          "shared_libs",
+      ],
+  }
+
+  libdisplayconfig_cc_defaults {
+      name: "libdisplayconfig_defaults",
+      soong_config_variables: {
+          displayconfig_enabled : {
+              cflags: [
+              "-Wno-unused-parameter",
+              "-DQTI_DISPLAY_CONFIG_ENABLED"
+              ],
+              shared_libs : ["libdisplayconfig.qti"]
+          }
+      }
+  }
+
 cc_defaults {
     name: "surfaceflinger_defaults",
     cflags: [
@@ -11,9 +38,9 @@
     ],
 }
 
-cc_defaults {
+libdisplayconfig_cc_defaults {
     name: "libsurfaceflinger_defaults",
-    defaults: ["surfaceflinger_defaults"],
+    defaults: ["surfaceflinger_defaults", "libdisplayconfig_defaults"],
     cflags: [
         "-DLOG_TAG=\"SurfaceFlinger\"",
         "-DGL_GLEXT_PROTOTYPES",
@@ -31,6 +58,7 @@
         "android.hardware.graphics.composer@2.2",
         "android.hardware.graphics.composer@2.3",
         "android.hardware.graphics.composer@2.4",
+        "vendor.qti.hardware.display.composer@3.0",
         "android.hardware.power@1.0",
         "android.hardware.power@1.3",
         "android.hardware.power-cpp",
@@ -79,6 +107,7 @@
         "android.hardware.graphics.composer@2.2-command-buffer",
         "android.hardware.graphics.composer@2.3-command-buffer",
         "android.hardware.graphics.composer@2.4-command-buffer",
+        "display_intf_headers",
     ],
     export_static_lib_headers: [
         "libcompositionengine",
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 07be791..3f86188 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -34,6 +34,10 @@
 #include "Scheduler/LayerHistory.h"
 #include "TimeStats/TimeStats.h"
 
+#include "frame_extn_intf.h"
+#include "smomo_interface.h"
+#include "layer_extn_intf.h"
+
 namespace android {
 
 BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {}
@@ -122,7 +126,18 @@
         mFlinger->mTimeStats->incrementBadDesiredPresent(getSequence());
     }
 
-    const bool isDue = addedTime < expectedPresentTime;
+    bool isDue = addedTime < expectedPresentTime;
+
+    if (isDue && mFlinger->mSmoMo) {
+        smomo::SmomoBufferStats bufferStats;
+        bufferStats.id = getSequence();
+        bufferStats.queued_frames = getQueuedFrameCount();
+        bufferStats.auto_timestamp = mQueueItems[0].mIsAutoTimestamp;
+        bufferStats.timestamp = mQueueItems[0].mTimestamp;
+        bufferStats.dequeue_latency = 0;
+        isDue = mFlinger->mSmoMo->ShouldPresentNow(bufferStats, expectedPresentTime);
+    }
+
     return isDue || !isPlausible;
 }
 
@@ -324,9 +339,6 @@
         }
 
         uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId();
-        mFlinger->mFrameTracer->traceFence(layerId, bufferID, currentFrameNumber,
-                                           mQueueItems[0].mFenceTime,
-                                           FrameTracer::FrameEvent::ACQUIRE_FENCE);
         mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime);
         mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime,
                                                FrameTracer::FrameEvent::LATCH);
@@ -393,8 +405,12 @@
 
 void BufferQueueLayer::onFrameAvailable(const BufferItem& item) {
     const int32_t layerId = getSequence();
-    mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber,
-                                           systemTime(), FrameTracer::FrameEvent::QUEUE);
+    const uint64_t bufferId = item.mGraphicBuffer->getId();
+    mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
+                                           FrameTracer::FrameEvent::QUEUE);
+    mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
+                                       std::make_shared<FenceTime>(item.mFence),
+                                       FrameTracer::FrameEvent::ACQUIRE_FENCE);
 
     ATRACE_CALL();
     // Add this buffer from our internal queue tracker
@@ -430,6 +446,42 @@
     mFlinger->mInterceptor->saveBufferUpdate(layerId, item.mGraphicBuffer->getWidth(),
                                              item.mGraphicBuffer->getHeight(), item.mFrameNumber);
 
+    if (mFlinger->mSmoMo) {
+        smomo::SmomoBufferStats bufferStats;
+        bufferStats.id = getSequence();
+        bufferStats.queued_frames = getQueuedFrameCount();
+        bufferStats.auto_timestamp = item.mIsAutoTimestamp;
+        bufferStats.timestamp = item.mTimestamp;
+        bufferStats.dequeue_latency = 0;
+        mFlinger->mSmoMo->CollectLayerStats(bufferStats);
+    }
+
+    if (mFlinger->mFrameExtn && mFlinger->mDolphinFuncsEnabled) {
+        composer::FrameInfo frameInfo;
+        frameInfo.version.major = (uint8_t)(1);
+        frameInfo.version.minor = (uint8_t)(0);
+        frameInfo.max_queued_frames = mFlinger->mMaxQueuedFrames;
+        frameInfo.num_idle = mFlinger->mNumIdle;
+        frameInfo.max_queued_layer_name = mFlinger->mNameLayerMax;
+        frameInfo.current_timestamp = systemTime(SYSTEM_TIME_MONOTONIC);
+        frameInfo.previous_timestamp = mLastTimeStamp;
+        frameInfo.vsync_timestamp = mFlinger->mVsyncTimeStamp;
+        frameInfo.refresh_timestamp = mFlinger->mRefreshTimeStamp;
+        frameInfo.ref_latency = mFrameTracker.getPreviousGfxInfo();
+        frameInfo.vsync_period = mFlinger->mVsyncPeriod;
+        frameInfo.transparent_region = !this->isOpaque(mDrawingState);
+        if (frameInfo.transparent_region) {
+            if (this->isLayerFocusedBasedOnPriority(this->getPriority())) {
+                frameInfo.transparent_region = false;
+            }
+        }
+        frameInfo.width = item.mGraphicBuffer->getWidth();
+        frameInfo.height = item.mGraphicBuffer->getHeight();
+        frameInfo.layer_name = this->getName().c_str();
+        mLastTimeStamp = frameInfo.current_timestamp;
+        mFlinger->mFrameExtn->SetFrameInfo(frameInfo);
+    }
+
     mFlinger->signalLayerUpdate();
     mConsumer->onBufferAvailable(item);
 }
@@ -460,8 +512,12 @@
     }
 
     const int32_t layerId = getSequence();
-    mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber,
-                                           systemTime(), FrameTracer::FrameEvent::QUEUE);
+    const uint64_t bufferId = item.mGraphicBuffer->getId();
+    mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, item.mFrameNumber, systemTime(),
+                                           FrameTracer::FrameEvent::QUEUE);
+    mFlinger->mFrameTracer->traceFence(layerId, bufferId, item.mFrameNumber,
+                                       std::make_shared<FenceTime>(item.mFence),
+                                       FrameTracer::FrameEvent::ACQUIRE_FENCE);
     mConsumer->onBufferAvailable(item);
 }
 
@@ -496,6 +552,10 @@
     if (!mFlinger->isLayerTripleBufferingDisabled()) {
         mProducer->setMaxDequeuedBufferCount(2);
     }
+
+    if (mFlinger->mUseLayerExt && mFlinger->mLayerExt) {
+        mLayerClass = mFlinger->mLayerExt->GetLayerClass(mName);
+    }
 }
 
 status_t BufferQueueLayer::setDefaultBufferProperties(uint32_t w, uint32_t h, PixelFormat format) {
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 5ebc22d..315e88b 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -148,6 +148,7 @@
     std::atomic<bool> mSidebandStreamChanged{false};
 
     sp<ContentsChangedListener> mContentsChangedListener;
+    nsecs_t mLastTimeStamp = -1;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp
index b3b9fe5..ff327b8 100644
--- a/services/surfaceflinger/CompositionEngine/Android.bp
+++ b/services/surfaceflinger/CompositionEngine/Android.bp
@@ -1,9 +1,15 @@
-cc_defaults {
+soong_config_module_type_import {
+    from: "frameworks/native/services/surfaceflinger/Android.bp",
+    module_types: ["libdisplayconfig_cc_defaults"],
+}
+
+libdisplayconfig_cc_defaults {
     name: "libcompositionengine_defaults",
-    defaults: ["surfaceflinger_defaults"],
+    defaults: ["surfaceflinger_defaults", "libdisplayconfig_defaults"],
     cflags: [
         "-DLOG_TAG=\"CompositionEngine\"",
         "-DATRACE_TAG=ATRACE_TAG_GRAPHICS",
+        "-Wno-unused-private-field",
     ],
     shared_libs: [
         "android.frameworks.vr.composer@2.0",
@@ -36,6 +42,7 @@
         "android.hardware.graphics.composer@2.3-command-buffer",
         "android.hardware.graphics.composer@2.4-command-buffer",
         "libsurfaceflinger_headers",
+        "display_intf_headers",
     ],
 }
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
index 8a9763b..6ff0f53 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h
@@ -189,7 +189,13 @@
     // The output-independent frame for the cursor
     Rect cursorFrame;
 
+    // layer classification
+    uint32_t layerClass;
+
     virtual ~LayerFECompositionState();
+    bool isSecureDisplay{false};
+    bool isSecureCamera{false};
+    bool isScreenshot{false};
 
     // Debugging
     virtual void dump(std::string& out) const;
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
index baf5258..32bef3b 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h
@@ -149,6 +149,8 @@
         Region dirtyRegion;
     };
 
+    bool hasSecureDisplay{false};
+
     virtual ~Output();
 
     // Returns true if the output is valid. This is meant to be checked post-
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
index f680460..07e83ad 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/RenderSurface.h
@@ -98,6 +98,12 @@
 
     // Debugging - gets the page flip count for the RenderSurface
     virtual std::uint32_t getPageFlipCount() const = 0;
+   // Called to set the viewport and projection state for rendering into this
+   // surface
+    virtual void setViewportAndProjection() = 0;
+
+    // Called to flip the client target when needed
+    virtual void flipClientTarget(bool flip)  = 0;
 };
 
 } // namespace compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
index 7a4f738..0d8de81 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h
@@ -91,6 +91,8 @@
     bool mIsVirtual = false;
     std::optional<DisplayId> mId;
     Hwc2::PowerAdvisor* mPowerAdvisor = nullptr;
+    bool mHasScreenshot = false;
+    DisplayConnectionType mConnectionType = DisplayConnectionType::Internal;
 };
 
 // This template factory function standardizes the implementation details of the
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
index 2864c10..6932be0 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/HwcBufferCache.h
@@ -61,6 +61,8 @@
     // buffer) pair. "counter" is a unique value that indicates the last time this slot was updated
     // or used and allows us to keep track of the least-recently used buffer.
     wp<GraphicBuffer> mBuffers[BufferQueue::NUM_BUFFER_SLOTS];
+    uint32_t mNextSlot = 0;
+    bool mReduceSlotsForWideVideo = false;
 };
 
 } // namespace compositionengine::impl
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
index 5127a6f..e23442d 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/RenderSurface.h
@@ -68,6 +68,8 @@
     void setSizeForTest(const ui::Size&);
     sp<GraphicBuffer>& mutableGraphicBufferForTest();
     base::unique_fd& mutableBufferReadyForTest();
+    void flipClientTarget(bool flip) override;
+    void setViewportAndProjection() override;
 
 private:
     const compositionengine::CompositionEngine& mCompositionEngine;
@@ -80,6 +82,7 @@
     const sp<DisplaySurface> mDisplaySurface;
     ui::Size mSize;
     bool mProtected{false};
+    bool mFlipClientTarget{false};
     std::uint32_t mPageFlipCount{0};
 };
 
diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
index a0cae6f..581d063 100644
--- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
+++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/RenderSurface.h
@@ -41,9 +41,11 @@
     MOCK_METHOD2(prepareFrame, void(bool, bool));
     MOCK_METHOD1(dequeueBuffer, sp<GraphicBuffer>(base::unique_fd*));
     MOCK_METHOD1(queueBuffer, void(base::unique_fd));
+    MOCK_METHOD1(flipClientTarget, void(bool flip));
     MOCK_METHOD0(onPresentDisplayCompleted, void());
     MOCK_METHOD0(flip, void());
     MOCK_CONST_METHOD1(dump, void(std::string& result));
+    MOCK_METHOD0(setViewportAndProjection, void());
     MOCK_CONST_METHOD0(getPageFlipCount, std::uint32_t());
 };
 
diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp
index d201104..bc5e1f7 100644
--- a/services/surfaceflinger/CompositionEngine/src/Display.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp
@@ -20,12 +20,17 @@
 #include <compositionengine/DisplayCreationArgs.h>
 #include <compositionengine/DisplaySurface.h>
 #include <compositionengine/LayerFE.h>
+#include <compositionengine/LayerFECompositionState.h>
 #include <compositionengine/impl/Display.h>
 #include <compositionengine/impl/DisplayColorProfile.h>
 #include <compositionengine/impl/DumpHelpers.h>
 #include <compositionengine/impl/OutputLayer.h>
 #include <compositionengine/impl/RenderSurface.h>
 
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+#include <config/client_interface.h>
+#endif
+
 #include <utils/Trace.h>
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
@@ -41,6 +46,10 @@
 
 namespace android::compositionengine::impl {
 
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+::DisplayConfig::ClientInterface *mDisplayConfigIntf = nullptr;
+#endif
+
 std::shared_ptr<Display> createDisplay(
         const compositionengine::CompositionEngine& compositionEngine,
         const compositionengine::DisplayCreationArgs& args) {
@@ -52,6 +61,7 @@
 void Display::setConfiguration(const compositionengine::DisplayCreationArgs& args) {
     mIsVirtual = !args.physical;
     mId = args.physical ? std::make_optional(args.physical->id) : std::nullopt;
+    mConnectionType = args.physical ? args.physical->type : DisplayConnectionType::Internal;
     mPowerAdvisor = args.powerAdvisor;
 
     editState().isSecure = args.isSecure;
@@ -64,6 +74,15 @@
     if (!args.physical && args.useHwcVirtualDisplays) {
         mId = maybeAllocateDisplayIdForVirtualDisplay(args.pixels, args.pixelFormat);
     }
+
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+    int ret = ::DisplayConfig::ClientInterface::Create(args.name, nullptr, &mDisplayConfigIntf);
+    if (ret) {
+        ALOGE("DisplayConfig HIDL not present\n");
+        mDisplayConfigIntf = nullptr;
+    }
+#endif
+
 }
 
 std::optional<DisplayId> Display::maybeAllocateDisplayIdForVirtualDisplay(
@@ -194,6 +213,13 @@
         ALOGE_IF(!hwcLayer, "Failed to create a HWC layer for a HWC supported display %s",
                  getName().c_str());
         result->setHwcLayer(std::move(hwcLayer));
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+        if (layerFE->getCompositionState()->internalOnly && mDisplayConfigIntf) {
+            const auto hwcDisplayId = hwc.fromPhysicalDisplayId(*mId);
+            mDisplayConfigIntf->SetLayerAsMask(static_cast<uint32_t>(*hwcDisplayId),
+                                               result->getHwcLayer()->getId());
+        }
+#endif
     }
     return result;
 }
@@ -248,6 +274,21 @@
     // Get any composition changes requested by the HWC device, and apply them.
     std::optional<android::HWComposer::DeviceRequestedChanges> changes;
     auto& hwc = getCompositionEngine().getHwComposer();
+
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+    auto layers = getOutputLayersOrderedByZ();
+    bool hasScreenshot = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
+         return layer->getLayerFE().getCompositionState()->isScreenshot;
+    });
+    if ((mIsVirtual || (mConnectionType == DisplayConnectionType::External)) &&
+        (hasScreenshot != mHasScreenshot) && mDisplayConfigIntf) {
+        const auto hwcDisplayId = hwc.fromPhysicalDisplayId(*mId);
+        if (hwcDisplayId) {
+            mDisplayConfigIntf->SetDisplayAnimating(*hwcDisplayId, hasScreenshot);
+            mHasScreenshot = hasScreenshot;
+        }
+    }
+#endif
     if (status_t result = hwc.getDeviceCompositionChanges(*mId, anyLayersRequireClientComposition(),
                                                           &changes);
         result != NO_ERROR) {
@@ -331,7 +372,7 @@
     if (clientTargetProperty.dataspace == ui::Dataspace::UNKNOWN) {
         return;
     }
-    auto outputState = editState();
+    auto &outputState = editState();
     outputState.dataspace = clientTargetProperty.dataspace;
     getRenderSurface()->setBufferDataspace(clientTargetProperty.dataspace);
     getRenderSurface()->setBufferPixelFormat(clientTargetProperty.pixelFormat);
diff --git a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
index cedc333..c3b613a 100644
--- a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp
@@ -22,28 +22,96 @@
 
 #include <gui/BufferQueue.h>
 #include <ui/GraphicBuffer.h>
+#include <cstdlib>
+#include <cutils/properties.h>
+#include <QtiGrallocDefs.h>
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
 #pragma clang diagnostic pop // ignored "-Wconversion"
 
+constexpr int MAX_VIDEO_WIDTH = 5760;
+constexpr int MAX_VIDEO_HEIGHT = 2160;
+constexpr int MAX_NUM_SLOTS_FOR_WIDE_VIDEOS = 4;
+
 namespace android::compositionengine::impl {
 
 HwcBufferCache::HwcBufferCache() {
     std::fill(std::begin(mBuffers), std::end(mBuffers), wp<GraphicBuffer>(nullptr));
+    char value[PROPERTY_VALUE_MAX];
+    property_get("vendor.display.reduce_slots_for_wide_video", value, "1");
+    mReduceSlotsForWideVideo = atoi(value);
+}
+
+//TODO: Move to common location
+static bool formatIsYuv(const PixelFormat format) {
+    switch (format) {
+        case HAL_PIXEL_FORMAT_YCBCR_422_SP:
+        case HAL_PIXEL_FORMAT_YCRCB_420_SP:
+        case HAL_PIXEL_FORMAT_YCBCR_422_I:
+        case HAL_PIXEL_FORMAT_YCBCR_420_888:
+        case HAL_PIXEL_FORMAT_Y8:
+        case HAL_PIXEL_FORMAT_Y16:
+        case HAL_PIXEL_FORMAT_YV12:
+        case HAL_PIXEL_FORMAT_YCBCR_P010:
+        case HAL_PIXEL_FORMAT_NV12_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_NV21_ENCODEABLE:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_TILED:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO:
+        case HAL_PIXEL_FORMAT_YCrCb_422_SP:
+        case HAL_PIXEL_FORMAT_YCbCr_444_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_444_SP:
+        case HAL_PIXEL_FORMAT_YCrCb_422_I:
+        case HAL_PIXEL_FORMAT_NV21_ZSL:
+        case HAL_PIXEL_FORMAT_YCrCb_420_SP_VENUS:
+        case HAL_PIXEL_FORMAT_NV12_HEIF:
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010_UBWC:
+        case HAL_PIXEL_FORMAT_YCbCr_420_P010_VENUS:
+        case HAL_PIXEL_FORMAT_CbYCrY_422_I:
+        case HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT:
+        case HAL_PIXEL_FORMAT_YCbCr_422_I_10BIT_COMPRESSED:
+        case HAL_PIXEL_FORMAT_YCbCr_420_SP_VENUS_UBWC:
+        case HAL_PIXEL_FORMAT_YCbCr_420_TP10_UBWC:
+            return true;
+         default:
+            return false;
+    }
 }
 
 void HwcBufferCache::getHwcBuffer(int slot, const sp<GraphicBuffer>& buffer, uint32_t* outSlot,
                                   sp<GraphicBuffer>* outBuffer) {
     // default is 0
+    wp<GraphicBuffer> weakCopy(buffer);
+    uint32_t width = 0;
+    uint32_t height = 0;
+    PixelFormat format = PIXEL_FORMAT_NONE;
+    if (buffer) {
+        width = buffer->getWidth();
+        height = buffer->getHeight();
+        format = buffer->getPixelFormat();
+    }
+    bool widevideo = false;
+    uint32_t numSlots = BufferQueue::NUM_BUFFER_SLOTS;
+
+    // Workaround to reduce slots for 8k buffers
+    if ((width * height > MAX_VIDEO_WIDTH * MAX_VIDEO_HEIGHT) && mReduceSlotsForWideVideo &&
+        formatIsYuv(format)) {
+        numSlots = MAX_NUM_SLOTS_FOR_WIDE_VIDEOS;
+        widevideo = true;
+    }
     if (slot == BufferQueue::INVALID_BUFFER_SLOT || slot < 0 ||
-        slot >= BufferQueue::NUM_BUFFER_SLOTS) {
+        slot >= numSlots) {
         *outSlot = 0;
+        if (widevideo && slot >= numSlots) {
+            *outSlot = mNextSlot % numSlots;
+            mNextSlot = *outSlot + 1;
+        }
     } else {
         *outSlot = static_cast<uint32_t>(slot);
     }
 
     auto& currentBuffer = mBuffers[*outSlot];
-    wp<GraphicBuffer> weakCopy(buffer);
     if (currentBuffer == weakCopy) {
         // already cached in HWC, skip sending the buffer
         *outBuffer = nullptr;
diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp
index e8f54f5..8567ac6 100644
--- a/services/surfaceflinger/CompositionEngine/src/Output.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp
@@ -689,12 +689,23 @@
     }
 
     // respect hdrDataSpace only when there is no legacy HDR support
-    const bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
+    bool isHdr = hdrDataSpace != ui::Dataspace::UNKNOWN &&
             !mDisplayColorProfile->hasLegacyHdrSupport(hdrDataSpace) && !isHdrClientComposition;
+
+    auto layers = getOutputLayersOrderedByZ();
+    bool hasSecureDisplay = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
+         return layer->getLayerFE().getCompositionState()->isSecureDisplay;
+    });
+
     if (isHdr) {
         bestDataSpace = hdrDataSpace;
     }
 
+    if (hasSecureDisplay) {
+        bestDataSpace = ui::Dataspace::V0_SRGB;
+        isHdr = false;
+     }
+
     ui::RenderIntent intent;
     switch (refreshArgs.outputColorSetting) {
         case OutputColorSetting::kManaged:
@@ -817,24 +828,35 @@
     const TracedOrdinal<bool> hasClientComposition = {"hasClientComposition",
                                                       outputState.usesClientComposition};
 
+    bool hasSecureCamera = false;
+    bool hasSecureDisplay = false;
+    bool needsProtected = false;
+    for (auto* layer : getOutputLayersOrderedByZ()) {
+         if (layer->getLayerFE().getCompositionState()->isSecureCamera) {
+             hasSecureCamera = true;
+         }
+         if (layer->getLayerFE().getCompositionState()->isSecureDisplay) {
+             hasSecureDisplay = true;
+         }
+         if (layer->getLayerFE().getCompositionState()->hasProtectedContent) {
+            needsProtected = true;
+         }
+    }
+
     auto& renderEngine = getCompositionEngine().getRenderEngine();
-    const bool supportsProtectedContent = renderEngine.supportsProtectedContent();
+    const bool supportsProtectedContent = renderEngine.supportsProtectedContent() &&
+                                          !hasSecureCamera && !hasSecureDisplay &&
+                                          outputState.isSecure && needsProtected;
 
     // If we the display is secure, protected content support is enabled, and at
     // least one layer has protected content, we need to use a secure back
     // buffer.
-    if (outputState.isSecure && supportsProtectedContent) {
-        auto layers = getOutputLayersOrderedByZ();
-        bool needsProtected = std::any_of(layers.begin(), layers.end(), [](auto* layer) {
-            return layer->getLayerFE().getCompositionState()->hasProtectedContent;
-        });
-        if (needsProtected != renderEngine.isProtected()) {
-            renderEngine.useProtectedContext(needsProtected);
-        }
-        if (needsProtected != mRenderSurface->isProtected() &&
-            needsProtected == renderEngine.isProtected()) {
-            mRenderSurface->setProtected(needsProtected);
-        }
+    if (supportsProtectedContent != renderEngine.isProtected()) {
+        renderEngine.useProtectedContext(supportsProtectedContent);
+    }
+    if (supportsProtectedContent != mRenderSurface->isProtected() &&
+        supportsProtectedContent == renderEngine.isProtected()) {
+        mRenderSurface->setProtected(supportsProtectedContent);
     }
 
     base::unique_fd fd;
diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
index 1faf775..8f345bd 100644
--- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp
@@ -475,6 +475,12 @@
             // Ignored
             break;
     }
+
+    if (auto error = hwcLayer->setType(outputIndependentState.layerClass);
+        error != hal::Error::NONE) {
+        ALOGE("[%s] Failed to set layer class: %s (%d)", getLayerFE().getDebugName(),
+              to_string(error).c_str(), static_cast<int32_t>(error));
+    }
 }
 
 void OutputLayer::writeSolidColorStateToHWC(HWC2::Layer* hwcLayer,
diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
index 2773fd3..3cf1438 100644
--- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
+++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp
@@ -172,7 +172,8 @@
 void RenderSurface::queueBuffer(base::unique_fd readyFence) {
     auto& state = mDisplay.getState();
 
-    if (state.usesClientComposition || state.flipClientTarget) {
+
+    if (state.usesClientComposition || state.flipClientTarget || mFlipClientTarget) {
         // hasFlipClientTargetRequest could return true even if we haven't
         // dequeued a buffer before. Try dequeueing one if we don't have a
         // buffer ready.
@@ -193,7 +194,8 @@
         } else {
             status_t result =
                     mNativeWindow->queueBuffer(mNativeWindow.get(),
-                                               mGraphicBuffer->getNativeBuffer(), dup(readyFence));
+                                               mGraphicBuffer->getNativeBuffer(),
+                                               mFlipClientTarget ? -1 : dup(readyFence));
             if (result != NO_ERROR) {
                 ALOGE("Error when queueing buffer for display [%s]: %d", mDisplay.getName().c_str(),
                       result);
@@ -203,7 +205,8 @@
                     LOG_ALWAYS_FATAL("ANativeWindow::queueBuffer failed with error: %d", result);
                 } else {
                     mNativeWindow->cancelBuffer(mNativeWindow.get(),
-                                                mGraphicBuffer->getNativeBuffer(), dup(readyFence));
+                                                mGraphicBuffer->getNativeBuffer(),
+                                                mFlipClientTarget ? -1 : dup(readyFence));
                 }
             }
 
@@ -225,6 +228,12 @@
     mPageFlipCount++;
 }
 
+void RenderSurface::setViewportAndProjection() {
+    Rect sourceCrop = Rect(mSize);
+    Rect viewPort = Rect(mSize.width,  mSize.height);
+    auto& renderEngine = mCompositionEngine.getRenderEngine();
+    renderEngine.setViewportAndProjection(viewPort, sourceCrop);
+}
 void RenderSurface::dump(std::string& out) const {
     using android::base::StringAppendF;
 
@@ -259,5 +268,9 @@
     return mGraphicBuffer;
 }
 
+void RenderSurface::flipClientTarget(bool flip) {
+    mFlipClientTarget = flip;
+}
+
 } // namespace impl
 } // namespace android::compositionengine
diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
index 09f37fb..29fd4b9 100644
--- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp
@@ -159,6 +159,7 @@
         EXPECT_CALL(mCompositionEngine, getHwComposer()).WillRepeatedly(ReturnRef(mHwComposer));
         EXPECT_CALL(mCompositionEngine, getRenderEngine()).WillRepeatedly(ReturnRef(mRenderEngine));
         EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+        EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     }
 
     DisplayCreationArgs getDisplayCreationArgsForPhysicalHWCDisplay() {
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
index d21b97e..f8c2e3c 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWC2.h
@@ -67,6 +67,7 @@
     MOCK_METHOD1(setVisibleRegion, Error(const android::Region&));
     MOCK_METHOD1(setZOrder, Error(uint32_t));
     MOCK_METHOD2(setInfo, Error(uint32_t, uint32_t));
+    MOCK_METHOD1(setType, Error(uint32_t));
 
     MOCK_METHOD1(setColorTransform, Error(const android::mat4&));
     MOCK_METHOD3(setLayerGenericMetadata,
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
index 75a4fec..817de9a 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockHWComposer.h
@@ -75,6 +75,7 @@
     MOCK_METHOD4(getDisplayedContentSample,
                  status_t(DisplayId, uint64_t, uint64_t, DisplayedFrameStats*));
     MOCK_METHOD2(setDisplayBrightness, std::future<status_t>(DisplayId, float));
+    MOCK_METHOD2(setDisplayElapseTime, status_t(DisplayId, uint64_t));
     MOCK_METHOD2(getDisplayBrightnessSupport, status_t(DisplayId, bool*));
 
     MOCK_METHOD2(onHotplug,
diff --git a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
index b738096..d7dff36 100644
--- a/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
+++ b/services/surfaceflinger/CompositionEngine/tests/MockPowerAdvisor.h
@@ -32,6 +32,7 @@
     MOCK_METHOD0(onBootFinished, void());
     MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
     MOCK_METHOD0(notifyDisplayUpdateImminent, void());
+    MOCK_METHOD0(canNotifyDisplayUpdateImminent, bool());
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
index 59ed72e..e1989ae 100644
--- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
+++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp
@@ -2871,6 +2871,7 @@
     mOutput.mState.usesClientComposition = false;
 
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
 
     EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
 
@@ -2883,6 +2884,7 @@
     mOutput.mState.flipClientTarget = true;
 
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
 
     EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(mOutputBuffer));
     EXPECT_CALL(mOutput, setExpensiveRenderingExpected(false));
@@ -2892,6 +2894,7 @@
 
 TEST_F(OutputComposeSurfacesTest, doesMinimalWorkIfDequeueBufferFailsForClientComposition) {
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
 
     EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
 
@@ -2904,6 +2907,7 @@
     mOutput.mState.flipClientTarget = true;
 
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
 
     EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillOnce(Return(nullptr));
 
@@ -2914,6 +2918,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -2936,6 +2941,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -2963,6 +2969,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -2991,6 +2998,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -3019,6 +3027,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{r1, r2}));
     EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -3050,6 +3059,7 @@
     EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
     EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+    EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
     EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
             .WillOnce(Return(std::vector<LayerFE::LayerSettings>{r1, r2}))
             .WillOnce(Return(std::vector<LayerFE::LayerSettings>{r1, r3}));
@@ -3072,6 +3082,7 @@
 struct OutputComposeSurfacesTest_UsesExpectedDisplaySettings : public OutputComposeSurfacesTest {
     OutputComposeSurfacesTest_UsesExpectedDisplaySettings() {
         EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+        EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
         EXPECT_CALL(mOutput, generateClientCompositionRequests(_, _, kDefaultOutputDataspace))
                 .WillRepeatedly(Return(std::vector<LayerFE::LayerSettings>{}));
         EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
@@ -3219,6 +3230,8 @@
     mOutput.mState.isSecure = false;
     mLayer2.mLayerFEState.hasProtectedContent = true;
     EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(true));
+    EXPECT_CALL(mRenderEngine, isProtected).WillOnce(Return(true));
+    EXPECT_CALL(mRenderEngine, useProtectedContext(false)).WillOnce(Return(true));
 
     mOutput.composeSurfaces(kDebugRegion, kDefaultRefreshArgs);
 }
@@ -3311,6 +3324,7 @@
         EXPECT_CALL(mOutput, getSkipColorTransform()).WillRepeatedly(Return(false));
         EXPECT_CALL(*mDisplayColorProfile, hasWideColorGamut()).WillRepeatedly(Return(true));
         EXPECT_CALL(mRenderEngine, supportsProtectedContent()).WillRepeatedly(Return(false));
+        EXPECT_CALL(mRenderEngine, isProtected()).WillRepeatedly(Return(false));
         EXPECT_CALL(mOutput, appendRegionFlashRequests(RegionEq(kDebugRegion), _))
                 .WillRepeatedly(Return());
         EXPECT_CALL(*mRenderSurface, dequeueBuffer(_)).WillRepeatedly(Return(mOutputBuffer));
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 730f297..ce38f25 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -61,7 +61,8 @@
         mConnectionType(args.connectionType),
         mCompositionDisplay{args.compositionDisplay},
         mPhysicalOrientation(args.physicalOrientation),
-        mIsPrimary(args.isPrimary) {
+        mIsPrimary(args.isPrimary),
+        mIsPowerModeOverride(false){
     mCompositionDisplay->editState().isSecure = args.isSecure;
     mCompositionDisplay->createRenderSurface(
             compositionengine::RenderSurfaceCreationArgs{ANativeWindow_getWidth(
@@ -142,6 +143,14 @@
     return mActiveConfig;
 }
 
+void DisplayDevice::setPowerModeOverrideConfig(bool supported) {
+    mIsPowerModeOverride = supported;
+}
+
+bool DisplayDevice::getPowerModeOverrideConfig() const {
+    return mIsPowerModeOverride;
+}
+
 ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
     return mCompositionDisplay->getState().dataspace;
 }
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index cb467ea..49dd910 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -151,6 +151,8 @@
     HwcConfigIndexType getActiveConfig() const;
     void setActiveConfig(HwcConfigIndexType mode);
 
+    void setPowerModeOverrideConfig(bool supported);
+    bool getPowerModeOverrideConfig() const;
     // release HWC resources (if any) for removable displays
     void disconnect();
 
@@ -182,6 +184,7 @@
 
     // TODO(b/74619554): Remove special cases for primary display.
     const bool mIsPrimary;
+    bool mIsPowerModeOverride;
 };
 
 struct DisplayDeviceState {
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index a3f1b52..805050d 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -32,12 +32,21 @@
 #include <gui/BufferQueue.h>
 #include <hidl/HidlTransportSupport.h>
 #include <hidl/HidlTransportUtils.h>
+#include <vendor/qti/hardware/display/composer/3.0/IQtiComposerClient.h>
+
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+#include <config/client_interface.h>
+namespace DisplayConfig {
+class ClientInterface;
+}
+#endif
 
 namespace android {
 
 using hardware::Return;
 using hardware::hidl_vec;
 using hardware::hidl_handle;
+using vendor::qti::hardware::display::composer::V3_0::IQtiComposerClient;
 
 namespace Hwc2 {
 
@@ -117,6 +126,16 @@
 
 namespace impl {
 
+void Composer::CommandWriter::setLayerType(uint32_t type)
+{
+    constexpr uint16_t kSetLayerTypeLength = 1;
+    beginCommand(static_cast<V2_1::IComposerClient::Command>(
+                         IQtiComposerClient::Command::SET_LAYER_TYPE),
+                 kSetLayerTypeLength);
+    write(type);
+    endCommand();
+}
+
 #if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
 Composer::CommandWriter::CommandWriter(uint32_t initialMaxSize)
     : CommandWriterBase(initialMaxSize) {}
@@ -170,6 +189,16 @@
 }
 #endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
 
+void Composer::CommandWriter::setDisplayElapseTime(uint64_t time)
+{
+    constexpr uint16_t kSetDisplayElapseTimeLength = 2;
+    beginCommand(static_cast<V2_1::IComposerClient::Command>(
+                         IQtiComposerClient::Command::SET_DISPLAY_ELAPSE_TIME),
+                 kSetDisplayElapseTimeLength);
+    write64(time);
+    endCommand();
+}
+
 Composer::Composer(const std::string& serviceName)
     : mWriter(kWriterInitialSize),
       mIsUsingVrComposer(serviceName == std::string("vr"))
@@ -216,6 +245,29 @@
         LOG_ALWAYS_FATAL("failed to create composer client");
     }
 
+     // On successful creation of composer client only AllowIdleFallback
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+    if (mClient) {
+        ::DisplayConfig::ClientInterface *mDisplayConfigIntf = nullptr;
+        ::DisplayConfig::ClientInterface::Create("SurfaceFlinger"+std::to_string(0),
+                                                        nullptr, &mDisplayConfigIntf);
+        if (mDisplayConfigIntf) {
+#ifdef DISPLAY_CONFIG_API_LEVEL_2
+            std::string value = "";
+            std::string idle_fallback_prop = "enable_allow_idle_fallback";
+            int ret = mDisplayConfigIntf->GetDebugProperty(idle_fallback_prop, &value);
+            ALOGI("enable_allow_idle_fallback, ret:%d value:%s", ret, value.c_str());
+            if (!ret && (value == "1")) {
+                if(mDisplayConfigIntf->AllowIdleFallback()) {
+                    ALOGW("failed to set Idle time");
+                }
+            }
+#endif
+            ::DisplayConfig::ClientInterface::Destroy(mDisplayConfigIntf);
+        }
+    }
+#endif
+
 #if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
     if (mIsUsingVrComposer) {
         sp<IVrComposerClient> vrClient = IVrComposerClient::castFrom(mClient);
@@ -642,6 +694,13 @@
     return Error::NONE;
 }
 
+Error Composer::setDisplayElapseTime(Display display, uint64_t timeStamp)
+{
+    mWriter.selectDisplay(display);
+    mWriter.setDisplayElapseTime(timeStamp);
+    return Error::NONE;
+}
+
 Error Composer::setPowerMode(Display display, IComposerClient::PowerMode mode) {
     Return<Error> ret(Error::UNSUPPORTED);
     if (mClient_2_2) {
@@ -871,6 +930,19 @@
 }
 #endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
 
+Error Composer::setLayerType(Display display, Layer layer, uint32_t type)
+{
+    if (mClient_2_4) {
+        if (sp<IQtiComposerClient> qClient = IQtiComposerClient::castFrom(mClient_2_4)) {
+            mWriter.selectDisplay(display);
+            mWriter.selectLayer(layer);
+            mWriter.setLayerType(type);
+        }
+    }
+
+    return Error::NONE;
+}
+
 Error Composer::execute()
 {
     // prepare input command queue
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 00ef782..5408d55 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -189,6 +189,7 @@
                                         const std::vector<IComposerClient::Rect>& visible) = 0;
     virtual Error setLayerZOrder(Display display, Layer layer, uint32_t z) = 0;
     virtual Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) = 0;
+    virtual Error setLayerType(Display display, Layer layer, uint32_t type) = 0;
 
     // Composer HAL 2.2
     virtual Error setLayerPerFrameMetadata(
@@ -242,6 +243,7 @@
             std::vector<IComposerClient::LayerGenericMetadataKey>* outKeys) = 0;
     virtual Error getClientTargetProperty(
             Display display, IComposerClient::ClientTargetProperty* outClientTargetProperty) = 0;
+    virtual Error setDisplayElapseTime(Display display, uint64_t timeStamp) = 0;
 };
 
 namespace impl {
@@ -437,6 +439,7 @@
                                 const std::vector<IComposerClient::Rect>& visible) override;
     Error setLayerZOrder(Display display, Layer layer, uint32_t z) override;
     Error setLayerInfo(Display display, Layer layer, uint32_t type, uint32_t appId) override;
+    Error setLayerType(Display display, Layer layer, uint32_t type) override;
 
     // Composer HAL 2.2
     Error setLayerPerFrameMetadata(
@@ -463,6 +466,7 @@
             Display display, Layer layer,
             const std::vector<IComposerClient::PerFrameMetadataBlob>& metadata) override;
     Error setDisplayBrightness(Display display, float brightness) override;
+    Error setDisplayElapseTime(Display display, uint64_t timeStamp) override;
 
     // Composer HAL 2.4
     bool isVsyncPeriodSwitchSupported() override { return mClient_2_4 != nullptr; }
@@ -497,10 +501,12 @@
         ~CommandWriter() override;
 
         void setLayerInfo(uint32_t type, uint32_t appId);
+        void setLayerType(uint32_t type);
         void setClientTargetMetadata(
                 const IVrComposerClient::BufferMetadata& metadata);
         void setLayerBufferMetadata(
                 const IVrComposerClient::BufferMetadata& metadata);
+        void setDisplayElapseTime(uint64_t time);
 
     private:
         void writeBufferMetadata(
@@ -511,6 +517,9 @@
     public:
         explicit CommandWriter(uint32_t initialMaxSize) : CommandWriterBase(initialMaxSize) {}
         ~CommandWriter() override {}
+
+        void setDisplayElapseTime(uint64_t time);
+        void setLayerType(uint32_t type);
     };
 #endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER
 
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 08559bd..940437f 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -570,6 +570,12 @@
     return static_cast<Error>(intError);
 }
 
+Error Display::setDisplayElapseTime(uint64_t timeStamp)
+{
+    auto intError = mComposer.setDisplayElapseTime(mId, timeStamp);
+    return static_cast<Error>(intError);
+}
+
 Error Display::setPowerMode(PowerMode mode)
 {
     auto intMode = static_cast<Hwc2::IComposerClient::PowerMode>(mode);
@@ -983,6 +989,20 @@
   return static_cast<Error>(intError);
 }
 
+Error Layer::setType(uint32_t type)
+{
+    if (type == mType) {
+        return Error::NONE;
+    }
+    auto intError = mComposer.setLayerType(mDisplayId, mId, type);
+    Error error = static_cast<Error>(intError);
+    if (error != Error::NONE) {
+        return error;
+    }
+    mType = type;
+    return error;
+}
+
 // Composer HAL 2.3
 Error Layer::setColorTransform(const android::mat4& matrix) {
     if (matrix == mColorMatrix) {
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index 6819ff4..469baf7 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -236,6 +236,7 @@
     [[clang::warn_unused_result]] virtual hal::Error setContentType(hal::ContentType) = 0;
     [[clang::warn_unused_result]] virtual hal::Error getClientTargetProperty(
             hal::ClientTargetProperty* outClientTargetProperty) = 0;
+    [[clang::warn_unused_result]] virtual hal::Error setDisplayElapseTime(uint64_t timeStamp) = 0;
 };
 
 namespace impl {
@@ -308,6 +309,7 @@
             std::vector<hal::ContentType>* outSupportedContentTypes) const override;
     hal::Error setContentType(hal::ContentType) override;
     hal::Error getClientTargetProperty(hal::ClientTargetProperty* outClientTargetProperty) override;
+    hal::Error setDisplayElapseTime(uint64_t timeStamp) override;
 
     // Other Display methods
     hal::HWDisplayId getId() const override { return mId; }
@@ -342,7 +344,7 @@
     bool mIsConnected = false;
 
     std::unordered_map<hal::HWLayerId, std::unique_ptr<Layer>> mLayers;
-    std::unordered_map<hal::HWConfigId, std::shared_ptr<const Config>> mConfigs;
+    std::map<hal::HWConfigId, std::shared_ptr<const Config>> mConfigs;
 
     std::once_flag mDisplayCapabilityQueryFlag;
     std::unordered_set<hal::DisplayCapability> mDisplayCapabilities;
@@ -381,6 +383,7 @@
             const android::Region& region) = 0;
     [[clang::warn_unused_result]] virtual hal::Error setZOrder(uint32_t z) = 0;
     [[clang::warn_unused_result]] virtual hal::Error setInfo(uint32_t type, uint32_t appId) = 0;
+    [[clang::warn_unused_result]] virtual hal::Error setType(uint32_t type) = 0;
 
     // Composer HAL 2.3
     [[clang::warn_unused_result]] virtual hal::Error setColorTransform(
@@ -423,6 +426,7 @@
     hal::Error setVisibleRegion(const android::Region& region) override;
     hal::Error setZOrder(uint32_t z) override;
     hal::Error setInfo(uint32_t type, uint32_t appId) override;
+    hal::Error setType(uint32_t type) override;
 
     // Composer HAL 2.3
     hal::Error setColorTransform(const android::mat4& matrix) override;
@@ -449,6 +453,7 @@
     android::HdrMetadata mHdrMetadata;
     android::mat4 mColorMatrix;
     uint32_t mBufferSlot;
+    uint32_t mType{0};
 };
 
 } // namespace impl
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 7a2f0f3..910f99d 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -381,7 +381,11 @@
             ? DisplayConnectionType::Internal
             : DisplayConnectionType::External;
 
-    RETURN_IF_HWC_ERROR(error, displayId, FALLBACK_TYPE);
+    if (error != hal::Error::NONE) {
+      ALOGV("%s failed with error %s", __FUNCTION__, to_string(error).c_str());
+      return FALLBACK_TYPE;
+    }
+
     return type;
 }
 
@@ -585,6 +589,7 @@
         return NO_ERROR;
     }
 
+    displayData.lastPresentFence = Fence::NO_FENCE;
     auto error = hwcDisplay->present(&displayData.lastPresentFence);
     RETURN_IF_HWC_ERROR_FOR("present", error, displayId, UNKNOWN_ERROR);
 
@@ -606,10 +611,6 @@
         return INVALID_OPERATION;
     }
 
-    if (mode == hal::PowerMode::OFF) {
-        setVsyncEnabled(displayId, hal::Vsync::DISABLE);
-    }
-
     auto& hwcDisplay = displayData.hwcDisplay;
     switch (mode) {
         case hal::PowerMode::OFF:
@@ -1000,6 +1001,16 @@
     return mComposer->getMaxVirtualDisplayCount();
 }
 
+status_t HWComposer::setDisplayElapseTime(DisplayId displayId, uint64_t timeStamp) {
+    RETURN_IF_INVALID_DISPLAY(displayId, BAD_INDEX);
+    const auto& displayData = mDisplayData[displayId];
+
+    auto error = displayData.hwcDisplay->setDisplayElapseTime(timeStamp);
+    if (error == hal::Error::BAD_PARAMETER) RETURN_IF_HWC_ERROR(error, displayId, BAD_VALUE);
+    RETURN_IF_HWC_ERROR(error, displayId, UNKNOWN_ERROR);
+    return NO_ERROR;
+}
+
 } // namespace impl
 } // namespace android
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index c355ebd..eb90ab2 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -223,6 +223,7 @@
 
     virtual std::optional<DisplayId> toPhysicalDisplayId(hal::HWDisplayId hwcDisplayId) const = 0;
     virtual std::optional<hal::HWDisplayId> fromPhysicalDisplayId(DisplayId displayId) const = 0;
+    virtual status_t setDisplayElapseTime(DisplayId displayId, uint64_t timeStamp) = 0;
 };
 
 namespace impl {
@@ -319,6 +320,7 @@
 
     bool onVsync(hal::HWDisplayId hwcDisplayId, int64_t timestamp) override;
     void setVsyncEnabled(DisplayId displayId, hal::Vsync enabled) override;
+    status_t setDisplayElapseTime(DisplayId displayId, uint64_t timeStamp) override;
 
     nsecs_t getRefreshTimestamp(DisplayId displayId) const override;
     bool isConnected(DisplayId displayId) const override;
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
index 4b4c050..4f93996 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.cpp
@@ -127,6 +127,14 @@
     }
 }
 
+bool PowerAdvisor::canNotifyDisplayUpdateImminent() {
+    bool canNotify = mSendUpdateImminent.load();
+    if (mUseUpdateImminentTimer) {
+        mUpdateImminentTimer.reset();
+    }
+    return canNotify;
+}
+
 class HidlPowerHalWrapper : public PowerAdvisor::HalWrapper {
 public:
     HidlPowerHalWrapper(sp<V1_3::IPower> powerHal) : mPowerHal(std::move(powerHal)) {}
diff --git a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
index 95eb0e2..c94423c 100644
--- a/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
+++ b/services/surfaceflinger/DisplayHardware/PowerAdvisor.h
@@ -34,6 +34,7 @@
     virtual void onBootFinished() = 0;
     virtual void setExpensiveRenderingExpected(DisplayId displayId, bool expected) = 0;
     virtual void notifyDisplayUpdateImminent() = 0;
+    virtual bool canNotifyDisplayUpdateImminent() = 0;
 };
 
 namespace impl {
@@ -56,6 +57,7 @@
     void onBootFinished() override;
     void setExpensiveRenderingExpected(DisplayId displayId, bool expected) override;
     void notifyDisplayUpdateImminent() override;
+    bool canNotifyDisplayUpdateImminent() override;
 
 private:
     HalWrapper* getPowerHal() REQUIRES(mPowerHalMutex);
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index fba3261..aa368f7 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -62,7 +62,7 @@
                                              const sp<IGraphicBufferProducer>& sink,
                                              const sp<IGraphicBufferProducer>& bqProducer,
                                              const sp<IGraphicBufferConsumer>& bqConsumer,
-                                             const std::string& name)
+                                             const std::string& name, bool secure)
       : ConsumerBase(bqConsumer),
         mHwc(hwc),
         mDisplayId(displayId),
@@ -84,7 +84,9 @@
         mDbgState(DBG_STATE_IDLE),
         mDbgLastCompositionType(COMPOSITION_UNKNOWN),
         mMustRecompose(false),
-        mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv) {
+        mForceHwcCopy(SurfaceFlinger::useHwcForRgbToYuv),
+        mSecure(secure),
+        mSinkUsage(0) {
     mSource[SOURCE_SINK] = sink;
     mSource[SOURCE_SCRATCH] = bqProducer;
 
@@ -102,6 +104,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);
@@ -130,7 +134,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(mDbgState != DBG_STATE_IDLE,
             "Unexpected beginFrame() in %s state", dbgStateStr());
     mDbgState = DBG_STATE_BEGUN;
@@ -167,7 +175,7 @@
     }
 
     if (mCompositionType != COMPOSITION_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
@@ -179,7 +187,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();
     }
 
@@ -261,7 +269,7 @@
         int sslot = mapProducer2SourceSlot(SOURCE_SINK, mOutputProducerSlot);
         QueueBufferOutput qbo;
         VDS_LOGV("onFrameCommitted: queue sink sslot=%d", sslot);
-        if (mMustRecompose) {
+        if (retireFence->isValid() && mMustRecompose) {
             status_t result = mSource[SOURCE_SINK]->queueBuffer(sslot,
                     QueueBufferInput(
                         systemTime(), false /* isAutoTimestamp */,
@@ -323,7 +331,15 @@
 
 status_t VirtualDisplaySurface::dequeueBuffer(Source source,
         PixelFormat format, uint64_t usage, int* sslot, sp<Fence>* fence) {
-    LOG_FATAL_IF(!mDisplayId);
+    LOG_FATAL_IF(mDisplayId < 0, "mDisplayId=%d but should not be < 0.", mDisplayId);
+
+    // 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("dequeueBuffer(%s): updated scratch buffer usage flags=%#" PRIx64,
+                dbgSourceStr(source), usage);
+    }
 
     status_t result =
             mSource[source]->dequeueBuffer(sslot, fence, mSinkBufferWidth, mSinkBufferHeight,
@@ -350,11 +366,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("dequeueBuffer(%s): buffers[%d]=%p fmt=%d usage=%#" PRIx64,
                 dbgSourceStr(source), pslot, mProducerBuffers[pslot].get(),
@@ -414,7 +430,7 @@
                     mSinkBufferWidth, mSinkBufferHeight,
                     buf->getPixelFormat(), buf->getUsage());
             mOutputFormat = format;
-            mOutputUsage = usage;
+            setOutputUsage(usage);
             result = refreshOutputBuffer();
             if (result < 0)
                 return result;
@@ -695,6 +711,21 @@
     }
 }
 
+/* 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
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index 3cbad8f..337e91e 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -80,7 +80,8 @@
     VirtualDisplaySurface(HWComposer& hwc, const std::optional<DisplayId>& displayId,
                           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
@@ -131,6 +132,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
@@ -256,6 +258,8 @@
     compositionengine::impl::HwcBufferCache mHwcBufferCache;
 
     bool mForceHwcCopy;
+    bool mSecure;
+    int mSinkUsage;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp
index 8ad805b..134bd4b 100644
--- a/services/surfaceflinger/FrameTracker.cpp
+++ b/services/surfaceflinger/FrameTracker.cpp
@@ -101,6 +101,27 @@
     }
 }
 
+nsecs_t FrameTracker::getPreviousGfxInfo() {
+    Mutex::Autolock lock(mMutex);
+    size_t previous = -1;
+    if (mOffset > 0) {
+        previous = (mOffset-1) % NUM_FRAME_RECORDS;
+    } else if (mOffset == 0) {
+        previous = NUM_FRAME_RECORDS - 1;
+    }
+    if (previous >= 0) {
+        nsecs_t desiredPresentTime = mFrameRecords[previous].desiredPresentTime;
+        const std::shared_ptr<FenceTime>& rfence = mFrameRecords[previous].frameReadyFence;
+        if (rfence != nullptr) {
+            nsecs_t frameReadyTime = rfence->getSignalTime();
+            if (desiredPresentTime != INT64_MAX && frameReadyTime != INT64_MAX) {
+                return (frameReadyTime - desiredPresentTime);
+            }
+        }
+    }
+    return INT64_MAX;
+}
+
 void FrameTracker::clearStats() {
     Mutex::Autolock lock(mMutex);
     for (size_t i = 0; i < NUM_FRAME_RECORDS; i++) {
diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h
index 35382be..c552620 100644
--- a/services/surfaceflinger/FrameTracker.h
+++ b/services/surfaceflinger/FrameTracker.h
@@ -89,6 +89,9 @@
     // dumpStats dump appends the current frame display time history to the result string.
     void dumpStats(std::string& result) const;
 
+    //get previous frame gfx info.
+    nsecs_t getPreviousGfxInfo();
+
 private:
     struct FrameRecord {
         FrameRecord() :
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 6fe5ce5..9f933d8 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -67,9 +67,18 @@
 #include "MonitoredProducer.h"
 #include "SurfaceFlinger.h"
 #include "TimeStats/TimeStats.h"
+#include "QtiGralloc.h"
+
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+#include <config/client_interface.h>
+namespace DisplayConfig {
+    class ClientInterface;
+}
+#endif
 
 #define DEBUG_RESIZE 0
 
+using android::hardware::graphics::common::V1_0::BufferUsage;
 namespace android {
 
 using base::StringAppendF;
@@ -138,6 +147,8 @@
 
     mCallingPid = args.callingPid;
     mCallingUid = args.callingUid;
+    mDontScreenShot = args.metadata.getInt32(METADATA_WINDOW_TYPE_DONT_SCREENSHOT, 0) ?
+                      true : false;
 }
 
 void Layer::onFirstRef() {
@@ -493,9 +504,13 @@
     compositionState->geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse();
     compositionState->geomUsesSourceCrop = usesSourceCrop();
     compositionState->isSecure = isSecure();
+    compositionState->isSecureDisplay = isSecureDisplay();
+    compositionState->isSecureCamera = isSecureCamera();
+    compositionState->isScreenshot = isScreenshot();
 
     compositionState->type = type;
     compositionState->appId = appId;
+    compositionState->layerClass = mLayerClass;
 
     compositionState->metadata.clear();
     const auto& supportedMetadata = mFlinger->getHwComposer().getSupportedLayerGenericMetadata();
@@ -772,6 +787,23 @@
     return (s.flags & layer_state_t::eLayerSecure);
 }
 
+bool Layer::isSecureDisplay() const {
+    sp<const GraphicBuffer> buffer = getBuffer();
+    return buffer && (buffer->getUsage() & GRALLOC_USAGE_PRIVATE_SECURE_DISPLAY);
+}
+
+bool Layer::isSecureCamera() const {
+    sp<const GraphicBuffer> buffer = getBuffer();
+    bool protected_buffer = buffer && (buffer->getUsage() & BufferUsage::PROTECTED);
+    bool camera_output = buffer && (buffer->getUsage() & BufferUsage::CAMERA_OUTPUT);
+    return protected_buffer && camera_output;
+}
+
+bool Layer::isScreenshot() const {
+    return ((getName().find("ScreenshotSurface") != std::string::npos) ||
+            (getName().find("RotationLayer") != std::string::npos) ||
+            (getName().find("BackColorSurface") != std::string::npos));
+}
 // ----------------------------------------------------------------------------
 // transaction
 // ----------------------------------------------------------------------------
@@ -1333,17 +1365,23 @@
 int32_t Layer::getFrameRateSelectionPriority() const {
     // Check if layer has priority set.
     if (mDrawingState.frameRateSelectionPriority != PRIORITY_UNSET) {
-        return mDrawingState.frameRateSelectionPriority;
+        mPriority = mDrawingState.frameRateSelectionPriority;
+        return mPriority;
     }
     // If not, search whether its parents have it set.
     sp<Layer> parent = getParent();
     if (parent != nullptr) {
-        return parent->getFrameRateSelectionPriority();
+        mPriority = parent->getFrameRateSelectionPriority();
+        return mPriority;
     }
 
     return Layer::PRIORITY_UNSET;
 }
 
+int32_t Layer::getPriority() {
+    return mPriority;
+}
+
 bool Layer::isLayerFocusedBasedOnPriority(int32_t priority) {
     return priority == PRIORITY_FOCUSED_WITH_MODE || priority == PRIORITY_FOCUSED_WITHOUT_MODE;
 };
@@ -1464,6 +1502,13 @@
 
 void Layer::deferTransactionUntil_legacy(const sp<Layer>& barrierLayer, uint64_t frameNumber) {
     ATRACE_CALL();
+    if (mLayerDetached) {
+        // If the layer is detached, then we don't defer this transaction since we will not
+        // commit the pending state while the layer is detached. Adding sync points may cause
+        // the barrier layer to wait for the states to be committed before dequeuing a buffer.
+        return;
+    }
+
     mCurrentState.barrierLayer_legacy = barrierLayer;
     mCurrentState.frameNumber_legacy = frameNumber;
     // We don't set eTransactionNeeded, because just receiving a deferral
@@ -1510,6 +1555,36 @@
     if (mPotentialCursor) {
         usage |= GraphicBuffer::USAGE_CURSOR;
     }
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+    if (mDontScreenShot) {
+        // This is a WINDOW_TYPE_DONT_SCREENSHOT "mask" layer which needs to be CPU-read for
+        // special processing and programming of mask h/w IF the feature is supported.
+        static bool rc_supported = false;
+        static int read_rc_supported = true;
+        if (read_rc_supported) {
+          // Do this once per process lifetime.
+          read_rc_supported = false;
+          ::DisplayConfig::ClientInterface *DisplayConfigIntf = nullptr;
+          ::DisplayConfig::ClientInterface::Create("SurfaceFlinger::Layer" + std::to_string(0),
+              nullptr, &DisplayConfigIntf);
+          if (DisplayConfigIntf) {
+              std::string value = "0";
+              std::string rc_prop = "enable_rc_support";
+              int ret = DisplayConfigIntf->GetDebugProperty(rc_prop, &value);
+              ALOGI("enable_rc_support, ret:%d value:%s", ret, value.c_str());
+              if (!ret && (value == "1")) {
+                  DisplayConfigIntf->IsRCSupported(0, &rc_supported);
+              }
+              ::DisplayConfig::ClientInterface::Destroy(DisplayConfigIntf);
+          }
+          ALOGI("Mask layers are %sCPU-readable.", rc_supported ? "" : "*NOT* ");
+        }
+        if (rc_supported) {
+            usage |= GraphicBuffer::USAGE_SW_READ_RARELY;
+            usage |= GraphicBuffer::USAGE_SW_WRITE_RARELY;
+        }
+    }
+#endif  // QTI_DISPLAY_CONFIG_ENABLED
     usage |= GraphicBuffer::USAGE_HW_COMPOSER;
     return usage;
 }
@@ -1585,6 +1660,7 @@
     result.append(" Layer name\n");
     result.append("           Z | ");
     result.append(" Window Type | ");
+    result.append(" Layer Class | ");
     result.append(" Comp Type | ");
     result.append(" Transform | ");
     result.append("  Disp Frame (LTRB) | ");
@@ -1636,6 +1712,7 @@
         StringAppendF(&result, "  %10d | ", layerState.z);
     }
     StringAppendF(&result, "  %10d | ", mWindowType);
+    StringAppendF(&result, "  %10d | ", mLayerClass);
     StringAppendF(&result, "%10s | ", toString(getCompositionType(display)).c_str());
     StringAppendF(&result, "%10s | ", toString(outputLayerState.bufferTransform).c_str());
     const Rect& frame = outputLayerState.displayFrame;
@@ -2453,14 +2530,36 @@
     xSurfaceInset = (xSurfaceInset >= 0) ? std::min(xSurfaceInset, layerBounds.getWidth() / 2) : 0;
     ySurfaceInset = (ySurfaceInset >= 0) ? std::min(ySurfaceInset, layerBounds.getHeight() / 2) : 0;
 
-    layerBounds.inset(xSurfaceInset, ySurfaceInset, xSurfaceInset, ySurfaceInset);
+    // inset while protecting from overflow TODO(b/161235021): What is going wrong
+    // in the overflow scenario?
+    {
+    int32_t tmp;
+    if (!__builtin_add_overflow(layerBounds.left, xSurfaceInset, &tmp)) layerBounds.left = tmp;
+    if (!__builtin_sub_overflow(layerBounds.right, xSurfaceInset, &tmp)) layerBounds.right = tmp;
+    if (!__builtin_add_overflow(layerBounds.top, ySurfaceInset, &tmp)) layerBounds.top = tmp;
+    if (!__builtin_sub_overflow(layerBounds.bottom, ySurfaceInset, &tmp)) layerBounds.bottom = tmp;
+    }
 
     // Input coordinate should match the layer bounds.
     info.frameLeft = layerBounds.left;
     info.frameTop = layerBounds.top;
     info.frameRight = layerBounds.right;
     info.frameBottom = layerBounds.bottom;
-
+    // validate layer bound before access
+    //layer = #1
+    //layerBounds  l = 2147483647 t = -2147483648 r = 2147483647 b = -2147483648
+    //Todo:  Need to fix at framework level.
+    if (info.frameLeft > INT16_MAX || info.frameTop > INT16_MAX ||
+        info.frameRight > INT16_MAX || info.frameBottom > INT16_MAX ||
+        info.frameLeft < INT16_MIN || info.frameTop < INT16_MIN ||
+        info.frameRight < INT16_MIN || info.frameBottom < INT16_MIN) {
+        ALOGE("Layer %s left = %d top = %d right = %d  bottom = %d", getName().c_str(),
+               info.frameLeft, info.frameTop, info.frameRight,  info.frameBottom);
+        info.frameLeft = 0;
+        info.frameTop = 0;
+        info.frameRight = 0;
+        info.frameBottom = 0;
+    }
     // Position the touchable region relative to frame screen location and restrict it to frame
     // bounds.
     info.touchableRegion = info.touchableRegion.translate(info.frameLeft, info.frameTop);
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 6c5d114..1232185 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -418,6 +418,7 @@
     //  If the variable is not set on the layer, it traverses up the tree to inherit the frame
     //  rate priority from its parent.
     virtual int32_t getFrameRateSelectionPriority() const;
+    int32_t getPriority();
     static bool isLayerFocusedBasedOnPriority(int32_t priority);
 
     virtual ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; }
@@ -496,6 +497,10 @@
      */
     bool isSecure() const;
 
+    bool isSecureCamera() const;
+    bool isSecureDisplay() const;
+    bool isScreenshot() const;
+
     /*
      * isVisible - true if this layer is visible, false otherwise
      */
@@ -978,9 +983,9 @@
      */
     virtual bool needsInputInfo() const { return hasInputInfo(); }
 
-protected:
     compositionengine::OutputLayer* findOutputLayerForDisplay(const DisplayDevice*) const;
 
+protected:
     bool usingRelativeZ(LayerVector::StateSet stateSet) const;
 
     bool mPremultipliedAlpha{true};
@@ -988,6 +993,7 @@
     const std::string mTransactionName{"TX - " + mName};
 
     bool mPrimaryDisplayOnly = false;
+    bool mDontScreenShot = false;
 
     // These are only accessed by the main thread or the tracing thread.
     State mDrawingState;
@@ -1010,6 +1016,8 @@
     FenceTimeline mAcquireTimeline;
     FenceTimeline mReleaseTimeline;
 
+    uint32_t mLayerClass{0};
+
     // main thread
     sp<NativeHandle> mSidebandStream;
     // False if the buffer and its contents have been previously used for GPU
@@ -1114,6 +1122,8 @@
     // shadow radius is the set shadow radius, otherwise its the parent's shadow radius.
     float mEffectiveShadowRadius = 0.f;
 
+    mutable int32_t mPriority = Layer::PRIORITY_UNSET;
+
     // Returns true if the layer can draw shadows on its border.
     virtual bool canDrawShadows() const { return true; }
 
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 18a2891..a0441ae 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -58,6 +58,12 @@
                                           PixelFormat format, uint64_t usage,
                                           uint64_t* outBufferAge,
                                           FrameEventHistoryDelta* outTimestamps) {
+    if (mFlinger->mDolphinFuncsEnabled) {
+        sp<Layer> layer = mLayer.promote();
+        if (layer != nullptr) {
+            mFlinger->mDolphinDequeueBuffer(layer->getName().c_str());
+        }
+    }
     return mProducer->dequeueBuffer(slot, fence, w, h, format, usage, outBufferAge, outTimestamps);
 }
 
@@ -77,6 +83,12 @@
 
 status_t MonitoredProducer::queueBuffer(int slot, const QueueBufferInput& input,
         QueueBufferOutput* output) {
+    if (mFlinger->mDolphinFuncsEnabled) {
+        sp<Layer> layer = mLayer.promote();
+        if (layer != nullptr) {
+            mFlinger->mDolphinQueueBuffer(layer->getName().c_str());
+        }
+    }
     return mProducer->queueBuffer(slot, input, output);
 }
 
diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp
index ff91bf7..5c2bf61 100644
--- a/services/surfaceflinger/Scheduler/DispSync.cpp
+++ b/services/surfaceflinger/Scheduler/DispSync.cpp
@@ -671,7 +671,11 @@
 nsecs_t DispSync::getPeriod() {
     // lock mutex as mPeriod changes multiple times in updateModelLocked
     Mutex::Autolock lock(mMutex);
-    return mPeriod;
+    if (mPendingPeriod && !mModelUpdated) {
+        return mPendingPeriod;
+    } else {
+        return mPeriod;
+    }
 }
 
 void DispSync::updateModelLocked() {
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
index 8752b66..62c2066 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp
@@ -23,6 +23,7 @@
 #include "DispSyncSource.h"
 
 #include <android-base/stringprintf.h>
+#include <dlfcn.h>
 #include <utils/Trace.h>
 #include <mutex>
 
@@ -39,7 +40,21 @@
         mTraceVsync(traceVsync),
         mVsyncOnLabel(base::StringPrintf("VsyncOn-%s", name)),
         mDispSync(dispSync),
-        mPhaseOffset(base::StringPrintf("VsyncOffset-%s", name), phaseOffset) {}
+        mPhaseOffset(base::StringPrintf("VsyncOffset-%s", name), phaseOffset) {
+        mDolphinHandle = dlopen("libdolphin.so", RTLD_NOW);
+        if (!mDolphinHandle) {
+            ALOGW("Unable to open libdolphin.so: %s.", dlerror());
+        } else {
+            mDolphinCheck = (bool (*) (const char*))dlsym(mDolphinHandle, "dolphinCheck");
+            if (!mDolphinCheck)
+                dlclose(mDolphinHandle);
+        }
+}
+
+DispSyncSource::~DispSyncSource() {
+    if(mDolphinCheck)
+        dlclose(mDolphinHandle);
+}
 
 void DispSyncSource::setVSyncEnabled(bool enable) {
     std::lock_guard lock(mVsyncMutex);
@@ -58,6 +73,16 @@
             ALOGE("error unregistering vsync callback: %s (%d)", strerror(-err), err);
         }
         // ATRACE_INT(mVsyncOnLabel.c_str(), 0);
+        if (mDolphinCheck) {
+            if (mDolphinCheck(mName)) {
+                status_t err = mDispSync->addEventListener(mName, mPhaseOffset,
+                                                           static_cast<DispSync::Callback*>(this),
+                                                           mLastCallbackTime);
+                if (err != NO_ERROR) {
+                    ALOGE("error registering vsync callback: %s (%d)", strerror(-err), err);
+                }
+            }
+        }
     }
     mEnabled = enable;
 }
diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.h b/services/surfaceflinger/Scheduler/DispSyncSource.h
index 2aee3f6..cd54b63 100644
--- a/services/surfaceflinger/Scheduler/DispSyncSource.h
+++ b/services/surfaceflinger/Scheduler/DispSyncSource.h
@@ -28,7 +28,7 @@
 public:
     DispSyncSource(DispSync* dispSync, nsecs_t phaseOffset, bool traceVsync, const char* name);
 
-    ~DispSyncSource() override = default;
+    ~DispSyncSource();
 
     // The following methods are implementation of VSyncSource.
     const char* getName() const override { return mName; }
@@ -57,6 +57,8 @@
     mutable std::mutex mVsyncMutex;
     TracedOrdinal<nsecs_t> mPhaseOffset GUARDED_BY(mVsyncMutex);
     bool mEnabled GUARDED_BY(mVsyncMutex) = false;
+    void *mDolphinHandle = nullptr;
+    bool (*mDolphinCheck)(const char* name) = nullptr;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp
index cf57664..d4ded0a 100644
--- a/services/surfaceflinger/Scheduler/EventThread.cpp
+++ b/services/surfaceflinger/Scheduler/EventThread.cpp
@@ -20,6 +20,7 @@
 
 #define ATRACE_TAG ATRACE_TAG_GRAPHICS
 
+#include <dlfcn.h>
 #include <pthread.h>
 #include <sched.h>
 #include <sys/types.h>
@@ -125,7 +126,7 @@
       : resyncCallback(std::move(resyncCallback)),
         mConfigChanged(configChanged),
         mEventThread(eventThread),
-        mChannel(gui::BitTube::DefaultSize) {}
+        mChannel(gui::BitTube(8 * 1024 /* default size is 4KB, double it */)) {}
 
 EventThreadConnection::~EventThreadConnection() {
     // do nothing here -- clean-up will happen automatically
@@ -144,6 +145,7 @@
     }
 
     outChannel->setReceiveFd(mChannel.moveReceiveFd());
+    outChannel->setSendFd(base::unique_fd(dup(mChannel.getSendFd())));
     return NO_ERROR;
 }
 
@@ -157,11 +159,6 @@
     mEventThread->requestNextVsync(this);
 }
 
-void EventThreadConnection::requestLatestConfig() {
-    ATRACE_NAME("requestLatestConfig");
-    mEventThread->requestLatestConfig(this);
-}
-
 status_t EventThreadConnection::postEvent(const DisplayEventReceiver::Event& event) {
     ssize_t size = DisplayEventReceiver::sendEvents(&mChannel, &event, 1);
     return size < 0 ? status_t(size) : status_t(NO_ERROR);
@@ -198,10 +195,20 @@
     }
 
     set_sched_policy(tid, SP_FOREGROUND);
+    mDolphinHandle = dlopen("libdolphin.so", RTLD_NOW);
+    if (!mDolphinHandle) {
+        ALOGW("Unable to open libdolphin.so: %s.", dlerror());
+    } else {
+        mDolphinCheck = (bool (*) (const char*))dlsym(mDolphinHandle, "dolphinCheck");
+        if (!mDolphinCheck)
+            dlclose(mDolphinHandle);
+    }
 }
 
 EventThread::~EventThread() {
     mVSyncSource->setCallback(nullptr);
+    if(mDolphinCheck)
+        dlclose(mDolphinHandle);
 
     {
         std::lock_guard<std::mutex> lock(mMutex);
@@ -274,28 +281,6 @@
     }
 }
 
-void EventThread::requestLatestConfig(const sp<EventThreadConnection>& connection) {
-    std::lock_guard<std::mutex> lock(mMutex);
-    if (connection->mForcedConfigChangeDispatch) {
-        return;
-    }
-    connection->mForcedConfigChangeDispatch = true;
-    auto pendingConfigChange =
-            std::find_if(std::begin(mPendingEvents), std::end(mPendingEvents),
-                         [&](const DisplayEventReceiver::Event& event) {
-                             return event.header.type ==
-                                     DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED;
-                         });
-
-    // If we didn't find a pending config change event, then push out the
-    // latest one we've ever seen.
-    if (pendingConfigChange == std::end(mPendingEvents)) {
-        mPendingEvents.push_back(mLastConfigChangeEvent);
-    }
-
-    mCondition.notify_all();
-}
-
 void EventThread::onScreenReleased() {
     std::lock_guard<std::mutex> lock(mMutex);
     if (!mVSyncState || mVSyncState->synthetic) {
@@ -371,14 +356,12 @@
                         mInterceptVSyncsCallback(event->header.timestamp);
                     }
                     break;
-                case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED:
-                    mLastConfigChangeEvent = *event;
-                    break;
             }
         }
 
         bool vsyncRequested = false;
 
+        int aliveCount = 0;
         // Find connections that should consume this event.
         auto it = mDisplayEventConnections.begin();
         while (it != mDisplayEventConnections.end()) {
@@ -386,11 +369,9 @@
                 vsyncRequested |= connection->vsyncRequest != VSyncRequest::None;
 
                 if (event && shouldConsumeEvent(*event, connection)) {
-                    if (event->header.type == DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED &&
-                        connection->mForcedConfigChangeDispatch) {
-                        connection->mForcedConfigChangeDispatch = false;
-                    }
                     consumers.push_back(connection);
+                    if (mDolphinCheck)
+                        aliveCount++;
                 }
 
                 ++it;
@@ -398,6 +379,21 @@
                 it = mDisplayEventConnections.erase(it);
             }
         }
+        if (mDolphinCheck) {
+            if (event && aliveCount == 0 && mDolphinCheck(mThreadName)) {
+                auto it = mDisplayEventConnections.begin();
+                while (it != mDisplayEventConnections.end() && aliveCount == 0) {
+                    if (const auto connection = it->promote()) {
+                        consumers.push_back(connection);
+                        aliveCount++;
+                        mVSyncSource->setVSyncEnabled(false);
+                        ++it;
+                    } else {
+                        it = mDisplayEventConnections.erase(it);
+                    }
+                }
+            }
+        }
 
         if (!consumers.empty()) {
             dispatchEvent(*event, consumers);
@@ -465,9 +461,7 @@
             return true;
 
         case DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED: {
-            const bool oneTimeDispatch = connection->mForcedConfigChangeDispatch;
-            return oneTimeDispatch ||
-                    connection->mConfigChanged == ISurfaceComposer::eConfigChangedDispatch;
+            return connection->mConfigChanged == ISurfaceComposer::eConfigChangedDispatch;
         }
 
         case DisplayEventReceiver::DISPLAY_EVENT_VSYNC:
@@ -490,20 +484,26 @@
 
 void EventThread::dispatchEvent(const DisplayEventReceiver::Event& event,
                                 const DisplayEventConsumers& consumers) {
+    const uint8_t num_attempts = 3;
     for (const auto& consumer : consumers) {
-        switch (consumer->postEvent(event)) {
-            case NO_ERROR:
-                break;
+        bool needs_retry = true;
+        for (uint8_t attempt = 0; needs_retry && (attempt < num_attempts); attempt++) {
+            switch (consumer->postEvent(event)) {
+                case NO_ERROR:
+                    needs_retry = false;
+                    break;
 
-            case -EAGAIN:
-                // TODO: Try again if pipe is full.
-                ALOGW("Failed dispatching %s for %s", toString(event).c_str(),
-                      toString(*consumer).c_str());
-                break;
+                case -EAGAIN:
+                    ALOGW("Failed dispatching %s for %s. attempt %d", toString(event).c_str(),
+                          toString(*consumer).c_str(), attempt+1);
+                    needs_retry = true;
+                    break;
 
-            default:
-                // Treat EPIPE and other errors as fatal.
-                removeDisplayEventConnectionLocked(consumer);
+                default:
+                    // Treat EPIPE and other errors as fatal.
+                    removeDisplayEventConnectionLocked(consumer);
+                    needs_retry = false;
+            }
         }
     }
 }
diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h
index 831bf7b..461a26d 100644
--- a/services/surfaceflinger/Scheduler/EventThread.h
+++ b/services/surfaceflinger/Scheduler/EventThread.h
@@ -81,19 +81,13 @@
     status_t stealReceiveChannel(gui::BitTube* outChannel) override;
     status_t setVsyncRate(uint32_t rate) override;
     void requestNextVsync() override; // asynchronous
-    void requestLatestConfig() override; // asynchronous
 
     // Called in response to requestNextVsync.
     const ResyncCallback resyncCallback;
 
     VSyncRequest vsyncRequest = VSyncRequest::None;
-    ISurfaceComposer::ConfigChanged mConfigChanged =
+    const ISurfaceComposer::ConfigChanged mConfigChanged =
             ISurfaceComposer::ConfigChanged::eConfigChangedSuppress;
-    // Store whether we need to force dispatching a config change separately -
-    // if mConfigChanged ever changes before the config change is dispatched
-    // then we still need to propagate an initial config to the app if we
-    // haven't already.
-    bool mForcedConfigChangeDispatch = false;
 
 private:
     virtual void onFirstRef();
@@ -130,10 +124,6 @@
     virtual void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) = 0;
     // Requests the next vsync. If resetIdleTimer is set to true, it resets the idle timer.
     virtual void requestNextVsync(const sp<EventThreadConnection>& connection) = 0;
-    // Dispatches the most recent configuration
-    // Usage of this method assumes that only the primary internal display
-    // supports multiple display configurations.
-    virtual void requestLatestConfig(const sp<EventThreadConnection>& connection) = 0;
 
     // Retrieves the number of event connections tracked by this EventThread.
     virtual size_t getEventThreadConnectionCount() = 0;
@@ -154,7 +144,6 @@
     status_t registerDisplayEventConnection(const sp<EventThreadConnection>& connection) override;
     void setVsyncRate(uint32_t rate, const sp<EventThreadConnection>& connection) override;
     void requestNextVsync(const sp<EventThreadConnection>& connection) override;
-    void requestLatestConfig(const sp<EventThreadConnection>& connection) override;
 
     // called before the screen is turned off from main thread
     void onScreenReleased() override;
@@ -202,7 +191,6 @@
 
     std::vector<wp<EventThreadConnection>> mDisplayEventConnections GUARDED_BY(mMutex);
     std::deque<DisplayEventReceiver::Event> mPendingEvents GUARDED_BY(mMutex);
-    DisplayEventReceiver::Event mLastConfigChangeEvent GUARDED_BY(mMutex);
 
     // VSYNC state of connected display.
     struct VSyncState {
@@ -232,6 +220,8 @@
     State mState GUARDED_BY(mMutex) = State::Idle;
 
     static const char* toCString(State);
+    void *mDolphinHandle = nullptr;
+    bool (*mDolphinCheck)(const char* name) = nullptr;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
index 44f20d0..61602d7 100644
--- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
+++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp
@@ -27,6 +27,7 @@
 
 #undef LOG_TAG
 #define LOG_TAG "LayerInfoV2"
+#define MAX_FRAME_TIME 100000000
 
 namespace android::scheduler {
 
@@ -126,14 +127,19 @@
     bool missingPresentTime = false;
     int numFrames = 0;
     for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) {
+        bool noUpdate = false;
         // Ignore frames captured during a config change
         if (it->pendingConfigChange || (it + 1)->pendingConfigChange) {
             return std::nullopt;
         }
-
-        totalQueueTimeDeltas +=
-                std::max(((it + 1)->queueTime - it->queueTime), mHighRefreshRatePeriod);
-        numFrames++;
+        nsecs_t val = std::max(((it + 1)->queueTime - it->queueTime), mHighRefreshRatePeriod);
+        // Only if val < 10,000,000ns (10FPS) add to count.
+        if (val < MAX_FRAME_TIME) {
+            totalQueueTimeDeltas += val;
+            numFrames++;
+        } else {
+            noUpdate = true;
+        }
 
         if (!missingPresentTime && (it->presetTime == 0 || (it + 1)->presetTime == 0)) {
             missingPresentTime = true;
@@ -144,9 +150,15 @@
             }
             continue;
         }
-
-        totalPresentTimeDeltas +=
-                std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
+        // Check threshold here as well
+        val = std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod);
+        if (val < MAX_FRAME_TIME) {
+            totalPresentTimeDeltas += val;
+            if (noUpdate && !missingPresentTime) {
+                //If queueTime was out of bound but presentTime was in bound, increment numFrames
+                numFrames++;
+            }
+        }
     }
 
     // Calculate the average frame time based on presentation timestamps. If those
@@ -157,6 +169,9 @@
     // presentation timestamps we look at the queue time to see if the current refresh rate still
     // matches the content.
 
+    if (!numFrames) {
+        return std::nullopt;
+    }
     const auto averageFrameTime =
             static_cast<float>(missingPresentTime ? totalQueueTimeDeltas : totalPresentTimeDeltas) /
             numFrames;
diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp
index 6067e69..e68f03f 100644
--- a/services/surfaceflinger/Scheduler/MessageQueue.cpp
+++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp
@@ -123,6 +123,7 @@
     while ((n = DisplayEventReceiver::getEvents(&mEventTube, buffer, 8)) > 0) {
         for (int i = 0; i < n; i++) {
             if (buffer[i].header.type == DisplayEventReceiver::DISPLAY_EVENT_VSYNC) {
+                mFlinger->mVsyncTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
                 mHandler->dispatchInvalidate(buffer[i].vsync.expectedVSyncTimestamp);
                 break;
             }
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index fe2e406..e34f278 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -203,6 +203,23 @@
     return getPhaseOffsets(fps, static_cast<nsecs_t>(1e9f / fps));
 }
 
+void PhaseOffsets::UpdateSfOffsets(std::unordered_map<float, int64_t> advancedSfOffsets) {
+    for (auto& item: advancedSfOffsets) {
+        float fps = item.first;
+        auto iter = std::find_if(mOffsets.begin(), mOffsets.end(),
+                                 [&fps](const std::pair<float, Offsets>& candidateFps) {
+                                     return fpsEqualsWithMargin(fps, candidateFps.first);
+                                 });
+
+        if (iter != mOffsets.end()) {
+            auto& [early, earlyGl, late] = iter->second;
+            late.sf = item.second;
+            early.sf = item.second;
+            earlyGl.sf = item.second;
+        }
+    }
+}
+
 static void validateSysprops() {
     const auto validatePropertyBool = [](const char* prop) {
         LOG_ALWAYS_FATAL_IF(!property_get_bool(prop, false), "%s is false", prop);
@@ -354,5 +371,9 @@
                   mAppEarlyGlDuration, mSfEarlyGlDuration);
 }
 
+void PhaseDurations::UpdateSfOffsets(std::unordered_map<float, int64_t> advancedSfOffsets) {
+    ALOGW("UpdateSfOffsets not supported for map with size: %zu", advancedSfOffsets.size());
+}
+
 } // namespace impl
 } // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h
index 9ec6d56..b2b25a6 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.h
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h
@@ -41,6 +41,8 @@
     virtual void setRefreshRateFps(float fps) = 0;
 
     virtual void dump(std::string& result) const = 0;
+
+    virtual void UpdateSfOffsets(std::unordered_map<float, int64_t> advancedSfOffsets) = 0;
 };
 
 namespace impl {
@@ -66,6 +68,9 @@
     // Returns current offsets in human friendly format.
     void dump(std::string& result) const override;
 
+    // Update the Advanced Sf Offsets for the given refresh rates in mOffsets map.
+    void UpdateSfOffsets(std::unordered_map<float, int64_t> advancedSfOffsets) override;
+
 protected:
     // Used for unit tests
     PhaseOffsets(const std::vector<float>& refreshRates, float currentFps,
@@ -86,8 +91,8 @@
     const std::optional<nsecs_t> mEarlyAppOffsetNs;
     const std::optional<nsecs_t> mEarlyGlAppOffsetNs;
     const nsecs_t mThresholdForNextVsync;
-    const std::unordered_map<float, Offsets> mOffsets;
 
+    std::unordered_map<float, Offsets> mOffsets;
     std::atomic<float> mRefreshRateFps;
 };
 
@@ -113,6 +118,9 @@
     // Returns current offsets in human friendly format.
     void dump(std::string& result) const override;
 
+    // Update the Advanced Sf Offsets for the given refresh rates in mOffsets map.
+    void UpdateSfOffsets(std::unordered_map<float, int64_t> advancedSfOffsets) override;
+
 protected:
     // Used for unit tests
     PhaseDurations(const std::vector<float>& refreshRates, float currentFps, nsecs_t sfDuration,
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 5c0ba01..cca3d57 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -182,29 +182,39 @@
     auto vsyncSource = makePrimaryDispSyncSource(connectionName, phaseOffsetNs);
     auto eventThread = std::make_unique<impl::EventThread>(std::move(vsyncSource),
                                                            std::move(interceptCallback));
-    return createConnection(std::move(eventThread));
+    bool triggerRefresh = !strcmp(connectionName, "app");
+    return createConnection(std::move(eventThread), triggerRefresh);
 }
 
-Scheduler::ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread) {
+Scheduler::ConnectionHandle Scheduler::createConnection(std::unique_ptr<EventThread> eventThread,
+                                                        bool triggerRefresh) {
     const ConnectionHandle handle = ConnectionHandle{mNextConnectionHandleId++};
     ALOGV("Creating a connection handle with ID %" PRIuPTR, handle.id);
 
     auto connection =
-            createConnectionInternal(eventThread.get(), ISurfaceComposer::eConfigChangedSuppress);
+            createConnectionInternal(eventThread.get(), ISurfaceComposer::eConfigChangedSuppress,
+                                     triggerRefresh);
 
     mConnections.emplace(handle, Connection{connection, std::move(eventThread)});
     return handle;
 }
 
-sp<EventThreadConnection> Scheduler::createConnectionInternal(
-        EventThread* eventThread, ISurfaceComposer::ConfigChanged configChanged) {
-    return eventThread->createEventConnection([&] { resync(); }, configChanged);
+sp<EventThreadConnection> Scheduler::createConnectionInternal(EventThread* eventThread,
+        ISurfaceComposer::ConfigChanged configChanged, bool triggerRefresh) {
+    // Refresh need to be triggered from app thread alone.
+    // Triggering it from sf connection can result in infinite loop due to requestnextvsync.
+    if (triggerRefresh) {
+        return eventThread->createEventConnection([&] { resyncAndRefresh(); }, configChanged);
+    } else {
+        return eventThread->createEventConnection([&] { resync(); }, configChanged);
+    }
 }
 
-sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(
-        ConnectionHandle handle, ISurfaceComposer::ConfigChanged configChanged) {
+sp<IDisplayEventConnection> Scheduler::createDisplayEventConnection(ConnectionHandle handle,
+        ISurfaceComposer::ConfigChanged configChanged, bool triggerRefresh) {
     RETURN_IF_INVALID_HANDLE(handle, nullptr);
-    return createConnectionInternal(mConnections[handle].thread.get(), configChanged);
+    return createConnectionInternal(mConnections[handle].thread.get(), configChanged,
+                                    triggerRefresh);
 }
 
 sp<EventThreadConnection> Scheduler::getEventConnection(ConnectionHandle handle) {
@@ -297,7 +307,7 @@
                 std::make_unique<impl::EventThread>(std::move(vsyncSource),
                                                     impl::EventThread::InterceptVSyncsCallback());
 
-        mInjectorConnectionHandle = createConnection(std::move(eventThread));
+        mInjectorConnectionHandle = createConnection(std::move(eventThread), false /* No Refresh */);
     }
 
     mInjectVSyncs = enable;
@@ -334,7 +344,7 @@
     }
 }
 
-void Scheduler::resyncToHardwareVsync(bool makeAvailable, nsecs_t period) {
+void Scheduler::resyncToHardwareVsync(bool makeAvailable, nsecs_t period, bool force_resync) {
     {
         std::lock_guard<std::mutex> lock(mHWVsyncLock);
         if (makeAvailable) {
@@ -350,7 +360,21 @@
         return;
     }
 
-    setVsyncPeriod(period);
+    setVsyncPeriod(period, force_resync);
+}
+
+void Scheduler::resyncAndRefresh() {
+    resync();
+
+    if (!mDisplayIdle) {
+        return;
+    }
+
+    ATRACE_CALL();
+    const auto& refreshRate = mRefreshRateConfigs.getCurrentRefreshRate();
+    mSchedulerCallback.repaintEverythingForHWC();
+    resyncToHardwareVsync(true /* makeAvailable */, refreshRate.getVsyncPeriod(), true);
+    mDisplayIdle = false;
 }
 
 void Scheduler::resync() {
@@ -364,11 +388,11 @@
     }
 }
 
-void Scheduler::setVsyncPeriod(nsecs_t period) {
+void Scheduler::setVsyncPeriod(nsecs_t period, bool force_resync) {
     std::lock_guard<std::mutex> lock(mHWVsyncLock);
     mPrimaryDispSync->setPeriod(period);
 
-    if (!mPrimaryHWVsyncEnabled) {
+    if (!mPrimaryHWVsyncEnabled || force_resync) {
         mPrimaryDispSync->beginResync();
         mEventControlThread->setVsyncEnabled(true);
         mPrimaryHWVsyncEnabled = true;
@@ -708,4 +732,8 @@
     }
 }
 
+void Scheduler::setIdleState() {
+    mDisplayIdle = true;
+}
+
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 730ea8f..ed735d8 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -87,7 +87,8 @@
                                       impl::EventThread::InterceptVSyncsCallback);
 
     sp<IDisplayEventConnection> createDisplayEventConnection(ConnectionHandle,
-                                                             ISurfaceComposer::ConfigChanged);
+                                                             ISurfaceComposer::ConfigChanged,
+                                                             bool triggerRefresh);
 
     sp<EventThreadConnection> getEventConnection(ConnectionHandle);
 
@@ -119,8 +120,9 @@
     // Otherwise, if hardware vsync is not already enabled then this method will
     // no-op.
     // The period is the vsync period from the current display configuration.
-    void resyncToHardwareVsync(bool makeAvailable, nsecs_t period);
+    void resyncToHardwareVsync(bool makeAvailable, nsecs_t period, bool force_resync = false);
     void resync();
+    void resyncAndRefresh();
 
     // Passes a vsync sample to DispSync. periodFlushed will be true if
     // DispSync detected that the vsync period changed, and false otherwise.
@@ -163,6 +165,8 @@
 
     size_t getEventThreadConnectionCount(ConnectionHandle handle);
 
+    void setIdleState();
+
 private:
     friend class TestableScheduler;
 
@@ -180,9 +184,10 @@
     std::unique_ptr<VSyncSource> makePrimaryDispSyncSource(const char* name, nsecs_t phaseOffsetNs);
 
     // Create a connection on the given EventThread.
-    ConnectionHandle createConnection(std::unique_ptr<EventThread>);
+    ConnectionHandle createConnection(std::unique_ptr<EventThread>, bool triggerRefresh);
     sp<EventThreadConnection> createConnectionInternal(EventThread*,
-                                                       ISurfaceComposer::ConfigChanged);
+                                                       ISurfaceComposer::ConfigChanged,
+                                                       bool triggerRefresh);
 
     // Update feature state machine to given state when corresponding timer resets or expires.
     void kernelIdleTimerCallback(TimerState);
@@ -194,7 +199,7 @@
     template <class T>
     bool handleTimerStateChanged(T* currentState, T newState);
 
-    void setVsyncPeriod(nsecs_t period);
+    void setVsyncPeriod(nsecs_t period, bool force_resync = false);
 
     // This function checks whether individual features that are affecting the refresh rate
     // selection were initialized, prioritizes them, and calculates the HwcConfigIndexType
@@ -279,6 +284,8 @@
     const bool mUseContentDetection;
     // This variable indicates whether to use V2 version of the content detection.
     const bool mUseContentDetectionV2;
+    // This flag indicates display in idle. Refresh as and when vsync is requested.
+    bool mDisplayIdle;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
index a596bce..2a6fd05 100644
--- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.cpp
@@ -243,7 +243,8 @@
     std::vector<Invocation> invocations;
     {
         std::lock_guard<decltype(mMutex)> lk(mMutex);
-        mLastTimerCallback = mTimeKeeper->now();
+        auto const now = mTimeKeeper->now();
+        mLastTimerCallback = now;
         for (auto it = mCallbacks.begin(); it != mCallbacks.end(); it++) {
             auto& callback = it->second;
             auto const wakeupTime = callback->wakeupTime();
@@ -251,7 +252,8 @@
                 continue;
             }
 
-            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack) {
+            auto const lagAllowance = std::max(now - mIntendedWakeupTime, static_cast<nsecs_t>(0));
+            if (*wakeupTime < mIntendedWakeupTime + mTimerSlack + lagAllowance) {
                 callback->executing();
                 invocations.emplace_back(
                         Invocation{callback, *callback->lastExecutedVsyncTarget(), *wakeupTime});
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
index ab5773d..61f3fbb 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp
@@ -255,21 +255,9 @@
     }
 }
 
-bool VSyncPredictor::needsMoreSamples(nsecs_t now) const {
-    using namespace std::literals::chrono_literals;
+bool VSyncPredictor::needsMoreSamples() const {
     std::lock_guard<std::mutex> lk(mMutex);
-    bool needsMoreSamples = true;
-    if (mTimestamps.size() >= kMinimumSamplesForPrediction) {
-        nsecs_t constexpr aLongTime =
-                std::chrono::duration_cast<std::chrono::nanoseconds>(500ms).count();
-        if (!(mLastTimestampIndex < 0 || mTimestamps.empty())) {
-            auto const lastTimestamp = mTimestamps[mLastTimestampIndex];
-            needsMoreSamples = !((lastTimestamp + aLongTime) > now);
-        }
-    }
-
-    ATRACE_INT("VSP-moreSamples", needsMoreSamples);
-    return needsMoreSamples;
+    return mTimestamps.size() < kMinimumSamplesForPrediction;
 }
 
 void VSyncPredictor::resetModel() {
diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.h b/services/surfaceflinger/Scheduler/VSyncPredictor.h
index 3ca878d..5f3c418 100644
--- a/services/surfaceflinger/Scheduler/VSyncPredictor.h
+++ b/services/surfaceflinger/Scheduler/VSyncPredictor.h
@@ -52,11 +52,10 @@
      */
     void setPeriod(nsecs_t period) final;
 
-    /* Query if the model is in need of more samples to make a prediction at timePoint.
-     * \param [in] timePoint    The timePoint to inquire of.
+    /* Query if the model is in need of more samples to make a prediction.
      * \return  True, if model would benefit from more samples, False if not.
      */
-    bool needsMoreSamples(nsecs_t timePoint) const;
+    bool needsMoreSamples() const final;
 
     std::tuple<nsecs_t /* slope */, nsecs_t /* intercept */> getVSyncPredictionModel() const;
 
diff --git a/services/surfaceflinger/Scheduler/VSyncReactor.cpp b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
index c743de0..efa8bab 100644
--- a/services/surfaceflinger/Scheduler/VSyncReactor.cpp
+++ b/services/surfaceflinger/Scheduler/VSyncReactor.cpp
@@ -233,6 +233,7 @@
 }
 
 void VSyncReactor::startPeriodTransition(nsecs_t newPeriod) {
+    ATRACE_CALL();
     mPeriodConfirmationInProgress = true;
     mPeriodTransitioningTo = newPeriod;
     mMoreSamplesNeeded = true;
@@ -240,8 +241,7 @@
 }
 
 void VSyncReactor::endPeriodTransition() {
-    setIgnorePresentFencesInternal(false);
-    mMoreSamplesNeeded = false;
+    ATRACE_CALL();
     mPeriodTransitioningTo.reset();
     mPeriodConfirmationInProgress = false;
     mLastHwVsync.reset();
@@ -254,6 +254,8 @@
 
     if (!mSupportKernelIdleTimer && period == getPeriod()) {
         endPeriodTransition();
+        setIgnorePresentFencesInternal(false);
+        mMoreSamplesNeeded = false;
     } else {
         startPeriodTransition(period);
     }
@@ -303,6 +305,7 @@
 
     std::lock_guard<std::mutex> lk(mMutex);
     if (periodConfirmed(timestamp, hwcVsyncPeriod)) {
+        ATRACE_NAME("VSR: period confirmed");
         if (mPeriodTransitioningTo) {
             mTracker->setPeriod(*mPeriodTransitioningTo);
             for (auto& entry : mCallbacks) {
@@ -310,17 +313,29 @@
             }
             *periodFlushed = true;
         }
+
+        if (mLastHwVsync) {
+            mTracker->addVsyncTimestamp(*mLastHwVsync);
+        }
+        mTracker->addVsyncTimestamp(timestamp);
+
         endPeriodTransition();
+        mMoreSamplesNeeded = mTracker->needsMoreSamples();
     } else if (mPeriodConfirmationInProgress) {
+        ATRACE_NAME("VSR: still confirming period");
         mLastHwVsync = timestamp;
         mMoreSamplesNeeded = true;
         *periodFlushed = false;
     } else {
-        mMoreSamplesNeeded = false;
+        ATRACE_NAME("VSR: adding sample");
         *periodFlushed = false;
+        mTracker->addVsyncTimestamp(timestamp);
+        mMoreSamplesNeeded = mTracker->needsMoreSamples();
     }
 
-    mTracker->addVsyncTimestamp(timestamp);
+    if (!mMoreSamplesNeeded) {
+        setIgnorePresentFencesInternal(false);
+    }
     return mMoreSamplesNeeded;
 }
 
diff --git a/services/surfaceflinger/Scheduler/VSyncTracker.h b/services/surfaceflinger/Scheduler/VSyncTracker.h
index 05a6fc3..107c540 100644
--- a/services/surfaceflinger/Scheduler/VSyncTracker.h
+++ b/services/surfaceflinger/Scheduler/VSyncTracker.h
@@ -66,6 +66,8 @@
     /* Inform the tracker that the samples it has are not accurate for prediction. */
     virtual void resetModel() = 0;
 
+    virtual bool needsMoreSamples() const = 0;
+
     virtual void dump(std::string& result) const = 0;
 
 protected:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 14da0c5..bcd14c0 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -65,6 +65,8 @@
 #include <renderengine/RenderEngine.h>
 #include <statslog.h>
 #include <sys/types.h>
+#include <sys/stat.h>
+#include <fstream>
 #include <ui/ColorSpace.h>
 #include <ui/DebugUtils.h>
 #include <ui/DisplayConfig.h>
@@ -126,6 +128,19 @@
 #include "TimeStats/TimeStats.h"
 #include "android-base/parseint.h"
 #include "android-base/stringprintf.h"
+#include <composer_extn_intf.h>
+
+#include "frame_extn_intf.h"
+#include "smomo_interface.h"
+#include "QtiGralloc.h"
+#include "layer_extn_intf.h"
+
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+#include <config/client_interface.h>
+namespace DisplayConfig {
+class ClientInterface;
+}
+#endif
 
 #define MAIN_THREAD ACQUIRE(mStateLock) RELEASE(mStateLock)
 
@@ -136,9 +151,20 @@
         return (expr);                                             \
     }()
 
-#undef NO_THREAD_SAFETY_ANALYSIS
-#define NO_THREAD_SAFETY_ANALYSIS \
-    _Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"")
+// TODO(b/157175504): Restore NO_THREAD_SAFETY_ANALYSIS prohibition and fix all
+//   identified issues.
+//#undef NO_THREAD_SAFETY_ANALYSIS
+//#define NO_THREAD_SAFETY_ANALYSIS \
+//    _Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"")
+
+composer::ComposerExtnLib composer::ComposerExtnLib::g_composer_ext_lib_;
+
+#ifdef PHASE_OFFSET_EXTN
+struct ComposerExtnIntf {
+    composer::PhaseOffsetExtnIntf *phaseOffsetExtnIntf = nullptr;
+};
+struct ComposerExtnIntf g_comp_ext_intf_;
+#endif
 
 namespace android {
 
@@ -251,6 +277,20 @@
     std::function<void()> mCallback;
 };
 
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+class DisplayConfigCallbackHandler : public ::DisplayConfig::ConfigCallback {
+public:
+    DisplayConfigCallbackHandler(SurfaceFlinger& flinger) : mFlinger(flinger) {
+    }
+    void NotifyIdleStatus(bool is_idle) {
+      ALOGV("received idle notification");
+      ATRACE_CALL();
+      mFlinger.NotifyIdleStatus();
+    }
+  private:
+    SurfaceFlinger& mFlinger;
+};
+#endif
 }  // namespace anonymous
 
 // ---------------------------------------------------------------------------
@@ -279,7 +319,11 @@
 Dataspace SurfaceFlinger::wideColorGamutCompositionDataspace = Dataspace::V0_SRGB;
 ui::PixelFormat SurfaceFlinger::wideColorGamutCompositionPixelFormat = ui::PixelFormat::RGBA_8888;
 bool SurfaceFlinger::useFrameRateApi;
-
+bool SurfaceFlinger::sDirectStreaming;
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+::DisplayConfig::ClientInterface *mDisplayConfigIntf = nullptr;
+DisplayConfigCallbackHandler *mDisplayConfigCallbackhandler = nullptr;
+#endif
 std::string getHwcServiceName() {
     char value[PROPERTY_VALUE_MAX] = {};
     property_get("debug.sf.hwc_service_name", value, "default");
@@ -310,6 +354,84 @@
 
 SurfaceFlingerBE::SurfaceFlingerBE() : mHwcServiceName(getHwcServiceName()) {}
 
+bool SmomoWrapper::init() {
+    mSmoMoLibHandle = dlopen(SMOMO_LIBRARY_NAME, RTLD_NOW);
+    if (!mSmoMoLibHandle) {
+        ALOGE("Unable to open SmoMo lib: %s", dlerror());
+        return false;
+    }
+
+    mSmoMoCreateFunc =
+        reinterpret_cast<CreateSmoMoFuncPtr>(dlsym(mSmoMoLibHandle,
+            CREATE_SMOMO_INTERFACE_NAME));
+    mSmoMoDestroyFunc =
+        reinterpret_cast<DestroySmoMoFuncPtr>(dlsym(mSmoMoLibHandle,
+            DESTROY_SMOMO_INTERFACE_NAME));
+
+    if (!mSmoMoCreateFunc || !mSmoMoDestroyFunc) {
+        ALOGE("Can't load SmoMo symbols: %s", dlerror());
+        dlclose(mSmoMoLibHandle);
+        return false;
+    }
+
+    if (!mSmoMoCreateFunc(SMOMO_VERSION_TAG, &mInst)) {
+        ALOGE("Unable to create SmoMo interface");
+        dlclose(mSmoMoLibHandle);
+        return false;
+    }
+
+    return true;
+}
+
+SmomoWrapper::~SmomoWrapper() {
+    if (mInst) {
+        mSmoMoDestroyFunc(mInst);
+    }
+
+    if (mSmoMoLibHandle) {
+      dlclose(mSmoMoLibHandle);
+    }
+}
+
+bool LayerExtWrapper::init() {
+    mLayerExtLibHandle = dlopen(LAYER_EXTN_LIBRARY_NAME, RTLD_NOW);
+    if (!mLayerExtLibHandle) {
+        ALOGE("Unable to open layer ext lib: %s", dlerror());
+        return false;
+    }
+
+    mLayerExtCreateFunc =
+        reinterpret_cast<CreateLayerExtnFuncPtr>(dlsym(mLayerExtLibHandle,
+            CREATE_LAYER_EXTN_INTERFACE));
+    mLayerExtDestroyFunc =
+        reinterpret_cast<DestroyLayerExtnFuncPtr>(dlsym(mLayerExtLibHandle,
+            DESTROY_LAYER_EXTN_INTERFACE));
+
+    if (!mLayerExtCreateFunc || !mLayerExtDestroyFunc) {
+        ALOGE("Can't load layer ext symbols: %s", dlerror());
+        dlclose(mLayerExtLibHandle);
+        return false;
+    }
+
+    if (!mLayerExtCreateFunc(LAYER_EXTN_VERSION_TAG, &mInst)) {
+        ALOGE("Unable to create layer ext interface");
+        dlclose(mLayerExtLibHandle);
+        return false;
+    }
+
+    return true;
+}
+
+LayerExtWrapper::~LayerExtWrapper() {
+    if (mInst) {
+        mLayerExtDestroyFunc(mInst);
+    }
+
+    if (mLayerExtLibHandle) {
+      dlclose(mLayerExtLibHandle);
+    }
+}
+
 SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag)
       : mFactory(factory),
         mInterceptor(mFactory.createSurfaceInterceptor(this)),
@@ -420,6 +542,13 @@
     property_get("ro.sf.blurs_are_expensive", value, "0");
     mBlursAreExpensive = atoi(value);
 
+    property_get("vendor.display.enable_fb_scaling", value, "0");
+    mUseFbScaling = atoi(value);
+    ALOGI_IF(mUseFbScaling, "Enable FrameBuffer Scaling");
+    property_get("debug.sf.enable_advanced_sf_phase_offset", value, "0");
+    mUseAdvanceSfOffset = atoi(value);
+    ALOGI_IF(mUseAdvanceSfOffset, "Enable Advance SF Phase Offset");
+
     const size_t defaultListSize = ISurfaceComposer::MAX_LAYERS;
     auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize));
     mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize;
@@ -430,6 +559,21 @@
     property_get("debug.sf.disable_client_composition_cache", value, "0");
     mDisableClientCompositionCache = atoi(value);
 
+    char property[PROPERTY_VALUE_MAX] = {0};
+    if((property_get("vendor.display.vsync_reliable_on_doze", property, "0") > 0) &&
+        (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        mVsyncSourceReliableOnDoze = true;
+    }
+
+    // If mPluggableVsyncPrioritized is true then the order of priority of V-syncs is Pluggable
+    // followed by Primary and Secondary built-ins.
+    if((property_get("vendor.display.pluggable_vsync_prioritized", property, "0") > 0) &&
+        (!strncmp(property, "1", PROPERTY_VALUE_MAX ) ||
+        (!strncasecmp(property,"true", PROPERTY_VALUE_MAX )))) {
+        mPluggableVsyncPrioritized = true;
+    }
+
     // We should be reading 'persist.sys.sf.color_saturation' here
     // but since /data may be encrypted, we need to wait until after vold
     // comes online to attempt to read the property. The property is
@@ -445,12 +589,82 @@
     }
 
     useFrameRateApi = use_frame_rate_api(true);
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+    mDisplayConfigCallbackhandler = new DisplayConfigCallbackHandler(*this);
+    int ret = ::DisplayConfig::ClientInterface::Create("SurfaceFlinger"+std::to_string(0),
+                                                        mDisplayConfigCallbackhandler,
+                                                        &mDisplayConfigIntf);
+    if (ret || !mDisplayConfigIntf) {
+        ALOGE("DisplayConfig HIDL not present\n");
+        mDisplayConfigIntf = nullptr;
+    }
 
+    if (mDisplayConfigIntf) {
+#ifdef DISPLAY_CONFIG_API_LEVEL_1
+        std::string value = "";
+        std::string qsync_prop = "enable_qsync_idle";
+        ret = mDisplayConfigIntf->GetDebugProperty(qsync_prop, &value);
+        ALOGI("enable_qsync_idle, ret:%d value:%s", ret, value.c_str());
+        if (!ret && (value == "1")) {
+          mDisplayConfigIntf->ControlIdleStatusCallback(true);
+        }
+#endif
+    }
+#endif
     mKernelIdleTimerEnabled = mSupportKernelIdleTimer = sysprop::support_kernel_idle_timer(false);
     base::SetProperty(KERNEL_IDLE_TIMER_PROP, mKernelIdleTimerEnabled ? "true" : "false");
+
+    mDolphinHandle = dlopen("libdolphin.so", RTLD_NOW);
+    if (!mDolphinHandle) {
+        ALOGW("Unable to open libdolphin.so: %s.", dlerror());
+    } else {
+        mDolphinInit = (bool (*) ())dlsym(mDolphinHandle, "dolphinInit");
+        mDolphinMonitor = (bool (*) (int, nsecs_t))dlsym(mDolphinHandle, "dolphinMonitor");
+        mDolphinScaling = (void (*)(int, int))dlsym(mDolphinHandle, "dolphinScaling");
+        mDolphinRefresh = (void (*) ())dlsym(mDolphinHandle, "dolphinRefresh");
+        mDolphinDequeueBuffer = (void (*)(const char *))dlsym(mDolphinHandle,
+                "dolphinDequeueBuffer");
+        mDolphinQueueBuffer = (void (*)(const char *))dlsym(mDolphinHandle,
+                "dolphinQueueBuffer");
+        bool allDolphinSymbolsFound = mDolphinInit && mDolphinMonitor &&
+                mDolphinScaling && mDolphinRefresh && mDolphinDequeueBuffer &&
+                mDolphinQueueBuffer;
+        if (allDolphinSymbolsFound && mDolphinInit()) {
+            mDolphinFuncsEnabled = true;
+        }
+        if (!mDolphinFuncsEnabled)
+            dlclose(mDolphinHandle);
+    }
+
+    mFrameExtnLibHandle = dlopen(EXTENSION_LIBRARY_NAME, RTLD_NOW);
+    if (!mFrameExtnLibHandle) {
+        ALOGE("Unable to open libframeextension.so: %s.", dlerror());
+    } else {
+        mCreateFrameExtnFunc =
+            (bool (*) (composer::FrameExtnIntf**))(dlsym(mFrameExtnLibHandle,
+                                                                CREATE_FRAME_EXTN_INTERFACE));
+        mDestroyFrameExtnFunc =
+            (bool (*) (composer::FrameExtnIntf*))(dlsym(mFrameExtnLibHandle,
+                                                                 DESTROY_FRAME_EXTN_INTERFACE));
+        if (mCreateFrameExtnFunc && mDestroyFrameExtnFunc) {
+            mCreateFrameExtnFunc(&mFrameExtn);
+            if (!mFrameExtn) {
+                ALOGE("Frame Extension Object create failed.");
+                dlclose(mFrameExtnLibHandle);
+            }
+        } else {
+            ALOGE("Can't load libframeextension symbols: %s", dlerror());
+            dlclose(mFrameExtnLibHandle);
+        }
+    }
 }
 
-SurfaceFlinger::~SurfaceFlinger() = default;
+SurfaceFlinger::~SurfaceFlinger() {
+    if (mDolphinFuncsEnabled)
+        dlclose(mDolphinHandle);
+    if (mFrameExtn)
+        dlclose(mFrameExtnLibHandle);
+}
 
 void SurfaceFlinger::onFirstRef() {
     mEventQueue->init(this);
@@ -630,7 +844,20 @@
         if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) {
             enableRefreshRateOverlay(true);
         }
+        if (mUseFbScaling) {
+            Mutex::Autolock _l(mStateLock);
+            ssize_t index = mCurrentState.displays.indexOfKey(getInternalDisplayTokenLocked());
+            if (index < 0) {
+                ALOGE("Invalid token %p", getInternalDisplayTokenLocked().get());
+            } else {
+                const DisplayDeviceState& state = mCurrentState.displays.valueAt(index);
+                setFrameBufferSizeForScaling(getDefaultDisplayDeviceLocked(), state);
+            }
+        }
+
     }));
+
+    setupEarlyWakeUpFeature();
 }
 
 uint32_t SurfaceFlinger::getNewTexture() {
@@ -699,6 +926,15 @@
     LOG_ALWAYS_FATAL_IF(!display, "Missing internal display after registering composer callback.");
     LOG_ALWAYS_FATAL_IF(!getHwComposer().isConnected(*display->getId()),
                         "Internal display is disconnected.");
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+    if (!mDisplayConfigIntf) {
+        ALOGE("DisplayConfig HIDL not present\n");
+        mDisplayConfigIntf = nullptr;
+    } else {
+        mDisplayConfigIntf->IsAsyncVDSCreationSupported(&mAsyncVdsCreationSupported);
+        ALOGI("IsAsyncVDSCreationSupported %d", mAsyncVdsCreationSupported);
+    }
+#endif
 
     if (useVrFlinger) {
         auto vrFlingerRequestDisplayCallback = [this](bool requestDisplay) {
@@ -746,6 +982,56 @@
         ALOGE("Run StartPropertySetThread failed!");
     }
 
+    char smomoProp[PROPERTY_VALUE_MAX];
+    property_get("vendor.display.use_smooth_motion", smomoProp, "0");
+    if (atoi(smomoProp) && mSmoMo.init()) {
+        mSmoMo->SetChangeRefreshRateCallback(
+            [this](int32_t refreshRate) {
+                setRefreshRateTo(refreshRate);
+            });
+
+        std::vector<float> refreshRates;
+        auto iter = mRefreshRateConfigs->getAllRefreshRates().cbegin();
+        while (iter != mRefreshRateConfigs->getAllRefreshRates().cend()) {
+            if (iter->second->getFps() > 0) {
+                refreshRates.push_back(iter->second->getFps());
+            }
+            ++iter;
+        }
+        mSmoMo->SetDisplayRefreshRates(refreshRates);
+
+        ALOGI("SmoMo is enabled");
+    }
+
+    char layerExtProp[PROPERTY_VALUE_MAX];
+    property_get("vendor.display.use_layer_ext", layerExtProp, "0");
+    if (atoi(layerExtProp)) {
+        mUseLayerExt = true;
+    }
+    property_get("vendor.display.split_layer_ext", layerExtProp, "0");
+    if (atoi(layerExtProp)) {
+        mSplitLayerExt = true;
+    }
+    if ((mUseLayerExt || mSplitLayerExt) && mLayerExt.init()) {
+        ALOGI("Layer Extension is enabled");
+    }
+
+    mComposerExtnIntf = composer::ComposerExtnLib::GetInstance();
+    if (!mComposerExtnIntf) {
+        ALOGE("Unable to get composer extension");
+    } else {
+        int ret = mComposerExtnIntf->CreateFrameScheduler(&mFrameSchedulerExtnIntf);
+        if (ret) {
+            ALOGI("Unable to create frame scheduler extension");
+        }
+
+        ret = mComposerExtnIntf->CreateDisplayExtn(&mDisplayExtnIntf);
+        if (ret) {
+            ALOGI("Unable to create display extension");
+        }
+
+        createPhaseOffsetExtn();
+    }
     ALOGV("Done initializing");
 }
 
@@ -985,6 +1271,7 @@
 void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) {
     ATRACE_CALL();
     auto& refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId);
+    mVsyncPeriod = refreshRate.getVsyncPeriod();
     ALOGV("setDesiredActiveConfig(%s)", refreshRate.getName().c_str());
 
     std::lock_guard<std::mutex> lock(mActiveConfigLock);
@@ -1022,6 +1309,8 @@
     if (mRefreshRateOverlay) {
         mRefreshRateOverlay->changeRefreshRate(refreshRate);
     }
+
+    setContentFps(static_cast<uint32_t>(refreshRate.getFps()));
 }
 
 status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
@@ -1398,6 +1687,47 @@
             .get();
 }
 
+status_t SurfaceFlinger::setDisplayElapseTime(const sp<DisplayDevice>& display) const {
+    nsecs_t sfOffset = mPhaseConfiguration->getCurrentOffsets().late.sf;
+    if (!mUseAdvanceSfOffset && (sfOffset >= 0)) {
+        return OK;
+    }
+
+    if (mDisplaysList.size() != 1 || display->isVirtual()) {
+        // Revisit this for multi displays.
+        return OK;
+    }
+
+    uint64_t timeStamp = static_cast<uint64_t>(mVsyncTimeStamp + (sfOffset * -1));
+    return getHwComposer().setDisplayElapseTime(*display->getId(), timeStamp);
+}
+
+status_t SurfaceFlinger::isSupportedConfigSwitch(const sp<IBinder>& displayToken, int config) {
+    sp<DisplayDevice> display = nullptr;
+    {
+        Mutex::Autolock lock(mStateLock);
+        display = (getDisplayDeviceLocked(displayToken));
+    }
+
+    if (!display) {
+        ALOGE("Attempt to switch config %d for invalid display token %p", config,
+               displayToken.get());
+        return NAME_NOT_FOUND;
+    }
+#if (defined QTI_DISPLAY_CONFIG_ENABLED && defined VALIDATE_CONFIG_SWITCH)
+    const auto displayId = display->getId();
+    const auto hwcDisplayId = getHwComposer().fromPhysicalDisplayId(*displayId);
+    bool supported = false;
+    mDisplayConfigIntf->IsSupportedConfigSwitch(*hwcDisplayId, config, &supported);
+    if (!supported) {
+        ALOGW("Switching to config:%d is not supported", config);
+        return INVALID_OPERATION;
+    }
+#endif
+
+    return NO_ERROR;
+}
+
 status_t SurfaceFlinger::getDisplayedContentSample(const sp<IBinder>& displayToken,
                                                    uint64_t maxFrames, uint64_t timestamp,
                                                    DisplayedFrameStats* outStats) const {
@@ -1544,21 +1874,21 @@
 
 sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection(
         ISurfaceComposer::VsyncSource vsyncSource, ISurfaceComposer::ConfigChanged configChanged) {
-    const auto& handle =
-            vsyncSource == eVsyncSourceSurfaceFlinger ? mSfConnectionHandle : mAppConnectionHandle;
+    bool triggerRefresh = vsyncSource != eVsyncSourceSurfaceFlinger;
+    const auto& handle = triggerRefresh ? mAppConnectionHandle : mSfConnectionHandle;
 
-    return mScheduler->createDisplayEventConnection(handle, configChanged);
+    return mScheduler->createDisplayEventConnection(handle, configChanged, triggerRefresh);
 }
 
 void SurfaceFlinger::signalTransaction() {
     mScheduler->resetIdleTimer();
-    mPowerAdvisor.notifyDisplayUpdateImminent();
+    notifyDisplayUpdateImminent();
     mEventQueue->invalidate();
 }
 
 void SurfaceFlinger::signalLayerUpdate() {
     mScheduler->resetIdleTimer();
-    mPowerAdvisor.notifyDisplayUpdateImminent();
+    notifyDisplayUpdateImminent();
     mEventQueue->invalidate();
 }
 
@@ -1567,8 +1897,14 @@
     mEventQueue->refresh();
 }
 
-nsecs_t SurfaceFlinger::getVsyncPeriod() const {
-    const auto displayId = getInternalDisplayIdLocked();
+nsecs_t SurfaceFlinger::getVsyncPeriodFromHWC() const {
+    auto displayId = getInternalDisplayIdLocked();
+    if (mNextVsyncSource) {
+        displayId = mNextVsyncSource->getId();
+    } else if (mActiveVsyncSource) {
+        displayId = mActiveVsyncSource->getId();
+    }
+
     if (!displayId || !getHwComposer().isConnected(*displayId)) {
         return 0;
     }
@@ -1591,11 +1927,6 @@
         return;
     }
 
-    if (hwcDisplayId != getHwComposer().getInternalHwcDisplayId()) {
-        // For now, we don't do anything with external display vsyncs.
-        return;
-    }
-
     bool periodFlushed = false;
     mScheduler->addResyncSample(timestamp, vsyncPeriod, &periodFlushed);
     if (periodFlushed) {
@@ -1628,6 +1959,27 @@
     }
 
     setDesiredActiveConfig({refreshRate.getConfigId(), event});
+
+    uint32_t hwcDisplayId;
+    if (getHwcDisplayId(display, &hwcDisplayId)) {
+        setDisplayExtnActiveConfig(hwcDisplayId, refreshRate.getConfigId().value());
+    }
+}
+
+void SurfaceFlinger::setRefreshRateTo(int32_t refreshRate) {
+    auto& currentRefreshRate = mRefreshRateConfigs->getCurrentRefreshRate();
+
+    auto iter = mRefreshRateConfigs->getAllRefreshRates().cbegin();
+    while (iter != mRefreshRateConfigs->getAllRefreshRates().cend()) {
+        if (iter->second->inPolicy(refreshRate, refreshRate)) {
+            break;
+        }
+        ++iter;
+    }
+
+    if (currentRefreshRate != *iter->second) {
+        changeRefreshRate(*iter->second, Scheduler::ConfigEvent::Changed);
+    }
 }
 
 void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hal::HWDisplayId hwcDisplayId,
@@ -1648,6 +2000,15 @@
 
     mPendingHotplugEvents.emplace_back(HotplugEvent{hwcDisplayId, connection});
 
+    if (connection != hal::Connection::CONNECTED) {
+        const std::optional<DisplayIdentificationInfo> info =
+           getHwComposer().onHotplug(hwcDisplayId, connection);
+        if (info) {
+            mDisplaysList.remove(getDisplayDeviceLocked(mPhysicalDisplayTokens[info->id]));
+        }
+        mNextVsyncSource = getVsyncSource();
+    }
+
     if (std::this_thread::get_id() == mMainThreadId) {
         // Process all pending hot plug events immediately if we are on the main thread.
         processDisplayHotplugEventsLocked();
@@ -1677,26 +2038,49 @@
         return;
     }
     repaintEverythingForHWC();
+
+    if (mDisplaysList.size() != 1) {
+        // Revisit this for multi displays.
+        return;
+    }
+
+    {
+        // Track Vsync Period before and after refresh.
+        std::lock_guard lock(mVsyncPeriodMutex);
+        mVsyncPeriods = {};
+        mVsyncPeriods.push_back(getVsyncPeriodFromHWC());
+    }
 }
 
-void SurfaceFlinger::setPrimaryVsyncEnabled(bool enabled) {
+void SurfaceFlinger::setVsyncEnabled(bool enabled) {
     ATRACE_CALL();
 
     // Enable / Disable HWVsync from the main thread to avoid race conditions with
     // display power state.
-    static_cast<void>(schedule([=]() MAIN_THREAD { setPrimaryVsyncEnabledInternal(enabled); }));
+    static_cast<void>(schedule([=]() MAIN_THREAD { setVsyncEnabledInternal(enabled); }));
 }
 
-void SurfaceFlinger::setPrimaryVsyncEnabledInternal(bool enabled) {
+void SurfaceFlinger::setVsyncEnabledInternal(bool enabled) {
     ATRACE_CALL();
+    Mutex::Autolock lockVsync(mVsyncLock);
 
     mHWCVsyncPendingState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE;
 
-    if (const auto displayId = getInternalDisplayIdLocked()) {
-        sp<DisplayDevice> display = getDefaultDisplayDeviceLocked();
-        if (display && display->isPoweredOn()) {
-            getHwComposer().setVsyncEnabled(*displayId, mHWCVsyncPendingState);
+    auto displayId = getInternalDisplayIdLocked();
+    if (mNextVsyncSource) {
+        // Disable current vsync source before enabling the next source
+        if (mActiveVsyncSource) {
+            displayId = mActiveVsyncSource->getId();
+            getHwComposer().setVsyncEnabled(*displayId, hal::Vsync::DISABLE);
         }
+        displayId = mNextVsyncSource->getId();
+    } else if (mActiveVsyncSource) {
+        displayId = mActiveVsyncSource->getId();
+    }
+    getHwComposer().setVsyncEnabled(*displayId, mHWCVsyncPendingState);
+    if (mNextVsyncSource) {
+        mActiveVsyncSource = mNextVsyncSource;
+        mNextVsyncSource = NULL;
     }
 }
 
@@ -1774,7 +2158,7 @@
     setPowerModeInternal(display, currentDisplayPowerMode);
 
     // Reset the timing values to account for the period of the swapped in HWC
-    const nsecs_t vsyncPeriod = getVsyncPeriod();
+    const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
     mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
 
     // The present fences returned from vr_hwc are not an accurate
@@ -1796,8 +2180,8 @@
     // We are storing the last 2 present fences. If sf's phase offset is to be
     // woken up before the actual vsync but targeting the next vsync, we need to check
     // fence N-2
-    return mVSyncModulator->getOffsets().sf > 0 ? mPreviousPresentFences[0]
-                                                : mPreviousPresentFences[1];
+    return mVSyncModulator->getOffsets().sf >= 0 ? mPreviousPresentFences[0]
+                                                 : mPreviousPresentFences[1];
 }
 
 bool SurfaceFlinger::previousFramePending(int graceTimeMs) {
@@ -1829,7 +2213,36 @@
     mScheduler->getDisplayStatInfo(&stats);
     const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime(now);
     // Inflate the expected present time if we're targetting the next vsync.
-    return mVSyncModulator->getOffsets().sf > 0 ? presentTime : presentTime + stats.vsyncPeriod;
+    return mVSyncModulator->getOffsets().sf >= 0 ? presentTime : presentTime + stats.vsyncPeriod;
+}
+
+void SurfaceFlinger::updateFrameScheduler() NO_THREAD_SAFETY_ANALYSIS {
+    if (!mFrameSchedulerExtnIntf) {
+        return;
+    }
+
+    const sp<Fence>& fence = mVSyncModulator->getOffsets().sf > 0 ? mPreviousPresentFences[0]
+                                                                  : mPreviousPresentFences[1];
+
+    if (fence == Fence::NO_FENCE) {
+        return;
+    }
+    int fenceFd = fence->get();
+    nsecs_t timeStamp = 0;
+    int ret = mFrameSchedulerExtnIntf->UpdateFrameScheduling(fenceFd, &timeStamp);
+    if (ret <= 0) {
+        return;
+    }
+
+    const nsecs_t period = getVsyncPeriodFromHWC();
+    mScheduler->resyncToHardwareVsync(true, period, true /* force resync */);
+    if (timeStamp > 0) {
+        bool periodFlushed = false;
+        mScheduler->addResyncSample(timeStamp, period, &periodFlushed);
+        if (periodFlushed) {
+            mVSyncModulator->onRefreshRateChangeCompleted();
+        }
+    }
 }
 
 void SurfaceFlinger::onMessageReceived(int32_t what, nsecs_t expectedVSyncTime) {
@@ -1840,10 +2253,24 @@
             break;
         }
         case MessageQueue::REFRESH: {
+            if (mFrameExtn) {
+                mRefreshTimeStamp = systemTime(SYSTEM_TIME_MONOTONIC);
+            }
+            if (mDolphinFuncsEnabled) {
+                mDolphinRefresh();
+            }
             onMessageRefresh();
+            if (mFrameExtn) {
+                mNumIdle = 0;
+            }
             break;
         }
     }
+#ifdef PASS_COMPOSITOR_PID
+    if (mDisplayExtnIntf) {
+        mDisplayExtnIntf->SendCompositorPid();
+    }
+#endif
 }
 
 void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) {
@@ -1855,7 +2282,7 @@
     // seeing this same value.
     const nsecs_t lastExpectedPresentTime = mExpectedPresentTime.load();
     mExpectedPresentTime = expectedVSyncTime;
-
+    updateFrameScheduler();
     // When Backpressure propagation is enabled we want to give a small grace period
     // for the present fence to fire instead of just giving up on this frame to handle cases
     // where present fence is just about to get signaled.
@@ -1929,6 +2356,44 @@
         }
     }
 
+    if (mDolphinFuncsEnabled) {
+        int maxQueuedFrames = 0;
+        mDrawingState.traverseInZOrder([&](Layer* layer) {
+            if (layer->hasReadyFrame()) {
+                const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
+                if (layer->shouldPresentNow(expectedPresentTime)) {
+                    int layerQueuedFrames = layer->getQueuedFrameCount();
+                    const auto& drawingState{layer->getDrawingState()};
+                    bool isLayerAvailable = layer->isOpaque(drawingState);
+                    if (!isLayerAvailable) {
+                        int32_t priority = layer->getPriority();
+                        if (layer->isLayerFocusedBasedOnPriority(priority)) {
+                            isLayerAvailable = true;
+                        }
+                    }
+                    if (maxQueuedFrames < layerQueuedFrames &&
+                        isLayerAvailable) {
+                        maxQueuedFrames = layerQueuedFrames;
+                        mNameLayerMax = layer->getName();
+                    }
+                }
+            }
+        });
+        mMaxQueuedFrames = maxQueuedFrames;
+        DisplayStatInfo stats;
+        mScheduler->getDisplayStatInfo(&stats);
+        if(mDolphinMonitor(maxQueuedFrames, stats.vsyncPeriod)) {
+            signalLayerUpdate();
+            if (mFrameExtn) {
+                mNumIdle++;
+            }
+            return;
+        }
+        if (mFrameExtn) {
+            mNumIdle++;
+        }
+    }
+
     // Our jank window is always at least 100ms since we missed a
     // frame...
     static constexpr nsecs_t kMinJankyDuration =
@@ -2014,6 +2479,11 @@
         }
         signalRefresh();
     }
+    if (mFrameExtn && mDolphinFuncsEnabled) {
+        if (!refreshNeeded) {
+            mDolphinScaling(mNumIdle, mMaxQueuedFrames);
+        }
+    }
 }
 
 bool SurfaceFlinger::handleMessageTransaction() {
@@ -2090,8 +2560,17 @@
     // Store the present time just before calling to the composition engine so we could notify
     // the scheduler.
     const auto presentTime = systemTime();
+    dumpDrawCycle(true);
+
+    {
+        Mutex::Autolock lock(mStateLock);
+        for (const auto& [_, display] : mDisplays) {
+            setDisplayElapseTime(display);
+        }
+    }
 
     mCompositionEngine->present(refreshArgs);
+
     mTimeStats->recordFrameDuration(mFrameStartTime, systemTime());
     // Reset the frame start time now that we've recorded this frame.
     mFrameStartTime = 0;
@@ -2122,7 +2601,8 @@
         mTimeStats->incrementCompositionStrategyChanges();
     }
 
-    mVSyncModulator->onRefreshed(mHadClientComposition);
+    // TODO: b/160583065 Enable skip validation when SF caches all client composition layers
+    mVSyncModulator->onRefreshed(mHadClientComposition || mReusedClientComposition);
 
     mLayersWithQueuedFrames.clear();
     if (mVisibleRegionsDirty) {
@@ -2237,8 +2717,13 @@
 
     getBE().mDisplayTimeline.updateSignalTimes();
     mPreviousPresentFences[1] = mPreviousPresentFences[0];
-    mPreviousPresentFences[0] =
-            display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE;
+
+    sp<DisplayDevice> vSyncSource = mNextVsyncSource;
+    if (mNextVsyncSource == NULL) {
+        vSyncSource = mActiveVsyncSource;
+    }
+    mPreviousPresentFences[0] = vSyncSource ?
+        getHwComposer().getPresentFence(*vSyncSource->getId()) : Fence::NO_FENCE;
     auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFences[0]);
     getBE().mDisplayTimeline.push(presentFenceTime);
 
@@ -2272,6 +2757,8 @@
         mScheduler->addPresentFence(presentFenceTime);
     }
 
+    forceResyncModel();
+
     const bool isDisplayConnected = display && getHwComposer().isConnected(*display->getId());
 
     if (!hasSyncFramework) {
@@ -2295,6 +2782,8 @@
         mAnimFrameTracker.advanceFrame();
     }
 
+    dumpDrawCycle(false);
+
     mTimeStats->incrementTotalFrames();
     if (mHadClientComposition) {
         mTimeStats->incrementClientCompositionFrames();
@@ -2361,6 +2850,43 @@
         mRegionSamplingThread->notifyNewContent();
     }
 
+    if (mSplitLayerExt && mLayerExt) {
+        std::vector<std::string> layerInfo;
+        mDrawingState.traverse([&](Layer* layer) {
+            if (layer->findOutputLayerForDisplay(display)) {
+                layerInfo.push_back(layer->getName());
+            }
+        });
+        mLayerExt->UpdateLayerState(layerInfo, mNumLayers);
+    }
+
+    if (mSmoMo) {
+        ATRACE_NAME("SmoMoUpdateState");
+        Mutex::Autolock lock(mStateLock);
+
+        uint32_t fps = 0;
+        std::vector<smomo::SmomoLayerStats> layers;
+
+        // Disable SmoMo by passing empty layer stack in multiple display case
+        if (mDisplays.size() == 1) {
+            mDrawingState.traverse([&](Layer* layer) {
+                if (layer->findOutputLayerForDisplay(display)) {
+                    smomo::SmomoLayerStats layerStats;
+                    layerStats.id = layer->getSequence();
+                    layerStats.name = layer->getName();
+                    layers.push_back(layerStats);
+                }
+            });
+
+            fps = mRefreshRateConfigs->getCurrentRefreshRate().getFps();
+        }
+
+        mSmoMo->UpdateSmomoState(layers, fps);
+        int content_fps = mSmoMo->GetFrameRate();
+        setContentFps((content_fps > 0) ? content_fps : fps);
+    }
+
+
     // Even though ATRACE_INT64 already checks if tracing is enabled, it doesn't prevent the
     // side-effect of getTotalSize(), so we check that again here
     if (ATRACE_ENABLED()) {
@@ -2373,6 +2899,30 @@
     return displayDevice.getViewport().toFloatRect();
 }
 
+void SurfaceFlinger::forceResyncModel() NO_THREAD_SAFETY_ANALYSIS {
+    std::lock_guard lock(mVsyncPeriodMutex);
+    if (!mVsyncPeriods.size()) {
+        return;
+    }
+
+    const nsecs_t period = getVsyncPeriodFromHWC();
+    // Model resync should happen at every fps change.
+    // Upon increase/decrease in vsync period start resync immediately.
+    // Initial set of vsync wakeups happen at ref_time + N * period where N = 1, 2, 3 ..
+    // Since if doesnt make use of timestamp to compute period, resync can be triggered
+    // as soon as change is fps(period) is observed.
+    if (period > mVsyncPeriods.at(mVsyncPeriods.size() - 1)) {
+        ATRACE_CALL();
+        mScheduler->resyncToHardwareVsync(true, period, true /* force resync */);
+        mVsyncPeriods.push_back(period);
+    } else if (period < mVsyncPeriods.at(mVsyncPeriods.size() - 1)) {
+        // Vsync period changed. Trigger resync.
+        ATRACE_CALL();
+        mScheduler->resyncToHardwareVsync(true, period, true /* force resync */);
+        mVsyncPeriods = {};
+    }
+}
+
 void SurfaceFlinger::computeLayerBounds() {
     for (const auto& pair : ON_MAIN_THREAD(mDisplays)) {
         const auto& displayDevice = pair.second;
@@ -2389,6 +2939,71 @@
     }
 }
 
+sp<DisplayDevice> SurfaceFlinger::getVsyncSource() {
+    // Return the vsync source from the active displays based on the order in which they are
+    // connected.
+    // Normally the order of priority is Primary (Built-in/Pluggable) followed by Secondary
+    // built-ins followed by Pluggable. But if mPluggableVsyncPrioritized is true then the
+    // order of priority is Pluggables followed by Primary and Secondary built-ins.
+
+    for (const auto& display : mDisplaysList) {
+        hal::PowerMode mode = display->getPowerMode();
+        if (display->isVirtual() || (mode == hal::PowerMode::OFF) ||
+            (mode == hal::PowerMode::DOZE_SUSPEND)) {
+            continue;
+        }
+
+        if (mVsyncSourceReliableOnDoze) {
+            if ((mode == hal::PowerMode::ON) ||
+                (mode == hal::PowerMode::DOZE)) {
+              return display;
+            }
+        } else if (mode == hal::PowerMode::ON) {
+            return display;
+        }
+    }
+
+    // In-case active displays are not present, source the vsync from
+    // the display which is in doze mode even if it is unreliable
+    // in the same order of display priority as above.
+    if (!mVsyncSourceReliableOnDoze) {
+        for (const auto& display : mDisplaysList) {
+            hal::PowerMode mode = display->getPowerMode();
+            if (display->isVirtual()) {
+                continue;
+            }
+
+            if (mode == hal::PowerMode::DOZE) {
+                return display;
+            }
+        }
+    }
+
+    return NULL;
+}
+
+void SurfaceFlinger::updateVsyncSource()
+            NO_THREAD_SAFETY_ANALYSIS {
+    Mutex::Autolock lock(mVsyncLock);
+    mNextVsyncSource = getVsyncSource();
+
+    if (mNextVsyncSource == NULL) {
+        // Switch off vsync for the last enabled source
+        mScheduler->disableHardwareVsync(true);
+        mScheduler->onScreenReleased(mAppConnectionHandle);
+    } else if (mNextVsyncSource && (mActiveVsyncSource == NULL)) {
+        mScheduler->onScreenAcquired(mAppConnectionHandle);
+        bool isPrimary = mNextVsyncSource->isPrimary();
+        nsecs_t vsync = (isPrimary && (mVsyncPeriod > 0)) ? mVsyncPeriod : getVsyncPeriodFromHWC();
+        mScheduler->resyncToHardwareVsync(true, vsync);
+    } else if ((mNextVsyncSource != NULL) &&
+        (mActiveVsyncSource != NULL)) {
+        // Switch vsync to the new source
+        mScheduler->disableHardwareVsync(true);
+        mScheduler->resyncToHardwareVsync(true, getVsyncPeriodFromHWC());
+    }
+}
+
 void SurfaceFlinger::postFrame() {
     const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked());
     if (display && getHwComposer().isConnected(*display->getId())) {
@@ -2438,6 +3053,8 @@
 
         const DisplayId displayId = info->id;
         const auto it = mPhysicalDisplayTokens.find(displayId);
+        bool isInternalDisplay = (getHwComposer().getDisplayConnectionType(displayId) ==
+                                  DisplayConnectionType::Internal);
 
         if (event.connection == hal::Connection::CONNECTED) {
             if (it == mPhysicalDisplayTokens.end()) {
@@ -2475,8 +3092,19 @@
                 mCurrentState.displays.removeItemsAt(index);
             }
             mPhysicalDisplayTokens.erase(it);
+            updateVsyncSource();
+            if (mInternalPresentationDisplays && isInternalDisplay) {
+                // Update mInternalPresentationDisplays flag
+                updateInternalDisplaysPresentationMode();
+            }
         }
 
+        if (mEarlyWakeUpEnabled && isInternalDisplay) {
+            uint32_t hwcDisplayId = static_cast<uint32_t>(event.hwcDisplayId);
+            bool isConnected = (event.connection == hal::Connection::CONNECTED);
+            uint32_t activeConfigId = getHwComposer().getActiveConfigIndex(displayId);
+            updateDisplayExtension(hwcDisplayId, activeConfigId, isConnected);
+        }
         processDisplayChangesLocked();
     }
 
@@ -2578,6 +3206,7 @@
                                          const DisplayDeviceState& state) {
     int width = 0;
     int height = 0;
+    bool canAllocateHwcForVDS = false;
     ui::PixelFormat pixelFormat = static_cast<ui::PixelFormat>(PIXEL_FORMAT_UNKNOWN);
     if (state.physical) {
         const auto& activeConfig =
@@ -2594,6 +3223,20 @@
         status = state.surface->query(NATIVE_WINDOW_FORMAT, &intPixelFormat);
         ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status);
         pixelFormat = static_cast<ui::PixelFormat>(intPixelFormat);
+        if (mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer()) {
+            if (maxVirtualDisplaySize == 0 ||
+                ((uint64_t)width <= maxVirtualDisplaySize &&
+                (uint64_t)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;
+               }
+            }
+        }
+
     } else {
         // Virtual displays without a surface are dormant:
         // they have external state (layer stack, projection,
@@ -2610,7 +3253,8 @@
     builder.setIsSecure(state.isSecure);
     builder.setLayerStackId(state.layerStack);
     builder.setPowerAdvisor(&mPowerAdvisor);
-    builder.setUseHwcVirtualDisplays(mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer());
+    builder.setUseHwcVirtualDisplays((mUseHwcVirtualDisplays && canAllocateHwcForVDS) ||
+                                     getHwComposer().isUsingVrComposer());
     builder.setName(state.displayName);
     const auto compositionDisplay = getCompositionEngine().createDisplay(builder.build());
 
@@ -2624,8 +3268,9 @@
 
     if (state.isVirtual()) {
         sp<VirtualDisplaySurface> vds =
-                new VirtualDisplaySurface(getHwComposer(), displayId, state.surface, bqProducer,
-                                          bqConsumer, state.displayName);
+                new VirtualDisplaySurface(getHwComposer(), displayId, state.surface,
+                                          bqProducer, bqConsumer, state.displayName,
+                                          state.isSecure);
 
         displaySurface = vds;
         producer = vds;
@@ -2645,9 +3290,44 @@
     const auto display = setupNewDisplayDeviceInternal(displayToken, compositionDisplay, state,
                                                        displaySurface, producer);
     mDisplays.emplace(displayToken, display);
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+    const auto hwcDisplayId = getHwComposer().fromPhysicalDisplayId(*displayId);
+    bool supported = false;
+    if (mDisplayConfigIntf) {
+        mDisplayConfigIntf->IsPowerModeOverrideSupported(*hwcDisplayId, &supported);
+    }
+    if (supported) {
+      sp<DisplayDevice> display = getDisplayDeviceLocked(displayToken);
+      display->setPowerModeOverrideConfig(true);
+    }
+#endif
     if (!state.isVirtual()) {
+        sp<DisplayDevice> display = getDisplayDeviceLocked(displayToken);
+        if (mPluggableVsyncPrioritized && !isInternalDisplay(display)) {
+            // Insert the pluggable display just before the first built-in display
+            // so that the earlier pluggable display remains the V-sync source.
+            auto it = mDisplaysList.begin();
+            for (; it != mDisplaysList.end(); it++ ) {
+                if(isInternalDisplay(*it)) {
+                    break;
+                }
+            }
+            mDisplaysList.insert(it, display);
+        } else {
+            mDisplaysList.push_back(display);
+        }
         LOG_FATAL_IF(!displayId);
         dispatchDisplayHotplugEvent(displayId->value, true);
+
+        if (!display->isPrimary() && isInternalDisplay(display)) {
+            const auto defaultDisplay = getDefaultDisplayDeviceLocked();
+            if (defaultDisplay && defaultDisplay->isPrimary()) {
+                if (state.layerStack != defaultDisplay->getLayerStack()) {
+                    // Internal Physical Displays are in Presentation Mode
+                    mInternalPresentationDisplays = true;
+                }
+            }
+        }
     }
 
     if (display->isPrimary()) {
@@ -2693,30 +3373,70 @@
     }
 
     if (const auto display = getDisplayDeviceLocked(displayToken)) {
+        bool displaySizeChanged = false;
         if (currentState.layerStack != drawingState.layerStack) {
             display->setLayerStack(currentState.layerStack);
         }
         if ((currentState.orientation != drawingState.orientation) ||
             (currentState.viewport != drawingState.viewport) ||
             (currentState.frame != drawingState.frame)) {
-            display->setProjection(currentState.orientation, currentState.viewport,
+            if (mUseFbScaling && display->isPrimary()) {
+                const ssize_t index = mCurrentState.displays.indexOfKey(displayToken);
+                DisplayDeviceState& tmpState = mCurrentState.displays.editValueAt(index);
+                tmpState.width =  currentState.viewport.width();
+                tmpState.height = currentState.viewport.height();
+                tmpState.frame =  currentState.viewport;
+                setFrameBufferSizeForScaling(display, currentState);
+                displaySizeChanged = true;
+            } else {
+                display->setProjection(currentState.orientation, currentState.viewport,
                                    currentState.frame);
+            }
         }
         if (currentState.width != drawingState.width ||
             currentState.height != drawingState.height) {
-            display->setDisplaySize(currentState.width, currentState.height);
+            if (!displaySizeChanged) {
+                display->setDisplaySize(currentState.width, currentState.height);
 
-            if (display->isPrimary()) {
-                mScheduler->onPrimaryDisplayAreaChanged(currentState.width * currentState.height);
-            }
+                if (display->isPrimary()) {
+                    mScheduler->onPrimaryDisplayAreaChanged(
+                                   currentState.width * currentState.height);
+                }
 
-            if (mRefreshRateOverlay) {
-                mRefreshRateOverlay->setViewport(display->getSize());
+                if (mRefreshRateOverlay) {
+                    mRefreshRateOverlay->setViewport(display->getSize());
+                }
             }
         }
     }
 }
 
+void SurfaceFlinger::setFrameBufferSizeForScaling(sp<DisplayDevice> displayDevice,
+                                                  const DisplayDeviceState& state) {
+    base::unique_fd fd;
+    auto display = displayDevice->getCompositionDisplay();
+    int newWidth = state.viewport.width();
+    int newHeight = state.viewport.height();
+    if (state.orientation == ui::ROTATION_90 || state.orientation == ui::ROTATION_270){
+        std::swap(newWidth, newHeight);
+    }
+    if (displayDevice->getWidth() == newWidth && displayDevice->getHeight() == newHeight) {
+        displayDevice->setProjection(state.orientation, state.viewport, state.viewport);
+        return;
+    }
+
+    if (mBootStage == BootStage::FINISHED) {
+        displayDevice->setDisplaySize(newWidth, newHeight);
+        displayDevice->setProjection(state.orientation, state.viewport, state.viewport);
+        display->getRenderSurface()->setViewportAndProjection();
+        display->getRenderSurface()->flipClientTarget(true);
+        // queue a scratch buffer to flip Client Target with updated size
+        display->getRenderSurface()->queueBuffer(std::move(fd));
+        display->getRenderSurface()->flipClientTarget(false);
+        // releases the FrameBuffer that was acquired as part of queueBuffer()
+        display->getRenderSurface()->onPresentDisplayCompleted();
+    }
+}
 void SurfaceFlinger::processDisplayChangesLocked() {
     // here we take advantage of Vector's copy-on-write semantics to
     // improve performance by skipping the transaction entirely when
@@ -2975,7 +3695,7 @@
 
     // start the EventThread
     mScheduler =
-            getFactory().createScheduler([this](bool enabled) { setPrimaryVsyncEnabled(enabled); },
+            getFactory().createScheduler([this](bool enabled) { setVsyncEnabled(enabled); },
                                          *mRefreshRateConfigs, *this);
     mAppConnectionHandle =
             mScheduler->createConnection("app", mPhaseConfiguration->getCurrentOffsets().late.app,
@@ -3088,6 +3808,8 @@
     bool visibleRegions = false;
     bool frameQueued = false;
     bool newDataLatched = false;
+    std::set<uint32_t> layerStackIds;
+    uint32_t layerStackId = 0;
 
     const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
 
@@ -3105,6 +3827,8 @@
             frameQueued = true;
             if (layer->shouldPresentNow(expectedPresentTime)) {
                 mLayersWithQueuedFrames.push_back(layer);
+                layerStackId = layer->getLayerStack();
+                layerStackIds.insert(layerStackId);
             } else {
                 ATRACE_NAME("!layer->shouldPresentNow()");
                 layer->useEmptyDamage();
@@ -3114,6 +3838,10 @@
         }
     });
 
+    if (wakeUpPresentationDisplays && !mLayersWithQueuedFrames.empty()) {
+        handlePresentationDisplaysEarlyWakeup(layerStackIds.size(), layerStackId);
+    }
+
     // The client can continue submitting buffers for offscreen layers, but they will not
     // be shown on screen. Therefore, we need to latch and release buffers of offscreen
     // layers to ensure dequeueBuffer doesn't block indefinitely.
@@ -3185,6 +3913,12 @@
         if (mNumLayers >= ISurfaceComposer::MAX_LAYERS) {
             ALOGE("AddClientLayer failed, mNumLayers (%zu) >= MAX_LAYERS (%zu)", mNumLayers.load(),
                   ISurfaceComposer::MAX_LAYERS);
+            mCurrentState.traverseInZOrder([&](Layer* layer) {
+                const auto& p = layer->getParent();
+                ALOGE("layer (%s) ::  parent (%s).",
+                layer->getName().c_str(),
+                (p != nullptr) ? p->getName().c_str() : "no-parent");
+            });
             return NO_MEMORY;
         }
 
@@ -3339,6 +4073,10 @@
 
     bool privileged = callingThreadHasUnscopedSurfaceFlingerAccess();
 
+    if (mAsyncVdsCreationSupported) {
+        checkVirtualDisplayHint(displays);
+    }
+
     Mutex::Autolock _l(mStateLock);
 
     // If its TransactionQueue already has a pending TransactionState or if it is pending
@@ -3541,6 +4279,47 @@
     }
 }
 
+void SurfaceFlinger::checkVirtualDisplayHint(const Vector<DisplayState>& displays) {
+    for (const DisplayState& s : displays) {
+        const ssize_t index = mCurrentState.displays.indexOfKey(s.token);
+        if (index < 0)
+            continue;
+
+        DisplayDeviceState& state = mCurrentState.displays.editValueAt(index);
+        const uint32_t what = s.what;
+        if (what & DisplayState::eSurfaceChanged) {
+            if (IInterface::asBinder(state.surface) != IInterface::asBinder(s.surface)) {
+                if (state.isVirtual() && s.surface != nullptr &&
+                    (mUseHwcVirtualDisplays || getHwComposer().isUsingVrComposer())) {
+                    int width = 0;
+                    int status = s.surface->query(NATIVE_WINDOW_WIDTH, &width);
+                    ALOGE_IF(status != NO_ERROR, "Unable to query width (%d)", status);
+                    int height = 0;
+                    status = s.surface->query(NATIVE_WINDOW_HEIGHT, &height);
+                    ALOGE_IF(status != NO_ERROR, "Unable to query height (%d)", status);
+                    int format = 0;
+                    status = s.surface->query(NATIVE_WINDOW_FORMAT, &format);
+                    ALOGE_IF(status != NO_ERROR, "Unable to query format (%d)", status);
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+                    if ((mDisplayConfigIntf) && (maxVirtualDisplaySize == 0 ||
+                        ((uint64_t)width <= maxVirtualDisplaySize &&
+                        (uint64_t)height <= maxVirtualDisplaySize))) {
+                        uint64_t usage = 0;
+                        // Replace with native_window_get_consumer_usage ?
+                        status = s.surface->getConsumerUsage(&usage);
+                        ALOGW_IF(status != NO_ERROR, "Unable to query usage (%d)", status);
+                        if ((status == NO_ERROR) && canAllocateHwcDisplayIdForVDS(usage)) {
+                            mDisplayConfigIntf->CreateVirtualDisplay(width, height, format);
+                            return;
+                        }
+                    }
+#endif
+                }
+            }
+        }
+    }
+}
+
 uint32_t SurfaceFlinger::setDisplayStateLocked(const DisplayState& s) {
     const ssize_t index = mCurrentState.displays.indexOfKey(s.token);
     if (index < 0) return 0;
@@ -3999,10 +4778,12 @@
 
     // window type is WINDOW_TYPE_DONT_SCREENSHOT from SurfaceControl.java
     // TODO b/64227542
+    metadata.setInt32(METADATA_WINDOW_TYPE_DONT_SCREENSHOT, 0);
     if (metadata.has(METADATA_WINDOW_TYPE)) {
         int32_t windowType = metadata.getInt32(METADATA_WINDOW_TYPE, 0);
         if (windowType == 441731) {
             metadata.setInt32(METADATA_WINDOW_TYPE, InputWindowInfo::TYPE_NAVIGATION_BAR_PANEL);
+            metadata.setInt32(METADATA_WINDOW_TYPE_DONT_SCREENSHOT, 1);
             primaryDisplayOnly = true;
         }
     }
@@ -4216,8 +4997,7 @@
                         {});
 
     setPowerModeInternal(display, hal::PowerMode::ON);
-
-    const nsecs_t vsyncPeriod = getVsyncPeriod();
+    const nsecs_t vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
     mAnimFrameTracker.setDisplayRefreshPeriod(vsyncPeriod);
 
     // Use phase of 0 since phase is not known.
@@ -4247,21 +5027,35 @@
         return;
     }
 
+    mActiveVsyncSource = getVsyncSource();
+
     display->setPowerMode(mode);
 
+    // Dummy display created by LibSurfaceFlinger unit test
+    // for setPowerModeInternal test cases.
+    bool isDummyDisplay = (std::find(mDisplaysList.begin(),
+        mDisplaysList.end(), display) == mDisplaysList.end());
+
     if (mInterceptor->isEnabled()) {
         mInterceptor->savePowerModeUpdate(display->getSequenceId(), static_cast<int32_t>(mode));
     }
-
+    const auto vsyncPeriod = mRefreshRateConfigs->getCurrentRefreshRate().getVsyncPeriod();
     if (currentMode == hal::PowerMode::OFF) {
         if (SurfaceFlinger::setSchedFifo(true) != NO_ERROR) {
             ALOGW("Couldn't set SCHED_FIFO on display on: %s\n", strerror(errno));
         }
         getHwComposer().setPowerMode(*displayId, mode);
-        if (display->isPrimary() && mode != hal::PowerMode::DOZE_SUSPEND) {
-            getHwComposer().setVsyncEnabled(*displayId, mHWCVsyncPendingState);
-            mScheduler->onScreenAcquired(mAppConnectionHandle);
-            mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+        bool internalDisplay = isInternalDisplay(display);
+        if (isDummyDisplay) {
+            if (display->isPrimary() && mode != hal::PowerMode::DOZE_SUSPEND) {
+                getHwComposer().setVsyncEnabled(*displayId, mHWCVsyncPendingState);
+                mScheduler->onScreenAcquired(mAppConnectionHandle);
+                mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
+            }
+        } else if ((mPluggableVsyncPrioritized && !internalDisplay) ||
+                   (displayId == getInternalDisplayIdLocked()) ||
+                   internalDisplay) {
+            updateVsyncSource();
         }
 
         mVisibleRegionsDirty = true;
@@ -4269,32 +5063,43 @@
         repaintEverything();
     } else if (mode == hal::PowerMode::OFF) {
         // Turn off the display
-        if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) {
-            ALOGW("Couldn't set SCHED_OTHER on display off: %s\n", strerror(errno));
-        }
-        if (display->isPrimary() && currentMode != hal::PowerMode::DOZE_SUSPEND) {
-            mScheduler->disableHardwareVsync(true);
-            mScheduler->onScreenReleased(mAppConnectionHandle);
-        }
+        if (isDummyDisplay) {
+            if (SurfaceFlinger::setSchedFifo(false) != NO_ERROR) {
+                ALOGW("Couldn't set SCHED_OTHER on display off: %s\n", strerror(errno));
+            }
+            if (display->isPrimary() && currentMode != hal::PowerMode::DOZE_SUSPEND) {
+                mScheduler->disableHardwareVsync(true);
+                mScheduler->onScreenReleased(mAppConnectionHandle);
+            }
 
-        // Make sure HWVsync is disabled before turning off the display
-        getHwComposer().setVsyncEnabled(*displayId, hal::Vsync::DISABLE);
-
+            // Make sure HWVsync is disabled before turning off the display
+            getHwComposer().setVsyncEnabled(*displayId, hal::Vsync::DISABLE);
+        } else {
+            updateVsyncSource();
+        }
         getHwComposer().setPowerMode(*displayId, mode);
         mVisibleRegionsDirty = true;
         // from this point on, SF will stop drawing on this display
     } else if (mode == hal::PowerMode::DOZE || mode == hal::PowerMode::ON) {
         // Update display while dozing
         getHwComposer().setPowerMode(*displayId, mode);
-        if (display->isPrimary() && currentMode == hal::PowerMode::DOZE_SUSPEND) {
-            mScheduler->onScreenAcquired(mAppConnectionHandle);
-            mScheduler->resyncToHardwareVsync(true, getVsyncPeriod());
+        if (isDummyDisplay) {
+            if (display->isPrimary() && currentMode == hal::PowerMode::DOZE_SUSPEND) {
+                mScheduler->onScreenAcquired(mAppConnectionHandle);
+                mScheduler->resyncToHardwareVsync(true, vsyncPeriod);
+            }
+        } else {
+            updateVsyncSource();
         }
     } else if (mode == hal::PowerMode::DOZE_SUSPEND) {
         // Leave display going to doze
-        if (display->isPrimary()) {
-            mScheduler->disableHardwareVsync(true);
-            mScheduler->onScreenReleased(mAppConnectionHandle);
+        if (isDummyDisplay) {
+            if (display->isPrimary()) {
+                mScheduler->disableHardwareVsync(true);
+                mScheduler->onScreenReleased(mAppConnectionHandle);
+            }
+        } else {
+            updateVsyncSource();
         }
         getHwComposer().setPowerMode(*displayId, mode);
     } else {
@@ -4302,16 +5107,30 @@
         getHwComposer().setPowerMode(*displayId, mode);
     }
 
+    const sp<DisplayDevice> vsyncSource = getVsyncSource();
+    struct sched_param param = {0};
+    if (vsyncSource != NULL) {
+        param.sched_priority = 1;
+        if (sched_setscheduler(0, SCHED_FIFO, &param) != 0) {
+            ALOGW("Couldn't set SCHED_FIFO on display on");
+        }
+    } else {
+        if (sched_setscheduler(0, SCHED_OTHER, &param) != 0) {
+            ALOGW("Couldn't set SCHED_OTHER on display off");
+        }
+    }
+
     if (display->isPrimary()) {
         mTimeStats->setPowerMode(mode);
         mRefreshRateStats->setPowerMode(mode);
         mScheduler->setDisplayPowerState(mode == hal::PowerMode::ON);
     }
 
+    setEarlyWakeUpConfig(display, mode);
     ALOGD("Finished setting power mode %d on display %s", mode, to_string(*displayId).c_str());
 }
 
-void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
+void SurfaceFlinger::setPowerModeOnMainThread(const sp<IBinder>& displayToken, int mode) {
     schedule([=]() MAIN_THREAD {
         const auto display = getDisplayDeviceLocked(displayToken);
         if (!display) {
@@ -4325,7 +5144,82 @@
     }).wait();
 }
 
+void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) {
+    sp<DisplayDevice> display = nullptr;
+    {
+        Mutex::Autolock lock(mStateLock);
+        display = (getDisplayDeviceLocked(displayToken));
+    }
+    if (!display) {
+        ALOGE("Attempt to set power mode %d for invalid display token %p", mode,
+               displayToken.get());
+        return;
+    } else if (display->isVirtual()) {
+         ALOGW("Attempt to set power mode %d for virtual display", mode);
+         return;
+    }
+
+#ifdef QTI_DISPLAY_CONFIG_ENABLED
+    const auto displayId = display->getId();
+    const auto hwcDisplayId = getHwComposer().fromPhysicalDisplayId(*displayId);
+    const hal::PowerMode currentDisplayPowerMode = display->getPowerMode();
+    const hal::PowerMode newDisplayPowerMode = static_cast<hal::PowerMode>(mode);
+    // Fallback to default power state behavior as HWC does not support power mode override.
+    if (!display->getPowerModeOverrideConfig() ||
+        !((currentDisplayPowerMode  ==  hal::PowerMode::OFF &&
+        newDisplayPowerMode == hal::PowerMode::ON) ||
+        (currentDisplayPowerMode  ==  hal::PowerMode::ON &&
+        newDisplayPowerMode == hal::PowerMode::OFF))) {
+        setPowerModeOnMainThread(displayToken, mode);
+        return;
+    }
+
+    ::DisplayConfig::PowerMode hwcMode = ::DisplayConfig::PowerMode::kOff;
+    switch (mode) {
+    case HWC_POWER_MODE_DOZE:         hwcMode = ::DisplayConfig::PowerMode::kDoze;        break;
+    case HWC_POWER_MODE_NORMAL:       hwcMode = ::DisplayConfig::PowerMode::kOn;          break;
+    case HWC_POWER_MODE_DOZE_SUSPEND: hwcMode = ::DisplayConfig::PowerMode::kDozeSuspend; break;
+    default:                          hwcMode = ::DisplayConfig::PowerMode::kOff;         break;
+    }
+
+    bool step_up = false;
+    if (currentDisplayPowerMode == hal::PowerMode::OFF) {
+        if (newDisplayPowerMode == hal::PowerMode::DOZE ||
+            newDisplayPowerMode == hal::PowerMode::ON) {
+            step_up = true;
+        }
+    } else if (currentDisplayPowerMode == hal::PowerMode::DOZE_SUSPEND) {
+        if (newDisplayPowerMode == hal::PowerMode::DOZE ||
+            newDisplayPowerMode == hal::PowerMode::ON) {
+            step_up = true;
+        }
+    } else if (currentDisplayPowerMode == hal::PowerMode::DOZE) {
+        if (newDisplayPowerMode == hal::PowerMode::ON) {
+            step_up = true;
+        }
+    }
+    // Change hardware state first while stepping up.
+    if (step_up) {
+        mDisplayConfigIntf->SetPowerMode(*hwcDisplayId, hwcMode);
+    }
+    // Change SF state now.
+    setPowerModeOnMainThread(displayToken, mode);
+    // Change hardware state now while stepping down.
+
+    if (!step_up) {
+        mDisplayConfigIntf->SetPowerMode(*hwcDisplayId, hwcMode);
+    }
+#else
+    setPowerModeOnMainThread(displayToken, mode);
+#endif
+}
+
 status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) {
+    size_t numArgs = args.size();
+    if (numArgs && ((args[0] == String16("--file")) ||
+        (args[0] == String16("--allocated_buffers")))) {
+        return doDumpContinuous(fd, args);
+    }
     std::string result;
 
     IPCThreadState* ipc = IPCThreadState::self();
@@ -4366,7 +5260,13 @@
                 (it->second)(args, asProto, result);
                 dumpLayers = false;
             } else if (!asProto) {
-                dumpAllLocked(args, result);
+                // selection of mini dumpsys (Format: adb shell dumpsys SurfaceFlinger --mini)
+                if (numArgs && ((args[0] == String16("--mini")))) {
+                    dumpMini(result);
+                    dumpLayers = false;
+                } else {
+                    dumpAllLocked(args, result);
+                }
             }
         }
 
@@ -4387,6 +5287,129 @@
     return NO_ERROR;
 }
 
+status_t SurfaceFlinger::doDumpContinuous(int fd, const DumpArgs& args) {
+    // Format: adb shell dumpsys SurfaceFlinger --file --no-limit
+    size_t numArgs = args.size();
+    status_t err = NO_ERROR;
+
+    if (args[0] == String16("--allocated_buffers")) {
+        std::string dumpsys;
+        GraphicBufferAllocator& alloc(GraphicBufferAllocator::get());
+        alloc.dump(dumpsys);
+        write(fd, dumpsys.c_str(), dumpsys.size());
+        return NO_ERROR;
+    }
+
+    Mutex::Autolock _l(mFileDump.lock);
+    // Same command is used to start and end dump.
+    mFileDump.running = !mFileDump.running;
+    // selection of full dumpsys or not (defualt, dumpsys will be minimum required)
+    // Format: adb shell dumpsys SurfaceFlinger --file --no-limit --full-dump
+    if (numArgs >= 3 && (args[2] == String16("--full-dump"))) {
+                 mFileDump.fullDump = true;
+    }
+    if (mFileDump.running) {
+        std::ofstream ofs;
+        ofs.open(mFileDump.name, std::ofstream::out | std::ofstream::trunc);
+        if (!ofs) {
+            mFileDump.running = false;
+            err = UNKNOWN_ERROR;
+        } else {
+            ofs.close();
+            mFileDump.position = 0;
+            if (numArgs >= 2 && (args[1] == String16("--no-limit"))) {
+            mFileDump.noLimit = true;
+            } else {
+                mFileDump.noLimit = false;
+            }
+        }
+    }
+
+    std::string result;
+    result += mFileDump.running ? "Start" : "End";
+    result += mFileDump.noLimit ? " unlimited" : " fixed limit";
+    result += " dumpsys to file : ";
+    result += mFileDump.name;
+    result += "\n";
+    write(fd, result.c_str(), result.size());
+
+    return NO_ERROR;
+}
+
+void SurfaceFlinger::dumpDrawCycle(bool prePrepare) {
+    Mutex::Autolock _l(mFileDump.lock);
+
+    // User might stop dump collection in middle of prepare & commit.
+    // Collect dumpsys again after commit and replace.
+    if (!mFileDump.running && !mFileDump.replaceAfterCommit) {
+        return;
+    }
+    Vector<String16> args;
+    std::string dumpsys;
+    {
+        Mutex::Autolock lock(mStateLock);
+        if (mFileDump.fullDump) {
+            dumpAllLocked(args, dumpsys);
+        } else {
+            dumpMini(dumpsys);
+        }
+    }
+
+    if (mFileDump.fullDump) {
+        const LayersProto layersProto = dumpDrawingStateProto(SurfaceTracing::TRACE_ALL);
+        const auto layerTree = LayerProtoParser::generateLayerTree(layersProto);
+        dumpsys.append(LayerProtoParser::layerTreeToString(layerTree));
+        dumpsys.append("\n");
+        dumpsys.append("Offscreen Layers:\n");
+        for (Layer* offscreenLayer : mOffscreenLayers) {
+            offscreenLayer->traverse(LayerVector::StateSet::Drawing,
+                                     [&](Layer* layer) {
+                                         layer->dumpCallingUidPid(dumpsys);
+                                     });
+        }
+    }
+
+    char timeStamp[32];
+    char dataSize[32];
+    char hms[32];
+    long millis;
+    struct timeval tv;
+    struct tm *ptm;
+    gettimeofday(&tv, NULL);
+    ptm = localtime(&tv.tv_sec);
+    strftime (hms, sizeof (hms), "%H:%M:%S", ptm);
+    millis = tv.tv_usec / 1000;
+    snprintf(timeStamp, sizeof(timeStamp), "Timestamp: %s.%03ld", hms, millis);
+    snprintf(dataSize, sizeof(dataSize), "Size: %8zu", dumpsys.size());
+    std::fstream fs;
+    fs.open(mFileDump.name, std::ios::app);
+    if (!fs) {
+        ALOGE("Failed to open %s file for dumpsys", mFileDump.name);
+        return;
+    }
+    // Format:
+    //    | start code | after commit? | time stamp | dump size | dump data |
+    fs.seekp(mFileDump.position, std::ios::beg);
+    fs << "#@#@-- DUMPSYS START --@#@#" << std::endl;
+    fs << "PostCommit: " << ( prePrepare ? "false" : "true" ) << std::endl;
+    fs << timeStamp << std::endl;
+    fs << dataSize << std::endl;
+    fs << dumpsys << std::endl;
+
+    if (prePrepare) {
+        mFileDump.replaceAfterCommit = true;
+    } else {
+        mFileDump.replaceAfterCommit = false;
+        // Reposition only after commit.
+        // Keep file size to appx 20 MB limit by default, wrap around if exceeds.
+        mFileDump.position = fs.tellp();
+        if (!mFileDump.noLimit && (mFileDump.position > (20 * 1024 * 1024))) {
+            mFileDump.position = 0;
+        }
+    }
+    fs.close();
+}
+
 status_t SurfaceFlinger::dumpCritical(int fd, const DumpArgs&, bool asProto) {
     if (asProto && mTracing.isEnabled()) {
         mTracing.writeToFileAsync();
@@ -4401,7 +5424,7 @@
 }
 
 void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) const {
-    StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriod());
+    StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriodFromHWC());
 
     if (args.size() > 1) {
         const auto name = String8(args[1]);
@@ -4466,7 +5489,7 @@
     mPhaseConfiguration->dump(result);
     StringAppendF(&result,
                   "      present offset: %9" PRId64 " ns\t     VSYNC period: %9" PRId64 " ns\n\n",
-                  dispSyncPresentTimeOffset, getVsyncPeriod());
+                  dispSyncPresentTimeOffset, getVsyncPeriodFromHWC());
 
     scheduler::RefreshRateConfigs::Policy policy = mRefreshRateConfigs->getDisplayManagerPolicy();
     StringAppendF(&result,
@@ -4696,6 +5719,42 @@
                   }).get());
 }
 
+void SurfaceFlinger::dumpMini(std::string& result) const {
+    /*
+     *      * Dump Display state
+     *           */
+    StringAppendF(&result, "Displays (%zu entries)\n", mDisplays.size());
+    for (const auto& [token, display] : mDisplays) {
+        display->dump(result);
+    }
+    result.append("\n");
+
+    /*
+     * HWC layer minidump
+     */
+    for (const auto& [token, display] : mDisplays) {
+        const auto displayId = display->getId();
+        if (!displayId) {
+            continue;
+        }
+
+        StringAppendF(&result, "Display %s HWC layers:\n", to_string(*displayId).c_str());
+        Layer::miniDumpHeader(result);
+        const DisplayDevice& displayDevice = *display;
+        mCurrentState.traverseInZOrder(
+                [&](Layer* layer) { layer->miniDump(result, displayDevice); });
+        result.append("\n");
+    }
+
+    /*
+     * Dump HWComposer state
+     */
+    result.append("h/w composer state:\n");
+    bool hwcDisabled = mDebugDisableHWC || mDebugRegion;
+    StringAppendF(&result, "  h/w composer %s\n", hwcDisabled ? "disabled" : "enabled");
+    getHwComposer().dump(result);
+}
+
 void SurfaceFlinger::dumpAllLocked(const DumpArgs& args, std::string& result) const {
     const bool colorize = !args.empty() && args[0] == String16("--color");
     Colorizer colorizer(colorize);
@@ -5010,9 +6069,9 @@
         code == IBinder::SYSPROPS_TRANSACTION) {
         return OK;
     }
-    // Numbers from 1000 to 1036 are currently used for backdoors. The code
+    // Numbers from 1000 to 1036 and 20000 to 20002 are currently used for backdoors. The code
     // in onTransact verifies that the user is root, and has access to use SF.
-    if (code >= 1000 && code <= 1036) {
+    if ((code >= 1000 && code <= 1036) || (code >= 20000 && code <= 20002)) {
         ALOGV("Accessing SurfaceFlinger through backdoor code: %u", code);
         return OK;
     }
@@ -5331,8 +6390,12 @@
             case 1035: {
                 n = data.readInt32();
                 mDebugDisplayConfigSetByBackdoor = false;
-                if (n >= 0) {
+                const auto numConfigs = mRefreshRateConfigs->getAllRefreshRates().size();
+                if ((n >= 0) && (n < numConfigs)) {
                     const auto displayToken = getInternalDisplayToken();
+                    if(isSupportedConfigSwitch(displayToken, n) != NO_ERROR) {
+                        return BAD_VALUE;
+                    }
                     status_t result = setActiveConfig(displayToken, n);
                     if (result != NO_ERROR) {
                         return result;
@@ -5353,6 +6416,163 @@
                 }
                 return NO_ERROR;
             }
+            case 20000: {
+                uint64_t disp = 0;
+                int32_t mode = HWC_POWER_MODE_NORMAL;
+                int32_t tile_h_loc = -1;
+                int32_t tile_v_loc = -1;
+                uint32_t num_h_tiles = 1;
+                uint32_t num_v_tiles = 1;
+                if (data.readUint64(&disp) != NO_ERROR) {
+                    err = BAD_TYPE;
+                    ALOGE("Invalid 64-bit unsigned-int display id parameter.");
+                    break;
+                }
+                if (data.readInt32(&mode) != NO_ERROR) {
+                    err = BAD_TYPE;
+                    ALOGE("Invalid 32-bit signed-int power mode parameter.");
+                    break;
+                }
+                if (data.readInt32(&tile_h_loc) != NO_ERROR) {
+                    tile_h_loc = -1;
+                }
+                if (data.readInt32(&tile_v_loc) != NO_ERROR) {
+                    tile_v_loc = 0;
+                }
+                if (tile_h_loc < 0) {
+                    ALOGI("Debug: Set display = %llu, power mode = %d", (unsigned long long)disp,
+                          mode);
+                    setPowerMode(getPhysicalDisplayToken(disp), mode);
+                } else {
+#if defined(QTI_DISPLAY_CONFIG_ENABLED) && defined(DISPLAY_CONFIG_TILE_DISPLAY_APIS_1_0)
+                    ::DisplayConfig::PowerMode hwcMode = ::DisplayConfig::PowerMode::kOff;
+                    switch (mode) {
+                        case HWC_POWER_MODE_DOZE:
+                            hwcMode = ::DisplayConfig::PowerMode::kDoze;
+                            break;
+                        case HWC_POWER_MODE_NORMAL:
+                            hwcMode = ::DisplayConfig::PowerMode::kOn;
+                            break;
+                        case HWC_POWER_MODE_DOZE_SUSPEND:
+                            hwcMode = ::DisplayConfig::PowerMode::kDozeSuspend;
+                            break;
+                        default:
+                            break;
+                    }
+                    // A regular display has one h tile and one v tile.
+                    mDisplayConfigIntf->GetDisplayTileCount(disp, &num_h_tiles, &num_v_tiles);
+                    if (((num_h_tiles * num_v_tiles) < 2) || tile_h_loc >= num_h_tiles
+                        || tile_v_loc >= num_v_tiles) {
+                        ALOGE("Debug: Display %llu has only %u h tiles and %u v tiles. Not a true "
+                              "tile display or invalid tile h or v locations given.",
+                              (unsigned long long)disp, num_h_tiles, num_v_tiles);
+                    } else {
+                        err = mDisplayConfigIntf->SetPowerModeTiled(disp, hwcMode, tile_h_loc,
+                                                                    tile_v_loc);
+                        if (NO_ERROR != err) {
+                            ALOGE("Debug: DisplayConfig::SetPowerModeTiled() returned error %d",
+                                  err);
+                            break;
+                        }
+                    }
+#endif
+                    ALOGI("Debug: Set display = %llu, power mode = %d at tile h loc = %d, tile v "
+                          "loc = %d (Has %u h tiles and %u v tiles)", (unsigned long long)disp,
+                          mode, tile_h_loc, tile_v_loc, num_h_tiles, num_v_tiles);
+                }
+                return NO_ERROR;
+            }
+            case 20001: {
+                uint64_t disp = 0;
+                int32_t level = 0;
+                int32_t tile_h_loc = -1;
+                int32_t tile_v_loc = -1;
+                uint32_t num_h_tiles = 1;
+                uint32_t num_v_tiles = 1;
+                if (data.readUint64(&disp) != NO_ERROR) {
+                    err = BAD_TYPE;
+                    ALOGE("Invalid 64-bit unsigned-int display id parameter.");
+                    break;
+                }
+                if (data.readInt32(&level) != NO_ERROR) {
+                    err = BAD_TYPE;
+                    ALOGE("Invalid 32-bit signed-int brightess parameter.");
+                    break;
+                }
+                float levelf = static_cast<float>(level)/255.0f;
+                if (data.readInt32(&tile_h_loc) != NO_ERROR) {
+                    tile_h_loc = -1;
+                }
+                if (data.readInt32(&tile_v_loc) != NO_ERROR) {
+                    tile_v_loc = 0;
+                }
+                if (tile_h_loc < 0) {
+                    ALOGI("Debug: Set display = %llu, brightness level = %d/255 (%0.2ff)",
+                          (unsigned long long)disp, level, levelf);
+                    setDisplayBrightness(getPhysicalDisplayToken(disp), levelf);
+                } else {
+#if defined(QTI_DISPLAY_CONFIG_ENABLED) && defined(DISPLAY_CONFIG_TILE_DISPLAY_APIS_1_0)
+                    // A regular display has one h tile and one v tile.
+                    mDisplayConfigIntf->GetDisplayTileCount(disp, &num_h_tiles, &num_v_tiles);
+                    if (((num_h_tiles * num_v_tiles) < 2) || tile_h_loc >= num_h_tiles
+                        || tile_v_loc >= num_v_tiles) {
+                        ALOGE("Debug: Display %llu has only %u h tiles and %u v tiles. Not a true "
+                              "tile display or invalid tile h or v locations given.",
+                              (unsigned long long)disp, num_h_tiles, num_v_tiles);
+                    } else {
+                        err = mDisplayConfigIntf->SetPanelBrightnessTiled(disp, level, tile_h_loc,
+                                                                          tile_v_loc);
+                        if (NO_ERROR != err) {
+                            ALOGE("Debug: DisplayConfig::SetPanelBrightnessTiled() returned error "
+                                  "%d", err);
+                            break;
+                        }
+                    }
+#endif
+                    ALOGI("Debug: Set display = %llu, brightness level = %d/255 (%0.2ff) at tile h "
+                          "loc = %d, tile v loc = %d (Has %u h tiles and %u v tiles)",
+                          (unsigned long long)disp, level, levelf, tile_h_loc, tile_v_loc,
+                          num_h_tiles, num_v_tiles);
+                }
+                return NO_ERROR;
+            }
+            case 20002: {
+                uint64_t disp = 0;
+                int32_t pref = 0;
+                if (data.readUint64(&disp) != NO_ERROR) {
+                    err = BAD_TYPE;
+                    ALOGE("Invalid 64-bit unsigned-int display id parameter.");
+                    break;
+                }
+                if (data.readInt32(&pref) != NO_ERROR) {
+                    err = BAD_TYPE;
+                    ALOGE("Invalid 32-bit signed-int wider-mode preference parameter.");
+                    break;
+                }
+                ALOGI("Debug: Set display = %llu, wider-mode preference = %d",
+                      (unsigned long long)disp, pref);
+#if defined(QTI_DISPLAY_CONFIG_ENABLED) && defined(DISPLAY_CONFIG_TILE_DISPLAY_APIS_1_0)
+                ::DisplayConfig::WiderModePref wider_mode_pref =
+                    ::DisplayConfig::WiderModePref::kNoPreference;
+                switch (pref) {
+                    case 1:
+                        wider_mode_pref = ::DisplayConfig::WiderModePref::kWiderAsyncMode;
+                        break;
+                    case 2:
+                        wider_mode_pref = ::DisplayConfig::WiderModePref::kWiderSyncMode;
+                        break;
+                    default:
+                        // Use default DisplayConfig::WiderModePref::kNoPreference.
+                        break;
+                }
+                err = mDisplayConfigIntf->SetWiderModePreference(disp, wider_mode_pref);
+                if (NO_ERROR != err) {
+                    ALOGE("Debug: DisplayConfig::SetWiderModePreference() returned error %d", err);
+                    break;
+                }
+#endif
+                return NO_ERROR;
+            }
         }
     }
     return err;
@@ -5365,7 +6585,7 @@
 
 void SurfaceFlinger::repaintEverythingForHWC() {
     mRepaintEverything = true;
-    mPowerAdvisor.notifyDisplayUpdateImminent();
+    notifyAllDisplaysUpdateImminent();
     mEventQueue->invalidate();
 }
 
@@ -5860,6 +7080,9 @@
     std::vector<Layer*> renderedLayers;
     Region clearRegion = Region::INVALID_REGION;
     traverseLayers([&](Layer* layer) {
+        if (layer->isSecureDisplay()) {
+            return;
+        }
         const bool supportProtectedContent = false;
         Region clip(renderArea.getBounds());
         compositionengine::LayerFE::ClientCompositionTargetSettings targetSettings{
@@ -5998,6 +7221,8 @@
     LOG_ALWAYS_FATAL_IF(!policy && !overridePolicy, "Can only clear the override policy");
 
     if (!display->isPrimary()) {
+        return NO_ERROR;
+
         // TODO(b/144711714): For non-primary displays we should be able to set an active config
         // as well. For now, just call directly to setActiveConfigWithConstraints but ideally
         // it should go thru setDesiredActiveConfig, similar to primary display.
@@ -6025,6 +7250,14 @@
                                             ->getVsyncPeriod();
         mScheduler->onNonPrimaryDisplayConfigChanged(mAppConnectionHandle, display->getId()->value,
                                                      policy->defaultConfig, vsyncPeriod);
+
+        if (isInternalDisplay(display)) {
+            uint32_t hwcDisplayId;
+            if (getHwcDisplayId(display, &hwcDisplayId)) {
+                setDisplayExtnActiveConfig(hwcDisplayId, policy->defaultConfig.value());
+            }
+        }
+
         return NO_ERROR;
     }
 
@@ -6072,6 +7305,10 @@
               preferredRefreshRate.getConfigId().value());
         setDesiredActiveConfig(
                 {preferredRefreshRate.getConfigId(), Scheduler::ConfigEvent::Changed});
+        uint32_t hwcDisplayId;
+        if (getHwcDisplayId(display, &hwcDisplayId)) {
+            setDisplayExtnActiveConfig(hwcDisplayId, preferredRefreshRate.getConfigId().value());
+        }
     } else {
         LOG_ALWAYS_FATAL("Desired config not allowed: %d",
                          preferredRefreshRate.getConfigId().value());
@@ -6080,6 +7317,27 @@
     return NO_ERROR;
 }
 
+bool SurfaceFlinger::canAllocateHwcDisplayIdForVDS(uint64_t usage) {
+    uint64_t flag_mask_pvt_wfd = ~0;
+    uint64_t flag_mask_hw_video = ~0;
+    char value[PROPERTY_VALUE_MAX] = {};
+    property_get("vendor.display.vds_allow_hwc", value, "0");
+    int allowHwcForVDS = atoi(value);
+    // 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;
+    // GRALLOC_USAGE_PRIVATE_WFD + GRALLOC_USAGE_SW_READ_OFTEN
+    // WFD using GLES (directstreaming).
+    sDirectStreaming = ((usage & GRALLOC_USAGE_PRIVATE_WFD) &&
+                        (usage & GRALLOC_USAGE_SW_READ_OFTEN));
+    return (allowHwcForVDS || ((usage & flag_mask_pvt_wfd) &&
+            (usage & flag_mask_hw_video)));
+}
+
+bool SurfaceFlinger::skipColorLayer(const char* layerType) {
+    return (sDirectStreaming && !strncmp(layerType, "ColorLayer", strlen("ColorLayer")));
+}
 status_t SurfaceFlinger::setDesiredDisplayConfigSpecs(const sp<IBinder>& displayToken,
                                                       int32_t defaultConfig,
                                                       float primaryRefreshRateMin,
@@ -6252,6 +7510,11 @@
         Mutex::Autolock lock(mStateLock);
         if (authenticateSurfaceTextureLocked(surface)) {
             sp<Layer> layer = (static_cast<MonitoredProducer*>(surface.get()))->getLayer();
+            if (layer == nullptr) {
+                ALOGE("Attempt to set frame rate on a layer that no longer exists");
+                return BAD_VALUE;
+            }
+
             if (layer->setFrameRate(
                         Layer::FrameRate(frameRate,
                                          Layer::FrameRate::convertCompatibility(compatibility)))) {
@@ -6358,6 +7621,210 @@
     }));
 }
 
+void SurfaceFlinger::setContentFps(uint32_t contentFps) {
+    if (mBootFinished && !mSetActiveConfigPending) {
+        if (mDisplayExtnIntf) {
+            mDisplayExtnIntf->SetContentFps(contentFps);
+        }
+    }
+}
+
+bool SurfaceFlinger::isInternalDisplay(const sp<DisplayDevice>& display) {
+    if (display) {
+        const auto connectionType = display->getConnectionType();
+        return (connectionType && (*connectionType == DisplayConnectionType::Internal));
+    }
+    return false;
+}
+
+bool SurfaceFlinger::getHwcDisplayId(const sp<DisplayDevice>& display, uint32_t *hwcDisplayId) {
+    if (display) {
+        const auto displayId = display->getId();
+        if (displayId) {
+            const auto halDisplayId = getHwComposer().fromPhysicalDisplayId(*displayId);
+            if (halDisplayId) {
+                *hwcDisplayId = static_cast<uint32_t>(*halDisplayId);
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void SurfaceFlinger::updateDisplayExtension(uint32_t displayId, uint32_t configId, bool connected) {
+    ALOGV("updateDisplayExtn: Display:%d, Config:%d, Connected:%d", displayId, configId, connected);
+
+#ifdef EARLY_WAKEUP_FEATURE
+    if (connected) {
+        mDisplayExtnIntf->RegisterDisplay(displayId);
+        mDisplayExtnIntf->SetActiveConfig(displayId, configId);
+    } else {
+        mDisplayExtnIntf->UnregisterDisplay(displayId);
+    }
+#endif
+}
+
+void SurfaceFlinger::setDisplayExtnActiveConfig(uint32_t displayId, uint32_t activeConfigId) {
+    if (!mEarlyWakeUpEnabled) {
+        return;
+    }
+
+    ALOGV("setDisplayExtnActiveConfig: Display:%d, ActiveConfig:%d", displayId, activeConfigId);
+#ifdef EARLY_WAKEUP_FEATURE
+    mDisplayExtnIntf->SetActiveConfig(displayId, activeConfigId);
+#endif
+}
+
+void SurfaceFlinger::notifyAllDisplaysUpdateImminent() {
+    if (!mEarlyWakeUpEnabled) {
+        mPowerAdvisor.notifyDisplayUpdateImminent();
+        return;
+    }
+
+#ifdef EARLY_WAKEUP_FEATURE
+    if (mPowerAdvisor.canNotifyDisplayUpdateImminent()) {
+        ATRACE_CALL();
+        // Notify Display Extn for GPU and Display Early Wakeup
+        mDisplayExtnIntf->NotifyEarlyWakeUp(true, true);
+    }
+#endif
+}
+
+void SurfaceFlinger::notifyDisplayUpdateImminent() {
+    if (!mEarlyWakeUpEnabled) {
+        mPowerAdvisor.notifyDisplayUpdateImminent();
+        return;
+    }
+
+#ifdef EARLY_WAKEUP_FEATURE
+    if (mPowerAdvisor.canNotifyDisplayUpdateImminent()) {
+        ATRACE_CALL();
+
+        if (mInternalPresentationDisplays) {
+            // Notify Display Extn for GPU Early Wakeup only
+            mDisplayExtnIntf->NotifyEarlyWakeUp(true, false);
+            wakeUpPresentationDisplays = true;
+        } else {
+            // Notify Display Extn for GPU and Display Early Wakeup
+            mDisplayExtnIntf->NotifyEarlyWakeUp(true, true);
+        }
+    }
+#endif
+}
+
+void SurfaceFlinger::handlePresentationDisplaysEarlyWakeup(size_t updatingDisplays,
+                                                           uint32_t layerStackId) {
+    // Filter-out the updating display(s) for early wake-up in Presentation mode.
+    if (mEarlyWakeUpEnabled && mInternalPresentationDisplays) {
+        ATRACE_CALL();
+        uint32_t hwcDisplayId;
+        bool internalDisplay = false;
+        bool singleUpdatingDisplay = (updatingDisplays == 1);
+
+        if (singleUpdatingDisplay) {
+            Mutex::Autolock lock(mStateLock);
+            const sp<DisplayDevice> display = getDisplayByLayerStack(layerStackId);
+            internalDisplay = isInternalDisplay(display) && getHwcDisplayId(display, &hwcDisplayId);
+        }
+
+#ifdef EARLY_WAKEUP_FEATURE
+        if (!singleUpdatingDisplay) {
+            // Notify Display Extn for Early Wakeup of displays
+            mDisplayExtnIntf->NotifyEarlyWakeUp(false, true);
+        } else if (internalDisplay) {
+            // Notify Display Extn for Early Wakeup of given display
+            mDisplayExtnIntf->NotifyDisplayEarlyWakeUp(hwcDisplayId);
+        }
+#endif
+
+    }
+    wakeUpPresentationDisplays = false;
+}
+
+void SurfaceFlinger::updateInternalDisplaysPresentationMode() {
+    mInternalPresentationDisplays = false;
+    if (mDisplaysList.size() <= 1) {
+        return;
+    }
+
+    bool compareStack = false;
+    ui::LayerStack previousStackId;
+    for (const auto& display : mDisplaysList) {
+        if (isInternalDisplay(display)) {
+            auto currentStackId = display->getLayerStack();
+            // Compare Layer Stack IDs of Internal Displays
+            if (compareStack && (previousStackId != currentStackId)) {
+                mInternalPresentationDisplays = true;
+                return;
+            }
+            previousStackId = currentStackId;
+            compareStack = true;
+        }
+    }
+}
+
+void SurfaceFlinger::NotifyIdleStatus() {
+  mScheduler->setIdleState();
+}
+
+void SurfaceFlinger::setupEarlyWakeUpFeature() {
+#ifdef EARLY_WAKEUP_FEATURE
+    mEarlyWakeUpEnabled = false;
+    char propValue[PROPERTY_VALUE_MAX];
+    property_get("vendor.display.enable_early_wakeup", propValue, "0");
+    if (mDisplayExtnIntf && (atoi(propValue) == 1)) {
+        for (const auto& display : mDisplaysList) {
+            // Register Internal Physical Displays
+            if (isInternalDisplay(display)) {
+                uint32_t hwcDisplayId;
+                if (getHwcDisplayId(display, &hwcDisplayId)) {
+                    const auto displayId = display->getId();
+                    uint32_t configId = getHwComposer().getActiveConfigIndex(*displayId);
+                    updateDisplayExtension(hwcDisplayId, configId, true);
+                }
+            }
+        }
+        mEarlyWakeUpEnabled = true;
+    }
+    ALOGI("Early Wakeup Feature enabled: %d", mEarlyWakeUpEnabled);
+#endif
+}
+
+void SurfaceFlinger::createPhaseOffsetExtn() {
+#ifdef PHASE_OFFSET_EXTN
+    if (mUseAdvanceSfOffset) {
+        int ret = mComposerExtnIntf->CreatePhaseOffsetExtn(&g_comp_ext_intf_.phaseOffsetExtnIntf);
+        if (ret) {
+            ALOGI("Unable to create PhaseOffset extension");
+            return;
+        }
+
+        // Get the Advanced SF Offsets from Phase Offset Extn
+        std::unordered_map<float, int64_t> advancedSfOffsets;
+        g_comp_ext_intf_.phaseOffsetExtnIntf->GetAdvancedSfOffsets(&advancedSfOffsets);
+
+        // Update the Advanced SF Offsets
+        std::lock_guard<std::mutex> lock(mActiveConfigLock);
+        mPhaseConfiguration->UpdateSfOffsets(advancedSfOffsets);
+        mVSyncModulator->setPhaseOffsets(mPhaseConfiguration->getCurrentOffsets());
+    }
+#endif
+}
+
+void SurfaceFlinger::setEarlyWakeUpConfig(const sp<DisplayDevice>& display, hal::PowerMode mode) {
+    if (mEarlyWakeUpEnabled && isInternalDisplay(display)) {
+        uint32_t hwcDisplayId;
+        if (getHwcDisplayId(display, &hwcDisplayId)) {
+            // Enable/disable Early Wake-up feature on a display based on its Power mode.
+            bool enable = (mode == hal::PowerMode::ON) || (mode == hal::PowerMode::DOZE);
+            ALOGV("setEarlyWakeUpConfig: Display: %d, Enable: %d", hwcDisplayId, enable);
+#ifdef DYNAMIC_EARLY_WAKEUP_CONFIG
+            mDisplayExtnIntf->SetEarlyWakeUpConfig(hwcDisplayId, enable);
+#endif
+        }
+    }
+}
+
 } // namespace android
 
 #if defined(__gl_h_)
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 913158f..54cdefd 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -81,9 +81,34 @@
 #include <unordered_map>
 #include <unordered_set>
 #include <utility>
+#include <list>
 
 using namespace android::surfaceflinger;
 
+namespace smomo {
+class SmomoIntf;
+} // namespace smomo
+
+namespace composer {
+class ComposerExtnIntf;
+class ComposerExtnLib;
+class FrameSchedulerIntf;
+class DisplayExtnIntf;
+} // namespace composer
+
+using smomo::SmomoIntf;
+
+namespace composer {
+class LayerExtnIntf;
+}
+
+using composer::LayerExtnIntf;
+
+namespace composer {
+class FrameExtnIntf;
+}
+using composer::FrameExtnIntf;
+
 namespace android {
 
 class Client;
@@ -172,6 +197,52 @@
     int32_t mComposerSequenceId = 0;
 };
 
+class SmomoWrapper {
+public:
+    SmomoWrapper() {}
+    ~SmomoWrapper();
+
+    bool init();
+
+    SmomoIntf* operator->() { return mInst; }
+    operator bool() { return mInst != nullptr; }
+
+    SmomoWrapper(const SmomoWrapper&) = delete;
+    SmomoWrapper& operator=(const SmomoWrapper&) = delete;
+
+private:
+    SmomoIntf *mInst = nullptr;
+    void *mSmoMoLibHandle = nullptr;
+
+    using CreateSmoMoFuncPtr = std::add_pointer<bool(uint16_t, SmomoIntf**)>::type;
+    using DestroySmoMoFuncPtr = std::add_pointer<void(SmomoIntf*)>::type;
+    CreateSmoMoFuncPtr mSmoMoCreateFunc;
+    DestroySmoMoFuncPtr mSmoMoDestroyFunc;
+};
+
+class LayerExtWrapper {
+public:
+    LayerExtWrapper() {}
+    ~LayerExtWrapper();
+
+    bool init();
+
+    LayerExtnIntf* operator->() { return     mInst; }
+    operator bool() { return mInst != nullptr; }
+
+    LayerExtWrapper(const LayerExtWrapper&) = delete;
+    LayerExtWrapper& operator=(const LayerExtWrapper&) = delete;
+
+private:
+    LayerExtnIntf *mInst = nullptr;
+    void *mLayerExtLibHandle = nullptr;
+
+    using CreateLayerExtnFuncPtr = std::add_pointer<bool(uint16_t, LayerExtnIntf**)>::type;
+    using DestroyLayerExtnFuncPtr = std::add_pointer<void(LayerExtnIntf*)>::type;
+    CreateLayerExtnFuncPtr mLayerExtCreateFunc;
+    DestroyLayerExtnFuncPtr mLayerExtDestroyFunc;
+};
+
 class SurfaceFlinger : public BnSurfaceComposer,
                        public PriorityDumper,
                        public ClientCache::ErasedRecipient,
@@ -242,6 +313,8 @@
 
     static bool useContextPriority;
 
+    static bool sDirectStreaming;
+
     // The data space and pixel format that SurfaceFlinger expects hardware composer
     // to composite efficiently. Meaning under most scenarios, hardware composer
     // will accept layers with the data space and pixel format.
@@ -298,10 +371,10 @@
 
     // enable/disable h/w composer event
     // TODO: this should be made accessible only to EventThread
-    void setPrimaryVsyncEnabled(bool enabled);
+    void setVsyncEnabled(bool enabled);
 
     // main thread function to enable/disable h/w composer event
-    void setPrimaryVsyncEnabledInternal(bool enabled) REQUIRES(mStateLock);
+    void setVsyncEnabledInternal(bool enabled) REQUIRES(mStateLock);
 
     // called on the main thread by MessageQueue when an internal message
     // is received
@@ -336,6 +409,10 @@
     // debug.sf.disable_client_composition_cache
     bool mDisableClientCompositionCache = false;
 
+    nsecs_t mVsyncTimeStamp = -1;
+
+    void NotifyIdleStatus();
+
 private:
     friend class BufferLayer;
     friend class BufferQueueLayer;
@@ -504,6 +581,9 @@
     status_t setFrameRate(const sp<IGraphicBufferProducer>& surface, float frameRate,
                           int8_t compatibility) override;
     status_t acquireFrameRateFlexibilityToken(sp<IBinder>* outToken) override;
+    status_t setDisplayElapseTime(const sp<DisplayDevice>& display) const;
+    status_t isSupportedConfigSwitch(const sp<IBinder>& displayToken, int config);
+
     /* ------------------------------------------------------------------------
      * DeathRecipient interface
      */
@@ -526,6 +606,7 @@
             int32_t sequenceId, hal::HWDisplayId display,
             const hal::VsyncPeriodChangeTimeline& updatedTimeline) override;
     void onSeamlessPossible(int32_t sequenceId, hal::HWDisplayId display) override;
+    void setPowerModeOnMainThread(const sp<IBinder>& displayToken, int mode);
 
     /* ------------------------------------------------------------------------
      * ISchedulerCallback
@@ -607,6 +688,7 @@
     void commitInputWindowCommands() REQUIRES(mStateLock);
     void setInputWindowsFinished();
     void updateCursorAsync();
+    void updateFrameScheduler();
     void initScheduler(DisplayId primaryDisplayId);
 
     /* handlePageFlip - latch a new buffer if available and compute the dirty
@@ -645,6 +727,7 @@
     bool transactionIsReadyToBeApplied(int64_t desiredPresentTime,
                                        const Vector<ComposerState>& states);
     uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
+    void checkVirtualDisplayHint(const Vector<DisplayState>& displays);
     uint32_t addInputWindowCommands(const InputWindowCommands& inputWindowCommands)
             REQUIRES(mStateLock);
 
@@ -737,6 +820,9 @@
     void traverseLayersInDisplay(const sp<const DisplayDevice>& display,
                                  const LayerVector::Visitor& visitor);
 
+
+    bool canAllocateHwcDisplayIdForVDS(uint64_t usage);
+    bool skipColorLayer(const char* layerType);
     sp<StartPropertySetThread> mStartPropertySetThread;
 
     /* ------------------------------------------------------------------------
@@ -819,6 +905,9 @@
      */
     void invalidateHwcGeometry();
 
+    sp<DisplayDevice> getVsyncSource();
+    void updateVsyncSource();
+    void forceResyncModel();
     void postComposition();
     void getCompositorTiming(CompositorTiming* compositorTiming);
     void updateCompositorTiming(const DisplayStatInfo& stats, nsecs_t compositeTime,
@@ -845,19 +934,23 @@
                                const DisplayDeviceState& currentState,
                                const DisplayDeviceState& drawingState) REQUIRES(mStateLock);
     void processDisplayHotplugEventsLocked() REQUIRES(mStateLock);
+    void setFrameBufferSizeForScaling(sp<DisplayDevice> displayDevice,
+                                      const DisplayDeviceState& state);
 
     void dispatchDisplayHotplugEvent(PhysicalDisplayId displayId, bool connected);
 
     /* ------------------------------------------------------------------------
      * VSync
      */
-    nsecs_t getVsyncPeriod() const REQUIRES(mStateLock);
+    nsecs_t getVsyncPeriodFromHWC() const REQUIRES(mStateLock);
 
     // Sets the refresh rate by switching active configs, if they are available for
     // the desired refresh rate.
     void changeRefreshRateLocked(const RefreshRate&, Scheduler::ConfigEvent event)
             REQUIRES(mStateLock);
 
+    void setRefreshRateTo(int32_t refreshRate);
+
     bool isDisplayConfigAllowed(HwcConfigIndexType configId) const REQUIRES(mStateLock);
 
     // Gets the fence for the previous frame.
@@ -940,7 +1033,7 @@
     }
 
     void dumpAllLocked(const DumpArgs& args, std::string& result) const REQUIRES(mStateLock);
-
+    void dumpMini(std::string& result) const REQUIRES(mStateLock);
     void appendSfConfigString(std::string& result) const;
     void listLayersLocked(std::string& result) const;
     void dumpStatsLocked(const DumpArgs& args, std::string& result) const REQUIRES(mStateLock);
@@ -974,6 +1067,19 @@
 
     status_t doDump(int fd, const DumpArgs& args, bool asProto);
 
+    status_t doDumpContinuous(int fd, const DumpArgs& args);
+    void dumpDrawCycle(bool prePrepare);
+
+    struct {
+      Mutex lock;
+      const char *name = "/data/misc/wmtrace/dumpsys.txt";
+      bool running = false;
+      bool noLimit = false;
+      bool fullDump = false;
+      bool replaceAfterCommit = false;
+      long int position = 0;
+    } mFileDump;
+
     status_t dumpCritical(int fd, const DumpArgs&, bool asProto);
 
     status_t dumpAll(int fd, const DumpArgs& args, bool asProto) override {
@@ -982,6 +1088,30 @@
 
     void onFrameRateFlexibilityTokenReleased();
 
+    void setContentFps(uint32_t contentFps);
+
+    bool isInternalDisplay(const sp<DisplayDevice>& display);
+
+    bool getHwcDisplayId(const sp<DisplayDevice>& display, uint32_t *hwcDisplayId);
+
+    void updateDisplayExtension(uint32_t displayId, uint32_t configId, bool connected);
+
+    void setDisplayExtnActiveConfig(uint32_t displayId, uint32_t activeConfigId);
+
+    void notifyAllDisplaysUpdateImminent();
+
+    void notifyDisplayUpdateImminent();
+
+    void handlePresentationDisplaysEarlyWakeup(size_t updatingDisplays, uint32_t layerStackId);
+
+    void updateInternalDisplaysPresentationMode();
+
+    void setupEarlyWakeUpFeature();
+
+    void createPhaseOffsetExtn();
+
+    void setEarlyWakeUpConfig(const sp<DisplayDevice>& display, hal::PowerMode mode);
+
     /* ------------------------------------------------------------------------
      * VrFlinger
      */
@@ -1000,6 +1130,8 @@
 
     // access must be protected by mStateLock
     mutable Mutex mStateLock;
+    mutable Mutex mVsyncLock;
+    mutable Mutex mDolphinStateLock;
     State mCurrentState{LayerVector::StateSet::Current};
     std::atomic<int32_t> mTransactionFlags = 0;
     Condition mTransactionCV;
@@ -1075,6 +1207,8 @@
 
     // don't use a lock for these, we don't care
     int mDebugRegion = 0;
+    bool mVsyncSourceReliableOnDoze = false;
+    bool mPluggableVsyncPrioritized = false;
     bool mDebugDisableHWC = false;
     bool mDebugDisableTransformHint = false;
     volatile nsecs_t mDebugInTransaction = 0;
@@ -1098,10 +1232,16 @@
     std::atomic<bool> mDisableBlurs = false;
     // If blurs are considered expensive and should require high GPU frequency.
     bool mBlursAreExpensive = false;
+    bool mUseAdvanceSfOffset = false;
+    bool mUseFbScaling = false;
+    bool mAsyncVdsCreationSupported = false;
     std::atomic<uint32_t> mFrameMissedCount = 0;
     std::atomic<uint32_t> mHwcFrameMissedCount = 0;
     std::atomic<uint32_t> mGpuFrameMissedCount = 0;
 
+    std::mutex mVsyncPeriodMutex;
+    std::vector<nsecs_t> mVsyncPeriods;
+
     TransactionCompletedThread mTransactionCompletedThread;
 
     // Restrict layers to use two buffers in their bufferqueues.
@@ -1162,6 +1302,10 @@
     bool mHasPoweredOff = false;
 
     std::atomic<size_t> mNumLayers = 0;
+    // Vsync Source
+    sp<DisplayDevice> mActiveVsyncSource = NULL;
+    sp<DisplayDevice> mNextVsyncSource = NULL;
+    std::list<sp<DisplayDevice>> mDisplaysList;
 
     // Verify that transaction is being called by an approved process:
     // either AID_GRAPHICS or AID_SYSTEM.
@@ -1295,6 +1439,39 @@
     int mFrameRateFlexibilityTokenCount = 0;
 
     sp<IBinder> mDebugFrameRateFlexibilityToken;
+
+    SmomoWrapper mSmoMo;
+    LayerExtWrapper mLayerExt;
+
+public:
+    nsecs_t mRefreshTimeStamp = -1;
+    nsecs_t mVsyncPeriod = -1;
+    std::string mNameLayerMax;
+    int mMaxQueuedFrames = -1;
+    int mNumIdle = -1;
+
+private:
+    bool mEarlyWakeUpEnabled = false;
+    bool wakeUpPresentationDisplays = false;
+    bool mInternalPresentationDisplays = false;
+    bool mDolphinFuncsEnabled = false;
+    void *mDolphinHandle = nullptr;
+    bool (*mDolphinInit)() = nullptr;
+    bool (*mDolphinMonitor)(int number, nsecs_t vsyncPeriod) = nullptr;
+    void (*mDolphinScaling)(int numIdle, int maxQueuedFrames) = nullptr;
+    void (*mDolphinRefresh)() = nullptr;
+    void (*mDolphinDequeueBuffer)(const char *name) = nullptr;
+    void (*mDolphinQueueBuffer)(const char *name) = nullptr;
+
+    FrameExtnIntf* mFrameExtn = nullptr;
+    void *mFrameExtnLibHandle = nullptr;
+    bool (*mCreateFrameExtnFunc)(FrameExtnIntf **interface) = nullptr;
+    bool (*mDestroyFrameExtnFunc)(FrameExtnIntf *interface) = nullptr;
+    composer::ComposerExtnIntf *mComposerExtnIntf = nullptr;
+    composer::FrameSchedulerIntf *mFrameSchedulerExtnIntf = nullptr;
+    composer::DisplayExtnIntf *mDisplayExtnIntf = nullptr;
+    bool mUseLayerExt = false;
+    bool mSplitLayerExt = false;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index ce5f35c..06bdcdc 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -85,7 +85,7 @@
 using HotplugEvent = TestableSurfaceFlinger::HotplugEvent;
 using HWC2Display = TestableSurfaceFlinger::HWC2Display;
 
-constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666;
+constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'667;
 constexpr int32_t DEFAULT_DPI = 320;
 constexpr int DEFAULT_VIRTUAL_DISPLAY_SURFACE_FORMAT = HAL_PIXEL_FORMAT_RGB_565;
 
diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
index b50ddf5..2a59a28 100644
--- a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
+++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h
@@ -35,6 +35,7 @@
 
     void setRefreshRateFps(float) override {}
     void dump(std::string&) const override {}
+    void UpdateSfOffsets(std::unordered_map<float, int64_t>) override {}
 };
 
 } // namespace android::scheduler
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 1aa7320..72c4395 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -115,7 +115,8 @@
     ASSERT_NO_FATAL_FAILURE(
             connection = mScheduler->createDisplayEventConnection(handle,
                                                                   ISurfaceComposer::
-                                                                          eConfigChangedSuppress));
+                                                                          eConfigChangedSuppress,
+                                                                  false /* No Refresh */));
     EXPECT_FALSE(connection);
     EXPECT_FALSE(mScheduler->getEventConnection(handle));
 
@@ -143,7 +144,9 @@
     ASSERT_NO_FATAL_FAILURE(
             connection = mScheduler->createDisplayEventConnection(mConnectionHandle,
                                                                   ISurfaceComposer::
-                                                                          eConfigChangedSuppress));
+                                                                          eConfigChangedSuppress,
+                                                                  false /* No Refresh */));
+
     ASSERT_EQ(mEventThreadConnection, connection);
     EXPECT_TRUE(mScheduler->getEventConnection(mConnectionHandle));
 
diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h
index d5ecae8..7b1c8f7 100644
--- a/services/surfaceflinger/tests/unittests/TestableScheduler.h
+++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h
@@ -51,7 +51,7 @@
 
     // Used to inject mock event thread.
     ConnectionHandle createConnection(std::unique_ptr<EventThread> eventThread) {
-        return Scheduler::createConnection(std::move(eventThread));
+        return Scheduler::createConnection(std::move(eventThread), false /* No Refresh */);
     }
 
     size_t layerHistorySize() const NO_THREAD_SAFETY_ANALYSIS {
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
index be49ef3..c2a7752 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchRealtimeTest.cpp
@@ -51,6 +51,7 @@
 
     void setPeriod(nsecs_t) final {}
     void resetModel() final {}
+    bool needsMoreSamples() const final { return false; }
     void dump(std::string&) const final {}
 
 private:
@@ -86,6 +87,7 @@
 
     void setPeriod(nsecs_t) final {}
     void resetModel() final {}
+    bool needsMoreSamples() const final { return false; }
     void dump(std::string&) const final {}
 
 private:
diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
index d940dc5..373f6a5 100644
--- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp
@@ -47,6 +47,7 @@
     MOCK_CONST_METHOD0(currentPeriod, nsecs_t());
     MOCK_METHOD1(setPeriod, void(nsecs_t));
     MOCK_METHOD0(resetModel, void());
+    MOCK_CONST_METHOD0(needsMoreSamples, bool());
     MOCK_CONST_METHOD1(dump, void(std::string&));
 
     nsecs_t nextVSyncTime(nsecs_t timePoint) const {
@@ -115,11 +116,15 @@
 
     operator VSyncDispatch::CallbackToken() const { return mToken; }
 
-    void counter(nsecs_t time, nsecs_t) { mCalls.push_back(time); }
+    void counter(nsecs_t time, nsecs_t wakeup_time) {
+        mCalls.push_back(time);
+        mWakeupTime.push_back(wakeup_time);
+    }
 
     VSyncDispatch& mDispatch;
     VSyncDispatch::CallbackToken mToken;
     std::vector<nsecs_t> mCalls;
+    std::vector<nsecs_t> mWakeupTime;
 };
 
 class PausingCallback {
@@ -747,6 +752,31 @@
     EXPECT_THAT(cb2.mCalls.size(), Eq(1));
 }
 
+TEST_F(VSyncDispatchTimerQueueTest, laggedTimerGroupsCallbacksWithinLag) {
+    CountingCallback cb1(mDispatch);
+    CountingCallback cb2(mDispatch);
+
+    Sequence seq;
+    EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
+            .InSequence(seq)
+            .WillOnce(Return(1000));
+    EXPECT_CALL(mMockClock, alarmIn(_, 600)).InSequence(seq);
+    EXPECT_CALL(mStubTracker, nextAnticipatedVSyncTimeFrom(1000))
+            .InSequence(seq)
+            .WillOnce(Return(1000));
+
+    EXPECT_EQ(mDispatch.schedule(cb1, 400, 1000), ScheduleResult::Scheduled);
+    EXPECT_EQ(mDispatch.schedule(cb2, 390, 1000), ScheduleResult::Scheduled);
+
+    mMockClock.setLag(100);
+    mMockClock.advanceBy(700);
+
+    ASSERT_THAT(cb1.mWakeupTime.size(), Eq(1));
+    EXPECT_THAT(cb1.mWakeupTime[0], Eq(600));
+    ASSERT_THAT(cb2.mWakeupTime.size(), Eq(1));
+    EXPECT_THAT(cb2.mWakeupTime[0], Eq(610));
+}
+
 class VSyncDispatchTimerQueueEntryTest : public testing::Test {
 protected:
     nsecs_t const mPeriod = 1000;
diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
index fc39235..d4cd11d 100644
--- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp
@@ -73,27 +73,27 @@
 
 TEST_F(VSyncPredictorTest, reportsSamplesNeededWhenHasNoDataPoints) {
     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
-        EXPECT_TRUE(tracker.needsMoreSamples(mNow += mPeriod));
-        tracker.addVsyncTimestamp(mNow);
+        EXPECT_TRUE(tracker.needsMoreSamples());
+        tracker.addVsyncTimestamp(mNow += mPeriod);
     }
-    EXPECT_FALSE(tracker.needsMoreSamples(mNow));
+    EXPECT_FALSE(tracker.needsMoreSamples());
 }
 
 TEST_F(VSyncPredictorTest, reportsSamplesNeededAfterExplicitRateChange) {
     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
         tracker.addVsyncTimestamp(mNow += mPeriod);
     }
-    EXPECT_FALSE(tracker.needsMoreSamples(mNow));
+    EXPECT_FALSE(tracker.needsMoreSamples());
 
     auto const changedPeriod = mPeriod * 2;
     tracker.setPeriod(changedPeriod);
-    EXPECT_TRUE(tracker.needsMoreSamples(mNow));
+    EXPECT_TRUE(tracker.needsMoreSamples());
 
     for (auto i = 0u; i < kMinimumSamplesForPrediction; i++) {
-        EXPECT_TRUE(tracker.needsMoreSamples(mNow += changedPeriod));
-        tracker.addVsyncTimestamp(mNow);
+        EXPECT_TRUE(tracker.needsMoreSamples());
+        tracker.addVsyncTimestamp(mNow += changedPeriod);
     }
-    EXPECT_FALSE(tracker.needsMoreSamples(mNow));
+    EXPECT_FALSE(tracker.needsMoreSamples());
 }
 
 TEST_F(VSyncPredictorTest, transitionsToModelledPointsAfterSynthetic) {
@@ -320,20 +320,6 @@
     EXPECT_THAT(intercept, Eq(0));
 }
 
-TEST_F(VSyncPredictorTest, willBecomeInaccurateAfterA_longTimeWithNoSamples) {
-    auto const simulatedVsyncs = generateVsyncTimestamps(kMinimumSamplesForPrediction, mPeriod, 0);
-
-    for (auto const& timestamp : simulatedVsyncs) {
-        tracker.addVsyncTimestamp(timestamp);
-    }
-    auto const mNow = *simulatedVsyncs.rbegin();
-    EXPECT_FALSE(tracker.needsMoreSamples(mNow));
-
-    // TODO: would be better to decay this as a result of the variance of the samples
-    static auto constexpr aLongTimeOut = 1000000000;
-    EXPECT_TRUE(tracker.needsMoreSamples(mNow + aLongTimeOut));
-}
-
 TEST_F(VSyncPredictorTest, idealModelPredictionsBeforeRegressionModelIsBuilt) {
     auto const simulatedVsyncs =
             generateVsyncTimestamps(kMinimumSamplesForPrediction + 1, mPeriod, 0);
@@ -443,7 +429,7 @@
         // When VsyncPredictor returns the period it means that it doesn't know how to predict and
         // it needs to get more samples
         if (slope == mPeriod && intercept == 0) {
-            EXPECT_TRUE(tracker.needsMoreSamples(now));
+            EXPECT_TRUE(tracker.needsMoreSamples());
         }
     }
 }
diff --git a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
index a972562..6856612 100644
--- a/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
+++ b/services/surfaceflinger/tests/unittests/VSyncReactorTest.cpp
@@ -41,6 +41,7 @@
     MOCK_CONST_METHOD0(currentPeriod, nsecs_t());
     MOCK_METHOD1(setPeriod, void(nsecs_t));
     MOCK_METHOD0(resetModel, void());
+    MOCK_CONST_METHOD0(needsMoreSamples, bool());
     MOCK_CONST_METHOD1(dump, void(std::string&));
 };
 
@@ -57,6 +58,7 @@
     nsecs_t currentPeriod() const final { return mTracker->currentPeriod(); }
     void setPeriod(nsecs_t period) final { mTracker->setPeriod(period); }
     void resetModel() final { mTracker->resetModel(); }
+    bool needsMoreSamples() const final { return mTracker->needsMoreSamples(); }
     void dump(std::string& result) const final { mTracker->dump(result); }
 
 private:
@@ -455,6 +457,83 @@
     EXPECT_FALSE(mReactor.addPresentFence(generateSignalledFenceWithTime(0)));
 }
 
+TEST_F(VSyncReactorTest, hwVsyncIsRequestedForTracker) {
+    auto time = 0;
+    bool periodFlushed = false;
+    nsecs_t const newPeriod = 4000;
+    mReactor.setPeriod(newPeriod);
+
+    static auto constexpr numSamplesWithNewPeriod = 4;
+    Sequence seq;
+    EXPECT_CALL(*mMockTracker, needsMoreSamples())
+            .Times(numSamplesWithNewPeriod - 2)
+            .InSequence(seq)
+            .WillRepeatedly(Return(true));
+    EXPECT_CALL(*mMockTracker, needsMoreSamples())
+            .Times(1)
+            .InSequence(seq)
+            .WillRepeatedly(Return(false));
+    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(numSamplesWithNewPeriod);
+
+    EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+
+    EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+    // confirmed period, but predictor wants numRequest samples. This one and prior are valid.
+    EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod, std::nullopt, &periodFlushed));
+    EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod, std::nullopt, &periodFlushed));
+    EXPECT_FALSE(mReactor.addResyncSample(time += newPeriod, std::nullopt, &periodFlushed));
+}
+
+TEST_F(VSyncReactorTest, hwVsyncturnsOffOnConfirmationWhenTrackerDoesntRequest) {
+    auto time = 0;
+    bool periodFlushed = false;
+    nsecs_t const newPeriod = 4000;
+    mReactor.setPeriod(newPeriod);
+
+    Sequence seq;
+    EXPECT_CALL(*mMockTracker, needsMoreSamples())
+            .Times(1)
+            .InSequence(seq)
+            .WillRepeatedly(Return(false));
+    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
+
+    EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+    EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+    EXPECT_FALSE(mReactor.addResyncSample(time += newPeriod, std::nullopt, &periodFlushed));
+}
+
+TEST_F(VSyncReactorTest, hwVsyncIsRequestedForTrackerMultiplePeriodChanges) {
+    auto time = 0;
+    bool periodFlushed = false;
+    nsecs_t const newPeriod1 = 4000;
+    nsecs_t const newPeriod2 = 7000;
+
+    mReactor.setPeriod(newPeriod1);
+
+    Sequence seq;
+    EXPECT_CALL(*mMockTracker, needsMoreSamples())
+            .Times(4)
+            .InSequence(seq)
+            .WillRepeatedly(Return(true));
+    EXPECT_CALL(*mMockTracker, needsMoreSamples())
+            .Times(1)
+            .InSequence(seq)
+            .WillRepeatedly(Return(false));
+    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(7);
+
+    EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+    EXPECT_TRUE(mReactor.addResyncSample(time += period, std::nullopt, &periodFlushed));
+    // confirmed period, but predictor wants numRequest samples. This one and prior are valid.
+    EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod1, std::nullopt, &periodFlushed));
+    EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod1, std::nullopt, &periodFlushed));
+
+    mReactor.setPeriod(newPeriod2);
+    EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod1, std::nullopt, &periodFlushed));
+    EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod2, std::nullopt, &periodFlushed));
+    EXPECT_TRUE(mReactor.addResyncSample(time += newPeriod2, std::nullopt, &periodFlushed));
+    EXPECT_FALSE(mReactor.addResyncSample(time += newPeriod2, std::nullopt, &periodFlushed));
+}
+
 static nsecs_t computeWorkload(nsecs_t period, nsecs_t phase) {
     return period - phase;
 }
@@ -648,7 +727,7 @@
 
 TEST_F(VSyncReactorTest, periodChangeWithGivenVsyncPeriod) {
     bool periodFlushed = true;
-    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(3);
+    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(2);
     mReactor.setIgnorePresentFences(true);
 
     nsecs_t const newPeriod = 5000;
@@ -672,7 +751,7 @@
                                     kPendingLimit, true /* supportKernelIdleTimer */);
 
     bool periodFlushed = true;
-    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(5);
+    EXPECT_CALL(*mMockTracker, addVsyncTimestamp(_)).Times(4);
     idleReactor.setIgnorePresentFences(true);
 
     // First, set the same period, which should only be confirmed when we receive two
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index c2c5072..7df3239 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -111,6 +111,7 @@
                  Error(Display, Layer, const std::vector<IComposerClient::Rect>&));
     MOCK_METHOD3(setLayerZOrder, Error(Display, Layer, uint32_t));
     MOCK_METHOD4(setLayerInfo, Error(Display, Layer, uint32_t, uint32_t));
+    MOCK_METHOD3(setLayerType, Error(Display, Layer, uint32_t));
     MOCK_METHOD3(getRenderIntents, Error(Display, ColorMode, std::vector<RenderIntent>*));
     MOCK_METHOD3(setLayerColorTransform, Error(Display, Layer, const float*));
     MOCK_METHOD4(getDisplayedContentSamplingAttributes,
@@ -141,6 +142,7 @@
     MOCK_METHOD1(getLayerGenericMetadataKeys,
                  V2_4::Error(std::vector<IComposerClient::LayerGenericMetadataKey>*));
     MOCK_METHOD2(getClientTargetProperty, Error(Display, IComposerClient::ClientTargetProperty*));
+    MOCK_METHOD2(setDisplayElapseTime, Error(Display, uint64_t));
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
index fe99e77..f01997b 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
@@ -96,6 +96,7 @@
     MOCK_METHOD1(getClientTargetProperty, hal::Error(hal::ClientTargetProperty*));
     MOCK_CONST_METHOD1(getConnectionType, hal::Error(android::DisplayConnectionType*));
     MOCK_CONST_METHOD0(isVsyncPeriodSwitchSupported, bool());
+    MOCK_METHOD1(setDisplayElapseTime, hal::Error(uint64_t));
 };
 
 } // namespace mock
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
index e22d0cf..d19b943 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockPowerAdvisor.h
@@ -32,6 +32,7 @@
     MOCK_METHOD0(onBootFinished, void());
     MOCK_METHOD2(setExpensiveRenderingExpected, void(DisplayId displayId, bool expected));
     MOCK_METHOD0(notifyDisplayUpdateImminent, void());
+    MOCK_METHOD0(canNotifyDisplayUpdateImminent, bool());
 };
 
 } // namespace mock
diff --git a/vulkan/libvulkan/Android.bp b/vulkan/libvulkan/Android.bp
index f69de1f..aa8040b 100644
--- a/vulkan/libvulkan/Android.bp
+++ b/vulkan/libvulkan/Android.bp
@@ -89,7 +89,6 @@
         "libhardware",
         "libsync",
         "libbase",
-        "libdl_android",
         "libhidlbase",
         "liblog",
         "libui",
@@ -100,6 +99,7 @@
         "libnativebridge_lazy",
         "libnativeloader_lazy",
         "libnativewindow",
+        "libvndksupport",
         "android.hardware.graphics.common@1.0",
         "libSurfaceFlingerProp",
     ],
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 7bcb2c1..f840561 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -28,20 +28,17 @@
 #include <android/dlext.h>
 #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
-#include <cutils/properties.h>
 #include <graphicsenv/GraphicsEnv.h>
 #include <log/log.h>
-#include <nativeloader/dlext_namespaces.h>
 #include <sys/prctl.h>
 #include <utils/Timers.h>
 #include <utils/Trace.h>
+#include <vndksupport/linker.h>
 
 #include <algorithm>
 #include <array>
 #include <climits>
 #include <new>
-#include <string_view>
-#include <sstream>
 #include <vector>
 
 #include "stubhal.h"
@@ -151,19 +148,11 @@
 
 Hal Hal::hal_;
 
-void* LoadLibrary(const android_dlextinfo& dlextinfo,
-                  const std::string_view subname) {
-    ATRACE_CALL();
-
-    std::stringstream ss;
-    ss << "vulkan." << subname << ".so";
-    return android_dlopen_ext(ss.str().c_str(), RTLD_LOCAL | RTLD_NOW, &dlextinfo);
-}
-
 const std::array<const char*, 2> HAL_SUBNAME_KEY_PROPERTIES = {{
     "ro.hardware." HWVULKAN_HARDWARE_MODULE_ID,
-    "ro.board.platform",
+    "ro.board.platform"
 }};
+constexpr int LIB_DL_FLAGS = RTLD_LOCAL | RTLD_NOW;
 
 // LoadDriver returns:
 // * 0 when succeed, or
@@ -174,23 +163,30 @@
                const hwvulkan_module_t** module) {
     ATRACE_CALL();
 
-    const android_dlextinfo dlextinfo = {
-        .flags = ANDROID_DLEXT_USE_NAMESPACE,
-        .library_namespace = library_namespace,
-    };
     void* so = nullptr;
-    char prop[PROPERTY_VALUE_MAX];
     for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
-        int prop_len = property_get(key, prop, nullptr);
-        if (prop_len > 0 && prop_len <= UINT_MAX) {
-            std::string_view lib_name(prop, static_cast<unsigned int>(prop_len));
-            so = LoadLibrary(dlextinfo, lib_name);
-            if (so)
-                break;
+        std::string lib_name = android::base::GetProperty(key, "");
+        if (lib_name.empty())
+            continue;
+
+        lib_name = "vulkan." + lib_name + ".so";
+        if (library_namespace) {
+            // load updated driver
+            const android_dlextinfo dlextinfo = {
+                .flags = ANDROID_DLEXT_USE_NAMESPACE,
+                .library_namespace = library_namespace,
+            };
+            so = android_dlopen_ext(lib_name.c_str(), LIB_DL_FLAGS, &dlextinfo);
+        } else {
+            // load built-in driver
+            so = android_load_sphal_library(lib_name.c_str(), LIB_DL_FLAGS);
         }
+        if (so)
+            break;
     }
-    if (!so)
+    if (!so) {
         return -ENOENT;
+    }
 
     auto hmi = static_cast<hw_module_t*>(dlsym(so, HAL_MODULE_INFO_SYM_AS_STR));
     if (!hmi) {
@@ -211,12 +207,9 @@
 int LoadBuiltinDriver(const hwvulkan_module_t** module) {
     ATRACE_CALL();
 
-    auto ns = android_get_exported_namespace("sphal");
-    if (!ns)
-        return -ENOENT;
     android::GraphicsEnv::getInstance().setDriverToLoad(
         android::GpuStatsInfo::Driver::VULKAN);
-    return LoadDriver(ns, module);
+    return LoadDriver(nullptr, module);
 }
 
 int LoadUpdatedDriver(const hwvulkan_module_t** module) {
@@ -238,7 +231,6 @@
 
 bool Hal::Open() {
     ATRACE_CALL();
-
     const nsecs_t openTime = systemTime();
 
     ALOG_ASSERT(!hal_.dev_, "OpenHAL called more than once");
@@ -256,16 +248,16 @@
     if (result != 0) {
         android::GraphicsEnv::getInstance().setDriverLoaded(
             android::GpuStatsInfo::Api::API_VK, false, systemTime() - openTime);
-        ALOGV("unable to load Vulkan HAL, using stub HAL (result=%d)", result);
         return true;
     }
 
-
     hwvulkan_device_t* device;
     ATRACE_BEGIN("hwvulkan module open");
     result =
         module->common.methods->open(&module->common, HWVULKAN_DEVICE_0,
                                      reinterpret_cast<hw_device_t**>(&device));
+
+
     ATRACE_END();
     if (result != 0) {
         android::GraphicsEnv::getInstance().setDriverLoaded(