SF: Deprecate content detection v1

Remove the code for the old content detection algorithm,
which is no longer used.

Bug: 174120566
Test: presubmit
Change-Id: I0828bcb886f32ec2ebc896848b72340862613100
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
deleted file mode 100644
index 359ee26..0000000
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#undef LOG_TAG
-#define LOG_TAG "LayerHistory"
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "LayerHistory.h"
-
-#include <android-base/stringprintf.h>
-#include <cutils/properties.h>
-#include <utils/Log.h>
-#include <utils/Timers.h>
-#include <utils/Trace.h>
-
-#include <algorithm>
-#include <cmath>
-#include <string>
-#include <utility>
-
-#include "../Layer.h"
-#include "LayerInfo.h"
-#include "SchedulerUtils.h"
-
-namespace android::scheduler::impl {
-
-namespace {
-
-bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) {
-    if (layer.getFrameRateForLayerTree().rate > 0) {
-        return layer.isVisible();
-    }
-    return layer.isVisible() && info.getLastUpdatedTime() >= threshold;
-}
-
-bool traceEnabled() {
-    char value[PROPERTY_VALUE_MAX];
-    property_get("debug.sf.layer_history_trace", value, "0");
-    return atoi(value);
-}
-
-bool useFrameRatePriority() {
-    char value[PROPERTY_VALUE_MAX];
-    property_get("debug.sf.use_frame_rate_priority", value, "1");
-    return atoi(value);
-}
-
-void trace(const wp<Layer>& weak, int fps) {
-    const auto layer = weak.promote();
-    if (!layer) return;
-
-    const auto& name = layer->getName();
-    const auto tag = "LFPS " + name;
-    ATRACE_INT(tag.c_str(), fps);
-    ALOGD("%s: %s @ %d Hz", __FUNCTION__, name.c_str(), fps);
-}
-} // namespace
-
-LayerHistory::LayerHistory()
-      : mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {}
-LayerHistory::~LayerHistory() = default;
-
-void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highRefreshRate,
-                                 LayerVoteType /*type*/) {
-    auto info = std::make_unique<LayerInfo>(lowRefreshRate, highRefreshRate);
-    std::lock_guard lock(mLock);
-    mLayerInfos.emplace_back(layer, std::move(info));
-}
-
-void LayerHistory::record(Layer* layer, nsecs_t presentTime, nsecs_t now,
-                          LayerUpdateType /*updateType*/) {
-    std::lock_guard lock(mLock);
-
-    const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(),
-                                 [layer](const auto& pair) { return pair.first == layer; });
-    LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer);
-
-    const auto& info = it->second;
-    info->setLastPresentTime(presentTime, now);
-
-    // Activate layer if inactive.
-    if (const auto end = activeLayers().end(); it >= end) {
-        std::iter_swap(it, end);
-        mActiveLayersEnd++;
-    }
-}
-
-LayerHistory::Summary LayerHistory::summarize(nsecs_t now) {
-    ATRACE_CALL();
-    std::lock_guard lock(mLock);
-
-    partitionLayers(now);
-
-    LayerHistory::Summary summary;
-    for (const auto& [weakLayer, info] : activeLayers()) {
-        const bool recent = info->isRecentlyActive(now);
-        auto layer = weakLayer.promote();
-        // Only use the layer if the reference still exists.
-        if (layer || CC_UNLIKELY(mTraceEnabled)) {
-            const auto layerFocused =
-                    Layer::isLayerFocusedBasedOnPriority(layer->getFrameRateSelectionPriority());
-            // Check if frame rate was set on layer.
-            const auto frameRate = layer->getFrameRateForLayerTree();
-            if (frameRate.rate > 0.f) {
-                const auto voteType = [&]() {
-                    switch (frameRate.type) {
-                        case Layer::FrameRateCompatibility::Default:
-                            return LayerVoteType::ExplicitDefault;
-                        case Layer::FrameRateCompatibility::ExactOrMultiple:
-                            return LayerVoteType::ExplicitExactOrMultiple;
-                        case Layer::FrameRateCompatibility::NoVote:
-                            return LayerVoteType::NoVote;
-                    }
-                }();
-                summary.push_back(
-                        RefreshRateConfigs::LayerRequirement{.name = layer->getName(),
-                                                             .vote = voteType,
-                                                             .desiredRefreshRate = frameRate.rate,
-                                                             .seamlessness = frameRate.seamlessness,
-                                                             .weight = 1.0f,
-                                                             .focused = layerFocused});
-            } else if (recent) {
-                summary.push_back(
-                        RefreshRateConfigs::LayerRequirement{.name = layer->getName(),
-                                                             .vote = LayerVoteType::Heuristic,
-                                                             .desiredRefreshRate =
-                                                                     info->getRefreshRate(now),
-                                                             .seamlessness =
-                                                                     Seamlessness::OnlySeamless,
-                                                             .weight = 1.0f,
-                                                             .focused = layerFocused});
-            }
-
-            if (CC_UNLIKELY(mTraceEnabled)) {
-                trace(weakLayer, round<int>(frameRate.rate));
-            }
-        }
-    }
-
-    return summary;
-}
-
-void LayerHistory::partitionLayers(nsecs_t now) {
-    const nsecs_t threshold = getActiveLayerThreshold(now);
-
-    // Collect expired and inactive layers after active layers.
-    size_t i = 0;
-    while (i < mActiveLayersEnd) {
-        auto& [weak, info] = mLayerInfos[i];
-        if (const auto layer = weak.promote(); layer && isLayerActive(*layer, *info, threshold)) {
-            i++;
-            continue;
-        }
-
-        if (CC_UNLIKELY(mTraceEnabled)) {
-            trace(weak, 0);
-        }
-
-        info->clearHistory();
-        std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]);
-    }
-
-    // Collect expired layers after inactive layers.
-    size_t end = mLayerInfos.size();
-    while (i < end) {
-        if (mLayerInfos[i].first.promote()) {
-            i++;
-        } else {
-            std::swap(mLayerInfos[i], mLayerInfos[--end]);
-        }
-    }
-
-    mLayerInfos.erase(mLayerInfos.begin() + static_cast<long>(end), mLayerInfos.end());
-}
-
-void LayerHistory::clear() {
-    std::lock_guard lock(mLock);
-
-    for (const auto& [layer, info] : activeLayers()) {
-        info->clearHistory();
-    }
-
-    mActiveLayersEnd = 0;
-}
-
-std::string LayerHistory::dump() const {
-    std::lock_guard lock(mLock);
-    return base::StringPrintf("LayerHistory{size=%zu, active=%zu}", mLayerInfos.size(),
-                              mActiveLayersEnd);
-}
-
-} // namespace android::scheduler::impl
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 128699b..3235cf2 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -76,66 +76,6 @@
 };
 
 namespace impl {
-// Records per-layer history of scheduling-related information (primarily present time),
-// heuristically categorizes layers as active or inactive, and summarizes stats about
-// active layers (primarily maximum refresh rate). See go/content-fps-detection-in-scheduler.
-class LayerHistory : public android::scheduler::LayerHistory {
-public:
-    LayerHistory();
-    virtual ~LayerHistory();
-
-    // Layers are unregistered when the weak reference expires.
-    void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate,
-                       LayerVoteType type) override;
-
-    void setDisplayArea(uint32_t /*displayArea*/) override {}
-
-    void setConfigChangePending(bool /*pending*/) override {}
-
-    // Marks the layer as active, and records the given state to its history.
-    void record(Layer*, nsecs_t presentTime, nsecs_t now, LayerUpdateType updateType) override;
-
-    // Rebuilds sets of active/inactive layers, and accumulates stats for active layers.
-    android::scheduler::LayerHistory::Summary summarize(nsecs_t now) override;
-
-    void clear() override;
-    std::string dump() const override;
-
-private:
-    friend class android::scheduler::LayerHistoryTest;
-    friend TestableScheduler;
-
-    using LayerPair = std::pair<wp<Layer>, std::unique_ptr<LayerInfo>>;
-    using LayerInfos = std::vector<LayerPair>;
-
-    struct ActiveLayers {
-        LayerInfos& infos;
-        const size_t index;
-
-        auto begin() { return infos.begin(); }
-        auto end() { return begin() + static_cast<long>(index); }
-    };
-
-    ActiveLayers activeLayers() REQUIRES(mLock) { return {mLayerInfos, mActiveLayersEnd}; }
-
-    // Iterates over layers in a single pass, swapping pairs such that active layers precede
-    // inactive layers, and inactive layers precede expired layers. Removes expired layers by
-    // truncating after inactive layers.
-    void partitionLayers(nsecs_t now) REQUIRES(mLock);
-
-    mutable std::mutex mLock;
-
-    // Partitioned such that active layers precede inactive layers. For fast lookup, the few active
-    // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache.
-    LayerInfos mLayerInfos GUARDED_BY(mLock);
-    size_t mActiveLayersEnd GUARDED_BY(mLock) = 0;
-
-    // Whether to emit systrace output and debug logs.
-    const bool mTraceEnabled;
-
-    // Whether to use priority sent from WindowManager to determine the relevancy of the layer.
-    const bool mUseFrameRatePriority;
-};
 
 class LayerHistoryV2 : public android::scheduler::LayerHistory {
 public:
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp
deleted file mode 100644
index 6d9dd43..0000000
--- a/services/surfaceflinger/Scheduler/LayerInfo.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "LayerInfo.h"
-
-#include <algorithm>
-#include <utility>
-
-namespace android::scheduler {
-
-LayerInfo::LayerInfo(float lowRefreshRate, float highRefreshRate)
-      : mLowRefreshRate(lowRefreshRate), mHighRefreshRate(highRefreshRate) {}
-
-void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) {
-    lastPresentTime = std::max(lastPresentTime, static_cast<nsecs_t>(0));
-
-    // Buffers can come with a present time far in the future. That keeps them relevant.
-    mLastUpdatedTime = std::max(lastPresentTime, now);
-    mPresentTimeHistory.insertPresentTime(mLastUpdatedTime);
-
-    if (mLastPresentTime == 0) {
-        // First frame
-        mLastPresentTime = lastPresentTime;
-        return;
-    }
-
-    const nsecs_t period = lastPresentTime - mLastPresentTime;
-    mLastPresentTime = lastPresentTime;
-    // Ignore time diff that are too high - those are stale values
-    if (period > MAX_ACTIVE_LAYER_PERIOD_NS.count()) return;
-
-    const float fps = std::min(1e9f / period, mHighRefreshRate);
-    mRefreshRateHistory.insertRefreshRate(fps);
-}
-
-} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h
deleted file mode 100644
index 820624b..0000000
--- a/services/surfaceflinger/Scheduler/LayerInfo.h
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <utils/Timers.h>
-
-#include <chrono>
-#include <deque>
-
-#include "SchedulerUtils.h"
-
-namespace android {
-
-class Layer;
-
-namespace scheduler {
-
-using namespace std::chrono_literals;
-
-// Maximum period between presents for a layer to be considered active.
-constexpr std::chrono::nanoseconds MAX_ACTIVE_LAYER_PERIOD_NS = 1200ms;
-
-// Earliest present time for a layer to be considered active.
-constexpr nsecs_t getActiveLayerThreshold(nsecs_t now) {
-    return now - MAX_ACTIVE_LAYER_PERIOD_NS.count();
-}
-
-// Stores history of present times and refresh rates for a layer.
-class LayerInfo {
-    // Layer is considered frequent if the earliest value in the window of most recent present times
-    // is within a threshold. If a layer is infrequent, its average refresh rate is disregarded in
-    // favor of a low refresh rate.
-    static constexpr size_t FREQUENT_LAYER_WINDOW_SIZE = 3;
-    static constexpr std::chrono::nanoseconds MAX_FREQUENT_LAYER_PERIOD_NS = 250ms;
-
-    /**
-     * Struct that keeps the information about the refresh rate for last
-     * HISTORY_SIZE frames. This is used to better determine the refresh rate
-     * for individual layers.
-     */
-    class RefreshRateHistory {
-    public:
-        explicit RefreshRateHistory(float highRefreshRate) : mHighRefreshRate(highRefreshRate) {}
-
-        void insertRefreshRate(float refreshRate) {
-            mElements.push_back(refreshRate);
-            if (mElements.size() > HISTORY_SIZE) {
-                mElements.pop_front();
-            }
-        }
-
-        float getRefreshRateAvg() const {
-            return mElements.empty() ? mHighRefreshRate : calculate_mean(mElements);
-        }
-
-        void clearHistory() { mElements.clear(); }
-
-    private:
-        const float mHighRefreshRate;
-
-        static constexpr size_t HISTORY_SIZE = 30;
-        std::deque<float> mElements;
-    };
-
-    /**
-     * Struct that keeps the information about the present time for last
-     * HISTORY_SIZE frames. This is used to better determine whether the given layer
-     * is still relevant and it's refresh rate should be considered.
-     */
-    class PresentTimeHistory {
-    public:
-        static constexpr size_t HISTORY_SIZE = 90;
-
-        void insertPresentTime(nsecs_t presentTime) {
-            mElements.push_back(presentTime);
-            if (mElements.size() > HISTORY_SIZE) {
-                mElements.pop_front();
-            }
-        }
-
-        // Returns whether the earliest present time is within the active threshold.
-        bool isRecentlyActive(nsecs_t now) const {
-            if (mElements.size() < 2) {
-                return false;
-            }
-
-            // The layer had to publish at least HISTORY_SIZE or HISTORY_DURATION of updates
-            if (mElements.size() < HISTORY_SIZE &&
-                mElements.back() - mElements.front() < HISTORY_DURATION.count()) {
-                return false;
-            }
-
-            return mElements.back() >= getActiveLayerThreshold(now);
-        }
-
-        bool isFrequent(nsecs_t now) const {
-            // Assume layer is infrequent if too few present times have been recorded.
-            if (mElements.size() < FREQUENT_LAYER_WINDOW_SIZE) {
-                return false;
-            }
-
-            // Layer is frequent if the earliest value in the window of most recent present times is
-            // within threshold.
-            const auto it = mElements.end() - FREQUENT_LAYER_WINDOW_SIZE;
-            const nsecs_t threshold = now - MAX_FREQUENT_LAYER_PERIOD_NS.count();
-            return *it >= threshold;
-        }
-
-        void clearHistory() { mElements.clear(); }
-
-    private:
-        std::deque<nsecs_t> mElements;
-        static constexpr std::chrono::nanoseconds HISTORY_DURATION = 1s;
-    };
-
-    friend class LayerHistoryTest;
-
-public:
-    LayerInfo(float lowRefreshRate, float highRefreshRate);
-
-    LayerInfo(const LayerInfo&) = delete;
-    LayerInfo& operator=(const LayerInfo&) = delete;
-
-    // Records the last requested oresent time. It also stores information about when
-    // the layer was last updated. If the present time is farther in the future than the
-    // updated time, the updated time is the present time.
-    void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now);
-
-    bool isRecentlyActive(nsecs_t now) const { return mPresentTimeHistory.isRecentlyActive(now); }
-    bool isFrequent(nsecs_t now) const { return mPresentTimeHistory.isFrequent(now); }
-
-    float getRefreshRate(nsecs_t now) const {
-        return isFrequent(now) ? mRefreshRateHistory.getRefreshRateAvg() : mLowRefreshRate;
-    }
-
-    // Return the last updated time. If the present time is farther in the future than the
-    // updated time, the updated time is the present time.
-    nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; }
-
-    void clearHistory() {
-        mRefreshRateHistory.clearHistory();
-        mPresentTimeHistory.clearHistory();
-    }
-
-private:
-    const float mLowRefreshRate;
-    const float mHighRefreshRate;
-
-    nsecs_t mLastUpdatedTime = 0;
-    nsecs_t mLastPresentTime = 0;
-    RefreshRateHistory mRefreshRateHistory{mHighRefreshRate};
-    PresentTimeHistory mPresentTimeHistory;
-};
-
-} // namespace scheduler
-} // namespace android
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
index 4ebab3e..2559eb4 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp
@@ -69,60 +69,6 @@
                               primaryRange.max, appRequestRange.min, appRequestRange.max);
 }
 
-const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(
-        const std::vector<LayerRequirement>& layers) const {
-    std::lock_guard lock(mLock);
-    int contentFramerate = 0;
-    int explicitContentFramerate = 0;
-    for (const auto& layer : layers) {
-        const auto desiredRefreshRateRound = round<int>(layer.desiredRefreshRate);
-        if (layer.vote == LayerVoteType::ExplicitDefault ||
-            layer.vote == LayerVoteType::ExplicitExactOrMultiple) {
-            if (desiredRefreshRateRound > explicitContentFramerate) {
-                explicitContentFramerate = desiredRefreshRateRound;
-            }
-        } else {
-            if (desiredRefreshRateRound > contentFramerate) {
-                contentFramerate = desiredRefreshRateRound;
-            }
-        }
-    }
-
-    if (explicitContentFramerate != 0) {
-        contentFramerate = explicitContentFramerate;
-    } else if (contentFramerate == 0) {
-        contentFramerate = round<int>(mMaxSupportedRefreshRate->getFps());
-    }
-    ATRACE_INT("ContentFPS", contentFramerate);
-
-    // Find the appropriate refresh rate with minimal error
-    auto iter = min_element(mPrimaryRefreshRates.cbegin(), mPrimaryRefreshRates.cend(),
-                            [contentFramerate](const auto& lhs, const auto& rhs) -> bool {
-                                return std::abs(lhs->fps - contentFramerate) <
-                                        std::abs(rhs->fps - contentFramerate);
-                            });
-
-    // Some content aligns better on higher refresh rate. For example for 45fps we should choose
-    // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't
-    // align well with both
-    const RefreshRate* bestSoFar = *iter;
-    constexpr float MARGIN = 0.05f;
-    float ratio = (*iter)->fps / contentFramerate;
-    if (std::abs(std::round(ratio) - ratio) > MARGIN) {
-        while (iter != mPrimaryRefreshRates.cend()) {
-            ratio = (*iter)->fps / contentFramerate;
-
-            if (std::abs(std::round(ratio) - ratio) <= MARGIN) {
-                bestSoFar = *iter;
-                break;
-            }
-            ++iter;
-        }
-    }
-
-    return *bestSoFar;
-}
-
 std::pair<nsecs_t, nsecs_t> RefreshRateConfigs::getDisplayFrames(nsecs_t layerPeriod,
                                                                  nsecs_t displayPeriod) const {
     auto [displayFramesQuot, displayFramesRem] = std::div(layerPeriod, displayPeriod);
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index 2ef8f0c..a5fadbf 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -236,10 +236,6 @@
         bool operator!=(const LayerRequirement& other) const { return !(*this == other); }
     };
 
-    // Returns the refresh rate that fits best to the given layers.
-    const RefreshRate& getRefreshRateForContent(const std::vector<LayerRequirement>& layers) const
-            EXCLUDES(mLock);
-
     // Global state describing signals that affect refresh rate choice.
     struct GlobalSignals {
         // Whether the user touched the screen recently. Used to apply touch boost.
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 3706631..1e00577 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -89,9 +89,8 @@
                                                 timerSlack.count(), vsyncMoveThreshold.count());
 }
 
-const char* toContentDetectionString(bool useContentDetection, bool useContentDetectionV2) {
-    if (!useContentDetection) return "off";
-    return useContentDetectionV2 ? "V2" : "V1";
+const char* toContentDetectionString(bool useContentDetection) {
+    return useContentDetection ? "on" : "off";
 }
 
 } // namespace
@@ -119,14 +118,13 @@
 Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback)
       : Scheduler(configs, callback,
                   {.supportKernelTimer = sysprop::support_kernel_idle_timer(false),
-                   .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false),
-                   .useContentDetectionV2 =
-                           base::GetBoolProperty("debug.sf.use_content_detection_v2"s, true)}) {}
+                   .useContentDetection = sysprop::use_content_detection_for_refresh_rate(false)}) {
+}
 
 Scheduler::Scheduler(const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& callback,
                      Options options)
       : Scheduler(createVsyncSchedule(options.supportKernelTimer), configs, callback,
-                  createLayerHistory(configs, options.useContentDetectionV2), options) {
+                  createLayerHistory(configs), options) {
     using namespace sysprop;
 
     const int setIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms"s, 0);
@@ -195,14 +193,10 @@
 }
 
 std::unique_ptr<LayerHistory> Scheduler::createLayerHistory(
-        const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2) {
+        const scheduler::RefreshRateConfigs& configs) {
     if (!configs.canSwitch()) return nullptr;
 
-    if (useContentDetectionV2) {
-        return std::make_unique<scheduler::impl::LayerHistoryV2>(configs);
-    }
-
-    return std::make_unique<scheduler::impl::LayerHistory>();
+    return std::make_unique<scheduler::impl::LayerHistoryV2>(configs);
 }
 
 std::unique_ptr<VSyncSource> Scheduler::makePrimaryDispSyncSource(
@@ -518,14 +512,6 @@
         // still need to be registered.
         mLayerHistory->registerLayer(layer, minFps, maxFps,
                                      scheduler::LayerHistory::LayerVoteType::Max);
-    } else if (!mOptions.useContentDetectionV2) {
-        // In V1 of content detection, all layers are registered as Heuristic (unless it's
-        // wallpaper).
-        const auto highFps =
-                layer->getWindowType() == InputWindowInfo::Type::WALLPAPER ? minFps : maxFps;
-
-        mLayerHistory->registerLayer(layer, minFps, highFps,
-                                     scheduler::LayerHistory::LayerVoteType::Heuristic);
     } else {
         if (layer->getWindowType() == InputWindowInfo::Type::WALLPAPER) {
             // Running Wallpaper at Min is considered as part of content detection.
@@ -564,8 +550,6 @@
             return;
         }
         mFeatures.contentRequirements = summary;
-        mFeatures.contentDetectionV1 =
-                !summary.empty() ? ContentDetectionState::On : ContentDetectionState::Off;
 
         scheduler::RefreshRateConfigs::GlobalSignals consideredSignals;
         newConfigId = calculateRefreshRateConfigIndexType(&consideredSignals);
@@ -672,8 +656,7 @@
     StringAppendF(&result, "+  Touch timer: %s\n",
                   mTouchTimer ? mTouchTimer->dump().c_str() : "off");
     StringAppendF(&result, "+  Content detection: %s %s\n\n",
-                  toContentDetectionString(mOptions.useContentDetection,
-                                           mOptions.useContentDetectionV2),
+                  toContentDetectionString(mOptions.useContentDetection),
                   mLayerHistory ? mLayerHistory->dump().c_str() : "(no layer history)");
 }
 
@@ -730,29 +713,6 @@
     const bool touchActive = mTouchTimer && mFeatures.touch == TouchState::Active;
     const bool idle = mIdleTimer && mFeatures.idleTimer == TimerState::Expired;
 
-    if (!mOptions.useContentDetectionV2) {
-        // As long as touch is active we want to be in performance mode.
-        if (touchActive) {
-            return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId();
-        }
-
-        // If timer has expired as it means there is no new content on the screen.
-        if (idle) {
-            if (consideredSignals) consideredSignals->idle = true;
-            return mRefreshRateConfigs.getMinRefreshRateByPolicy().getConfigId();
-        }
-
-        // If content detection is off we choose performance as we don't know the content fps.
-        if (mFeatures.contentDetectionV1 == ContentDetectionState::Off) {
-            // NOTE: V1 always calls this, but this is not a default behavior for V2.
-            return mRefreshRateConfigs.getMaxRefreshRateByPolicy().getConfigId();
-        }
-
-        // Content detection is on, find the appropriate refresh rate with minimal error
-        return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements)
-                .getConfigId();
-    }
-
     return mRefreshRateConfigs
             .getBestRefreshRate(mFeatures.contentRequirements, {.touch = touchActive, .idle = idle},
                                 consideredSignals)
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 4c86d26..936d96a 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -180,8 +180,6 @@
         bool supportKernelTimer;
         // Whether to use content detection at all.
         bool useContentDetection;
-        // Whether to use improved content detection.
-        bool useContentDetectionV2;
     };
 
     struct VsyncSchedule {
@@ -198,8 +196,7 @@
               std::unique_ptr<LayerHistory>, Options);
 
     static VsyncSchedule createVsyncSchedule(bool supportKernelIdleTimer);
-    static std::unique_ptr<LayerHistory> createLayerHistory(const scheduler::RefreshRateConfigs&,
-                                                            bool useContentDetectionV2);
+    static std::unique_ptr<LayerHistory> createLayerHistory(const scheduler::RefreshRateConfigs&);
 
     // Create a connection on the given EventThread.
     ConnectionHandle createConnection(std::unique_ptr<EventThread>);
@@ -267,7 +264,6 @@
     std::mutex mFeatureStateLock;
 
     struct {
-        ContentDetectionState contentDetectionV1 = ContentDetectionState::Off;
         TimerState idleTimer = TimerState::Reset;
         TouchState touch = TouchState::Inactive;
         TimerState displayPowerTimer = TimerState::Expired;