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