1 /* 2 * Copyright (C) 2022 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.adservices.common; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.os.LimitExceededException; 22 23 import com.android.adservices.shared.common.exception.ProviderServiceInternalException; 24 import com.android.adservices.shared.common.exception.ServiceUnavailableException; 25 26 import java.io.IOException; 27 import java.io.InvalidObjectException; 28 import java.lang.annotation.Retention; 29 import java.lang.annotation.RetentionPolicy; 30 import java.util.concurrent.TimeoutException; 31 32 /** 33 * Utility class containing status codes and functions used by various response objects. 34 * 35 * <p>Those status codes are internal only. 36 * 37 * @hide 38 */ 39 public final class AdServicesStatusUtils { 40 41 /** 42 * The status code has not been set. Keep unset status code the lowest value of the status 43 * codes. 44 */ 45 public static final int STATUS_UNSET = -1; 46 47 /** The call was successful. */ 48 public static final int STATUS_SUCCESS = 0; 49 50 /** 51 * An internal error occurred within the API, which the caller cannot address. 52 * 53 * <p>This error may be considered similar to {@link IllegalStateException}. 54 */ 55 public static final int STATUS_INTERNAL_ERROR = 1; 56 57 /** 58 * The caller supplied invalid arguments to the call. 59 * 60 * <p>This error may be considered similar to {@link IllegalArgumentException}. 61 */ 62 public static final int STATUS_INVALID_ARGUMENT = 2; 63 64 /** There was an unknown error. */ 65 public static final int STATUS_UNKNOWN_ERROR = 3; 66 67 /** 68 * There was an I/O error. 69 * 70 * <p>This error may be considered similar to {@link IOException}. 71 */ 72 public static final int STATUS_IO_ERROR = 4; 73 74 /** 75 * Result code for Rate Limit Reached. 76 * 77 * <p>This error may be considered similar to {@link LimitExceededException}. 78 */ 79 public static final int STATUS_RATE_LIMIT_REACHED = 5; 80 81 /** 82 * Killswitch was enabled. AdServices is not available. 83 * 84 * <p>This error may be considered similar to {@link IllegalStateException}. 85 */ 86 public static final int STATUS_KILLSWITCH_ENABLED = 6; 87 88 /** 89 * User consent was revoked. AdServices is not available. 90 * 91 * <p>This error may be considered similar to {@link IllegalStateException}. 92 */ 93 public static final int STATUS_USER_CONSENT_REVOKED = 7; 94 95 /** 96 * AdServices were disabled. AdServices is not available. 97 * 98 * <p>This error may be considered similar to {@link IllegalStateException}. 99 */ 100 public static final int STATUS_ADSERVICES_DISABLED = 8; 101 102 /** 103 * The caller is not authorized to make this call. Permission was not requested. 104 * 105 * <p>This error may be considered similar to {@link SecurityException}. 106 */ 107 public static final int STATUS_PERMISSION_NOT_REQUESTED = 9; 108 109 /** 110 * The caller is not authorized to make this call. Caller is not allowed (not present in the 111 * allowed list). 112 * 113 * <p>This error may be considered similar to {@link SecurityException}. 114 */ 115 public static final int STATUS_CALLER_NOT_ALLOWED = 10; 116 117 /** 118 * The caller is not authorized to make this call. Call was executed from background thread. 119 * 120 * <p>This error may be considered similar to {@link IllegalStateException}. 121 */ 122 public static final int STATUS_BACKGROUND_CALLER = 11; 123 124 /** 125 * The caller is not authorized to make this call. 126 * 127 * <p>This error may be considered similar to {@link SecurityException}. 128 */ 129 public static final int STATUS_UNAUTHORIZED = 12; 130 131 /** 132 * There was an internal Timeout within the API, which is non-recoverable by the caller 133 * 134 * <p>This error may be considered similar to {@link java.util.concurrent.TimeoutException} 135 */ 136 public static final int STATUS_TIMEOUT = 13; 137 138 /** 139 * The device is not running a version of WebView that supports JSSandbox, required for FLEDGE 140 * Ad Selection. 141 * 142 * <p>This error may be considered similar to {@link IllegalStateException}. 143 */ 144 public static final int STATUS_JS_SANDBOX_UNAVAILABLE = 14; 145 146 /** 147 * The service received an invalid object from the remote server. 148 * 149 * <p>This error may be considered similar to {@link InvalidObjectException}. 150 */ 151 public static final int STATUS_INVALID_OBJECT = 15; 152 153 /** 154 * The caller is not authorized to make this call because it crosses user boundaries. 155 * 156 * <p>This error may be considered similar to {@link SecurityException}. 157 */ 158 public static final int STATUS_CALLER_NOT_ALLOWED_TO_CROSS_USER_BOUNDARIES = 16; 159 160 /** 161 * Result code for Server Rate Limit Reached. 162 * 163 * <p>This error may be considered similar to {@link LimitExceededException}. 164 */ 165 public static final int STATUS_SERVER_RATE_LIMIT_REACHED = 17; 166 167 /** 168 * Consent notification has not been displayed yet. AdServices is not available. 169 * 170 * <p>This error may be considered similar to {@link IllegalStateException}. 171 */ 172 public static final int STATUS_USER_CONSENT_NOTIFICATION_NOT_DISPLAYED_YET = 18; 173 174 /** 175 * Result code for Encryption related failures. 176 * 177 * <p>This error may be considered similar to {@link IllegalArgumentException}. 178 */ 179 public static final int STATUS_ENCRYPTION_FAILURE = 19; 180 181 /** 182 * The caller is not authorized to make this call because the package is not in the allowlist. 183 * 184 * <p>This error may be considered similar to {@link SecurityException}. 185 */ 186 public static final int STATUS_CALLER_NOT_ALLOWED_PACKAGE_NOT_IN_ALLOWLIST = 20; 187 188 /** 189 * The caller is not authorized to make this call because the package is not in the allowlist. 190 * 191 * <p>This error may be considered similar to {@link SecurityException}. 192 */ 193 public static final int STATUS_CALLER_NOT_ALLOWED_PACKAGE_BLOCKLISTED = 21; 194 195 /** 196 * The caller is not authorized to make this call because enrollment data can't be found. 197 * 198 * <p>This error may be considered similar to {@link SecurityException}. 199 */ 200 public static final int STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_MATCH_NOT_FOUND = 22; 201 202 /** 203 * The caller is not authorized to make this call because enrollment ID is invalid. 204 * 205 * <p>This error may be considered similar to {@link SecurityException}. 206 */ 207 public static final int STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_INVALID_ID = 23; 208 209 /** 210 * The caller is not authorized to make this call because enrollment ID is in the blocklist. 211 * 212 * <p>This error may be considered similar to {@link SecurityException}. 213 */ 214 public static final int STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_BLOCKLISTED = 24; 215 216 /** 217 * The caller is not authorized to make this call because permission was not requested in the 218 * manifest. 219 * 220 * <p>This error may be considered similar to {@link SecurityException}. 221 */ 222 public static final int STATUS_CALLER_NOT_ALLOWED_MANIFEST_ADSERVICES_CONFIG_NO_PERMISSION = 25; 223 224 /** 225 * AdServices activity is disabled. 226 * 227 * <p>This error may be considered similar to {@link IllegalStateException}. 228 */ 229 public static final int STATUS_ADSERVICES_ACTIVITY_DISABLED = 26; 230 231 /** 232 * Callback is shut down and encountered an error when invoking its methods. 233 * 234 * <p>This error may be considered similar to {@link IllegalStateException}. 235 */ 236 public static final int STATUS_CALLBACK_SHUTDOWN = 27; 237 238 /** 239 * The provider service throws an error as the callback when AdServices tries to call it. 240 * 241 * <p>This error may be considered similar to {@link IllegalStateException}. 242 */ 243 public static final int STATUS_PROVIDER_SERVICE_INTERNAL_ERROR = 28; 244 245 /** 246 * The scheduleCustomAudienceUpdate() request failed because an existing update has not been 247 * executed yet and should be explicitly replaced by the caller. 248 * 249 * <p>This error throws an {@link IllegalStateException}. 250 */ 251 public static final int STATUS_UPDATE_ALREADY_PENDING_ERROR = 29; 252 253 /** The error message to be returned along with {@link LimitExceededException}. */ 254 public static final String RATE_LIMIT_REACHED_ERROR_MESSAGE = "API rate limit exceeded."; 255 256 /** The error message to be returned along with {@link LimitExceededException}. */ 257 public static final String SERVER_RATE_LIMIT_REACHED_ERROR_MESSAGE = 258 "Server rate limit exceeded."; 259 260 /** 261 * The error message to be returned along with {@link SecurityException} when permission was not 262 * requested in the manifest. 263 */ 264 public static final String SECURITY_EXCEPTION_PERMISSION_NOT_REQUESTED_ERROR_MESSAGE = 265 "Caller is not authorized to call this API. Permission was not requested."; 266 267 /** 268 * The error message to be returned along with {@link SecurityException} when caller is not 269 * allowed to call AdServices (not present in the allowed list). 270 */ 271 public static final String SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE = 272 "Caller is not authorized to call this API. Caller is not allowed."; 273 274 /** 275 * The error message to be returned along with {@link SecurityException} when call was executed 276 * from the background thread. 277 */ 278 public static final String ILLEGAL_STATE_BACKGROUND_CALLER_ERROR_MESSAGE = 279 "Background thread is not allowed to call this service."; 280 281 /** 282 * The error message to be returned along with {@link IllegalStateException} when call failed 283 * because AdServices activity is disabled. 284 */ 285 public static final String ILLEGAL_STATE_ACTIVITY_DISABLED_ERROR_MESSAGE = 286 "AdServices activity is disabled."; 287 288 /** 289 * The error message to be returned along with {@link SecurityException} when call failed 290 * because it crosses user boundaries. 291 */ 292 public static final String SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_TO_CROSS_USER_BOUNDARIES = 293 "Caller is not authorized to access information from another user"; 294 295 /** 296 * The error message to be returned along with {@link SecurityException} when caller not allowed 297 * to perform this operation on behalf of the given package. 298 */ 299 public static final String SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ON_BEHALF_ERROR_MESSAGE = 300 "Caller is not allowed to perform this operation on behalf of the given package."; 301 302 /** The error message to be returned along with {@link TimeoutException}. */ 303 public static final String TIMED_OUT_ERROR_MESSAGE = "API timed out."; 304 305 /** The error message to be returned along with {@link InvalidObjectException}. */ 306 public static final String INVALID_OBJECT_ERROR_MESSAGE = 307 "The service received an invalid object from the server."; 308 309 /** The error message to be returned along with {@link IllegalArgumentException}. */ 310 public static final String ENCRYPTION_FAILURE_MESSAGE = "Failed to encrypt responses."; 311 312 /** The error message to be returned along with {@link ServiceUnavailableException}. */ 313 public static final String SERVICE_UNAVAILABLE_ERROR_MESSAGE = "Service is not available."; 314 315 /** 316 * The error message returned when a call to schedule a custom audience update fails because of 317 * an existing pending update. 318 */ 319 public static final String UPDATE_ALREADY_PENDING_ERROR_MESSAGE = 320 "Failed to schedule update. A request is already pending."; 321 322 /** Returns true for a successful status. */ isSuccess(@tatusCode int statusCode)323 public static boolean isSuccess(@StatusCode int statusCode) { 324 return statusCode == STATUS_SUCCESS; 325 } 326 327 /** Converts the input {@code statusCode} to an exception to be used in the callback. */ 328 @NonNull asException(@tatusCode int statusCode)329 public static Exception asException(@StatusCode int statusCode) { 330 switch (statusCode) { 331 case STATUS_ENCRYPTION_FAILURE: 332 return new IllegalArgumentException(ENCRYPTION_FAILURE_MESSAGE); 333 case STATUS_INVALID_ARGUMENT: 334 return new IllegalArgumentException(); 335 case STATUS_IO_ERROR: 336 return new IOException(); 337 case STATUS_KILLSWITCH_ENABLED: // Intentional fallthrough 338 case STATUS_USER_CONSENT_NOTIFICATION_NOT_DISPLAYED_YET: // Intentional fallthrough 339 case STATUS_USER_CONSENT_REVOKED: // Intentional fallthrough 340 case STATUS_JS_SANDBOX_UNAVAILABLE: 341 return new ServiceUnavailableException(SERVICE_UNAVAILABLE_ERROR_MESSAGE); 342 case STATUS_PERMISSION_NOT_REQUESTED: 343 return new SecurityException( 344 SECURITY_EXCEPTION_PERMISSION_NOT_REQUESTED_ERROR_MESSAGE); 345 case STATUS_CALLER_NOT_ALLOWED: 346 return new SecurityException(SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE); 347 case STATUS_CALLER_NOT_ALLOWED_PACKAGE_NOT_IN_ALLOWLIST: 348 return new SecurityException(SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE); 349 case STATUS_CALLER_NOT_ALLOWED_PACKAGE_BLOCKLISTED: 350 return new SecurityException(SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE); 351 case STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_MATCH_NOT_FOUND: 352 return new SecurityException(SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE); 353 case STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_INVALID_ID: 354 return new SecurityException(SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE); 355 case STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_BLOCKLISTED: 356 return new SecurityException(SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE); 357 case STATUS_CALLER_NOT_ALLOWED_MANIFEST_ADSERVICES_CONFIG_NO_PERMISSION: 358 return new SecurityException(SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE); 359 case STATUS_BACKGROUND_CALLER: 360 return new IllegalStateException(ILLEGAL_STATE_BACKGROUND_CALLER_ERROR_MESSAGE); 361 case STATUS_ADSERVICES_ACTIVITY_DISABLED: 362 return new IllegalStateException(ILLEGAL_STATE_ACTIVITY_DISABLED_ERROR_MESSAGE); 363 case STATUS_UPDATE_ALREADY_PENDING_ERROR: 364 return new IllegalStateException(UPDATE_ALREADY_PENDING_ERROR_MESSAGE); 365 case STATUS_UNAUTHORIZED: 366 return new SecurityException( 367 SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ON_BEHALF_ERROR_MESSAGE); 368 case STATUS_TIMEOUT: 369 return new TimeoutException(TIMED_OUT_ERROR_MESSAGE); 370 case STATUS_RATE_LIMIT_REACHED: 371 return new LimitExceededException(RATE_LIMIT_REACHED_ERROR_MESSAGE); 372 case STATUS_INVALID_OBJECT: 373 return new InvalidObjectException(INVALID_OBJECT_ERROR_MESSAGE); 374 case STATUS_SERVER_RATE_LIMIT_REACHED: 375 return new LimitExceededException(SERVER_RATE_LIMIT_REACHED_ERROR_MESSAGE); 376 case STATUS_PROVIDER_SERVICE_INTERNAL_ERROR: 377 return new ProviderServiceInternalException(); 378 default: 379 return new IllegalStateException(); 380 } 381 } 382 383 /** Converts the {@link AdServicesResponse} to an exception to be used in the callback. */ 384 // TODO(b/328601595): Add unit test for AdServicesStatusUtils.asException 385 @NonNull asException(@onNull AdServicesResponse adServicesResponse)386 public static Exception asException(@NonNull AdServicesResponse adServicesResponse) { 387 return asException(adServicesResponse.getStatusCode()); 388 } 389 390 /** 391 * Result codes that are common across various APIs. 392 * 393 * @hide 394 */ 395 @IntDef( 396 prefix = {"STATUS_"}, 397 value = { 398 STATUS_UNSET, 399 STATUS_SUCCESS, 400 STATUS_INTERNAL_ERROR, 401 STATUS_INVALID_ARGUMENT, 402 STATUS_RATE_LIMIT_REACHED, 403 STATUS_UNKNOWN_ERROR, 404 STATUS_IO_ERROR, 405 STATUS_KILLSWITCH_ENABLED, 406 STATUS_USER_CONSENT_REVOKED, 407 STATUS_ADSERVICES_DISABLED, 408 STATUS_ADSERVICES_ACTIVITY_DISABLED, 409 STATUS_PERMISSION_NOT_REQUESTED, 410 STATUS_CALLER_NOT_ALLOWED, 411 STATUS_BACKGROUND_CALLER, 412 STATUS_UNAUTHORIZED, 413 STATUS_TIMEOUT, 414 STATUS_JS_SANDBOX_UNAVAILABLE, 415 STATUS_INVALID_OBJECT, 416 STATUS_SERVER_RATE_LIMIT_REACHED, 417 STATUS_USER_CONSENT_NOTIFICATION_NOT_DISPLAYED_YET, 418 STATUS_ENCRYPTION_FAILURE, 419 STATUS_CALLER_NOT_ALLOWED_PACKAGE_NOT_IN_ALLOWLIST, 420 STATUS_CALLER_NOT_ALLOWED_PACKAGE_BLOCKLISTED, 421 STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_MATCH_NOT_FOUND, 422 STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_INVALID_ID, 423 STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_BLOCKLISTED, 424 STATUS_CALLER_NOT_ALLOWED_MANIFEST_ADSERVICES_CONFIG_NO_PERMISSION, 425 STATUS_CALLBACK_SHUTDOWN, 426 STATUS_PROVIDER_SERVICE_INTERNAL_ERROR, 427 STATUS_UPDATE_ALREADY_PENDING_ERROR, 428 }) 429 @Retention(RetentionPolicy.SOURCE) 430 public @interface StatusCode {} 431 AdServicesStatusUtils()432 private AdServicesStatusUtils() { 433 throw new UnsupportedOperationException(); 434 } 435 } 436