• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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