Skip to content

Commit aa202a6

Browse files
author
Jeff Brown
committed
Add a mechanism to adjust auto-brightness at night.
Uses the twilight service to determine the hours of sunrise and sunset. Shortly after sunset or before sunrise gradually start to apply a gamma correction factor to the auto-brightness calculations to make the screen a little dimmer at night. The effect is relatively small and is mostly noticeable in dark rooms. This is just a first pass at the algorithm, we can tweak the adjustment later to ensure that it has even less impact in moderate or bright environments. Change-Id: Idf89022a5d0bb52975e04779352d53fa63371178
1 parent 2416e09 commit aa202a6

File tree

3 files changed

+90
-5
lines changed

3 files changed

+90
-5
lines changed

services/java/com/android/server/SystemServer.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,12 @@ public void run() {
741741
w.getDefaultDisplay().getMetrics(metrics);
742742
context.getResources().updateConfiguration(config, metrics);
743743

744-
power.systemReady();
744+
try {
745+
power.systemReady(twilight);
746+
} catch (Throwable e) {
747+
reportWtf("making Power Manager Service ready", e);
748+
}
749+
745750
try {
746751
pm.systemReady();
747752
} catch (Throwable e) {

services/java/com/android/server/power/DisplayPowerController.java

Lines changed: 81 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
package com.android.server.power;
1818

1919
import com.android.server.LightsService;
20+
import com.android.server.TwilightService;
21+
import com.android.server.TwilightService.TwilightState;
2022

2123
import android.animation.Animator;
2224
import android.animation.ObjectAnimator;
@@ -88,6 +90,22 @@ final class DisplayPowerController {
8890
// auto-brightness adjustment setting.
8991
private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f;
9092

93+
// If true, enables the use of the current time as an auto-brightness adjustment.
94+
// The basic idea here is to expand the dynamic range of auto-brightness
95+
// when it is especially dark outside. The light sensor tends to perform
96+
// poorly at low light levels so we compensate for it by making an
97+
// assumption about the environment.
98+
private static final boolean USE_TWILIGHT_ADJUSTMENT = true;
99+
100+
// Specifies the maximum magnitude of the time of day adjustment.
101+
private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f;
102+
103+
// The amount of time after or before sunrise over which to start adjusting
104+
// the gamma. We want the change to happen gradually so that it is below the
105+
// threshold of perceptibility and so that the adjustment has maximum effect
106+
// well after dusk.
107+
private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;
108+
91109
private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 300;
92110
private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 600;
93111

@@ -148,6 +166,9 @@ final class DisplayPowerController {
148166
// The lights service.
149167
private final LightsService mLights;
150168

169+
// The twilight service.
170+
private final TwilightService mTwilight;
171+
151172
// The sensor manager.
152173
private final SensorManager mSensorManager;
153174

@@ -291,11 +312,14 @@ final class DisplayPowerController {
291312
private ObjectAnimator mElectronBeamOffAnimator;
292313
private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
293314

315+
// Twilight changed. We might recalculate auto-brightness values.
316+
private boolean mTwilightChanged;
317+
294318
/**
295319
* Creates the display power controller.
296320
*/
297321
public DisplayPowerController(Looper looper, Context context, Notifier notifier,
298-
LightsService lights, SuspendBlocker suspendBlocker,
322+
LightsService lights, TwilightService twilight, SuspendBlocker suspendBlocker,
299323
Callbacks callbacks, Handler callbackHandler) {
300324
mHandler = new DisplayControllerHandler(looper);
301325
mNotifier = notifier;
@@ -304,6 +328,7 @@ public DisplayPowerController(Looper looper, Context context, Notifier notifier,
304328
mCallbackHandler = callbackHandler;
305329

306330
mLights = lights;
331+
mTwilight = twilight;
307332
mSensorManager = new SystemSensorManager(mHandler.getLooper());
308333

309334
final Resources resources = context.getResources();
@@ -344,6 +369,10 @@ public DisplayPowerController(Looper looper, Context context, Notifier notifier,
344369
&& !DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
345370
mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
346371
}
372+
373+
if (mUseSoftwareAutoBrightnessConfig && USE_TWILIGHT_ADJUSTMENT) {
374+
mTwilight.registerListener(mTwilightListener, mHandler);
375+
}
347376
}
348377

349378
private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
@@ -486,7 +515,8 @@ private void updatePowerState() {
486515
// Update the power state request.
487516
final boolean mustNotify;
488517
boolean mustInitialize = false;
489-
boolean updateAutoBrightness = false;
518+
boolean updateAutoBrightness = mTwilightChanged;
519+
mTwilightChanged = false;
490520

491521
synchronized (mLock) {
492522
mPendingUpdatePowerStateLocked = false;
@@ -863,6 +893,22 @@ private void updateAutoBrightness(boolean sendUpdate) {
863893
}
864894
}
865895

896+
if (USE_TWILIGHT_ADJUSTMENT) {
897+
TwilightState state = mTwilight.getCurrentState();
898+
if (state != null && state.isNight()) {
899+
final long now = System.currentTimeMillis();
900+
final float earlyGamma =
901+
getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise());
902+
final float lateGamma =
903+
getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise());
904+
gamma *= earlyGamma * lateGamma;
905+
if (DEBUG) {
906+
Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma
907+
+ ", lateGamma=" + lateGamma);
908+
}
909+
}
910+
}
911+
866912
if (gamma != 1.0f) {
867913
final float in = value;
868914
value = FloatMath.pow(value, gamma);
@@ -889,6 +935,29 @@ private void updateAutoBrightness(boolean sendUpdate) {
889935
}
890936
}
891937

938+
private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
939+
if (lastSunset < 0 || nextSunrise < 0
940+
|| now < lastSunset || now > nextSunrise) {
941+
return 1.0f;
942+
}
943+
944+
if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) {
945+
return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
946+
(float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME);
947+
}
948+
949+
if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) {
950+
return lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
951+
(float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
952+
}
953+
954+
return TWILIGHT_ADJUSTMENT_MAX_GAMMA;
955+
}
956+
957+
private static float lerp(float x, float y, float alpha) {
958+
return x + (y - x) * alpha;
959+
}
960+
892961
private void sendOnStateChanged() {
893962
mCallbackHandler.post(mOnStateChangedRunnable);
894963
}
@@ -995,6 +1064,7 @@ private void dumpLocal(PrintWriter pw) {
9951064
pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
9961065
pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
9971066
pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
1067+
pw.println(" mTwilight.getCurrentState()=" + mTwilight.getCurrentState());
9981068

9991069
if (mElectronBeamOnAnimator != null) {
10001070
pw.println(" mElectronBeamOnAnimator.isStarted()=" +
@@ -1095,4 +1165,13 @@ public void onAccuracyChanged(Sensor sensor, int accuracy) {
10951165
// Not used.
10961166
}
10971167
};
1168+
1169+
private final TwilightService.TwilightListener mTwilightListener =
1170+
new TwilightService.TwilightListener() {
1171+
@Override
1172+
public void onTwilightStateChanged() {
1173+
mTwilightChanged = true;
1174+
updatePowerState();
1175+
}
1176+
};
10981177
}

services/java/com/android/server/power/PowerManagerService.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import com.android.server.BatteryService;
2121
import com.android.server.EventLogTags;
2222
import com.android.server.LightsService;
23+
import com.android.server.TwilightService;
2324
import com.android.server.Watchdog;
2425
import com.android.server.am.ActivityManagerService;
2526
import com.android.server.display.DisplayManagerService;
@@ -318,7 +319,7 @@ public void setPolicy(WindowManagerPolicy policy) {
318319
}
319320
}
320321

321-
public void systemReady() {
322+
public void systemReady(TwilightService twilight) {
322323
synchronized (mLock) {
323324
mSystemReady = true;
324325

@@ -331,7 +332,7 @@ public void systemReady() {
331332
createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
332333
mPolicy, mScreenOnListener);
333334
mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
334-
mContext, mNotifier, mLightsService,
335+
mContext, mNotifier, mLightsService, twilight,
335336
createSuspendBlockerLocked("PowerManagerService.Display"),
336337
mDisplayPowerControllerCallbacks, mHandler);
337338

0 commit comments

Comments
 (0)