1 /* 2 * Copyright (C) 2019 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 package com.android.internal.util; 17 18 import static com.android.internal.util.BitUtils.flagsUpTo; 19 20 import android.annotation.AppIdInt; 21 import android.annotation.ColorInt; 22 import android.annotation.FloatRange; 23 import android.annotation.IntRange; 24 import android.annotation.NonNull; 25 import android.annotation.Size; 26 import android.annotation.UserIdInt; 27 import android.content.Intent; 28 import android.content.pm.PackageManager; 29 import android.content.pm.PackageManager.PackageInfoFlagsBits; 30 import android.content.pm.PackageManager.PermissionResult; 31 import android.os.UserHandle; 32 33 import java.lang.annotation.Annotation; 34 35 /** 36 * Validations for common annotations, e.g. {@link IntRange}, {@link UserIdInt}, etc. 37 * 38 * For usability from generated {@link DataClass} code, all validations are overloads of 39 * {@link #validate} with the following shape: 40 * {@code 41 * <A extends Annotation> void validate( 42 * Class<A> cls, A ignored, Object value[, (String, Object)... annotationParams]) 43 * } 44 * The ignored {@link Annotation} parameter is used to differentiate between overloads that would 45 * otherwise have the same jvm signature. It's usually null at runtime. 46 */ 47 public class AnnotationValidations { AnnotationValidations()48 private AnnotationValidations() {} 49 validate(Class<UserIdInt> annotation, UserIdInt ignored, int value)50 public static void validate(Class<UserIdInt> annotation, UserIdInt ignored, int value) { 51 if ((value != UserHandle.USER_NULL && value < -3) 52 || value > Integer.MAX_VALUE / UserHandle.PER_USER_RANGE) { 53 invalid(annotation, value); 54 } 55 } 56 validate(Class<AppIdInt> annotation, AppIdInt ignored, int value)57 public static void validate(Class<AppIdInt> annotation, AppIdInt ignored, int value) { 58 if (value / UserHandle.PER_USER_RANGE != 0 || value < 0) { 59 invalid(annotation, value); 60 } 61 } 62 validate(Class<IntRange> annotation, IntRange ignored, int value, String paramName1, long param1, String paramName2, long param2)63 public static void validate(Class<IntRange> annotation, IntRange ignored, int value, 64 String paramName1, long param1, String paramName2, long param2) { 65 validate(annotation, ignored, value, paramName1, param1); 66 validate(annotation, ignored, value, paramName2, param2); 67 } 68 validate(Class<IntRange> annotation, IntRange ignored, int value, String paramName, long param)69 public static void validate(Class<IntRange> annotation, IntRange ignored, int value, 70 String paramName, long param) { 71 switch (paramName) { 72 case "from": 73 if (value < param) { 74 invalid(annotation, value, paramName, param); 75 } 76 break; 77 case "to": 78 if (value > param) { 79 invalid(annotation, value, paramName, param); 80 } 81 break; 82 } 83 } 84 85 /** 86 * Validate a long value with two parameters. 87 */ validate(Class<IntRange> annotation, IntRange ignored, long value, String paramName1, long param1, String paramName2, long param2)88 public static void validate(Class<IntRange> annotation, IntRange ignored, long value, 89 String paramName1, long param1, String paramName2, long param2) { 90 validate(annotation, ignored, value, paramName1, param1); 91 validate(annotation, ignored, value, paramName2, param2); 92 } 93 94 /** 95 * Validate a long value with one parameter. 96 */ validate(Class<IntRange> annotation, IntRange ignored, long value, String paramName, long param)97 public static void validate(Class<IntRange> annotation, IntRange ignored, long value, 98 String paramName, long param) { 99 switch (paramName) { 100 case "from": 101 if (value < param) { 102 invalid(annotation, value, paramName, param); 103 } 104 break; 105 case "to": 106 if (value > param) { 107 invalid(annotation, value, paramName, param); 108 } 109 break; 110 } 111 } 112 validate(Class<FloatRange> annotation, FloatRange ignored, float value, String paramName1, float param1, String paramName2, float param2)113 public static void validate(Class<FloatRange> annotation, FloatRange ignored, float value, 114 String paramName1, float param1, String paramName2, float param2) { 115 validate(annotation, ignored, value, paramName1, param1); 116 validate(annotation, ignored, value, paramName2, param2); 117 } 118 validate(Class<FloatRange> annotation, FloatRange ignored, float value, String paramName, float param)119 public static void validate(Class<FloatRange> annotation, FloatRange ignored, float value, 120 String paramName, float param) { 121 switch (paramName) { 122 case "from": if (value < param) invalid(annotation, value, paramName, param); break; 123 case "to": if (value > param) invalid(annotation, value, paramName, param); break; 124 } 125 } 126 validate(Class<NonNull> annotation, NonNull ignored, Object value)127 public static void validate(Class<NonNull> annotation, NonNull ignored, Object value) { 128 if (value == null) { 129 throw new NullPointerException(); 130 } 131 } 132 validate(Class<Size> annotation, Size ignored, int value, String paramName1, int param1, String paramName2, int param2)133 public static void validate(Class<Size> annotation, Size ignored, int value, 134 String paramName1, int param1, String paramName2, int param2) { 135 validate(annotation, ignored, value, paramName1, param1); 136 validate(annotation, ignored, value, paramName2, param2); 137 } 138 validate(Class<Size> annotation, Size ignored, int value, String paramName, int param)139 public static void validate(Class<Size> annotation, Size ignored, int value, 140 String paramName, int param) { 141 switch (paramName) { 142 case "value": { 143 if (param != -1 && value != param) invalid(annotation, value, paramName, param); 144 } break; 145 case "min": { 146 if (value < param) invalid(annotation, value, paramName, param); 147 } break; 148 case "max": { 149 if (value > param) invalid(annotation, value, paramName, param); 150 } break; 151 case "multiple": { 152 if (value % param != 0) invalid(annotation, value, paramName, param); 153 } break; 154 } 155 } 156 validate( Class<PermissionResult> annotation, PermissionResult ignored, int value)157 public static void validate( 158 Class<PermissionResult> annotation, PermissionResult ignored, int value) { 159 validateIntEnum(annotation, value, PackageManager.PERMISSION_GRANTED); 160 } 161 validate( Class<PackageInfoFlagsBits> annotation, PackageInfoFlagsBits ignored, long value)162 public static void validate( 163 Class<PackageInfoFlagsBits> annotation, PackageInfoFlagsBits ignored, long value) { 164 validateLongFlags(annotation, value, 165 flagsUpTo(PackageManager.MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS)); 166 } 167 validate( Class<Intent.Flags> annotation, Intent.Flags ignored, int value)168 public static void validate( 169 Class<Intent.Flags> annotation, Intent.Flags ignored, int value) { 170 validateIntFlags(annotation, value, flagsUpTo(Intent.FLAG_RECEIVER_OFFLOAD)); 171 } 172 173 174 @Deprecated validate(Class<? extends Annotation> annotation, Annotation ignored, Object value, Object... params)175 public static void validate(Class<? extends Annotation> annotation, 176 Annotation ignored, Object value, Object... params) {} 177 @Deprecated validate(Class<? extends Annotation> annotation, Annotation ignored, Object value)178 public static void validate(Class<? extends Annotation> annotation, 179 Annotation ignored, Object value) {} 180 @Deprecated validate(Class<? extends Annotation> annotation, Annotation ignored, int value, Object... params)181 public static void validate(Class<? extends Annotation> annotation, 182 Annotation ignored, int value, Object... params) {} validate(Class<? extends Annotation> annotation, Annotation ignored, int value)183 public static void validate(Class<? extends Annotation> annotation, 184 Annotation ignored, int value) { 185 if (("android.annotation".equals(annotation.getPackageName()) 186 && annotation.getSimpleName().endsWith("Res")) 187 || ColorInt.class.equals(annotation)) { 188 if (value < 0) { 189 invalid(annotation, value); 190 } 191 } 192 } validate(Class<? extends Annotation> annotation, Annotation ignored, long value)193 public static void validate(Class<? extends Annotation> annotation, 194 Annotation ignored, long value) { 195 if ("android.annotation".equals(annotation.getPackageName()) 196 && annotation.getSimpleName().endsWith("Long")) { 197 if (value < 0L) { 198 invalid(annotation, value); 199 } 200 } 201 } 202 validateIntEnum( Class<? extends Annotation> annotation, int value, int lastValid)203 private static void validateIntEnum( 204 Class<? extends Annotation> annotation, int value, int lastValid) { 205 if (value > lastValid) { 206 invalid(annotation, value); 207 } 208 } validateIntFlags( Class<? extends Annotation> annotation, int value, int validBits)209 private static void validateIntFlags( 210 Class<? extends Annotation> annotation, int value, int validBits) { 211 if ((validBits & value) != validBits) { 212 invalid(annotation, "0x" + Integer.toHexString(value)); 213 } 214 } validateLongFlags( Class<? extends Annotation> annotation, long value, int validBits)215 private static void validateLongFlags( 216 Class<? extends Annotation> annotation, long value, int validBits) { 217 if ((validBits & value) != validBits) { 218 invalid(annotation, "0x" + Long.toHexString(value)); 219 } 220 } invalid(Class<? extends Annotation> annotation, Object value)221 private static void invalid(Class<? extends Annotation> annotation, Object value) { 222 invalid("@" + annotation.getSimpleName(), value); 223 } 224 invalid(Class<? extends Annotation> annotation, Object value, String paramName, Object param)225 private static void invalid(Class<? extends Annotation> annotation, Object value, 226 String paramName, Object param) { 227 String paramPrefix = "value".equals(paramName) ? "" : paramName + " = "; 228 invalid("@" + annotation.getSimpleName() + "(" + paramPrefix + param + ")", value); 229 } 230 invalid(String valueKind, Object value)231 private static void invalid(String valueKind, Object value) { 232 throw new IllegalStateException("Invalid " + valueKind + ": " + value); 233 } 234 } 235