Merge changes I1348da2c,I103d2a56,I4ed64966

* changes:
  SurfaceFlinger: set change phase offsets for 90Hz
  SurfaceFlinger: get expectedPresentTime from Scheduler
  SF: set active config state machine
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index 3915757..0313c32 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -232,7 +232,7 @@
                     getTransformToDisplayInverse(), mFreezeGeometryUpdates);
 
     const nsecs_t expectedPresentTime = mFlinger->mUseScheduler
-            ? mFlinger->mScheduler->mPrimaryDispSync->expectedPresentTime()
+            ? mFlinger->mScheduler->expectedPresentTime()
             : mFlinger->mPrimaryDispSync->expectedPresentTime();
 
     // updateTexImage() below might drop the some buffers at the head of the queue if there is a
diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
index a0a4455..ab1f460 100644
--- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
+++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp
@@ -59,10 +59,10 @@
     const int highFpsEarlyGlAppOffsetNs = atoi(value);
 
     // TODO(b/122905996): Define these in device.mk.
-    property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "1000000");
+    property_get("debug.sf.high_fps_late_app_phase_offset_ns", value, "2000000");
     const int highFpsLateAppOffsetNs = atoi(value);
 
-    property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "8000000");
+    property_get("debug.sf.high_fps_late_sf_phase_offset_ns", value, "1000000");
     const int highFpsLateSfOffsetNs = atoi(value);
 
     mDefaultRefreshRateOffsets.early = {earlySfOffsetNs != -1 ? earlySfOffsetNs
@@ -83,7 +83,7 @@
                                                                       : highFpsLateAppOffsetNs,
                                        highFpsEarlyGlAppOffsetNs != -1 ? highFpsEarlyGlAppOffsetNs
                                                                        : highFpsLateSfOffsetNs};
-    mHighRefreshRateOffsets.late = {highFpsLateAppOffsetNs, highFpsLateSfOffsetNs};
+    mHighRefreshRateOffsets.late = {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs};
 }
 
 PhaseOffsets::Offsets PhaseOffsets::getCurrentOffsets() const {
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 2f581d2..5268c8c 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -69,7 +69,7 @@
     mEventControlThread = std::make_unique<impl::EventControlThread>(function);
 
     char value[PROPERTY_VALUE_MAX];
-    property_get("debug.sf.set_idle_timer_ms", value, "30");
+    property_get("debug.sf.set_idle_timer_ms", value, "0");
     mSetIdleTimerMs = atoi(value);
 
     if (mSetIdleTimerMs > 0) {
@@ -238,6 +238,10 @@
     mHWVsyncAvailable = makeAvailable;
 }
 
+nsecs_t Scheduler::expectedPresentTime() {
+    return mPrimaryDispSync->expectedPresentTime();
+}
+
 void Scheduler::addFramePresentTimeForLayer(const nsecs_t framePresentTime, bool isAutoTimestamp,
                                             const std::string layerName) {
     // This is V1 logic. It calculates the average FPS based on the timestamp frequency
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 4abf027..089d579 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -109,6 +109,7 @@
     void addPresentFence(const std::shared_ptr<FenceTime>& fenceTime);
     void setIgnorePresentFences(bool ignore);
     void makeHWSyncAvailable(bool makeAvailable);
+    nsecs_t expectedPresentTime();
     // Adds the present time for given layer to the history of present times.
     void addFramePresentTimeForLayer(const nsecs_t framePresentTime, bool isAutoTimestamp,
                                      const std::string layerName);
@@ -142,9 +143,6 @@
     // Function that is called when the timer expires.
     void expiredTimerCallback();
 
-    // TODO(b/113612090): Instead of letting BufferQueueLayer to access mDispSync directly, it
-    // should make request to Scheduler to compute next refresh.
-    friend class BufferQueueLayer;
 
     // If fences from sync Framework are supported.
     const bool mHasSyncFramework;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5f8de83..6e21739 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -351,10 +351,6 @@
     }
     ALOGV("Primary Display Orientation is set to %2d.", SurfaceFlinger::primaryDisplayOrientation);
 
-    mPrimaryDispSync =
-            getFactory().createDispSync("PrimaryDispSync", SurfaceFlinger::hasSyncFramework,
-                                        SurfaceFlinger::dispSyncPresentTimeOffset);
-
     auto surfaceFlingerConfigsServiceV1_2 = V1_2::ISurfaceFlingerConfigs::getService();
     if (surfaceFlingerConfigsServiceV1_2) {
         surfaceFlingerConfigsServiceV1_2->getDisplayNativePrimaries(
@@ -400,6 +396,12 @@
     property_get("debug.sf.use_scheduler", value, "0");
     mUseScheduler = atoi(value);
 
+    if (!mUseScheduler) {
+        mPrimaryDispSync =
+                getFactory().createDispSync("PrimaryDispSync", SurfaceFlinger::hasSyncFramework,
+                                            SurfaceFlinger::dispSyncPresentTimeOffset);
+    }
+
     const auto [early, gl, late] = mPhaseOffsets->getCurrentOffsets();
     mVsyncModulator.setPhaseOffsets(early, gl, late);
 
@@ -719,8 +721,10 @@
         }
     }
 
-    mEventControlThread = getFactory().createEventControlThread(
-            [this](bool enabled) { setPrimaryVsyncEnabled(enabled); });
+    if (!mUseScheduler) {
+        mEventControlThread = getFactory().createEventControlThread(
+                [this](bool enabled) { setPrimaryVsyncEnabled(enabled); });
+    }
 
     // initialize our drawing state
     mDrawingState = mCurrentState;
@@ -822,14 +826,12 @@
     return NO_ERROR;
 }
 
-status_t SurfaceFlinger::getDisplayConfigs(const sp<IBinder>& displayToken,
-                                           Vector<DisplayInfo>* configs) {
+status_t SurfaceFlinger::getDisplayConfigsLocked(const sp<IBinder>& displayToken,
+                                                 Vector<DisplayInfo>* configs) {
     if (!displayToken || !configs) {
         return BAD_VALUE;
     }
 
-    ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId);
-
     const auto displayId = getPhysicalDisplayIdLocked(displayToken);
     if (!displayId) {
         return NAME_NOT_FOUND;
@@ -957,22 +959,19 @@
     return display->getActiveConfig();
 }
 
-status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
-    ATRACE_NAME("setActiveConfigSync");
-    postMessageSync(new LambdaMessage(
-            [&]() NO_THREAD_SAFETY_ANALYSIS { setActiveConfigInternal(displayToken, mode); }));
-    return NO_ERROR;
-}
+void SurfaceFlinger::setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode) {
+    ATRACE_CALL();
 
-void SurfaceFlinger::setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) {
     Vector<DisplayInfo> configs;
-    getDisplayConfigs(displayToken, &configs);
+    // Lock is acquired by setRefreshRateTo.
+    getDisplayConfigsLocked(displayToken, &configs);
     if (mode < 0 || mode >= static_cast<int>(configs.size())) {
         ALOGE("Attempt to set active config %d for display with %zu configs", mode, configs.size());
         return;
     }
 
-    const auto display = getDisplayDevice(displayToken);
+    // Lock is acquired by setRefreshRateTo.
+    const auto display = getDisplayDeviceLocked(displayToken);
     if (!display) {
         ALOGE("Attempt to set active config %d for invalid display token %p", mode,
               displayToken.get());
@@ -988,23 +987,95 @@
         return;
     }
 
-    int currentMode = display->getActiveConfig();
-    if (mode == currentMode) {
-        // Don't update config if we are already running in the desired mode.
+    // Don't check against the current mode yet. Worst case we set the desired
+    // config twice.
+    {
+        std::lock_guard<std::mutex> lock(mActiveConfigLock);
+        mDesiredActiveConfig = ActiveConfigInfo{mode, displayToken};
+    }
+    // This will trigger HWC refresh without resetting the idle timer.
+    repaintEverythingForHWC();
+}
+
+status_t SurfaceFlinger::setActiveConfig(const sp<IBinder>& displayToken, int mode) {
+    ATRACE_CALL();
+    postMessageSync(new LambdaMessage(
+            [&]() NO_THREAD_SAFETY_ANALYSIS { setDesiredActiveConfig(displayToken, mode); }));
+    return NO_ERROR;
+}
+
+void SurfaceFlinger::setActiveConfigInHWC() {
+    ATRACE_CALL();
+
+    const auto display = getDisplayDevice(mUpcomingActiveConfig.displayToken);
+    if (!display) {
         return;
     }
-    if (mUseScheduler) {
-        mRefreshRateStats->setConfigMode(mode);
-    }
-
     const auto displayId = display->getId();
     LOG_ALWAYS_FATAL_IF(!displayId);
 
-    display->setActiveConfig(mode);
-    getHwComposer().setActiveConfig(*displayId, mode);
+    ATRACE_INT("ActiveConfigModeHWC", mUpcomingActiveConfig.configId);
+    getHwComposer().setActiveConfig(*displayId, mUpcomingActiveConfig.configId);
+    mSetActiveConfigState = SetActiveConfigState::NOTIFIED_HWC;
+    ATRACE_INT("SetActiveConfigState", mSetActiveConfigState);
+}
 
-    ATRACE_INT("ActiveConfigMode", mode);
+void SurfaceFlinger::setActiveConfigInternal() {
+    ATRACE_CALL();
+
+    std::lock_guard<std::mutex> lock(mActiveConfigLock);
+    if (mUseScheduler) {
+        mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId);
+    }
+
+    const auto display = getDisplayDeviceLocked(mUpcomingActiveConfig.displayToken);
+    display->setActiveConfig(mUpcomingActiveConfig.configId);
+
+    mSetActiveConfigState = SetActiveConfigState::NONE;
+    ATRACE_INT("SetActiveConfigState", mSetActiveConfigState);
+
     resyncToHardwareVsync(true, getVsyncPeriod());
+    ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId);
+}
+
+bool SurfaceFlinger::updateSetActiveConfigStateMachine() NO_THREAD_SAFETY_ANALYSIS {
+    // Store the local variable to release the lock.
+    ActiveConfigInfo desiredActiveConfig;
+    {
+        std::lock_guard<std::mutex> lock(mActiveConfigLock);
+        desiredActiveConfig = mDesiredActiveConfig;
+    }
+
+    const auto display = getDisplayDevice(desiredActiveConfig.displayToken);
+    if (display) {
+        if (mSetActiveConfigState == SetActiveConfigState::NONE &&
+            display->getActiveConfig() != desiredActiveConfig.configId) {
+            // Step 1) Desired active config was set, it is different than the
+            // config currently in use. Notify HWC.
+            mUpcomingActiveConfig = desiredActiveConfig;
+            setActiveConfigInHWC();
+        } else if (mSetActiveConfigState == SetActiveConfigState::NOTIFIED_HWC) {
+            // Step 2) HWC was notified and we received refresh from it.
+            mSetActiveConfigState = SetActiveConfigState::REFRESH_RECEIVED;
+            ATRACE_INT("SetActiveConfigState", mSetActiveConfigState);
+            repaintEverythingForHWC();
+            // We do not want to give another frame to HWC while we are transitioning.
+            return false;
+        } else if (mSetActiveConfigState == SetActiveConfigState::REFRESH_RECEIVED &&
+                   !(mPreviousPresentFence != Fence::NO_FENCE &&
+                     (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled))) {
+            // Step 3) We received the present fence from the HWC, so we assume it
+            // successfully updated the config, hence we update SF.
+            setActiveConfigInternal();
+            // If the config changed again while we were transitioning, restart the
+            // process.
+            if (desiredActiveConfig != mUpcomingActiveConfig) {
+                mUpcomingActiveConfig = desiredActiveConfig;
+                setActiveConfigInHWC(); // sets the state to NOTIFY_HWC
+            }
+        }
+    }
+    return true;
 }
 
 status_t SurfaceFlinger::getDisplayColorModes(const sp<IBinder>& displayToken,
@@ -1332,6 +1403,7 @@
 }
 
 void SurfaceFlinger::enableHardwareVsync() {
+    assert(!mUseScheduler);
     Mutex::Autolock _l(mHWVsyncLock);
     if (!mPrimaryHWVsyncEnabled && mHWVsyncAvailable) {
         mPrimaryDispSync->beginResync();
@@ -1374,6 +1446,7 @@
 }
 
 void SurfaceFlinger::disableHardwareVsync(bool makeUnavailable) {
+    assert(!mUseScheduler);
     Mutex::Autolock _l(mHWVsyncLock);
     if (mPrimaryHWVsyncEnabled) {
         mEventControlThread->setVsyncEnabled(false);
@@ -1482,8 +1555,7 @@
         // TODO(b/113612090): There should be a better way at determining which config
         // has the right refresh rate.
         if (std::abs(fps - newFps) <= 1) {
-            setActiveConfigInternal(getInternalDisplayTokenLocked(), i);
-            ATRACE_INT("FPS", newFps);
+            setDesiredActiveConfig(getInternalDisplayTokenLocked(), i);
         }
     }
 }
@@ -1627,14 +1699,16 @@
     ATRACE_CALL();
     switch (what) {
         case MessageQueue::INVALIDATE: {
+            if (!updateSetActiveConfigStateMachine()) {
+                break;
+            }
+
             if (mUseScheduler) {
                 // This call is made each time SF wakes up and creates a new frame.
                 mScheduler->incrementFrameCounter();
             }
-            bool frameMissed = !mHadClientComposition &&
-                    mPreviousPresentFence != Fence::NO_FENCE &&
-                    (mPreviousPresentFence->getSignalTime() ==
-                            Fence::SIGNAL_TIME_PENDING);
+            bool frameMissed = !mHadClientComposition && mPreviousPresentFence != Fence::NO_FENCE &&
+                    (mPreviousPresentFence->getStatus() == Fence::Status::Unsignaled);
             mFrameMissedCount += frameMissed;
             ATRACE_INT("FrameMissed", static_cast<int>(frameMissed));
             if (frameMissed) {
@@ -3041,7 +3115,12 @@
 
 void SurfaceFlinger::latchAndReleaseBuffer(const sp<Layer>& layer) {
     if (layer->hasReadyFrame()) {
-        const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+        nsecs_t expectedPresentTime;
+        if (mUseScheduler) {
+            expectedPresentTime = mScheduler->expectedPresentTime();
+        } else {
+            expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+        }
         if (layer->shouldPresentNow(expectedPresentTime)) {
             bool ignored = false;
             layer->latchBuffer(ignored, systemTime(), Fence::NO_FENCE);
@@ -3273,7 +3352,12 @@
     mDrawingState.traverseInZOrder([&](Layer* layer) {
         if (layer->hasReadyFrame()) {
             frameQueued = true;
-            const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+            nsecs_t expectedPresentTime;
+            if (mUseScheduler) {
+                expectedPresentTime = mScheduler->expectedPresentTime();
+            } else {
+                expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+            }
             if (layer->shouldPresentNow(expectedPresentTime)) {
                 mLayersWithQueuedFrames.push_back(layer);
             } else {
@@ -3614,7 +3698,12 @@
 
 bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime,
                                                    const Vector<ComposerState>& states) {
-    const nsecs_t expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+    nsecs_t expectedPresentTime;
+    if (mUseScheduler) {
+        expectedPresentTime = mScheduler->expectedPresentTime();
+    } else {
+        expectedPresentTime = mPrimaryDispSync->expectedPresentTime();
+    }
     // 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 &&
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 6546973..a748bc5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -437,7 +437,12 @@
                            const Rect& sourceCrop, float frameScale, bool childrenOnly) override;
     status_t getDisplayStats(const sp<IBinder>& displayToken, DisplayStatInfo* stats) override;
     status_t getDisplayConfigs(const sp<IBinder>& displayToken,
-                               Vector<DisplayInfo>* configs) override;
+                               Vector<DisplayInfo>* configs) override {
+        Mutex::Autolock _l(mStateLock);
+        return getDisplayConfigsLocked(displayToken, configs);
+    }
+    status_t getDisplayConfigsLocked(const sp<IBinder>& displayToken, Vector<DisplayInfo>* configs)
+            REQUIRES(mStateLock);
     int getActiveConfig(const sp<IBinder>& displayToken) override;
     status_t getDisplayColorModes(const sp<IBinder>& displayToken,
                                   Vector<ui::ColorMode>* configs) override;
@@ -503,8 +508,18 @@
 
     // called on the main thread in response to initializeDisplays()
     void onInitializeDisplays() REQUIRES(mStateLock);
-    // called on the main thread in response to setActiveConfig()
-    void setActiveConfigInternal(const sp<IBinder>& displayToken, int mode) REQUIRES(mStateLock);
+    // Sets the desired active config bit. It obtains the lock, and sets mDesiredActiveConfig.
+    void setDesiredActiveConfig(const sp<IBinder>& displayToken, int mode) REQUIRES(mStateLock);
+    // Calls setActiveConfig in HWC.
+    void setActiveConfigInHWC();
+    // Once HWC has returned the present fence, this sets the active config and a new refresh
+    // rate in SF. It also triggers HWC vsync.
+    void setActiveConfigInternal() REQUIRES(mStateLock);
+    // Active config is updated on INVALIDATE call in a state machine-like manner. When the
+    // desired config was set, HWC needs to update the pannel on the next refresh, and when
+    // we receive the fence back, we know that the process was complete. It returns whether
+    // the invalidate process should continue.
+    bool updateSetActiveConfigStateMachine();
     // called on the main thread in response to setPowerMode()
     void setPowerModeInternal(const sp<DisplayDevice>& display, int mode) REQUIRES(mStateLock);
 
@@ -1084,6 +1099,34 @@
     sp<Scheduler::ConnectionHandle> mSfConnectionHandle;
     std::unique_ptr<scheduler::RefreshRateStats> mRefreshRateStats;
 
+    // The following structs are used for configuring active config state at a desired time,
+    // which is once per vsync at invalidate time.
+    enum SetActiveConfigState {
+        NONE,            // not in progress
+        NOTIFIED_HWC,    // call to HWC has been made
+        REFRESH_RECEIVED // onRefresh was received from HWC
+    };
+    std::atomic<SetActiveConfigState> mSetActiveConfigState = SetActiveConfigState::NONE;
+
+    struct ActiveConfigInfo {
+        int configId;
+        sp<IBinder> displayToken;
+
+        bool operator!=(const ActiveConfigInfo& other) const {
+            if (configId != other.configId) {
+                return true;
+            }
+            return (displayToken != other.displayToken);
+        }
+    };
+    std::mutex mActiveConfigLock;
+    // This bit is set once we start setting the config. We read from this bit during the
+    // process. If at the end, this bit is different than mDesiredActiveConfig, we restart
+    // the process.
+    ActiveConfigInfo mUpcomingActiveConfig; // Always read and written on the main thread.
+    // This bit can be set at any point in time when the system wants the new config.
+    ActiveConfigInfo mDesiredActiveConfig GUARDED_BY(mActiveConfigLock);
+
     /* ------------------------------------------------------------------------ */
     sp<IInputFlinger> mInputFlinger;