1 /*
2  * Copyright (C) 2021 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.server.permission.access.permission
18 
19 import android.app.AppOpsManager
20 import android.app.admin.DevicePolicyManager
21 import android.content.pm.PackageManager
22 import android.os.Build
23 import android.permission.PermissionManager
24 import com.android.server.permission.access.util.andInv
25 import com.android.server.permission.access.util.flagsToString
26 import com.android.server.permission.access.util.hasAnyBit
27 import com.android.server.permission.access.util.hasBits
28 
29 /**
30  * A set of internal permission flags that's better than the set of `FLAG_PERMISSION_*` constants on
31  * [PackageManager].
32  *
33  * The old binary permission state is now tracked by multiple `*_GRANTED` and `*_REVOKED` flags, so
34  * that:
35  * - With [INSTALL_GRANTED] and [INSTALL_REVOKED], we can now get rid of the old per-package
36  *   `areInstallPermissionsFixed` attribute and correctly track it per-permission, finally fixing
37  *   edge cases during module rollbacks.
38  * - With [LEGACY_GRANTED] and [IMPLICIT_GRANTED], we can now ensure that legacy permissions and
39  *   implicit permissions split from non-runtime permissions are never revoked, without checking
40  *   split permissions and package state everywhere slowly and in slightly different ways.
41  * - With [RESTRICTION_REVOKED], we can now get rid of the error-prone logic about revoking and
42  *   potentially re-granting permissions upon restriction state changes.
43  *
44  * Permission grants due to protection level are now tracked by [PROTECTION_GRANTED], and permission
45  * grants due to [PackageManager.grantRuntimePermission] are now tracked by [RUNTIME_GRANTED].
46  *
47  * The [PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED] and
48  * [PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED] flags are now unified into [IMPLICIT], and
49  * they can be differentiated by the presence of [LEGACY_GRANTED].
50  *
51  * The rest of the permission flags have a 1:1 mapping to the old `FLAG_PERMISSION_*` constants, and
52  * don't have any effect on the binary permission state.
53  */
54 object PermissionFlags {
55     /** Permission flag for a normal permission that is granted at package installation. */
56     const val INSTALL_GRANTED = 1 shl 0
57 
58     /**
59      * Permission flag for a normal permission that is revoked at package installation.
60      *
61      * Normally packages that have already been installed cannot be granted new normal permissions
62      * until its next installation (update), so this flag helps track that the normal permission was
63      * revoked upon its most recent installation.
64      */
65     const val INSTALL_REVOKED = 1 shl 1
66 
67     /**
68      * Permission flag for a signature or internal permission that is granted based on the
69      * permission's protection level, including its protection and protection flags.
70      *
71      * For example, this flag may be set when the permission is a signature permission and the
72      * package is having a compatible signing certificate with the package defining the permission,
73      * or when the permission is a privileged permission and the package is a privileged app with
74      * its permission in the
75      * [privileged permission allowlist](https://source.android.com/docs/core/permissions/perms-allowlist).
76      */
77     const val PROTECTION_GRANTED = 1 shl 2
78 
79     /**
80      * Permission flag for a role or runtime permission that is or was granted by a role.
81      *
82      * @see PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE
83      */
84     const val ROLE = 1 shl 3
85 
86     /**
87      * Permission flag for a development, role or runtime permission that is granted via
88      * [PackageManager.grantRuntimePermission].
89      */
90     const val RUNTIME_GRANTED = 1 shl 4
91 
92     /**
93      * Permission flag for a runtime permission whose state is set by the user.
94      *
95      * For example, this flag may be set when the permission is allowed by the user in the request
96      * permission dialog, or managed in the permission settings.
97      *
98      * @see PackageManager.FLAG_PERMISSION_USER_SET
99      */
100     const val USER_SET = 1 shl 5
101 
102     /**
103      * Permission flag for a runtime permission whose state is (revoked and) fixed by the user.
104      *
105      * For example, this flag may be set when the permission is denied twice by the user in the
106      * request permission dialog.
107      *
108      * @see PackageManager.FLAG_PERMISSION_USER_FIXED
109      */
110     const val USER_FIXED = 1 shl 6
111 
112     /**
113      * Permission flag for a runtime permission whose state is set and fixed by the device policy
114      * via [DevicePolicyManager.setPermissionGrantState].
115      *
116      * @see PackageManager.FLAG_PERMISSION_POLICY_FIXED
117      */
118     const val POLICY_FIXED = 1 shl 7
119 
120     /**
121      * Permission flag for a runtime permission that is (pregranted and) fixed by the system.
122      *
123      * For example, this flag may be set in
124      * [com.android.server.pm.permission.DefaultPermissionGrantPolicy].
125      *
126      * @see PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
127      */
128     const val SYSTEM_FIXED = 1 shl 8
129 
130     /**
131      * Permission flag for a runtime permission that is or was pregranted by the system.
132      *
133      * For example, this flag may be set in
134      * [com.android.server.pm.permission.DefaultPermissionGrantPolicy].
135      *
136      * @see PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
137      */
138     const val PREGRANT = 1 shl 9
139 
140     /**
141      * Permission flag for a runtime permission that is granted because the package targets a legacy
142      * SDK version before [Build.VERSION_CODES.M] and doesn't support runtime permissions.
143      *
144      * As long as this flag is set, the permission should always be considered granted, although
145      * [APP_OP_REVOKED] may cause the app op for the runtime permission to be revoked. Once the
146      * package targets a higher SDK version so that it started supporting runtime permissions, this
147      * flag should be removed and the remaining flags should take effect.
148      *
149      * @see PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
150      * @see PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
151      */
152     const val LEGACY_GRANTED = 1 shl 10
153 
154     /**
155      * Permission flag for a runtime permission that is granted because the package targets a lower
156      * SDK version and the permission is implicit to it as a
157      * [split permission][PermissionManager.SplitPermissionInfo] from other non-runtime permissions.
158      *
159      * As long as this flag is set, the permission should always be considered granted, although
160      * [APP_OP_REVOKED] may cause the app op for the runtime permission to be revoked. Once the
161      * package targets a higher SDK version so that the permission is no longer implicit to it, this
162      * flag should be removed and the remaining flags should take effect.
163      *
164      * @see PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
165      * @see PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
166      */
167     const val IMPLICIT_GRANTED = 1 shl 11
168 
169     /**
170      * Permission flag for a runtime permission that is granted because the package targets a legacy
171      * SDK version before [Build.VERSION_CODES.M] and doesn't support runtime permissions, so that
172      * it needs to be reviewed by the user; or granted because the package targets a lower SDK
173      * version and the permission is implicit to it as a
174      * [split permission][PermissionManager.SplitPermissionInfo] from other non-runtime permissions,
175      * so that it needs to be revoked when it's no longer implicit.
176      *
177      * @see PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
178      * @see PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
179      */
180     const val IMPLICIT = 1 shl 12
181 
182     /**
183      * Permission flag for a runtime permission that is user-sensitive when it's granted.
184      *
185      * This flag is informational and managed by PermissionController.
186      *
187      * @see PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
188      */
189     const val USER_SENSITIVE_WHEN_GRANTED = 1 shl 13
190 
191     /**
192      * Permission flag for a runtime permission that is user-sensitive when it's revoked.
193      *
194      * This flag is informational and managed by PermissionController.
195      *
196      * @see PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED
197      */
198     const val USER_SENSITIVE_WHEN_REVOKED = 1 shl 14
199 
200     /**
201      * Permission flag for a restricted runtime permission that is exempt by the package's
202      * installer.
203      *
204      * For example, this flag may be set when the installer applied the exemption as part of the
205      * [session parameters](https://developer.android.com/reference/android/content/pm/PackageInstaller.SessionParams#setWhitelistedRestrictedPermissions(java.util.Set%3Cjava.lang.String%3E)).
206      *
207      * The permission will be restricted when none of the exempt flags is set.
208      *
209      * @see PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
210      */
211     const val INSTALLER_EXEMPT = 1 shl 15
212 
213     /**
214      * Permission flag for a restricted runtime permission that is exempt by the system.
215      *
216      * For example, this flag may be set when the package is a system app.
217      *
218      * The permission will be restricted when none of the exempt flags is set.
219      *
220      * @see PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT
221      */
222     const val SYSTEM_EXEMPT = 1 shl 16
223 
224     /**
225      * Permission flag for a restricted runtime permission that is exempt due to system upgrade.
226      *
227      * For example, this flag may be set when the package was installed before the system was
228      * upgraded to [Build.VERSION_CODES.Q], when restricted permissions were introduced.
229      *
230      * The permission will be restricted when none of the exempt flags is set.
231      *
232      * @see PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT
233      */
234     const val UPGRADE_EXEMPT = 1 shl 17
235 
236     /**
237      * Permission flag for a restricted runtime permission that is revoked due to being hard
238      * restricted.
239      *
240      * @see PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION
241      */
242     const val RESTRICTION_REVOKED = 1 shl 18
243 
244     /**
245      * Permission flag for a restricted runtime permission that is soft restricted.
246      *
247      * @see PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION
248      */
249     const val SOFT_RESTRICTED = 1 shl 19
250 
251     /**
252      * Permission flag for a runtime permission whose app op is revoked.
253      *
254      * For example, this flag may be set when the runtime permission is legacy or implicit but still
255      * "revoked" by the user in permission settings, or when the app op mode for the runtime
256      * permission is set to revoked via [AppOpsManager.setUidMode].
257      *
258      * @see PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
259      */
260     const val APP_OP_REVOKED = 1 shl 20
261 
262     /**
263      * Permission flag for a runtime permission that is granted as one-time.
264      *
265      * For example, this flag may be set when the user selected "Only this time" in the request
266      * permission dialog.
267      *
268      * This flag, along with other user decisions when it is set, should never be persisted, and
269      * should be removed once the permission is revoked.
270      *
271      * @see PackageManager.FLAG_PERMISSION_ONE_TIME
272      */
273     const val ONE_TIME = 1 shl 21
274 
275     /**
276      * Permission flag for a runtime permission that was revoked due to app hibernation.
277      *
278      * This flag is informational and added by PermissionController, and should be removed once the
279      * permission is granted again.
280      *
281      * @see PackageManager.FLAG_PERMISSION_AUTO_REVOKED
282      */
283     const val HIBERNATION = 1 shl 22
284 
285     /**
286      * Permission flag for a runtime permission that is selected by the user.
287      *
288      * For example, this flag may be set when one of the coarse/fine location accuracies is selected
289      * by the user.
290      *
291      * This flag is informational and managed by PermissionController.
292      *
293      * @see PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY
294      */
295     const val USER_SELECTED = 1 shl 23
296 
297     /** Mask for all permission flags. */
298     const val MASK_ALL = 0.inv()
299 
300     /** Mask for all permission flags that may be applied to a runtime permission. */
301     const val MASK_RUNTIME =
302         ROLE or
303             RUNTIME_GRANTED or
304             USER_SET or
305             USER_FIXED or
306             POLICY_FIXED or
307             SYSTEM_FIXED or
308             PREGRANT or
309             LEGACY_GRANTED or
310             IMPLICIT_GRANTED or
311             IMPLICIT or
312             USER_SENSITIVE_WHEN_GRANTED or
313             USER_SENSITIVE_WHEN_REVOKED or
314             INSTALLER_EXEMPT or
315             SYSTEM_EXEMPT or
316             UPGRADE_EXEMPT or
317             RESTRICTION_REVOKED or
318             SOFT_RESTRICTED or
319             APP_OP_REVOKED or
320             ONE_TIME or
321             HIBERNATION or
322             USER_SELECTED
323 
324     /** Mask for all permission flags about permission exemption. */
325     const val MASK_EXEMPT = INSTALLER_EXEMPT or SYSTEM_EXEMPT or UPGRADE_EXEMPT
326 
327     /** Mask for all permission flags about permission restriction. */
328     const val MASK_RESTRICTED = RESTRICTION_REVOKED or SOFT_RESTRICTED
329 
isPermissionGrantednull330     fun isPermissionGranted(flags: Int): Boolean {
331         if (flags.hasBits(INSTALL_GRANTED)) {
332             return true
333         }
334         if (flags.hasBits(INSTALL_REVOKED)) {
335             return false
336         }
337         if (flags.hasBits(PROTECTION_GRANTED)) {
338             return true
339         }
340         if (flags.hasBits(LEGACY_GRANTED) || flags.hasBits(IMPLICIT_GRANTED)) {
341             return true
342         }
343         if (flags.hasBits(RESTRICTION_REVOKED)) {
344             return false
345         }
346         return flags.hasBits(RUNTIME_GRANTED)
347     }
348 
isAppOpGrantednull349     fun isAppOpGranted(flags: Int): Boolean {
350         if (!isPermissionGranted(flags)) {
351             return false
352         }
353         if (flags.hasAnyBit(MASK_RESTRICTED)) {
354             return false
355         }
356         if (flags.hasBits(APP_OP_REVOKED)) {
357             return false
358         }
359         return true
360     }
361 
toApiFlagsnull362     fun toApiFlags(flags: Int): Int {
363         var apiFlags = 0
364         if (flags.hasBits(USER_SET)) {
365             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SET
366         }
367         if (flags.hasBits(USER_FIXED)) {
368             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_FIXED
369         }
370         if (flags.hasBits(POLICY_FIXED)) {
371             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_POLICY_FIXED
372         }
373         if (flags.hasBits(SYSTEM_FIXED)) {
374             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SYSTEM_FIXED
375         }
376         if (flags.hasBits(PREGRANT)) {
377             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT
378         }
379         if (flags.hasBits(IMPLICIT)) {
380             apiFlags =
381                 apiFlags or
382                     if (flags.hasBits(LEGACY_GRANTED)) {
383                         PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED
384                     } else {
385                         PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED
386                     }
387         }
388         if (flags.hasBits(USER_SENSITIVE_WHEN_GRANTED)) {
389             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED
390         }
391         if (flags.hasBits(USER_SENSITIVE_WHEN_REVOKED)) {
392             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED
393         }
394         if (flags.hasBits(INSTALLER_EXEMPT)) {
395             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT
396         }
397         if (flags.hasBits(SYSTEM_EXEMPT)) {
398             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT
399         }
400         if (flags.hasBits(UPGRADE_EXEMPT)) {
401             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT
402         }
403         if (flags.hasBits(RESTRICTION_REVOKED) || flags.hasBits(SOFT_RESTRICTED)) {
404             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION
405         }
406         if (flags.hasBits(ROLE)) {
407             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE
408         }
409         if (flags.hasBits(APP_OP_REVOKED)) {
410             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_REVOKED_COMPAT
411         }
412         if (flags.hasBits(ONE_TIME)) {
413             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_ONE_TIME
414         }
415         if (flags.hasBits(HIBERNATION)) {
416             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_AUTO_REVOKED
417         }
418         if (flags.hasBits(USER_SELECTED)) {
419             apiFlags = apiFlags or PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY
420         }
421         return apiFlags
422     }
423 
updateRuntimePermissionGrantednull424     fun updateRuntimePermissionGranted(flags: Int, isGranted: Boolean): Int =
425         if (isGranted) flags or RUNTIME_GRANTED else flags andInv RUNTIME_GRANTED
426 
427     fun updateFlags(permission: Permission, flags: Int, apiFlagMask: Int, apiFlagValues: Int): Int {
428         val oldApiFlags = toApiFlags(flags)
429         val newApiFlags = (oldApiFlags andInv apiFlagMask) or (apiFlagValues and apiFlagMask)
430         return fromApiFlags(newApiFlags, permission, flags)
431     }
432 
fromApiFlagsnull433     private fun fromApiFlags(apiFlags: Int, permission: Permission, oldFlags: Int): Int {
434         var flags = 0
435         flags = flags or (oldFlags and INSTALL_GRANTED)
436         flags = flags or (oldFlags and INSTALL_REVOKED)
437         flags = flags or (oldFlags and PROTECTION_GRANTED)
438         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE)) {
439             flags = flags or ROLE
440         }
441         flags = flags or (oldFlags and RUNTIME_GRANTED)
442         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SET)) {
443             flags = flags or USER_SET
444         }
445         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_FIXED)) {
446             flags = flags or USER_FIXED
447         }
448         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_POLICY_FIXED)) {
449             flags = flags or POLICY_FIXED
450         }
451         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SYSTEM_FIXED)) {
452             flags = flags or SYSTEM_FIXED
453         }
454         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT)) {
455             flags = flags or PREGRANT
456         }
457         flags = flags or (oldFlags and LEGACY_GRANTED)
458         flags = flags or (oldFlags and IMPLICIT_GRANTED)
459         if (
460             apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) ||
461                 apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKE_WHEN_REQUESTED)
462         ) {
463             flags = flags or IMPLICIT
464         }
465         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_GRANTED)) {
466             flags = flags or USER_SENSITIVE_WHEN_GRANTED
467         }
468         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_USER_SENSITIVE_WHEN_DENIED)) {
469             flags = flags or USER_SENSITIVE_WHEN_REVOKED
470         }
471         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT)) {
472             flags = flags or INSTALLER_EXEMPT
473         }
474         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT)) {
475             flags = flags or SYSTEM_EXEMPT
476         }
477         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT)) {
478             flags = flags or UPGRADE_EXEMPT
479         }
480         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION)) {
481             if (permission.isHardRestricted) {
482                 flags = flags or RESTRICTION_REVOKED
483             }
484             if (permission.isSoftRestricted) {
485                 flags = flags or SOFT_RESTRICTED
486             }
487         }
488         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_REVOKED_COMPAT)) {
489             flags = flags or APP_OP_REVOKED
490         }
491         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_ONE_TIME)) {
492             flags = flags or ONE_TIME
493         }
494         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_AUTO_REVOKED)) {
495             flags = flags or HIBERNATION
496         }
497         if (apiFlags.hasBits(PackageManager.FLAG_PERMISSION_SELECTED_LOCATION_ACCURACY)) {
498             flags = flags or USER_SELECTED
499         }
500         return flags
501     }
502 
flagToStringnull503     fun flagToString(flag: Int): String =
504         when (flag) {
505             INSTALL_GRANTED -> "INSTALL_GRANTED"
506             INSTALL_REVOKED -> "INSTALL_REVOKED"
507             PROTECTION_GRANTED -> "PROTECTION_GRANTED"
508             ROLE -> "ROLE"
509             RUNTIME_GRANTED -> "RUNTIME_GRANTED"
510             USER_SET -> "USER_SET"
511             USER_FIXED -> "USER_FIXED"
512             POLICY_FIXED -> "POLICY_FIXED"
513             SYSTEM_FIXED -> "SYSTEM_FIXED"
514             PREGRANT -> "PREGRANT"
515             LEGACY_GRANTED -> "LEGACY_GRANTED"
516             IMPLICIT_GRANTED -> "IMPLICIT_GRANTED"
517             IMPLICIT -> "IMPLICIT"
518             USER_SENSITIVE_WHEN_GRANTED -> "USER_SENSITIVE_WHEN_GRANTED"
519             USER_SENSITIVE_WHEN_REVOKED -> "USER_SENSITIVE_WHEN_REVOKED"
520             INSTALLER_EXEMPT -> "INSTALLER_EXEMPT"
521             SYSTEM_EXEMPT -> "SYSTEM_EXEMPT"
522             UPGRADE_EXEMPT -> "UPGRADE_EXEMPT"
523             RESTRICTION_REVOKED -> "RESTRICTION_REVOKED"
524             SOFT_RESTRICTED -> "SOFT_RESTRICTED"
525             APP_OP_REVOKED -> "APP_OP_REVOKED"
526             ONE_TIME -> "ONE_TIME"
527             HIBERNATION -> "HIBERNATION"
528             USER_SELECTED -> "USER_SELECTED"
529             else -> "0x${flag.toUInt().toString(16).uppercase()}"
530         }
531 
<lambda>null532     fun toString(flags: Int): String = flags.flagsToString { flagToString(it) }
533 
apiFlagsToStringnull534     fun apiFlagsToString(apiFlags: Int): String =
535         apiFlags.flagsToString { PackageManager.permissionFlagToString(it) }
536 }
537