1 /*
2  * Copyright (C) 2018 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.content;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.app.AppOpsManager;
22 import android.os.Binder;
23 import android.os.Process;
24 import android.permission.IPermissionChecker;
25 import android.permission.PermissionCheckerManager;
26 import android.permission.PermissionCheckerManager.PermissionResult;
27 
28 /**
29  * This class provides permission check APIs that verify both the
30  * permission and the associated app op for this permission if
31  * such is defined.
32  * <p>
33  * In the new permission model permissions with protection level
34  * dangerous are runtime permissions. For apps targeting {@link android.os.Build.VERSION_CODES#M}
35  * and above the user may not grant such permissions or revoke
36  * them at any time. For apps targeting API lower than {@link android.os.Build.VERSION_CODES#M}
37  * these permissions are always granted as such apps do not expect
38  * permission revocations and would crash. Therefore, when the
39  * user disables a permission for a legacy app in the UI the
40  * platform disables the APIs guarded by this permission making
41  * them a no-op which is doing nothing or returning an empty
42  * result or default error.
43  * </p>
44  * <p>
45  * It is important that when you perform an operation on behalf of
46  * another app you use these APIs to check for permissions as the
47  * app may be a legacy app that does not participate in the new
48  * permission model for which the user had disabled the "permission"
49  * which is achieved by disallowing the corresponding app op.
50  * </p>
51  * <p>
52  * This class has two types of methods and you should be careful which
53  * type to call based on whether permission protected data is being
54  * passed to the app or you are just checking whether the app holds a
55  * permission. The reason is that a permission check requires checking
56  * the runtime permission and if it is granted checking the corresponding
57  * app op as for apps not supporting the runtime mode we never revoke
58  * permissions but disable app ops. Since there are two types of app op
59  * checks, one that does not leave a record an action was performed and
60  * another the does, one needs to call the preflight flavor of the checks
61  * named xxxForPreflight only if no private data is being delivered but
62  * a permission check is what is needed and the xxxForDataDelivery where
63  * the permission check is right before private data delivery.
64  *
65  * @hide
66  */
67 public final class PermissionChecker {
68     /**
69      * The permission is granted.
70      *
71      * @hide
72      */
73     public static final int PERMISSION_GRANTED = PermissionCheckerManager.PERMISSION_GRANTED;
74 
75     /**
76      * The permission is denied. Applicable only to runtime permissions.
77      *
78      * <p>Returned when:
79      * <ul>
80      *   <li>the runtime permission is granted, but the corresponding app op is denied
81      *       for runtime permissions.</li>
82      * </ul>
83      *
84      * @hide
85      */
86     public static final int PERMISSION_SOFT_DENIED =
87             PermissionCheckerManager.PERMISSION_SOFT_DENIED;
88 
89     /**
90      * The permission is denied.
91      *
92      * <p>Returned when:
93      * <ul>
94      *   <li>the permission is denied for non app op permissions.</li>
95      *   <li>the app op is denied or app op is {@link AppOpsManager#MODE_DEFAULT}
96      *   and permission is denied.</li>
97      * </ul>
98      *
99      * @hide
100      */
101     public static final int PERMISSION_HARD_DENIED =
102             PermissionCheckerManager.PERMISSION_HARD_DENIED;
103 
104     /** Constant when the PID for which we check permissions is unknown. */
105     public static final int PID_UNKNOWN = -1;
106 
107     private static volatile IPermissionChecker sService;
108 
PermissionChecker()109     private PermissionChecker() {
110         /* do nothing */
111     }
112 
113     /**
114      * Checks whether a given package in a UID and PID has a given permission
115      * and whether the app op that corresponds to this permission is allowed.
116      *
117      * <strong>NOTE:</strong> Use this method only for permission checks at the
118      * point where you will deliver the permission protected data to clients.
119      *
120      * <p>For example, if an app registers a location listener it should have the location
121      * permission but no data is actually sent to the app at the moment of registration
122      * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
123      * to determine if the app has or may have location permission (if app has only foreground
124      * location the grant state depends on the app's fg/gb state) and this check will not
125      * leave a trace that permission protected data was delivered. When you are about to
126      * deliver the location data to a registered listener you should use this method which
127      * will evaluate the permission access based on the current fg/bg state of the app and
128      * leave a record that the data was accessed.
129      *
130      * <p>For more details how to determine the {@code packageName}, {@code attributionTag}, and
131      * {@code message}, please check the description in
132      * {@link AppOpsManager#noteOp(String, int, String, String, String)}
133      *
134      * @param context Context for accessing resources.
135      * @param permission The permission to check.
136      * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
137      *    is not known.
138      * @param uid The uid for which to check.
139      * @param packageName The package name for which to check. If null the
140      *     the first package for the calling UID will be used.
141      * @param attributionTag attribution tag
142      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
143      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
144      * @param message A message describing the reason the permission was checked
145      * @param startDataDelivery Whether this is the start of data delivery.
146      *
147      * @see #checkPermissionForPreflight(Context, String, int, int, String)
148      */
149     @PermissionCheckerManager.PermissionResult
checkPermissionForDataDelivery(@onNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName, @Nullable String attributionTag, @Nullable String message, boolean startDataDelivery)150     public static int checkPermissionForDataDelivery(@NonNull Context context,
151             @NonNull String permission, int pid, int uid, @Nullable String packageName,
152             @Nullable String attributionTag, @Nullable String message, boolean startDataDelivery) {
153         return checkPermissionForDataDelivery(context, permission, pid, new AttributionSource(uid,
154                 pid, packageName, attributionTag), message, startDataDelivery);
155     }
156 
157     /**
158      * Checks whether a given package in a UID and PID has a given permission
159      * and whether the app op that corresponds to this permission is allowed.
160      *
161      * <strong>NOTE:</strong> Use this method only for permission checks at the
162      * point where you will deliver the permission protected data to clients.
163      *
164      * <p>For example, if an app registers a location listener it should have the location
165      * permission but no data is actually sent to the app at the moment of registration
166      * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
167      * to determine if the app has or may have location permission (if app has only foreground
168      * location the grant state depends on the app's fg/gb state) and this check will not
169      * leave a trace that permission protected data was delivered. When you are about to
170      * deliver the location data to a registered listener you should use this method which
171      * will evaluate the permission access based on the current fg/bg state of the app and
172      * leave a record that the data was accessed.
173      *
174      * <p>For more details how to determine the {@code packageName}, {@code attributionTag}, and
175      * {@code message}, please check the description in
176      * {@link AppOpsManager#noteOp(String, int, String, String, String)}
177      *
178      * @param context Context for accessing resources.
179      * @param permission The permission to check.
180      * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
181      *    is not known.
182      * @param uid The uid for which to check.
183      * @param packageName The package name for which to check. If null the
184      *     the first package for the calling UID will be used.
185      * @param attributionTag attribution tag
186      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
187      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
188      * @param message A message describing the reason the permission was checked
189      *
190      * @see #checkPermissionForPreflight(Context, String, int, int, String)
191      */
192     @PermissionResult
checkPermissionForDataDelivery(@onNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName, @Nullable String attributionTag, @Nullable String message)193     public static int checkPermissionForDataDelivery(@NonNull Context context,
194             @NonNull String permission, int pid, int uid, @Nullable String packageName,
195             @Nullable String attributionTag, @Nullable String message) {
196         return checkPermissionForDataDelivery(context, permission, pid, uid,
197                 packageName, attributionTag, message, false /*startDataDelivery*/);
198     }
199 
200     /**
201      * Checks whether a given data access chain described by the given {@link AttributionSource}
202      * has a given permission and whether the app op that corresponds to this permission
203      * is allowed. Call this method if you are the datasource which would not blame you for
204      * access to the data since you are the data.
205      *
206      * <strong>NOTE:</strong> Use this method only for permission checks at the
207      * point where you will deliver the permission protected data to clients.
208      *
209      * <p>For example, if an app registers a location listener it should have the location
210      * permission but no data is actually sent to the app at the moment of registration
211      * and you should use {@link #checkPermissionForPreflight(Context, String, int, int, String)}
212      * to determine if the app has or may have location permission (if app has only foreground
213      * location the grant state depends on the app's fg/gb state) and this check will not
214      * leave a trace that permission protected data was delivered. When you are about to
215      * deliver the location data to a registered listener you should use this method which
216      * will evaluate the permission access based on the current fg/bg state of the app and
217      * leave a record that the data was accessed.
218      *
219      * @param context Context for accessing resources.
220      * @param permission The permission to check.
221      * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
222      *    is not known.
223      * @param attributionSource the permission identity
224      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
225      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
226      * @param message A message describing the reason the permission was checked
227      *
228      * @see #checkPermissionForPreflight(Context, String, AttributionSource)
229      */
230     @PermissionResult
checkPermissionForDataDeliveryFromDataSource(@onNull Context context, @NonNull String permission, int pid, @NonNull AttributionSource attributionSource, @Nullable String message)231     public static int checkPermissionForDataDeliveryFromDataSource(@NonNull Context context,
232             @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
233             @Nullable String message) {
234         return checkPermissionForDataDeliveryCommon(context, permission, attributionSource,
235                 message, false /*startDataDelivery*/, /*fromDatasource*/ true);
236     }
237 
238     /**
239      * Checks whether a given data access chain described by the given {@link AttributionSource}
240      * has a given permission and whether the app op that corresponds to this permission
241      * is allowed.
242      *
243      * <strong>NOTE:</strong> Use this method only for permission checks at the
244      * point where you will deliver the permission protected data to clients.
245      *
246      * <p>For example, if an app registers a location listener it should have the location
247      * permission but no data is actually sent to the app at the moment of registration
248      * and you should use {@link #checkPermissionForPreflight(Context, String, AttributionSource)}
249      * to determine if the app has or may have location permission (if app has only foreground
250      * location the grant state depends on the app's fg/gb state) and this check will not
251      * leave a trace that permission protected data was delivered. When you are about to
252      * deliver the location data to a registered listener you should use this method which
253      * will evaluate the permission access based on the current fg/bg state of the app and
254      * leave a record that the data was accessed.
255      *
256      * @param context Context for accessing resources.
257      * @param permission The permission to check.
258      * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
259      *    is not known.
260      * @param attributionSource the permission identity
261      * @param message A message describing the reason the permission was checked
262      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
263      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
264      *
265      * @see #checkPermissionForPreflight(Context, String, AttributionSource)
266      */
267     @PermissionResult
checkPermissionForDataDelivery(@onNull Context context, @NonNull String permission, int pid, @NonNull AttributionSource attributionSource, @Nullable String message)268     public static int checkPermissionForDataDelivery(@NonNull Context context,
269             @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
270             @Nullable String message) {
271         return checkPermissionForDataDelivery(context, permission, pid, attributionSource,
272                 message, false /*startDataDelivery*/);
273     }
274 
275     /**
276      * Checks whether a given data access chain described by the given {@link AttributionSource}
277      * has a given permission and whether the app op that corresponds to this permission
278      * is allowed.
279      *
280      * <strong>NOTE:</strong> Use this method only for permission checks at the
281      * point where you will deliver the permission protected data to clients.
282      *
283      * <p>For example, if an app registers a data listener it should have the required
284      * permission but no data is actually sent to the app at the moment of registration
285      * and you should use {@link #checkPermissionForPreflight(Context, String,
286      * AttributionSource)}
287      * to determine if the app has or may have permission and this check will not
288      * leave a trace that permission protected data was delivered. When you are about to
289      * deliver the data to a registered listener you should use this method which
290      * will evaluate the permission access based on the current fg/bg state of the app and
291      * leave a record that the data was accessed.
292      *
293      * @param context Context for accessing resources.
294      * @param permission The permission to check.
295      * @param pid The process id for which to check. Use {@link #PID_UNKNOWN} if the PID
296      *    is not known.
297      * @param attributionSource The identity for which to check the permission.
298      * @param message A message describing the reason the permission was checked
299      * @param startDataDelivery Whether this is the start of data delivery.
300      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
301      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
302      *
303      * @see #checkPermissionForPreflight(Context, String, AttributionSource)
304      */
305     @PermissionResult
checkPermissionForDataDelivery(@onNull Context context, @NonNull String permission, int pid, @NonNull AttributionSource attributionSource, @Nullable String message, boolean startDataDelivery)306     public static int checkPermissionForDataDelivery(@NonNull Context context,
307             @NonNull String permission, int pid, @NonNull AttributionSource attributionSource,
308             @Nullable String message, boolean startDataDelivery) {
309         return checkPermissionForDataDeliveryCommon(context, permission, attributionSource,
310                 message, startDataDelivery, /*fromDatasource*/ false);
311     }
312 
313     @SuppressWarnings("ConstantConditions")
checkPermissionForDataDeliveryCommon(@onNull Context context, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message, boolean startDataDelivery, boolean fromDatasource)314     private static int checkPermissionForDataDeliveryCommon(@NonNull Context context,
315             @NonNull String permission, @NonNull AttributionSource attributionSource,
316             @Nullable String message, boolean startDataDelivery, boolean fromDatasource) {
317         return context.getSystemService(PermissionCheckerManager.class).checkPermission(permission,
318                 attributionSource.asState(), message, true /*forDataDelivery*/, startDataDelivery,
319                 fromDatasource, AppOpsManager.OP_NONE);
320     }
321 
322     /**
323      * Checks whether a given data access chain described by the given {@link AttributionSource}
324      * has a given permission and whether the app op that corresponds to this permission
325      * is allowed. The app ops area also marked as started. This is useful for long running
326      * permissions like camera.
327      *
328      * <strong>NOTE:</strong> Use this method only for permission checks at the
329      * point where you will deliver the permission protected data to clients.
330      *
331      * <p>For example, if an app registers a data listener it should have the required
332      * permission but no data is actually sent to the app at the moment of registration
333      * and you should use {@link #checkPermissionForPreflight(Context, String,
334      * AttributionSource)}
335      * to determine if the app has or may have permission and this check will not
336      * leave a trace that permission protected data was delivered. When you are about to
337      * deliver the data to a registered listener you should use this method which
338      * will evaluate the permission access based on the current fg/bg state of the app and
339      * leave a record that the data was accessed.
340      *
341      * @param context Context for accessing resources.
342      * @param permission The permission to check.
343      * @param attributionSource The identity for which to check the permission.
344      * @param message A message describing the reason the permission was checked
345      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
346      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
347      *
348      * @see #checkPermissionForPreflight(Context, String, AttributionSource)
349      */
350     @PermissionResult
351     @SuppressWarnings("ConstantConditions")
checkPermissionAndStartDataDelivery(@onNull Context context, @NonNull String permission, @NonNull AttributionSource attributionSource, @Nullable String message)352     public static int checkPermissionAndStartDataDelivery(@NonNull Context context,
353             @NonNull String permission, @NonNull AttributionSource attributionSource,
354             @Nullable String message) {
355         return context.getSystemService(PermissionCheckerManager.class).checkPermission(
356                 permission, attributionSource.asState(), message, true /*forDataDelivery*/,
357                 /*startDataDelivery*/ true, /*fromDatasource*/ false, AppOpsManager.OP_NONE);
358     }
359 
360     /**
361      * Checks whether a given data access chain described by the given {@link
362      * AttributionSource} has a given app op allowed and marks the op as started.
363      *
364      * <strong>NOTE:</strong> Use this method only for app op checks at the
365      * point where you will deliver the protected data to clients.
366      *
367      * <p>For example, if an app registers a data listener it should have the data
368      * op but no data is actually sent to the app at the moment of registration
369      * and you should use {@link #checkOpForPreflight(Context, String, AttributionSource, String)}
370      * to determine if the app has or may have op access and this check will not
371      * leave a trace that op protected data was delivered. When you are about to
372      * deliver the data to a registered listener you should use this method which
373      * will evaluate the op access based on the current fg/bg state of the app and
374      * leave a record that the data was accessed.
375      *
376      * @param context Context for accessing resources.
377      * @param opName THe op to start.
378      * @param attributionSource The identity for which to check the permission.
379      * @param message A message describing the reason the permission was checked
380      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
381      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
382      *
383      * @see #finishDataDelivery(Context, String, AttributionSource)
384      */
385     @PermissionResult
386     @SuppressWarnings("ConstantConditions")
startOpForDataDelivery(@onNull Context context, @NonNull String opName, @NonNull AttributionSource attributionSource, @Nullable String message)387     public static int startOpForDataDelivery(@NonNull Context context,
388             @NonNull String opName, @NonNull AttributionSource attributionSource,
389             @Nullable String message) {
390         return context.getSystemService(PermissionCheckerManager.class).checkOp(
391                 AppOpsManager.strOpToOp(opName), attributionSource.asState(), message,
392                 true /*forDataDelivery*/, true /*startDataDelivery*/);
393     }
394 
395     /**
396      * Finishes an ongoing op for data access chain described by the given {@link
397      * AttributionSource}.
398      *
399      * @param context Context for accessing resources.
400      * @param op The op to finish.
401      * @param attributionSource The identity for which finish op.
402      *
403      * @see #startOpForDataDelivery(Context, String, AttributionSource, String)
404      * @see #checkPermissionAndStartDataDelivery(Context, String, AttributionSource, String)
405      */
406     @SuppressWarnings("ConstantConditions")
finishDataDelivery(@onNull Context context, @NonNull String op, @NonNull AttributionSource attributionSource)407     public static void finishDataDelivery(@NonNull Context context, @NonNull String op,
408             @NonNull AttributionSource attributionSource) {
409         context.getSystemService(PermissionCheckerManager.class).finishDataDelivery(
410                 AppOpsManager.strOpToOp(op), attributionSource.asState(),
411                 /*fromDatasource*/ false);
412     }
413 
414     /**
415      * Finishes an ongoing op for data access chain described by the given {@link
416      * AttributionSource}. Call this method if you are the datasource which would
417      * not finish an op for your attribution source as it was not started.
418      *
419      * @param context Context for accessing resources.
420      * @param op The op to finish.
421      * @param attributionSource The identity for which finish op.
422      *
423      * @see #startOpForDataDelivery(Context, String, AttributionSource, String)
424      * @see #checkPermissionAndStartDataDelivery(Context, String, AttributionSource, String)
425      */
426     @SuppressWarnings("ConstantConditions")
finishDataDeliveryFromDatasource(@onNull Context context, @NonNull String op, @NonNull AttributionSource attributionSource)427     public static void finishDataDeliveryFromDatasource(@NonNull Context context,
428             @NonNull String op, @NonNull AttributionSource attributionSource) {
429         context.getSystemService(PermissionCheckerManager.class).finishDataDelivery(
430                 AppOpsManager.strOpToOp(op), attributionSource.asState(),
431                 /*fromDatasource*/ true);
432     }
433 
434     /**
435      * Checks whether a given data access chain described by the given {@link
436      * AttributionSource} has a given app op allowed.
437      *
438      * <strong>NOTE:</strong> Use this method only for op checks at the
439      * preflight point where you will not deliver the protected data
440      * to clients but schedule a data delivery, apps register listeners,
441      * etc.
442      *
443      * <p>For example, if an app registers a data listener it should have the op
444      * but no data is actually sent to the app at the moment of registration
445      * and you should use this method to determine if the app has or may have data
446      * access and this check will not leave a trace that protected data
447      * was delivered. When you are about to deliver the data to a registered
448      * listener you should use {@link #checkOpForDataDelivery(Context, String,
449      * AttributionSource, String)} which will evaluate the op access based
450      * on the current fg/bg state of the app and leave a record that the data was
451      * accessed.
452      *
453      * @param context Context for accessing resources.
454      * @param opName The op to check.
455      * @param attributionSource The identity for which to check the permission.
456      * @param message A message describing the reason the permission was checked
457      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
458      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
459      *
460      * @see #checkOpForDataDelivery(Context, String, AttributionSource, String)
461      */
462     @PermissionResult
463     @SuppressWarnings("ConstantConditions")
checkOpForPreflight(@onNull Context context, @NonNull String opName, @NonNull AttributionSource attributionSource, @Nullable String message)464     public static int checkOpForPreflight(@NonNull Context context,
465             @NonNull String opName, @NonNull AttributionSource attributionSource,
466             @Nullable String message) {
467         return context.getSystemService(PermissionCheckerManager.class).checkOp(
468                 AppOpsManager.strOpToOp(opName), attributionSource.asState(), message,
469                 false /*forDataDelivery*/, false /*startDataDelivery*/);
470     }
471 
472     /**
473      * Checks whether a given data access chain described by the given {@link AttributionSource}
474      * has an allowed app op.
475      *
476      * <strong>NOTE:</strong> Use this method only for op checks at the
477      * point where you will deliver the permission protected data to clients.
478      *
479      * <p>For example, if an app registers a data listener it should have the data
480      * permission but no data is actually sent to the app at the moment of registration
481      * and you should use {@link #checkOpForPreflight(Context, String, AttributionSource, String)}
482      * to determine if the app has or may have data access and this check will not
483      * leave a trace that op protected data was delivered. When you are about to
484      * deliver the  data to a registered listener you should use this method which
485      * will evaluate the op access based on the current fg/bg state of the app and
486      * leave a record that the data was accessed.
487      *
488      * @param context Context for accessing resources.
489      * @param opName The op to check.
490      * @param attributionSource The identity for which to check the op.
491      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
492      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
493      * @param message A message describing the reason the permission was checked
494      *
495      * @see #checkOpForPreflight(Context, String, AttributionSource, String)
496      */
497     @PermissionResult
498     @SuppressWarnings("ConstantConditions")
checkOpForDataDelivery(@onNull Context context, @NonNull String opName, @NonNull AttributionSource attributionSource, @Nullable String message)499     public static int checkOpForDataDelivery(@NonNull Context context,
500             @NonNull String opName, @NonNull AttributionSource attributionSource,
501             @Nullable String message) {
502         return context.getSystemService(PermissionCheckerManager.class).checkOp(
503                 AppOpsManager.strOpToOp(opName), attributionSource.asState(), message,
504                 true /*forDataDelivery*/, false /*startDataDelivery*/);
505     }
506 
507     /**
508      * Checks whether a given package in a UID and PID has a given permission
509      * and whether the app op that corresponds to this permission is allowed.
510      *
511      * <strong>NOTE:</strong> Use this method only for permission checks at the
512      * preflight point where you will not deliver the permission protected data
513      * to clients but schedule permission data delivery, apps register listeners,
514      * etc.
515      *
516      * <p>For example, if an app registers a location listener it should have the location
517      * permission but no data is actually sent to the app at the moment of registration
518      * and you should use this method to determine if the app has or may have location
519      * permission (if app has only foreground location the grant state depends on the app's
520      * fg/gb state) and this check will not leave a trace that permission protected data
521      * was delivered. When you are about to deliver the location data to a registered
522      * listener you should use {@link #checkPermissionForDataDelivery(Context, String,
523      * int, int, String, String, String)} which will evaluate the permission access based
524      * on the currentfg/bg state of the app and leave a record that the data was accessed.
525      *
526      * @param context Context for accessing resources.
527      * @param permission The permission to check.
528      * @param pid The process id for which to check.
529      * @param uid The uid for which to check.
530      * @param packageName The package name for which to check. If null the
531      *     the first package for the calling UID will be used.
532      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
533      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
534      *
535      * @see #checkPermissionForDataDelivery(Context, String, int, int, String, String, String)
536      */
537     @PermissionResult
checkPermissionForPreflight(@onNull Context context, @NonNull String permission, int pid, int uid, @Nullable String packageName)538     public static int checkPermissionForPreflight(@NonNull Context context,
539             @NonNull String permission, int pid, int uid, @Nullable String packageName) {
540         return checkPermissionForPreflight(context, permission, new AttributionSource(
541                 uid, packageName, null /*attributionTag*/));
542     }
543 
544     /**
545      * Checks whether a given data access chain described by the given {@link AttributionSource}
546      * has a given permission and whether the app op that corresponds to this permission
547      * is allowed.
548      *
549      * <strong>NOTE:</strong> Use this method only for permission checks at the
550      * preflight point where you will not deliver the permission protected data
551      * to clients but schedule permission data delivery, apps register listeners,
552      * etc.
553      *
554      * <p>For example, if an app registers a data listener it should have the required
555      * permission but no data is actually sent to the app at the moment of registration
556      * and you should use this method to determine if the app has or may have the
557      * permission and this check will not leave a trace that permission protected data
558      * was delivered. When you are about to deliver the protected data to a registered
559      * listener you should use {@link #checkPermissionForDataDelivery(Context, String,
560      * int, AttributionSource, String, boolean)} which will evaluate the permission access based
561      * on the current fg/bg state of the app and leave a record that the data was accessed.
562      *
563      * @param context Context for accessing resources.
564      * @param permission The permission to check.
565      * @param attributionSource The identity for which to check the permission.
566      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
567      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
568      *
569      * @see #checkPermissionForDataDelivery(Context, String, int, AttributionSource,
570      *     String, boolean)
571      */
572     @PermissionResult
573     @SuppressWarnings("ConstantConditions")
checkPermissionForPreflight(@onNull Context context, @NonNull String permission, @NonNull AttributionSource attributionSource)574     public static int checkPermissionForPreflight(@NonNull Context context,
575             @NonNull String permission, @NonNull AttributionSource attributionSource) {
576         return context.getSystemService(PermissionCheckerManager.class)
577                 .checkPermission(permission, attributionSource.asState(), null /*message*/,
578                 false /*forDataDelivery*/, /*startDataDelivery*/ false, /*fromDatasource*/ false,
579                 AppOpsManager.OP_NONE);
580     }
581 
582     /**
583      * Checks whether your app has a given permission and whether the app op
584      * that corresponds to this permission is allowed.
585      *
586      * <strong>NOTE:</strong> Use this method only for permission checks at the
587      * point where you will deliver the permission protected data to clients.
588      *
589      * <p>For example, if an app registers a location listener it should have the location
590      * permission but no data is actually sent to the app at the moment of registration
591      * and you should use {@link #checkSelfPermissionForPreflight(Context, String)}
592      * to determine if the app has or may have location permission (if app has only foreground
593      * location the grant state depends on the app's fg/gb state) and this check will not
594      * leave a trace that permission protected data was delivered. When you are about to
595      * deliver the location data to a registered listener you should use this method
596      * which will evaluate the permission access based on the current fg/bg state of the
597      * app and leave a record that the data was accessed.
598      *
599      * <p>This API assumes the {@link Binder#getCallingUid()} is the same as
600      * {@link Process#myUid()}.
601      *
602      * @param context Context for accessing resources.
603      * @param permission The permission to check.
604      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
605      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
606      * @param message A message describing the reason the permission was checked
607      *
608      * @see #checkSelfPermissionForPreflight(Context, String)
609      */
610     @PermissionResult
checkSelfPermissionForDataDelivery(@onNull Context context, @NonNull String permission, @Nullable String message)611     public static int checkSelfPermissionForDataDelivery(@NonNull Context context,
612             @NonNull String permission, @Nullable String message) {
613         return checkPermissionForDataDelivery(context, permission, Process.myPid(),
614                 Process.myUid(), context.getPackageName(), context.getAttributionTag(), message,
615                 /*startDataDelivery*/ false);
616     }
617 
618     /**
619      * Checks whether your app has a given permission and whether the app op
620      * that corresponds to this permission is allowed.
621      *
622      * <strong>NOTE:</strong> Use this method only for permission checks at the
623      * preflight point where you will not deliver the permission protected data
624      * to clients but schedule permission data delivery, apps register listeners,
625      * etc.
626      *
627      * <p>For example, if an app registers a location listener it should have the location
628      * permission but no data is actually sent to the app at the moment of registration
629      * and you should use this method to determine if the app has or may have location
630      * permission (if app has only foreground location the grant state depends on the
631      * app's fg/gb state) and this check will not leave a trace that permission protected
632      * data was delivered. When you are about to deliver the location data to a registered
633      * listener you should use this method which will evaluate the permission access based
634      * on the current fg/bg state of the app and leave a record that the data was accessed.
635      *
636      * <p>This API assumes the {@link Binder#getCallingUid()} is the same as
637      * {@link Process#myUid()}.
638      *
639      * @param context Context for accessing resources.
640      * @param permission The permission to check.
641      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
642      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
643      *
644      * @see #checkSelfPermissionForDataDelivery(Context, String, String)
645      */
646     @PermissionResult
checkSelfPermissionForPreflight(@onNull Context context, @NonNull String permission)647     public static int checkSelfPermissionForPreflight(@NonNull Context context,
648             @NonNull String permission) {
649         return checkPermissionForPreflight(context, permission, Process.myPid(),
650                 Process.myUid(), context.getPackageName());
651     }
652 
653     /**
654      * Checks whether the IPC you are handling has a given permission and whether
655      * the app op that corresponds to this permission is allowed.
656      *
657      * <strong>NOTE:</strong> Use this method only for permission checks at the
658      * point where you will deliver the permission protected data to clients.
659      *
660      * <p>For example, if an app registers a location listener it should have the location
661      * permission but no data is actually sent to the app at the moment of registration
662      * and you should use {@link #checkCallingPermissionForPreflight(Context, String, String)}
663      * to determine if the app has or may have location permission (if app has only foreground
664      * location the grant state depends on the app's fg/gb state) and this check will not
665      * leave a trace that permission protected data was delivered. When you are about to
666      * deliver the location data to a registered listener you should use this method which
667      * will evaluate the permission access based on the current fg/bg state of the app and
668      * leave a record that the data was accessed.
669      *
670      * <p>For more details how to determine the {@code callingPackageName},
671      * {@code callingAttributionTag}, and {@code message}, please check the description in
672      * {@link AppOpsManager#noteOp(String, int, String, String, String)}
673      *
674      * @param context Context for accessing resources.
675      * @param permission The permission to check.
676      * @param callingPackageName The package name making the IPC. If null the
677      *     the first package for the calling UID will be used.
678      * @param callingAttributionTag attribution tag
679      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
680      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
681      * @param message A message describing the reason the permission was checked
682      *
683      * @see #checkCallingPermissionForPreflight(Context, String, String)
684      */
685     @PermissionResult
checkCallingPermissionForDataDelivery(@onNull Context context, @NonNull String permission, @Nullable String callingPackageName, @Nullable String callingAttributionTag, @Nullable String message)686     public static int checkCallingPermissionForDataDelivery(@NonNull Context context,
687             @NonNull String permission, @Nullable String callingPackageName,
688             @Nullable String callingAttributionTag, @Nullable String message) {
689         if (Binder.getCallingPid() == Process.myPid()) {
690             return PERMISSION_HARD_DENIED;
691         }
692         return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
693                 Binder.getCallingUid(), callingPackageName, callingAttributionTag, message,
694                 /*startDataDelivery*/ false);
695     }
696 
697     /**
698      * Checks whether the IPC you are handling has a given permission and whether
699      * the app op that corresponds to this permission is allowed.
700      *
701      * <strong>NOTE:</strong> Use this method only for permission checks at the
702      * preflight point where you will not deliver the permission protected data
703      * to clients but schedule permission data delivery, apps register listeners,
704      * etc.
705      *
706      * <p>For example, if an app registers a location listener it should have the location
707      * permission but no data is actually sent to the app at the moment of registration
708      * and you should use this method to determine if the app has or may have location
709      * permission (if app has only foreground location the grant state depends on the app's
710      * fg/gb state) and this check will not leave a trace that permission protected data
711      * was delivered. When you are about to deliver the location data to a registered
712      * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
713      * String, String, String, String)} which will evaluate the permission access based on the
714      * current fg/bg stateof the app and leave a record that the data was accessed.
715      *
716      * @param context Context for accessing resources.
717      * @param permission The permission to check.
718      * @param packageName The package name making the IPC. If null the
719      *     the first package for the calling UID will be used.
720      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
721      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
722      *
723      * @see #checkCallingPermissionForDataDelivery(Context, String, String, String, String)
724      */
725     @PermissionResult
checkCallingPermissionForPreflight(@onNull Context context, @NonNull String permission, @Nullable String packageName)726     public static int checkCallingPermissionForPreflight(@NonNull Context context,
727             @NonNull String permission, @Nullable String packageName) {
728         if (Binder.getCallingPid() == Process.myPid()) {
729             return PERMISSION_HARD_DENIED;
730         }
731         return checkPermissionForPreflight(context, permission, Binder.getCallingPid(),
732                 Binder.getCallingUid(), packageName);
733     }
734 
735     /**
736      * Checks whether the IPC you are handling or your app has a given permission
737      * and whether the app op that corresponds to this permission is allowed.
738      *
739      * <strong>NOTE:</strong> Use this method only for permission checks at the
740      * point where you will deliver the permission protected data to clients.
741      *
742      * <p>For example, if an app registers a location listener it should have the location
743      * permission but no data is actually sent to the app at the moment of registration
744      * and you should use {@link #checkCallingOrSelfPermissionForPreflight(Context, String)}
745      * to determine if the app has or may have location permission (if app has only foreground
746      * location the grant state depends on the app's fg/gb state) and this check will not
747      * leave a trace that permission protected data was delivered. When you are about to
748      * deliver the location data to a registered listener you should use this method which
749      * will evaluate the permission access based on the current fg/bg state of the app and
750      * leave a record that the data was accessed.
751      *
752      * <p>For more details how to determine the {@code callingPackageName},
753      * {@code callingAttributionTag}, and {@code message}, please check the description in
754      * {@link AppOpsManager#noteOp(String, int, String, String, String)}
755      *
756      * @param context Context for accessing resources.
757      * @param permission The permission to check.
758      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
759      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
760      * @param callingPackageName package name tag of caller (if not self)
761      * @param callingAttributionTag attribution tag of caller (if not self)
762      * @param message A message describing the reason the permission was checked
763      *
764      * @see #checkCallingOrSelfPermissionForPreflight(Context, String)
765      */
766     @PermissionResult
checkCallingOrSelfPermissionForDataDelivery(@onNull Context context, @NonNull String permission, @Nullable String callingPackageName, @Nullable String callingAttributionTag, @Nullable String message)767     public static int checkCallingOrSelfPermissionForDataDelivery(@NonNull Context context,
768             @NonNull String permission, @Nullable String callingPackageName,
769             @Nullable String callingAttributionTag, @Nullable String message) {
770         callingPackageName = (Binder.getCallingPid() == Process.myPid())
771                 ? context.getPackageName() : callingPackageName;
772         callingAttributionTag = (Binder.getCallingPid() == Process.myPid())
773                 ? context.getAttributionTag() : callingAttributionTag;
774         return checkPermissionForDataDelivery(context, permission, Binder.getCallingPid(),
775                 Binder.getCallingUid(), callingPackageName, callingAttributionTag, message,
776                 /*startDataDelivery*/ false);
777     }
778 
779     /**
780      * Checks whether the IPC you are handling or your app has a given permission
781      * and whether the app op that corresponds to this permission is allowed.
782      *
783      * <strong>NOTE:</strong> Use this method only for permission checks at the
784      * preflight point where you will not deliver the permission protected data
785      * to clients but schedule permission data delivery, apps register listeners,
786      * etc.
787      *
788      * <p>For example, if an app registers a location listener it should have the location
789      * permission but no data is actually sent to the app at the moment of registration
790      * and you should use this method to determine if the app has or may have location
791      * permission (if app has only foreground location the grant state depends on the
792      * app's fg/gb state) and this check will not leave a trace that permission protected
793      * data was delivered. When you are about to deliver the location data to a registered
794      * listener you should use {@link #checkCallingOrSelfPermissionForDataDelivery(Context,
795      * String, String, String, String)} which will evaluate the permission access based on the
796      * current fg/bg state of the app and leave a record that the data was accessed.
797      *
798      * @param context Context for accessing resources.
799      * @param permission The permission to check.
800      * @return The permission check result which is either {@link #PERMISSION_GRANTED}
801      *     or {@link #PERMISSION_SOFT_DENIED} or {@link #PERMISSION_HARD_DENIED}.
802      *
803      * @see #checkCallingOrSelfPermissionForDataDelivery(Context, String, String, String, String)
804      */
805     @PermissionResult
checkCallingOrSelfPermissionForPreflight(@onNull Context context, @NonNull String permission)806     public static int checkCallingOrSelfPermissionForPreflight(@NonNull Context context,
807             @NonNull String permission) {
808         String packageName = (Binder.getCallingPid() == Process.myPid())
809                 ? context.getPackageName() : null;
810         return checkPermissionForPreflight(context, permission, Binder.getCallingPid(),
811                 Binder.getCallingUid(), packageName);
812     }
813 }
814