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