• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.systemui.doze;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.hardware.Sensor;
24 import android.hardware.SensorEvent;
25 import android.hardware.SensorEventListener;
26 import android.hardware.SensorManager;
27 import android.os.Handler;
28 import android.os.SystemProperties;
29 import android.os.Trace;
30 import android.os.UserHandle;
31 import android.provider.Settings;
32 import android.view.Display;
33 
34 import com.android.internal.annotations.VisibleForTesting;
35 import com.android.systemui.broadcast.BroadcastDispatcher;
36 
37 /**
38  * Controls the screen brightness when dozing.
39  */
40 public class DozeScreenBrightness extends BroadcastReceiver implements DozeMachine.Part,
41         SensorEventListener {
42     private static final boolean DEBUG_AOD_BRIGHTNESS = SystemProperties
43             .getBoolean("debug.aod_brightness", false);
44     protected static final String ACTION_AOD_BRIGHTNESS =
45             "com.android.systemui.doze.AOD_BRIGHTNESS";
46     protected static final String BRIGHTNESS_BUCKET = "brightness_bucket";
47 
48     private final Context mContext;
49     private final DozeMachine.Service mDozeService;
50     private final DozeHost mDozeHost;
51     private final Handler mHandler;
52     private final SensorManager mSensorManager;
53     private final Sensor mLightSensor;
54     private final BroadcastDispatcher mBroadcastDispatcher;
55     private final int[] mSensorToBrightness;
56     private final int[] mSensorToScrimOpacity;
57     private final boolean mDebuggable;
58 
59     private boolean mRegistered;
60     private int mDefaultDozeBrightness;
61     private boolean mPaused = false;
62     private boolean mScreenOff = false;
63     private int mLastSensorValue = -1;
64 
65     /**
66      * Debug value used for emulating various display brightness buckets:
67      *
68      * {@code am broadcast -p com.android.systemui -a com.android.systemui.doze.AOD_BRIGHTNESS
69      * --ei brightness_bucket 1}
70      */
71     private int mDebugBrightnessBucket = -1;
72 
73     @VisibleForTesting
DozeScreenBrightness(Context context, DozeMachine.Service service, SensorManager sensorManager, Sensor lightSensor, BroadcastDispatcher broadcastDispatcher, DozeHost host, Handler handler, int defaultDozeBrightness, int[] sensorToBrightness, int[] sensorToScrimOpacity, boolean debuggable)74     public DozeScreenBrightness(Context context, DozeMachine.Service service,
75             SensorManager sensorManager, Sensor lightSensor,
76             BroadcastDispatcher broadcastDispatcher, DozeHost host,
77             Handler handler, int defaultDozeBrightness, int[] sensorToBrightness,
78             int[] sensorToScrimOpacity, boolean debuggable) {
79         mContext = context;
80         mDozeService = service;
81         mSensorManager = sensorManager;
82         mLightSensor = lightSensor;
83         mBroadcastDispatcher = broadcastDispatcher;
84         mDozeHost = host;
85         mHandler = handler;
86         mDebuggable = debuggable;
87 
88         mDefaultDozeBrightness = defaultDozeBrightness;
89         mSensorToBrightness = sensorToBrightness;
90         mSensorToScrimOpacity = sensorToScrimOpacity;
91 
92         if (mDebuggable) {
93             IntentFilter filter = new IntentFilter();
94             filter.addAction(ACTION_AOD_BRIGHTNESS);
95             mBroadcastDispatcher.registerReceiverWithHandler(this, filter, handler, UserHandle.ALL);
96         }
97     }
98 
DozeScreenBrightness(Context context, DozeMachine.Service service, SensorManager sensorManager, Sensor lightSensor, BroadcastDispatcher broadcastDispatcher, DozeHost host, Handler handler, AlwaysOnDisplayPolicy policy)99     public DozeScreenBrightness(Context context, DozeMachine.Service service,
100             SensorManager sensorManager, Sensor lightSensor,
101             BroadcastDispatcher broadcastDispatcher, DozeHost host, Handler handler,
102             AlwaysOnDisplayPolicy policy) {
103         this(context, service, sensorManager, lightSensor, broadcastDispatcher, host, handler,
104                 context.getResources().getInteger(
105                         com.android.internal.R.integer.config_screenBrightnessDoze),
106                 policy.screenBrightnessArray, policy.dimmingScrimArray, DEBUG_AOD_BRIGHTNESS);
107     }
108 
109     @Override
transitionTo(DozeMachine.State oldState, DozeMachine.State newState)110     public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) {
111         switch (newState) {
112             case INITIALIZED:
113             case DOZE:
114                 resetBrightnessToDefault();
115                 break;
116             case FINISH:
117                 onDestroy();
118                 break;
119         }
120         if (newState != DozeMachine.State.FINISH) {
121             setScreenOff(newState == DozeMachine.State.DOZE);
122             setPaused(newState == DozeMachine.State.DOZE_AOD_PAUSED);
123         }
124     }
125 
126     @Override
onScreenState(int state)127     public void onScreenState(int state) {
128         if (state == Display.STATE_DOZE || state == Display.STATE_DOZE_SUSPEND) {
129             setLightSensorEnabled(true);
130         } else {
131             setLightSensorEnabled(false);
132         }
133     }
134 
onDestroy()135     private void onDestroy() {
136         setLightSensorEnabled(false);
137         if (mDebuggable) {
138             mBroadcastDispatcher.unregisterReceiver(this);
139         }
140     }
141 
142     @Override
onSensorChanged(SensorEvent event)143     public void onSensorChanged(SensorEvent event) {
144         Trace.beginSection("DozeScreenBrightness.onSensorChanged" + event.values[0]);
145         try {
146             if (mRegistered) {
147                 mLastSensorValue = (int) event.values[0];
148                 updateBrightnessAndReady(false /* force */);
149             }
150         } finally {
151             Trace.endSection();
152         }
153     }
154 
updateBrightnessAndReady(boolean force)155     private void updateBrightnessAndReady(boolean force) {
156         if (force || mRegistered || mDebugBrightnessBucket != -1) {
157             int sensorValue = mDebugBrightnessBucket == -1
158                     ? mLastSensorValue : mDebugBrightnessBucket;
159             int brightness = computeBrightness(sensorValue);
160             boolean brightnessReady = brightness > 0;
161             if (brightnessReady) {
162                 mDozeService.setDozeScreenBrightness(clampToUserSetting(brightness));
163             }
164 
165             int scrimOpacity = -1;
166             if (mLightSensor == null) {
167                 // No light sensor, scrims are always transparent.
168                 scrimOpacity = 0;
169             } else if (brightnessReady) {
170                 // Only unblank scrim once brightness is ready.
171                 scrimOpacity = computeScrimOpacity(sensorValue);
172             }
173             if (scrimOpacity >= 0) {
174                 mDozeHost.setAodDimmingScrim(scrimOpacity / 255f);
175             }
176         }
177     }
178 
computeScrimOpacity(int sensorValue)179     private int computeScrimOpacity(int sensorValue) {
180         if (sensorValue < 0 || sensorValue >= mSensorToScrimOpacity.length) {
181             return -1;
182         }
183         return mSensorToScrimOpacity[sensorValue];
184     }
185 
computeBrightness(int sensorValue)186     private int computeBrightness(int sensorValue) {
187         if (sensorValue < 0 || sensorValue >= mSensorToBrightness.length) {
188             return -1;
189         }
190         return mSensorToBrightness[sensorValue];
191     }
192 
193     @Override
onAccuracyChanged(Sensor sensor, int accuracy)194     public void onAccuracyChanged(Sensor sensor, int accuracy) {
195     }
196 
resetBrightnessToDefault()197     private void resetBrightnessToDefault() {
198         mDozeService.setDozeScreenBrightness(clampToUserSetting(mDefaultDozeBrightness));
199         mDozeHost.setAodDimmingScrim(0f);
200     }
201     //TODO: brightnessfloat change usages to float.
clampToUserSetting(int brightness)202     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 
setLightSensorEnabled(boolean enabled)209     private void setLightSensorEnabled(boolean enabled) {
210         if (enabled && !mRegistered && mLightSensor != null) {
211             // Wait until we get an event from the sensor until indicating ready.
212             mRegistered = mSensorManager.registerListener(this, mLightSensor,
213                     SensorManager.SENSOR_DELAY_NORMAL, mHandler);
214             mLastSensorValue = -1;
215         } else if (!enabled && mRegistered) {
216             mSensorManager.unregisterListener(this);
217             mRegistered = false;
218             mLastSensorValue = -1;
219             // Sensor is not enabled, hence we use the default brightness and are always ready.
220         }
221     }
222 
setPaused(boolean paused)223     private void setPaused(boolean paused) {
224         if (mPaused != paused) {
225             mPaused = paused;
226             updateBrightnessAndReady(false /* force */);
227         }
228     }
229 
setScreenOff(boolean screenOff)230     private void setScreenOff(boolean screenOff) {
231         if (mScreenOff != screenOff) {
232             mScreenOff = screenOff;
233             updateBrightnessAndReady(true /* force */);
234         }
235     }
236 
237     @Override
onReceive(Context context, Intent intent)238     public void onReceive(Context context, Intent intent) {
239         mDebugBrightnessBucket = intent.getIntExtra(BRIGHTNESS_BUCKET, -1);
240         updateBrightnessAndReady(false /* force */);
241     }
242 }
243