1 /*
2  * Copyright (C) 2023 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.feature;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.hardware.display.DisplayManager;
22 import android.provider.DeviceConfig;
23 import android.provider.DeviceConfigInterface;
24 import android.util.Slog;
25 
26 import com.android.server.display.utils.DeviceConfigParsingUtils;
27 
28 import java.util.concurrent.Executor;
29 
30 /**
31  * Helper class to access all DeviceConfig features for display_manager namespace
32  *
33  **/
34 public class DeviceConfigParameterProvider {
35 
36     private static final String TAG = "DisplayFeatureProvider";
37 
38     private final DeviceConfigInterface mDeviceConfig;
39 
DeviceConfigParameterProvider(DeviceConfigInterface deviceConfig)40     public DeviceConfigParameterProvider(DeviceConfigInterface deviceConfig) {
41         mDeviceConfig = deviceConfig;
42     }
43 
44     // feature: revamping_display_power_controller_feature
45     // parameter: use_newly_structured_display_power_controller
isNewPowerControllerFeatureEnabled()46     public boolean isNewPowerControllerFeatureEnabled() {
47         return mDeviceConfig.getBoolean(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
48                 DisplayManager.DeviceConfig.KEY_NEW_POWER_CONTROLLER, true);
49     }
50 
51     // feature: hdr_output_control
52     // parameter: enable_hdr_output_control
isHdrOutputControlFeatureEnabled()53     public boolean isHdrOutputControlFeatureEnabled() {
54         return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
55                 DisplayManager.HDR_OUTPUT_CONTROL_FLAG, true);
56     }
57 
58     // feature: flexible_brightness_range_feature
59     // parameter: normal_brightness_mode_controller_enabled
isNormalBrightnessControllerFeatureEnabled()60     public boolean isNormalBrightnessControllerFeatureEnabled() {
61         return DeviceConfig.getBoolean(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
62                 DisplayManager.DeviceConfig.KEY_USE_NORMAL_BRIGHTNESS_MODE_CONTROLLER, false);
63     }
64 
isDisableScreenWakeLocksWhileCachedFeatureEnabled()65     public boolean isDisableScreenWakeLocksWhileCachedFeatureEnabled() {
66         return mDeviceConfig.getBoolean(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
67                 DisplayManager.DeviceConfig.KEY_DISABLE_SCREEN_WAKE_LOCKS_WHILE_CACHED, true);
68     }
69 
70     // feature: smooth_display_feature
71     // parameter: peak_refresh_rate_default
getPeakRefreshRateDefault()72     public float getPeakRefreshRateDefault() {
73         return mDeviceConfig.getFloat(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
74                 DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, -1);
75     }
76 
77     // Test parameters
78     // usage e.g.: adb shell device_config put display_manager refresh_rate_in_hbm_sunlight 90
79 
80     // allows to customize brightness throttling data
getBrightnessThrottlingData()81     public String getBrightnessThrottlingData() {
82         return mDeviceConfig.getString(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
83                 DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA, null);
84     }
85 
getRefreshRateInHbmSunlight()86     public int getRefreshRateInHbmSunlight() {
87         return mDeviceConfig.getInt(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
88                 DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_SUNLIGHT, -1);
89     }
90 
getRefreshRateInHbmHdr()91     public int getRefreshRateInHbmHdr() {
92         return mDeviceConfig.getInt(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
93                 DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HBM_HDR, -1);
94     }
95 
96 
getRefreshRateInHighZone()97     public int getRefreshRateInHighZone() {
98         return mDeviceConfig.getInt(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
99                 DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE, -1);
100     }
101 
getRefreshRateInLowZone()102     public int getRefreshRateInLowZone() {
103         return mDeviceConfig.getInt(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
104                 DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE, -1);
105     }
106 
107     /**
108      * Get the high ambient brightness thresholds for the configured refresh rate zone. The values
109      * are paired with brightness thresholds.
110      *
111      * A negative value means that only the display brightness threshold should be used.
112      *
113      * Return null if no such property or wrong format (not comma separated integers).
114      */
115     @Nullable
getHighAmbientBrightnessThresholds()116     public float[] getHighAmbientBrightnessThresholds() {
117         return DeviceConfigParsingUtils.ambientBrightnessThresholdsIntToFloat(
118                 getIntArrayProperty(DisplayManager.DeviceConfig
119                         .KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS));
120     }
121 
122     /**
123      * Get the high display brightness thresholds for the configured refresh rate zone. The values
124      * are paired with lux thresholds.
125      *
126      * A negative value means that only the ambient threshold should be used.
127      *
128      * Return null if no such property or wrong format (not comma separated integers).
129      */
130     @Nullable
getHighDisplayBrightnessThresholds()131     public float[] getHighDisplayBrightnessThresholds() {
132         return DeviceConfigParsingUtils.displayBrightnessThresholdsIntToFloat(
133                 getIntArrayProperty(DisplayManager.DeviceConfig
134                         .KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS));
135     }
136 
137     /**
138      * Get the low display brightness thresholds for the configured refresh rate zone. The values
139      * are paired with lux thresholds.
140      *
141      * A negative value means that only the ambient threshold should be used.
142      *
143      * Return null if no such property or wrong format (not comma separated integers).
144      */
145     @Nullable
getLowDisplayBrightnessThresholds()146     public float[] getLowDisplayBrightnessThresholds() {
147         return DeviceConfigParsingUtils.displayBrightnessThresholdsIntToFloat(
148                 getIntArrayProperty(DisplayManager.DeviceConfig
149                         .KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS));
150     }
151 
152     /**
153      * Get the low ambient brightness thresholds for the configured refresh rate zone. The values
154      * are paired with brightness thresholds.
155      *
156      * A negative value means that only the display brightness threshold should be used.
157      *
158      * Return null if no such property or wrong format (not comma separated integers).
159      */
160     @Nullable
getLowAmbientBrightnessThresholds()161     public float[] getLowAmbientBrightnessThresholds() {
162         return DeviceConfigParsingUtils.ambientBrightnessThresholdsIntToFloat(
163                 getIntArrayProperty(DisplayManager.DeviceConfig
164                         .KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS));
165     }
166 
167     /** add property change listener to DeviceConfig */
addOnPropertiesChangedListener(Executor executor, DeviceConfig.OnPropertiesChangedListener listener)168     public void addOnPropertiesChangedListener(Executor executor,
169             DeviceConfig.OnPropertiesChangedListener listener) {
170         mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
171                 executor, listener);
172     }
173 
174     /** remove property change listener from DeviceConfig */
removeOnPropertiesChangedListener( DeviceConfig.OnPropertiesChangedListener listener)175     public void removeOnPropertiesChangedListener(
176             DeviceConfig.OnPropertiesChangedListener listener) {
177         mDeviceConfig.removeOnPropertiesChangedListener(listener);
178     }
179 
180     @Nullable
getIntArrayProperty(String prop)181     private int[] getIntArrayProperty(String prop) {
182         String strArray = mDeviceConfig.getString(DeviceConfig.NAMESPACE_DISPLAY_MANAGER, prop,
183                 null);
184 
185         if (strArray != null) {
186             return parseIntArray(strArray);
187         }
188         return null;
189     }
190 
191     @Nullable
parseIntArray(@onNull String strArray)192     private int[] parseIntArray(@NonNull String strArray) {
193         String[] items = strArray.split(",");
194         int[] array = new int[items.length];
195 
196         try {
197             for (int i = 0; i < array.length; i++) {
198                 array[i] = Integer.parseInt(items[i]);
199             }
200         } catch (NumberFormatException e) {
201             Slog.e(TAG, "Incorrect format for array: '" + strArray + "'", e);
202             array = null;
203         }
204 
205         return array;
206     }
207 }
208