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