diff options
-rw-r--r-- | libs/binder/IServiceManager.cpp | 4 | ||||
-rw-r--r-- | libs/binder/include/binder/IInterface.h | 8 | ||||
-rw-r--r-- | libs/gralloc/types/Android.bp | 5 | ||||
-rw-r--r-- | libs/gui/Android.bp | 5 | ||||
-rw-r--r-- | libs/math/Android.bp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/Android.bp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/CompositionEngine/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/LayerHistoryV2.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/LayerInfoV2.cpp | 55 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/LayerInfoV2.h | 14 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp | 21 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/Scheduler.cpp | 77 | ||||
-rw-r--r-- | services/surfaceflinger/Scheduler/Scheduler.h | 5 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp | 44 | ||||
-rw-r--r-- | services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp | 9 |
17 files changed, 130 insertions, 139 deletions
diff --git a/libs/binder/IServiceManager.cpp b/libs/binder/IServiceManager.cpp index 912d4706ed..a9f2d73951 100644 --- a/libs/binder/IServiceManager.cpp +++ b/libs/binder/IServiceManager.cpp @@ -85,8 +85,8 @@ private: sp<AidlServiceManager> mTheRealServiceManager; }; -static std::once_flag gSmOnce; -static sp<IServiceManager> gDefaultServiceManager; +[[clang::no_destroy]] static std::once_flag gSmOnce; +[[clang::no_destroy]] static sp<IServiceManager> gDefaultServiceManager; sp<IServiceManager> defaultServiceManager() { diff --git a/libs/binder/include/binder/IInterface.h b/libs/binder/include/binder/IInterface.h index 3a401adfa5..7116154951 100644 --- a/libs/binder/include/binder/IInterface.h +++ b/libs/binder/include/binder/IInterface.h @@ -20,6 +20,8 @@ #include <binder/Binder.h> +#include <assert.h> + namespace android { // ---------------------------------------------------------------------- @@ -155,7 +157,11 @@ public: \ std::unique_ptr<I##INTERFACE> I##INTERFACE::default_impl; \ bool I##INTERFACE::setDefaultImpl(std::unique_ptr<I##INTERFACE> impl)\ { \ - if (!I##INTERFACE::default_impl && impl) { \ + /* Only one user of this interface can use this function */ \ + /* at a time. This is a heuristic to detect if two different */ \ + /* users in the same process use this function. */ \ + assert(!I##INTERFACE::default_impl); \ + if (impl) { \ I##INTERFACE::default_impl = std::move(impl); \ return true; \ } \ diff --git a/libs/gralloc/types/Android.bp b/libs/gralloc/types/Android.bp index 00f7484a80..66fb295a19 100644 --- a/libs/gralloc/types/Android.bp +++ b/libs/gralloc/types/Android.bp @@ -27,6 +27,11 @@ cc_library { enabled: true, support_system_process: true, }, + apex_available: [ + "//apex_available:platform", + "com.android.media.swcodec", + ], + min_sdk_version: "29", srcs: [ "Gralloc4.cpp" diff --git a/libs/gui/Android.bp b/libs/gui/Android.bp index 7976ecb707..4a4510e047 100644 --- a/libs/gui/Android.bp +++ b/libs/gui/Android.bp @@ -130,6 +130,11 @@ cc_library_shared { cc_library_static { name: "libgui_bufferqueue_static", vendor_available: true, + apex_available: [ + "//apex_available:platform", + "com.android.media.swcodec", + ], + min_sdk_version: "29", cflags: [ "-DNO_BUFFERHUB", diff --git a/libs/math/Android.bp b/libs/math/Android.bp index 693bace1f4..3b1edcb43a 100644 --- a/libs/math/Android.bp +++ b/libs/math/Android.bp @@ -16,6 +16,14 @@ cc_library_static { name: "libmath", host_supported: true, vendor_available: true, + apex_available: [ + "//apex_available:platform", + "com.android.media", + "com.android.media.swcodec", + "com.android.neuralnetworks", + ], + min_sdk_version: "29", + export_include_dirs: ["include"], } diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 01829371ea..a790d0b745 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -38,7 +38,6 @@ cc_defaults { "libbinder", "libbufferhubqueue", "libcutils", - "libdl", "libEGL", "libfmq", "libGLESv1_CM", @@ -73,7 +72,6 @@ cc_defaults { "librenderengine", "libserviceutils", "libtrace_proto", - "libvr_manager", "libvrflinger", ], header_libs: [ diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index fda451bd9e..b3b9fe5981 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -21,7 +21,6 @@ cc_defaults { "liblog", "libnativewindow", "libprotobuf-cpp-lite", - "libsync", "libtimestats", "libui", "libutils", diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index 660baffa3a..408465320d 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -28,7 +28,6 @@ #include <log/log.h> #include <renderengine/RenderEngine.h> -#include <sync/sync.h> #include <system/window.h> #include <ui/GraphicBuffer.h> #include <ui/Rect.h> diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp index e6c5cc9700..120a60f8d8 100644 --- a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp @@ -90,7 +90,7 @@ LayerHistoryV2::~LayerHistoryV2() = default; void LayerHistoryV2::registerLayer(Layer* layer, float /*lowRefreshRate*/, float highRefreshRate, LayerVoteType type) { const nsecs_t highRefreshRatePeriod = static_cast<nsecs_t>(1e9f / highRefreshRate); - auto info = std::make_unique<LayerInfoV2>(highRefreshRatePeriod, type); + auto info = std::make_unique<LayerInfoV2>(layer->getName(), highRefreshRatePeriod, type); std::lock_guard lock(mLock); mLayerInfos.emplace_back(layer, std::move(info)); } diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp index b7d0bdd101..255eac6efc 100644 --- a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp @@ -27,8 +27,10 @@ namespace android::scheduler { -LayerInfoV2::LayerInfoV2(nsecs_t highRefreshRatePeriod, LayerHistory::LayerVoteType defaultVote) - : mHighRefreshRatePeriod(highRefreshRatePeriod), +LayerInfoV2::LayerInfoV2(const std::string& name, nsecs_t highRefreshRatePeriod, + LayerHistory::LayerVoteType defaultVote) + : mName(name), + mHighRefreshRatePeriod(highRefreshRatePeriod), mDefaultVote(defaultVote), mLayerVote({defaultVote, 0.0f}) {} @@ -45,42 +47,23 @@ void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) { } } -bool LayerInfoV2::isFrameTimeValid(const FrameTimeData& frameTime) const { - return frameTime.queueTime >= std::chrono::duration_cast<std::chrono::nanoseconds>( - mFrameTimeValidSince.time_since_epoch()) - .count(); -} - bool LayerInfoV2::isFrequent(nsecs_t now) const { - // Find the first valid frame time - auto it = mFrameTimes.begin(); - for (; it != mFrameTimes.end(); ++it) { - if (isFrameTimeValid(*it)) { - break; + for (auto it = mFrameTimes.crbegin(); it != mFrameTimes.crend(); ++it) { + if (now - it->queueTime >= MAX_FREQUENT_LAYER_PERIOD_NS.count()) { + ALOGV("%s infrequent (last frame is %.2fms ago", mName.c_str(), + (now - mFrameTimes.back().queueTime) / 1e6f); + return false; } - } - // If we know nothing about this layer we consider it as frequent as it might be the start - // of an animation. - if (std::distance(it, mFrameTimes.end()) < FREQUENT_LAYER_WINDOW_SIZE) { - return true; - } - - // Find the first active frame - for (; it != mFrameTimes.end(); ++it) { - if (it->queueTime >= getActiveLayerThreshold(now)) { - break; + const auto numFrames = std::distance(mFrameTimes.crbegin(), it + 1); + if (numFrames >= FREQUENT_LAYER_WINDOW_SIZE) { + ALOGV("%s frequent (burst of %zu frames", mName.c_str(), numFrames); + return true; } } - const auto numFrames = std::distance(it, mFrameTimes.end()); - if (numFrames < FREQUENT_LAYER_WINDOW_SIZE) { - return false; - } - - // Layer is considered frequent if the average frame rate is higher than the threshold - const auto totalTime = mFrameTimes.back().queueTime - it->queueTime; - return (1e9f * (numFrames - 1)) / totalTime >= MIN_FPS_FOR_FREQUENT_LAYER; + ALOGV("%s infrequent (not enough frames %zu)", mName.c_str(), mFrameTimes.size()); + return false; } bool LayerInfoV2::hasEnoughDataForHeuristic() const { @@ -89,10 +72,6 @@ bool LayerInfoV2::hasEnoughDataForHeuristic() const { return false; } - if (!isFrameTimeValid(mFrameTimes.front())) { - return false; - } - if (mFrameTimes.size() < HISTORY_SIZE && mFrameTimes.back().queueTime - mFrameTimes.front().queueTime < HISTORY_TIME.count()) { return false; @@ -167,18 +146,22 @@ std::optional<float> LayerInfoV2::calculateRefreshRateIfPossible() { std::pair<LayerHistory::LayerVoteType, float> LayerInfoV2::getRefreshRate(nsecs_t now) { if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) { + ALOGV("%s voted %d ", mName.c_str(), static_cast<int>(mLayerVote.type)); return {mLayerVote.type, mLayerVote.fps}; } if (!isFrequent(now)) { + ALOGV("%s is infrequent", mName.c_str()); return {LayerHistory::LayerVoteType::Min, 0}; } auto refreshRate = calculateRefreshRateIfPossible(); if (refreshRate.has_value()) { + ALOGV("%s calculated refresh rate: %.2f", mName.c_str(), refreshRate.value()); return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()}; } + ALOGV("%s Max (can't resolve refresh rate", mName.c_str()); return {LayerHistory::LayerVoteType::Max, 0}; } diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h index e36b7f709e..97c7017648 100644 --- a/services/surfaceflinger/Scheduler/LayerInfoV2.h +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h @@ -54,7 +54,8 @@ class LayerInfoV2 { friend class LayerHistoryTestV2; public: - LayerInfoV2(nsecs_t highRefreshRatePeriod, LayerHistory::LayerVoteType defaultVote); + LayerInfoV2(const std::string& name, nsecs_t highRefreshRatePeriod, + LayerHistory::LayerVoteType defaultVote); LayerInfoV2(const LayerInfo&) = delete; LayerInfoV2& operator=(const LayerInfoV2&) = delete; @@ -83,11 +84,7 @@ public: nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; } void clearHistory() { - // Mark mFrameTimeValidSince to now to ignore all previous frame times. - // We are not deleting the old frame to keep track of whether we should treat the first - // buffer as Max as we don't know anything about this layer or Min as this layer is - // posting infrequent updates. - mFrameTimeValidSince = std::chrono::steady_clock::now(); + mFrameTimes.clear(); mLastReportedRefreshRate = 0.0f; } @@ -101,7 +98,8 @@ private: bool isFrequent(nsecs_t now) const; bool hasEnoughDataForHeuristic() const; std::optional<float> calculateRefreshRateIfPossible(); - bool isFrameTimeValid(const FrameTimeData&) const; + + const std::string mName; // Used for sanitizing the heuristic data const nsecs_t mHighRefreshRatePeriod; @@ -118,8 +116,6 @@ private: } mLayerVote; std::deque<FrameTimeData> mFrameTimes; - std::chrono::time_point<std::chrono::steady_clock> mFrameTimeValidSince = - std::chrono::steady_clock::now(); static constexpr size_t HISTORY_SIZE = 90; static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s; }; diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 8d958df572..4a4f9c8111 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -103,7 +103,7 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( ATRACE_CALL(); ALOGV("getRefreshRateForContent %zu layers", layers.size()); - *touchConsidered = false; + if (touchConsidered) *touchConsidered = false; std::lock_guard lock(mLock); int noVoteLayers = 0; @@ -131,7 +131,8 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( // Consider the touch event if there are no Explicit* layers. Otherwise wait until after we've // selected a refresh rate to see if we should apply touch boost. if (touchActive && explicitDefaultVoteLayers == 0 && explicitExactOrMultipleVoteLayers == 0) { - *touchConsidered = true; + ALOGV("TouchBoost - choose %s", getMaxRefreshRateByPolicyLocked().getName().c_str()); + if (touchConsidered) *touchConsidered = true; return getMaxRefreshRateByPolicyLocked(); } @@ -139,12 +140,13 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( return getMinRefreshRateByPolicyLocked(); } - if (layers.empty()) { - return getCurrentRefreshRateByPolicyLocked(); + if (layers.empty() || noVoteLayers == layers.size()) { + return getMaxRefreshRateByPolicyLocked(); } // Only if all layers want Min we should return Min if (noVoteLayers + minVoteLayers == layers.size()) { + ALOGV("all layers Min - choose %s", getMinRefreshRateByPolicyLocked().getName().c_str()); return getMinRefreshRateByPolicyLocked(); } @@ -243,9 +245,11 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( return 1.0f / iter; }(); - ALOGV("%s (ExplicitExactOrMultiple, weight %.2f) %.2fHz gives %s score of %.2f", - layer.name.c_str(), weight, 1e9f / layerPeriod, scores[i].first->name.c_str(), - layerScore); + ALOGV("%s (%s, weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(), + layer.vote == LayerVoteType::ExplicitExactOrMultiple + ? "ExplicitExactOrMultiple" + : "Heuristic", + weight, 1e9f / layerPeriod, scores[i].first->name.c_str(), layerScore); scores[i].second += weight * layerScore; continue; } @@ -266,7 +270,8 @@ const RefreshRate& RefreshRateConfigs::getBestRefreshRate( const RefreshRate& touchRefreshRate = getMaxRefreshRateByPolicyLocked(); if (touchActive && explicitDefaultVoteLayers == 0 && bestRefreshRate->fps < touchRefreshRate.fps) { - *touchConsidered = true; + if (touchConsidered) *touchConsidered = true; + ALOGV("TouchBoost - choose %s", touchRefreshRate.getName().c_str()); return touchRefreshRate; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index f87c1f8131..4eef81d113 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -385,38 +385,33 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime(nsecs_t now) { void Scheduler::registerLayer(Layer* layer) { if (!mLayerHistory) return; - // If the content detection feature is off, all layers are registered at NoVote. We still - // keep the layer history, since we use it for other features (like Frame Rate API), so layers - // still need to be registered. - if (!mUseContentDetection) { - mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(), - mRefreshRateConfigs.getMaxRefreshRate().getFps(), - scheduler::LayerHistory::LayerVoteType::NoVote); - return; - } + const auto minFps = mRefreshRateConfigs.getMinRefreshRate().getFps(); + const auto maxFps = mRefreshRateConfigs.getMaxRefreshRate().getFps(); - // In V1 of content detection, all layers are registered as Heuristic (unless it's wallpaper). - if (!mUseContentDetectionV2) { - const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().getFps(); - const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER - ? lowFps - : mRefreshRateConfigs.getMaxRefreshRate().getFps(); - - mLayerHistory->registerLayer(layer, lowFps, highFps, + if (layer->getWindowType() == InputWindowInfo::TYPE_STATUS_BAR) { + mLayerHistory->registerLayer(layer, minFps, maxFps, + scheduler::LayerHistory::LayerVoteType::NoVote); + } else if (!mUseContentDetection) { + // If the content detection feature is off, all layers are registered at Max. We still keep + // the layer history, since we use it for other features (like Frame Rate API), so layers + // still need to be registered. + mLayerHistory->registerLayer(layer, minFps, maxFps, + scheduler::LayerHistory::LayerVoteType::Max); + } else if (!mUseContentDetectionV2) { + // In V1 of content detection, all layers are registered as Heuristic (unless it's + // wallpaper). + const auto highFps = + layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER ? minFps : maxFps; + + mLayerHistory->registerLayer(layer, minFps, highFps, scheduler::LayerHistory::LayerVoteType::Heuristic); } else { if (layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER) { // Running Wallpaper at Min is considered as part of content detection. - mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(), - mRefreshRateConfigs.getMaxRefreshRate().getFps(), + mLayerHistory->registerLayer(layer, minFps, maxFps, scheduler::LayerHistory::LayerVoteType::Min); - } else if (layer->getWindowType() == InputWindowInfo::TYPE_STATUS_BAR) { - mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(), - mRefreshRateConfigs.getMaxRefreshRate().getFps(), - scheduler::LayerHistory::LayerVoteType::NoVote); } else { - mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().getFps(), - mRefreshRateConfigs.getMaxRefreshRate().getFps(), + mLayerHistory->registerLayer(layer, minFps, maxFps, scheduler::LayerHistory::LayerVoteType::Heuristic); } } @@ -526,7 +521,9 @@ void Scheduler::idleTimerCallback(TimerState state) { void Scheduler::touchTimerCallback(TimerState state) { const TouchState touch = state == TimerState::Reset ? TouchState::Active : TouchState::Inactive; - handleTimerStateChanged(&mFeatures.touch, touch, true /* eventOnContentDetection */); + if (handleTimerStateChanged(&mFeatures.touch, touch, true /* eventOnContentDetection */)) { + mLayerHistory->clear(); + } ATRACE_INT("TouchState", static_cast<int>(touch)); } @@ -549,18 +546,19 @@ void Scheduler::dump(std::string& result) const { } template <class T> -void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) { +bool Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) { ConfigEvent event = ConfigEvent::None; HwcConfigIndexType newConfigId; + bool touchConsidered = false; { std::lock_guard<std::mutex> lock(mFeatureStateLock); if (*currentState == newState) { - return; + return touchConsidered; } *currentState = newState; - newConfigId = calculateRefreshRateConfigIndexType(); + newConfigId = calculateRefreshRateConfigIndexType(&touchConsidered); if (mFeatures.configId == newConfigId) { - return; + return touchConsidered; } mFeatures.configId = newConfigId; if (eventOnContentDetection && !mFeatures.contentRequirements.empty()) { @@ -569,10 +567,12 @@ void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventO } const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); mSchedulerCallback.changeRefreshRate(newRefreshRate, event); + return touchConsidered; } -HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType() { +HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType(bool* touchConsidered) { ATRACE_CALL(); + if (touchConsidered) *touchConsidered = false; // If Display Power is not in normal operation we want to be in performance mode. When coming // back to normal mode, a grace period is given with DisplayPowerTimer. @@ -607,18 +607,9 @@ HwcConfigIndexType Scheduler::calculateRefreshRateConfigIndexType() { .getConfigId(); } - bool touchConsidered; - const auto& ret = mRefreshRateConfigs - .getBestRefreshRate(mFeatures.contentRequirements, touchActive, idle, - &touchConsidered) - .getConfigId(); - if (touchConsidered) { - // Clear layer history if refresh rate was selected based on touch to allow - // the hueristic to pick up with the new rate. - mLayerHistory->clear(); - } - - return ret; + return mRefreshRateConfigs + .getBestRefreshRate(mFeatures.contentRequirements, touchActive, idle, touchConsidered) + .getConfigId(); } std::optional<HwcConfigIndexType> Scheduler::getPreferredConfigId() { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 4a0280fe1e..6eabfd2e47 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -177,14 +177,15 @@ private: // handles various timer features to change the refresh rate. template <class T> - void handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection); + bool handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection); void setVsyncPeriod(nsecs_t period); // This function checks whether individual features that are affecting the refresh rate // selection were initialized, prioritizes them, and calculates the HwcConfigIndexType // for the suggested refresh rate. - HwcConfigIndexType calculateRefreshRateConfigIndexType() REQUIRES(mFeatureStateLock); + HwcConfigIndexType calculateRefreshRateConfigIndexType(bool* touchConsidered = nullptr) + REQUIRES(mFeatureStateLock); // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e65b80a9b4..18f789eacc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1943,13 +1943,9 @@ void SurfaceFlinger::onMessageInvalidate(nsecs_t expectedVSyncTime) { const nsecs_t jankDuration = currentTime - mMissedFrameJankStart; if (jankDuration > kMinJankyDuration && jankDuration < kMaxJankyDuration) { ATRACE_NAME("Jank detected"); - ALOGD("Detected janky event. Missed frames: %d", mMissedFrameJankCount); const int32_t jankyDurationMillis = jankDuration / (1000 * 1000); - { - ATRACE_NAME("Pushing to statsd"); - android::util::stats_write(android::util::DISPLAY_JANK_REPORTED, - jankyDurationMillis, mMissedFrameJankCount); - } + android::util::stats_write(android::util::DISPLAY_JANK_REPORTED, + jankyDurationMillis, mMissedFrameJankCount); } // We either reported a jank event or we missed the trace diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp index 431cf0f4b3..d55648ae34 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp @@ -103,12 +103,22 @@ TEST_F(LayerHistoryTestV2, oneLayer) { EXPECT_TRUE(history().summarize(time).empty()); EXPECT_EQ(0, activeLayerCount()); + // The first few updates are considered infrequent + for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { + history().record(layer.get(), 0, time); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + } + // Max returned if active layers have insufficient history. - for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { history().record(layer.get(), 0, time); ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); } // Max is returned since we have enough history but there is no timestamp votes. @@ -117,6 +127,7 @@ TEST_F(LayerHistoryTestV2, oneLayer) { ASSERT_EQ(1, history().summarize(time).size()); EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); } } @@ -134,7 +145,7 @@ TEST_F(LayerHistoryTestV2, oneInvisibleLayer) { auto summary = history().summarize(time); ASSERT_EQ(1, history().summarize(time).size()); // Layer is still considered inactive so we expect to get Min - EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); @@ -464,28 +475,15 @@ TEST_F(LayerHistoryTestV2, inactiveLayers) { nsecs_t time = systemTime(); - // the very first updates makes the layer frequent + // The first few updates are considered infrequent for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE - 1; i++) { - history().record(layer.get(), time, time); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - - EXPECT_EQ(1, layerCount()); + history().record(layer.get(), 0, time); ASSERT_EQ(1, history().summarize(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(1, frequentLayerCount(time)); + EXPECT_EQ(0, frequentLayerCount(time)); } - // the next update with the MAX_FREQUENT_LAYER_PERIOD_NS will get us to infrequent - history().record(layer.get(), time, time); - time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); - - EXPECT_EQ(1, layerCount()); - ASSERT_EQ(1, history().summarize(time).size()); - EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); - EXPECT_EQ(1, activeLayerCount()); - EXPECT_EQ(0, frequentLayerCount(time)); - // advance the time for the previous frame to be inactive time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); @@ -528,9 +526,11 @@ TEST_F(LayerHistoryTestV2, invisibleExplicitLayer) { nsecs_t time = systemTime(); - // Post a buffer to the layers to make them active - history().record(explicitVisiblelayer.get(), time, time); - history().record(explicitInvisiblelayer.get(), time, time); + // Post a few buffers to the layers to make them active + for (int i = 0; i < FREQUENT_LAYER_WINDOW_SIZE; i++) { + history().record(explicitVisiblelayer.get(), time, time); + history().record(explicitInvisiblelayer.get(), time, time); + } EXPECT_EQ(2, layerCount()); ASSERT_EQ(1, history().summarize(time).size()); diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 2b168b2cf2..692f71f8d3 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -340,15 +340,14 @@ TEST_F(RefreshRateConfigsTest, getBestRefreshRate_noLayers) { std::make_unique<RefreshRateConfigs>(m60_72_90Device, /*currentConfigId=*/ HWC_CONFIG_ID_72); - // If there are not layers, there is not content detection, so return the current - // refresh rate. + // If there are no layers we select the default frame rate, which is the max of the primary + // range. auto layers = std::vector<LayerRequirement>{}; - EXPECT_EQ(mExpected72Config, + EXPECT_EQ(mExpected90Config, refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false, &ignored)); - // Current refresh rate can always be changed. - refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_60); + ASSERT_GE(refreshRateConfigs->setDisplayManagerPolicy({HWC_CONFIG_ID_60, {60, 60}}), 0); EXPECT_EQ(mExpected60Config, refreshRateConfigs->getBestRefreshRate(layers, /*touchActive*/ false, /*idle*/ false, &ignored)); |