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.config; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.res.Resources; 22 import android.text.TextUtils; 23 24 import com.android.internal.annotations.VisibleForTesting; 25 import com.android.server.display.feature.DisplayManagerFlags; 26 27 import java.util.Collections; 28 import java.util.List; 29 30 /** 31 * Uniquely identifies a Sensor, with the combination of Type and Name. 32 */ 33 public class SensorData { 34 35 public static final String TEMPERATURE_TYPE_DISPLAY = "DISPLAY"; 36 public static final String TEMPERATURE_TYPE_SKIN = "SKIN"; 37 38 @Nullable 39 public final String type; 40 @Nullable 41 public final String name; 42 public final float minRefreshRate; 43 public final float maxRefreshRate; 44 public final List<SupportedModeData> supportedModes; 45 46 @VisibleForTesting SensorData()47 public SensorData() { 48 this(/* type= */ null, /* name= */ null); 49 } 50 51 @VisibleForTesting SensorData(String type, String name)52 public SensorData(String type, String name) { 53 this(type, name, /* minRefreshRate= */ 0f, /* maxRefreshRate= */ Float.POSITIVE_INFINITY); 54 } 55 56 @VisibleForTesting SensorData(String type, String name, float minRefreshRate, float maxRefreshRate)57 public SensorData(String type, String name, float minRefreshRate, float maxRefreshRate) { 58 this(type, name, minRefreshRate, maxRefreshRate, /* supportedModes= */ List.of()); 59 } 60 61 @VisibleForTesting SensorData(String type, String name, float minRefreshRate, float maxRefreshRate, List<SupportedModeData> supportedModes)62 public SensorData(String type, String name, float minRefreshRate, float maxRefreshRate, 63 List<SupportedModeData> supportedModes) { 64 this.type = type; 65 this.name = name; 66 this.minRefreshRate = minRefreshRate; 67 this.maxRefreshRate = maxRefreshRate; 68 this.supportedModes = Collections.unmodifiableList(supportedModes); 69 } 70 71 /** 72 * @return True if the sensor matches both the specified name and type, or one if only one 73 * is specified (not-empty). Always returns false if both parameters are null or empty. 74 */ matches(String sensorName, String sensorType)75 public boolean matches(String sensorName, String sensorType) { 76 final boolean isNameSpecified = !TextUtils.isEmpty(sensorName); 77 final boolean isTypeSpecified = !TextUtils.isEmpty(sensorType); 78 return (isNameSpecified || isTypeSpecified) 79 && (!isNameSpecified || sensorName.equals(name)) 80 && (!isTypeSpecified || sensorType.equals(type)); 81 } 82 83 @Override toString()84 public String toString() { 85 return "SensorData{" 86 + "type= " + type 87 + ", name= " + name 88 + ", refreshRateRange: [" + minRefreshRate + ", " + maxRefreshRate + "]" 89 + ", supportedModes=" + supportedModes 90 + '}'; 91 } 92 93 /** 94 * Loads ambient light sensor data from DisplayConfiguration and if missing from resources xml 95 */ loadAmbientLightSensorConfig(DisplayConfiguration config, Resources resources)96 public static SensorData loadAmbientLightSensorConfig(DisplayConfiguration config, 97 Resources resources) { 98 SensorDetails sensorDetails = config.getLightSensor(); 99 if (sensorDetails != null) { 100 return loadSensorData(sensorDetails); 101 } else { 102 return loadAmbientLightSensorConfig(resources); 103 } 104 } 105 106 /** 107 * Loads ambient light sensor data from resources xml 108 */ loadAmbientLightSensorConfig(Resources resources)109 public static SensorData loadAmbientLightSensorConfig(Resources resources) { 110 return new SensorData( 111 resources.getString(com.android.internal.R.string.config_displayLightSensorType), 112 /* name= */ ""); 113 } 114 115 /** 116 * Loads screen off brightness sensor data from DisplayConfiguration 117 */ loadScreenOffBrightnessSensorConfig(DisplayConfiguration config)118 public static SensorData loadScreenOffBrightnessSensorConfig(DisplayConfiguration config) { 119 SensorDetails sensorDetails = config.getScreenOffBrightnessSensor(); 120 if (sensorDetails != null) { 121 return loadSensorData(sensorDetails); 122 } else { 123 return new SensorData(); 124 } 125 } 126 127 /** 128 * Loads proximity sensor data from DisplayConfiguration 129 */ 130 @Nullable loadProxSensorConfig( DisplayManagerFlags flags, DisplayConfiguration config)131 public static SensorData loadProxSensorConfig( 132 DisplayManagerFlags flags, DisplayConfiguration config) { 133 SensorData DEFAULT_SENSOR = new SensorData(); 134 List<SensorDetails> sensorDetailsList = config.getProxSensor(); 135 if (sensorDetailsList.isEmpty()) { 136 return DEFAULT_SENSOR; 137 } 138 139 SensorData selectedSensor = DEFAULT_SENSOR; 140 // Prioritize flagged sensors. 141 for (SensorDetails sensorDetails : sensorDetailsList) { 142 String flagStr = sensorDetails.getFeatureFlag(); 143 if (flags.isUseFusionProxSensorEnabled() && 144 flags.getUseFusionProxSensorFlagName().equals(flagStr)) { 145 selectedSensor = loadSensorData(sensorDetails); 146 break; 147 } 148 } 149 150 // Check for normal un-flagged sensor if a flagged one wasn't found. 151 if (DEFAULT_SENSOR == selectedSensor) { 152 for (SensorDetails sensorDetails : sensorDetailsList) { 153 if (sensorDetails.getFeatureFlag() != null) { 154 continue; 155 } 156 selectedSensor = loadSensorData(sensorDetails); 157 break; 158 } 159 } 160 161 // Check if we shouldn't use a sensor at all. 162 if (DEFAULT_SENSOR != selectedSensor) { 163 if ("".equals(selectedSensor.name) && "".equals(selectedSensor.type)) { 164 // <proxSensor> with empty values to the config means no sensor should be used. 165 // See also {@link com.android.server.display.utils.SensorUtils} 166 selectedSensor = null; 167 } 168 } 169 170 return selectedSensor; 171 } 172 173 /** 174 * Loads temperature sensor data for no config case. (Type: SKIN, Name: null) 175 */ loadTempSensorUnspecifiedConfig()176 public static SensorData loadTempSensorUnspecifiedConfig() { 177 return new SensorData(TEMPERATURE_TYPE_SKIN, null); 178 } 179 180 /** 181 * Loads temperature sensor data from given display config. 182 * If empty or null config given default to (Type: SKIN, Name: null) 183 */ loadTempSensorConfig(DisplayManagerFlags flags, DisplayConfiguration config)184 public static SensorData loadTempSensorConfig(DisplayManagerFlags flags, 185 DisplayConfiguration config) { 186 SensorDetails sensorDetails = config.getTempSensor(); 187 if (!flags.isSensorBasedBrightnessThrottlingEnabled() || sensorDetails == null) { 188 return new SensorData(TEMPERATURE_TYPE_SKIN, null); 189 } 190 String name = sensorDetails.getName(); 191 String type = sensorDetails.getType(); 192 if (TextUtils.isEmpty(type) || TextUtils.isEmpty(name)) { 193 type = TEMPERATURE_TYPE_SKIN; 194 name = null; 195 } 196 return new SensorData(type, name); 197 } 198 199 /** 200 * Loads sensor unspecified config, this means system should use default sensor. 201 * See also {@link com.android.server.display.utils.SensorUtils} 202 */ 203 @NonNull loadSensorUnspecifiedConfig()204 public static SensorData loadSensorUnspecifiedConfig() { 205 return new SensorData(); 206 } 207 loadSensorData(@onNull SensorDetails sensorDetails)208 private static SensorData loadSensorData(@NonNull SensorDetails sensorDetails) { 209 float minRefreshRate = 0f; 210 float maxRefreshRate = Float.POSITIVE_INFINITY; 211 RefreshRateRange rr = sensorDetails.getRefreshRate(); 212 if (rr != null) { 213 minRefreshRate = rr.getMinimum().floatValue(); 214 maxRefreshRate = rr.getMaximum().floatValue(); 215 } 216 List<SupportedModeData> supportedModes = SupportedModeData.load( 217 sensorDetails.getSupportedModes()); 218 219 return new SensorData(sensorDetails.getType(), sensorDetails.getName(), minRefreshRate, 220 maxRefreshRate, supportedModes); 221 } 222 223 } 224