1 /* 2 * Copyright (C) 2024 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.server.display.brightness.strategy; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.hardware.Sensor; 22 import android.hardware.SensorManager; 23 import android.os.Handler; 24 import android.os.SystemClock; 25 import android.util.IndentingPrintWriter; 26 import android.view.Display; 27 28 import com.android.internal.annotations.VisibleForTesting; 29 import com.android.server.display.BrightnessMappingStrategy; 30 import com.android.server.display.DisplayBrightnessState; 31 import com.android.server.display.DisplayDeviceConfig; 32 import com.android.server.display.ScreenOffBrightnessSensorController; 33 import com.android.server.display.brightness.BrightnessReason; 34 import com.android.server.display.brightness.BrightnessUtils; 35 import com.android.server.display.brightness.StrategyExecutionRequest; 36 import com.android.server.display.brightness.StrategySelectionNotifyRequest; 37 import com.android.server.display.layout.Layout; 38 import com.android.server.display.utils.SensorUtils; 39 40 import java.io.PrintWriter; 41 42 /** 43 * This strategy is used when the screen has just turned ON, with auto-brightness ON but there is 44 * no valid lux values available yet. In such a case, if configured, we set the brightness state 45 * from this 46 */ 47 public final class AutoBrightnessFallbackStrategy implements DisplayBrightnessStrategy { 48 49 @Nullable 50 private ScreenOffBrightnessSensorController mScreenOffBrightnessSensorController; 51 @VisibleForTesting 52 @Nullable 53 Sensor mScreenOffBrightnessSensor; 54 55 // Indicates if the associated LogicalDisplay is enabled or not. 56 private boolean mIsEnabled; 57 58 // Represents if the associated display is a lead display or not. If not, the variable 59 // represents the lead display ID 60 private int mLeadDisplayId; 61 62 @NonNull 63 private final Injector mInjector; 64 AutoBrightnessFallbackStrategy(Injector injector)65 public AutoBrightnessFallbackStrategy(Injector injector) { 66 mInjector = (injector == null) ? new RealInjector() : injector; 67 } 68 69 @Override updateBrightness( StrategyExecutionRequest strategyExecutionRequest)70 public DisplayBrightnessState updateBrightness( 71 StrategyExecutionRequest strategyExecutionRequest) { 72 assert mScreenOffBrightnessSensorController != null; 73 float brightness = mScreenOffBrightnessSensorController.getAutomaticScreenBrightness(); 74 BrightnessReason brightnessReason = new BrightnessReason(); 75 brightnessReason.setReason(BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR); 76 return new DisplayBrightnessState.Builder() 77 .setBrightness(brightness) 78 .setSdrBrightness(brightness) 79 .setBrightnessReason(brightnessReason) 80 .setDisplayBrightnessStrategyName(getName()) 81 .setShouldUpdateScreenBrightnessSetting(brightness 82 != strategyExecutionRequest.getCurrentScreenBrightness()) 83 .build(); 84 } 85 86 @NonNull 87 @Override getName()88 public String getName() { 89 return "AutoBrightnessFallbackStrategy"; 90 } 91 92 @Override getReason()93 public int getReason() { 94 return BrightnessReason.REASON_SCREEN_OFF_BRIGHTNESS_SENSOR; 95 } 96 97 @Override dump(PrintWriter writer)98 public void dump(PrintWriter writer) { 99 writer.println("AutoBrightnessFallbackStrategy:"); 100 writer.println(" mLeadDisplayId=" + mLeadDisplayId); 101 writer.println(" mIsEnabled=" + mIsEnabled); 102 if (mScreenOffBrightnessSensorController != null) { 103 IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " "); 104 mScreenOffBrightnessSensorController.dump(ipw); 105 } 106 } 107 108 @Override strategySelectionPostProcessor( StrategySelectionNotifyRequest strategySelectionNotifyRequest)109 public void strategySelectionPostProcessor( 110 StrategySelectionNotifyRequest strategySelectionNotifyRequest) { 111 if (mScreenOffBrightnessSensorController != null) { 112 int targetDisplayState = strategySelectionNotifyRequest.getTargetDisplayState(); 113 mScreenOffBrightnessSensorController.setLightSensorEnabled( 114 strategySelectionNotifyRequest.isAutoBrightnessEnabled() && mIsEnabled 115 && (targetDisplayState == Display.STATE_OFF 116 || (targetDisplayState == Display.STATE_DOZE 117 && !strategySelectionNotifyRequest 118 .isAllowAutoBrightnessWhileDozingConfig())) 119 && mLeadDisplayId == Layout.NO_LEAD_DISPLAY); 120 } 121 } 122 123 /** 124 * Gets the associated ScreenOffBrightnessSensorController, controlling the brightness when 125 * auto-brightness is enabled, but the lux is not valid yet. 126 */ getScreenOffBrightnessSensorController()127 public ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController() { 128 return mScreenOffBrightnessSensorController; 129 } 130 131 /** 132 * Sets up the auto brightness fallback sensor 133 */ setupAutoBrightnessFallbackSensor(SensorManager sensorManager, DisplayDeviceConfig displayDeviceConfig, Handler handler, BrightnessMappingStrategy brightnessMappingStrategy, boolean isEnabled, int leadDisplayId)134 public void setupAutoBrightnessFallbackSensor(SensorManager sensorManager, 135 DisplayDeviceConfig displayDeviceConfig, Handler handler, 136 BrightnessMappingStrategy brightnessMappingStrategy, boolean isEnabled, 137 int leadDisplayId) { 138 mIsEnabled = isEnabled; 139 mLeadDisplayId = leadDisplayId; 140 if (mScreenOffBrightnessSensorController != null) { 141 mScreenOffBrightnessSensorController.stop(); 142 mScreenOffBrightnessSensorController = null; 143 } 144 loadScreenOffBrightnessSensor(sensorManager, displayDeviceConfig); 145 int[] sensorValueToLux = displayDeviceConfig.getScreenOffBrightnessSensorValueToLux(); 146 if (mScreenOffBrightnessSensor != null && sensorValueToLux != null) { 147 mScreenOffBrightnessSensorController = 148 mInjector.getScreenOffBrightnessSensorController( 149 sensorManager, 150 mScreenOffBrightnessSensor, 151 handler, 152 SystemClock::uptimeMillis, 153 sensorValueToLux, 154 brightnessMappingStrategy); 155 } 156 } 157 158 /** 159 * Stops the associated ScreenOffBrightnessSensorController responsible for managing the 160 * brightness when this strategy is selected 161 */ stop()162 public void stop() { 163 if (mScreenOffBrightnessSensorController != null) { 164 mScreenOffBrightnessSensorController.stop(); 165 } 166 } 167 168 /** 169 * Checks if the strategy is valid, based on its internal state. Note that there can still be 170 * external factors like auto-brightness not being enabled because of which this strategy is not 171 * selected 172 */ isValid()173 public boolean isValid() { 174 return mScreenOffBrightnessSensorController != null 175 && BrightnessUtils.isValidBrightnessValue( 176 mScreenOffBrightnessSensorController.getAutomaticScreenBrightness()); 177 } 178 loadScreenOffBrightnessSensor(SensorManager sensorManager, DisplayDeviceConfig displayDeviceConfig)179 private void loadScreenOffBrightnessSensor(SensorManager sensorManager, 180 DisplayDeviceConfig displayDeviceConfig) { 181 mScreenOffBrightnessSensor = mInjector.getScreenOffBrightnessSensor(sensorManager, 182 displayDeviceConfig); 183 } 184 185 186 @VisibleForTesting 187 interface Injector { getScreenOffBrightnessSensor(SensorManager sensorManager, DisplayDeviceConfig displayDeviceConfig)188 Sensor getScreenOffBrightnessSensor(SensorManager sensorManager, 189 DisplayDeviceConfig displayDeviceConfig); 190 getScreenOffBrightnessSensorController( SensorManager sensorManager, Sensor lightSensor, Handler handler, ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux, BrightnessMappingStrategy brightnessMapper)191 ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController( 192 SensorManager sensorManager, 193 Sensor lightSensor, 194 Handler handler, 195 ScreenOffBrightnessSensorController.Clock clock, 196 int[] sensorValueToLux, 197 BrightnessMappingStrategy brightnessMapper); 198 } 199 200 static class RealInjector implements Injector { 201 @Override getScreenOffBrightnessSensor(SensorManager sensorManager, DisplayDeviceConfig displayDeviceConfig)202 public Sensor getScreenOffBrightnessSensor(SensorManager sensorManager, 203 DisplayDeviceConfig displayDeviceConfig) { 204 return SensorUtils.findSensor(sensorManager, 205 displayDeviceConfig.getScreenOffBrightnessSensor(), SensorUtils.NO_FALLBACK); 206 } 207 208 @Override getScreenOffBrightnessSensorController( SensorManager sensorManager, Sensor lightSensor, Handler handler, ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux, BrightnessMappingStrategy brightnessMapper)209 public ScreenOffBrightnessSensorController getScreenOffBrightnessSensorController( 210 SensorManager sensorManager, Sensor lightSensor, Handler handler, 211 ScreenOffBrightnessSensorController.Clock clock, int[] sensorValueToLux, 212 BrightnessMappingStrategy brightnessMapper) { 213 return new ScreenOffBrightnessSensorController( 214 sensorManager, lightSensor, handler, clock, sensorValueToLux, brightnessMapper); 215 } 216 } 217 } 218