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};