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 com.android.adservices.service.common; 18 19 import static android.adservices.common.AdServicesStatusUtils.STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_BLOCKLISTED; 20 import static android.adservices.common.AdServicesStatusUtils.STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_MATCH_NOT_FOUND; 21 import static android.adservices.common.AdServicesStatusUtils.STATUS_CALLER_NOT_ALLOWED_MANIFEST_ADSERVICES_CONFIG_NO_PERMISSION; 22 import static android.adservices.common.AdServicesStatusUtils.STATUS_PERMISSION_NOT_REQUESTED; 23 import static android.adservices.common.AdServicesStatusUtils.STATUS_UNAUTHORIZED; 24 25 import static com.android.adservices.service.common.AppManifestConfigCall.API_AD_SELECTION; 26 import static com.android.adservices.service.common.AppManifestConfigCall.API_CUSTOM_AUDIENCES; 27 import static com.android.adservices.service.common.AppManifestConfigCall.API_PROTECTED_SIGNALS; 28 29 import android.adservices.common.AdServicesStatusUtils; 30 import android.adservices.common.AdTechIdentifier; 31 import android.annotation.NonNull; 32 import android.content.Context; 33 import android.content.pm.PackageManager; 34 import android.net.Uri; 35 import android.os.Build; 36 import android.util.Pair; 37 38 import androidx.annotation.RequiresApi; 39 40 import com.android.adservices.LoggerFactory; 41 import com.android.adservices.data.enrollment.EnrollmentDao; 42 import com.android.adservices.service.FlagsFactory; 43 import com.android.adservices.service.enrollment.EnrollmentData; 44 import com.android.adservices.service.enrollment.EnrollmentStatus; 45 import com.android.adservices.service.enrollment.EnrollmentUtil; 46 import com.android.adservices.service.stats.AdServicesLogger; 47 import com.android.internal.annotations.VisibleForTesting; 48 49 import java.util.Collection; 50 import java.util.Locale; 51 import java.util.Objects; 52 53 /** Verify caller of FLEDGE API has the permission of performing certain behaviour. */ 54 @RequiresApi(Build.VERSION_CODES.S) 55 public class FledgeAuthorizationFilter { 56 57 @VisibleForTesting public static final String INVALID_API_TYPE = "Invalid apiType: %d"; 58 private static final LoggerFactory.Logger sLogger = LoggerFactory.getFledgeLogger(); 59 @NonNull private final PackageManager mPackageManager; 60 @NonNull private final EnrollmentDao mEnrollmentDao; 61 @NonNull private final AdServicesLogger mAdServicesLogger; 62 private EnrollmentUtil mEnrollmentUtil; 63 64 @VisibleForTesting FledgeAuthorizationFilter( @onNull PackageManager packageManager, @NonNull EnrollmentDao enrollmentDao, @NonNull AdServicesLogger adServicesLogger)65 public FledgeAuthorizationFilter( 66 @NonNull PackageManager packageManager, 67 @NonNull EnrollmentDao enrollmentDao, 68 @NonNull AdServicesLogger adServicesLogger) { 69 this(packageManager, enrollmentDao, adServicesLogger, null); 70 } 71 72 @VisibleForTesting FledgeAuthorizationFilter( @onNull PackageManager packageManager, @NonNull EnrollmentDao enrollmentDao, @NonNull AdServicesLogger adServicesLogger, EnrollmentUtil enrollmentUtil)73 public FledgeAuthorizationFilter( 74 @NonNull PackageManager packageManager, 75 @NonNull EnrollmentDao enrollmentDao, 76 @NonNull AdServicesLogger adServicesLogger, 77 EnrollmentUtil enrollmentUtil) { 78 Objects.requireNonNull(packageManager); 79 Objects.requireNonNull(enrollmentDao); 80 Objects.requireNonNull(adServicesLogger); 81 82 mPackageManager = packageManager; 83 mEnrollmentDao = enrollmentDao; 84 mAdServicesLogger = adServicesLogger; 85 mEnrollmentUtil = enrollmentUtil; 86 } 87 88 /** Creates an instance of {@link FledgeAuthorizationFilter}. */ create( @onNull Context context, @NonNull AdServicesLogger adServicesLogger)89 public static FledgeAuthorizationFilter create( 90 @NonNull Context context, @NonNull AdServicesLogger adServicesLogger) { 91 Objects.requireNonNull(context); 92 93 return new FledgeAuthorizationFilter( 94 context.getPackageManager(), 95 EnrollmentDao.getInstance(), 96 adServicesLogger, 97 EnrollmentUtil.getInstance()); 98 } 99 100 /** 101 * Check if the package name provided by the caller is one of the package of the calling uid. 102 * 103 * @param callingPackageName the caller-supplied package name 104 * @param callingUid the uid get from the Binder 105 * @param apiNameLoggingId the id of the api being called 106 * @throws CallerMismatchException if the package name provided does not associate with the uid. 107 */ assertCallingPackageName( @onNull String callingPackageName, int callingUid, int apiNameLoggingId)108 public void assertCallingPackageName( 109 @NonNull String callingPackageName, int callingUid, int apiNameLoggingId) 110 throws CallerMismatchException { 111 Objects.requireNonNull(callingPackageName); 112 113 sLogger.v( 114 "Asserting package name \"%s\" is valid for uid %d", 115 callingPackageName, callingUid); 116 117 String[] packageNamesForUid = mPackageManager.getPackagesForUid(callingUid); 118 for (String packageNameForUid : packageNamesForUid) { 119 sLogger.v("Candidate package name \"%s\"", packageNameForUid); 120 if (callingPackageName.equals(packageNameForUid)) return; 121 } 122 123 sLogger.v("No match found, failing calling package name match in API %d", apiNameLoggingId); 124 mAdServicesLogger.logFledgeApiCallStats( 125 apiNameLoggingId, callingPackageName, STATUS_UNAUTHORIZED, /*latencyMs=*/ 0); 126 throw new CallerMismatchException(); 127 } 128 129 /** 130 * Check if the app had declared a permission, and throw an error if it has not 131 * 132 * @param context api service context 133 * @param apiNameLoggingId the id of the api being called 134 * @throws SecurityException if the package did not declare custom audience permission 135 */ assertAppDeclaredPermission( @onNull Context context, @NonNull String appPackageName, int apiNameLoggingId, @NonNull String permission)136 public void assertAppDeclaredPermission( 137 @NonNull Context context, 138 @NonNull String appPackageName, 139 int apiNameLoggingId, 140 @NonNull String permission) 141 throws SecurityException { 142 Objects.requireNonNull(context); 143 Objects.requireNonNull(appPackageName); 144 Objects.requireNonNull(permission); 145 146 if (!PermissionHelper.hasPermission(context, appPackageName, permission)) { 147 logAndThrowPermissionFailure(appPackageName, apiNameLoggingId, permission); 148 } 149 } 150 151 /** 152 * Check if the app had declared any of the listed permissions, and throw an error if it has not 153 * 154 * @param context api service context 155 * @param appPackageName the package name of the calling app 156 * @param apiNameLoggingId the id of the api being called 157 * @param permissions lists of permissions that allow calling the API 158 * @throws SecurityException if the package did not declare custom audience permission 159 */ assertAppDeclaredAnyPermission( @onNull Context context, @NonNull String appPackageName, int apiNameLoggingId, @NonNull Collection<String> permissions)160 public void assertAppDeclaredAnyPermission( 161 @NonNull Context context, 162 @NonNull String appPackageName, 163 int apiNameLoggingId, 164 @NonNull Collection<String> permissions) 165 throws SecurityException { 166 Objects.requireNonNull(context); 167 Objects.requireNonNull(appPackageName); 168 Objects.requireNonNull(permissions); 169 170 for (String permission : permissions) { 171 if (PermissionHelper.hasPermission(context, appPackageName, permission)) { 172 return; // Found a valid permission 173 } 174 } 175 logAndThrowMultiplePermissionFailure(appPackageName, apiNameLoggingId, permissions); 176 } 177 logAndThrowPermissionFailure( String callerAppPackageName, int apiNameLoggingId, String permission)178 private void logAndThrowPermissionFailure( 179 String callerAppPackageName, int apiNameLoggingId, String permission) { 180 sLogger.v("Permission %s not declared by caller in API %d", permission, apiNameLoggingId); 181 mAdServicesLogger.logFledgeApiCallStats( 182 apiNameLoggingId, 183 callerAppPackageName, 184 STATUS_PERMISSION_NOT_REQUESTED, 185 /*latencyMs=*/ 0); 186 throw new SecurityException( 187 AdServicesStatusUtils.SECURITY_EXCEPTION_PERMISSION_NOT_REQUESTED_ERROR_MESSAGE); 188 } 189 logAndThrowMultiplePermissionFailure( String callerAppPackageName, int apiNameLoggingId, Collection<String> permissions)190 private void logAndThrowMultiplePermissionFailure( 191 String callerAppPackageName, int apiNameLoggingId, Collection<String> permissions) { 192 sLogger.v("Permissions %s not declared by caller in API %d", permissions, apiNameLoggingId); 193 mAdServicesLogger.logFledgeApiCallStats( 194 apiNameLoggingId, 195 callerAppPackageName, 196 STATUS_PERMISSION_NOT_REQUESTED, 197 /*latencyMs=*/ 0); 198 throw new SecurityException( 199 AdServicesStatusUtils.SECURITY_EXCEPTION_PERMISSION_NOT_REQUESTED_ERROR_MESSAGE); 200 } 201 202 /** 203 * Check if a certain ad tech is enrolled and authorized to perform the operation for the 204 * package. 205 * 206 * @param context api service context 207 * @param appPackageName the package name to check against 208 * @param adTechIdentifier the ad tech to check against 209 * @param apiNameLoggingId the id of the api being called 210 * @throws AdTechNotAllowedException if the ad tech is not authorized to perform the operation 211 */ assertAdTechAllowed( @onNull Context context, @NonNull String appPackageName, @NonNull AdTechIdentifier adTechIdentifier, int apiNameLoggingId, @AppManifestConfigCall.ApiType int apiType)212 public void assertAdTechAllowed( 213 @NonNull Context context, 214 @NonNull String appPackageName, 215 @NonNull AdTechIdentifier adTechIdentifier, 216 int apiNameLoggingId, 217 @AppManifestConfigCall.ApiType int apiType) 218 throws AdTechNotAllowedException { 219 Objects.requireNonNull(context); 220 Objects.requireNonNull(appPackageName); 221 Objects.requireNonNull(adTechIdentifier); 222 223 int buildId = -1; 224 int dataFileGroupStatus = 0; 225 if (mEnrollmentUtil != null) { 226 buildId = mEnrollmentUtil.getBuildId(); 227 dataFileGroupStatus = mEnrollmentUtil.getFileGroupStatus(); 228 } 229 int enrollmentRecordsCount = mEnrollmentDao.getEnrollmentRecordCountForLogging(); 230 EnrollmentData enrollmentData = getEnrollmentData(adTechIdentifier, apiType); 231 232 if (enrollmentData == null) { 233 sLogger.v( 234 "Enrollment data match not found for ad tech \"%s\" while calling API %d", 235 adTechIdentifier.toString(), apiNameLoggingId); 236 mAdServicesLogger.logFledgeApiCallStats( 237 apiNameLoggingId, 238 appPackageName, 239 STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_MATCH_NOT_FOUND, 240 /*latencyMs=*/ 0); 241 if (mEnrollmentUtil != null) { 242 mEnrollmentUtil.logEnrollmentFailedStats( 243 mAdServicesLogger, 244 buildId, 245 dataFileGroupStatus, 246 enrollmentRecordsCount, 247 adTechIdentifier.toString(), 248 EnrollmentStatus.ErrorCause.ENROLLMENT_NOT_FOUND_ERROR_CAUSE.getValue()); 249 } 250 throw new AdTechNotAllowedException(); 251 } 252 253 if (!isAllowedAccess(appPackageName, apiType, enrollmentData)) { 254 sLogger.v( 255 "App package name \"%s\" with ad tech identifier \"%s\" not authorized to call" 256 + " API %d", 257 appPackageName, adTechIdentifier.toString(), apiNameLoggingId); 258 mAdServicesLogger.logFledgeApiCallStats( 259 apiNameLoggingId, 260 appPackageName, 261 STATUS_CALLER_NOT_ALLOWED_MANIFEST_ADSERVICES_CONFIG_NO_PERMISSION, 262 /*latencyMs=*/ 0); 263 mEnrollmentUtil.logEnrollmentFailedStats( 264 mAdServicesLogger, 265 buildId, 266 dataFileGroupStatus, 267 enrollmentRecordsCount, 268 adTechIdentifier.toString(), 269 EnrollmentStatus.ErrorCause.UNKNOWN_ERROR_CAUSE.getValue()); 270 throw new AdTechNotAllowedException(); 271 } 272 273 // Check if enrollment is in blocklist. 274 if (FlagsFactory.getFlags().isEnrollmentBlocklisted(enrollmentData.getEnrollmentId())) { 275 sLogger.v( 276 "App package name \"%s\" with ad tech identifier \"%s\" not authorized to call" 277 + " API %d", 278 appPackageName, adTechIdentifier.toString(), apiNameLoggingId); 279 mAdServicesLogger.logFledgeApiCallStats( 280 apiNameLoggingId, 281 appPackageName, 282 STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_BLOCKLISTED, 283 /*latencyMs=*/ 0); 284 mEnrollmentUtil.logEnrollmentFailedStats( 285 mAdServicesLogger, 286 buildId, 287 dataFileGroupStatus, 288 enrollmentRecordsCount, 289 adTechIdentifier.toString(), 290 EnrollmentStatus.ErrorCause.ENROLLMENT_BLOCKLISTED_ERROR_CAUSE.getValue()); 291 throw new AdTechNotAllowedException(); 292 } 293 } 294 getEnrollmentData(AdTechIdentifier adTechIdentifier, int apiType)295 private EnrollmentData getEnrollmentData(AdTechIdentifier adTechIdentifier, int apiType) { 296 if (apiType == API_CUSTOM_AUDIENCES) { 297 return mEnrollmentDao.getEnrollmentDataForFledgeByAdTechIdentifier(adTechIdentifier); 298 } else if (apiType == API_PROTECTED_SIGNALS) { 299 return mEnrollmentDao.getEnrollmentDataForPASByAdTechIdentifier(adTechIdentifier); 300 } else if (apiType == API_AD_SELECTION) { 301 EnrollmentData caEnrollment = 302 mEnrollmentDao.getEnrollmentDataForFledgeByAdTechIdentifier(adTechIdentifier); 303 if (caEnrollment == null) { 304 return mEnrollmentDao.getEnrollmentDataForPASByAdTechIdentifier(adTechIdentifier); 305 } 306 return caEnrollment; 307 } else { 308 throw new IllegalStateException(String.format(INVALID_API_TYPE, apiType)); 309 } 310 } 311 getAdTechIdentifierEnrollmentDataPair( Uri uriForAdTech, int apiType)312 private Pair<AdTechIdentifier, EnrollmentData> getAdTechIdentifierEnrollmentDataPair( 313 Uri uriForAdTech, int apiType) { 314 if (apiType == API_CUSTOM_AUDIENCES) { 315 return mEnrollmentDao.getEnrollmentDataForFledgeByMatchingAdTechIdentifier( 316 uriForAdTech); 317 } else if (apiType == API_PROTECTED_SIGNALS) { 318 return mEnrollmentDao.getEnrollmentDataForPASByMatchingAdTechIdentifier(uriForAdTech); 319 } else if (apiType == API_AD_SELECTION) { 320 Pair<AdTechIdentifier, EnrollmentData> caEnrollment = 321 mEnrollmentDao.getEnrollmentDataForFledgeByMatchingAdTechIdentifier( 322 uriForAdTech); 323 if (caEnrollment == null) { 324 return mEnrollmentDao.getEnrollmentDataForPASByMatchingAdTechIdentifier( 325 uriForAdTech); 326 } 327 return caEnrollment; 328 } else { 329 throw new IllegalStateException( 330 String.format(Locale.ENGLISH, INVALID_API_TYPE, apiType)); 331 } 332 } 333 isAllowedAccess( String appPackageName, @AppManifestConfigCall.ApiType int apiType, EnrollmentData enrollmentData)334 private boolean isAllowedAccess( 335 String appPackageName, 336 @AppManifestConfigCall.ApiType int apiType, 337 EnrollmentData enrollmentData) { 338 if (apiType == API_CUSTOM_AUDIENCES) { 339 return AppManifestConfigHelper.isAllowedCustomAudiencesAccess( 340 appPackageName, enrollmentData.getEnrollmentId()); 341 } else if (apiType == API_PROTECTED_SIGNALS) { 342 return AppManifestConfigHelper.isAllowedProtectedSignalsAccess( 343 appPackageName, enrollmentData.getEnrollmentId()); 344 } else if (apiType == API_AD_SELECTION) { 345 return AppManifestConfigHelper.isAllowedAdSelectionAccess( 346 appPackageName, enrollmentData.getEnrollmentId()); 347 } else { 348 throw new IllegalStateException( 349 String.format(Locale.ENGLISH, INVALID_API_TYPE, apiType)); 350 } 351 } 352 353 /** 354 * Extract and return an {@link AdTechIdentifier} from the given {@link Uri} after checking if 355 * the ad tech is enrolled and authorized to perform the operation for the package. 356 * 357 * @param context API service context 358 * @param appPackageName the package name to check against 359 * @param uriForAdTech a {@link Uri} matching the ad tech to check against 360 * @param apiNameLoggingId the logging ID of the API being called 361 * @return an {@link AdTechIdentifier} which is allowed to perform the operation 362 * @throws AdTechNotAllowedException if the ad tech is not authorized to perform the operation 363 */ 364 @NonNull getAndAssertAdTechFromUriAllowed( @onNull Context context, @NonNull String appPackageName, @NonNull Uri uriForAdTech, int apiNameLoggingId, @AppManifestConfigCall.ApiType int apiType)365 public AdTechIdentifier getAndAssertAdTechFromUriAllowed( 366 @NonNull Context context, 367 @NonNull String appPackageName, 368 @NonNull Uri uriForAdTech, 369 int apiNameLoggingId, 370 @AppManifestConfigCall.ApiType int apiType) 371 throws AdTechNotAllowedException { 372 Objects.requireNonNull(context); 373 Objects.requireNonNull(appPackageName); 374 Objects.requireNonNull(uriForAdTech); 375 376 int buildId = -1; 377 int dataFileGroupStatus = 0; 378 if (mEnrollmentUtil != null) { 379 buildId = mEnrollmentUtil.getBuildId(); 380 dataFileGroupStatus = mEnrollmentUtil.getFileGroupStatus(); 381 } 382 int enrollmentRecordsCount = mEnrollmentDao.getEnrollmentRecordCountForLogging(); 383 Pair<AdTechIdentifier, EnrollmentData> enrollmentResult = 384 getAdTechIdentifierEnrollmentDataPair(uriForAdTech, apiType); 385 386 if (enrollmentResult == null) { 387 sLogger.v( 388 "Enrollment data match not found for URI \"%s\" while calling API %d", 389 uriForAdTech, apiNameLoggingId); 390 mAdServicesLogger.logFledgeApiCallStats( 391 apiNameLoggingId, 392 appPackageName, 393 STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_MATCH_NOT_FOUND, 394 /*latencyMs=*/ 0); 395 mEnrollmentUtil.logEnrollmentFailedStats( 396 mAdServicesLogger, 397 buildId, 398 dataFileGroupStatus, 399 enrollmentRecordsCount, 400 uriForAdTech.toString(), 401 EnrollmentStatus.ErrorCause.ENROLLMENT_NOT_FOUND_ERROR_CAUSE.getValue()); 402 throw new AdTechNotAllowedException(); 403 } 404 405 AdTechIdentifier adTechIdentifier = enrollmentResult.first; 406 EnrollmentData enrollmentData = enrollmentResult.second; 407 408 boolean isAllowedAccess = isAllowedAccess(appPackageName, apiType, enrollmentData); 409 410 boolean isEnrollmentBlocklisted = 411 FlagsFactory.getFlags().isEnrollmentBlocklisted(enrollmentData.getEnrollmentId()); 412 int errorCause = EnrollmentStatus.ErrorCause.UNKNOWN_ERROR_CAUSE.getValue(); 413 if (!isAllowedAccess || isEnrollmentBlocklisted) { 414 sLogger.v( 415 "App package name \"%s\" with ad tech identifier \"%s\" from URI \"%s\" not" 416 + " authorized to call API %d", 417 appPackageName, adTechIdentifier.toString(), uriForAdTech, apiNameLoggingId); 418 419 int resultCode; 420 if (!isAllowedAccess) { 421 resultCode = STATUS_CALLER_NOT_ALLOWED_MANIFEST_ADSERVICES_CONFIG_NO_PERMISSION; 422 } else { 423 resultCode = STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_BLOCKLISTED; 424 errorCause = 425 EnrollmentStatus.ErrorCause.ENROLLMENT_BLOCKLISTED_ERROR_CAUSE.getValue(); 426 } 427 mAdServicesLogger.logFledgeApiCallStats( 428 apiNameLoggingId, appPackageName, resultCode, /*latencyMs=*/ 0); 429 mEnrollmentUtil.logEnrollmentFailedStats( 430 mAdServicesLogger, 431 buildId, 432 dataFileGroupStatus, 433 enrollmentRecordsCount, 434 uriForAdTech.toString(), 435 errorCause); 436 throw new AdTechNotAllowedException(); 437 } 438 439 return adTechIdentifier; 440 } 441 442 /** 443 * Check if a certain ad tech is enrolled for FLEDGE. 444 * 445 * @param adTechIdentifier the ad tech to check against 446 * @param apiNameLoggingId the id of the api being called 447 * @throws AdTechNotAllowedException if the ad tech is not enrolled in FLEDGE 448 */ assertAdTechEnrolled( @onNull AdTechIdentifier adTechIdentifier, int apiNameLoggingId)449 public void assertAdTechEnrolled( 450 @NonNull AdTechIdentifier adTechIdentifier, int apiNameLoggingId) 451 throws AdTechNotAllowedException { 452 Objects.requireNonNull(adTechIdentifier); 453 454 EnrollmentData enrollmentData = 455 mEnrollmentDao.getEnrollmentDataForFledgeByAdTechIdentifier(adTechIdentifier); 456 457 if (enrollmentData == null) { 458 sLogger.v( 459 "Enrollment data match not found for ad tech \"%s\" while calling API %d", 460 adTechIdentifier.toString(), apiNameLoggingId); 461 mAdServicesLogger.logFledgeApiCallStats( 462 apiNameLoggingId, 463 STATUS_CALLER_NOT_ALLOWED_ENROLLMENT_MATCH_NOT_FOUND, 464 /*latencyMs=*/ 0); 465 466 int buildId = -1; 467 int dataFileGroupStatus = 0; 468 if (mEnrollmentUtil != null) { 469 buildId = mEnrollmentUtil.getBuildId(); 470 dataFileGroupStatus = mEnrollmentUtil.getFileGroupStatus(); 471 } 472 mEnrollmentUtil.logEnrollmentFailedStats( 473 mAdServicesLogger, 474 buildId, 475 dataFileGroupStatus, 476 mEnrollmentDao.getEnrollmentRecordCountForLogging(), 477 adTechIdentifier.toString(), 478 EnrollmentStatus.ErrorCause.ENROLLMENT_NOT_FOUND_ERROR_CAUSE.getValue()); 479 throw new AdTechNotAllowedException(); 480 } 481 } 482 483 /** 484 * Internal exception for easy assertion catches specific to checking that a caller matches the 485 * given package name. 486 * 487 * <p>This exception is not meant to be exposed externally and should not be passed outside of 488 * the service. 489 */ 490 public static class CallerMismatchException extends SecurityException { 491 /** 492 * Creates a {@link CallerMismatchException}, used in cases where a caller should match the 493 * package name provided to the API. 494 */ CallerMismatchException()495 public CallerMismatchException() { 496 super( 497 AdServicesStatusUtils 498 .SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ON_BEHALF_ERROR_MESSAGE); 499 } 500 } 501 502 /** 503 * Internal exception for easy assertion catches specific to checking that an ad tech is allowed 504 * to use the PP APIs. 505 * 506 * <p>This exception is not meant to be exposed externally and should not be passed outside of 507 * the service. 508 */ 509 public static class AdTechNotAllowedException extends SecurityException { 510 /** 511 * Creates a {@link AdTechNotAllowedException}, used in cases where an ad tech should have 512 * been allowed to use the PP APIs. 513 */ AdTechNotAllowedException()514 public AdTechNotAllowedException() { 515 super(AdServicesStatusUtils.SECURITY_EXCEPTION_CALLER_NOT_ALLOWED_ERROR_MESSAGE); 516 } 517 } 518 } 519