1 /* 2 * Copyright (C) 2020 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 android.car.hardware.power; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.util.SparseBooleanArray; 23 24 import java.lang.annotation.Retention; 25 import java.lang.annotation.RetentionPolicy; 26 import java.util.ArrayList; 27 import java.util.Iterator; 28 import java.util.List; 29 30 /** 31 * Utility class used when dealing with PowerComponent. 32 * 33 * @hide 34 */ 35 public final class PowerComponentUtil { 36 /** 37 * The component is marked as enabled in the power policy. 38 */ 39 public static final int COMPONENT_STATE_ENABLED = 1; 40 41 /** 42 * The component is marked as disabled in the power policy. 43 */ 44 public static final int COMPONENT_STATE_DISABLED = 2; 45 46 /** 47 * The component is not specified in the power policy. 48 */ 49 public static final int COMPONENT_STATE_UNTOUCHED = 3; 50 51 @IntDef(prefix = { "COMPONENT_STATE_" }, value = { 52 COMPONENT_STATE_ENABLED, 53 COMPONENT_STATE_DISABLED, 54 COMPONENT_STATE_UNTOUCHED 55 }) 56 @Retention(RetentionPolicy.SOURCE) 57 public @interface ComponentState { } 58 59 /** 60 * Represetns an invalid power component. 61 */ 62 public static final int INVALID_POWER_COMPONENT = -1; 63 64 /** 65 * The first component in {@link PowerComponent}. 66 */ 67 public static final int FIRST_POWER_COMPONENT = PowerComponent.AUDIO; 68 69 /** 70 * The last component in {@link PowerComponent}. 71 * 72 * <p> This should be updated when a new component is added to {@link PowerComponent}. 73 */ 74 public static final int LAST_POWER_COMPONENT = PowerComponent.CPU; 75 76 private static final String POWER_COMPONENT_PREFIX = "POWER_COMPONENT_"; 77 78 private static final String POWER_COMPONENT_AUDIO = "AUDIO"; 79 private static final String POWER_COMPONENT_MEDIA = "MEDIA"; 80 private static final String POWER_COMPONENT_DISPLAY = "DISPLAY"; 81 private static final String POWER_COMPONENT_BLUETOOTH = "BLUETOOTH"; 82 private static final String POWER_COMPONENT_WIFI = "WIFI"; 83 private static final String POWER_COMPONENT_CELLULAR = "CELLULAR"; 84 private static final String POWER_COMPONENT_ETHERNET = "ETHERNET"; 85 private static final String POWER_COMPONENT_PROJECTION = "PROJECTION"; 86 private static final String POWER_COMPONENT_NFC = "NFC"; 87 private static final String POWER_COMPONENT_INPUT = "INPUT"; 88 private static final String POWER_COMPONENT_VOICE_INTERACTION = "VOICE_INTERACTION"; 89 private static final String POWER_COMPONENT_VISUAL_INTERACTION = "VISUAL_INTERACTION"; 90 private static final String POWER_COMPONENT_TRUSTED_DEVICE_DETECTION = 91 "TRUSTED_DEVICE_DETECTION"; 92 private static final String POWER_COMPONENT_LOCATION = "LOCATION"; 93 private static final String POWER_COMPONENT_MICROPHONE = "MICROPHONE"; 94 private static final String POWER_COMPONENT_CPU = "CPU"; 95 96 private interface ComponentFilter { filter(int[] components)97 boolean filter(int[] components); 98 } 99 100 // PowerComponentUtil is intended to provide static variables and methods. PowerComponentUtil()101 private PowerComponentUtil() {} 102 103 /** 104 * Checks whether the given component is valid. 105 */ isValidPowerComponent(int component)106 public static boolean isValidPowerComponent(int component) { 107 return component >= FIRST_POWER_COMPONENT && component <= LAST_POWER_COMPONENT; 108 } 109 110 /** 111 * Checks whether the given policy has one ore more components specified in the given filter. 112 */ hasComponents(@onNull CarPowerPolicy policy, @NonNull CarPowerPolicyFilter filter)113 public static boolean hasComponents(@NonNull CarPowerPolicy policy, 114 @NonNull CarPowerPolicyFilter filter) { 115 SparseBooleanArray filterSet = new SparseBooleanArray(); 116 int[] components = filter.getComponents(); 117 for (int i = 0; i < components.length; i++) { 118 filterSet.put(components[i], true); 119 } 120 121 ComponentFilter componentFilter = (c) -> { 122 for (int i = 0; i < c.length; i++) { 123 if (filterSet.get(c[i])) { 124 return true; 125 } 126 } 127 return false; 128 }; 129 130 if (componentFilter.filter(policy.getEnabledComponents())) { 131 return true; 132 } 133 return componentFilter.filter(policy.getDisabledComponents()); 134 } 135 136 /** 137 * Matches the given string to {@link PowerComponent}. 138 */ toPowerComponent(@ullable String componentArg, boolean prefix)139 public static int toPowerComponent(@Nullable String componentArg, boolean prefix) { 140 String component = componentArg; 141 if (component == null) { 142 return INVALID_POWER_COMPONENT; 143 } 144 if (prefix) { 145 if (!component.startsWith(POWER_COMPONENT_PREFIX)) { 146 return INVALID_POWER_COMPONENT; 147 } 148 component = component.substring(POWER_COMPONENT_PREFIX.length()); 149 } 150 switch (component) { 151 case POWER_COMPONENT_AUDIO: 152 return PowerComponent.AUDIO; 153 case POWER_COMPONENT_MEDIA: 154 return PowerComponent.MEDIA; 155 case POWER_COMPONENT_DISPLAY: 156 return PowerComponent.DISPLAY; 157 case POWER_COMPONENT_BLUETOOTH: 158 return PowerComponent.BLUETOOTH; 159 case POWER_COMPONENT_WIFI: 160 return PowerComponent.WIFI; 161 case POWER_COMPONENT_CELLULAR: 162 return PowerComponent.CELLULAR; 163 case POWER_COMPONENT_ETHERNET: 164 return PowerComponent.ETHERNET; 165 case POWER_COMPONENT_PROJECTION: 166 return PowerComponent.PROJECTION; 167 case POWER_COMPONENT_NFC: 168 return PowerComponent.NFC; 169 case POWER_COMPONENT_INPUT: 170 return PowerComponent.INPUT; 171 case POWER_COMPONENT_VOICE_INTERACTION: 172 return PowerComponent.VOICE_INTERACTION; 173 case POWER_COMPONENT_VISUAL_INTERACTION: 174 return PowerComponent.VISUAL_INTERACTION; 175 case POWER_COMPONENT_TRUSTED_DEVICE_DETECTION: 176 return PowerComponent.TRUSTED_DEVICE_DETECTION; 177 case POWER_COMPONENT_LOCATION: 178 return PowerComponent.LOCATION; 179 case POWER_COMPONENT_MICROPHONE: 180 return PowerComponent.MICROPHONE; 181 case POWER_COMPONENT_CPU: 182 return PowerComponent.CPU; 183 default: 184 if (component.matches("\\d+")) { 185 int componentNumber = Integer.parseInt(component); 186 if (componentNumber >= PowerComponent.MINIMUM_CUSTOM_COMPONENT_VALUE) { 187 return componentNumber; 188 } 189 } 190 return INVALID_POWER_COMPONENT; 191 } 192 } 193 194 /** 195 * Convert {@link PowerComponent} to string. 196 */ 197 @NonNull powerComponentToString(int component)198 public static String powerComponentToString(int component) { 199 switch (component) { 200 case PowerComponent.AUDIO: 201 return POWER_COMPONENT_AUDIO; 202 case PowerComponent.MEDIA: 203 return POWER_COMPONENT_MEDIA; 204 case PowerComponent.DISPLAY: 205 return POWER_COMPONENT_DISPLAY; 206 case PowerComponent.BLUETOOTH: 207 return POWER_COMPONENT_BLUETOOTH; 208 case PowerComponent.WIFI: 209 return POWER_COMPONENT_WIFI; 210 case PowerComponent.CELLULAR: 211 return POWER_COMPONENT_CELLULAR; 212 case PowerComponent.ETHERNET: 213 return POWER_COMPONENT_ETHERNET; 214 case PowerComponent.PROJECTION: 215 return POWER_COMPONENT_PROJECTION; 216 case PowerComponent.NFC: 217 return POWER_COMPONENT_NFC; 218 case PowerComponent.INPUT: 219 return POWER_COMPONENT_INPUT; 220 case PowerComponent.VOICE_INTERACTION: 221 return POWER_COMPONENT_VOICE_INTERACTION; 222 case PowerComponent.VISUAL_INTERACTION: 223 return POWER_COMPONENT_VISUAL_INTERACTION; 224 case PowerComponent.TRUSTED_DEVICE_DETECTION: 225 return POWER_COMPONENT_TRUSTED_DEVICE_DETECTION; 226 case PowerComponent.LOCATION: 227 return POWER_COMPONENT_LOCATION; 228 case PowerComponent.MICROPHONE: 229 return POWER_COMPONENT_MICROPHONE; 230 case PowerComponent.CPU: 231 return POWER_COMPONENT_CPU; 232 default: 233 if (component >= PowerComponent.MINIMUM_CUSTOM_COMPONENT_VALUE) { 234 return Integer.toString(component); 235 } 236 return "unknown component"; 237 } 238 } 239 240 /** 241 * Convert list of {@link PowerComponent} to list of strings. 242 */ 243 @NonNull powerComponentsToStrings(Iterable<Integer> components)244 public static List<String> powerComponentsToStrings(Iterable<Integer> components) { 245 List<String> powerComponents = new ArrayList<>(); 246 Iterator<Integer> componentsIterator = components.iterator(); 247 while (componentsIterator.hasNext()) { 248 Integer component = componentsIterator.next(); 249 powerComponents.add(powerComponentToString(component)); 250 } 251 return powerComponents; 252 } 253 254 /** 255 * Convert list of {@link PowerComponent} to string containing a list of the components, 256 * each separated by a comma and a space. (Example: "AUDIO, WIFI") 257 */ 258 @NonNull powerComponentsToString(Iterable<Integer> components)259 public static String powerComponentsToString(Iterable<Integer> components) { 260 StringBuilder builder = new StringBuilder(); 261 Iterator<Integer> componentsIterator = components.iterator(); 262 // Do first element separately to not start the list with a comma 263 if (componentsIterator.hasNext()) { 264 builder.append(powerComponentToString(componentsIterator.next())); 265 } 266 while (componentsIterator.hasNext()) { 267 builder.append( 268 String.format(", %s", powerComponentToString(componentsIterator.next()))); 269 } 270 return builder.toString(); 271 } 272 273 /** 274 * Convert list of strings to list of {@link PowerComponent}. 275 */ 276 @NonNull toPowerComponents(Iterable<String> components, boolean prefix)277 public static Iterable<Integer> toPowerComponents(Iterable<String> components, boolean prefix) { 278 List<Integer> powerComponents = new ArrayList<>(); 279 Iterator<String> componentsIterator = components.iterator(); 280 while (componentsIterator.hasNext()) { 281 String component = componentsIterator.next(); 282 powerComponents.add(toPowerComponent(component, prefix)); 283 } 284 return powerComponents; 285 } 286 } 287