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.Context; 20 import android.hardware.Sensor; 21 import android.hardware.SensorEvent; 22 import android.hardware.SensorEventListener; 23 import android.hardware.SensorManager; 24 import android.os.Handler; 25 import android.os.Trace; 26 27 import com.android.internal.annotations.VisibleForTesting; 28 29 /** 30 * Controls the screen brightness when dozing. 31 */ 32 public class DozeScreenBrightness implements DozeMachine.Part, SensorEventListener { 33 private final Context mContext; 34 private final DozeMachine.Service mDozeService; 35 private final DozeHost mDozeHost; 36 private final Handler mHandler; 37 private final SensorManager mSensorManager; 38 private final Sensor mLightSensor; 39 private final int[] mSensorToBrightness; 40 private final int[] mSensorToScrimOpacity; 41 42 private boolean mRegistered; 43 private int mDefaultDozeBrightness; 44 private boolean mPaused = false; 45 private int mLastSensorValue = -1; 46 DozeScreenBrightness(Context context, DozeMachine.Service service, SensorManager sensorManager, Sensor lightSensor, DozeHost host, Handler handler, int defaultDozeBrightness, int[] sensorToBrightness, int[] sensorToScrimOpacity)47 public DozeScreenBrightness(Context context, DozeMachine.Service service, 48 SensorManager sensorManager, Sensor lightSensor, DozeHost host, 49 Handler handler, int defaultDozeBrightness, int[] sensorToBrightness, 50 int[] sensorToScrimOpacity) { 51 mContext = context; 52 mDozeService = service; 53 mSensorManager = sensorManager; 54 mLightSensor = lightSensor; 55 mDozeHost = host; 56 mHandler = handler; 57 58 mDefaultDozeBrightness = defaultDozeBrightness; 59 mSensorToBrightness = sensorToBrightness; 60 mSensorToScrimOpacity = sensorToScrimOpacity; 61 } 62 63 @VisibleForTesting DozeScreenBrightness(Context context, DozeMachine.Service service, SensorManager sensorManager, Sensor lightSensor, DozeHost host, Handler handler, AlwaysOnDisplayPolicy policy)64 public DozeScreenBrightness(Context context, DozeMachine.Service service, 65 SensorManager sensorManager, Sensor lightSensor, DozeHost host, 66 Handler handler, AlwaysOnDisplayPolicy policy) { 67 this(context, service, sensorManager, lightSensor, host, handler, 68 context.getResources().getInteger( 69 com.android.internal.R.integer.config_screenBrightnessDoze), 70 policy.screenBrightnessArray, policy.dimmingScrimArray); 71 } 72 73 @Override transitionTo(DozeMachine.State oldState, DozeMachine.State newState)74 public void transitionTo(DozeMachine.State oldState, DozeMachine.State newState) { 75 switch (newState) { 76 case INITIALIZED: 77 resetBrightnessToDefault(); 78 break; 79 case DOZE_AOD: 80 case DOZE_REQUEST_PULSE: 81 setLightSensorEnabled(true); 82 break; 83 case DOZE: 84 setLightSensorEnabled(false); 85 resetBrightnessToDefault(); 86 break; 87 case FINISH: 88 setLightSensorEnabled(false); 89 break; 90 } 91 if (newState != DozeMachine.State.FINISH) { 92 setPaused(newState == DozeMachine.State.DOZE_AOD_PAUSED); 93 } 94 } 95 96 @Override onSensorChanged(SensorEvent event)97 public void onSensorChanged(SensorEvent event) { 98 Trace.beginSection("DozeScreenBrightness.onSensorChanged" + event.values[0]); 99 try { 100 if (mRegistered) { 101 mLastSensorValue = (int) event.values[0]; 102 updateBrightnessAndReady(); 103 } 104 } finally { 105 Trace.endSection(); 106 } 107 } 108 updateBrightnessAndReady()109 private void updateBrightnessAndReady() { 110 if (mRegistered) { 111 int brightness = computeBrightness(mLastSensorValue); 112 boolean brightnessReady = brightness > 0; 113 if (brightnessReady) { 114 mDozeService.setDozeScreenBrightness(brightness); 115 } 116 117 int scrimOpacity = -1; 118 if (mPaused) { 119 // If AOD is paused, force the screen black until the 120 // sensor reports a new brightness. This ensures that when the screen comes on 121 // again, it will only show after the brightness sensor has stabilized, 122 // avoiding a potential flicker. 123 scrimOpacity = 255; 124 } else if (brightnessReady) { 125 // Only unblank scrim once brightness is ready. 126 scrimOpacity = computeScrimOpacity(mLastSensorValue); 127 } 128 if (scrimOpacity >= 0) { 129 mDozeHost.setAodDimmingScrim(scrimOpacity / 255f); 130 } 131 } 132 } 133 computeScrimOpacity(int sensorValue)134 private int computeScrimOpacity(int sensorValue) { 135 if (sensorValue < 0 || sensorValue >= mSensorToScrimOpacity.length) { 136 return -1; 137 } 138 return mSensorToScrimOpacity[sensorValue]; 139 } 140 computeBrightness(int sensorValue)141 private int computeBrightness(int sensorValue) { 142 if (sensorValue < 0 || sensorValue >= mSensorToBrightness.length) { 143 return -1; 144 } 145 return mSensorToBrightness[sensorValue]; 146 } 147 148 @Override onAccuracyChanged(Sensor sensor, int accuracy)149 public void onAccuracyChanged(Sensor sensor, int accuracy) { 150 } 151 resetBrightnessToDefault()152 private void resetBrightnessToDefault() { 153 mDozeService.setDozeScreenBrightness(mDefaultDozeBrightness); 154 mDozeHost.setAodDimmingScrim(0f); 155 } 156 setLightSensorEnabled(boolean enabled)157 private void setLightSensorEnabled(boolean enabled) { 158 if (enabled && !mRegistered && mLightSensor != null) { 159 // Wait until we get an event from the sensor until indicating ready. 160 mRegistered = mSensorManager.registerListener(this, mLightSensor, 161 SensorManager.SENSOR_DELAY_NORMAL, mHandler); 162 mLastSensorValue = -1; 163 } else if (!enabled && mRegistered) { 164 mSensorManager.unregisterListener(this); 165 mRegistered = false; 166 mLastSensorValue = -1; 167 // Sensor is not enabled, hence we use the default brightness and are always ready. 168 } 169 } 170 setPaused(boolean paused)171 private void setPaused(boolean paused) { 172 if (mPaused != paused) { 173 mPaused = paused; 174 updateBrightnessAndReady(); 175 } 176 } 177 178 } 179