Loading services/permission/java/com/android/server/permission/access/AccessCheckingService.kt +94 −4 Original line number Diff line number Diff line Loading @@ -17,6 +17,10 @@ package com.android.server.permission.access import android.content.Context import android.content.pm.PackageManager import android.content.pm.PackageManagerInternal import android.os.SystemProperties import android.os.UserHandle import com.android.internal.annotations.Keep import com.android.server.LocalManagerRegistry import com.android.server.LocalServices Loading @@ -24,12 +28,16 @@ import com.android.server.SystemConfig import com.android.server.SystemService import com.android.server.appop.AppOpsCheckingServiceInterface import com.android.server.permission.access.appop.AppOpService import com.android.server.permission.access.collection.IntSet import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.permission.PermissionService import com.android.server.pm.KnownPackages import com.android.server.pm.PackageManagerLocal import com.android.server.pm.UserManagerService import com.android.server.pm.permission.PermissionManagerServiceInterface import com.android.server.pm.pkg.PackageState import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract @Keep class AccessCheckingService(context: Context) : SystemService(context) { Loading @@ -44,6 +52,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { private lateinit var appOpService: AppOpService private lateinit var permissionService: PermissionService private lateinit var packageManagerInternal: PackageManagerInternal private lateinit var packageManagerLocal: PackageManagerLocal private lateinit var userManagerService: UserManagerService private lateinit var systemConfig: SystemConfig Loading @@ -57,6 +66,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { } fun initialize() { packageManagerInternal = LocalServices.getService(PackageManagerInternal::class.java) packageManagerLocal = LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java) userManagerService = UserManagerService.getInstance() Loading @@ -64,19 +74,94 @@ class AccessCheckingService(context: Context) : SystemService(context) { val userIds = IntSet(userManagerService.userIdsIncludingPreCreated) val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates val knownPackages = packageManagerInternal.knownPackages val isLeanback = systemConfig.isLeanback val configPermissions = systemConfig.permissions val privilegedPermissionAllowlistPackages = systemConfig.privilegedPermissionAllowlistPackages val permissionAllowlist = systemConfig.permissionAllowlist val implicitToSourcePermissions = systemConfig.implicitToSourcePermissions val state = AccessState() policy.initialize( state, userIds, packageStates, disabledSystemPackageStates, permissionAllowlist state, userIds, packageStates, disabledSystemPackageStates, knownPackages, isLeanback, configPermissions, privilegedPermissionAllowlistPackages, permissionAllowlist, implicitToSourcePermissions ) persistence.read(state) this.state = state mutateState { with(policy) { onInitialized() } } appOpService.initialize() permissionService.initialize() } private val PackageManagerInternal.knownPackages: IntMap<Array<String>> get() = IntMap<Array<String>>().apply { this[KnownPackages.PACKAGE_INSTALLER] = getKnownPackageNames( KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] = getKnownPackageNames( KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_VERIFIER] = getKnownPackageNames( KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_SETUP_WIZARD] = getKnownPackageNames( KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] = getKnownPackageNames( KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_CONFIGURATOR] = getKnownPackageNames( KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] = getKnownPackageNames( KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_APP_PREDICTOR] = getKnownPackageNames( KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_COMPANION] = getKnownPackageNames( KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_RETAIL_DEMO] = getKnownPackageNames( KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_RECENTS] = getKnownPackageNames( KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM ) } private val SystemConfig.isLeanback: Boolean get() = PackageManager.FEATURE_LEANBACK in availableFeatures private val SystemConfig.privilegedPermissionAllowlistPackages: IndexedListSet<String> get() = IndexedListSet<String>().apply { this += "android" if (PackageManager.FEATURE_AUTOMOTIVE in availableFeatures) { // Note that SystemProperties.get(String, String) forces returning an empty string // even if we pass null for the def parameter. val carServicePackage = SystemProperties.get("ro.android.car.carservice.package") if (carServicePackage.isNotEmpty()) { this += carServicePackage } } } private val SystemConfig.implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>> get() = IndexedMap<String, IndexedListSet<String>>().apply { splitPermissions.forEach { splitPermissionInfo -> val sourcePermissionName = splitPermissionInfo.splitPermission splitPermissionInfo.newPermissions.forEach { implicitPermissionName -> getOrPut(implicitPermissionName) { IndexedListSet() } += sourcePermissionName } } } fun getDecision(subject: AccessUri, `object`: AccessUri): Int = getState { with(policy) { getDecision(subject, `object`) } Loading Loading @@ -151,10 +236,15 @@ class AccessCheckingService(context: Context) : SystemService(context) { Pair<Map<String, PackageState>, Map<String, PackageState>> get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates } internal inline fun <T> getState(action: GetStateScope.() -> T): T = GetStateScope(state).action() @OptIn(ExperimentalContracts::class) internal inline fun <T> getState(action: GetStateScope.() -> T): T { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } return GetStateScope(state).action() } @OptIn(ExperimentalContracts::class) internal inline fun mutateState(crossinline action: MutateStateScope.() -> Unit) { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } synchronized(stateLock) { val oldState = state val newState = oldState.copy() Loading services/permission/java/com/android/server/permission/access/AccessPolicy.kt +20 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.permission.access import android.util.Log import com.android.modules.utils.BinaryXmlPullParser import com.android.modules.utils.BinaryXmlSerializer import com.android.server.SystemConfig import com.android.server.permission.access.appop.PackageAppOpPolicy import com.android.server.permission.access.appop.UidAppOpPolicy import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports Loading Loading @@ -59,7 +60,12 @@ class AccessPolicy private constructor( userIds: IntSet, packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, permissionAllowlist: PermissionAllowlist knownPackages: IntMap<Array<String>>, isLeanback: Boolean, configPermissions: Map<String, SystemConfig.PermissionEntry>, privilegedPermissionAllowlistPackages: IndexedListSet<String>, permissionAllowlist: PermissionAllowlist, implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>> ) { state.systemState.apply { this.userIds += userIds Loading @@ -69,7 +75,12 @@ class AccessPolicy private constructor( appIds.getOrPut(packageState.appId) { IndexedListSet() } .add(packageState.packageName) } this.knownPackages = knownPackages this.isLeanback = isLeanback this.configPermissions = configPermissions this.privilegedPermissionAllowlistPackages = privilegedPermissionAllowlistPackages this.permissionAllowlist = permissionAllowlist this.implicitToSourcePermissions = implicitToSourcePermissions } } Loading @@ -79,6 +90,12 @@ class AccessPolicy private constructor( } } fun MutateStateScope.onInitialized() { forEachSchemePolicy { with(it) { onInitialized() } } } fun MutateStateScope.onUserAdded(userId: Int) { newState.systemState.userIds += userId newState.userStates[userId] = UserState() Loading Loading @@ -292,6 +309,8 @@ abstract class SchemePolicy { open fun GetStateScope.onStateMutated() {} open fun MutateStateScope.onInitialized() {} open fun MutateStateScope.onUserAdded(userId: Int) {} open fun MutateStateScope.onUserRemoved(userId: Int) {} Loading services/permission/java/com/android/server/permission/access/AccessState.kt +14 −11 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.permission.access import android.content.pm.PermissionGroupInfo import com.android.server.SystemConfig import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.permission.Permission import com.android.server.pm.permission.PermissionAllowlist Loading @@ -42,15 +43,15 @@ class SystemState private constructor( var packageStates: Map<String, PackageState>, var disabledSystemPackageStates: Map<String, PackageState>, val appIds: IntMap<IndexedListSet<String>>, // A map of KnownPackagesInt to a set of known package names val knownPackages: IntMap<IndexedListSet<String>>, // A map of userId to packageName val deviceAndProfileOwners: IntMap<String>, // Whether the device supports leanback UI // Mapping from KnownPackages keys to package names. var knownPackages: IntMap<Array<String>>, var isLeanback: Boolean, val privilegedPermissionAllowlistSourcePackageNames: IndexedListSet<String>, var configPermissions: Map<String, SystemConfig.PermissionEntry>, var privilegedPermissionAllowlistPackages: IndexedListSet<String>, var permissionAllowlist: PermissionAllowlist, val implicitToSourcePermissions: Map<String, Set<String>>, var implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>, // Mapping from user ID to package name. var deviceAndProfileOwners: IntMap<String>, val permissionGroups: IndexedMap<String, PermissionGroupInfo>, val permissionTrees: IndexedMap<String, Permission>, val permissions: IndexedMap<String, Permission> Loading @@ -61,11 +62,12 @@ class SystemState private constructor( emptyMap(), IntMap(), IntMap(), IntMap(), false, emptyMap(), IndexedListSet(), PermissionAllowlist(), IndexedMap(), IntMap(), IndexedMap(), IndexedMap(), IndexedMap() Loading @@ -77,12 +79,13 @@ class SystemState private constructor( packageStates, disabledSystemPackageStates, appIds.copy { it.copy() }, knownPackages.copy { it.copy() }, deviceAndProfileOwners.copy { it }, knownPackages, isLeanback, privilegedPermissionAllowlistSourcePackageNames.copy(), configPermissions, privilegedPermissionAllowlistPackages, permissionAllowlist, implicitToSourcePermissions, deviceAndProfileOwners, permissionGroups.copy { it }, permissionTrees.copy { it }, permissions.copy { it } Loading services/permission/java/com/android/server/permission/access/permission/Permission.kt +64 −49 Original line number Diff line number Diff line Loading @@ -17,13 +17,18 @@ package com.android.server.permission.access.permission import android.content.pm.PermissionInfo import android.os.UserHandle import com.android.server.permission.access.util.hasBits import libcore.util.EmptyArray data class Permission( val permissionInfo: PermissionInfo, val isReconciled: Boolean, val type: Int, val appId: Int val appId: Int, @Suppress("ArrayInDataClass") val gids: IntArray = EmptyArray.INT, val areGidsPerUser: Boolean = false ) { inline val name: String get() = permissionInfo.name Loading @@ -37,36 +42,50 @@ data class Permission( inline val isDynamic: Boolean get() = type == TYPE_DYNAMIC inline val protectionLevel: Int @Suppress("DEPRECATION") get() = permissionInfo.protectionLevel inline val isInternal: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_INTERNAL inline val isNormal: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_NORMAL inline val isRuntime: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_DANGEROUS inline val isAppOp: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_FLAG_APPOP inline val isRemoved: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_REMOVED) inline val isSignature: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_SIGNATURE inline val isSoftRestricted: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_SOFT_RESTRICTED) inline val isAppOp: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_APPOP) inline val isHardRestricted: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_HARD_RESTRICTED) inline val isAppPredictor: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) inline val isSignature: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_SIGNATURE inline val isCompanion: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_COMPANION) inline val isInternal: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_INTERNAL inline val isConfigurator: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) inline val isDevelopment: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) inline val isIncidentReportApprover: Boolean get() = permissionInfo.protectionFlags .hasBits(PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) inline val isInstaller: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_INSTALLER) inline val isInstant: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_INSTANT) inline val isKnownSigner: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER) inline val isOem: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_OEM) Loading @@ -79,54 +98,53 @@ data class Permission( inline val isPrivileged: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_PRIVILEGED) inline val isSetup: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_SETUP) inline val isRecents: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RECENTS) inline val isVerifier: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_VERIFIER) inline val isRetailDemo: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) inline val isVendorPrivileged: Boolean get() = permissionInfo.protectionFlags .hasBits(PROTECTION_FLAG_VENDOR_PRIVILEGED) inline val isRole: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_ROLE) inline val isRuntimeOnly: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) inline val isSetup: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_SETUP) inline val isSystemTextClassifier: Boolean get() = permissionInfo.protectionFlags .hasBits(PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) inline val isConfigurator: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) inline val isIncidentReportApprover: Boolean inline val isVendorPrivileged: Boolean get() = permissionInfo.protectionFlags .hasBits(PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) inline val isAppPredictor: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) .hasBits(PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) inline val isCompanion: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_COMPANION) inline val isVerifier: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_VERIFIER) inline val isRetailDemo: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) inline val isHardRestricted: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_HARD_RESTRICTED) inline val isRecents: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RECENTS) inline val isRemoved: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_REMOVED) inline val isRole: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_ROLE) inline val isSoftRestricted: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_SOFT_RESTRICTED) inline val isKnownSigner: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER) inline val knownCerts: Set<String> get() = permissionInfo.knownCerts inline val hasGids: Boolean get() = throw NotImplementedError() get() = gids.isNotEmpty() inline val protectionLevel: Int @Suppress("DEPRECATION") get() = permissionInfo.protectionLevel inline val knownCerts: Set<String> get() = permissionInfo.knownCerts fun getGidsForUser(userId: Int): IntArray = if (areGidsPerUser) { IntArray(gids.size) { i -> UserHandle.getUid(userId, gids[i]) } } else { gids.clone() } companion object { // The permission is defined in an application manifest. Loading @@ -135,8 +153,5 @@ data class Permission( const val TYPE_CONFIG = 1 // The permission is defined dynamically. const val TYPE_DYNAMIC = 2 // TODO: PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED is a testApi const val PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000 } } services/permission/java/com/android/server/permission/access/permission/PermissionService.kt +42 −16 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.os.UserHandle import android.permission.IOnPermissionsChangeListener import android.permission.PermissionManager import android.provider.Settings import android.util.IntArray as GrowingIntArray import android.util.Log import com.android.internal.compat.IPlatformCompat import com.android.server.FgThread Loading @@ -61,6 +62,7 @@ import com.android.server.pm.permission.LegacyPermissionState import com.android.server.pm.permission.PermissionManagerServiceInterface import com.android.server.pm.permission.PermissionManagerServiceInternal import com.android.server.pm.pkg.AndroidPackage import libcore.util.EmptyArray import java.io.FileDescriptor import java.io.PrintWriter Loading @@ -77,6 +79,7 @@ class PermissionService( private lateinit var packageManagerInternal: PackageManagerInternal private lateinit var packageManagerLocal: PackageManagerLocal private lateinit var platformCompat: IPlatformCompat private lateinit var systemConfig: SystemConfig private lateinit var userManagerService: UserManagerService private val mountedStorageVolumes = IndexedSet<String?>() Loading @@ -94,6 +97,7 @@ class PermissionService( platformCompat = IPlatformCompat.Stub.asInterface( ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE) ) systemConfig = SystemConfig.getInstance() userManagerService = UserManagerService.getInstance() handlerThread = ServiceThread(LOG_TAG, Process.THREAD_PRIORITY_BACKGROUND, true) Loading Loading @@ -263,7 +267,10 @@ class PermissionService( } override fun getPermissionGids(permissionName: String, userId: Int): IntArray { TODO("Not yet implemented") val permission = service.getState { with(policy) { getPermissions()[permissionName] } } ?: return EmptyArray.INT return permission.getGidsForUser(userId) } override fun addPermission(permissionInfo: PermissionInfo, async: Boolean): Boolean { Loading @@ -286,6 +293,29 @@ class PermissionService( TODO("Not yet implemented") } override fun getGidsForUid(uid: Int): IntArray { val appId = UserHandle.getAppId(uid) val userId = UserHandle.getUserId(uid) val permissionFlags = service.getState { with(policy) { getUidPermissionFlags(appId, userId) } } ?: return EmptyArray.INT val gids = GrowingIntArray.wrap(systemConfig.globalGids) permissionFlags.forEachIndexed { _, permissionName, flags -> if (!PermissionFlags.isPermissionGranted(flags)) { return@forEachIndexed } val permission = service.getState { with(policy) { getPermissions()[permissionName] } } ?: return@forEachIndexed val permissionGids = permission.getGidsForUser(userId) if (permissionGids.isEmpty()) { return@forEachIndexed } gids.addAll(permissionGids) } return gids.toArray() } override fun grantRuntimePermission(packageName: String, permissionName: String, userId: Int) { TODO("Not yet implemented") } Loading @@ -306,14 +336,6 @@ class PermissionService( TODO("Not yet implemented") } override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { onPermissionsChangeListeners.addListener(listener) } override fun removeOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { onPermissionsChangeListeners.removeListener(listener) } override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int { // TODO: Implement permission checks. val appId = 0 Loading Loading @@ -493,21 +515,29 @@ class PermissionService( TODO("Not yet implemented") } override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { onPermissionsChangeListeners.addListener(listener) } override fun removeOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { onPermissionsChangeListeners.removeListener(listener) } override fun addOnRuntimePermissionStateChangedListener( listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener ) { TODO("Not yet implemented") // TODO: Should be removed once we remove PermissionPolicyService. } override fun removeOnRuntimePermissionStateChangedListener( listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener ) { TODO("Not yet implemented") // TODO: Should be removed once we remove PermissionPolicyService. } override fun getSplitPermissions(): List<SplitPermissionInfoParcelable> { return PermissionManager.splitPermissionInfoListToParcelableList( SystemConfig.getInstance().splitPermissions systemConfig.splitPermissions ) } Loading @@ -534,10 +564,6 @@ class PermissionService( return appOpPermissionPackageNames } override fun getGidsForUid(uid: Int): IntArray { TODO("Not yet implemented") } override fun backupRuntimePermissions(userId: Int): ByteArray? { TODO("Not yet implemented") } Loading Loading
services/permission/java/com/android/server/permission/access/AccessCheckingService.kt +94 −4 Original line number Diff line number Diff line Loading @@ -17,6 +17,10 @@ package com.android.server.permission.access import android.content.Context import android.content.pm.PackageManager import android.content.pm.PackageManagerInternal import android.os.SystemProperties import android.os.UserHandle import com.android.internal.annotations.Keep import com.android.server.LocalManagerRegistry import com.android.server.LocalServices Loading @@ -24,12 +28,16 @@ import com.android.server.SystemConfig import com.android.server.SystemService import com.android.server.appop.AppOpsCheckingServiceInterface import com.android.server.permission.access.appop.AppOpService import com.android.server.permission.access.collection.IntSet import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.permission.PermissionService import com.android.server.pm.KnownPackages import com.android.server.pm.PackageManagerLocal import com.android.server.pm.UserManagerService import com.android.server.pm.permission.PermissionManagerServiceInterface import com.android.server.pm.pkg.PackageState import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind import kotlin.contracts.contract @Keep class AccessCheckingService(context: Context) : SystemService(context) { Loading @@ -44,6 +52,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { private lateinit var appOpService: AppOpService private lateinit var permissionService: PermissionService private lateinit var packageManagerInternal: PackageManagerInternal private lateinit var packageManagerLocal: PackageManagerLocal private lateinit var userManagerService: UserManagerService private lateinit var systemConfig: SystemConfig Loading @@ -57,6 +66,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { } fun initialize() { packageManagerInternal = LocalServices.getService(PackageManagerInternal::class.java) packageManagerLocal = LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java) userManagerService = UserManagerService.getInstance() Loading @@ -64,19 +74,94 @@ class AccessCheckingService(context: Context) : SystemService(context) { val userIds = IntSet(userManagerService.userIdsIncludingPreCreated) val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates val knownPackages = packageManagerInternal.knownPackages val isLeanback = systemConfig.isLeanback val configPermissions = systemConfig.permissions val privilegedPermissionAllowlistPackages = systemConfig.privilegedPermissionAllowlistPackages val permissionAllowlist = systemConfig.permissionAllowlist val implicitToSourcePermissions = systemConfig.implicitToSourcePermissions val state = AccessState() policy.initialize( state, userIds, packageStates, disabledSystemPackageStates, permissionAllowlist state, userIds, packageStates, disabledSystemPackageStates, knownPackages, isLeanback, configPermissions, privilegedPermissionAllowlistPackages, permissionAllowlist, implicitToSourcePermissions ) persistence.read(state) this.state = state mutateState { with(policy) { onInitialized() } } appOpService.initialize() permissionService.initialize() } private val PackageManagerInternal.knownPackages: IntMap<Array<String>> get() = IntMap<Array<String>>().apply { this[KnownPackages.PACKAGE_INSTALLER] = getKnownPackageNames( KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] = getKnownPackageNames( KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_VERIFIER] = getKnownPackageNames( KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_SETUP_WIZARD] = getKnownPackageNames( KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] = getKnownPackageNames( KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_CONFIGURATOR] = getKnownPackageNames( KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] = getKnownPackageNames( KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_APP_PREDICTOR] = getKnownPackageNames( KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_COMPANION] = getKnownPackageNames( KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_RETAIL_DEMO] = getKnownPackageNames( KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM ) this[KnownPackages.PACKAGE_RECENTS] = getKnownPackageNames( KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM ) } private val SystemConfig.isLeanback: Boolean get() = PackageManager.FEATURE_LEANBACK in availableFeatures private val SystemConfig.privilegedPermissionAllowlistPackages: IndexedListSet<String> get() = IndexedListSet<String>().apply { this += "android" if (PackageManager.FEATURE_AUTOMOTIVE in availableFeatures) { // Note that SystemProperties.get(String, String) forces returning an empty string // even if we pass null for the def parameter. val carServicePackage = SystemProperties.get("ro.android.car.carservice.package") if (carServicePackage.isNotEmpty()) { this += carServicePackage } } } private val SystemConfig.implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>> get() = IndexedMap<String, IndexedListSet<String>>().apply { splitPermissions.forEach { splitPermissionInfo -> val sourcePermissionName = splitPermissionInfo.splitPermission splitPermissionInfo.newPermissions.forEach { implicitPermissionName -> getOrPut(implicitPermissionName) { IndexedListSet() } += sourcePermissionName } } } fun getDecision(subject: AccessUri, `object`: AccessUri): Int = getState { with(policy) { getDecision(subject, `object`) } Loading Loading @@ -151,10 +236,15 @@ class AccessCheckingService(context: Context) : SystemService(context) { Pair<Map<String, PackageState>, Map<String, PackageState>> get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates } internal inline fun <T> getState(action: GetStateScope.() -> T): T = GetStateScope(state).action() @OptIn(ExperimentalContracts::class) internal inline fun <T> getState(action: GetStateScope.() -> T): T { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } return GetStateScope(state).action() } @OptIn(ExperimentalContracts::class) internal inline fun mutateState(crossinline action: MutateStateScope.() -> Unit) { contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } synchronized(stateLock) { val oldState = state val newState = oldState.copy() Loading
services/permission/java/com/android/server/permission/access/AccessPolicy.kt +20 −1 Original line number Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.permission.access import android.util.Log import com.android.modules.utils.BinaryXmlPullParser import com.android.modules.utils.BinaryXmlSerializer import com.android.server.SystemConfig import com.android.server.permission.access.appop.PackageAppOpPolicy import com.android.server.permission.access.appop.UidAppOpPolicy import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports Loading Loading @@ -59,7 +60,12 @@ class AccessPolicy private constructor( userIds: IntSet, packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, permissionAllowlist: PermissionAllowlist knownPackages: IntMap<Array<String>>, isLeanback: Boolean, configPermissions: Map<String, SystemConfig.PermissionEntry>, privilegedPermissionAllowlistPackages: IndexedListSet<String>, permissionAllowlist: PermissionAllowlist, implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>> ) { state.systemState.apply { this.userIds += userIds Loading @@ -69,7 +75,12 @@ class AccessPolicy private constructor( appIds.getOrPut(packageState.appId) { IndexedListSet() } .add(packageState.packageName) } this.knownPackages = knownPackages this.isLeanback = isLeanback this.configPermissions = configPermissions this.privilegedPermissionAllowlistPackages = privilegedPermissionAllowlistPackages this.permissionAllowlist = permissionAllowlist this.implicitToSourcePermissions = implicitToSourcePermissions } } Loading @@ -79,6 +90,12 @@ class AccessPolicy private constructor( } } fun MutateStateScope.onInitialized() { forEachSchemePolicy { with(it) { onInitialized() } } } fun MutateStateScope.onUserAdded(userId: Int) { newState.systemState.userIds += userId newState.userStates[userId] = UserState() Loading Loading @@ -292,6 +309,8 @@ abstract class SchemePolicy { open fun GetStateScope.onStateMutated() {} open fun MutateStateScope.onInitialized() {} open fun MutateStateScope.onUserAdded(userId: Int) {} open fun MutateStateScope.onUserRemoved(userId: Int) {} Loading
services/permission/java/com/android/server/permission/access/AccessState.kt +14 −11 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ package com.android.server.permission.access import android.content.pm.PermissionGroupInfo import com.android.server.SystemConfig import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.permission.Permission import com.android.server.pm.permission.PermissionAllowlist Loading @@ -42,15 +43,15 @@ class SystemState private constructor( var packageStates: Map<String, PackageState>, var disabledSystemPackageStates: Map<String, PackageState>, val appIds: IntMap<IndexedListSet<String>>, // A map of KnownPackagesInt to a set of known package names val knownPackages: IntMap<IndexedListSet<String>>, // A map of userId to packageName val deviceAndProfileOwners: IntMap<String>, // Whether the device supports leanback UI // Mapping from KnownPackages keys to package names. var knownPackages: IntMap<Array<String>>, var isLeanback: Boolean, val privilegedPermissionAllowlistSourcePackageNames: IndexedListSet<String>, var configPermissions: Map<String, SystemConfig.PermissionEntry>, var privilegedPermissionAllowlistPackages: IndexedListSet<String>, var permissionAllowlist: PermissionAllowlist, val implicitToSourcePermissions: Map<String, Set<String>>, var implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>, // Mapping from user ID to package name. var deviceAndProfileOwners: IntMap<String>, val permissionGroups: IndexedMap<String, PermissionGroupInfo>, val permissionTrees: IndexedMap<String, Permission>, val permissions: IndexedMap<String, Permission> Loading @@ -61,11 +62,12 @@ class SystemState private constructor( emptyMap(), IntMap(), IntMap(), IntMap(), false, emptyMap(), IndexedListSet(), PermissionAllowlist(), IndexedMap(), IntMap(), IndexedMap(), IndexedMap(), IndexedMap() Loading @@ -77,12 +79,13 @@ class SystemState private constructor( packageStates, disabledSystemPackageStates, appIds.copy { it.copy() }, knownPackages.copy { it.copy() }, deviceAndProfileOwners.copy { it }, knownPackages, isLeanback, privilegedPermissionAllowlistSourcePackageNames.copy(), configPermissions, privilegedPermissionAllowlistPackages, permissionAllowlist, implicitToSourcePermissions, deviceAndProfileOwners, permissionGroups.copy { it }, permissionTrees.copy { it }, permissions.copy { it } Loading
services/permission/java/com/android/server/permission/access/permission/Permission.kt +64 −49 Original line number Diff line number Diff line Loading @@ -17,13 +17,18 @@ package com.android.server.permission.access.permission import android.content.pm.PermissionInfo import android.os.UserHandle import com.android.server.permission.access.util.hasBits import libcore.util.EmptyArray data class Permission( val permissionInfo: PermissionInfo, val isReconciled: Boolean, val type: Int, val appId: Int val appId: Int, @Suppress("ArrayInDataClass") val gids: IntArray = EmptyArray.INT, val areGidsPerUser: Boolean = false ) { inline val name: String get() = permissionInfo.name Loading @@ -37,36 +42,50 @@ data class Permission( inline val isDynamic: Boolean get() = type == TYPE_DYNAMIC inline val protectionLevel: Int @Suppress("DEPRECATION") get() = permissionInfo.protectionLevel inline val isInternal: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_INTERNAL inline val isNormal: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_NORMAL inline val isRuntime: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_DANGEROUS inline val isAppOp: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_FLAG_APPOP inline val isRemoved: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_REMOVED) inline val isSignature: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_SIGNATURE inline val isSoftRestricted: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_SOFT_RESTRICTED) inline val isAppOp: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_APPOP) inline val isHardRestricted: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_HARD_RESTRICTED) inline val isAppPredictor: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) inline val isSignature: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_SIGNATURE inline val isCompanion: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_COMPANION) inline val isInternal: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_INTERNAL inline val isConfigurator: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) inline val isDevelopment: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) inline val isIncidentReportApprover: Boolean get() = permissionInfo.protectionFlags .hasBits(PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) inline val isInstaller: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_INSTALLER) inline val isInstant: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_INSTANT) inline val isKnownSigner: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER) inline val isOem: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_OEM) Loading @@ -79,54 +98,53 @@ data class Permission( inline val isPrivileged: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_PRIVILEGED) inline val isSetup: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_SETUP) inline val isRecents: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RECENTS) inline val isVerifier: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_VERIFIER) inline val isRetailDemo: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) inline val isVendorPrivileged: Boolean get() = permissionInfo.protectionFlags .hasBits(PROTECTION_FLAG_VENDOR_PRIVILEGED) inline val isRole: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_ROLE) inline val isRuntimeOnly: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) inline val isSetup: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_SETUP) inline val isSystemTextClassifier: Boolean get() = permissionInfo.protectionFlags .hasBits(PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) inline val isConfigurator: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) inline val isIncidentReportApprover: Boolean inline val isVendorPrivileged: Boolean get() = permissionInfo.protectionFlags .hasBits(PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) inline val isAppPredictor: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) .hasBits(PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) inline val isCompanion: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_COMPANION) inline val isVerifier: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_VERIFIER) inline val isRetailDemo: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) inline val isHardRestricted: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_HARD_RESTRICTED) inline val isRecents: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RECENTS) inline val isRemoved: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_REMOVED) inline val isRole: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_ROLE) inline val isSoftRestricted: Boolean get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_SOFT_RESTRICTED) inline val isKnownSigner: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER) inline val knownCerts: Set<String> get() = permissionInfo.knownCerts inline val hasGids: Boolean get() = throw NotImplementedError() get() = gids.isNotEmpty() inline val protectionLevel: Int @Suppress("DEPRECATION") get() = permissionInfo.protectionLevel inline val knownCerts: Set<String> get() = permissionInfo.knownCerts fun getGidsForUser(userId: Int): IntArray = if (areGidsPerUser) { IntArray(gids.size) { i -> UserHandle.getUid(userId, gids[i]) } } else { gids.clone() } companion object { // The permission is defined in an application manifest. Loading @@ -135,8 +153,5 @@ data class Permission( const val TYPE_CONFIG = 1 // The permission is defined dynamically. const val TYPE_DYNAMIC = 2 // TODO: PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED is a testApi const val PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000 } }
services/permission/java/com/android/server/permission/access/permission/PermissionService.kt +42 −16 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.os.UserHandle import android.permission.IOnPermissionsChangeListener import android.permission.PermissionManager import android.provider.Settings import android.util.IntArray as GrowingIntArray import android.util.Log import com.android.internal.compat.IPlatformCompat import com.android.server.FgThread Loading @@ -61,6 +62,7 @@ import com.android.server.pm.permission.LegacyPermissionState import com.android.server.pm.permission.PermissionManagerServiceInterface import com.android.server.pm.permission.PermissionManagerServiceInternal import com.android.server.pm.pkg.AndroidPackage import libcore.util.EmptyArray import java.io.FileDescriptor import java.io.PrintWriter Loading @@ -77,6 +79,7 @@ class PermissionService( private lateinit var packageManagerInternal: PackageManagerInternal private lateinit var packageManagerLocal: PackageManagerLocal private lateinit var platformCompat: IPlatformCompat private lateinit var systemConfig: SystemConfig private lateinit var userManagerService: UserManagerService private val mountedStorageVolumes = IndexedSet<String?>() Loading @@ -94,6 +97,7 @@ class PermissionService( platformCompat = IPlatformCompat.Stub.asInterface( ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE) ) systemConfig = SystemConfig.getInstance() userManagerService = UserManagerService.getInstance() handlerThread = ServiceThread(LOG_TAG, Process.THREAD_PRIORITY_BACKGROUND, true) Loading Loading @@ -263,7 +267,10 @@ class PermissionService( } override fun getPermissionGids(permissionName: String, userId: Int): IntArray { TODO("Not yet implemented") val permission = service.getState { with(policy) { getPermissions()[permissionName] } } ?: return EmptyArray.INT return permission.getGidsForUser(userId) } override fun addPermission(permissionInfo: PermissionInfo, async: Boolean): Boolean { Loading @@ -286,6 +293,29 @@ class PermissionService( TODO("Not yet implemented") } override fun getGidsForUid(uid: Int): IntArray { val appId = UserHandle.getAppId(uid) val userId = UserHandle.getUserId(uid) val permissionFlags = service.getState { with(policy) { getUidPermissionFlags(appId, userId) } } ?: return EmptyArray.INT val gids = GrowingIntArray.wrap(systemConfig.globalGids) permissionFlags.forEachIndexed { _, permissionName, flags -> if (!PermissionFlags.isPermissionGranted(flags)) { return@forEachIndexed } val permission = service.getState { with(policy) { getPermissions()[permissionName] } } ?: return@forEachIndexed val permissionGids = permission.getGidsForUser(userId) if (permissionGids.isEmpty()) { return@forEachIndexed } gids.addAll(permissionGids) } return gids.toArray() } override fun grantRuntimePermission(packageName: String, permissionName: String, userId: Int) { TODO("Not yet implemented") } Loading @@ -306,14 +336,6 @@ class PermissionService( TODO("Not yet implemented") } override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { onPermissionsChangeListeners.addListener(listener) } override fun removeOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { onPermissionsChangeListeners.removeListener(listener) } override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int { // TODO: Implement permission checks. val appId = 0 Loading Loading @@ -493,21 +515,29 @@ class PermissionService( TODO("Not yet implemented") } override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { onPermissionsChangeListeners.addListener(listener) } override fun removeOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { onPermissionsChangeListeners.removeListener(listener) } override fun addOnRuntimePermissionStateChangedListener( listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener ) { TODO("Not yet implemented") // TODO: Should be removed once we remove PermissionPolicyService. } override fun removeOnRuntimePermissionStateChangedListener( listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener ) { TODO("Not yet implemented") // TODO: Should be removed once we remove PermissionPolicyService. } override fun getSplitPermissions(): List<SplitPermissionInfoParcelable> { return PermissionManager.splitPermissionInfoListToParcelableList( SystemConfig.getInstance().splitPermissions systemConfig.splitPermissions ) } Loading @@ -534,10 +564,6 @@ class PermissionService( return appOpPermissionPackageNames } override fun getGidsForUid(uid: Int): IntArray { TODO("Not yet implemented") } override fun backupRuntimePermissions(userId: Int): ByteArray? { TODO("Not yet implemented") } Loading