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

Commit 765197fc authored by Rupesh Bansal's avatar Rupesh Bansal Committed by Android (Google) Code Review
Browse files

Merge "Added configurable idlescreen timeout" into main

parents 1a8bea44 1996ad82
Loading
Loading
Loading
Loading
+92 −3
Original line number Diff line number Diff line
@@ -2099,6 +2099,65 @@ public final class SurfaceControl implements Parcelable {
        }
    }

    /**
     * Contains information of the idle time of the screen after which the refresh rate is to be
     * reduced.
     *
     * @hide
     */
    public static final class IdleScreenRefreshRateConfig {
        /**
         *  The time(in ms) after which the refresh rate is to be reduced. Defaults to -1, which
         *  means no timeout has been configured for the current conditions
         */
        public int timeoutMillis;

        public IdleScreenRefreshRateConfig() {
            timeoutMillis = -1;
        }

        public IdleScreenRefreshRateConfig(int timeoutMillis) {
            this.timeoutMillis = timeoutMillis;
        }

        /**
         * Checks whether the two objects have the same values.
         */
        @Override
        public boolean equals(Object other) {
            if (other == this) {
                return true;
            }

            if (!(other instanceof IdleScreenRefreshRateConfig) || other == null) {
                return false;
            }

            IdleScreenRefreshRateConfig
                    idleScreenRefreshRateConfig = (IdleScreenRefreshRateConfig) other;
            return timeoutMillis == idleScreenRefreshRateConfig.timeoutMillis;
        }

        @Override
        public int hashCode() {
            return Objects.hash(timeoutMillis);
        }

        @Override
        public String toString() {
            return "timeoutMillis: " + timeoutMillis;
        }

        /**
         * Copies the supplied object's values to this object.
         */
        public void copyFrom(IdleScreenRefreshRateConfig other) {
            if (other != null) {
                this.timeoutMillis = other.timeoutMillis;
            }
        }
    }


    /**
     * Contains information about desired display configuration.
@@ -2132,6 +2191,15 @@ public final class SurfaceControl implements Parcelable {
         */
        public final RefreshRateRanges appRequestRanges;

        /**
         * Represents the idle time of the screen after which the associated display's refresh rate
         * is to be reduced to preserve power
         * Defaults to null, meaning that the device is not configured to have a timeout.
         * Timeout value of -1 refers that the current conditions require no timeout
         */
        @Nullable
        public IdleScreenRefreshRateConfig idleScreenRefreshRateConfig;

        public DesiredDisplayModeSpecs() {
            this.primaryRanges = new RefreshRateRanges();
            this.appRequestRanges = new RefreshRateRanges();
@@ -2144,13 +2212,17 @@ public final class SurfaceControl implements Parcelable {
        }

        public DesiredDisplayModeSpecs(int defaultMode, boolean allowGroupSwitching,
                RefreshRateRanges primaryRanges, RefreshRateRanges appRequestRanges) {
                RefreshRateRanges primaryRanges, RefreshRateRanges appRequestRanges,
                @Nullable IdleScreenRefreshRateConfig idleScreenRefreshRateConfig) {
            this.defaultMode = defaultMode;
            this.allowGroupSwitching = allowGroupSwitching;
            this.primaryRanges =
                    new RefreshRateRanges(primaryRanges.physical, primaryRanges.render);
            this.appRequestRanges =
                    new RefreshRateRanges(appRequestRanges.physical, appRequestRanges.render);
            this.idleScreenRefreshRateConfig =
                    (idleScreenRefreshRateConfig == null) ? null : new IdleScreenRefreshRateConfig(
                            idleScreenRefreshRateConfig.timeoutMillis);
        }

        @Override
@@ -2165,7 +2237,9 @@ public final class SurfaceControl implements Parcelable {
            return other != null && defaultMode == other.defaultMode
                    && allowGroupSwitching == other.allowGroupSwitching
                    && primaryRanges.equals(other.primaryRanges)
                    && appRequestRanges.equals(other.appRequestRanges);
                    && appRequestRanges.equals(other.appRequestRanges)
                    && Objects.equals(
                    idleScreenRefreshRateConfig, other.idleScreenRefreshRateConfig);
        }

        @Override
@@ -2181,6 +2255,7 @@ public final class SurfaceControl implements Parcelable {
            allowGroupSwitching = other.allowGroupSwitching;
            primaryRanges.copyFrom(other.primaryRanges);
            appRequestRanges.copyFrom(other.appRequestRanges);
            copyIdleScreenRefreshRateConfig(other.idleScreenRefreshRateConfig);
        }

        @Override
@@ -2188,7 +2263,21 @@ public final class SurfaceControl implements Parcelable {
            return "defaultMode=" + defaultMode
                    + " allowGroupSwitching=" + allowGroupSwitching
                    + " primaryRanges=" + primaryRanges
                    + " appRequestRanges=" + appRequestRanges;
                    + " appRequestRanges=" + appRequestRanges
                    + " idleScreenRefreshRate=" + String.valueOf(idleScreenRefreshRateConfig);
        }

        private void copyIdleScreenRefreshRateConfig(IdleScreenRefreshRateConfig other) {
            if (idleScreenRefreshRateConfig == null) {
                if (other != null) {
                    idleScreenRefreshRateConfig =
                            new IdleScreenRefreshRateConfig(other.timeoutMillis);
                }
            } else if (other == null) {
                idleScreenRefreshRateConfig = null;
            } else {
                idleScreenRefreshRateConfig.copyFrom(other);
            }
        }
    }

+50 −2
Original line number Diff line number Diff line
@@ -205,6 +205,12 @@ static struct {
    jfieldID render;
} gRefreshRateRangesClassInfo;

static struct {
    jclass clazz;
    jmethodID ctor;
    jfieldID timeoutMillis;
} gIdleScreenRefreshRateConfigClassInfo;

static struct {
    jclass clazz;
    jmethodID ctor;
@@ -212,6 +218,7 @@ static struct {
    jfieldID allowGroupSwitching;
    jfieldID primaryRanges;
    jfieldID appRequestRanges;
    jfieldID idleScreenRefreshRateConfig;
} gDesiredDisplayModeSpecsClassInfo;

static struct {
@@ -1407,6 +1414,18 @@ static jboolean nativeSetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobj
        return ranges;
    };

    const auto makeIdleScreenRefreshRateConfig = [env](jobject obj)
            -> std::optional<gui::DisplayModeSpecs::IdleScreenRefreshRateConfig> {
        if (obj == NULL) {
            return std::nullopt;
        }
        gui::DisplayModeSpecs::IdleScreenRefreshRateConfig idleScreenRefreshRateConfig;
        idleScreenRefreshRateConfig.timeoutMillis =
                env->GetIntField(obj, gIdleScreenRefreshRateConfigClassInfo.timeoutMillis);

        return idleScreenRefreshRateConfig;
    };

    gui::DisplayModeSpecs specs;
    specs.defaultMode = env->GetIntField(DesiredDisplayModeSpecs,
                                         gDesiredDisplayModeSpecsClassInfo.defaultMode);
@@ -1421,6 +1440,10 @@ static jboolean nativeSetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobj
            makeRanges(env->GetObjectField(DesiredDisplayModeSpecs,
                                           gDesiredDisplayModeSpecsClassInfo.appRequestRanges));

    specs.idleScreenRefreshRateConfig = makeIdleScreenRefreshRateConfig(
            env->GetObjectField(DesiredDisplayModeSpecs,
                                gDesiredDisplayModeSpecsClassInfo.idleScreenRefreshRateConfig));

    size_t result = SurfaceComposerClient::setDesiredDisplayModeSpecs(token, specs);
    return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
}
@@ -1440,6 +1463,17 @@ static jobject nativeGetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobje
                              rangeToJava(ranges.physical), rangeToJava(ranges.render));
    };

    const auto idleScreenRefreshRateConfigToJava =
            [env](const std::optional<gui::DisplayModeSpecs::IdleScreenRefreshRateConfig>&
                          idleScreenRefreshRateConfig) -> jobject {
        if (!idleScreenRefreshRateConfig.has_value()) {
            return NULL; // Return null if input config is null
        }
        return env->NewObject(gIdleScreenRefreshRateConfigClassInfo.clazz,
                              gIdleScreenRefreshRateConfigClassInfo.ctor,
                              idleScreenRefreshRateConfig->timeoutMillis);
    };

    gui::DisplayModeSpecs specs;
    if (SurfaceComposerClient::getDesiredDisplayModeSpecs(token, &specs) != NO_ERROR) {
        return nullptr;
@@ -1448,7 +1482,8 @@ static jobject nativeGetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobje
    return env->NewObject(gDesiredDisplayModeSpecsClassInfo.clazz,
                          gDesiredDisplayModeSpecsClassInfo.ctor, specs.defaultMode,
                          specs.allowGroupSwitching, rangesToJava(specs.primaryRanges),
                          rangesToJava(specs.appRequestRanges));
                          rangesToJava(specs.appRequestRanges),
                          idleScreenRefreshRateConfigToJava(specs.idleScreenRefreshRateConfig));
}

static jobject nativeGetDisplayNativePrimaries(JNIEnv* env, jclass, jobject tokenObj) {
@@ -2607,13 +2642,23 @@ int register_android_view_SurfaceControl(JNIEnv* env)
            GetFieldIDOrDie(env, RefreshRateRangesClazz, "render",
                            "Landroid/view/SurfaceControl$RefreshRateRange;");

    jclass IdleScreenRefreshRateConfigClazz =
            FindClassOrDie(env, "android/view/SurfaceControl$IdleScreenRefreshRateConfig");
    gIdleScreenRefreshRateConfigClassInfo.clazz =
            MakeGlobalRefOrDie(env, IdleScreenRefreshRateConfigClazz);
    gIdleScreenRefreshRateConfigClassInfo.ctor =
            GetMethodIDOrDie(env, gIdleScreenRefreshRateConfigClassInfo.clazz, "<init>", "(I)V");
    gIdleScreenRefreshRateConfigClassInfo.timeoutMillis =
            GetFieldIDOrDie(env, gIdleScreenRefreshRateConfigClassInfo.clazz, "timeoutMillis", "I");

    jclass DesiredDisplayModeSpecsClazz =
            FindClassOrDie(env, "android/view/SurfaceControl$DesiredDisplayModeSpecs");
    gDesiredDisplayModeSpecsClassInfo.clazz = MakeGlobalRefOrDie(env, DesiredDisplayModeSpecsClazz);
    gDesiredDisplayModeSpecsClassInfo.ctor =
            GetMethodIDOrDie(env, gDesiredDisplayModeSpecsClassInfo.clazz, "<init>",
                             "(IZLandroid/view/SurfaceControl$RefreshRateRanges;Landroid/view/"
                             "SurfaceControl$RefreshRateRanges;)V");
                             "SurfaceControl$RefreshRateRanges;Landroid/view/"
                             "SurfaceControl$IdleScreenRefreshRateConfig;)V");
    gDesiredDisplayModeSpecsClassInfo.defaultMode =
            GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "defaultMode", "I");
    gDesiredDisplayModeSpecsClassInfo.allowGroupSwitching =
@@ -2624,6 +2669,9 @@ int register_android_view_SurfaceControl(JNIEnv* env)
    gDesiredDisplayModeSpecsClassInfo.appRequestRanges =
            GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "appRequestRanges",
                            "Landroid/view/SurfaceControl$RefreshRateRanges;");
    gDesiredDisplayModeSpecsClassInfo.idleScreenRefreshRateConfig =
            GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "idleScreenRefreshRateConfig",
                            "Landroid/view/SurfaceControl$IdleScreenRefreshRateConfig;");

    jclass jankDataClazz =
                FindClassOrDie(env, "android/view/SurfaceControl$JankData");
+6 −0
Original line number Diff line number Diff line
@@ -3471,6 +3471,12 @@ public class DisplayDeviceConfig {
                    throw new RuntimeException("Lux values should be in ascending order in the"
                            + " idle screen refresh rate timeout config");
                }

                int timeout = point.getTimeout().intValue();
                if (timeout < 0) {
                    throw new RuntimeException("The timeout value cannot be negative in"
                            + " idle screen refresh rate timeout config");
                }
                previousLux = newLux;
            }
        }
+2 −1
Original line number Diff line number Diff line
@@ -1103,7 +1103,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
                        new SurfaceControl.DesiredDisplayModeSpecs(baseSfModeId,
                                mDisplayModeSpecs.allowGroupSwitching,
                                mDisplayModeSpecs.primary,
                                mDisplayModeSpecs.appRequest)));
                                mDisplayModeSpecs.appRequest,
                                mDisplayModeSpecs.mIdleScreenRefreshRateConfig)));
            }
        }

+91 −7
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.SurfaceControl.IdleScreenRefreshRateConfig;
import android.view.SurfaceControl.RefreshRateRange;
import android.view.SurfaceControl.RefreshRateRanges;

@@ -74,6 +76,7 @@ import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.os.BackgroundThread;
import com.android.server.LocalServices;
import com.android.server.display.DisplayDeviceConfig;
import com.android.server.display.config.IdleScreenRefreshRateTimeoutLuxThresholdPoint;
import com.android.server.display.feature.DeviceConfigParameterProvider;
import com.android.server.display.feature.DisplayManagerFlags;
import com.android.server.display.utils.AmbientFilter;
@@ -184,6 +187,8 @@ public class DisplayModeDirector {

    private final boolean mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled;

    private final DisplayManagerFlags mDisplayManagerFlags;

    private final boolean mDvrrSupported;


@@ -206,7 +211,7 @@ public class DisplayModeDirector {
            .isDisplaysRefreshRatesSynchronizationEnabled();
        mIsBackUpSmoothDisplayAndForcePeakRefreshRateEnabled = displayManagerFlags
                .isBackUpSmoothDisplayAndForcePeakRefreshRateEnabled();

        mDisplayManagerFlags = displayManagerFlags;
        mContext = context;
        mHandler = new DisplayModeDirectorHandler(handler.getLooper());
        mInjector = injector;
@@ -374,7 +379,7 @@ public class DisplayModeDirector {
                final RefreshRateRanges ranges = new RefreshRateRanges(range, range);
                return new DesiredDisplayModeSpecs(defaultMode.getModeId(),
                        /*allowGroupSwitching */ false,
                        ranges, ranges);
                        ranges, ranges, mBrightnessObserver.getIdleScreenRefreshRateConfig());
            }

            boolean modeSwitchingDisabled =
@@ -422,7 +427,8 @@ public class DisplayModeDirector {
                                    appRequestSummary.maxPhysicalRefreshRate),
                            new RefreshRateRange(
                                    appRequestSummary.minRenderFrameRate,
                                    appRequestSummary.maxRenderFrameRate)));
                                    appRequestSummary.maxRenderFrameRate)),
                    mBrightnessObserver.getIdleScreenRefreshRateConfig());
        }
    }

@@ -763,6 +769,16 @@ public class DisplayModeDirector {
         */
        public boolean allowGroupSwitching;

        /**
         * Represents the idle time of the screen after which the associated display's refresh rate
         * is to be reduced to preserve power
         * Defaults to null, meaning that the device is not configured to have a timeout based on
         * the surrounding conditions
         * -1 means that the current conditions require no timeout
         */
        @Nullable
        public IdleScreenRefreshRateConfig mIdleScreenRefreshRateConfig;

        /**
         * The primary refresh rate ranges.
         */
@@ -783,11 +799,13 @@ public class DisplayModeDirector {
        public DesiredDisplayModeSpecs(int baseModeId,
                boolean allowGroupSwitching,
                @NonNull RefreshRateRanges primary,
                @NonNull RefreshRateRanges appRequest) {
                @NonNull RefreshRateRanges appRequest,
                @Nullable SurfaceControl.IdleScreenRefreshRateConfig idleScreenRefreshRateConfig) {
            this.baseModeId = baseModeId;
            this.allowGroupSwitching = allowGroupSwitching;
            this.primary = primary;
            this.appRequest = appRequest;
            this.mIdleScreenRefreshRateConfig = idleScreenRefreshRateConfig;
        }

        /**
@@ -797,9 +815,10 @@ public class DisplayModeDirector {
        public String toString() {
            return String.format("baseModeId=%d allowGroupSwitching=%b"
                            + " primary=%s"
                            + " appRequest=%s",
                            + " appRequest=%s"
                            + " idleScreenRefreshRateConfig=%s",
                    baseModeId, allowGroupSwitching, primary.toString(),
                    appRequest.toString());
                    appRequest.toString(), String.valueOf(mIdleScreenRefreshRateConfig));
        }

        /**
@@ -830,12 +849,18 @@ public class DisplayModeDirector {
                    desiredDisplayModeSpecs.appRequest)) {
                return false;
            }

            if (!Objects.equals(mIdleScreenRefreshRateConfig,
                    desiredDisplayModeSpecs.mIdleScreenRefreshRateConfig)) {
                return false;
            }
            return true;
        }

        @Override
        public int hashCode() {
            return Objects.hash(baseModeId, allowGroupSwitching, primary, appRequest);
            return Objects.hash(baseModeId, allowGroupSwitching, primary, appRequest,
                    mIdleScreenRefreshRateConfig);
        }

        /**
@@ -853,6 +878,14 @@ public class DisplayModeDirector {
            appRequest.physical.max = other.appRequest.physical.max;
            appRequest.render.min = other.appRequest.render.min;
            appRequest.render.max = other.appRequest.render.max;

            if (other.mIdleScreenRefreshRateConfig == null) {
                mIdleScreenRefreshRateConfig = null;
            } else {
                mIdleScreenRefreshRateConfig =
                        new IdleScreenRefreshRateConfig(
                                other.mIdleScreenRefreshRateConfig.timeoutMillis);
            }
        }
    }

@@ -1543,12 +1576,20 @@ public class DisplayModeDirector {
        private float mAmbientLux = -1.0f;
        private AmbientFilter mAmbientFilter;

        /**
         * The current timeout configuration. This value is used by surface flinger to track the
         * time after which an idle screen's refresh rate is to be reduced.
         */
        @Nullable
        private SurfaceControl.IdleScreenRefreshRateConfig mIdleScreenRefreshRateConfig;

        private float mBrightness = PowerManager.BRIGHTNESS_INVALID_FLOAT;

        private final Context mContext;
        private final Injector mInjector;
        private final Handler mHandler;


        private final boolean mVsyncLowLightBlockingVoteEnabled;

        private final IThermalEventListener.Stub mThermalListener =
@@ -1643,6 +1684,11 @@ public class DisplayModeDirector {
            return mRefreshRateInLowZone;
        }

        @VisibleForTesting
        IdleScreenRefreshRateConfig getIdleScreenRefreshRateConfig() {
            return mIdleScreenRefreshRateConfig;
        }

        private void loadLowBrightnessThresholds(@Nullable DisplayDeviceConfig displayDeviceConfig,
                boolean attemptReadFromFeatureParams) {
            loadRefreshRateInHighZone(displayDeviceConfig, attemptReadFromFeatureParams);
@@ -2381,6 +2427,10 @@ public class DisplayModeDirector {
                    // is interrupted by a new sensor event.
                    mHandler.postDelayed(mInjectSensorEventRunnable, INJECT_EVENTS_INTERVAL_MS);
                }

                if (mDisplayManagerFlags.isIdleScreenRefreshRateTimeoutEnabled()) {
                    updateIdleScreenRefreshRate(mAmbientLux);
                }
            }

            @Override
@@ -2440,6 +2490,40 @@ public class DisplayModeDirector {
                }
            };
        }

        private void updateIdleScreenRefreshRate(float ambientLux) {
            List<IdleScreenRefreshRateTimeoutLuxThresholdPoint>
                    idleScreenRefreshRateTimeoutLuxThresholdPoints;
            synchronized (mLock) {
                if (mDefaultDisplayDeviceConfig == null || mDefaultDisplayDeviceConfig
                        .getIdleScreenRefreshRateTimeoutLuxThresholdPoint().isEmpty()) {
                    // Setting this to null will let surface flinger know that the idle timer is not
                    // configured in the display configs
                    mIdleScreenRefreshRateConfig = null;
                    return;
                }

                idleScreenRefreshRateTimeoutLuxThresholdPoints =
                        mDefaultDisplayDeviceConfig
                                .getIdleScreenRefreshRateTimeoutLuxThresholdPoint();
            }
            int newTimeout = -1;
            for (IdleScreenRefreshRateTimeoutLuxThresholdPoint point :
                    idleScreenRefreshRateTimeoutLuxThresholdPoints) {
                int newLux = point.getLux().intValue();
                if (newLux <= ambientLux) {
                    newTimeout = point.getTimeout().intValue();
                }
            }
            if (mIdleScreenRefreshRateConfig == null
                    || newTimeout != mIdleScreenRefreshRateConfig.timeoutMillis) {
                mIdleScreenRefreshRateConfig =
                        new IdleScreenRefreshRateConfig(newTimeout);
                synchronized (mLock) {
                    notifyDesiredDisplayModeSpecsChangedLocked();
                }
            }
        }
    }

    private class UdfpsObserver extends IUdfpsRefreshRateRequestCallback.Stub {
Loading