SurfaceFlinger: correctly pass desired present time for BLAST

Pass whether a desired present time is automatically
populated or not to match BufferStateLayer behavior to the one
we have for BufferQueueLayer.

Bug: 169901895
Test: expand notification shade and observe systrace
Change-Id: Ia02c5633d46dde67d2c3be33b084d63c40c2afb0
diff --git a/libs/gui/BLASTBufferQueue.cpp b/libs/gui/BLASTBufferQueue.cpp
index 8328322..9fc5495 100644
--- a/libs/gui/BLASTBufferQueue.cpp
+++ b/libs/gui/BLASTBufferQueue.cpp
@@ -311,7 +311,9 @@
     t->setCrop(mSurfaceControl, computeCrop(bufferItem));
     t->setTransform(mSurfaceControl, bufferItem.mTransform);
     t->setTransformToDisplayInverse(mSurfaceControl, bufferItem.mTransformToDisplayInverse);
-    t->setDesiredPresentTime(bufferItem.mTimestamp);
+    if (!bufferItem.mIsAutoTimestamp) {
+        t->setDesiredPresentTime(bufferItem.mTimestamp);
+    }
     t->setFrameNumber(mSurfaceControl, bufferItem.mFrameNumber);
 
     if (!mNextFrameTimelineVsyncIdQueue.empty()) {
diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp
index 405658b..a8d6832 100644
--- a/libs/gui/ISurfaceComposer.cpp
+++ b/libs/gui/ISurfaceComposer.cpp
@@ -71,7 +71,7 @@
     virtual status_t setTransactionState(
             int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
             const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
-            const InputWindowCommands& commands, int64_t desiredPresentTime,
+            const InputWindowCommands& commands, int64_t desiredPresentTime, bool isAutoTimestamp,
             const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
             const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
         Parcel data, reply;
@@ -92,6 +92,7 @@
         SAFE_PARCEL(data.writeStrongBinder, applyToken);
         SAFE_PARCEL(commands.write, data);
         SAFE_PARCEL(data.writeInt64, desiredPresentTime);
+        SAFE_PARCEL(data.writeBool, isAutoTimestamp);
         SAFE_PARCEL(data.writeStrongBinder, uncacheBuffer.token.promote());
         SAFE_PARCEL(data.writeUint64, uncacheBuffer.id);
         SAFE_PARCEL(data.writeBool, hasListenerCallbacks);
@@ -1297,7 +1298,9 @@
             SAFE_PARCEL(inputWindowCommands.read, data);
 
             int64_t desiredPresentTime = 0;
+            bool isAutoTimestamp = true;
             SAFE_PARCEL(data.readInt64, &desiredPresentTime);
+            SAFE_PARCEL(data.readBool, &isAutoTimestamp);
 
             client_cache_t uncachedBuffer;
             sp<IBinder> tmpBinder;
@@ -1323,8 +1326,8 @@
 
             return setTransactionState(frameTimelineVsyncId, state, displays, stateFlags,
                                        applyToken, inputWindowCommands, desiredPresentTime,
-                                       uncachedBuffer, hasListenerCallbacks, listenerCallbacks,
-                                       transactionId);
+                                       isAutoTimestamp, uncachedBuffer, hasListenerCallbacks,
+                                       listenerCallbacks, transactionId);
         }
         case BOOT_FINISHED: {
             CHECK_INTERFACE(ISurfaceComposer, data, reply);
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 0d370d3..5570d99 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -395,6 +395,7 @@
         mExplicitEarlyWakeupEnd(other.mExplicitEarlyWakeupEnd),
         mContainsBuffer(other.mContainsBuffer),
         mDesiredPresentTime(other.mDesiredPresentTime),
+        mIsAutoTimestamp(other.mIsAutoTimestamp),
         mFrameTimelineVsyncId(other.mFrameTimelineVsyncId) {
     mDisplayStates = other.mDisplayStates;
     mComposerStates = other.mComposerStates;
@@ -424,6 +425,7 @@
     const bool explicitEarlyWakeupEnd = parcel->readBool();
     const bool containsBuffer = parcel->readBool();
     const int64_t desiredPresentTime = parcel->readInt64();
+    const bool isAutoTimestamp = parcel->readBool();
     const int64_t frameTimelineVsyncId = parcel->readInt64();
 
     size_t count = static_cast<size_t>(parcel->readUint32());
@@ -497,6 +499,7 @@
     mExplicitEarlyWakeupEnd = explicitEarlyWakeupEnd;
     mContainsBuffer = containsBuffer;
     mDesiredPresentTime = desiredPresentTime;
+    mIsAutoTimestamp = isAutoTimestamp;
     mFrameTimelineVsyncId = frameTimelineVsyncId;
     mDisplayStates = displayStates;
     mListenerCallbacks = listenerCallbacks;
@@ -527,6 +530,7 @@
     parcel->writeBool(mExplicitEarlyWakeupEnd);
     parcel->writeBool(mContainsBuffer);
     parcel->writeInt64(mDesiredPresentTime);
+    parcel->writeBool(mIsAutoTimestamp);
     parcel->writeInt64(mFrameTimelineVsyncId);
     parcel->writeUint32(static_cast<uint32_t>(mDisplayStates.size()));
     for (auto const& displayState : mDisplayStates) {
@@ -628,7 +632,8 @@
     mEarlyWakeup = false;
     mExplicitEarlyWakeupStart = false;
     mExplicitEarlyWakeupEnd = false;
-    mDesiredPresentTime = -1;
+    mDesiredPresentTime = 0;
+    mIsAutoTimestamp = true;
     mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
 }
 
@@ -640,8 +645,9 @@
     uncacheBuffer.id = cacheId;
 
     sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
-    sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {}, -1,
-                            uncacheBuffer, false, {}, 0 /* Undefined transactionId */);
+    sf->setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, {}, {}, 0, applyToken, {},
+                            systemTime(), true, uncacheBuffer, false, {},
+                            0 /* Undefined transactionId */);
 }
 
 void SurfaceComposerClient::Transaction::cacheBuffers() {
@@ -759,7 +765,7 @@
 
     sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
     sf->setTransactionState(mFrameTimelineVsyncId, composerStates, displayStates, flags, applyToken,
-                            mInputWindowCommands, mDesiredPresentTime,
+                            mInputWindowCommands, mDesiredPresentTime, mIsAutoTimestamp,
                             {} /*uncacheBuffer - only set in doUncacheBufferTransaction*/,
                             hasListenerCallbacks, listenerCallbacks, mId);
     mId = generateId();
@@ -1201,6 +1207,9 @@
     }
     s->what |= layer_state_t::eBufferChanged;
     s->buffer = buffer;
+    if (mIsAutoTimestamp) {
+        mDesiredPresentTime = systemTime();
+    }
 
     registerSurfaceControlForCallback(sc);
 
@@ -1295,6 +1304,7 @@
 SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setDesiredPresentTime(
         nsecs_t desiredPresentTime) {
     mDesiredPresentTime = desiredPresentTime;
+    mIsAutoTimestamp = false;
     return *this;
 }
 
diff --git a/libs/gui/include/gui/ISurfaceComposer.h b/libs/gui/include/gui/ISurfaceComposer.h
index 7d25d61..40316db 100644
--- a/libs/gui/include/gui/ISurfaceComposer.h
+++ b/libs/gui/include/gui/ISurfaceComposer.h
@@ -166,7 +166,7 @@
             int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
             const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
             const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
-            const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+            bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
             const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) = 0;
 
     /* signal that we're done booting.
diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h
index 3ee4a39..0abe72c 100644
--- a/libs/gui/include/gui/SurfaceComposerClient.h
+++ b/libs/gui/include/gui/SurfaceComposerClient.h
@@ -373,13 +373,17 @@
         // to be presented. When it is not possible to present at exactly that time, it will be
         // presented after the time has passed.
         //
+        // If the client didn't pass a desired presentation time, mDesiredPresentTime will be
+        // populated to the time setBuffer was called, and mIsAutoTimestamp will be set to true.
+        //
         // Desired present times that are more than 1 second in the future may be ignored.
         // When a desired present time has already passed, the transaction will be presented as soon
         // as possible.
         //
         // Transactions from the same process are presented in the same order that they are applied.
         // The desired present time does not affect this ordering.
-        int64_t mDesiredPresentTime = -1;
+        int64_t mDesiredPresentTime = 0;
+        bool mIsAutoTimestamp = true;
 
         // The vsync Id provided by Choreographer.getVsyncId
         int64_t mFrameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp
index 7761db8..fa98cd4c 100644
--- a/libs/gui/tests/Surface_test.cpp
+++ b/libs/gui/tests/Surface_test.cpp
@@ -700,7 +700,7 @@
                                  const Vector<DisplayState>& /*displays*/, uint32_t /*flags*/,
                                  const sp<IBinder>& /*applyToken*/,
                                  const InputWindowCommands& /*inputWindowCommands*/,
-                                 int64_t /*desiredPresentTime*/,
+                                 int64_t /*desiredPresentTime*/, bool /*isAutoTimestamp*/,
                                  const client_cache_t& /*cachedBuffer*/,
                                  bool /*hasListenerCallbacks*/,
                                  const std::vector<ListenerCallbacks>& /*listenerCallbacks*/,
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index 0b9caba..df1472d 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -341,7 +341,7 @@
 }
 
 bool BufferStateLayer::setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence,
-                                 nsecs_t postTime, nsecs_t desiredPresentTime,
+                                 nsecs_t postTime, nsecs_t desiredPresentTime, bool isAutoTimestamp,
                                  const client_cache_t& clientCacheId, uint64_t frameNumber) {
     ATRACE_CALL();
 
@@ -365,13 +365,13 @@
     const int32_t layerId = getSequence();
     mFlinger->mTimeStats->setPostTime(layerId, mCurrentState.frameNumber, getName().c_str(),
                                       mOwnerUid, postTime);
-    desiredPresentTime = desiredPresentTime <= 0 ? 0 : desiredPresentTime;
     mCurrentState.desiredPresentTime = desiredPresentTime;
+    mCurrentState.isAutoTimestamp = isAutoTimestamp;
 
-    mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime,
+    mFlinger->mScheduler->recordLayerHistory(this, isAutoTimestamp ? 0 : desiredPresentTime,
                                              LayerHistory::LayerUpdateType::Buffer);
 
-    addFrameEvent(acquireFence, postTime, desiredPresentTime);
+    addFrameEvent(acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime);
     return true;
 }
 
@@ -533,7 +533,7 @@
         return true;
     }
 
-    return mCurrentState.desiredPresentTime <= expectedPresentTime;
+    return mCurrentState.isAutoTimestamp || mCurrentState.desiredPresentTime <= expectedPresentTime;
 }
 
 bool BufferStateLayer::onPreComposition(nsecs_t refreshStartTime) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index ad00c65..734f647 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -70,8 +70,8 @@
     bool setCrop(const Rect& crop) override;
     bool setFrame(const Rect& frame) override;
     bool setBuffer(const sp<GraphicBuffer>& buffer, const sp<Fence>& acquireFence, nsecs_t postTime,
-                   nsecs_t desiredPresentTime, const client_cache_t& clientCacheId,
-                   uint64_t frameNumber) override;
+                   nsecs_t desiredPresentTime, bool isAutoTimestamp,
+                   const client_cache_t& clientCacheId, uint64_t frameNumber) override;
     bool setAcquireFence(const sp<Fence>& fence) override;
     bool setDataspace(ui::Dataspace dataspace) override;
     bool setHdrMetadata(const HdrMetadata& hdrMetadata) override;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c9e97da..d6023b6 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -275,7 +275,8 @@
         // recent callback handle.
         std::deque<sp<CallbackHandle>> callbackHandles;
         bool colorSpaceAgnostic;
-        nsecs_t desiredPresentTime = -1;
+        nsecs_t desiredPresentTime = 0;
+        bool isAutoTimestamp = true;
 
         // Length of the cast shadow. If the radius is > 0, a shadow of length shadowRadius will
         // be rendered around the layer.
@@ -444,7 +445,8 @@
     virtual bool setFrame(const Rect& /*frame*/) { return false; };
     virtual bool setBuffer(const sp<GraphicBuffer>& /*buffer*/, const sp<Fence>& /*acquireFence*/,
                            nsecs_t /*postTime*/, nsecs_t /*desiredPresentTime*/,
-                           const client_cache_t& /*clientCacheId*/, uint64_t /* frameNumber */) {
+                           bool /*isAutoTimestamp*/, const client_cache_t& /*clientCacheId*/,
+                           uint64_t /* frameNumber */) {
         return false;
     };
     virtual bool setAcquireFence(const sp<Fence>& /*fence*/) { return false; };
diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp
index a959b9a..c291b7f 100644
--- a/services/surfaceflinger/RefreshRateOverlay.cpp
+++ b/services/surfaceflinger/RefreshRateOverlay.cpp
@@ -235,7 +235,7 @@
 void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) {
     mCurrentFps = refreshRate.getFps().getIntValue();
     auto buffer = getOrCreateBuffers(*mCurrentFps)[mFrame];
-    mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {},
+    mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
                       mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */));
 
     mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
@@ -247,7 +247,7 @@
     const auto& buffers = getOrCreateBuffers(*mCurrentFps);
     mFrame = (mFrame + 1) % buffers.size();
     auto buffer = buffers[mFrame];
-    mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, {},
+    mLayer->setBuffer(buffer, Fence::NO_FENCE, 0, 0, true, {},
                       mLayer->getHeadFrameNumber(-1 /* expectedPresentTime */));
 
     mFlinger.mTransactionFlags.fetch_or(eTransactionMask);
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 14536b3..68d2a68 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3262,8 +3262,9 @@
                 applyTransactionState(transaction.frameTimelineVsyncId, transaction.states,
                                       transaction.displays, transaction.flags,
                                       mPendingInputWindowCommands, transaction.desiredPresentTime,
-                                      transaction.buffer, transaction.postTime,
-                                      transaction.privileged, transaction.hasListenerCallbacks,
+                                      transaction.isAutoTimestamp, transaction.buffer,
+                                      transaction.postTime, transaction.privileged,
+                                      transaction.hasListenerCallbacks,
                                       transaction.listenerCallbacks, transaction.originPid,
                                       transaction.originUid, transaction.id, /*isMainThread*/ true);
                 transactionQueue.pop();
@@ -3294,7 +3295,7 @@
     bool ready = true;
     // Do not present if the desiredPresentTime has not passed unless it is more than one second
     // in the future. We ignore timestamps more than 1 second in the future for stability reasons.
-    if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime &&
+    if (desiredPresentTime > 0 && desiredPresentTime >= expectedPresentTime &&
         desiredPresentTime < expectedPresentTime + s2ns(1)) {
         ready = false;
     }
@@ -3331,7 +3332,7 @@
         int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
         const Vector<DisplayState>& displays, uint32_t flags, const sp<IBinder>& applyToken,
         const InputWindowCommands& inputWindowCommands, int64_t desiredPresentTime,
-        const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
+        bool isAutoTimestamp, const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
         const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
     ATRACE_CALL();
 
@@ -3372,17 +3373,19 @@
     const int originPid = ipc->getCallingPid();
     const int originUid = ipc->getCallingUid();
 
-    if (pendingTransactions || !transactionIsReadyToBeApplied(desiredPresentTime, states, true)) {
+    if (pendingTransactions ||
+        !transactionIsReadyToBeApplied(isAutoTimestamp ? 0 : desiredPresentTime, states, true)) {
         mTransactionQueues[applyToken].emplace(frameTimelineVsyncId, states, displays, flags,
-                                               desiredPresentTime, uncacheBuffer, postTime,
-                                               privileged, hasListenerCallbacks, listenerCallbacks,
-                                               originPid, originUid, transactionId);
+                                               desiredPresentTime, isAutoTimestamp, uncacheBuffer,
+                                               postTime, privileged, hasListenerCallbacks,
+                                               listenerCallbacks, originPid, originUid,
+                                               transactionId);
         setTransactionFlags(eTransactionFlushNeeded);
         return NO_ERROR;
     }
 
     applyTransactionState(frameTimelineVsyncId, states, displays, flags, inputWindowCommands,
-                          desiredPresentTime, uncacheBuffer, postTime, privileged,
+                          desiredPresentTime, isAutoTimestamp, uncacheBuffer, postTime, privileged,
                           hasListenerCallbacks, listenerCallbacks, originPid, originUid,
                           transactionId, /*isMainThread*/ false);
     return NO_ERROR;
@@ -3392,9 +3395,10 @@
         int64_t frameTimelineVsyncId, const Vector<ComposerState>& states,
         const Vector<DisplayState>& displays, uint32_t flags,
         const InputWindowCommands& inputWindowCommands, const int64_t desiredPresentTime,
-        const client_cache_t& uncacheBuffer, const int64_t postTime, bool privileged,
-        bool hasListenerCallbacks, const std::vector<ListenerCallbacks>& listenerCallbacks,
-        int originPid, int originUid, uint64_t transactionId, bool isMainThread) {
+        bool isAutoTimestamp, const client_cache_t& uncacheBuffer, const int64_t postTime,
+        bool privileged, bool hasListenerCallbacks,
+        const std::vector<ListenerCallbacks>& listenerCallbacks, int originPid, int originUid,
+        uint64_t transactionId, bool isMainThread) {
     uint32_t transactionFlags = 0;
 
     if (flags & eAnimation) {
@@ -3428,12 +3432,13 @@
     std::unordered_set<ListenerCallbacks, ListenerCallbacksHash> listenerCallbacksWithSurfaces;
     uint32_t clientStateFlags = 0;
     for (const ComposerState& state : states) {
-        clientStateFlags |=
-                setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime, postTime,
-                                     privileged, listenerCallbacksWithSurfaces);
+        clientStateFlags |= setClientStateLocked(frameTimelineVsyncId, state, desiredPresentTime,
+                                                 isAutoTimestamp, postTime, privileged,
+                                                 listenerCallbacksWithSurfaces);
         if ((flags & eAnimation) && state.state.surface) {
             if (const auto layer = fromHandleLocked(state.state.surface).promote(); layer) {
-                mScheduler->recordLayerHistory(layer.get(), desiredPresentTime,
+                mScheduler->recordLayerHistory(layer.get(),
+                                               isAutoTimestamp ? 0 : desiredPresentTime,
                                                LayerHistory::LayerUpdateType::AnimationTX);
             }
         }
@@ -3608,7 +3613,7 @@
 
 uint32_t SurfaceFlinger::setClientStateLocked(
         int64_t frameTimelineVsyncId, const ComposerState& composerState,
-        int64_t desiredPresentTime, int64_t postTime, bool privileged,
+        int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
         std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks) {
     const layer_state_t& s = composerState.state;
 
@@ -3919,8 +3924,8 @@
                 ? s.frameNumber
                 : layer->getHeadFrameNumber(-1 /* expectedPresentTime */) + 1;
 
-        if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, s.cachedBuffer,
-                             frameNumber)) {
+        if (layer->setBuffer(buffer, s.acquireFence, postTime, desiredPresentTime, isAutoTimestamp,
+                             s.cachedBuffer, frameNumber)) {
             flags |= eTraversalNeeded;
         }
     }
@@ -4198,7 +4203,7 @@
     d.height = 0;
     displays.add(d);
     setTransactionState(ISurfaceComposer::INVALID_VSYNC_ID, state, displays, 0, nullptr,
-                        mPendingInputWindowCommands, -1, {}, false, {},
+                        mPendingInputWindowCommands, systemTime(), true, {}, false, {},
                         0 /* Undefined transactionId */);
 
     setPowerModeInternal(display, hal::PowerMode::ON);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index e3e9c4f..db75312 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -341,7 +341,7 @@
 
     virtual uint32_t setClientStateLocked(
             int64_t frameTimelineVsyncId, const ComposerState& composerState,
-            int64_t desiredPresentTime, int64_t postTime, bool privileged,
+            int64_t desiredPresentTime, bool isAutoTimestamp, int64_t postTime, bool privileged,
             std::unordered_set<ListenerCallbacks, ListenerCallbacksHash>& listenerCallbacks)
             REQUIRES(mStateLock);
     virtual void commitTransactionLocked();
@@ -434,8 +434,9 @@
     struct TransactionState {
         TransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& composerStates,
                          const Vector<DisplayState>& displayStates, uint32_t transactionFlags,
-                         int64_t desiredPresentTime, const client_cache_t& uncacheBuffer,
-                         int64_t postTime, bool privileged, bool hasListenerCallbacks,
+                         int64_t desiredPresentTime, bool isAutoTimestamp,
+                         const client_cache_t& uncacheBuffer, int64_t postTime, bool privileged,
+                         bool hasListenerCallbacks,
                          std::vector<ListenerCallbacks> listenerCallbacks, int originPid,
                          int originUid, uint64_t transactionId)
               : frameTimelineVsyncId(frameTimelineVsyncId),
@@ -443,6 +444,7 @@
                 displays(displayStates),
                 flags(transactionFlags),
                 desiredPresentTime(desiredPresentTime),
+                isAutoTimestamp(isAutoTimestamp),
                 buffer(uncacheBuffer),
                 postTime(postTime),
                 privileged(privileged),
@@ -457,6 +459,7 @@
         Vector<DisplayState> displays;
         uint32_t flags;
         const int64_t desiredPresentTime;
+        const bool isAutoTimestamp;
         client_cache_t buffer;
         const int64_t postTime;
         bool privileged;
@@ -520,8 +523,8 @@
                                  const Vector<DisplayState>& displays, uint32_t flags,
                                  const sp<IBinder>& applyToken,
                                  const InputWindowCommands& inputWindowCommands,
-                                 int64_t desiredPresentTime, const client_cache_t& uncacheBuffer,
-                                 bool hasListenerCallbacks,
+                                 int64_t desiredPresentTime, bool isAutoTimestamp,
+                                 const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
                                  const std::vector<ListenerCallbacks>& listenerCallbacks,
                                  uint64_t transactionId) override;
     void bootFinished() override;
@@ -723,7 +726,7 @@
     void applyTransactionState(int64_t frameTimelineVsyncId, const Vector<ComposerState>& state,
                                const Vector<DisplayState>& displays, uint32_t flags,
                                const InputWindowCommands& inputWindowCommands,
-                               const int64_t desiredPresentTime,
+                               const int64_t desiredPresentTime, bool isAutoTimestamp,
                                const client_cache_t& uncacheBuffer, const int64_t postTime,
                                bool privileged, bool hasListenerCallbacks,
                                const std::vector<ListenerCallbacks>& listenerCallbacks,
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index c98004a..25aaa14 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -371,14 +371,14 @@
                              const Vector<DisplayState>& displays, uint32_t flags,
                              const sp<IBinder>& applyToken,
                              const InputWindowCommands& inputWindowCommands,
-                             int64_t desiredPresentTime, const client_cache_t& uncacheBuffer,
-                             bool hasListenerCallbacks,
+                             int64_t desiredPresentTime, bool isAutoTimestamp,
+                             const client_cache_t& uncacheBuffer, bool hasListenerCallbacks,
                              std::vector<ListenerCallbacks>& listenerCallbacks,
                              uint64_t transactionId) {
         return mFlinger->setTransactionState(frameTimelineVsyncId, states, displays, flags,
                                              applyToken, inputWindowCommands, desiredPresentTime,
-                                             uncacheBuffer, hasListenerCallbacks, listenerCallbacks,
-                                             transactionId);
+                                             isAutoTimestamp, uncacheBuffer, hasListenerCallbacks,
+                                             listenerCallbacks, transactionId);
     }
 
     auto flushTransactionQueues() { return mFlinger->flushTransactionQueues(); };
diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
index c36d994..fa6ff30 100644
--- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp
@@ -97,7 +97,8 @@
         uint32_t flags = 0;
         sp<IBinder> applyToken = IInterface::asBinder(TransactionCompletedListener::getIInstance());
         InputWindowCommands inputWindowCommands;
-        int64_t desiredPresentTime = -1;
+        int64_t desiredPresentTime = 0;
+        bool isAutoTimestamp = true;
         int64_t frameTimelineVsyncId = ISurfaceComposer::INVALID_VSYNC_ID;
         client_cache_t uncacheBuffer;
         int64_t id = -1;
@@ -114,11 +115,13 @@
     }
 
     void setupSingle(TransactionInfo& transaction, uint32_t flags, bool syncInputWindows,
-                     int64_t desiredPresentTime, int64_t frameTimelineVsyncId) {
+                     int64_t desiredPresentTime, bool isAutoTimestamp,
+                     int64_t frameTimelineVsyncId) {
         mTransactionNumber++;
         transaction.flags |= flags; // ISurfaceComposer::eSynchronous;
         transaction.inputWindowCommands.syncInputWindows = syncInputWindows;
         transaction.desiredPresentTime = desiredPresentTime;
+        transaction.isAutoTimestamp = isAutoTimestamp;
         transaction.frameTimelineVsyncId = frameTimelineVsyncId;
     }
 
@@ -129,13 +132,15 @@
         EXPECT_CALL(*mVSyncTracker, nextAnticipatedVSyncTimeFrom(_)).WillOnce(Return(systemTime()));
         TransactionInfo transaction;
         setupSingle(transaction, flags, syncInputWindows,
-                    /*desiredPresentTime*/ -1, ISurfaceComposer::INVALID_VSYNC_ID);
+                    /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
+                    ISurfaceComposer::INVALID_VSYNC_ID);
         nsecs_t applicationTime = systemTime();
         mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states,
                                      transaction.displays, transaction.flags,
                                      transaction.applyToken, transaction.inputWindowCommands,
-                                     transaction.desiredPresentTime, transaction.uncacheBuffer,
-                                     mHasListenerCallbacks, mCallbacks, transaction.id);
+                                     transaction.desiredPresentTime, transaction.isAutoTimestamp,
+                                     transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
+                                     transaction.id);
 
         // This transaction should not have been placed on the transaction queue.
         // If transaction is synchronous or syncs input windows, SF
@@ -164,13 +169,15 @@
                 .WillOnce(Return(time + nsecs_t(5 * 1e8)));
         TransactionInfo transaction;
         setupSingle(transaction, flags, syncInputWindows,
-                    /*desiredPresentTime*/ time + s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID);
+                    /*desiredPresentTime*/ time + s2ns(1), false,
+                    ISurfaceComposer::INVALID_VSYNC_ID);
         nsecs_t applicationSentTime = systemTime();
         mFlinger.setTransactionState(transaction.frameTimelineVsyncId, transaction.states,
                                      transaction.displays, transaction.flags,
                                      transaction.applyToken, transaction.inputWindowCommands,
-                                     transaction.desiredPresentTime, transaction.uncacheBuffer,
-                                     mHasListenerCallbacks, mCallbacks, transaction.id);
+                                     transaction.desiredPresentTime, transaction.isAutoTimestamp,
+                                     transaction.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
+                                     transaction.id);
 
         nsecs_t returnedTime = systemTime();
         EXPECT_LE(returnedTime, applicationSentTime + s2ns(5));
@@ -189,20 +196,23 @@
         // transaction that should go on the pending thread
         TransactionInfo transactionA;
         setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
-                    /*desiredPresentTime*/ time + s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID);
+                    /*desiredPresentTime*/ time + s2ns(1), false,
+                    ISurfaceComposer::INVALID_VSYNC_ID);
 
         // transaction that would not have gone on the pending thread if not
         // blocked
         TransactionInfo transactionB;
         setupSingle(transactionB, flags, syncInputWindows,
-                    /*desiredPresentTime*/ -1, ISurfaceComposer::INVALID_VSYNC_ID);
+                    /*desiredPresentTime*/ systemTime(), /*isAutoTimestamp*/ true,
+                    ISurfaceComposer::INVALID_VSYNC_ID);
 
         nsecs_t applicationSentTime = systemTime();
         mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states,
                                      transactionA.displays, transactionA.flags,
                                      transactionA.applyToken, transactionA.inputWindowCommands,
-                                     transactionA.desiredPresentTime, transactionA.uncacheBuffer,
-                                     mHasListenerCallbacks, mCallbacks, transactionA.id);
+                                     transactionA.desiredPresentTime, transactionA.isAutoTimestamp,
+                                     transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
+                                     transactionA.id);
 
         // This thread should not have been blocked by the above transaction
         // (5s is the timeout period that applyTransactionState waits for SF to
@@ -213,8 +223,9 @@
         mFlinger.setTransactionState(transactionB.frameTimelineVsyncId, transactionB.states,
                                      transactionB.displays, transactionB.flags,
                                      transactionB.applyToken, transactionB.inputWindowCommands,
-                                     transactionB.desiredPresentTime, transactionB.uncacheBuffer,
-                                     mHasListenerCallbacks, mCallbacks, transactionB.id);
+                                     transactionB.desiredPresentTime, transactionB.isAutoTimestamp,
+                                     transactionB.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
+                                     transactionB.id);
 
         // this thread should have been blocked by the above transaction
         // if this is an animation, this thread should be blocked for 5s
@@ -256,12 +267,12 @@
             .WillOnce(Return(s2ns(2)));
     TransactionInfo transactionA; // transaction to go on pending queue
     setupSingle(transactionA, /*flags*/ 0, /*syncInputWindows*/ false,
-                /*desiredPresentTime*/ s2ns(1), ISurfaceComposer::INVALID_VSYNC_ID);
+                /*desiredPresentTime*/ s2ns(1), false, ISurfaceComposer::INVALID_VSYNC_ID);
     mFlinger.setTransactionState(transactionA.frameTimelineVsyncId, transactionA.states,
                                  transactionA.displays, transactionA.flags, transactionA.applyToken,
                                  transactionA.inputWindowCommands, transactionA.desiredPresentTime,
-                                 transactionA.uncacheBuffer, mHasListenerCallbacks, mCallbacks,
-                                 transactionA.id);
+                                 transactionA.isAutoTimestamp, transactionA.uncacheBuffer,
+                                 mHasListenerCallbacks, mCallbacks, transactionA.id);
 
     auto& transactionQueue = mFlinger.getTransactionQueue();
     ASSERT_EQ(1, transactionQueue.size());
@@ -279,8 +290,8 @@
     empty.applyToken = sp<IBinder>();
     mFlinger.setTransactionState(empty.frameTimelineVsyncId, empty.states, empty.displays,
                                  empty.flags, empty.applyToken, empty.inputWindowCommands,
-                                 empty.desiredPresentTime, empty.uncacheBuffer,
-                                 mHasListenerCallbacks, mCallbacks, empty.id);
+                                 empty.desiredPresentTime, empty.isAutoTimestamp,
+                                 empty.uncacheBuffer, mHasListenerCallbacks, mCallbacks, empty.id);
 
     // flush transaction queue should flush as desiredPresentTime has
     // passed