summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/display/feature/DisplayManagerFlags.java10
-rw-r--r--services/core/java/com/android/server/display/feature/display_flags.aconfig7
-rw-r--r--services/core/java/com/android/server/display/mode/DisplayModeDirector.java23
-rw-r--r--services/core/java/com/android/server/display/mode/VotesStatsReporter.java93
-rw-r--r--services/core/java/com/android/server/display/mode/VotesStorage.java37
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java5
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java2
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/mode/VotesStorageTest.java2
8 files changed, 156 insertions, 23 deletions
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index aa7f07d24dbf..35991b356bba 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -109,6 +109,11 @@ public class DisplayManagerFlags {
Flags.FLAG_FAST_HDR_TRANSITIONS,
Flags::fastHdrTransitions);
+ private final FlagState mRefreshRateVotingTelemetry = new FlagState(
+ Flags.FLAG_REFRESH_RATE_VOTING_TELEMETRY,
+ Flags::refreshRateVotingTelemetry
+ );
+
/** Returns whether connected display management is enabled or not. */
public boolean isConnectedDisplayManagementEnabled() {
return mConnectedDisplayManagementFlagState.isEnabled();
@@ -220,6 +225,10 @@ public class DisplayManagerFlags {
return mFastHdrTransitions.isEnabled();
}
+ public boolean isRefreshRateVotingTelemetryEnabled() {
+ return mRefreshRateVotingTelemetry.isEnabled();
+ }
+
/**
* dumps all flagstates
* @param pw printWriter
@@ -242,6 +251,7 @@ public class DisplayManagerFlags {
pw.println(" " + mBrightnessWearBedtimeModeClamperFlagState);
pw.println(" " + mAutoBrightnessModesFlagState);
pw.println(" " + mFastHdrTransitions);
+ pw.println(" " + mRefreshRateVotingTelemetry);
}
private static class FlagState {
diff --git a/services/core/java/com/android/server/display/feature/display_flags.aconfig b/services/core/java/com/android/server/display/feature/display_flags.aconfig
index 04ecbb9e08ad..e735282a496e 100644
--- a/services/core/java/com/android/server/display/feature/display_flags.aconfig
+++ b/services/core/java/com/android/server/display/feature/display_flags.aconfig
@@ -161,3 +161,10 @@ flag {
is_fixed_read_only: true
}
+flag {
+ name: "refresh_rate_voting_telemetry"
+ namespace: "display_manager"
+ description: "Feature flag for enabling telemetry for refresh rate voting in DisplayManager"
+ bug: "310029108"
+ is_fixed_read_only: true
+}
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 6e503cbd68f3..e9fc9d1e8a46 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -154,6 +154,9 @@ public class DisplayModeDirector {
private final VotesStorage mVotesStorage;
+ @Nullable
+ private final VotesStatsReporter mVotesStatsReporter;
+
/**
* The allowed refresh rate switching type. This is used by SurfaceFlinger.
*/
@@ -204,6 +207,8 @@ public class DisplayModeDirector {
mContext = context;
mHandler = new DisplayModeDirectorHandler(handler.getLooper());
mInjector = injector;
+ mVotesStatsReporter = injector.getVotesStatsReporter(
+ displayManagerFlags.isRefreshRateVotingTelemetryEnabled());
mSupportedModesByDisplay = new SparseArray<>();
mDefaultModeByDisplay = new SparseArray<>();
mAppRequestObserver = new AppRequestObserver();
@@ -214,7 +219,8 @@ public class DisplayModeDirector {
mBrightnessObserver = new BrightnessObserver(context, handler, injector);
mDefaultDisplayDeviceConfig = null;
mUdfpsObserver = new UdfpsObserver();
- mVotesStorage = new VotesStorage(this::notifyDesiredDisplayModeSpecsChangedLocked);
+ mVotesStorage = new VotesStorage(this::notifyDesiredDisplayModeSpecsChangedLocked,
+ mVotesStatsReporter);
mDisplayObserver = new DisplayObserver(context, handler, mVotesStorage);
mSensorObserver = new SensorObserver(context, mVotesStorage, injector);
mSkinThermalStatusObserver = new SkinThermalStatusObserver(injector, mVotesStorage);
@@ -341,6 +347,11 @@ public class DisplayModeDirector {
appRequestSummary.limitRefreshRanges(primarySummary);
Display.Mode baseMode = primarySummary.selectBaseMode(availableModes, defaultMode);
+ if (mVotesStatsReporter != null) {
+ mVotesStatsReporter.reportVotesActivated(displayId, lowestConsideredPriority,
+ baseMode, votes);
+ }
+
if (baseMode == null) {
Slog.w(TAG, "Can't find a set of allowed modes which satisfies the votes. Falling"
+ " back to the default mode. Display = " + displayId + ", votes = " + votes
@@ -2811,6 +2822,9 @@ public class DisplayModeDirector {
StatusBarManagerInternal getStatusBarManagerInternal();
SensorManagerInternal getSensorManagerInternal();
+
+ @Nullable
+ VotesStatsReporter getVotesStatsReporter(boolean refreshRateVotingTelemetryEnabled);
}
@VisibleForTesting
@@ -2943,6 +2957,13 @@ public class DisplayModeDirector {
return LocalServices.getService(SensorManagerInternal.class);
}
+ @Override
+ public VotesStatsReporter getVotesStatsReporter(boolean refreshRateVotingTelemetryEnabled) {
+ // if frame rate override supported, renderRates will be ignored in mode selection
+ return new VotesStatsReporter(supportsFrameRateOverride(),
+ refreshRateVotingTelemetryEnabled);
+ }
+
private DisplayManager getDisplayManager() {
if (mDisplayManager == null) {
mDisplayManager = mContext.getSystemService(DisplayManager.class);
diff --git a/services/core/java/com/android/server/display/mode/VotesStatsReporter.java b/services/core/java/com/android/server/display/mode/VotesStatsReporter.java
new file mode 100644
index 000000000000..a30c4d2b5b0b
--- /dev/null
+++ b/services/core/java/com/android/server/display/mode/VotesStatsReporter.java
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package com.android.server.display.mode;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.os.Trace;
+import android.util.SparseArray;
+import android.view.Display;
+
+/**
+ * The VotesStatsReporter is responsible for collecting and sending Vote related statistics
+ */
+class VotesStatsReporter {
+ private static final String TAG = "VotesStatsReporter";
+ private static final int REFRESH_RATE_NOT_LIMITED = 1000;
+ private final boolean mIgnoredRenderRate;
+ private final boolean mFrameworkStatsLogReportingEnabled;
+
+ public VotesStatsReporter(boolean ignoreRenderRate, boolean refreshRateVotingTelemetryEnabled) {
+ mIgnoredRenderRate = ignoreRenderRate;
+ mFrameworkStatsLogReportingEnabled = refreshRateVotingTelemetryEnabled;
+ }
+
+ void reportVoteAdded(int displayId, int priority, @NonNull Vote vote) {
+ int maxRefreshRate = getMaxRefreshRate(vote, mIgnoredRenderRate);
+ Trace.traceCounter(Trace.TRACE_TAG_POWER,
+ TAG + "." + displayId + ":" + Vote.priorityToString(priority), maxRefreshRate);
+ // if ( mFrameworkStatsLogReportingEnabled) {
+ // FrameworkStatsLog.write(VOTE_CHANGED, displayID, priority, ADDED, maxRefreshRate, -1);
+ // }
+ }
+
+ void reportVoteRemoved(int displayId, int priority) {
+ Trace.traceCounter(Trace.TRACE_TAG_POWER,
+ TAG + "." + displayId + ":" + Vote.priorityToString(priority), -1);
+ // if ( mFrameworkStatsLogReportingEnabled) {
+ // FrameworkStatsLog.write(VOTE_CHANGED, displayID, priority, REMOVED, -1, -1);
+ // }
+ }
+
+ void reportVotesActivated(int displayId, int minPriority, @Nullable Display.Mode baseMode,
+ SparseArray<Vote> votes) {
+// if (!mFrameworkStatsLogReportingEnabled) {
+// return;
+// }
+// int selectedRefreshRate = baseMode != null ? (int) baseMode.getRefreshRate() : -1;
+// for (int priority = minPriority; priority <= Vote.MAX_PRIORITY; priority ++) {
+// Vote vote = votes.get(priority);
+// if (vote != null) {
+// int maxRefreshRate = getMaxRefreshRate(vote, mIgnoredRenderRate);
+// FrameworkStatsLog.write(VOTE_CHANGED, displayId, priority,
+// ACTIVE, maxRefreshRate, selectedRefreshRate);
+// }
+// }
+ }
+
+ private static int getMaxRefreshRate(@NonNull Vote vote, boolean ignoreRenderRate) {
+ int maxRefreshRate = REFRESH_RATE_NOT_LIMITED;
+ if (vote instanceof RefreshRateVote.PhysicalVote physicalVote) {
+ maxRefreshRate = (int) physicalVote.mMaxRefreshRate;
+ } else if (!ignoreRenderRate && (vote instanceof RefreshRateVote.RenderVote renderVote)) {
+ maxRefreshRate = (int) renderVote.mMaxRefreshRate;
+ } else if (vote instanceof SupportedModesVote supportedModesVote) {
+ // SupportedModesVote limits mode by specific refreshRates, so highest rr is allowed
+ maxRefreshRate = 0;
+ for (SupportedModesVote.SupportedMode mode : supportedModesVote.mSupportedModes) {
+ maxRefreshRate = Math.max(maxRefreshRate, (int) mode.mPeakRefreshRate);
+ }
+ } else if (vote instanceof CombinedVote combinedVote) {
+ for (Vote subVote: combinedVote.mVotes) {
+ // CombinedVote should not have CombinedVote in mVotes, so recursion depth will be 1
+ maxRefreshRate = Math.min(maxRefreshRate,
+ getMaxRefreshRate(subVote, ignoreRenderRate));
+ }
+ }
+ return maxRefreshRate;
+ }
+}
diff --git a/services/core/java/com/android/server/display/mode/VotesStorage.java b/services/core/java/com/android/server/display/mode/VotesStorage.java
index 95fb8fc0947a..7a1f7e9d857c 100644
--- a/services/core/java/com/android/server/display/mode/VotesStorage.java
+++ b/services/core/java/com/android/server/display/mode/VotesStorage.java
@@ -18,7 +18,6 @@ package com.android.server.display.mode;
import android.annotation.NonNull;
import android.annotation.Nullable;
-import android.os.Trace;
import android.util.Slog;
import android.util.SparseArray;
@@ -38,6 +37,9 @@ class VotesStorage {
private final Listener mListener;
+ @Nullable
+ private final VotesStatsReporter mVotesStatsReporter;
+
private final Object mStorageLock = new Object();
// A map from the display ID to the collection of votes and their priority. The latter takes
// the form of another map from the priority to the vote itself so that each priority is
@@ -45,8 +47,9 @@ class VotesStorage {
@GuardedBy("mStorageLock")
private final SparseArray<SparseArray<Vote>> mVotesByDisplay = new SparseArray<>();
- VotesStorage(@NonNull Listener listener) {
+ VotesStorage(@NonNull Listener listener, @Nullable VotesStatsReporter votesStatsReporter) {
mListener = listener;
+ mVotesStatsReporter = votesStatsReporter;
}
/** sets logging enabled/disabled for this class */
void setLoggingEnabled(boolean loggingEnabled) {
@@ -110,17 +113,26 @@ class VotesStorage {
changed = true;
}
}
- Trace.traceCounter(Trace.TRACE_TAG_POWER,
- TAG + "." + displayId + ":" + Vote.priorityToString(priority),
- getMaxPhysicalRefreshRate(vote));
if (mLoggingEnabled) {
Slog.i(TAG, "Updated votes for display=" + displayId + " votes=" + votes);
}
if (changed) {
+ reportVoteStats(displayId, priority, vote);
mListener.onChanged();
}
}
+ private void reportVoteStats(int displayId, int priority, @Nullable Vote vote) {
+ if (mVotesStatsReporter == null) {
+ return;
+ }
+ if (vote == null) {
+ mVotesStatsReporter.reportVoteRemoved(displayId, priority);
+ } else {
+ mVotesStatsReporter.reportVoteAdded(displayId, priority, vote);
+ }
+ }
+
/** dump class values, for debugging */
void dump(@NonNull PrintWriter pw) {
SparseArray<SparseArray<Vote>> votesByDisplayLocal = new SparseArray<>();
@@ -157,21 +169,6 @@ class VotesStorage {
}
}
- private static int getMaxPhysicalRefreshRate(@Nullable Vote vote) {
- if (vote == null) {
- return -1;
- } else if (vote instanceof RefreshRateVote.PhysicalVote physicalVote) {
- return (int) physicalVote.mMaxRefreshRate;
- } else if (vote instanceof CombinedVote combinedVote) {
- return combinedVote.mVotes.stream()
- .filter(v -> v instanceof RefreshRateVote.PhysicalVote)
- .map(pv -> (int) (((RefreshRateVote.PhysicalVote) pv).mMaxRefreshRate))
- .min(Integer::compare)
- .orElse(1000); // for visualisation
- }
- return 1000; // for visualisation, otherwise e.g. -1 -> 60 will be unnoticeable
- }
-
interface Listener {
void onChanged();
}
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
index 60a0c039dd03..a0e5fd8e1b34 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/DisplayModeDirectorTest.java
@@ -3434,6 +3434,11 @@ public class DisplayModeDirectorTest {
return mSensorManagerInternal;
}
+ @Override
+ public VotesStatsReporter getVotesStatsReporter(boolean refreshRateVotingTelemetryEnabled) {
+ return null;
+ }
+
protected Display createDisplay(int id) {
return new Display(DisplayManagerGlobal.getInstance(), id, mDisplayInfo,
ApplicationProvider.getApplicationContext().getResources());
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
index f6774017c523..2815fcb764b6 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/SkinThermalStatusObserverTest.java
@@ -58,7 +58,7 @@ public class SkinThermalStatusObserverTest {
private RegisteringFakesInjector mInjector = new RegisteringFakesInjector();
private final TestHandler mHandler = new TestHandler(null);
- private final VotesStorage mStorage = new VotesStorage(() -> {});
+ private final VotesStorage mStorage = new VotesStorage(() -> {}, null);
@Before
public void setUp() {
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/VotesStorageTest.java b/services/tests/displayservicetests/src/com/android/server/display/mode/VotesStorageTest.java
index 50e239218fa0..1f6f1a41bea7 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/VotesStorageTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/VotesStorageTest.java
@@ -51,7 +51,7 @@ public class VotesStorageTest {
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mVotesStorage = new VotesStorage(mVotesListener);
+ mVotesStorage = new VotesStorage(mVotesListener, null);
}
@Test