1 /*
2  * Copyright (C) 2022 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;
18 
19 import android.annotation.NonNull;
20 import android.content.Context;
21 import android.hardware.display.DisplayManagerInternal;
22 import android.util.IndentingPrintWriter;
23 import android.util.Slog;
24 import android.view.Display;
25 
26 import com.android.internal.R;
27 import com.android.internal.annotations.VisibleForTesting;
28 import com.android.server.display.brightness.strategy.AutomaticBrightnessStrategy;
29 import com.android.server.display.brightness.strategy.BoostBrightnessStrategy;
30 import com.android.server.display.brightness.strategy.DisplayBrightnessStrategy;
31 import com.android.server.display.brightness.strategy.DozeBrightnessStrategy;
32 import com.android.server.display.brightness.strategy.FollowerBrightnessStrategy;
33 import com.android.server.display.brightness.strategy.InvalidBrightnessStrategy;
34 import com.android.server.display.brightness.strategy.OverrideBrightnessStrategy;
35 import com.android.server.display.brightness.strategy.ScreenOffBrightnessStrategy;
36 import com.android.server.display.brightness.strategy.TemporaryBrightnessStrategy;
37 
38 import java.io.PrintWriter;
39 
40 /**
41  * This maintains the logic needed to decide the eligible display brightness strategy.
42  */
43 public class DisplayBrightnessStrategySelector {
44     private static final String TAG = "DisplayBrightnessStrategySelector";
45     // True if light sensor is to be used to automatically determine doze screen brightness.
46     private final boolean mAllowAutoBrightnessWhileDozingConfig;
47 
48     // The brightness strategy used to manage the brightness state when the display is dozing.
49     private final DozeBrightnessStrategy mDozeBrightnessStrategy;
50     // The brightness strategy used to manage the brightness state when the display is in
51     // screen off state.
52     private final ScreenOffBrightnessStrategy mScreenOffBrightnessStrategy;
53     // The brightness strategy used to manage the brightness state when the request state is
54     // invalid.
55     private final OverrideBrightnessStrategy mOverrideBrightnessStrategy;
56     // The brightness strategy used to manage the brightness state in temporary state
57     private final TemporaryBrightnessStrategy mTemporaryBrightnessStrategy;
58     // The brightness strategy used to manage the brightness state when boost is requested
59     private final BoostBrightnessStrategy mBoostBrightnessStrategy;
60     // The brightness strategy used for additional displays
61     private final FollowerBrightnessStrategy mFollowerBrightnessStrategy;
62     // The brightness strategy used to manage the brightness state when the request is invalid.
63     private final InvalidBrightnessStrategy mInvalidBrightnessStrategy;
64     // Controls brightness when automatic (adaptive) brightness is running.
65     private final AutomaticBrightnessStrategy mAutomaticBrightnessStrategy;
66 
67     // We take note of the old brightness strategy so that we can know when the strategy changes.
68     private String mOldBrightnessStrategyName;
69 
70     private final int mDisplayId;
71 
72     /**
73      * The constructor of DozeBrightnessStrategy.
74      */
DisplayBrightnessStrategySelector(Context context, Injector injector, int displayId)75     public DisplayBrightnessStrategySelector(Context context, Injector injector, int displayId) {
76         if (injector == null) {
77             injector = new Injector();
78         }
79         mDisplayId = displayId;
80         mDozeBrightnessStrategy = injector.getDozeBrightnessStrategy();
81         mScreenOffBrightnessStrategy = injector.getScreenOffBrightnessStrategy();
82         mOverrideBrightnessStrategy = injector.getOverrideBrightnessStrategy();
83         mTemporaryBrightnessStrategy = injector.getTemporaryBrightnessStrategy();
84         mBoostBrightnessStrategy = injector.getBoostBrightnessStrategy();
85         mFollowerBrightnessStrategy = injector.getFollowerBrightnessStrategy(displayId);
86         mInvalidBrightnessStrategy = injector.getInvalidBrightnessStrategy();
87         mAutomaticBrightnessStrategy = injector.getAutomaticBrightnessStrategy(context, displayId);
88         mAllowAutoBrightnessWhileDozingConfig = context.getResources().getBoolean(
89                 R.bool.config_allowAutoBrightnessWhileDozing);
90         mOldBrightnessStrategyName = mInvalidBrightnessStrategy.getName();
91     }
92 
93     /**
94      * Selects the appropriate DisplayBrightnessStrategy based on the request and the display state
95      * to which the display is transitioning
96      */
97     @NonNull
selectStrategy( DisplayManagerInternal.DisplayPowerRequest displayPowerRequest, int targetDisplayState)98     public DisplayBrightnessStrategy selectStrategy(
99             DisplayManagerInternal.DisplayPowerRequest displayPowerRequest,
100             int targetDisplayState) {
101         DisplayBrightnessStrategy displayBrightnessStrategy = mInvalidBrightnessStrategy;
102         if (targetDisplayState == Display.STATE_OFF) {
103             displayBrightnessStrategy = mScreenOffBrightnessStrategy;
104         } else if (shouldUseDozeBrightnessStrategy(displayPowerRequest)) {
105             displayBrightnessStrategy = mDozeBrightnessStrategy;
106         } else if (BrightnessUtils.isValidBrightnessValue(
107                 mFollowerBrightnessStrategy.getBrightnessToFollow())) {
108             displayBrightnessStrategy = mFollowerBrightnessStrategy;
109         } else if (displayPowerRequest.boostScreenBrightness) {
110             displayBrightnessStrategy = mBoostBrightnessStrategy;
111         } else if (BrightnessUtils
112                 .isValidBrightnessValue(displayPowerRequest.screenBrightnessOverride)) {
113             displayBrightnessStrategy = mOverrideBrightnessStrategy;
114         } else if (BrightnessUtils.isValidBrightnessValue(
115                 mTemporaryBrightnessStrategy.getTemporaryScreenBrightness())) {
116             displayBrightnessStrategy = mTemporaryBrightnessStrategy;
117         }
118 
119         if (!mOldBrightnessStrategyName.equals(displayBrightnessStrategy.getName())) {
120             Slog.i(TAG,
121                     "Changing the DisplayBrightnessStrategy from " + mOldBrightnessStrategyName
122                             + " to" + displayBrightnessStrategy.getName() + " for display "
123                             + mDisplayId);
124             mOldBrightnessStrategyName = displayBrightnessStrategy.getName();
125         }
126         return displayBrightnessStrategy;
127     }
128 
getTemporaryDisplayBrightnessStrategy()129     public TemporaryBrightnessStrategy getTemporaryDisplayBrightnessStrategy() {
130         return mTemporaryBrightnessStrategy;
131     }
132 
getFollowerDisplayBrightnessStrategy()133     public FollowerBrightnessStrategy getFollowerDisplayBrightnessStrategy() {
134         return mFollowerBrightnessStrategy;
135     }
136 
getAutomaticBrightnessStrategy()137     public AutomaticBrightnessStrategy getAutomaticBrightnessStrategy() {
138         return mAutomaticBrightnessStrategy;
139     }
140 
141     /**
142      * Returns a boolean flag indicating if the light sensor is to be used to decide the screen
143      * brightness when dozing
144      */
isAllowAutoBrightnessWhileDozingConfig()145     public boolean isAllowAutoBrightnessWhileDozingConfig() {
146         return mAllowAutoBrightnessWhileDozingConfig;
147     }
148 
149     /**
150      * Dumps the state of this class.
151      */
dump(PrintWriter writer)152     public void dump(PrintWriter writer) {
153         writer.println();
154         writer.println("DisplayBrightnessStrategySelector:");
155         writer.println("  mDisplayId= " + mDisplayId);
156         writer.println("  mOldBrightnessStrategyName= " + mOldBrightnessStrategyName);
157         writer.println(
158                 "  mAllowAutoBrightnessWhileDozingConfig= "
159                         + mAllowAutoBrightnessWhileDozingConfig);
160         IndentingPrintWriter ipw = new IndentingPrintWriter(writer, " ");
161         mTemporaryBrightnessStrategy.dump(ipw);
162     }
163 
164     /**
165      * Validates if the conditions are met to qualify for the DozeBrightnessStrategy.
166      */
shouldUseDozeBrightnessStrategy( DisplayManagerInternal.DisplayPowerRequest displayPowerRequest)167     private boolean shouldUseDozeBrightnessStrategy(
168             DisplayManagerInternal.DisplayPowerRequest displayPowerRequest) {
169         // We are not checking the targetDisplayState, but rather relying on the policy because
170         // a user can define a different display state(displayPowerRequest.dozeScreenState) too
171         // in the request with the Doze policy
172         if (displayPowerRequest.policy == DisplayManagerInternal.DisplayPowerRequest.POLICY_DOZE) {
173             if (!mAllowAutoBrightnessWhileDozingConfig) {
174                 return true;
175             }
176         }
177         return false;
178     }
179 
180     @VisibleForTesting
181     static class Injector {
getScreenOffBrightnessStrategy()182         ScreenOffBrightnessStrategy getScreenOffBrightnessStrategy() {
183             return new ScreenOffBrightnessStrategy();
184         }
185 
getDozeBrightnessStrategy()186         DozeBrightnessStrategy getDozeBrightnessStrategy() {
187             return new DozeBrightnessStrategy();
188         }
189 
getOverrideBrightnessStrategy()190         OverrideBrightnessStrategy getOverrideBrightnessStrategy() {
191             return new OverrideBrightnessStrategy();
192         }
193 
getTemporaryBrightnessStrategy()194         TemporaryBrightnessStrategy getTemporaryBrightnessStrategy() {
195             return new TemporaryBrightnessStrategy();
196         }
197 
getBoostBrightnessStrategy()198         BoostBrightnessStrategy getBoostBrightnessStrategy() {
199             return new BoostBrightnessStrategy();
200         }
201 
getFollowerBrightnessStrategy(int displayId)202         FollowerBrightnessStrategy getFollowerBrightnessStrategy(int displayId) {
203             return new FollowerBrightnessStrategy(displayId);
204         }
205 
getInvalidBrightnessStrategy()206         InvalidBrightnessStrategy getInvalidBrightnessStrategy() {
207             return new InvalidBrightnessStrategy();
208         }
209 
getAutomaticBrightnessStrategy(Context context, int displayId)210         AutomaticBrightnessStrategy getAutomaticBrightnessStrategy(Context context, int displayId) {
211             return new AutomaticBrightnessStrategy(context, displayId);
212         }
213     }
214 }
215