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