1 /* 2 * Copyright (C) 2024 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.display.mode; 18 19 import static com.android.internal.util.FrameworkStatsLog.DISPLAY_MODE_DIRECTOR_VOTE_CHANGED; 20 import static com.android.internal.util.FrameworkStatsLog.DISPLAY_MODE_DIRECTOR_VOTE_CHANGED__VOTE_STATUS__STATUS_ACTIVE; 21 import static com.android.internal.util.FrameworkStatsLog.DISPLAY_MODE_DIRECTOR_VOTE_CHANGED__VOTE_STATUS__STATUS_ADDED; 22 import static com.android.internal.util.FrameworkStatsLog.DISPLAY_MODE_DIRECTOR_VOTE_CHANGED__VOTE_STATUS__STATUS_REMOVED; 23 24 import android.annotation.NonNull; 25 import android.annotation.Nullable; 26 import android.os.Trace; 27 import android.util.SparseArray; 28 import android.util.SparseIntArray; 29 import android.view.Display; 30 31 import com.android.internal.util.FrameworkStatsLog; 32 33 /** 34 * The VotesStatsReporter is responsible for collecting and sending Vote related statistics 35 */ 36 class VotesStatsReporter { 37 private static final String TAG = "VotesStatsReporter"; 38 private static final int REFRESH_RATE_NOT_LIMITED = 1000; 39 private final boolean mIgnoredRenderRate; 40 41 private final SparseIntArray mLastMinPriorityByDisplay = new SparseIntArray(); 42 VotesStatsReporter(boolean ignoreRenderRate)43 VotesStatsReporter(boolean ignoreRenderRate) { 44 mIgnoredRenderRate = ignoreRenderRate; 45 } 46 reportVoteChanged(int displayId, int priority, @Nullable Vote vote)47 void reportVoteChanged(int displayId, int priority, @Nullable Vote vote) { 48 if (vote == null) { 49 reportVoteRemoved(displayId, priority); 50 } else { 51 reportVoteAdded(displayId, priority, vote); 52 } 53 } 54 reportVoteAdded(int displayId, int priority, @NonNull Vote vote)55 private void reportVoteAdded(int displayId, int priority, @NonNull Vote vote) { 56 int maxRefreshRate = getMaxRefreshRate(vote, mIgnoredRenderRate); 57 Trace.traceCounter(Trace.TRACE_TAG_POWER, 58 TAG + "." + displayId + ":" + Vote.priorityToString(priority), maxRefreshRate); 59 FrameworkStatsLog.write( 60 DISPLAY_MODE_DIRECTOR_VOTE_CHANGED, displayId, priority, 61 DISPLAY_MODE_DIRECTOR_VOTE_CHANGED__VOTE_STATUS__STATUS_ADDED, 62 maxRefreshRate, -1); 63 } 64 reportVoteRemoved(int displayId, int priority)65 private void reportVoteRemoved(int displayId, int priority) { 66 Trace.traceCounter(Trace.TRACE_TAG_POWER, 67 TAG + "." + displayId + ":" + Vote.priorityToString(priority), -1); 68 FrameworkStatsLog.write( 69 DISPLAY_MODE_DIRECTOR_VOTE_CHANGED, displayId, priority, 70 DISPLAY_MODE_DIRECTOR_VOTE_CHANGED__VOTE_STATUS__STATUS_REMOVED, -1, -1); 71 } 72 reportVotesActivated(int displayId, int minPriority, @Nullable Display.Mode baseMode, SparseArray<Vote> votes)73 void reportVotesActivated(int displayId, int minPriority, @Nullable Display.Mode baseMode, 74 SparseArray<Vote> votes) { 75 int lastMinPriorityReported = mLastMinPriorityByDisplay.get( 76 displayId, Vote.MAX_PRIORITY + 1); 77 int selectedRefreshRate = baseMode != null ? (int) baseMode.getRefreshRate() : -1; 78 for (int priority = Vote.MIN_PRIORITY; priority <= Vote.MAX_PRIORITY; priority++) { 79 if (priority < lastMinPriorityReported && priority < minPriority) { 80 continue; 81 } 82 Vote vote = votes.get(priority); 83 if (vote == null) { 84 continue; 85 } 86 87 // Was previously reported ACTIVE, changed to ADDED 88 if (priority >= lastMinPriorityReported && priority < minPriority) { 89 int maxRefreshRate = getMaxRefreshRate(vote, mIgnoredRenderRate); 90 FrameworkStatsLog.write( 91 DISPLAY_MODE_DIRECTOR_VOTE_CHANGED, displayId, priority, 92 DISPLAY_MODE_DIRECTOR_VOTE_CHANGED__VOTE_STATUS__STATUS_ADDED, 93 maxRefreshRate, selectedRefreshRate); 94 } 95 // Was previously reported ADDED, changed to ACTIVE 96 if (priority >= minPriority && priority < lastMinPriorityReported) { 97 int maxRefreshRate = getMaxRefreshRate(vote, mIgnoredRenderRate); 98 FrameworkStatsLog.write( 99 DISPLAY_MODE_DIRECTOR_VOTE_CHANGED, displayId, priority, 100 DISPLAY_MODE_DIRECTOR_VOTE_CHANGED__VOTE_STATUS__STATUS_ACTIVE, 101 maxRefreshRate, selectedRefreshRate); 102 } 103 104 mLastMinPriorityByDisplay.put(displayId, minPriority); 105 } 106 } 107 getMaxRefreshRate(@onNull Vote vote, boolean ignoreRenderRate)108 private static int getMaxRefreshRate(@NonNull Vote vote, boolean ignoreRenderRate) { 109 int maxRefreshRate = REFRESH_RATE_NOT_LIMITED; 110 if (vote instanceof RefreshRateVote.PhysicalVote physicalVote) { 111 maxRefreshRate = (int) physicalVote.mMaxRefreshRate; 112 } else if (!ignoreRenderRate && (vote instanceof RefreshRateVote.RenderVote renderVote)) { 113 maxRefreshRate = (int) renderVote.mMaxRefreshRate; 114 } else if (vote instanceof SupportedRefreshRatesVote refreshRatesVote) { 115 // SupportedRefreshRatesVote limits mode by refreshRates, so highest rr is allowed 116 maxRefreshRate = 0; 117 for (SupportedRefreshRatesVote.RefreshRates rr : refreshRatesVote.mRefreshRates) { 118 maxRefreshRate = Math.max(maxRefreshRate, (int) rr.mPeakRefreshRate); 119 } 120 } else if (vote instanceof CombinedVote combinedVote) { 121 for (Vote subVote: combinedVote.mVotes) { 122 // CombinedVote should not have CombinedVote in mVotes, so recursion depth will be 1 123 maxRefreshRate = Math.min(maxRefreshRate, 124 getMaxRefreshRate(subVote, ignoreRenderRate)); 125 } 126 } 127 return maxRefreshRate; 128 } 129 } 130