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