VRR: Allowlist for small area detection
Add a allowlist mechanism for suppress frame rate when small area.
In this patch, we will keep a array list to record pkg name which
want to apply the small area detection for suppressing frame rate
and its threshold value of small area ratio.
In framewokr, we will check the all pkg uid by pkg name from
package manager and call a native function which include uid and
threshold.
In SF native, it get the threshold of uid and we will save them
as a map, and it will used to check should it apply small area
detection and what threshold it should use.
Bug: 281720315
Test: atest SmallAreaDetectionMappingsTest
Test: atest LayerHistoryTest
Change-Id: Iaf6c0090f9db499fc5ed097b2d3c6d9d871d4812
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp
index 13cf764..c92e670 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.cpp
+++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp
@@ -306,9 +306,9 @@
return {LayerStatus::NotFound, nullptr};
}
-bool LayerHistory::isSmallDirtyArea(uint32_t dirtyArea) const {
+bool LayerHistory::isSmallDirtyArea(uint32_t dirtyArea, float threshold) const {
const float ratio = (float)dirtyArea / mDisplayArea;
- const bool isSmallDirty = ratio <= kSmallDirtyArea;
+ const bool isSmallDirty = ratio <= threshold;
ATRACE_FORMAT_INSTANT("small dirty=%s, ratio=%.3f", isSmallDirty ? "true" : "false", ratio);
return isSmallDirty;
}
diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h
index 562bb4c..5750ea7 100644
--- a/services/surfaceflinger/Scheduler/LayerHistory.h
+++ b/services/surfaceflinger/Scheduler/LayerHistory.h
@@ -85,14 +85,12 @@
// return the frames per second of the layer with the given sequence id.
float getLayerFramerate(nsecs_t now, int32_t id) const;
- bool isSmallDirtyArea(uint32_t dirtyArea) const;
+ bool isSmallDirtyArea(uint32_t dirtyArea, float threshold) const;
private:
friend class LayerHistoryTest;
friend class TestableScheduler;
- static constexpr float kSmallDirtyArea = 0.07f;
-
using LayerPair = std::pair<Layer*, std::unique_ptr<LayerInfo>>;
// keyed by id as returned from Layer::getSequence()
using LayerInfos = std::unordered_map<int32_t, LayerPair>;
diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp
index 5a19ec5..27c96f7 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.cpp
+++ b/services/surfaceflinger/Scheduler/Scheduler.cpp
@@ -1179,4 +1179,20 @@
mFrameRateOverrideMappings.setPreferredRefreshRateForUid(frameRateOverride);
}
+void Scheduler::updateSmallAreaDetection(
+ std::vector<std::pair<uid_t, float>>& uidThresholdMappings) {
+ mSmallAreaDetectionAllowMappings.update(uidThresholdMappings);
+}
+
+void Scheduler::setSmallAreaDetectionThreshold(uid_t uid, float threshold) {
+ mSmallAreaDetectionAllowMappings.setThesholdForUid(uid, threshold);
+}
+
+bool Scheduler::isSmallDirtyArea(uid_t uid, uint32_t dirtyArea) {
+ std::optional<float> oThreshold = mSmallAreaDetectionAllowMappings.getThresholdForUid(uid);
+ if (oThreshold) return mLayerHistory.isSmallDirtyArea(dirtyArea, oThreshold.value());
+
+ return false;
+}
+
} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h
index ec20610..d65df2a 100644
--- a/services/surfaceflinger/Scheduler/Scheduler.h
+++ b/services/surfaceflinger/Scheduler/Scheduler.h
@@ -49,6 +49,7 @@
#include "MessageQueue.h"
#include "OneShotTimer.h"
#include "RefreshRateSelector.h"
+#include "SmallAreaDetectionAllowMappings.h"
#include "Utils/Dumper.h"
#include "VsyncModulator.h"
@@ -291,6 +292,13 @@
void setGameModeRefreshRateForUid(FrameRateOverride);
+ void updateSmallAreaDetection(std::vector<std::pair<uid_t, float>>& uidThresholdMappings);
+
+ void setSmallAreaDetectionThreshold(uid_t uid, float threshold);
+
+ // Returns true if the dirty area is less than threshold.
+ bool isSmallDirtyArea(uid_t uid, uint32_t dirtyArea);
+
// Retrieves the overridden refresh rate for a given uid.
std::optional<Fps> getFrameRateOverride(uid_t) const EXCLUDES(mDisplayLock);
@@ -314,11 +322,6 @@
return mFeatures.test(Feature::kSmallDirtyContentDetection);
}
- // Returns true if the dirty area is less than threshold.
- bool isSmallDirtyArea(uint32_t dirtyArea) const {
- return mLayerHistory.isSmallDirtyArea(dirtyArea);
- }
-
private:
friend class TestableScheduler;
@@ -557,6 +560,7 @@
static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms;
FrameRateOverrideMappings mFrameRateOverrideMappings;
+ SmallAreaDetectionAllowMappings mSmallAreaDetectionAllowMappings;
};
} // namespace scheduler
diff --git a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp
new file mode 100644
index 0000000..95cd5d1
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2023 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 <sys/types.h>
+
+#include "SmallAreaDetectionAllowMappings.h"
+
+namespace android::scheduler {
+void SmallAreaDetectionAllowMappings::update(
+ std::vector<std::pair<uid_t, float>>& uidThresholdMappings) {
+ std::lock_guard lock(mLock);
+ mMap.clear();
+ for (std::pair<uid_t, float> row : uidThresholdMappings) {
+ if (!isValidThreshold(row.second)) continue;
+
+ mMap.emplace(row.first, row.second);
+ }
+}
+
+void SmallAreaDetectionAllowMappings::setThesholdForUid(uid_t uid, float threshold) {
+ if (!isValidThreshold(threshold)) return;
+
+ std::lock_guard lock(mLock);
+ mMap.emplace(uid, threshold);
+}
+
+std::optional<float> SmallAreaDetectionAllowMappings::getThresholdForUid(uid_t uid) {
+ std::lock_guard lock(mLock);
+ const auto iter = mMap.find(uid);
+ if (iter != mMap.end()) {
+ return iter->second;
+ }
+ return std::nullopt;
+}
+} // namespace android::scheduler
diff --git a/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h
new file mode 100644
index 0000000..cbab690
--- /dev/null
+++ b/services/surfaceflinger/Scheduler/SmallAreaDetectionAllowMappings.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2023 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 <android-base/thread_annotations.h>
+#include <sys/types.h>
+#include <optional>
+#include <unordered_map>
+#include <vector>
+
+namespace android::scheduler {
+class SmallAreaDetectionAllowMappings {
+ using UidThresholdMap = std::unordered_map<uid_t, float>;
+
+public:
+ void update(std::vector<std::pair<uid_t, float>>& uidThresholdMappings);
+ void setThesholdForUid(uid_t uid, float threshold) EXCLUDES(mLock);
+ std::optional<float> getThresholdForUid(uid_t uid) EXCLUDES(mLock);
+
+private:
+ static bool isValidThreshold(float threshold) { return threshold >= 0.0f && threshold <= 1.0f; }
+ mutable std::mutex mLock;
+ UidThresholdMap mMap GUARDED_BY(mLock);
+};
+} // namespace android::scheduler