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

Commit 7b3e40dd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes from topic "b196691596" into sc-dev

* changes:
  Separate refresh rate restrictions for different High Brightness Modes
  Limit refresh rates if skin temperature is high
parents b0cde68e 46fff422
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -1257,6 +1257,23 @@ public final class DisplayManager {
         */
        String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS =
                "fixed_refresh_rate_high_ambient_brightness_thresholds";

        /**
         * Key for refresh rate when the device is in high brightness mode for sunlight visility.
         *
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.R.integer#config_defaultRefreshRateInHbmSunlight
         */
        String KEY_REFRESH_RATE_IN_HBM_SUNLIGHT = "refresh_rate_in_hbm_sunlight";

        /**
         * Key for refresh rate when the device is in high brightness mode for HDR.
         *
         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
         * @see android.R.integer#config_defaultRefreshRateInHbmHdr
         */
        String KEY_REFRESH_RATE_IN_HBM_HDR = "refresh_rate_in_hbm_hdr";

        /**
         * Key for default peak refresh rate
         *
+7 −0
Original line number Diff line number Diff line
@@ -4492,6 +4492,13 @@
         If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
    <integer name="config_fixedRefreshRateInHighZone">0</integer>

    <!-- Default refresh rate while the device has high brightness mode enabled for Sunlight.
         This value overrides values from DisplayDeviceConfig -->
    <integer name="config_defaultRefreshRateInHbmSunlight">0</integer>

    <!-- Default refresh rate while the device has high brightness mode enabled for HDR. -->
    <integer name="config_defaultRefreshRateInHbmHdr">0</integer>

    <!-- The type of the light sensor to be used by the display framework for things like
         auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
    <string name="config_displayLightSensorType" translatable="false" />
+2 −0
Original line number Diff line number Diff line
@@ -3948,6 +3948,8 @@
  <java-symbol type="integer" name="config_defaultRefreshRateInZone" />
  <java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
  <java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
  <java-symbol type="integer" name="config_defaultRefreshRateInHbmSunlight" />
  <java-symbol type="integer" name="config_defaultRefreshRateInHbmHdr" />

  <!-- For fixed refresh rate displays in high brightness-->
  <java-symbol type="integer" name="config_fixedRefreshRateInHighZone" />
+218 −28
Original line number Diff line number Diff line
@@ -36,9 +36,14 @@ import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.net.Uri;
import android.os.Handler;
import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.Looper;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.SystemClock;
import android.os.Temperature;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.Settings;
@@ -48,6 +53,7 @@ import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.Display;
import android.view.DisplayInfo;

@@ -72,7 +78,6 @@ import java.util.List;
import java.util.Locale;
import java.util.Objects;


/**
 * The DisplayModeDirector is responsible for determining what modes are allowed to be automatically
 * picked by the system based on system-wide and display-specific configuration.
@@ -87,6 +92,8 @@ public class DisplayModeDirector {
    private static final int MSG_REFRESH_RATE_IN_LOW_ZONE_CHANGED = 4;
    private static final int MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED = 5;
    private static final int MSG_HIGH_BRIGHTNESS_THRESHOLDS_CHANGED = 6;
    private static final int MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED = 7;
    private static final int MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED = 8;

    // Special ID used to indicate that given vote is to be applied globally, rather than to a
    // specific display.
@@ -108,6 +115,7 @@ public class DisplayModeDirector {
    private final UdfpsObserver mUdfpsObserver;
    private final SensorObserver mSensorObserver;
    private final HbmObserver mHbmObserver;
    private final SkinThermalStatusObserver mSkinThermalStatusObserver;
    private final DeviceConfigInterface mDeviceConfig;
    private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;

@@ -155,8 +163,10 @@ public class DisplayModeDirector {
            }
        };
        mSensorObserver = new SensorObserver(context, ballotBox, injector);
        mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler());
        mSkinThermalStatusObserver = new SkinThermalStatusObserver(injector, ballotBox);
        mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
        mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler(),
                mDeviceConfigDisplaySettings);
        mDeviceConfig = injector.getDeviceConfig();
        mAlwaysRespectAppRequest = false;
    }
@@ -174,6 +184,7 @@ public class DisplayModeDirector {
        mBrightnessObserver.observe(sensorManager);
        mSensorObserver.observe();
        mHbmObserver.observe();
        mSkinThermalStatusObserver.observe();
        synchronized (mLock) {
            // We may have a listener already registered before the call to start, so go ahead and
            // notify them to pick up our newly initialized state.
@@ -606,6 +617,7 @@ public class DisplayModeDirector {
            mUdfpsObserver.dumpLocked(pw);
            mSensorObserver.dumpLocked(pw);
            mHbmObserver.dumpLocked(pw);
            mSkinThermalStatusObserver.dumpLocked(pw);
        }
    }

@@ -714,6 +726,10 @@ public class DisplayModeDirector {
        return mUdfpsObserver;
    }

    @VisibleForTesting
    HbmObserver getHbmObserver() {
        return mHbmObserver;
    }

    @VisibleForTesting
    DesiredDisplayModeSpecs getDesiredDisplayModeSpecsWithInjectedFpsSettings(
@@ -784,6 +800,19 @@ public class DisplayModeDirector {
                            (DesiredDisplayModeSpecsListener) msg.obj;
                    desiredDisplayModeSpecsListener.onDesiredDisplayModeSpecsChanged();
                    break;

                case MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED: {
                    int refreshRateInHbmSunlight = msg.arg1;
                    mHbmObserver.onDeviceConfigRefreshRateInHbmSunlightChanged(
                            refreshRateInHbmSunlight);
                    break;
                }

                case MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED: {
                    int refreshRateInHbmHdr = msg.arg1;
                    mHbmObserver.onDeviceConfigRefreshRateInHbmHdrChanged(refreshRateInHbmHdr);
                    break;
                }
            }
        }
    }
@@ -910,16 +939,19 @@ public class DisplayModeDirector {
        // result is a range.
        public static final int PRIORITY_FLICKER_REFRESH_RATE = 1;

        // High-brightness-mode may need a specific range of refresh-rates to function properly.
        public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 2;

        // SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
        // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
        public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 2;
        public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 3;

        // APP_REQUEST_REFRESH_RATE_RANGE is used to for internal apps to limit the refresh
        // rate in certain cases, mostly to preserve power.
        // @see android.view.WindowManager.LayoutParams#preferredMinRefreshRate
        // @see android.view.WindowManager.LayoutParams#preferredMaxRefreshRate
        // It votes to [preferredMinRefreshRate, preferredMaxRefreshRate].
        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE = 3;
        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE = 4;

        // We split the app request into different priorities in case we can satisfy one desire
        // without the other.
@@ -934,32 +966,32 @@ public class DisplayModeDirector {
        // The preferred refresh rate is set on the main surface of the app outside of
        // DisplayModeDirector.
        // @see com.android.server.wm.WindowState#updateFrameRateSelectionPriorityIfNeeded
        public static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 4;
        public static final int PRIORITY_APP_REQUEST_SIZE = 5;
        public static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 5;
        public static final int PRIORITY_APP_REQUEST_SIZE = 6;

        // SETTING_PEAK_REFRESH_RATE has a high priority and will restrict the bounds of the rest
        // of low priority voters. It votes [0, max(PEAK, MIN)]
        public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 6;
        public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 7;

        // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
        public static final int PRIORITY_LOW_POWER_MODE = 7;
        public static final int PRIORITY_LOW_POWER_MODE = 8;

        // 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 = 8;
        public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 9;

        // High-brightness-mode may need a specific range of refresh-rates to function properly.
        public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 9;
        // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
        public static final int PRIORITY_SKIN_TEMPERATURE = 10;

        // 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 = 10;
        public static final int PRIORITY_PROXIMITY = 11;

        // 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 = 11;
        public static final int PRIORITY_UDFPS = 12;

        // 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.
@@ -1054,6 +1086,8 @@ public class DisplayModeDirector {
                    return "PRIORITY_PROXIMITY";
                case PRIORITY_LOW_POWER_MODE:
                    return "PRIORITY_LOW_POWER_MODE";
                case PRIORITY_SKIN_TEMPERATURE:
                    return "PRIORITY_SKIN_TEMPERATURE";
                case PRIORITY_UDFPS:
                    return "PRIORITY_UDFPS";
                case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
@@ -2245,33 +2279,78 @@ public class DisplayModeDirector {
     * HBM that are associated with that display. Restrictions are retrieved from
     * DisplayManagerInternal but originate in the display-device-config file.
     */
    private static class HbmObserver implements DisplayManager.DisplayListener {
    public static class HbmObserver implements DisplayManager.DisplayListener {
        private final BallotBox mBallotBox;
        private final Handler mHandler;
        private final SparseBooleanArray mHbmEnabled = new SparseBooleanArray();
        private final SparseIntArray mHbmMode = new SparseIntArray();
        private final Injector mInjector;
        private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
        private int mRefreshRateInHbmSunlight;
        private int mRefreshRateInHbmHdr;

        private DisplayManagerInternal mDisplayManagerInternal;

        HbmObserver(Injector injector, BallotBox ballotBox, Handler handler) {
        HbmObserver(Injector injector, BallotBox ballotBox, Handler handler,
                DeviceConfigDisplaySettings displaySettings) {
            mInjector = injector;
            mBallotBox = ballotBox;
            mHandler = handler;
            mDeviceConfigDisplaySettings = displaySettings;
        }

        public void observe() {
            mRefreshRateInHbmSunlight = mDeviceConfigDisplaySettings.getRefreshRateInHbmSunlight();
            mRefreshRateInHbmHdr = mDeviceConfigDisplaySettings.getRefreshRateInHbmHdr();

            mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
            mInjector.registerDisplayListener(this, mHandler,
                    DisplayManager.EVENT_FLAG_DISPLAY_BRIGHTNESS
                    | DisplayManager.EVENT_FLAG_DISPLAY_REMOVED);
        }

        /**
         * @return the refresh to lock to when the device is in high brightness mode for Sunlight.
         */
        @VisibleForTesting
        int getRefreshRateInHbmSunlight() {
            return mRefreshRateInHbmSunlight;
        }

        /**
         * @return the refresh to lock to when the device is in high brightness mode for HDR.
         */
        @VisibleForTesting
        int getRefreshRateInHbmHdr() {
            return mRefreshRateInHbmHdr;
        }

        /**
         * Recalculates the HBM vote when the device config has been changed.
         */
        public void onDeviceConfigRefreshRateInHbmSunlightChanged(int refreshRate) {
            if (refreshRate != mRefreshRateInHbmSunlight) {
                mRefreshRateInHbmSunlight = refreshRate;
                onDeviceConfigRefreshRateInHbmChanged();
            }
        }

        /**
         * Recalculates the HBM vote when the device config has been changed.
         */
        public void onDeviceConfigRefreshRateInHbmHdrChanged(int refreshRate) {
            if (refreshRate != mRefreshRateInHbmHdr) {
                mRefreshRateInHbmHdr = refreshRate;
                onDeviceConfigRefreshRateInHbmChanged();
            }
        }

        @Override
        public void onDisplayAdded(int displayId) {}

        @Override
        public void onDisplayRemoved(int displayId) {
            mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, null);
            mHbmMode.delete(displayId);
        }

        @Override
@@ -2281,15 +2360,33 @@ public class DisplayModeDirector {
                // Display no longer there. Assume we'll get an onDisplayRemoved very soon.
                return;
            }
            final boolean isHbmEnabled =
                    info.highBrightnessMode != BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF;
            if (isHbmEnabled == mHbmEnabled.get(displayId)) {
            final int hbmMode = info.highBrightnessMode;
            if (hbmMode == mHbmMode.get(displayId)) {
                // no change, ignore.
                return;
            }
            mHbmMode.put(displayId, hbmMode);
            recalculateVotesForDisplay(displayId);
        }

        private void onDeviceConfigRefreshRateInHbmChanged() {
            final int[] displayIds = mHbmMode.copyKeys();
            if (displayIds != null) {
                for (int id : displayIds) {
                    recalculateVotesForDisplay(id);
                }
            }
        }

        private void recalculateVotesForDisplay(int displayId) {
            final int hbmMode = mHbmMode.get(displayId, BrightnessInfo.HIGH_BRIGHTNESS_MODE_OFF);
            Vote vote = null;
            mHbmEnabled.put(displayId, isHbmEnabled);
            if (isHbmEnabled) {
            if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
                // Device resource properties take priority over DisplayDeviceConfig
                if (mRefreshRateInHbmSunlight > 0) {
                    vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight,
                            mRefreshRateInHbmSunlight);
                } else {
                    final List<RefreshRateLimitation> limits =
                        mDisplayManagerInternal.getRefreshRateLimitations(displayId);
                    for (int i = 0; limits != null && i < limits.size(); i++) {
@@ -2300,12 +2397,65 @@ public class DisplayModeDirector {
                        }
                    }
                }
            }
            if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_HDR
                    && mRefreshRateInHbmHdr > 0) {
                vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
            }
            mBallotBox.vote(displayId, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE, vote);
        }

        void dumpLocked(PrintWriter pw) {
            pw.println("   HbmObserver");
            pw.println("     mHbmEnabled: " + mHbmEnabled);
            pw.println("     mHbmMode: " + mHbmMode);
            pw.println("     mRefreshRateInHbmSunlight: " + mRefreshRateInHbmSunlight);
            pw.println("     mRefreshRateInHbmHdr: " + mRefreshRateInHbmHdr);
        }
    }

    private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
        private final BallotBox mBallotBox;
        private final Injector mInjector;

        private @Temperature.ThrottlingStatus int mStatus = -1;

        SkinThermalStatusObserver(Injector injector, BallotBox ballotBox) {
            mInjector = injector;
            mBallotBox = ballotBox;
        }

        @Override
        public void notifyThrottling(Temperature temp) {
            mStatus = temp.getStatus();
            if (mLoggingEnabled) {
                Slog.d(TAG, "New thermal throttling status "
                        + ", current thermal status = " + mStatus);
            }
            final Vote vote;
            if (mStatus >= Temperature.THROTTLING_CRITICAL) {
                vote = Vote.forRefreshRates(0f, 60f);
            } else {
                vote = null;
            }
            mBallotBox.vote(GLOBAL_ID, Vote.PRIORITY_SKIN_TEMPERATURE, vote);
        }

        public void observe() {
            IThermalService thermalService = mInjector.getThermalService();
            if (thermalService == null) {
                Slog.w(TAG, "Could not observe thermal status. Service not available");
                return;
            }
            try {
                thermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN);
            } catch (RemoteException e) {
                Slog.e(TAG, "Failed to register thermal status listener", e);
            }
        }

        void dumpLocked(PrintWriter writer) {
            writer.println("  SkinThermalStatusObserver:");
            writer.println("    mStatus: " + mStatus);
        }
    }

@@ -2378,6 +2528,29 @@ public class DisplayModeDirector {
            return refreshRate;
        }

        public int getRefreshRateInHbmSunlight() {
            final int defaultRefreshRateInHbmSunlight =
                    mContext.getResources().getInteger(
                            R.integer.config_defaultRefreshRateInHbmSunlight);

            final int refreshRate = mDeviceConfig.getInt(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                    DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_SUNLIGHT,
                    defaultRefreshRateInHbmSunlight);

            return refreshRate;
        }

        public int getRefreshRateInHbmHdr() {
            final int defaultRefreshRateInHbmHdr =
                    mContext.getResources().getInteger(R.integer.config_defaultRefreshRateInHbmHdr);

            final int refreshRate = mDeviceConfig.getInt(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                    DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_HDR,
                    defaultRefreshRateInHbmHdr);

            return refreshRate;
        }

        /*
         * Return null if no such property
         */
@@ -2417,6 +2590,15 @@ public class DisplayModeDirector {
                    .sendToTarget();
            mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HIGH_ZONE_CHANGED, refreshRateInHighZone, 0)
                    .sendToTarget();

            final int refreshRateInHbmSunlight = getRefreshRateInHbmSunlight();
            mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HBM_SUNLIGHT_CHANGED,
                    refreshRateInHbmSunlight, 0)
                    .sendToTarget();

            final int refreshRateInHbmHdr = getRefreshRateInHbmHdr();
            mHandler.obtainMessage(MSG_REFRESH_RATE_IN_HBM_HDR_CHANGED, refreshRateInHbmHdr, 0)
                    .sendToTarget();
        }

        private int[] getIntArrayProperty(String prop) {
@@ -2470,6 +2652,8 @@ public class DisplayModeDirector {
        BrightnessInfo getBrightnessInfo(int displayId);

        boolean isDozeState(Display d);

        IThermalService getThermalService();
    }

    @VisibleForTesting
@@ -2530,6 +2714,12 @@ public class DisplayModeDirector {
            return Display.isDozeState(d.getState());
        }

        @Override
        public IThermalService getThermalService() {
            return IThermalService.Stub.asInterface(
                    ServiceManager.getService(Context.THERMAL_SERVICE));
        }

        private DisplayManager getDisplayManager() {
            if (mDisplayManager == null) {
                mDisplayManager = mContext.getSystemService(DisplayManager.class);
+201 −3

File changed.

Preview size limit exceeded, changes collapsed.