Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6c8e08e authored by Oleg Petšjonkin's avatar Oleg Petšjonkin Committed by Android (Google) Code Review
Browse files

Merge "DisplayMode director refres rate votes telemetry" into main

parents 664fe94b 90e128b1
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -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 {
+7 −0
Original line number Diff line number Diff line
@@ -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
}
+22 −1
Original line number Diff line number Diff line
@@ -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
@@ -2821,6 +2832,9 @@ public class DisplayModeDirector {
        StatusBarManagerInternal getStatusBarManagerInternal();

        SensorManagerInternal getSensorManagerInternal();

        @Nullable
        VotesStatsReporter getVotesStatsReporter(boolean refreshRateVotingTelemetryEnabled);
    }

    @VisibleForTesting
@@ -2953,6 +2967,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);
+93 −0
Original line number Diff line number Diff line
/*
 * 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;
    }
}
+17 −20
Original line number Diff line number Diff line
@@ -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();
    }
Loading