Merge "Extend PowerHalWrapper to support HIDL 1.2 and 1.3"
diff --git a/cmds/installd/otapreopt.rc b/cmds/installd/otapreopt.rc
index 059ae75..0bad0c5 100644
--- a/cmds/installd/otapreopt.rc
+++ b/cmds/installd/otapreopt.rc
@@ -5,4 +5,4 @@
     # The dalvik-cache was not moved itself, so as to restrict the rights of otapreopt_slot.
     # But now the relabeling is annoying as there is no force option available here. So
     # explicitly list all the ISAs we know.
-    restorecon_recursive /data/dalvik-cache/arm /data/dalvik-cache/arm64 /data/dalvik-cache/mips /data/dalvik-cache/mips64 /data/dalvik-cache/x86 /data/dalvik-cache/x86_64
+    restorecon_recursive /data/dalvik-cache/arm /data/dalvik-cache/arm64 /data/dalvik-cache/riscv64 /data/dalvik-cache/x86 /data/dalvik-cache/x86_64
diff --git a/libs/input/Android.bp b/libs/input/Android.bp
index 29e02cf..34ef7b4 100644
--- a/libs/input/Android.bp
+++ b/libs/input/Android.bp
@@ -89,7 +89,6 @@
             shared_libs: [
                 "libutils",
                 "libbinder",
-                "libui",
             ],
 
             static_libs: [
diff --git a/libs/input/tests/Android.bp b/libs/input/tests/Android.bp
index c53811a..5aae37d 100644
--- a/libs/input/tests/Android.bp
+++ b/libs/input/tests/Android.bp
@@ -10,6 +10,7 @@
 
 cc_test {
     name: "libinput_tests",
+    host_supported: true,
     srcs: [
         "IdGenerator_test.cpp",
         "InputChannel_test.cpp",
@@ -24,6 +25,7 @@
     static_libs: [
         "libgui_window_info_static",
         "libinput",
+        "libui-types",
     ],
     cflags: [
         "-Wall",
@@ -35,11 +37,13 @@
         "libbinder",
         "libcutils",
         "liblog",
-        "libui",
         "libutils",
         "libvintf",
     ],
     data: ["data/*"],
+    test_options: {
+        unit_test: true,
+    },
     test_suites: ["device-tests"],
 }
 
@@ -60,7 +64,6 @@
         "libcutils",
         "libutils",
         "libbinder",
-        "libui",
         "libbase",
     ],
 }
diff --git a/libs/input/tests/InputDevice_test.cpp b/libs/input/tests/InputDevice_test.cpp
index e872fa4..2344463 100644
--- a/libs/input/tests/InputDevice_test.cpp
+++ b/libs/input/tests/InputDevice_test.cpp
@@ -65,6 +65,9 @@
     }
 
     void SetUp() override {
+#if !defined(__ANDROID__)
+        GTEST_SKIP() << "b/253299089 Generic files are currently read directly from device.";
+#endif
         loadKeyLayout("Generic");
         loadKeyCharacterMap("Generic");
     }
@@ -131,6 +134,9 @@
 }
 
 TEST(InputDeviceKeyLayoutTest, DoesNotLoadWhenRequiredKernelConfigIsMissing) {
+#if !defined(__ANDROID__)
+    GTEST_SKIP() << "Can't check kernel configs on host";
+#endif
     std::string klPath = base::GetExecutableDirectory() + "/data/kl_with_required_fake_config.kl";
     base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(klPath);
     ASSERT_FALSE(ret.ok()) << "Should not be able to load KeyLayout at " << klPath;
@@ -139,6 +145,9 @@
 }
 
 TEST(InputDeviceKeyLayoutTest, LoadsWhenRequiredKernelConfigIsPresent) {
+#if !defined(__ANDROID__)
+    GTEST_SKIP() << "Can't check kernel configs on host";
+#endif
     std::string klPath = base::GetExecutableDirectory() + "/data/kl_with_required_real_config.kl";
     base::Result<std::shared_ptr<KeyLayoutMap>> ret = KeyLayoutMap::load(klPath);
     ASSERT_TRUE(ret.ok()) << "Cannot load KeyLayout at " << klPath;
diff --git a/libs/jpegrecoverymap/OWNERS b/libs/jpegrecoverymap/OWNERS
index 6ace354..133af5b 100644
--- a/libs/jpegrecoverymap/OWNERS
+++ b/libs/jpegrecoverymap/OWNERS
@@ -1,3 +1,4 @@
 arifdikici@google.com
+deakin@google.com
 dichenzhang@google.com
 kyslov@google.com
\ No newline at end of file
diff --git a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
index c5f8e9a..6949f85 100644
--- a/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
+++ b/libs/jpegrecoverymap/include/jpegrecoverymap/recoverymap.h
@@ -16,61 +16,100 @@
 
 namespace android::recoverymap {
 
+/*
+ * Holds information for uncompressed image or recovery map.
+ */
+struct jpeg_r_uncompressed_struct {
+    // Pointer to the data location.
+    void* data;
+    // Width of the recovery map or image in pixels.
+    int width;
+    // Height of the recovery map or image in pixels.
+    int height;
+};
+
+/*
+ * Holds information for compressed image or recovery map.
+ */
+struct jpeg_r_compressed_struct {
+    // Pointer to the data location.
+    void* data;
+    // Data length;
+    int length;
+};
+
+typedef struct jpeg_r_uncompressed_struct* j_r_uncompressed_ptr;
+typedef struct jpeg_r_compressed_struct* j_r_compressed_ptr;
+
 class RecoveryMap {
 public:
     /*
      * This method is called in the decoding pipeline. It will decode the recovery map.
      *
-     * input: compressed recovery map
-     * output: uncompressed recovery map
+     * @param compressed_recovery_map compressed recovery map
+     * @param dest decoded recover map
+     * @return true if decoding succeeds
      */
-    void* decodeRecoveryMap(void* compressed_recovery_map);
+    bool decodeRecoveryMap(j_r_compressed_ptr compressed_recovery_map,
+                           j_r_uncompressed_ptr dest);
 
     /*
      * This method is called in the encoding pipeline. It will encode the recovery map.
      *
-     * input: uncompressed recovery map
-     * output: compressed recovery map
+     * @param uncompressed_recovery_map uncompressed recovery map
+     * @param dest encoded recover map
+     * @return true if encoding succeeds
      */
-    void* encodeRecoveryMap(void* uncompressed_recovery_map);
+    bool encodeRecoveryMap(j_r_uncompressed_ptr uncompressed_recovery_map,
+                           j_r_compressed_ptr dest);
 
     /*
      * This method is called in the encoding pipeline. It will take the uncompressed 8-bit and
      * 10-bit yuv images as input, and calculate the uncompressed recovery map.
      *
-     * input: uncompressed yuv_420 image, uncompressed p010 image
-     * output: uncompressed recovery map
+     * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
+     * @param uncompressed_p010_image uncompressed HDR image in P010 color format
+     * @param dest recover map
+     * @return true if calculation succeeds
      */
-    void* generateRecoveryMap(void* uncompressed_yuv_420_image, void* uncompressed_p010_image);
+    bool generateRecoveryMap(j_r_uncompressed_ptr uncompressed_yuv_420_image,
+                             j_r_uncompressed_ptr uncompressed_p010_image,
+                             j_r_uncompressed_ptr dest);
 
     /*
      * This method is called in the decoding pipeline. It will take the uncompressed (decoded)
-     * 8-bit yuv image and the uncompressed(decoded) recovery map as input, and calculate the
+     * 8-bit yuv image and the uncompressed (decoded) recovery map as input, and calculate the
      * 10-bit recovered image (in p010 color format).
      *
-     * input: uncompressed yuv_420 image, uncompressed recovery map
-     * output: uncompress p010 image
+     * @param uncompressed_yuv_420_image uncompressed SDR image in YUV_420 color format
+     * @param uncompressed_recovery_map uncompressed recovery map
+     * @param dest reconstructed HDR image
+     * @return true if calculation succeeds
      */
-    void* applyRecoveryMap(void* uncompressed_yuv_420_image, void* uncompressed_recovery_map);
+    bool applyRecoveryMap(j_r_uncompressed_ptr uncompressed_yuv_420_image,
+                          j_r_uncompressed_ptr uncompressed_recovery_map,
+                          j_r_uncompressed_ptr dest);
 
     /*
      * This method is called in the decoding pipeline. It will read XMP metadata to find the start
      * position of the compressed recovery map, and will extract the compressed recovery map.
      *
-     * input: compressed JPEG-G image (8-bit JPEG + compressed recovery map)
-     * output: compressed recovery map
+     * @param compressed_jpeg_r_image compressed JPEG_R image
+     * @return compressed recovery map
      */
-    void* extractRecoveryMap(void* compressed_jpeg_g_image);
+    j_r_compressed_ptr extractRecoveryMap(void* compressed_jpeg_r_image);
 
     /*
      * This method is called in the encoding pipeline. It will take the standard 8-bit JPEG image
      * and the compressed recovery map as input, and update the XMP metadata with the end of JPEG
      * marker, and append the compressed gian map after the JPEG.
      *
-     * input: compressed 8-bit JPEG image (standard JPEG), compressed recovery map
-     * output: compressed JPEG-G image (8-bit JPEG + compressed recovery map)
+     * @param compressed_jpeg_image compressed 8-bit JPEG image
+     * @param compress_recovery_map compressed recover map
+     * @return compressed JPEG_R image
      */
-    void* appendRecoveryMap(void* compressed_jpeg_image, void* compressed_recovery_map);
+    void* appendRecoveryMap(void* compressed_jpeg_image,
+                            j_r_compressed_ptr compressed_recovery_map);
 };
 
-} // namespace android::recoverymap
\ No newline at end of file
+} // namespace android::recoverymap
diff --git a/libs/jpegrecoverymap/recoverymap.cpp b/libs/jpegrecoverymap/recoverymap.cpp
index 3e95a31..bd92652 100644
--- a/libs/jpegrecoverymap/recoverymap.cpp
+++ b/libs/jpegrecoverymap/recoverymap.cpp
@@ -18,8 +18,54 @@
 
 namespace android::recoverymap {
 
-void* RecoveryMap::decodeRecoveryMap(void* compressed_recovery_map) {
-  if (compressed_recovery_map == nullptr) {
+bool RecoveryMap::decodeRecoveryMap(j_r_compressed_ptr compressed_recovery_map,
+                                    j_r_uncompressed_ptr dest) {
+  if (compressed_recovery_map == nullptr || dest == nullptr) {
+    return false;
+  }
+
+  // TBD
+  return true;
+}
+
+bool RecoveryMap::encodeRecoveryMap(j_r_uncompressed_ptr uncompressed_recovery_map,
+                                    j_r_compressed_ptr dest) {
+  if (uncompressed_recovery_map == nullptr || dest == nullptr) {
+    return false;
+  }
+
+  // TBD
+  return true;
+}
+
+bool RecoveryMap::generateRecoveryMap(j_r_uncompressed_ptr uncompressed_yuv_420_image,
+                                      j_r_uncompressed_ptr uncompressed_p010_image,
+                                      j_r_uncompressed_ptr dest) {
+  if (uncompressed_yuv_420_image == nullptr
+   || uncompressed_p010_image == nullptr
+   || dest == nullptr) {
+    return false;
+  }
+
+  // TBD
+  return true;
+}
+
+bool RecoveryMap::applyRecoveryMap(j_r_uncompressed_ptr uncompressed_yuv_420_image,
+                                   j_r_uncompressed_ptr uncompressed_recovery_map,
+                                   j_r_uncompressed_ptr dest) {
+  if (uncompressed_yuv_420_image == nullptr
+   || uncompressed_recovery_map == nullptr
+   || dest == nullptr) {
+    return false;
+  }
+
+  // TBD
+  return true;
+}
+
+j_r_compressed_ptr RecoveryMap::extractRecoveryMap(void* compressed_jpeg_r_image) {
+  if (compressed_jpeg_r_image == nullptr) {
     return nullptr;
   }
 
@@ -27,45 +73,8 @@
   return nullptr;
 }
 
-void* RecoveryMap::encodeRecoveryMap(void* uncompressed_recovery_map) {
-  if (uncompressed_recovery_map == nullptr) {
-    return nullptr;
-  }
-
-  // TBD
-  return nullptr;
-}
-
-void* RecoveryMap::generateRecoveryMap(
-    void* uncompressed_yuv_420_image, void* uncompressed_p010_image) {
-  if (uncompressed_yuv_420_image == nullptr || uncompressed_p010_image == nullptr) {
-    return nullptr;
-  }
-
-  // TBD
-  return nullptr;
-}
-
-void* RecoveryMap::applyRecoveryMap(
-    void* uncompressed_yuv_420_image, void* uncompressed_recovery_map) {
-  if (uncompressed_yuv_420_image == nullptr || uncompressed_recovery_map == nullptr) {
-    return nullptr;
-  }
-
-  // TBD
-  return nullptr;
-}
-
-void* RecoveryMap::extractRecoveryMap(void* compressed_jpeg_g_image) {
-  if (compressed_jpeg_g_image == nullptr) {
-    return nullptr;
-  }
-
-  // TBD
-  return nullptr;
-}
-
-void* RecoveryMap::appendRecoveryMap(void* compressed_jpeg_image, void* compressed_recovery_map) {
+void* RecoveryMap::appendRecoveryMap(void* compressed_jpeg_image,
+                                     j_r_compressed_ptr compressed_recovery_map) {
   if (compressed_jpeg_image == nullptr || compressed_recovery_map == nullptr) {
     return nullptr;
   }
diff --git a/services/surfaceflinger/Display/DisplayMap.h b/services/surfaceflinger/Display/DisplayMap.h
index baf0da9..0d59706 100644
--- a/services/surfaceflinger/Display/DisplayMap.h
+++ b/services/surfaceflinger/Display/DisplayMap.h
@@ -17,6 +17,7 @@
 #pragma once
 
 #include <ftl/small_map.h>
+#include <ftl/small_vector.h>
 
 namespace android::display {
 
@@ -28,4 +29,7 @@
 template <typename Key, typename Value>
 using PhysicalDisplayMap = ftl::SmallMap<Key, Value, 3>;
 
+template <typename T>
+using PhysicalDisplayVector = ftl::SmallVector<T, 3>;
+
 } // namespace android::display
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 12949d6..30f2c27 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -26,6 +26,7 @@
 #include <android/hardware/configstore/1.1/ISurfaceFlingerConfigs.h>
 #include <configstore/Utils.h>
 #include <ftl/fake_guard.h>
+#include <ftl/small_map.h>
 #include <gui/WindowInfo.h>
 #include <system/window.h>
 #include <utils/Timers.h>
@@ -41,6 +42,7 @@
 
 #include "../Layer.h"
 #include "DispSyncSource.h"
+#include "Display/DisplayMap.h"
 #include "EventThread.h"
 #include "FrameRateOverrideMappings.h"
 #include "OneShotTimer.h"
@@ -56,39 +58,6 @@
         }                                                            \
     } while (false)
 
-namespace {
-
-using android::Fps;
-using android::FpsApproxEqual;
-using android::FpsHash;
-using android::scheduler::AggregatedFpsScore;
-using android::scheduler::RefreshRateRankingsAndSignals;
-
-// Returns the aggregated score per Fps for the RefreshRateRankingsAndSignals sourced.
-auto getAggregatedScoresPerFps(
-        const std::vector<RefreshRateRankingsAndSignals>& refreshRateRankingsAndSignalsPerDisplay)
-        -> std::unordered_map<Fps, AggregatedFpsScore, FpsHash, FpsApproxEqual> {
-    std::unordered_map<Fps, AggregatedFpsScore, FpsHash, FpsApproxEqual> aggregatedScoresPerFps;
-
-    for (const auto& refreshRateRankingsAndSignal : refreshRateRankingsAndSignalsPerDisplay) {
-        const auto& refreshRateRankings = refreshRateRankingsAndSignal.refreshRateRankings;
-
-        std::for_each(refreshRateRankings.begin(), refreshRateRankings.end(), [&](const auto& it) {
-            const auto [score, result] =
-                    aggregatedScoresPerFps.try_emplace(it.displayModePtr->getFps(),
-                                                       AggregatedFpsScore{it.score,
-                                                                          /* numDisplays */ 1});
-            if (!result) { // update
-                score->second.totalScore += it.score;
-                score->second.numDisplays++;
-            }
-        });
-    }
-    return aggregatedScoresPerFps;
-}
-
-} // namespace
-
 namespace android::scheduler {
 
 Scheduler::Scheduler(ICompositor& compositor, ISchedulerCallback& callback, FeatureFlags features)
@@ -157,6 +126,15 @@
     mRefreshRateConfigs->startIdleTimer();
 }
 
+void Scheduler::registerDisplay(sp<const DisplayDevice> display) {
+    const bool ok = mDisplays.try_emplace(display->getPhysicalId(), std::move(display)).second;
+    ALOGE_IF(!ok, "%s: Duplicate display", __func__);
+}
+
+void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
+    mDisplays.erase(displayId);
+}
+
 void Scheduler::run() {
     while (true) {
         waitMessage();
@@ -711,66 +689,86 @@
     return consideredSignals;
 }
 
-void Scheduler::registerDisplay(const sp<const DisplayDevice>& display) {
-    const bool ok = mDisplays.try_emplace(display->getPhysicalId(), display).second;
-    ALOGE_IF(!ok, "Duplicate display registered");
-}
-
-void Scheduler::unregisterDisplay(PhysicalDisplayId displayId) {
-    mDisplays.erase(displayId);
-}
-
 std::vector<DisplayModeConfig> Scheduler::getBestDisplayModeConfigs() const {
     ATRACE_CALL();
 
-    std::vector<RefreshRateRankingsAndSignals> refreshRateRankingsAndSignalsPerDisplay;
-    refreshRateRankingsAndSignalsPerDisplay.reserve(mDisplays.size());
+    using Rankings = std::pair<std::vector<RefreshRateRanking>, GlobalSignals>;
+    display::PhysicalDisplayVector<Rankings> perDisplayRankings;
+
+    // Tallies the score of a refresh rate across `displayCount` displays.
+    struct RefreshRateTally {
+        explicit RefreshRateTally(float score) : score(score) {}
+
+        float score;
+        size_t displayCount = 1;
+    };
+
+    // Chosen to exceed a typical number of refresh rates across displays.
+    constexpr size_t kStaticCapacity = 8;
+    ftl::SmallMap<Fps, RefreshRateTally, kStaticCapacity, FpsApproxEqual> refreshRateTallies;
+
+    const auto globalSignals = makeGlobalSignals();
 
     for (const auto& [id, display] : mDisplays) {
-        const auto [rankings, signals] =
+        auto [rankings, signals] =
                 display->holdRefreshRateConfigs()
-                        ->getRankedRefreshRates(mPolicy.contentRequirements, makeGlobalSignals());
+                        ->getRankedRefreshRates(mPolicy.contentRequirements, globalSignals);
 
-        refreshRateRankingsAndSignalsPerDisplay.emplace_back(
-                RefreshRateRankingsAndSignals{rankings, signals});
+        for (const auto& [modePtr, score] : rankings) {
+            const auto [it, inserted] = refreshRateTallies.try_emplace(modePtr->getFps(), score);
+
+            if (!inserted) {
+                auto& tally = it->second;
+                tally.score += score;
+                tally.displayCount++;
+            }
+        }
+
+        perDisplayRankings.emplace_back(std::move(rankings), signals);
     }
 
-    // FPS and their Aggregated score.
-    std::unordered_map<Fps, AggregatedFpsScore, FpsHash, FpsApproxEqual> aggregatedScoresPerFps =
-            getAggregatedScoresPerFps(refreshRateRankingsAndSignalsPerDisplay);
+    auto maxScoreIt = refreshRateTallies.cbegin();
 
-    auto maxScoreIt = aggregatedScoresPerFps.cbegin();
-    // Selects the max Fps that is present on all the displays.
-    for (auto it = aggregatedScoresPerFps.cbegin(); it != aggregatedScoresPerFps.cend(); ++it) {
-        const auto [fps, aggregatedScore] = *it;
-        if (aggregatedScore.numDisplays == mDisplays.size() &&
-            aggregatedScore.totalScore >= maxScoreIt->second.totalScore) {
-            maxScoreIt = it;
+    // Find the first refresh rate common to all displays.
+    while (maxScoreIt != refreshRateTallies.cend() &&
+           maxScoreIt->second.displayCount != mDisplays.size()) {
+        ++maxScoreIt;
+    }
+
+    if (maxScoreIt != refreshRateTallies.cend()) {
+        // Choose the highest refresh rate common to all displays, if any.
+        for (auto it = maxScoreIt + 1; it != refreshRateTallies.cend(); ++it) {
+            const auto [fps, tally] = *it;
+
+            if (tally.displayCount == mDisplays.size() && tally.score > maxScoreIt->second.score) {
+                maxScoreIt = it;
+            }
         }
     }
-    return getDisplayModeConfigsForTheChosenFps(maxScoreIt->first,
-                                                refreshRateRankingsAndSignalsPerDisplay);
-}
 
-std::vector<DisplayModeConfig> Scheduler::getDisplayModeConfigsForTheChosenFps(
-        Fps chosenFps,
-        const std::vector<RefreshRateRankingsAndSignals>& refreshRateRankingsAndSignalsPerDisplay)
-        const {
+    const std::optional<Fps> chosenFps = maxScoreIt != refreshRateTallies.cend()
+            ? std::make_optional(maxScoreIt->first)
+            : std::nullopt;
+
     std::vector<DisplayModeConfig> displayModeConfigs;
     displayModeConfigs.reserve(mDisplays.size());
+
     using fps_approx_ops::operator==;
-    std::for_each(refreshRateRankingsAndSignalsPerDisplay.begin(),
-                  refreshRateRankingsAndSignalsPerDisplay.end(),
-                  [&](const auto& refreshRateRankingsAndSignal) {
-                      for (const auto& ranking : refreshRateRankingsAndSignal.refreshRateRankings) {
-                          if (ranking.displayModePtr->getFps() == chosenFps) {
-                              displayModeConfigs.emplace_back(
-                                      DisplayModeConfig{refreshRateRankingsAndSignal.globalSignals,
-                                                        ranking.displayModePtr});
-                              break;
-                          }
-                      }
-                  });
+
+    for (const auto& [rankings, signals] : perDisplayRankings) {
+        if (!chosenFps) {
+            displayModeConfigs.emplace_back(signals, rankings.front().displayModePtr);
+            continue;
+        }
+
+        for (const auto& ranking : rankings) {
+            const auto& modePtr = ranking.displayModePtr;
+            if (modePtr->getFps() == *chosenFps) {
+                displayModeConfigs.emplace_back(signals, modePtr);
+                break;
+            }
+        }
+    }
     return displayModeConfigs;
 }
 
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index 25fa714..6633b05 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -33,11 +33,12 @@
 #include <ui/GraphicTypes.h>
 #pragma clang diagnostic pop // ignored "-Wconversion -Wextra"
 
-#include <DisplayDevice.h>
 #include <scheduler/Features.h>
 #include <scheduler/Time.h>
+#include <ui/DisplayId.h>
 
 #include "Display/DisplayMap.h"
+#include "DisplayDevice.h"
 #include "EventThread.h"
 #include "FrameRateOverrideMappings.h"
 #include "LayerHistory.h"
@@ -108,19 +109,6 @@
     ~ISchedulerCallback() = default;
 };
 
-// Holds the total score of the FPS and
-// number of displays the FPS is found in.
-struct AggregatedFpsScore {
-    float totalScore;
-    size_t numDisplays;
-};
-
-// Represents the RefreshRateRankings and GlobalSignals for the selected RefreshRateRankings.
-struct RefreshRateRankingsAndSignals {
-    std::vector<RefreshRateRanking> refreshRateRankings;
-    GlobalSignals globalSignals;
-};
-
 class Scheduler : android::impl::MessageQueue {
     using Impl = android::impl::MessageQueue;
 
@@ -132,6 +120,9 @@
     void setRefreshRateConfigs(std::shared_ptr<RefreshRateConfigs>)
             EXCLUDES(mRefreshRateConfigsLock);
 
+    void registerDisplay(sp<const DisplayDevice>);
+    void unregisterDisplay(PhysicalDisplayId);
+
     void run();
 
     void createVsyncSchedule(FeatureFlags);
@@ -257,9 +248,6 @@
         return mLayerHistory.getLayerFramerate(now, id);
     }
 
-    void registerDisplay(const sp<const DisplayDevice>&);
-    void unregisterDisplay(PhysicalDisplayId);
-
 private:
     friend class TestableScheduler;
 
@@ -293,10 +281,6 @@
     // Returns the best display mode per display.
     std::vector<DisplayModeConfig> getBestDisplayModeConfigs() const REQUIRES(mPolicyLock);
 
-    // Returns the list of DisplayModeConfigs per display for the chosenFps.
-    std::vector<DisplayModeConfig> getDisplayModeConfigsForTheChosenFps(
-            Fps chosenFps, const std::vector<RefreshRateRankingsAndSignals>&) const;
-
     GlobalSignals makeGlobalSignals() const REQUIRES(mPolicyLock);
 
     bool updateFrameRateOverrides(GlobalSignals, Fps displayRefreshRate) REQUIRES(mPolicyLock);
@@ -344,9 +328,7 @@
 
     mutable std::mutex mPolicyLock;
 
-    // Holds the Physical displays registered through the SurfaceFlinger, used for making
-    // the refresh rate selections.
-    display::PhysicalDisplayMap<PhysicalDisplayId, const sp<const DisplayDevice>> mDisplays;
+    display::PhysicalDisplayMap<PhysicalDisplayId, sp<const DisplayDevice>> mDisplays;
 
     struct Policy {
         // Policy for choosing the display mode.
diff --git a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h
index 2c77142..bd4f409 100644
--- a/services/surfaceflinger/Scheduler/include/scheduler/Fps.h
+++ b/services/surfaceflinger/Scheduler/include/scheduler/Fps.h
@@ -138,10 +138,6 @@
     bool operator()(Fps lhs, Fps rhs) const { return isApproxEqual(lhs, rhs); }
 };
 
-struct FpsHash {
-    size_t operator()(Fps fps) const { return std::hash<nsecs_t>()(fps.getPeriodNsecs()); }
-};
-
 inline std::string to_string(Fps fps) {
     return base::StringPrintf("%.2f Hz", fps.getValue());
 }
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index 8b91c67..e0b508a 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -120,51 +120,6 @@
     });
 }
 
-sp<DisplayDevice> DisplayTransactionTest::injectDefaultInternalDisplay(
-        std::function<void(FakeDisplayDeviceInjector&)> injectExtra) {
-    constexpr PhysicalDisplayId DEFAULT_DISPLAY_ID = PhysicalDisplayId::fromPort(255u);
-    constexpr int DEFAULT_DISPLAY_WIDTH = 1080;
-    constexpr int DEFAULT_DISPLAY_HEIGHT = 1920;
-    constexpr HWDisplayId DEFAULT_DISPLAY_HWC_DISPLAY_ID = 0;
-
-    // The DisplayDevice is required to have a framebuffer (behind the
-    // ANativeWindow interface) which uses the actual hardware display
-    // size.
-    EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-            .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
-    EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-            .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_HEIGHT), Return(0)));
-    EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT));
-    EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT));
-    EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64));
-    EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(AnyNumber());
-
-    auto compositionDisplay =
-            compositionengine::impl::createDisplay(mFlinger.getCompositionEngine(),
-                                                   compositionengine::DisplayCreationArgsBuilder()
-                                                           .setId(DEFAULT_DISPLAY_ID)
-                                                           .setPixels({DEFAULT_DISPLAY_WIDTH,
-                                                                       DEFAULT_DISPLAY_HEIGHT})
-                                                           .setPowerAdvisor(&mPowerAdvisor)
-                                                           .build());
-
-    constexpr bool kIsPrimary = true;
-    auto injector = FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
-                                              ui::DisplayConnectionType::Internal,
-                                              DEFAULT_DISPLAY_HWC_DISPLAY_ID, kIsPrimary);
-
-    injector.setNativeWindow(mNativeWindow);
-    if (injectExtra) {
-        injectExtra(injector);
-    }
-
-    auto displayDevice = injector.inject();
-
-    Mock::VerifyAndClear(mNativeWindow.get());
-
-    return displayDevice;
-}
-
 bool DisplayTransactionTest::hasPhysicalHwcDisplay(HWDisplayId hwcDisplayId) const {
     const auto& map = mFlinger.hwcPhysicalDisplayIdMap();
 
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
index 9cceb5e..19c7d5c 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTestHelpers.h
@@ -42,6 +42,7 @@
 #include <renderengine/mock/RenderEngine.h>
 #include <ui/DebugUtils.h>
 
+#include "FakeDisplayInjector.h"
 #include "TestableScheduler.h"
 #include "TestableSurfaceFlinger.h"
 #include "mock/DisplayHardware/MockComposer.h"
@@ -88,8 +89,11 @@
     void injectMockComposer(int virtualDisplayCount);
     void injectFakeBufferQueueFactory();
     void injectFakeNativeWindowSurfaceFactory();
+
     sp<DisplayDevice> injectDefaultInternalDisplay(
-            std::function<void(TestableSurfaceFlinger::FakeDisplayDeviceInjector&)>);
+            std::function<void(TestableSurfaceFlinger::FakeDisplayDeviceInjector&)> injectExtra) {
+        return mFakeDisplayInjector.injectInternalDisplay(injectExtra);
+    }
 
     // --------------------------------------------------------------------
     // Postcondition helpers
@@ -114,6 +118,8 @@
     sp<GraphicBuffer> mBuffer = sp<GraphicBuffer>::make();
     Hwc2::mock::PowerAdvisor mPowerAdvisor;
 
+    FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow};
+
     // These mocks are created by the test, but are destroyed by SurfaceFlinger
     // by virtue of being stored into a std::unique_ptr. However we still need
     // to keep a reference to them for use in setting up call expectations.
diff --git a/services/surfaceflinger/tests/unittests/FakeDisplayInjector.h b/services/surfaceflinger/tests/unittests/FakeDisplayInjector.h
index 81b420c..6ee4b9b 100644
--- a/services/surfaceflinger/tests/unittests/FakeDisplayInjector.h
+++ b/services/surfaceflinger/tests/unittests/FakeDisplayInjector.h
@@ -27,49 +27,54 @@
 using FakeDisplayDeviceInjector = TestableSurfaceFlinger::FakeDisplayDeviceInjector;
 using android::hardware::graphics::composer::hal::HWDisplayId;
 using android::Hwc2::mock::PowerAdvisor;
-using testing::_;
-using testing::AnyNumber;
-using testing::DoAll;
-using testing::Mock;
-using testing::ResultOf;
-using testing::Return;
-using testing::SetArgPointee;
+
+struct FakeDisplayInjectorArgs {
+    uint8_t port = 255u;
+    HWDisplayId hwcDisplayId = 0;
+    bool isPrimary = true;
+};
 
 class FakeDisplayInjector {
 public:
-    sp<DisplayDevice> injectDefaultInternalDisplay(
-            const std::function<void(FakeDisplayDeviceInjector&)>& injectExtra,
-            TestableSurfaceFlinger& flinger, uint8_t port = 255u) const {
-        constexpr int DEFAULT_DISPLAY_WIDTH = 1080;
-        constexpr int DEFAULT_DISPLAY_HEIGHT = 1920;
-        constexpr HWDisplayId DEFAULT_DISPLAY_HWC_DISPLAY_ID = 0;
+    FakeDisplayInjector(TestableSurfaceFlinger& flinger, Hwc2::mock::PowerAdvisor& powerAdvisor,
+                        sp<mock::NativeWindow> nativeWindow)
+          : mFlinger(flinger), mPowerAdvisor(powerAdvisor), mNativeWindow(nativeWindow) {}
 
-        const PhysicalDisplayId physicalDisplayId = PhysicalDisplayId::fromPort(port);
+    sp<DisplayDevice> injectInternalDisplay(
+            const std::function<void(FakeDisplayDeviceInjector&)>& injectExtra,
+            FakeDisplayInjectorArgs args = {}) {
+        using testing::_;
+        using testing::AnyNumber;
+        using testing::DoAll;
+        using testing::Mock;
+        using testing::Return;
+        using testing::SetArgPointee;
+
+        constexpr ui::Size kResolution = {1080, 1920};
 
         // The DisplayDevice is required to have a framebuffer (behind the
         // ANativeWindow interface) which uses the actual hardware display
         // size.
         EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_WIDTH, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_WIDTH), Return(0)));
+                .WillRepeatedly(DoAll(SetArgPointee<1>(kResolution.getWidth()), Return(0)));
         EXPECT_CALL(*mNativeWindow, query(NATIVE_WINDOW_HEIGHT, _))
-                .WillRepeatedly(DoAll(SetArgPointee<1>(DEFAULT_DISPLAY_HEIGHT), Return(0)));
+                .WillRepeatedly(DoAll(SetArgPointee<1>(kResolution.getHeight()), Return(0)));
         EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_BUFFERS_FORMAT));
         EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_CONNECT));
         EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_SET_USAGE64));
         EXPECT_CALL(*mNativeWindow, perform(NATIVE_WINDOW_API_DISCONNECT)).Times(AnyNumber());
 
         auto compositionDisplay = compositionengine::impl::
-                createDisplay(flinger.getCompositionEngine(),
+                createDisplay(mFlinger.getCompositionEngine(),
                               compositionengine::DisplayCreationArgsBuilder()
-                                      .setId(physicalDisplayId)
-                                      .setPixels({DEFAULT_DISPLAY_WIDTH, DEFAULT_DISPLAY_HEIGHT})
-                                      .setPowerAdvisor(mPowerAdvisor)
+                                      .setId(PhysicalDisplayId::fromPort(args.port))
+                                      .setPixels(kResolution)
+                                      .setPowerAdvisor(&mPowerAdvisor)
                                       .build());
 
-        constexpr bool kIsPrimary = true;
-        auto injector = FakeDisplayDeviceInjector(flinger, compositionDisplay,
+        auto injector = FakeDisplayDeviceInjector(mFlinger, compositionDisplay,
                                                   ui::DisplayConnectionType::Internal,
-                                                  DEFAULT_DISPLAY_HWC_DISPLAY_ID, kIsPrimary);
+                                                  args.hwcDisplayId, args.isPrimary);
 
         injector.setNativeWindow(mNativeWindow);
         if (injectExtra) {
@@ -83,8 +88,9 @@
         return displayDevice;
     }
 
-    sp<mock::NativeWindow> mNativeWindow = sp<mock::NativeWindow>::make();
-    PowerAdvisor* mPowerAdvisor = new PowerAdvisor();
+    TestableSurfaceFlinger& mFlinger;
+    Hwc2::mock::PowerAdvisor& mPowerAdvisor;
+    sp<mock::NativeWindow> mNativeWindow;
 };
 
-} // namespace android
\ No newline at end of file
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
index 406d2bc..392398d 100644
--- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
+++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp
@@ -76,9 +76,12 @@
     ConnectionHandle mConnectionHandle;
     MockEventThread* mEventThread;
     sp<MockEventThreadConnection> mEventThreadConnection;
-    FakeDisplayInjector mFakeDisplayInjector;
 
     TestableSurfaceFlinger mFlinger;
+    Hwc2::mock::PowerAdvisor mPowerAdvisor;
+    sp<android::mock::NativeWindow> mNativeWindow = sp<android::mock::NativeWindow>::make();
+
+    FakeDisplayInjector mFakeDisplayInjector{mFlinger, mPowerAdvisor, mNativeWindow};
 };
 
 SchedulerTest::SchedulerTest() {
@@ -226,11 +229,10 @@
 }
 
 TEST_F(SchedulerTest, chooseRefreshRateForContentSelectsMaxRefreshRate) {
-    auto display = mFakeDisplayInjector.injectDefaultInternalDisplay(
-            [&](FakeDisplayDeviceInjector& injector) {
+    auto display =
+            mFakeDisplayInjector.injectInternalDisplay([&](FakeDisplayDeviceInjector& injector) {
                 injector.setDisplayModes(makeModes(kMode60_1, kMode120_1), kMode60_1->getId());
-            },
-            mFlinger);
+            });
 
     mScheduler->registerDisplay(display);
     mScheduler->setRefreshRateConfigs(display->holdRefreshRateConfigs());
@@ -255,11 +257,11 @@
 }
 
 TEST_F(SchedulerTest, getBestDisplayMode_singleDisplay) {
-    auto display = mFakeDisplayInjector.injectDefaultInternalDisplay(
-            [&](FakeDisplayDeviceInjector& injector) {
+    auto display =
+            mFakeDisplayInjector.injectInternalDisplay([&](FakeDisplayDeviceInjector& injector) {
                 injector.setDisplayModes(makeModes(kMode60_1, kMode120_1), kMode60_1->getId());
-            },
-            mFlinger);
+            });
+
     mScheduler->registerDisplay(display);
 
     std::vector<RefreshRateConfigs::LayerRequirement> layers =
@@ -293,16 +295,16 @@
 }
 
 TEST_F(SchedulerTest, getBestDisplayModes_multipleDisplays) {
-    auto display1 = mFakeDisplayInjector.injectDefaultInternalDisplay(
-            [&](FakeDisplayDeviceInjector& injector) {
+    auto display1 =
+            mFakeDisplayInjector.injectInternalDisplay([&](FakeDisplayDeviceInjector& injector) {
                 injector.setDisplayModes(makeModes(kMode60_1, kMode120_1), kMode60_1->getId());
-            },
-            mFlinger);
-    auto display2 = mFakeDisplayInjector.injectDefaultInternalDisplay(
+            });
+    auto display2 = mFakeDisplayInjector.injectInternalDisplay(
             [&](FakeDisplayDeviceInjector& injector) {
                 injector.setDisplayModes(makeModes(kMode60_2, kMode120_2), kMode60_2->getId());
             },
-            mFlinger, /* port */ 253u);
+            {.port = 253u, .hwcDisplayId = 42, .isPrimary = false});
+
     mScheduler->registerDisplay(display1);
     mScheduler->registerDisplay(display2);
 
@@ -354,11 +356,12 @@
 
     // Filters out the 120Hz as it's not present on the display3, even with touch active
     // we select 60Hz here.
-    auto display3 = mFakeDisplayInjector.injectDefaultInternalDisplay(
+    auto display3 = mFakeDisplayInjector.injectInternalDisplay(
             [&](FakeDisplayDeviceInjector& injector) {
                 injector.setDisplayModes(makeModes(kMode60_3), kMode60_3->getId());
             },
-            mFlinger, /* port */ 252u);
+            {.port = 252u, .hwcDisplayId = 41, .isPrimary = false});
+
     mScheduler->registerDisplay(display3);
 
     expectedDisplays = {display1, display2, display3};