SF: Adding Mock Display and tests for RefreshRateStats.
Following ag/6005545.
Test: adding SF tests.
Bug: 113612090
Change-Id: Ic4d1ca622f00c4396ae19c44defac0c69fabed1d
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp
index 392b608..68e7876 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp
@@ -143,8 +143,8 @@
return error;
}
- auto display = std::make_unique<Display>(
- *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, DisplayType::Virtual);
+ auto display = std::make_unique<impl::Display>(*mComposer.get(), mPowerAdvisor, mCapabilities,
+ displayId, DisplayType::Virtual);
display->setConnected(true);
*outDisplay = display.get();
mDisplays.emplace(displayId, std::move(display));
@@ -182,8 +182,8 @@
return;
}
- auto newDisplay = std::make_unique<Display>(
- *mComposer.get(), mPowerAdvisor, mCapabilities, displayId, displayType);
+ auto newDisplay = std::make_unique<impl::Display>(*mComposer.get(), mPowerAdvisor,
+ mCapabilities, displayId, displayType);
newDisplay->setConnected(true);
mDisplays.emplace(displayId, std::move(newDisplay));
} else if (connection == Connection::Disconnected) {
@@ -224,7 +224,36 @@
}
// Display methods
+Display::~Display() = default;
+Display::Config::Config(Display& display, hwc2_config_t id)
+ : mDisplay(display),
+ mId(id),
+ mWidth(-1),
+ mHeight(-1),
+ mVsyncPeriod(-1),
+ mDpiX(-1),
+ mDpiY(-1) {}
+
+Display::Config::Builder::Builder(Display& display, hwc2_config_t id)
+ : mConfig(new Config(display, id)) {}
+
+float Display::Config::Builder::getDefaultDensity() {
+ // Default density is based on TVs: 1080p displays get XHIGH density, lower-
+ // resolution displays get TV density. Maybe eventually we'll need to update
+ // it for 4k displays, though hopefully those will just report accurate DPI
+ // information to begin with. This is also used for virtual displays and
+ // older HWC implementations, so be careful about orientation.
+
+ auto longDimension = std::max(mConfig->mWidth, mConfig->mHeight);
+ if (longDimension >= 1080) {
+ return ACONFIGURATION_DENSITY_XHIGH;
+ } else {
+ return ACONFIGURATION_DENSITY_TV;
+ }
+}
+
+namespace impl {
Display::Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
const std::unordered_set<Capability>& capabilities, hwc2_display_t id,
DisplayType type)
@@ -272,35 +301,7 @@
}
}
-Display::Config::Config(Display& display, hwc2_config_t id)
- : mDisplay(display),
- mId(id),
- mWidth(-1),
- mHeight(-1),
- mVsyncPeriod(-1),
- mDpiX(-1),
- mDpiY(-1) {}
-
-Display::Config::Builder::Builder(Display& display, hwc2_config_t id)
- : mConfig(new Config(display, id)) {}
-
-float Display::Config::Builder::getDefaultDensity() {
- // Default density is based on TVs: 1080p displays get XHIGH density, lower-
- // resolution displays get TV density. Maybe eventually we'll need to update
- // it for 4k displays, though hopefully those will just report accurate DPI
- // information to begin with. This is also used for virtual displays and
- // older HWC implementations, so be careful about orientation.
-
- auto longDimension = std::max(mConfig->mWidth, mConfig->mHeight);
- if (longDimension >= 1080) {
- return ACONFIGURATION_DENSITY_XHIGH;
- } else {
- return ACONFIGURATION_DENSITY_TV;
- }
-}
-
// Required by HWC2 display
-
Error Display::acceptChanges()
{
auto intError = mComposer.acceptDisplayChanges(mId);
@@ -794,6 +795,7 @@
return mLayers.at(id).get();
}
+} // namespace impl
// Layer methods
diff --git a/services/surfaceflinger/DisplayHardware/HWC2.h b/services/surfaceflinger/DisplayHardware/HWC2.h
index f5cb97e..c1f481a 100644
--- a/services/surfaceflinger/DisplayHardware/HWC2.h
+++ b/services/surfaceflinger/DisplayHardware/HWC2.h
@@ -130,16 +130,11 @@
};
// Convenience C++ class to access hwc2_device_t Display functions directly.
-class Display
-{
+class Display {
public:
- Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
- const std::unordered_set<Capability>& capabilities,
- hwc2_display_t id, DisplayType type);
- ~Display();
+ virtual ~Display();
- class Config
- {
+ class Config {
public:
class Builder
{
@@ -207,78 +202,136 @@
float mDpiY;
};
- // Required by HWC2
+ virtual hwc2_display_t getId() const = 0;
+ virtual bool isConnected() const = 0;
+ virtual void setConnected(bool connected) = 0; // For use by Device only
+ virtual const std::unordered_set<DisplayCapability>& getCapabilities() const = 0;
- [[clang::warn_unused_result]] Error acceptChanges();
- [[clang::warn_unused_result]] Error createLayer(Layer** outLayer);
- [[clang::warn_unused_result]] Error destroyLayer(Layer* layer);
- [[clang::warn_unused_result]] Error getActiveConfig(
- std::shared_ptr<const Config>* outConfig) const;
- [[clang::warn_unused_result]] Error getActiveConfigIndex(int* outIndex) const;
- [[clang::warn_unused_result]] Error getChangedCompositionTypes(
- std::unordered_map<Layer*, Composition>* outTypes);
- [[clang::warn_unused_result]] Error getColorModes(
- std::vector<android::ui::ColorMode>* outModes) const;
+ [[clang::warn_unused_result]] virtual Error acceptChanges() = 0;
+ [[clang::warn_unused_result]] virtual Error createLayer(Layer** outLayer) = 0;
+ [[clang::warn_unused_result]] virtual Error destroyLayer(Layer* layer) = 0;
+ [[clang::warn_unused_result]] virtual Error getActiveConfig(
+ std::shared_ptr<const Config>* outConfig) const = 0;
+ [[clang::warn_unused_result]] virtual Error getActiveConfigIndex(int* outIndex) const = 0;
+ [[clang::warn_unused_result]] virtual Error getChangedCompositionTypes(
+ std::unordered_map<Layer*, Composition>* outTypes) = 0;
+ [[clang::warn_unused_result]] virtual Error getColorModes(
+ std::vector<android::ui::ColorMode>* outModes) const = 0;
// Returns a bitmask which contains HdrMetadata::Type::*.
- [[clang::warn_unused_result]] int32_t getSupportedPerFrameMetadata() const;
- [[clang::warn_unused_result]] Error getRenderIntents(
+ [[clang::warn_unused_result]] virtual int32_t getSupportedPerFrameMetadata() const = 0;
+ [[clang::warn_unused_result]] virtual Error getRenderIntents(
android::ui::ColorMode colorMode,
- std::vector<android::ui::RenderIntent>* outRenderIntents) const;
- [[clang::warn_unused_result]] Error getDataspaceSaturationMatrix(
- android::ui::Dataspace dataspace, android::mat4* outMatrix);
+ std::vector<android::ui::RenderIntent>* outRenderIntents) const = 0;
+ [[clang::warn_unused_result]] virtual Error getDataspaceSaturationMatrix(
+ android::ui::Dataspace dataspace, android::mat4* outMatrix) = 0;
+
+ // Doesn't call into the HWC2 device, so no Errors are possible
+ virtual std::vector<std::shared_ptr<const Config>> getConfigs() const = 0;
+
+ [[clang::warn_unused_result]] virtual Error getName(std::string* outName) const = 0;
+ [[clang::warn_unused_result]] virtual Error getRequests(
+ DisplayRequest* outDisplayRequests,
+ std::unordered_map<Layer*, LayerRequest>* outLayerRequests) = 0;
+ [[clang::warn_unused_result]] virtual Error getType(DisplayType* outType) const = 0;
+ [[clang::warn_unused_result]] virtual Error supportsDoze(bool* outSupport) const = 0;
+ [[clang::warn_unused_result]] virtual Error getHdrCapabilities(
+ android::HdrCapabilities* outCapabilities) const = 0;
+ [[clang::warn_unused_result]] virtual Error getDisplayedContentSamplingAttributes(
+ android::ui::PixelFormat* outFormat, android::ui::Dataspace* outDataspace,
+ uint8_t* outComponentMask) const = 0;
+ [[clang::warn_unused_result]] virtual Error setDisplayContentSamplingEnabled(
+ bool enabled, uint8_t componentMask, uint64_t maxFrames) const = 0;
+ [[clang::warn_unused_result]] virtual Error getDisplayedContentSample(
+ uint64_t maxFrames, uint64_t timestamp,
+ android::DisplayedFrameStats* outStats) const = 0;
+ [[clang::warn_unused_result]] virtual Error getReleaseFences(
+ std::unordered_map<Layer*, android::sp<android::Fence>>* outFences) const = 0;
+ [[clang::warn_unused_result]] virtual Error present(
+ android::sp<android::Fence>* outPresentFence) = 0;
+ [[clang::warn_unused_result]] virtual Error setActiveConfig(
+ const std::shared_ptr<const Config>& config) = 0;
+ [[clang::warn_unused_result]] virtual Error setClientTarget(
+ uint32_t slot, const android::sp<android::GraphicBuffer>& target,
+ const android::sp<android::Fence>& acquireFence, android::ui::Dataspace dataspace) = 0;
+ [[clang::warn_unused_result]] virtual Error setColorMode(
+ android::ui::ColorMode mode, android::ui::RenderIntent renderIntent) = 0;
+ [[clang::warn_unused_result]] virtual Error setColorTransform(
+ const android::mat4& matrix, android_color_transform_t hint) = 0;
+ [[clang::warn_unused_result]] virtual Error setOutputBuffer(
+ const android::sp<android::GraphicBuffer>& buffer,
+ const android::sp<android::Fence>& releaseFence) = 0;
+ [[clang::warn_unused_result]] virtual Error setPowerMode(PowerMode mode) = 0;
+ [[clang::warn_unused_result]] virtual Error setVsyncEnabled(Vsync enabled) = 0;
+ [[clang::warn_unused_result]] virtual Error validate(uint32_t* outNumTypes,
+ uint32_t* outNumRequests) = 0;
+ [[clang::warn_unused_result]] virtual Error presentOrValidate(
+ uint32_t* outNumTypes, uint32_t* outNumRequests,
+ android::sp<android::Fence>* outPresentFence, uint32_t* state) = 0;
+};
+
+namespace impl {
+
+class Display : public HWC2::Display {
+public:
+ Display(android::Hwc2::Composer& composer, android::Hwc2::PowerAdvisor& advisor,
+ const std::unordered_set<Capability>& capabilities, hwc2_display_t id,
+ DisplayType type);
+ ~Display() override;
+
+ // Required by HWC2
+ Error acceptChanges() override;
+ Error createLayer(Layer** outLayer) override;
+ Error destroyLayer(Layer* layer) override;
+ Error getActiveConfig(std::shared_ptr<const Config>* outConfig) const override;
+ Error getActiveConfigIndex(int* outIndex) const override;
+ Error getChangedCompositionTypes(std::unordered_map<Layer*, Composition>* outTypes) override;
+ Error getColorModes(std::vector<android::ui::ColorMode>* outModes) const override;
+ // Returns a bitmask which contains HdrMetadata::Type::*.
+ int32_t getSupportedPerFrameMetadata() const override;
+ Error getRenderIntents(android::ui::ColorMode colorMode,
+ std::vector<android::ui::RenderIntent>* outRenderIntents) const override;
+ Error getDataspaceSaturationMatrix(android::ui::Dataspace dataspace,
+ android::mat4* outMatrix) override;
// Doesn't call into the HWC2 device, so no errors are possible
- std::vector<std::shared_ptr<const Config>> getConfigs() const;
+ std::vector<std::shared_ptr<const Config>> getConfigs() const override;
- [[clang::warn_unused_result]] Error getName(std::string* outName) const;
- [[clang::warn_unused_result]] Error getRequests(
- DisplayRequest* outDisplayRequests,
- std::unordered_map<Layer*, LayerRequest>* outLayerRequests);
- [[clang::warn_unused_result]] Error getType(DisplayType* outType) const;
- [[clang::warn_unused_result]] Error supportsDoze(bool* outSupport) const;
- [[clang::warn_unused_result]] Error getHdrCapabilities(
- android::HdrCapabilities* outCapabilities) const;
- [[clang::warn_unused_result]] Error getDisplayedContentSamplingAttributes(
- android::ui::PixelFormat* outFormat, android::ui::Dataspace* outDataspace,
- uint8_t* outComponentMask) const;
- [[clang::warn_unused_result]] Error setDisplayContentSamplingEnabled(bool enabled,
- uint8_t componentMask,
- uint64_t maxFrames) const;
- [[clang::warn_unused_result]] Error getDisplayedContentSample(
- uint64_t maxFrames, uint64_t timestamp, android::DisplayedFrameStats* outStats) const;
- [[clang::warn_unused_result]] Error getReleaseFences(
- std::unordered_map<Layer*,
- android::sp<android::Fence>>* outFences) const;
- [[clang::warn_unused_result]] Error present(
- android::sp<android::Fence>* outPresentFence);
- [[clang::warn_unused_result]] Error setActiveConfig(
- const std::shared_ptr<const Config>& config);
- [[clang::warn_unused_result]] Error setClientTarget(
- uint32_t slot, const android::sp<android::GraphicBuffer>& target,
- const android::sp<android::Fence>& acquireFence,
- android::ui::Dataspace dataspace);
- [[clang::warn_unused_result]] Error setColorMode(
- android::ui::ColorMode mode,
- android::ui::RenderIntent renderIntent);
- [[clang::warn_unused_result]] Error setColorTransform(
- const android::mat4& matrix, android_color_transform_t hint);
- [[clang::warn_unused_result]] Error setOutputBuffer(
- const android::sp<android::GraphicBuffer>& buffer,
- const android::sp<android::Fence>& releaseFence);
- [[clang::warn_unused_result]] Error setPowerMode(PowerMode mode);
- [[clang::warn_unused_result]] Error setVsyncEnabled(Vsync enabled);
- [[clang::warn_unused_result]] Error validate(uint32_t* outNumTypes,
- uint32_t* outNumRequests);
- [[clang::warn_unused_result]] Error presentOrValidate(uint32_t* outNumTypes,
- uint32_t* outNumRequests,
- android::sp<android::Fence>* outPresentFence, uint32_t* state);
+ Error getName(std::string* outName) const override;
+ Error getRequests(DisplayRequest* outDisplayRequests,
+ std::unordered_map<Layer*, LayerRequest>* outLayerRequests) override;
+ Error getType(DisplayType* outType) const override;
+ Error supportsDoze(bool* outSupport) const override;
+ Error getHdrCapabilities(android::HdrCapabilities* outCapabilities) const override;
+ Error getDisplayedContentSamplingAttributes(android::ui::PixelFormat* outFormat,
+ android::ui::Dataspace* outDataspace,
+ uint8_t* outComponentMask) const override;
+ Error setDisplayContentSamplingEnabled(bool enabled, uint8_t componentMask,
+ uint64_t maxFrames) const override;
+ Error getDisplayedContentSample(uint64_t maxFrames, uint64_t timestamp,
+ android::DisplayedFrameStats* outStats) const override;
+ Error getReleaseFences(
+ std::unordered_map<Layer*, android::sp<android::Fence>>* outFences) const override;
+ Error present(android::sp<android::Fence>* outPresentFence) override;
+ Error setActiveConfig(const std::shared_ptr<const HWC2::Display::Config>& config) override;
+ Error setClientTarget(uint32_t slot, const android::sp<android::GraphicBuffer>& target,
+ const android::sp<android::Fence>& acquireFence,
+ android::ui::Dataspace dataspace) override;
+ Error setColorMode(android::ui::ColorMode mode,
+ android::ui::RenderIntent renderIntent) override;
+ Error setColorTransform(const android::mat4& matrix, android_color_transform_t hint) override;
+ Error setOutputBuffer(const android::sp<android::GraphicBuffer>& buffer,
+ const android::sp<android::Fence>& releaseFence) override;
+ Error setPowerMode(PowerMode mode) override;
+ Error setVsyncEnabled(Vsync enabled) override;
+ Error validate(uint32_t* outNumTypes, uint32_t* outNumRequests) override;
+ Error presentOrValidate(uint32_t* outNumTypes, uint32_t* outNumRequests,
+ android::sp<android::Fence>* outPresentFence, uint32_t* state) override;
// Other Display methods
-
- hwc2_display_t getId() const { return mId; }
- bool isConnected() const { return mIsConnected; }
- void setConnected(bool connected); // For use by Device only
- const std::unordered_set<DisplayCapability>& getCapabilities() const {
+ hwc2_display_t getId() const override { return mId; }
+ bool isConnected() const override { return mIsConnected; }
+ void setConnected(bool connected) override; // For use by Device only
+ const std::unordered_set<DisplayCapability>& getCapabilities() const override {
return mDisplayCapabilities;
};
@@ -309,6 +362,7 @@
std::unordered_map<hwc2_config_t, std::shared_ptr<const Config>> mConfigs;
std::unordered_set<DisplayCapability> mDisplayCapabilities;
};
+} // namespace impl
// Convenience C++ class to access hwc2_device_t Layer functions directly.
class Layer
diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
index ce1637a..bfe5da5 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h
@@ -19,9 +19,11 @@
#include <algorithm>
#include <numeric>
-#include "Scheduler/SchedulerUtils.h"
#include "android-base/stringprintf.h"
+#include "DisplayHardware/HWComposer.h"
+#include "Scheduler/SchedulerUtils.h"
+
namespace android {
namespace scheduler {
@@ -51,57 +53,58 @@
// baking them in.
explicit RefreshRateConfigs(
const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
- // This is the rate that HWC encapsulates right now when the screen is off.
- RefreshRate rate;
- rate.type = RefreshRateType::POWER_SAVING;
- rate.configId = SCREEN_OFF_CONFIG_ID;
- rate.name = "ScreenOff";
- mRefreshRates.push_back(rate);
-
- if (configs.size() < 1) {
- return;
- }
-
- std::vector<std::pair<int, nsecs_t>> configIdToVsyncPeriod;
- for (int i = 0; i < configs.size(); ++i) {
- configIdToVsyncPeriod.push_back(std::make_pair(i, configs.at(i)->getVsyncPeriod()));
- }
- std::sort(configIdToVsyncPeriod.begin(), configIdToVsyncPeriod.end(),
- [](const std::pair<int, nsecs_t>& a, const std::pair<int, nsecs_t>& b) {
- return a.second > b.second;
- });
-
- nsecs_t vsyncPeriod = configIdToVsyncPeriod.at(0).second;
- if (vsyncPeriod != 0) {
- const float fps = std::chrono::nanoseconds(1).count() / vsyncPeriod;
- rate.type = RefreshRateType::DEFAULT;
- rate.configId = configIdToVsyncPeriod.at(0).first;
- rate.name = base::StringPrintf("%2.ffps", fps);
- mRefreshRates.push_back(rate);
- }
- if (configs.size() < 2) {
- return;
- }
-
- vsyncPeriod = configIdToVsyncPeriod.at(1).second;
- if (vsyncPeriod != 0) {
- const float fps = std::chrono::nanoseconds(1).count() / vsyncPeriod;
- rate.type = RefreshRateType::PERFORMANCE;
- rate.configId = configIdToVsyncPeriod.at(1).first;
- rate.name = base::StringPrintf("%2.ffps", fps);
- mRefreshRates.push_back(rate);
- }
-
- for (auto refreshRate : mRefreshRates) {
- ALOGV("type: %d, id: %d, name: %s", refreshRate.type, refreshRate.configId,
- refreshRate.name.c_str());
- }
+ init(configs);
}
~RefreshRateConfigs() = default;
const std::vector<RefreshRate>& getRefreshRates() { return mRefreshRates; }
private:
+ void init(const std::vector<std::shared_ptr<const HWC2::Display::Config>>& configs) {
+ // This is the rate that HWC encapsulates right now when the device is in DOZE mode.
+ mRefreshRates.push_back(
+ RefreshRate{RefreshRateType::POWER_SAVING, SCREEN_OFF_CONFIG_ID, "ScreenOff"});
+
+ if (configs.size() < 1) {
+ ALOGE("Device does not have valid configs. Config size is 0.");
+ return;
+ }
+
+ // Create a map between config index and vsync period. This is all the info we need
+ // from the configs.
+ std::vector<std::pair<int, nsecs_t>> configIdToVsyncPeriod;
+ for (int i = 0; i < configs.size(); ++i) {
+ configIdToVsyncPeriod.emplace_back(i, configs.at(i)->getVsyncPeriod());
+ }
+
+ std::sort(configIdToVsyncPeriod.begin(), configIdToVsyncPeriod.end(),
+ [](const std::pair<int, nsecs_t>& a, const std::pair<int, nsecs_t>& b) {
+ return a.second > b.second;
+ });
+
+ // When the configs are ordered by the resync rate. We assume that the first one is DEFAULT.
+ nsecs_t vsyncPeriod = configIdToVsyncPeriod[0].second;
+ if (vsyncPeriod != 0) {
+ const float fps = 1e9 / vsyncPeriod;
+ mRefreshRates.push_back(RefreshRate{RefreshRateType::DEFAULT,
+ configIdToVsyncPeriod[0].first,
+ base::StringPrintf("%2.ffps", fps)});
+ }
+ if (configs.size() < 2) {
+ return;
+ }
+
+ // When the configs are ordered by the resync rate. We assume that the second one is
+ // PERFORMANCE, eg. the higher rate.
+ vsyncPeriod = configIdToVsyncPeriod[1].second;
+ if (vsyncPeriod != 0) {
+ const float fps = 1e9 / vsyncPeriod;
+ mRefreshRates.push_back(RefreshRate{RefreshRateType::PERFORMANCE,
+ configIdToVsyncPeriod[1].first,
+ base::StringPrintf("%2.ffps", fps)});
+ }
+ }
+
std::vector<RefreshRate> mRefreshRates;
};
diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h
index cd81e4d..7e22232 100644
--- a/services/surfaceflinger/Scheduler/RefreshRateStats.h
+++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h
@@ -82,9 +82,11 @@
std::unordered_map<std::string, int64_t> totalTime;
for (auto config : mRefreshRateConfigs->getRefreshRates()) {
+ int64_t totalTimeForConfig = 0;
if (mConfigModesTotalTime.find(config.configId) != mConfigModesTotalTime.end()) {
- totalTime[config.name] = mConfigModesTotalTime.at(config.configId);
+ totalTimeForConfig = mConfigModesTotalTime.at(config.configId);
}
+ totalTime[config.name] = totalTimeForConfig;
}
return totalTime;
}
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 8746a68..e298e20 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -4338,7 +4338,7 @@
if (display->isPrimary()) {
mTimeStats->setPowerMode(mode);
- if (mUseScheduler) {
+ if (mUseScheduler && mRefreshRateStats) {
// Update refresh rate stats.
mRefreshRateStats->setPowerMode(mode);
}
diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp
index ad31a40..e34e568 100644
--- a/services/surfaceflinger/tests/unittests/Android.bp
+++ b/services/surfaceflinger/tests/unittests/Android.bp
@@ -44,8 +44,10 @@
"LayerHistoryTest.cpp",
"SchedulerTest.cpp",
"SchedulerUtilsTest.cpp",
+ "RefreshRateStatsTest.cpp",
"TimeStatsTest.cpp",
"mock/DisplayHardware/MockComposer.cpp",
+ "mock/DisplayHardware/MockDisplay.cpp",
"mock/DisplayHardware/MockPowerAdvisor.cpp",
"mock/gui/MockGraphicBufferConsumer.cpp",
"mock/gui/MockGraphicBufferProducer.cpp",
diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
new file mode 100644
index 0000000..0384d9d
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp
@@ -0,0 +1,212 @@
+/*
+ * 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.
+ */
+
+#undef LOG_TAG
+#define LOG_TAG "SchedulerUnittests"
+
+#include <gmock/gmock.h>
+#include <log/log.h>
+#include <thread>
+
+#include "Scheduler/RefreshRateStats.h"
+#include "mock/DisplayHardware/MockDisplay.h"
+
+using namespace std::chrono_literals;
+
+namespace android {
+namespace scheduler {
+
+class RefreshRateStatsTest : public testing::Test {
+protected:
+ static constexpr int CONFIG_ID_90 = 0;
+ static constexpr int CONFIG_ID_60 = 1;
+ static constexpr int64_t VSYNC_90 = 11111111;
+ static constexpr int64_t VSYNC_60 = 16666667;
+
+ RefreshRateStatsTest();
+ ~RefreshRateStatsTest();
+
+ void init(std::vector<std::shared_ptr<const HWC2::Display::Config>> configs);
+
+ std::unique_ptr<RefreshRateStats> mRefreshRateStats;
+};
+
+RefreshRateStatsTest::RefreshRateStatsTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+RefreshRateStatsTest::~RefreshRateStatsTest() {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+ ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name());
+}
+
+void RefreshRateStatsTest::init(std::vector<std::shared_ptr<const HWC2::Display::Config>> configs) {
+ mRefreshRateStats = std::make_unique<RefreshRateStats>(configs);
+}
+
+namespace {
+/* ------------------------------------------------------------------------
+ * Test cases
+ */
+TEST_F(RefreshRateStatsTest, canCreateAndDestroyTest) {
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
+ init(configs);
+
+ // There is one default config, so the refresh rates should have one item.
+ ASSERT_EQ(1, mRefreshRateStats->getTotalTimes().size());
+}
+
+TEST_F(RefreshRateStatsTest, oneConfigTest) {
+ auto display = new Hwc2::mock::Display();
+
+ auto config = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
+ config.setVsyncPeriod(VSYNC_90);
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
+ configs.push_back(config.build());
+
+ init(configs);
+
+ std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(2, times.size());
+ ASSERT_EQ(0, times["ScreenOff"]);
+ ASSERT_EQ(0, times["90fps"]);
+ // Setting up tests on mobile harness can be flaky with time passing, so testing for
+ // exact time changes can result in flaxy numbers. To avoid that remember old
+ // numbers to make sure the correct values are increasing in the next test.
+ int screenOff = times["ScreenOff"];
+ int ninety = times["90fps"];
+
+ // Screen is off by default.
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_LT(screenOff, times["ScreenOff"]);
+ ASSERT_EQ(0, times["90fps"]);
+ screenOff = times["ScreenOff"];
+
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(screenOff, times["ScreenOff"]);
+ ASSERT_LT(ninety, times["90fps"]);
+ ninety = times["90fps"];
+
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_LT(screenOff, times["ScreenOff"]);
+ ASSERT_EQ(ninety, times["90fps"]);
+ screenOff = times["ScreenOff"];
+
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
+ // does not update refresh rates that come from the config.
+ ASSERT_LT(screenOff, times["ScreenOff"]);
+ ASSERT_EQ(ninety, times["90fps"]);
+}
+
+TEST_F(RefreshRateStatsTest, twoConfigsTest) {
+ auto display = new Hwc2::mock::Display();
+
+ auto config90 = HWC2::Display::Config::Builder(*display, CONFIG_ID_90);
+ config90.setVsyncPeriod(VSYNC_90);
+ std::vector<std::shared_ptr<const HWC2::Display::Config>> configs;
+ configs.push_back(config90.build());
+
+ auto config60 = HWC2::Display::Config::Builder(*display, CONFIG_ID_60);
+ config60.setVsyncPeriod(VSYNC_60);
+ configs.push_back(config60.build());
+
+ init(configs);
+
+ std::unordered_map<std::string, int64_t> times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(3, times.size());
+ ASSERT_EQ(0, times["ScreenOff"]);
+ ASSERT_EQ(0, times["60fps"]);
+ ASSERT_EQ(0, times["90fps"]);
+ // Setting up tests on mobile harness can be flaky with time passing, so testing for
+ // exact time changes can result in flaxy numbers. To avoid that remember old
+ // numbers to make sure the correct values are increasing in the next test.
+ int screenOff = times["ScreenOff"];
+ int sixty = times["60fps"];
+ int ninety = times["90fps"];
+
+ // Screen is off by default.
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_LT(screenOff, times["ScreenOff"]);
+ ASSERT_EQ(sixty, times["60fps"]);
+ ASSERT_EQ(ninety, times["90fps"]);
+ screenOff = times["ScreenOff"];
+
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(screenOff, times["ScreenOff"]);
+ ASSERT_EQ(sixty, times["60fps"]);
+ ASSERT_LT(ninety, times["90fps"]);
+ ninety = times["90fps"];
+
+ // When power mode is normal, time for configs updates.
+ mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(screenOff, times["ScreenOff"]);
+ ASSERT_EQ(ninety, times["90fps"]);
+ ASSERT_LT(sixty, times["60fps"]);
+ sixty = times["60fps"];
+
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(screenOff, times["ScreenOff"]);
+ ASSERT_LT(ninety, times["90fps"]);
+ ASSERT_EQ(sixty, times["60fps"]);
+ ninety = times["90fps"];
+
+ mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_EQ(screenOff, times["ScreenOff"]);
+ ASSERT_EQ(ninety, times["90fps"]);
+ ASSERT_LT(sixty, times["60fps"]);
+ sixty = times["60fps"];
+
+ // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config
+ // does not update refresh rates that come from the config.
+ mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE);
+ mRefreshRateStats->setConfigMode(CONFIG_ID_90);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_LT(screenOff, times["ScreenOff"]);
+ ASSERT_EQ(ninety, times["90fps"]);
+ ASSERT_EQ(sixty, times["60fps"]);
+ screenOff = times["ScreenOff"];
+
+ mRefreshRateStats->setConfigMode(CONFIG_ID_60);
+ std::this_thread::sleep_for(std::chrono::milliseconds(2));
+ times = mRefreshRateStats->getTotalTimes();
+ ASSERT_LT(screenOff, times["ScreenOff"]);
+ ASSERT_EQ(ninety, times["90fps"]);
+ ASSERT_EQ(sixty, times["60fps"]);
+}
+} // namespace
+} // namespace scheduler
+} // namespace android
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 687941a..2a8dda6 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -335,11 +335,11 @@
void setExpensiveRenderingExpected(hwc2_display_t, bool) override {}
};
- struct HWC2Display : public HWC2::Display {
+ struct HWC2Display : public HWC2::impl::Display {
HWC2Display(Hwc2::Composer& composer, Hwc2::PowerAdvisor& advisor,
const std::unordered_set<HWC2::Capability>& capabilities, hwc2_display_t id,
HWC2::DisplayType type)
- : HWC2::Display(composer, advisor, capabilities, id, type) {}
+ : HWC2::impl::Display(composer, advisor, capabilities, id, type) {}
~HWC2Display() {
// Prevents a call to disable vsyncs.
mType = HWC2::DisplayType::Invalid;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.cpp
new file mode 100644
index 0000000..2ec37c1
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.cpp
@@ -0,0 +1,29 @@
+/*
+ * 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 "mock/DisplayHardware/MockDisplay.h"
+
+namespace android {
+namespace Hwc2 {
+namespace mock {
+
+// Explicit default instantiation is recommended.
+Display::Display() = default;
+Display::~Display() = default;
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
\ No newline at end of file
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
new file mode 100644
index 0000000..d7e20c4
--- /dev/null
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockDisplay.h
@@ -0,0 +1,86 @@
+/*
+ * 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 <gmock/gmock.h>
+
+#include "DisplayHardware/HWC2.h"
+
+using HWC2::Error;
+using HWC2::Layer;
+
+namespace android {
+namespace Hwc2 {
+namespace mock {
+
+class Display : public HWC2::Display {
+public:
+ Display();
+ ~Display();
+
+ MOCK_CONST_METHOD0(getId, hwc2_layer_t());
+ MOCK_CONST_METHOD0(isConnected, bool());
+ MOCK_METHOD1(setConnected, void(bool));
+ MOCK_CONST_METHOD0(getCapabilities, const std::unordered_set<HWC2::DisplayCapability>&());
+
+ MOCK_METHOD0(acceptChanges, Error());
+ MOCK_METHOD1(createLayer, Error(Layer**));
+ MOCK_METHOD1(destroyLayer, Error(Layer*));
+ MOCK_CONST_METHOD1(getActiveConfig, Error(std::shared_ptr<const Config>*));
+ MOCK_CONST_METHOD1(getActiveConfigIndex, Error(int* outIndex));
+ MOCK_METHOD1(getChangedCompositionTypes, Error(std::unordered_map<Layer*, HWC2::Composition>*));
+ MOCK_CONST_METHOD1(getColorModes, Error(std::vector<android::ui::ColorMode>*));
+
+ MOCK_CONST_METHOD0(getSupportedPerFrameMetadata, int32_t());
+ MOCK_CONST_METHOD2(getRenderIntents,
+ Error(android::ui::ColorMode, std::vector<android::ui::RenderIntent>*));
+ MOCK_METHOD2(getDataspaceSaturationMatrix, Error(android::ui::Dataspace, android::mat4*));
+ MOCK_CONST_METHOD0(getConfigs, std::vector<std::shared_ptr<const Config>>());
+
+ MOCK_CONST_METHOD1(getName, Error(std::string*));
+ MOCK_METHOD2(getRequests,
+ Error(HWC2::DisplayRequest*, std::unordered_map<Layer*, HWC2::LayerRequest>*));
+ MOCK_CONST_METHOD1(getType, Error(HWC2::DisplayType*));
+ MOCK_CONST_METHOD1(supportsDoze, Error(bool*));
+ MOCK_CONST_METHOD1(getHdrCapabilities, Error(android::HdrCapabilities*));
+ MOCK_CONST_METHOD3(getDisplayedContentSamplingAttributes,
+ Error(android::ui::PixelFormat*, android::ui::Dataspace*, uint8_t*));
+ MOCK_CONST_METHOD3(setDisplayContentSamplingEnabled, Error(bool, uint8_t, uint64_t));
+ MOCK_CONST_METHOD3(getDisplayedContentSample,
+ Error(uint64_t, uint64_t, android::DisplayedFrameStats*));
+ MOCK_CONST_METHOD1(getReleaseFences,
+ Error(std::unordered_map<Layer*, android::sp<android::Fence>>* outFences));
+ MOCK_METHOD1(present, Error(android::sp<android::Fence>*));
+ MOCK_METHOD1(setActiveConfig, Error(const std::shared_ptr<const HWC2::Display::Config>&));
+ MOCK_METHOD4(setClientTarget,
+ Error(uint32_t, const android::sp<android::GraphicBuffer>&,
+ const android::sp<android::Fence>&, android::ui::Dataspace));
+ MOCK_METHOD2(setColorMode, Error(android::ui::ColorMode, android::ui::RenderIntent));
+ MOCK_METHOD2(setColorTransform, Error(const android::mat4&, android_color_transform_t));
+ MOCK_METHOD2(setOutputBuffer,
+ Error(const android::sp<android::GraphicBuffer>&,
+ const android::sp<android::Fence>&));
+ MOCK_METHOD1(setPowerMode, Error(HWC2::PowerMode));
+ MOCK_METHOD1(setVsyncEnabled, Error(HWC2::Vsync));
+ MOCK_METHOD2(validate, Error(uint32_t*, uint32_t*));
+ MOCK_METHOD4(presentOrValidate,
+ Error(uint32_t*, uint32_t*, android::sp<android::Fence>*, uint32_t*));
+};
+
+} // namespace mock
+} // namespace Hwc2
+} // namespace android
\ No newline at end of file