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 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 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 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 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 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 134 private int computeScrimOpacity(int sensorValue) { 135 if (sensorValue < 0 || sensorValue >= mSensorToScrimOpacity.length) { 136 return -1; 137 } 138 return mSensorToScrimOpacity[sensorValue]; 139 } 140 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 149 public void onAccuracyChanged(Sensor sensor, int accuracy) { 150 } 151 152 private void resetBrightnessToDefault() { 153 mDozeService.setDozeScreenBrightness(mDefaultDozeBrightness); 154 mDozeHost.setAodDimmingScrim(0f); 155 } 156 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 171 private void setPaused(boolean paused) { 172 if (mPaused != paused) { 173 mPaused = paused; 174 updateBrightnessAndReady(); 175 } 176 } 177 178 } 179