Merge changes Id05d2eac,I3d8bcbf8 into sc-dev

* changes:
  SF: Add DisplayDevice::initiateModeChange
  SF: Store display modes in DisplayDevice
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 63be3ed..e5e10a0 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -16,6 +16,7 @@
 
 #define LOG_TAG "LayerState"
 
+#include <apex/window.h>
 #include <inttypes.h>
 
 #include <binder/Parcel.h>
@@ -620,7 +621,8 @@
     return NO_ERROR;
 }
 
-bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName) {
+bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* inFunctionName,
+                       bool privileged) {
     const char* functionName = inFunctionName != nullptr ? inFunctionName : "call";
     int floatClassification = std::fpclassify(frameRate);
     if (frameRate < 0 || floatClassification == FP_INFINITE || floatClassification == FP_NAN) {
@@ -629,8 +631,10 @@
     }
 
     if (compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT &&
-        compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE) {
-        ALOGE("%s failed - invalid compatibility value %d", functionName, compatibility);
+        compatibility != ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE &&
+        (!privileged || compatibility != ANATIVEWINDOW_FRAME_RATE_EXACT)) {
+        ALOGE("%s failed - invalid compatibility value %d privileged: %s", functionName,
+              compatibility, privileged ? "yes" : "no");
         return false;
     }
 
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index 4a372bb..78f655a 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1518,7 +1518,10 @@
         mStatus = BAD_INDEX;
         return *this;
     }
-    if (!ValidateFrameRate(frameRate, compatibility, "Transaction::setFrameRate")) {
+    // Allow privileged values as well here, those will be ignored by SF if
+    // the caller is not privileged
+    if (!ValidateFrameRate(frameRate, compatibility, "Transaction::setFrameRate",
+                           /*privileged=*/true)) {
         mStatus = BAD_VALUE;
         return *this;
     }
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 4a291ae..83a9d33 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -309,11 +309,14 @@
     return compare_type(lhs.token, rhs.token);
 }
 
-// Returns true if the frameRate and compatibility are valid values, false
-// othwerise. If either of the params are invalid, an error log is printed, and
-// functionName is added to the log to indicate which function call failed.
-// functionName can be null.
-bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName);
+// Returns true if the frameRate is valid.
+//
+// @param frameRate the frame rate in Hz
+// @param compatibility a ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_*
+// @param functionName calling function or nullptr. Used for logging
+// @param privileged whether caller has unscoped surfaceflinger access
+bool ValidateFrameRate(float frameRate, int8_t compatibility, const char* functionName,
+                       bool privileged = false);
 
 struct CaptureArgs {
     const static int32_t UNSET_UID = -1;
diff --git a/libs/nativewindow/include/apex/window.h b/libs/nativewindow/include/apex/window.h
index 2d1354c..0923438 100644
--- a/libs/nativewindow/include/apex/window.h
+++ b/libs/nativewindow/include/apex/window.h
@@ -39,6 +39,19 @@
     // clang-format on
 };
 
+/*
+ * Internal extension of compatibility value for ANativeWindow_setFrameRate. */
+enum ANativeWindow_FrameRateCompatibilityInternal {
+    /**
+     * This surface belongs to an app on the High Refresh Rate Deny list, and needs the display
+     * to operate at the exact frame rate.
+     *
+     * This is used internally by the platform and should not be used by apps.
+     * @hide
+     */
+    ANATIVEWINDOW_FRAME_RATE_EXACT = 100,
+};
+
 /**
  * Prototype of the function that an ANativeWindow implementation would call
  * when ANativeWindow_cancelBuffer is called.
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a545d18..66ce3f1 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1432,21 +1432,28 @@
     };
 
     // update parents and children about the vote
-    // First traverse the tree and count how many layers has votes
+    // First traverse the tree and count how many layers has votes. In addition
+    // activate the layers in Scheduler's LayerHistory for it to check for changes
     int layersWithVote = 0;
-    traverseTree([&layersWithVote](Layer* layer) {
+    traverseTree([&layersWithVote, this](Layer* layer) {
         const auto layerVotedWithDefaultCompatibility =
                 layer->mCurrentState.frameRate.rate.isValid() &&
                 layer->mCurrentState.frameRate.type == FrameRateCompatibility::Default;
         const auto layerVotedWithNoVote =
                 layer->mCurrentState.frameRate.type == FrameRateCompatibility::NoVote;
+        const auto layerVotedWithExactCompatibility =
+                layer->mCurrentState.frameRate.type == FrameRateCompatibility::Exact;
 
         // We do not count layers that are ExactOrMultiple for the same reason
         // we are allowing touch boost for those layers. See
         // RefreshRateConfigs::getBestRefreshRate for more details.
-        if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote) {
+        if (layerVotedWithDefaultCompatibility || layerVotedWithNoVote ||
+            layerVotedWithExactCompatibility) {
             layersWithVote++;
         }
+
+        mFlinger->mScheduler->recordLayerHistory(layer, systemTime(),
+                                                 LayerHistory::LayerUpdateType::SetFrameRate);
     });
 
     // Now update the other layers
@@ -1474,10 +1481,6 @@
         return false;
     }
 
-    // Activate the layer in Scheduler's LayerHistory
-    mFlinger->mScheduler->recordLayerHistory(this, systemTime(),
-                                             LayerHistory::LayerUpdateType::SetFrameRate);
-
     mCurrentState.sequence++;
     mCurrentState.frameRate = frameRate;
     mCurrentState.modified = true;
@@ -1501,8 +1504,16 @@
         return frameRate;
     }
 
-    // This layer doesn't have a frame rate. If one of its ancestors or successors
-    // have a vote, return a NoVote for ancestors/successors to set the vote
+    // This layer doesn't have a frame rate. Check if its ancestors have a vote
+    if (sp<Layer> parent = getParent(); parent) {
+        if (const auto parentFrameRate = parent->getFrameRateForLayerTree();
+            parentFrameRate.rate.isValid()) {
+            return parentFrameRate;
+        }
+    }
+
+    // This layer and its ancestors don't have a frame rate. If one of successors
+    // has a vote, return a NoVote for successors to set the vote
     if (getDrawingState().treeHasFrameRateVote) {
         return {Fps(0.0f), FrameRateCompatibility::NoVote};
     }
@@ -1654,6 +1665,8 @@
             return "ExactOrMultiple";
         case FrameRateCompatibility::NoVote:
             return "NoVote";
+        case FrameRateCompatibility::Exact:
+            return "Exact";
     }
 }
 
@@ -1692,11 +1705,11 @@
     const FloatRect& crop = outputLayerState.sourceCrop;
     StringAppendF(&result, "%6.1f %6.1f %6.1f %6.1f | ", crop.left, crop.top, crop.right,
                   crop.bottom);
-    if (layerState.frameRate.rate.isValid() ||
-        layerState.frameRate.type != FrameRateCompatibility::Default) {
-        StringAppendF(&result, "%s %15s %17s", to_string(layerState.frameRate.rate).c_str(),
-                      frameRateCompatibilityString(layerState.frameRate.type).c_str(),
-                      toString(layerState.frameRate.seamlessness).c_str());
+    const auto frameRate = getFrameRateForLayerTree();
+    if (frameRate.rate.isValid() || frameRate.type != FrameRateCompatibility::Default) {
+        StringAppendF(&result, "%s %15s %17s", to_string(frameRate.rate).c_str(),
+                      frameRateCompatibilityString(frameRate.type).c_str(),
+                      toString(frameRate.seamlessness).c_str());
     } else {
         result.append(41, ' ');
     }
@@ -2755,6 +2768,8 @@
             return FrameRateCompatibility::Default;
         case ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE:
             return FrameRateCompatibility::ExactOrMultiple;
+        case ANATIVEWINDOW_FRAME_RATE_EXACT:
+            return FrameRateCompatibility::Exact;
         default:
             LOG_ALWAYS_FATAL("Invalid frame rate compatibility value %d", compatibility);
             return FrameRateCompatibility::Default;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index f78b5f3..359340e 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -145,6 +145,8 @@
     enum class FrameRateCompatibility {
         Default, // Layer didn't specify any specific handling strategy
 
+        Exact, // Layer needs the exact frame rate.
+
         ExactOrMultiple, // Layer needs the exact frame rate (or a multiple of it) to present the
                          // content properly. Any other value will result in a pull down.
 
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 170933d..7ef531d 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -71,6 +71,7 @@
     traceType(LayerHistory::LayerVoteType::Heuristic, fps);
     traceType(LayerHistory::LayerVoteType::ExplicitDefault, fps);
     traceType(LayerHistory::LayerVoteType::ExplicitExactOrMultiple, fps);
+    traceType(LayerHistory::LayerVoteType::ExplicitExact, fps);
     traceType(LayerHistory::LayerVoteType::Min, 1);
     traceType(LayerHistory::LayerVoteType::Max, 1);
 
@@ -172,6 +173,8 @@
                         return LayerVoteType::ExplicitExactOrMultiple;
                     case Layer::FrameRateCompatibility::NoVote:
                         return LayerVoteType::NoVote;
+                    case Layer::FrameRateCompatibility::Exact:
+                        return LayerVoteType::ExplicitExact;
                 }
             }();
 
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 0f1e267..81ffe0f 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -83,6 +83,8 @@
             return "ExplicitDefault";
         case LayerVoteType::ExplicitExactOrMultiple:
             return "ExplicitExactOrMultiple";
+        case LayerVoteType::ExplicitExact:
+            return "ExplicitExact";
     }
 }
 
@@ -165,6 +167,18 @@
         return (1.0f / iter) * seamlessness;
     }
 
+    if (layer.vote == LayerVoteType::ExplicitExact) {
+        const int divider = getFrameRateDivider(refreshRate.getFps(), layer.desiredRefreshRate);
+        if (mSupportsFrameRateOverride) {
+            // Since we support frame rate override, allow refresh rates which are
+            // multiples of the layer's request, as those apps would be throttled
+            // down to run at the desired refresh rate.
+            return divider > 0;
+        }
+
+        return divider == 1;
+    }
+
     return 0;
 }
 
@@ -199,21 +213,34 @@
     int maxVoteLayers = 0;
     int explicitDefaultVoteLayers = 0;
     int explicitExactOrMultipleVoteLayers = 0;
+    int explicitExact = 0;
     float maxExplicitWeight = 0;
     int seamedLayers = 0;
     for (const auto& layer : layers) {
-        if (layer.vote == LayerVoteType::NoVote) {
-            noVoteLayers++;
-        } else if (layer.vote == LayerVoteType::Min) {
-            minVoteLayers++;
-        } else if (layer.vote == LayerVoteType::Max) {
-            maxVoteLayers++;
-        } else if (layer.vote == LayerVoteType::ExplicitDefault) {
-            explicitDefaultVoteLayers++;
-            maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
-        } else if (layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
-            explicitExactOrMultipleVoteLayers++;
-            maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+        switch (layer.vote) {
+            case LayerVoteType::NoVote:
+                noVoteLayers++;
+                break;
+            case LayerVoteType::Min:
+                minVoteLayers++;
+                break;
+            case LayerVoteType::Max:
+                maxVoteLayers++;
+                break;
+            case LayerVoteType::ExplicitDefault:
+                explicitDefaultVoteLayers++;
+                maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+                break;
+            case LayerVoteType::ExplicitExactOrMultiple:
+                explicitExactOrMultipleVoteLayers++;
+                maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+                break;
+            case LayerVoteType::ExplicitExact:
+                explicitExact++;
+                maxExplicitWeight = std::max(maxExplicitWeight, layer.weight);
+                break;
+            case LayerVoteType::Heuristic:
+                break;
         }
 
         if (layer.seamlessness == Seamlessness::SeamedAndSeamless) {
@@ -221,8 +248,8 @@
         }
     }
 
-    const bool hasExplicitVoteLayers =
-            explicitDefaultVoteLayers > 0 || explicitExactOrMultipleVoteLayers > 0;
+    const bool hasExplicitVoteLayers = explicitDefaultVoteLayers > 0 ||
+            explicitExactOrMultipleVoteLayers > 0 || explicitExact > 0;
 
     // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've
     // selected a refresh rate to see if we should apply touch boost.
@@ -318,7 +345,9 @@
             bool inPrimaryRange = scores[i].refreshRate->inPolicy(policy->primaryRange.min,
                                                                   policy->primaryRange.max);
             if ((primaryRangeIsSingleRate || !inPrimaryRange) &&
-                !(layer.focused && layer.vote == LayerVoteType::ExplicitDefault)) {
+                !(layer.focused &&
+                  (layer.vote == LayerVoteType::ExplicitDefault ||
+                   layer.vote == LayerVoteType::ExplicitExact))) {
                 // Only focused layers with ExplicitDefault frame rate settings are allowed to score
                 // refresh rates outside the primary range.
                 continue;
@@ -358,7 +387,8 @@
     // actually increase the refresh rate over the normal selection.
     const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked();
 
-    if (globalSignals.touch && explicitDefaultVoteLayers == 0 &&
+    bool touchBoostForExplicitExact = explicitExact == 0 || mSupportsFrameRateOverride;
+    if (globalSignals.touch && explicitDefaultVoteLayers == 0 && touchBoostForExplicitExact &&
         bestRefreshRate->fps.lessThanWithMargin(touchRefreshRate.fps)) {
         setTouchConsidered();
         ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str());
@@ -412,7 +442,7 @@
 }
 
 RefreshRateConfigs::UidToFrameRateOverride RefreshRateConfigs::getFrameRateOverrides(
-        const std::vector<LayerRequirement>& layers, Fps displayFrameRate) const {
+        const std::vector<LayerRequirement>& layers, Fps displayFrameRate, bool touch) const {
     ATRACE_CALL();
     if (!mSupportsFrameRateOverride) return {};
 
@@ -423,6 +453,17 @@
             groupLayersByUid(layers);
     UidToFrameRateOverride frameRateOverrides;
     for (const auto& [uid, layersWithSameUid] : layersByUid) {
+        // Layers with ExplicitExactOrMultiple expect touch boost
+        const bool hasExplicitExactOrMultiple =
+                std::any_of(layersWithSameUid.cbegin(), layersWithSameUid.cend(),
+                            [](const auto& layer) {
+                                return layer->vote == LayerVoteType::ExplicitExactOrMultiple;
+                            });
+
+        if (touch && hasExplicitExactOrMultiple) {
+            continue;
+        }
+
         for (auto& score : scores) {
             score.score = 0;
         }
@@ -433,7 +474,8 @@
             }
 
             LOG_ALWAYS_FATAL_IF(layer->vote != LayerVoteType::ExplicitDefault &&
-                                layer->vote != LayerVoteType::ExplicitExactOrMultiple);
+                                layer->vote != LayerVoteType::ExplicitExactOrMultiple &&
+                                layer->vote != LayerVoteType::ExplicitExact);
             for (RefreshRateScore& score : scores) {
                 const auto layerScore = calculateLayerScoreLocked(*layer, *score.refreshRate,
                                                                   /*isSeamlessSwitch*/ true);
@@ -559,8 +601,10 @@
     mCurrentRefreshRate = mRefreshRates.at(configId).get();
 }
 
-RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId)
-      : mKnownFrameRates(constructKnownFrameRates(configs)) {
+RefreshRateConfigs::RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId,
+                                       bool enableFrameRateOverride)
+      : mKnownFrameRates(constructKnownFrameRates(configs)),
+        mEnableFrameRateOverride(enableFrameRateOverride) {
     updateDisplayConfigs(configs, currentConfigId);
 }
 
@@ -589,7 +633,7 @@
     mMaxSupportedRefreshRate = sortedConfigs.back();
 
     mSupportsFrameRateOverride = false;
-    if (android::sysprop::enable_frame_rate_override(true)) {
+    if (mEnableFrameRateOverride) {
         for (const auto& config1 : sortedConfigs) {
             for (const auto& config2 : sortedConfigs) {
                 if (getFrameRateDivider(config1->getFps(), config2->getFps()) >= 2) {
@@ -826,4 +870,4 @@
 } // namespace android::scheduler
 
 // TODO(b/129481165): remove the #pragma below and fix conversion issues
-#pragma clang diagnostic pop // ignored "-Wextra"
\ No newline at end of file
+#pragma clang diagnostic pop // ignored "-Wextra"
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 29402f5..0c7dc05 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -211,8 +211,11 @@
         Heuristic,       // Specific refresh rate that was calculated by platform using a heuristic
         ExplicitDefault, // Specific refresh rate that was provided by the app with Default
                          // compatibility
-        ExplicitExactOrMultiple // Specific refresh rate that was provided by the app with
-                                // ExactOrMultiple compatibility
+        ExplicitExactOrMultiple, // Specific refresh rate that was provided by the app with
+                                 // ExactOrMultiple compatibility
+        ExplicitExact,           // Specific refresh rate that was provided by the app with
+                                 // Exact compatibility
+
     };
 
     // Captures the layer requirements for a refresh rate. This will be used to determine the
@@ -298,7 +301,8 @@
     // Returns a known frame rate that is the closest to frameRate
     Fps findClosestKnownFrameRate(Fps frameRate) const;
 
-    RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId);
+    RefreshRateConfigs(const DisplayModes& configs, DisplayModeId currentConfigId,
+                       bool enableFrameRateOverride = false);
 
     void updateDisplayConfigs(const DisplayModes& configs, DisplayModeId currentConfig)
             EXCLUDES(mLock);
@@ -327,10 +331,15 @@
     // Returns a divider for the current refresh rate
     int getRefreshRateDivider(Fps frameRate) const EXCLUDES(mLock);
 
-    // Returns the frame rate override for each uid
     using UidToFrameRateOverride = std::map<uid_t, Fps>;
+    // Returns the frame rate override for each uid.
+    //
+    // @param layers list of visible layers
+    // @param displayFrameRate the display frame rate
+    // @param touch whether touch timer is active (i.e. user touched the screen recently)
     UidToFrameRateOverride getFrameRateOverrides(const std::vector<LayerRequirement>& layers,
-                                                 Fps displayFrameRate) const EXCLUDES(mLock);
+                                                 Fps displayFrameRate, bool touch) const
+            EXCLUDES(mLock);
 
     void dump(std::string& result) const EXCLUDES(mLock);
 
@@ -410,6 +419,7 @@
     // from based on the closest value.
     const std::vector<Fps> mKnownFrameRates;
 
+    const bool mEnableFrameRateOverride;
     bool mSupportsFrameRateOverride;
 };
 
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 588b83d..d861209 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -763,17 +763,11 @@
         return false;
     }
 
-    if (consideredSignals.touch) {
-        std::lock_guard lock(mFrameRateOverridesMutex);
-        const bool changed = !mFrameRateOverridesByContent.empty();
-        mFrameRateOverridesByContent.clear();
-        return changed;
-    }
-
     if (!consideredSignals.idle) {
         const auto frameRateOverrides =
                 mRefreshRateConfigs.getFrameRateOverrides(mFeatures.contentRequirements,
-                                                          displayRefreshRate);
+                                                          displayRefreshRate,
+                                                          consideredSignals.touch);
         std::lock_guard lock(mFrameRateOverridesMutex);
         if (!std::equal(mFrameRateOverridesByContent.begin(), mFrameRateOverridesByContent.end(),
                         frameRateOverrides.begin(), frameRateOverrides.end(),
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3a9f7de..a764cbb 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -2942,7 +2942,9 @@
 
     auto currentConfig = getHwComposer().getActiveMode(primaryDisplayId)->getId();
     const auto modes = getHwComposer().getModes(primaryDisplayId);
-    mRefreshRateConfigs = std::make_unique<scheduler::RefreshRateConfigs>(modes, currentConfig);
+    mRefreshRateConfigs = std::make_unique<
+            scheduler::RefreshRateConfigs>(modes, currentConfig,
+                                           android::sysprop::enable_frame_rate_override(true));
     const auto& currRefreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(currentConfig);
     mRefreshRateStats =
             std::make_unique<scheduler::RefreshRateStats>(*mTimeStats, currRefreshRate.getFps(),
@@ -3895,7 +3897,7 @@
     }
     if (what & layer_state_t::eFrameRateChanged) {
         if (ValidateFrameRate(s.frameRate, s.frameRateCompatibility,
-                              "SurfaceFlinger::setClientStateLocked") &&
+                              "SurfaceFlinger::setClientStateLocked", privileged) &&
             layer->setFrameRate(Layer::FrameRate(Fps(s.frameRate),
                                                  Layer::FrameRate::convertCompatibility(
                                                          s.frameRateCompatibility),
diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h
index 8fac8e9..df40ef6 100644
--- a/services/surfaceflinger/TimeStats/TimeStats.h
+++ b/services/surfaceflinger/TimeStats/TimeStats.h
@@ -315,8 +315,9 @@
 
     static const size_t MAX_NUM_LAYER_RECORDS = 200;
     static const size_t MAX_NUM_LAYER_STATS = 200;
+    static const size_t MAX_NUM_PULLED_LAYERS = MAX_NUM_LAYER_STATS;
     std::unique_ptr<StatsEventDelegate> mStatsDelegate = std::make_unique<StatsEventDelegate>();
-    size_t mMaxPulledLayers = 8;
+    size_t mMaxPulledLayers = MAX_NUM_PULLED_LAYERS;
     size_t mMaxPulledHistogramBuckets = 6;
 };
 
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
index 0a747ab..738ded1 100644
--- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
+++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp
@@ -1506,6 +1506,89 @@
     }
 }
 
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExact) {
+    auto refreshRateConfigs =
+            std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
+                                                 /*currentConfigId=*/HWC_CONFIG_ID_60);
+
+    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
+                                                LayerRequirement{.weight = 0.5f}};
+    auto& explicitExactLayer = layers[0];
+    auto& explicitExactOrMultipleLayer = layers[1];
+
+    explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple;
+    explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple";
+    explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60);
+
+    explicitExactLayer.vote = LayerVoteType::ExplicitExact;
+    explicitExactLayer.name = "ExplicitExact";
+    explicitExactLayer.desiredRefreshRate = Fps(30);
+
+    EXPECT_EQ(mExpected30Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+    EXPECT_EQ(mExpected30Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
+
+    explicitExactOrMultipleLayer.desiredRefreshRate = Fps(120);
+    explicitExactLayer.desiredRefreshRate = Fps(60);
+    EXPECT_EQ(mExpected60Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+    explicitExactLayer.desiredRefreshRate = Fps(72);
+    EXPECT_EQ(mExpected72Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+    explicitExactLayer.desiredRefreshRate = Fps(90);
+    EXPECT_EQ(mExpected90Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+    explicitExactLayer.desiredRefreshRate = Fps(120);
+    EXPECT_EQ(mExpected120Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+}
+
+TEST_F(RefreshRateConfigsTest, getBestRefreshRate_ExplicitExactEnableFrameRateOverride) {
+    auto refreshRateConfigs =
+            std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
+                                                 /*currentConfigId=*/HWC_CONFIG_ID_60,
+                                                 /*enableFrameRateOverride=*/true);
+
+    auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f},
+                                                LayerRequirement{.weight = 0.5f}};
+    auto& explicitExactLayer = layers[0];
+    auto& explicitExactOrMultipleLayer = layers[1];
+
+    explicitExactOrMultipleLayer.vote = LayerVoteType::ExplicitExactOrMultiple;
+    explicitExactOrMultipleLayer.name = "ExplicitExactOrMultiple";
+    explicitExactOrMultipleLayer.desiredRefreshRate = Fps(60);
+
+    explicitExactLayer.vote = LayerVoteType::ExplicitExact;
+    explicitExactLayer.name = "ExplicitExact";
+    explicitExactLayer.desiredRefreshRate = Fps(30);
+
+    EXPECT_EQ(mExpected60Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+    EXPECT_EQ(mExpected120Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = true, .idle = false}));
+
+    explicitExactOrMultipleLayer.desiredRefreshRate = Fps(120);
+    explicitExactLayer.desiredRefreshRate = Fps(60);
+    EXPECT_EQ(mExpected120Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+    explicitExactLayer.desiredRefreshRate = Fps(72);
+    EXPECT_EQ(mExpected72Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+    explicitExactLayer.desiredRefreshRate = Fps(90);
+    EXPECT_EQ(mExpected90Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+
+    explicitExactLayer.desiredRefreshRate = Fps(120);
+    EXPECT_EQ(mExpected120Config,
+              refreshRateConfigs->getBestRefreshRate(layers, {.touch = false, .idle = false}));
+}
+
 TEST_F(RefreshRateConfigsTest, testComparisonOperator) {
     EXPECT_TRUE(mExpected60Config < mExpected90Config);
     EXPECT_FALSE(mExpected60Config < mExpected60Config);
@@ -1537,7 +1620,7 @@
     EXPECT_EQ(KernelIdleTimerAction::TurnOff, refreshRateConfigs->getIdleTimerAction());
 }
 
-TEST_F(RefreshRateConfigsTest, RefreshRateDividerForUid) {
+TEST_F(RefreshRateConfigsTest, getRefreshRateDivider) {
     auto refreshRateConfigs =
             std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device,
                                                  /*currentConfigId=*/HWC_CONFIG_ID_30);
@@ -1562,57 +1645,66 @@
     EXPECT_EQ(4, refreshRateConfigs->getRefreshRateDivider(Fps(22.6f)));
 }
 
-TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_noLayers) {
+TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_noLayers) {
     auto refreshRateConfigs =
             std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
                                                  HWC_CONFIG_ID_120);
 
     auto layers = std::vector<LayerRequirement>{};
-    ASSERT_TRUE(refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f)).empty());
+    ASSERT_TRUE(refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false)
+                        .empty());
 }
 
 TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_60on120) {
     auto refreshRateConfigs =
             std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
-                                                 HWC_CONFIG_ID_120);
+                                                 HWC_CONFIG_ID_120,
+                                                 /*enableFrameRateOverride=*/true);
 
     auto layers = std::vector<LayerRequirement>{LayerRequirement{.weight = 1.0f}};
     layers[0].name = "Test layer";
     layers[0].ownerUid = 1234;
     layers[0].desiredRefreshRate = Fps(60.0f);
     layers[0].vote = LayerVoteType::ExplicitDefault;
-    auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+    auto frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
     ASSERT_EQ(1, frameRateOverrides.size());
     ASSERT_EQ(1, frameRateOverrides.count(1234));
     ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
 
     layers[0].vote = LayerVoteType::ExplicitExactOrMultiple;
-    frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
     ASSERT_EQ(1, frameRateOverrides.size());
     ASSERT_EQ(1, frameRateOverrides.count(1234));
     ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
 
     layers[0].vote = LayerVoteType::NoVote;
-    frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
     ASSERT_TRUE(frameRateOverrides.empty());
 
     layers[0].vote = LayerVoteType::Min;
-    frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
     ASSERT_TRUE(frameRateOverrides.empty());
 
     layers[0].vote = LayerVoteType::Max;
-    frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
     ASSERT_TRUE(frameRateOverrides.empty());
 
     layers[0].vote = LayerVoteType::Heuristic;
-    frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
     ASSERT_TRUE(frameRateOverrides.empty());
 }
 
-TEST_F(RefreshRateConfigsTest, populatePreferredFrameRate_twoUids) {
+TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_twoUids) {
     auto refreshRateConfigs =
             std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
-                                                 HWC_CONFIG_ID_120);
+                                                 HWC_CONFIG_ID_120,
+                                                 /*enableFrameRateOverride=*/true);
 
     auto layers = std::vector<LayerRequirement>{
             LayerRequirement{.ownerUid = 1234, .weight = 1.0f},
@@ -1626,7 +1718,8 @@
     layers[1].name = "Test layer 5678";
     layers[1].desiredRefreshRate = Fps(30.0f);
     layers[1].vote = LayerVoteType::ExplicitDefault;
-    auto frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+    auto frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
 
     ASSERT_EQ(2, frameRateOverrides.size());
     ASSERT_EQ(1, frameRateOverrides.count(1234));
@@ -1635,13 +1728,66 @@
     ASSERT_EQ(30.0f, frameRateOverrides.at(5678).getValue());
 
     layers[1].vote = LayerVoteType::Heuristic;
-    frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
     ASSERT_EQ(1, frameRateOverrides.size());
     ASSERT_EQ(1, frameRateOverrides.count(1234));
     ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
 
     layers[1].ownerUid = 1234;
-    frameRateOverrides = refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f));
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
+    ASSERT_TRUE(frameRateOverrides.empty());
+}
+
+TEST_F(RefreshRateConfigsTest, getFrameRateOverrides_touch) {
+    auto refreshRateConfigs =
+            std::make_unique<RefreshRateConfigs>(m30_60_72_90_120Device, /*currentConfigId=*/
+                                                 HWC_CONFIG_ID_120,
+                                                 /*enableFrameRateOverride=*/true);
+
+    auto layers = std::vector<LayerRequirement>{
+            LayerRequirement{.ownerUid = 1234, .weight = 1.0f},
+    };
+
+    layers[0].name = "Test layer";
+    layers[0].desiredRefreshRate = Fps(60.0f);
+    layers[0].vote = LayerVoteType::ExplicitDefault;
+
+    auto frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
+    ASSERT_EQ(1, frameRateOverrides.size());
+    ASSERT_EQ(1, frameRateOverrides.count(1234));
+    ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true);
+    ASSERT_EQ(1, frameRateOverrides.size());
+    ASSERT_EQ(1, frameRateOverrides.count(1234));
+    ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+    layers[0].vote = LayerVoteType::ExplicitExact;
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
+    ASSERT_EQ(1, frameRateOverrides.size());
+    ASSERT_EQ(1, frameRateOverrides.count(1234));
+    ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true);
+    ASSERT_EQ(1, frameRateOverrides.size());
+    ASSERT_EQ(1, frameRateOverrides.count(1234));
+    ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+    layers[0].vote = LayerVoteType::ExplicitExactOrMultiple;
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/false);
+    ASSERT_EQ(1, frameRateOverrides.size());
+    ASSERT_EQ(1, frameRateOverrides.count(1234));
+    ASSERT_EQ(60.0f, frameRateOverrides.at(1234).getValue());
+
+    frameRateOverrides =
+            refreshRateConfigs->getFrameRateOverrides(layers, Fps(120.0f), /*touch=*/true);
     ASSERT_TRUE(frameRateOverrides.empty());
 }
 
diff --git a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
index 1bbe8e2..e060df2 100644
--- a/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SetFrameRateTest.cpp
@@ -263,13 +263,13 @@
     commitTransaction();
     EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree());
     EXPECT_EQ(FRAME_RATE_VOTE2, child1->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE2, child2->getFrameRateForLayerTree());
 
     child1->setFrameRate(FRAME_RATE_NO_VOTE);
     commitTransaction();
     EXPECT_EQ(FRAME_RATE_VOTE3, parent->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE3, child1->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE3, child2->getFrameRateForLayerTree());
 
     parent->setFrameRate(FRAME_RATE_NO_VOTE);
     commitTransaction();
@@ -293,8 +293,8 @@
     parent->setFrameRate(FRAME_RATE_VOTE1);
     commitTransaction();
     EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
 
     parent->setFrameRate(FRAME_RATE_NO_VOTE);
     commitTransaction();
@@ -356,14 +356,14 @@
     parent->setFrameRate(FRAME_RATE_VOTE1);
     commitTransaction();
     EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
     EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
 
     addChild(child1, child2);
     commitTransaction();
     EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
 
     parent->setFrameRate(FRAME_RATE_NO_VOTE);
     commitTransaction();
@@ -387,13 +387,13 @@
     parent->setFrameRate(FRAME_RATE_VOTE1);
     commitTransaction();
     EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child2->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE1, child2->getFrameRateForLayerTree());
 
     removeChild(child1, child2);
     commitTransaction();
     EXPECT_EQ(FRAME_RATE_VOTE1, parent->getFrameRateForLayerTree());
-    EXPECT_EQ(FRAME_RATE_TREE, child1->getFrameRateForLayerTree());
+    EXPECT_EQ(FRAME_RATE_VOTE1, child1->getFrameRateForLayerTree());
     EXPECT_EQ(FRAME_RATE_NO_VOTE, child2->getFrameRateForLayerTree());
 
     parent->setFrameRate(FRAME_RATE_NO_VOTE);
@@ -473,5 +473,20 @@
                                          std::make_shared<EffectLayerFactory>()),
                          PrintToStringParamName);
 
+TEST_F(SetFrameRateTest, ValidateFrameRate) {
+    EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+    EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+    EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_FIXED_SOURCE, ""));
+    EXPECT_TRUE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, "", /*privileged=*/true));
+
+    EXPECT_FALSE(ValidateFrameRate(-1, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+    EXPECT_FALSE(
+            ValidateFrameRate(1.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+    EXPECT_FALSE(
+            ValidateFrameRate(0.0f / 0.0f, ANATIVEWINDOW_FRAME_RATE_COMPATIBILITY_DEFAULT, ""));
+
+    EXPECT_FALSE(ValidateFrameRate(60.0f, ANATIVEWINDOW_FRAME_RATE_EXACT, ""));
+}
+
 } // namespace
 } // namespace android