Merge "SF: Requery display modes if the active mode is not supported" into sc-dev
diff --git a/include/input/InputTransport.h b/include/input/InputTransport.h
index 11b714f..3b46cb5 100644
--- a/include/input/InputTransport.h
+++ b/include/input/InputTransport.h
@@ -181,21 +181,6 @@
     bool isValid(size_t actualSize) const;
     size_t size() const;
     void getSanitizedCopy(InputMessage* msg) const;
-
-    static const char* typeToString(Type type) {
-        switch (type) {
-            case Type::KEY:
-                return "KEY";
-            case Type::MOTION:
-                return "MOTION";
-            case Type::FINISHED:
-                return "FINISHED";
-            case Type::FOCUS:
-                return "FOCUS";
-            case Type::CAPTURE:
-                return "CAPTURE";
-        }
-    }
 };
 
 /*
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 4253610..6f79f4b 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -83,13 +83,13 @@
                 "InputWindow.cpp",
                 "android/FocusRequest.aidl",
                 "android/InputApplicationInfo.aidl",
+                "android/os/BlockUntrustedTouchesMode.aidl",
                 "android/os/IInputConstants.aidl",
+                "android/os/IInputFlinger.aidl",
                 "android/os/InputEventInjectionResult.aidl",
                 "android/os/InputEventInjectionSync.aidl",
-                "android/os/TouchOcclusionMode.aidl",
-                "android/os/BlockUntrustedTouchesMode.aidl",
-                "android/os/IInputFlinger.aidl",
                 "android/os/ISetInputWindowsListener.aidl",
+                "android/os/TouchOcclusionMode.aidl",
             ],
 
             export_shared_lib_headers: ["libbinder"],
diff --git a/libs/input/InputTransport.cpp b/libs/input/InputTransport.cpp
index 6218fdc..1e47a3c 100644
--- a/libs/input/InputTransport.cpp
+++ b/libs/input/InputTransport.cpp
@@ -34,6 +34,7 @@
 #include <utils/Trace.h>
 
 #include <input/InputTransport.h>
+#include <input/NamedEnum.h>
 
 using android::base::StringPrintf;
 
@@ -610,8 +611,8 @@
         return result;
     }
     if (msg.header.type != InputMessage::Type::FINISHED) {
-        ALOGE("channel '%s' publisher ~ Received unexpected message of type %d from consumer",
-                mChannel->getName().c_str(), msg.header.type);
+        ALOGE("channel '%s' publisher ~ Received unexpected %s message from consumer",
+              mChannel->getName().c_str(), NamedEnum::string(msg.header.type).c_str());
         return UNKNOWN_ERROR;
     }
     callback(msg.header.seq, msg.body.finished.handled == 1, msg.body.finished.consumeTime);
@@ -753,8 +754,9 @@
             }
 
             case InputMessage::Type::FINISHED: {
-                LOG_ALWAYS_FATAL("Consumed a FINISHED message, which should never be seen by "
-                                 "InputConsumer!");
+                LOG_ALWAYS_FATAL("Consumed a %s message, which should never be seen by "
+                                 "InputConsumer!",
+                                 NamedEnum::string(mMsg.header.type).c_str());
                 break;
             }
 
@@ -1299,14 +1301,14 @@
     out = out + "mChannel = " + mChannel->getName() + "\n";
     out = out + "mMsgDeferred: " + toString(mMsgDeferred) + "\n";
     if (mMsgDeferred) {
-        out = out + "mMsg : " + InputMessage::typeToString(mMsg.header.type) + "\n";
+        out = out + "mMsg : " + NamedEnum::string(mMsg.header.type) + "\n";
     }
     out += "Batches:\n";
     for (const Batch& batch : mBatches) {
         out += "    Batch:\n";
         for (const InputMessage& msg : batch.samples) {
             out += android::base::StringPrintf("        Message %" PRIu32 ": %s ", msg.header.seq,
-                                               InputMessage::typeToString(msg.header.type));
+                                               NamedEnum::string(msg.header.type).c_str());
             switch (msg.header.type) {
                 case InputMessage::Type::KEY: {
                     out += android::base::StringPrintf("action=%s keycode=%" PRId32,
diff --git a/services/inputflinger/host/InputFlinger.h b/services/inputflinger/host/InputFlinger.h
index 47773d9..8112038 100644
--- a/services/inputflinger/host/InputFlinger.h
+++ b/services/inputflinger/host/InputFlinger.h
@@ -43,19 +43,19 @@
 
     InputFlinger() ANDROID_API;
 
-    virtual status_t dump(int fd, const Vector<String16>& args);
+    status_t dump(int fd, const Vector<String16>& args) override;
     binder::Status setInputWindows(const std::vector<InputWindowInfo>&,
-                                   const sp<ISetInputWindowsListener>&) {
+                                   const sp<ISetInputWindowsListener>&) override {
         return binder::Status::ok();
     }
-    binder::Status createInputChannel(const std::string&, InputChannel*) {
+    binder::Status createInputChannel(const std::string&, InputChannel*) override {
         return binder::Status::ok();
     }
-    binder::Status removeInputChannel(const sp<IBinder>&) { return binder::Status::ok(); }
-    binder::Status setFocusedWindow(const FocusRequest&) { return binder::Status::ok(); }
+    binder::Status removeInputChannel(const sp<IBinder>&) override { return binder::Status::ok(); }
+    binder::Status setFocusedWindow(const FocusRequest&) override { return binder::Status::ok(); }
 
 private:
-    virtual ~InputFlinger();
+    ~InputFlinger() override;
 
     void dumpInternal(String8& result);
 
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index f30e1eb..296085a 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -370,9 +370,7 @@
 
     addFrameEvent(acquireFence, postTime, isAutoTimestamp ? 0 : desiredPresentTime);
 
-    if (info.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) {
-        setFrameTimelineVsyncForBufferTransaction(info, postTime);
-    }
+    setFrameTimelineVsyncForBufferTransaction(info, postTime);
 
     if (dequeueTime && *dequeueTime != 0) {
         const uint64_t bufferId = buffer->getId();
@@ -871,18 +869,13 @@
     return layerSize.width() != bufferWidth || layerSize.height() != bufferHeight;
 }
 
-void BufferStateLayer::incrementPendingBufferCount() {
-    mPendingBufferTransactions++;
-    tracePendingBufferCount();
-}
-
 void BufferStateLayer::decrementPendingBufferCount() {
-    mPendingBufferTransactions--;
-    tracePendingBufferCount();
+    int32_t pendingBuffers = --mPendingBufferTransactions;
+    tracePendingBufferCount(pendingBuffers);
 }
 
-void BufferStateLayer::tracePendingBufferCount() {
-    ATRACE_INT(mBlastTransactionName.c_str(), mPendingBufferTransactions);
+void BufferStateLayer::tracePendingBufferCount(int32_t pendingBuffers) {
+    ATRACE_INT(mBlastTransactionName.c_str(), pendingBuffers);
 }
 
 uint32_t BufferStateLayer::doTransaction(uint32_t flags) {
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 175a40b..6b422ea 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -113,9 +113,10 @@
     uint32_t getEffectiveScalingMode() const override;
 
     // See mPendingBufferTransactions
-    void incrementPendingBufferCount() override;
     void decrementPendingBufferCount();
     uint32_t doTransaction(uint32_t flags) override;
+    std::atomic<int32_t>* getPendingBufferCounter() override { return &mPendingBufferTransactions; }
+    std::string getPendingBufferCounterName() override { return mBlastTransactionName; }
 
 protected:
     void gatherBufferInfo() override;
@@ -127,7 +128,7 @@
     friend class TransactionFrameTracerTest;
     friend class TransactionSurfaceFrameTest;
 
-    inline void tracePendingBufferCount();
+    inline void tracePendingBufferCount(int32_t pendingBuffers);
 
     bool updateFrameEventHistory(const sp<Fence>& acquireFence, nsecs_t postedTime,
                                  nsecs_t requestedPresentTime);
@@ -184,7 +185,7 @@
     //     - If the integer increases, a buffer arrived at the server.
     //     - If the integer decreases in latchBuffer, that buffer was latched
     //     - If the integer decreases in setBuffer or doTransaction, a buffer was dropped
-    uint64_t mPendingBufferTransactions{0};
+    std::atomic<int32_t> mPendingBufferTransactions{0};
 
     // TODO(marissaw): support sticky transform for LEGACY camera mode
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a072554..ce97155 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -503,8 +503,6 @@
     virtual void useEmptyDamage() {}
     Region getVisibleRegion(const DisplayDevice*) const;
 
-    virtual void incrementPendingBufferCount() {}
-
     /*
      * isOpaque - true if this surface is opaque
      *
@@ -948,6 +946,9 @@
     bool setStretchEffect(const StretchEffect& effect);
     StretchEffect getStretchEffect() const;
 
+    virtual std::atomic<int32_t>* getPendingBufferCounter() { return nullptr; }
+    virtual std::string getPendingBufferCounterName() { return ""; }
+
 protected:
     class SyncPoint {
     public:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index b39231e..ad91183 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3318,7 +3318,6 @@
                     if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
                                                        transaction.desiredPresentTime,
                                                        transaction.states,
-                                                       false /* updateTransactionCounters*/,
                                                        pendingBuffers)) {
                         setTransactionFlags(eTransactionFlushNeeded);
                         break;
@@ -3343,13 +3342,9 @@
                 const auto& transaction = mTransactionQueue.front();
                 bool pendingTransactions = mPendingTransactionQueues.find(transaction.applyToken) !=
                         mPendingTransactionQueues.end();
-                // Call transactionIsReadyToBeApplied first in case we need to
-                // incrementPendingBufferCount and keep track of pending buffers
-                // if the transaction contains a buffer.
                 if (!transactionIsReadyToBeApplied(transaction.isAutoTimestamp,
                                                    transaction.desiredPresentTime,
                                                    transaction.states,
-                                                   true /* updateTransactionCounters */,
                                                    pendingBuffers) ||
                     pendingTransactions) {
                     mPendingTransactionQueues[transaction.applyToken].push(transaction);
@@ -3381,7 +3376,6 @@
 
 bool SurfaceFlinger::transactionIsReadyToBeApplied(
         bool isAutoTimestamp, int64_t desiredPresentTime, const Vector<ComposerState>& states,
-        bool updateTransactionCounters,
         std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& pendingBuffers) {
     const nsecs_t expectedPresentTime = mExpectedPresentTime.load();
     bool ready = true;
@@ -3420,10 +3414,6 @@
             ATRACE_NAME("!isVsyncValidForUid");
             ready = false;
         }
-        if (updateTransactionCounters) {
-            // See BufferStateLayer::mPendingBufferTransactions
-            layer->incrementPendingBufferCount();
-        }
 
         // If backpressure is enabled and we already have a buffer to commit, keep the transaction
         // in the queue.
@@ -3514,6 +3504,13 @@
         const std::vector<ListenerCallbacks>& listenerCallbacks, uint64_t transactionId) {
     ATRACE_CALL();
 
+    // Check for incoming buffer updates and increment the pending buffer count.
+    for (const auto& state : states) {
+        if ((state.state.what & layer_state_t::eAcquireFenceChanged) && (state.state.surface)) {
+            mBufferCountTracker.increment(state.state.surface->localBinder());
+        }
+    }
+
     uint32_t permissions =
             callingThreadHasUnscopedSurfaceFlingerAccess() ? Permission::ACCESS_SURFACE_FLINGER : 0;
     // Avoid checking for rotation permissions if the caller already has ACCESS_SURFACE_FLINGER
@@ -4091,10 +4088,16 @@
                                             std::move(metadata), format, handle, gbp, &layer);
 
             break;
-        case ISurfaceComposerClient::eFXSurfaceBufferState:
+        case ISurfaceComposerClient::eFXSurfaceBufferState: {
             result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags,
                                             std::move(metadata), handle, &layer);
-            break;
+            std::atomic<int32_t>* pendingBufferCounter = layer->getPendingBufferCounter();
+            if (pendingBufferCounter) {
+                std::string counterName = layer->getPendingBufferCounterName();
+                mBufferCountTracker.add((*handle)->localBinder(), counterName,
+                                        pendingBufferCounter);
+            }
+        } break;
         case ISurfaceComposerClient::eFXSurfaceEffect:
             // check if buffer size is set for color layer.
             if (w > 0 || h > 0) {
@@ -4261,6 +4264,7 @@
     auto it = mLayersByLocalBinderToken.begin();
     while (it != mLayersByLocalBinderToken.end()) {
         if (it->second == layer) {
+            mBufferCountTracker.remove(it->first->localBinder());
             it = mLayersByLocalBinderToken.erase(it);
         } else {
             it++;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 23f0842..6434ca2 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -416,6 +416,43 @@
         void traverseInReverseZOrder(const LayerVector::Visitor& visitor) const;
     };
 
+    // Keeps track of pending buffers per layer handle in the transaction queue or current/drawing
+    // state before the buffers are latched. The layer owns the atomic counters and decrements the
+    // count in the main thread when dropping or latching a buffer.
+    //
+    // The binder threads increment the same counter when a new transaction containing a buffer is
+    // added to the transaction queue. The map is updated with the layer handle lifecycle updates.
+    // This is done to avoid lock contention with the main thread.
+    class BufferCountTracker {
+    public:
+        void increment(BBinder* layerHandle) {
+            std::lock_guard<std::mutex> lock(mLock);
+            auto it = mCounterByLayerHandle.find(layerHandle);
+            if (it != mCounterByLayerHandle.end()) {
+                auto [name, pendingBuffers] = it->second;
+                int32_t count = ++(*pendingBuffers);
+                ATRACE_INT(name.c_str(), count);
+            } else {
+                ALOGW("Handle not found! %p", layerHandle);
+            }
+        }
+
+        void add(BBinder* layerHandle, const std::string& name, std::atomic<int32_t>* counter) {
+            std::lock_guard<std::mutex> lock(mLock);
+            mCounterByLayerHandle[layerHandle] = std::make_pair(name, counter);
+        }
+
+        void remove(BBinder* layerHandle) {
+            std::lock_guard<std::mutex> lock(mLock);
+            mCounterByLayerHandle.erase(layerHandle);
+        }
+
+    private:
+        std::mutex mLock;
+        std::unordered_map<BBinder*, std::pair<std::string, std::atomic<int32_t>*>>
+                mCounterByLayerHandle GUARDED_BY(mLock);
+    };
+
     struct ActiveModeInfo {
         DisplayModeId modeId;
         Scheduler::ModeEvent event = Scheduler::ModeEvent::None;
@@ -764,7 +801,6 @@
     void commitOffscreenLayers();
     bool transactionIsReadyToBeApplied(
             bool isAutoTimestamp, int64_t desiredPresentTime, const Vector<ComposerState>& states,
-            bool updateTransactionCounters,
             std::unordered_set<sp<IBinder>, ISurfaceComposer::SpHash<IBinder>>& pendingBuffers)
             REQUIRES(mStateLock);
     uint32_t setDisplayStateLocked(const DisplayState& s) REQUIRES(mStateLock);
@@ -1315,6 +1351,8 @@
     int mFrameRateFlexibilityTokenCount = 0;
 
     sp<IBinder> mDebugFrameRateFlexibilityToken;
+
+    BufferCountTracker mBufferCountTracker;
 };
 
 } // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
index bf9ec39..363bd80 100644
--- a/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
+++ b/services/surfaceflinger/tests/unittests/TransactionSurfaceFrameTest.cpp
@@ -368,6 +368,62 @@
 
         EXPECT_EQ(0u, layer->mPendingJankClassifications.size());
     }
+
+    void BufferSurfaceFrame_ReplaceValidTokenBufferWithInvalidTokenBuffer() {
+        sp<BufferStateLayer> layer = createBufferStateLayer();
+
+        sp<Fence> fence1(new Fence());
+        auto acquireFence1 = fenceFactory.createFenceTimeForTest(fence1);
+        sp<GraphicBuffer> buffer1{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+        layer->setBuffer(buffer1, fence1, 10, 20, false, mClientCache, 1, std::nullopt,
+                         {/*vsyncId*/ 1, /*inputEventId*/ 0});
+        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+        const auto droppedSurfaceFrame1 = layer->mCurrentState.bufferSurfaceFrameTX;
+
+        sp<Fence> fence2(new Fence());
+        auto acquireFence2 = fenceFactory.createFenceTimeForTest(fence2);
+        sp<GraphicBuffer> buffer2{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+        auto dropStartTime1 = systemTime();
+        layer->setBuffer(buffer2, fence2, 10, 20, false, mClientCache, 1, std::nullopt,
+                         {/*vsyncId*/ FrameTimelineInfo::INVALID_VSYNC_ID, /*inputEventId*/ 0});
+        auto dropEndTime1 = systemTime();
+        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+        const auto droppedSurfaceFrame2 = layer->mCurrentState.bufferSurfaceFrameTX;
+
+        sp<Fence> fence3(new Fence());
+        auto acquireFence3 = fenceFactory.createFenceTimeForTest(fence3);
+        sp<GraphicBuffer> buffer3{new GraphicBuffer(1, 1, HAL_PIXEL_FORMAT_RGBA_8888, 1, 0)};
+        auto dropStartTime2 = systemTime();
+        layer->setBuffer(buffer3, fence3, 10, 20, false, mClientCache, 1, std::nullopt,
+                         {/*vsyncId*/ 2, /*inputEventId*/ 0});
+        auto dropEndTime2 = systemTime();
+        acquireFence3->signalForTest(12);
+
+        EXPECT_EQ(0u, layer->mCurrentState.bufferlessSurfaceFramesTX.size());
+        ASSERT_NE(nullptr, layer->mCurrentState.bufferSurfaceFrameTX);
+        const auto& presentedSurfaceFrame = layer->mCurrentState.bufferSurfaceFrameTX;
+
+        commitTransaction(layer.get());
+        bool computeVisisbleRegions;
+        layer->updateTexImage(computeVisisbleRegions, 15, 0);
+
+        EXPECT_EQ(1, droppedSurfaceFrame1->getToken());
+        EXPECT_EQ(PresentState::Dropped, droppedSurfaceFrame1->getPresentState());
+        EXPECT_EQ(0u, droppedSurfaceFrame1->getActuals().endTime);
+        auto dropTime1 = droppedSurfaceFrame1->getDropTime();
+        EXPECT_TRUE(dropTime1 > dropStartTime1 && dropTime1 < dropEndTime1);
+
+        EXPECT_EQ(FrameTimelineInfo::INVALID_VSYNC_ID, droppedSurfaceFrame2->getToken());
+        EXPECT_EQ(PresentState::Dropped, droppedSurfaceFrame2->getPresentState());
+        EXPECT_EQ(0u, droppedSurfaceFrame2->getActuals().endTime);
+        auto dropTime2 = droppedSurfaceFrame2->getDropTime();
+        EXPECT_TRUE(dropTime2 > dropStartTime2 && dropTime2 < dropEndTime2);
+
+        EXPECT_EQ(2, presentedSurfaceFrame->getToken());
+        EXPECT_EQ(PresentState::Presented, presentedSurfaceFrame->getPresentState());
+    }
 };
 
 TEST_F(TransactionSurfaceFrameTest, PresentedBufferlessSurfaceFrame) {
@@ -407,4 +463,10 @@
 TEST_F(TransactionSurfaceFrameTest, PendingSurfaceFramesRemovedAfterClassification) {
     PendingSurfaceFramesRemovedAfterClassification();
 }
+
+TEST_F(TransactionSurfaceFrameTest,
+       BufferSurfaceFrame_ReplaceValidTokenBufferWithInvalidTokenBuffer) {
+    BufferSurfaceFrame_ReplaceValidTokenBufferWithInvalidTokenBuffer();
+}
+
 } // namespace android
\ No newline at end of file
diff --git a/vulkan/vkjson/vkjson.cc b/vulkan/vkjson/vkjson.cc
index bfc240e..a513239 100644
--- a/vulkan/vkjson/vkjson.cc
+++ b/vulkan/vkjson/vkjson.cc
@@ -1196,10 +1196,10 @@
                                           std::string* errors) {
   *t = T();
   Json::Value object(Json::objectValue);
-  Json::Reader reader;
-  reader.parse(json, object, false);
-  if (!object) {
-    if (errors) errors->assign(reader.getFormatedErrorMessages());
+  Json::CharReaderBuilder builder;
+  builder["collectComments"] = false;
+  std::unique_ptr<Json::CharReader> reader(builder.newCharReader());
+  if (!reader->parse(json.data(), json.data() + json.size(), &object, errors)) {
     return false;
   }
   return AsValue(&object, t);