blob: 39a256248aaee84601d116b259a6df730abec4e3 [file] [log] [blame]
Adrian Roos2981eb02017-05-26 18:40:09 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.systemui.doze;
18
Lucas Dupin92e6c892018-09-25 08:58:24 -070019import android.content.BroadcastReceiver;
Adrian Roos2981eb02017-05-26 18:40:09 -070020import android.content.Context;
Lucas Dupin92e6c892018-09-25 08:58:24 -070021import android.content.Intent;
22import android.content.IntentFilter;
Adrian Roos2981eb02017-05-26 18:40:09 -070023import android.hardware.Sensor;
24import android.hardware.SensorEvent;
25import android.hardware.SensorEventListener;
26import android.hardware.SensorManager;
27import android.os.Handler;
Lucas Dupinbf2fbd52018-11-28 17:14:54 +010028import android.os.SystemProperties;
Adrian Roos2adc2632017-09-05 17:01:42 +020029import android.os.Trace;
Lucas Dupinc48b74a2018-07-27 11:41:01 +080030import android.os.UserHandle;
31import android.provider.Settings;
Adrian Roos2981eb02017-05-26 18:40:09 -070032
Adrian Roos3a8f8922017-07-13 19:55:38 +020033import com.android.internal.annotations.VisibleForTesting;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000034import com.android.systemui.broadcast.BroadcastDispatcher;
Lucas Dupin59688552018-11-12 16:34:47 -080035
Adrian Roos2981eb02017-05-26 18:40:09 -070036/**
37 * Controls the screen brightness when dozing.
38 */
Lucas Dupin92e6c892018-09-25 08:58:24 -070039public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachine.Part,
40 SensorEventListener {
Lucas Dupinbf2fbd52018-11-28 17:14:54 +010041 private static final boolean DEBUG_AOD_BRIGHTNESS = SystemProperties
42 .getBoolean("debug.aod_brightness", false);
Lucas Dupin92e6c892018-09-25 08:58:24 -070043 protected static final String ACTION_AOD_BRIGHTNESS =
44 "com.android.systemui.doze.AOD_BRIGHTNESS";
45 protected static final String BRIGHTNESS_BUCKET = "brightness_bucket";
46
Adrian Roos2981eb02017-05-26 18:40:09 -070047 private final Context mContext;
48 private final DozeMachine.Service mDozeService;
Adrian Roosc8e29e72017-08-03 18:25:42 +020049 private final DozeHost mDozeHost;
Adrian Roos2981eb02017-05-26 18:40:09 -070050 private final Handler mHandler;
51 private final SensorManager mSensorManager;
52 private final Sensor mLightSensor;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000053 private final BroadcastDispatcher mBroadcastDispatcher;
Adrian Roos4d4aaba2017-07-26 19:17:51 +020054 private final int[] mSensorToBrightness;
Adrian Roosc8e29e72017-08-03 18:25:42 +020055 private final int[] mSensorToScrimOpacity;
Lucas Dupin92e6c892018-09-25 08:58:24 -070056 private final boolean mDebuggable;
Adrian Roosc7fd6962017-09-06 16:46:46 +020057
Adrian Roos2981eb02017-05-26 18:40:09 -070058 private boolean mRegistered;
Adrian Roosa79ad592017-08-31 15:17:17 +020059 private int mDefaultDozeBrightness;
Adrian Roosc7fd6962017-09-06 16:46:46 +020060 private boolean mPaused = false;
Lucas Dupin00603f02019-03-29 12:51:55 -070061 private boolean mScreenOff = false;
Adrian Roosc7fd6962017-09-06 16:46:46 +020062 private int mLastSensorValue = -1;
Adrian Roos2981eb02017-05-26 18:40:09 -070063
Lucas Dupin92e6c892018-09-25 08:58:24 -070064 /**
65 * Debug value used for emulating various display brightness buckets:
66 *
67 * {@code am broadcast -p com.android.systemui -a com.android.systemui.doze.AOD_BRIGHTNESS
68 * --ei brightness_bucket 1}
69 */
70 private int mDebugBrightnessBucket = -1;
71
72 @VisibleForTesting
Adrian Roos2981eb02017-05-26 18:40:09 -070073 public DozeScreenBrightness(Context context, DozeMachine.Service service,
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000074 SensorManager sensorManager, Sensor lightSensor,
75 BroadcastDispatcher broadcastDispatcher, DozeHost host,
Adrian Roosa79ad592017-08-31 15:17:17 +020076 Handler handler, int defaultDozeBrightness, int[] sensorToBrightness,
Lucas Dupin92e6c892018-09-25 08:58:24 -070077 int[] sensorToScrimOpacity, boolean debuggable) {
Adrian Roos2981eb02017-05-26 18:40:09 -070078 mContext = context;
79 mDozeService = service;
80 mSensorManager = sensorManager;
81 mLightSensor = lightSensor;
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000082 mBroadcastDispatcher = broadcastDispatcher;
Adrian Roosc8e29e72017-08-03 18:25:42 +020083 mDozeHost = host;
Adrian Roos2981eb02017-05-26 18:40:09 -070084 mHandler = handler;
Lucas Dupin92e6c892018-09-25 08:58:24 -070085 mDebuggable = debuggable;
Adrian Roos3a8f8922017-07-13 19:55:38 +020086
Adrian Roosa79ad592017-08-31 15:17:17 +020087 mDefaultDozeBrightness = defaultDozeBrightness;
88 mSensorToBrightness = sensorToBrightness;
89 mSensorToScrimOpacity = sensorToScrimOpacity;
Lucas Dupin92e6c892018-09-25 08:58:24 -070090
91 if (mDebuggable) {
Lucas Dupinbf2fbd52018-11-28 17:14:54 +010092 IntentFilter filter = new IntentFilter();
93 filter.addAction(ACTION_AOD_BRIGHTNESS);
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000094 mBroadcastDispatcher.registerReceiver(this, filter, handler, UserHandle.ALL);
Lucas Dupin92e6c892018-09-25 08:58:24 -070095 }
Adrian Roosa79ad592017-08-31 15:17:17 +020096 }
97
Adrian Roosa79ad592017-08-31 15:17:17 +020098 public DozeScreenBrightness(Context context, DozeMachine.Service service,
Fabian Kozynski5ca7a512019-10-16 19:56:11 +000099 SensorManager sensorManager, Sensor lightSensor,
100 BroadcastDispatcher broadcastDispatcher, DozeHost host, Handler handler,
101 AlwaysOnDisplayPolicy policy) {
102 this(context, service, sensorManager, lightSensor, broadcastDispatcher, host, handler,
Adrian Roosa79ad592017-08-31 15:17:17 +0200103 context.getResources().getInteger(
104 com.android.internal.R.integer.config_screenBrightnessDoze),
Lucas Dupinbf2fbd52018-11-28 17:14:54 +0100105 policy.screenBrightnessArray, policy.dimmingScrimArray, DEBUG_AOD_BRIGHTNESS);
Adrian Roos2981eb02017-05-26 18:40:09 -0700106 }
107
108 @Override
109 public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
110 switch (newState) {
111 case INITIALIZED:
112 resetBrightnessToDefault();
113 break;
114 case DOZE_AOD:
115 case DOZE_REQUEST_PULSE:
116 setLightSensorEnabled(true);
117 break;
118 case DOZE:
Adrian Roos2981eb02017-05-26 18:40:09 -0700119 setLightSensorEnabled(false);
120 resetBrightnessToDefault();
121 break;
122 case FINISH:
Lucas Dupin92e6c892018-09-25 08:58:24 -0700123 onDestroy();
Adrian Roos2981eb02017-05-26 18:40:09 -0700124 break;
125 }
Adrian Roosc7fd6962017-09-06 16:46:46 +0200126 if (newState != DozeMachine.State.FINISH) {
Lucas Dupin00603f02019-03-29 12:51:55 -0700127 setScreenOff(newState == DozeMachine.State.DOZE);
Adrian Roosc7fd6962017-09-06 16:46:46 +0200128 setPaused(newState == DozeMachine.State.DOZE_AOD_PAUSED);
129 }
Adrian Roos2981eb02017-05-26 18:40:09 -0700130 }
131
Lucas Dupin92e6c892018-09-25 08:58:24 -0700132 private void onDestroy() {
133 setLightSensorEnabled(false);
134 if (mDebuggable) {
Fabian Kozynski5ca7a512019-10-16 19:56:11 +0000135 mBroadcastDispatcher.unregisterReceiver(this);
Lucas Dupin92e6c892018-09-25 08:58:24 -0700136 }
137 }
138
Adrian Roos2981eb02017-05-26 18:40:09 -0700139 @Override
140 public void onSensorChanged(SensorEvent event) {
Adrian Roos2adc2632017-09-05 17:01:42 +0200141 Trace.beginSection("DozeScreenBrightness.onSensorChanged" + event.values[0]);
142 try {
143 if (mRegistered) {
144 mLastSensorValue = (int) event.values[0];
Lucas Dupin00603f02019-03-29 12:51:55 -0700145 updateBrightnessAndReady(false /* force */);
Adrian Roos2adc2632017-09-05 17:01:42 +0200146 }
147 } finally {
148 Trace.endSection();
Adrian Roosc7fd6962017-09-06 16:46:46 +0200149 }
150 }
151
Lucas Dupin00603f02019-03-29 12:51:55 -0700152 private void updateBrightnessAndReady(boolean force) {
153 if (force || mRegistered || mDebugBrightnessBucket != -1) {
Lucas Dupin92e6c892018-09-25 08:58:24 -0700154 int sensorValue = mDebugBrightnessBucket == -1
155 ? mLastSensorValue : mDebugBrightnessBucket;
156 int brightness = computeBrightness(sensorValue);
Adrian Roosc7fd6962017-09-06 16:46:46 +0200157 boolean brightnessReady = brightness > 0;
158 if (brightnessReady) {
Lucas Dupinc48b74a2018-07-27 11:41:01 +0800159 mDozeService.setDozeScreenBrightness(clampToUserSetting(brightness));
Adrian Roos4d4aaba2017-07-26 19:17:51 +0200160 }
Adrian Roosc8e29e72017-08-03 18:25:42 +0200161
Adrian Roosc7fd6962017-09-06 16:46:46 +0200162 int scrimOpacity = -1;
Lucas Dupin00603f02019-03-29 12:51:55 -0700163 if (mPaused || mScreenOff) {
Adrian Roosc7fd6962017-09-06 16:46:46 +0200164 // If AOD is paused, force the screen black until the
165 // sensor reports a new brightness. This ensures that when the screen comes on
166 // again, it will only show after the brightness sensor has stabilized,
167 // avoiding a potential flicker.
168 scrimOpacity = 255;
169 } else if (brightnessReady) {
170 // Only unblank scrim once brightness is ready.
Lucas Dupin92e6c892018-09-25 08:58:24 -0700171 scrimOpacity = computeScrimOpacity(sensorValue);
Adrian Roosc7fd6962017-09-06 16:46:46 +0200172 }
Adrian Roosc8e29e72017-08-03 18:25:42 +0200173 if (scrimOpacity >= 0) {
174 mDozeHost.setAodDimmingScrim(scrimOpacity / 255f);
175 }
Adrian Roos3a8f8922017-07-13 19:55:38 +0200176 }
177 }
178
Adrian Roosc8e29e72017-08-03 18:25:42 +0200179 private int computeScrimOpacity(int sensorValue) {
180 if (sensorValue < 0 || sensorValue >= mSensorToScrimOpacity.length) {
181 return -1;
182 }
183 return mSensorToScrimOpacity[sensorValue];
184 }
185
Adrian Roos3a8f8922017-07-13 19:55:38 +0200186 private int computeBrightness(int sensorValue) {
Adrian Roos4d4aaba2017-07-26 19:17:51 +0200187 if (sensorValue < 0 || sensorValue >= mSensorToBrightness.length) {
188 return -1;
Adrian Roos2981eb02017-05-26 18:40:09 -0700189 }
Adrian Roos4d4aaba2017-07-26 19:17:51 +0200190 return mSensorToBrightness[sensorValue];
Adrian Roos2981eb02017-05-26 18:40:09 -0700191 }
192
193 @Override
194 public void onAccuracyChanged(Sensor sensor, int accuracy) {
195 }
196
197 private void resetBrightnessToDefault() {
Lucas Dupinc48b74a2018-07-27 11:41:01 +0800198 mDozeService.setDozeScreenBrightness(clampToUserSetting(mDefaultDozeBrightness));
Adrian Roosc7fd6962017-09-06 16:46:46 +0200199 mDozeHost.setAodDimmingScrim(0f);
Adrian Roos2981eb02017-05-26 18:40:09 -0700200 }
201
Lucas Dupinc48b74a2018-07-27 11:41:01 +0800202 private int clampToUserSetting(int brightness) {
203 int userSetting = Settings.System.getIntForUser(mContext.getContentResolver(),
204 Settings.System.SCREEN_BRIGHTNESS, Integer.MAX_VALUE,
205 UserHandle.USER_CURRENT);
206 return Math.min(brightness, userSetting);
207 }
208
Adrian Roos2981eb02017-05-26 18:40:09 -0700209 private void setLightSensorEnabled(boolean enabled) {
210 if (enabled && !mRegistered && mLightSensor != null) {
Adrian Roosa79ad592017-08-31 15:17:17 +0200211 // Wait until we get an event from the sensor until indicating ready.
Adrian Roos2981eb02017-05-26 18:40:09 -0700212 mRegistered = mSensorManager.registerListener(this, mLightSensor,
213 SensorManager.SENSOR_DELAY_NORMAL, mHandler);
Adrian Roosc7fd6962017-09-06 16:46:46 +0200214 mLastSensorValue = -1;
Adrian Roos2981eb02017-05-26 18:40:09 -0700215 } else if (!enabled && mRegistered) {
216 mSensorManager.unregisterListener(this);
217 mRegistered = false;
Adrian Roosc7fd6962017-09-06 16:46:46 +0200218 mLastSensorValue = -1;
Adrian Roosa79ad592017-08-31 15:17:17 +0200219 // Sensor is not enabled, hence we use the default brightness and are always ready.
Adrian Roos2981eb02017-05-26 18:40:09 -0700220 }
221 }
Adrian Roosa79ad592017-08-31 15:17:17 +0200222
Adrian Roosc7fd6962017-09-06 16:46:46 +0200223 private void setPaused(boolean paused) {
224 if (mPaused != paused) {
225 mPaused = paused;
Lucas Dupin00603f02019-03-29 12:51:55 -0700226 updateBrightnessAndReady(false /* force */);
227 }
228 }
229
230 private void setScreenOff(boolean screenOff) {
231 if (mScreenOff != screenOff) {
232 mScreenOff = screenOff;
233 updateBrightnessAndReady(true /* force */);
Adrian Roosa79ad592017-08-31 15:17:17 +0200234 }
235 }
236
Lucas Dupin92e6c892018-09-25 08:58:24 -0700237 @Override
238 public void onReceive(Context context, Intent intent) {
239 mDebugBrightnessBucket = intent.getIntExtra(BRIGHTNESS_BUCKET, -1);
Lucas Dupin00603f02019-03-29 12:51:55 -0700240 updateBrightnessAndReady(false /* force */);
Lucas Dupin92e6c892018-09-25 08:58:24 -0700241 }
Adrian Roos2981eb02017-05-26 18:40:09 -0700242}