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

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

Merge "Default refresh rate for concurrent displays"

parents 6f621bbc 9714a08e
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -337,6 +337,9 @@ public final class DisplayInfo implements Parcelable {
    @Nullable
    public DisplayShape displayShape;

    @Nullable
    public SurfaceControl.RefreshRateRange layoutLimitedRefreshRate;

    public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
        @Override
        public DisplayInfo createFromParcel(Parcel source) {
@@ -411,7 +414,8 @@ public final class DisplayInfo implements Parcelable {
                && brightnessDefault == other.brightnessDefault
                && Objects.equals(roundedCorners, other.roundedCorners)
                && installOrientation == other.installOrientation
                && Objects.equals(displayShape, other.displayShape);
                && Objects.equals(displayShape, other.displayShape)
                && Objects.equals(layoutLimitedRefreshRate, other.layoutLimitedRefreshRate);
    }

    @Override
@@ -466,6 +470,7 @@ public final class DisplayInfo implements Parcelable {
        roundedCorners = other.roundedCorners;
        installOrientation = other.installOrientation;
        displayShape = other.displayShape;
        layoutLimitedRefreshRate = other.layoutLimitedRefreshRate;
    }

    public void readFromParcel(Parcel source) {
@@ -526,6 +531,7 @@ public final class DisplayInfo implements Parcelable {
        }
        installOrientation = source.readInt();
        displayShape = source.readTypedObject(DisplayShape.CREATOR);
        layoutLimitedRefreshRate = source.readTypedObject(SurfaceControl.RefreshRateRange.CREATOR);
    }

    @Override
@@ -584,6 +590,7 @@ public final class DisplayInfo implements Parcelable {
        }
        dest.writeInt(installOrientation);
        dest.writeTypedObject(displayShape, flags);
        dest.writeTypedObject(layoutLimitedRefreshRate, flags);
    }

    @Override
@@ -843,6 +850,8 @@ public final class DisplayInfo implements Parcelable {
        sb.append(brightnessDefault);
        sb.append(", installOrientation ");
        sb.append(Surface.rotationToString(installOrientation));
        sb.append(", layoutLimitedRefreshRate ");
        sb.append(layoutLimitedRefreshRate);
        sb.append("}");
        return sb.toString();
    }
+30 −1
Original line number Diff line number Diff line
@@ -1757,7 +1757,7 @@ public final class SurfaceControl implements Parcelable {
     * Information about the min and max refresh rate DM would like to set the display to.
     * @hide
     */
    public static final class RefreshRateRange {
    public static final class RefreshRateRange implements Parcelable {
        public static final String TAG = "RefreshRateRange";

        // The tolerance within which we consider something approximately equals.
@@ -1826,6 +1826,35 @@ public final class SurfaceControl implements Parcelable {
            this.min = other.min;
            this.max = other.max;
        }

        /**
         * Writes the RefreshRateRange to parce
         *
         * @param dest parcel to write the transaction to
         */
        @Override
        public void writeToParcel(@NonNull Parcel dest, @WriteFlags int flags) {
            dest.writeFloat(min);
            dest.writeFloat(max);
        }

        @Override
        public int describeContents() {
            return 0;
        }

        public static final @NonNull Creator<RefreshRateRange> CREATOR =
                new Creator<RefreshRateRange>() {
                    @Override
                    public RefreshRateRange createFromParcel(Parcel in) {
                        return new RefreshRateRange(in.readFloat(), in.readFloat());
                    }

                    @Override
                    public RefreshRateRange[] newArray(int size) {
                        return new RefreshRateRange[size];
                    }
                };
    }

    /**
+1 −0
Original line number Diff line number Diff line
@@ -133,6 +133,7 @@ class DeviceStateToLayoutMap {
                    } else {
                        display.setPosition(POSITION_UNKNOWN);
                    }
                    display.setRefreshRateZoneId(d.getRefreshRateZoneId());
                }
            }
        } catch (IOException | DatatypeConfigurationException | XmlPullParserException e) {
+42 −3
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.util.Pair;
import android.util.Slog;
import android.util.Spline;
import android.view.DisplayAddress;
import android.view.SurfaceControl;

import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting;
@@ -53,6 +54,7 @@ import com.android.server.display.config.NitsMap;
import com.android.server.display.config.Point;
import com.android.server.display.config.RefreshRateConfigs;
import com.android.server.display.config.RefreshRateRange;
import com.android.server.display.config.RefreshRateZone;
import com.android.server.display.config.SdrHdrRatioMap;
import com.android.server.display.config.SdrHdrRatioPoint;
import com.android.server.display.config.SensorDetails;
@@ -503,10 +505,10 @@ public class DisplayDeviceConfig {
    /**
     * Array of light sensor lux values to define our levels for auto backlight
     * brightness support.

     *
     * The N + 1 entries of this array define N control points defined in mBrightnessLevelsNits,
     * with first value always being 0 lux

     *
     * The control points must be strictly increasing.  Each control point
     * corresponds to an entry in the brightness backlight values arrays.
     * For example, if lux == level[1] (second element of the levels array)
@@ -515,7 +517,6 @@ public class DisplayDeviceConfig {
     *
     * Spline interpolation is used to determine the auto-brightness
     * backlight values for lux levels between these control points.
     *
     */
    private float[] mBrightnessLevelsLux;

@@ -619,6 +620,10 @@ public class DisplayDeviceConfig {
     */
    private int mDefaultLowBlockingZoneRefreshRate = DEFAULT_LOW_REFRESH_RATE;

    // Refresh rate profiles, currently only for concurrent mode profile and controlled by Layout
    private final Map<String, SurfaceControl.RefreshRateRange> mRefreshRateZoneProfiles =
            new HashMap<>();

    /**
     * The display uses different gamma curves for different refresh rates. It's hard for panel
     * vendors to tune the curves to have exact same brightness for different refresh rate. So
@@ -1353,6 +1358,23 @@ public class DisplayDeviceConfig {
        return mDefaultLowBlockingZoneRefreshRate;
    }

    /**
     * @return Refresh rate range for specific profile id or null
     */
    @Nullable
    public SurfaceControl.RefreshRateRange getRefreshRange(@Nullable String id) {
        if (TextUtils.isEmpty(id)) {
            return null;
        }
        return mRefreshRateZoneProfiles.get(id);
    }

    @NonNull
    @VisibleForTesting
    Map<String, SurfaceControl.RefreshRateRange> getRefreshRangeProfiles() {
        return mRefreshRateZoneProfiles;
    }

    /**
     * @return An array of lower display brightness thresholds. This, in combination with lower
     * ambient brightness thresholds help define buckets in which the refresh rate switching is not
@@ -1500,6 +1522,7 @@ public class DisplayDeviceConfig {
                + ", mDefaultHighBlockingZoneRefreshRate= " + mDefaultHighBlockingZoneRefreshRate
                + ", mDefaultPeakRefreshRate= " + mDefaultPeakRefreshRate
                + ", mDefaultRefreshRate= " + mDefaultRefreshRate
                + ", mRefreshRateZoneProfiles= " + mRefreshRateZoneProfiles
                + ", mLowDisplayBrightnessThresholds= "
                + Arrays.toString(mLowDisplayBrightnessThresholds)
                + ", mLowAmbientBrightnessThresholds= "
@@ -1828,6 +1851,7 @@ public class DisplayDeviceConfig {
        loadDefaultRefreshRate(refreshRateConfigs);
        loadLowerRefreshRateBlockingZones(lowerBlockingZoneConfig);
        loadHigherRefreshRateBlockingZones(higherBlockingZoneConfig);
        loadRefreshRateZoneProfiles(refreshRateConfigs);
    }

    private void loadPeakDefaultRefreshRate(RefreshRateConfigs refreshRateConfigs) {
@@ -1850,6 +1874,21 @@ public class DisplayDeviceConfig {
        }
    }

    /** Loads the refresh rate profiles. */
    private void loadRefreshRateZoneProfiles(RefreshRateConfigs refreshRateConfigs) {
        if (refreshRateConfigs == null) {
            return;
        }
        for (RefreshRateZone zone :
                refreshRateConfigs.getRefreshRateZoneProfiles().getRefreshRateZoneProfile()) {
            RefreshRateRange range = zone.getRefreshRateRange();
            mRefreshRateZoneProfiles.put(
                    zone.getId(),
                    new SurfaceControl.RefreshRateRange(
                            range.getMinimum().floatValue(), range.getMaximum().floatValue()));
        }
    }

    /**
     * Loads the refresh rate configurations pertaining to the upper blocking zones.
     */
+36 −11
Original line number Diff line number Diff line
@@ -159,7 +159,6 @@ public class DisplayModeDirector {
        mSupportedModesByDisplay = new SparseArray<>();
        mDefaultModeByDisplay = new SparseArray<>();
        mAppRequestObserver = new AppRequestObserver();
        mDisplayObserver = new DisplayObserver(context, handler);
        mDeviceConfig = injector.getDeviceConfig();
        mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
        mSettingsObserver = new SettingsObserver(context, handler);
@@ -170,6 +169,7 @@ public class DisplayModeDirector {
                updateVoteLocked(displayId, priority, vote);
            }
        };
        mDisplayObserver = new DisplayObserver(context, handler, ballotBox);
        mSensorObserver = new SensorObserver(context, ballotBox, injector);
        mSkinThermalStatusObserver = new SkinThermalStatusObserver(injector, ballotBox);
        mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler(),
@@ -1186,26 +1186,29 @@ public class DisplayModeDirector {
        // rest of low priority voters. It votes [0, max(PEAK, MIN)]
        public static final int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 7;

        // For concurrent displays we want to limit refresh rate on all displays
        public static final int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 8;

        // LOW_POWER_MODE force the render frame rate to [0, 60HZ] if
        // Settings.Global.LOW_POWER_MODE is on.
        public static final int PRIORITY_LOW_POWER_MODE = 8;
        public static final int PRIORITY_LOW_POWER_MODE = 9;

        // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the
        // higher priority voters' result is a range, it will fix the rate to a single choice.
        // It's used to avoid refresh rate switches in certain conditions which may result in the
        // user seeing the display flickering when the switches occur.
        public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 9;
        public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 10;

        // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
        public static final int PRIORITY_SKIN_TEMPERATURE = 10;
        public static final int PRIORITY_SKIN_TEMPERATURE = 11;

        // The proximity sensor needs the refresh rate to be locked in order to function, so this is
        // set to a high priority.
        public static final int PRIORITY_PROXIMITY = 11;
        public static final int PRIORITY_PROXIMITY = 12;

        // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
        // to function, so this needs to be the highest priority of all votes.
        public static final int PRIORITY_UDFPS = 12;
        public static final int PRIORITY_UDFPS = 13;

        // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
        // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
@@ -1657,10 +1660,12 @@ public class DisplayModeDirector {
        // calling into us already holding its own lock.
        private final Context mContext;
        private final Handler mHandler;
        private final BallotBox mBallotBox;

        DisplayObserver(Context context, Handler handler) {
        DisplayObserver(Context context, Handler handler, BallotBox ballotBox) {
            mContext = context;
            mHandler = handler;
            mBallotBox = ballotBox;
        }

        public void observe() {
@@ -1689,7 +1694,9 @@ public class DisplayModeDirector {

        @Override
        public void onDisplayAdded(int displayId) {
            updateDisplayModes(displayId);
            DisplayInfo displayInfo = getDisplayInfo(displayId);
            updateDisplayModes(displayId, displayInfo);
            updateLayoutLimitedFrameRate(displayId, displayInfo);
        }

        @Override
@@ -1698,23 +1705,41 @@ public class DisplayModeDirector {
                mSupportedModesByDisplay.remove(displayId);
                mDefaultModeByDisplay.remove(displayId);
            }
            updateLayoutLimitedFrameRate(displayId, null);
        }

        @Override
        public void onDisplayChanged(int displayId) {
            updateDisplayModes(displayId);
            DisplayInfo displayInfo = getDisplayInfo(displayId);
            updateDisplayModes(displayId, displayInfo);
            updateLayoutLimitedFrameRate(displayId, displayInfo);
        }

        private void updateDisplayModes(int displayId) {
        @Nullable
        private DisplayInfo getDisplayInfo(int displayId) {
            Display d = mContext.getSystemService(DisplayManager.class).getDisplay(displayId);
            if (d == null) {
                // We can occasionally get a display added or changed event for a display that was
                // subsequently removed, which means this returns null. Check this case and bail
                // out early; if it gets re-attached we'll eventually get another call back for it.
                return;
                return null;
            }
            DisplayInfo info = new DisplayInfo();
            d.getDisplayInfo(info);
            return info;
        }

        private void updateLayoutLimitedFrameRate(int displayId, @Nullable DisplayInfo info) {
            Vote vote = info != null && info.layoutLimitedRefreshRate != null
                    ? Vote.forPhysicalRefreshRates(info.layoutLimitedRefreshRate.min,
                    info.layoutLimitedRefreshRate.max) : null;
            mBallotBox.vote(displayId, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE, vote);
        }

        private void updateDisplayModes(int displayId, @Nullable DisplayInfo info) {
            if (info == null) {
                return;
            }
            boolean changed = false;
            synchronized (mLock) {
                if (!Arrays.equals(mSupportedModesByDisplay.get(displayId), info.supportedModes)) {
Loading