Merge "Add ModernPermissionManagerServiceImpl skeleton and two methods."

This commit is contained in:
Hai Zhang
2022-12-06 04:56:06 +00:00
committed by Android (Google) Code Review
15 changed files with 696 additions and 261 deletions

View File

@@ -467,7 +467,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@Override
public PermissionInfo getPermissionInfo(String permissionName, String packageName, int flags) {
return mPermissionManagerServiceImpl.getPermissionInfo(permissionName, packageName, flags);
return mPermissionManagerServiceImpl.getPermissionInfo(permissionName, flags, packageName);
}
@Override
@@ -792,14 +792,14 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@NonNull
@Override
public ArrayList<PermissionInfo> getAllPermissionsWithProtection(
public List<PermissionInfo> getAllPermissionsWithProtection(
@PermissionInfo.Protection int protection) {
return mPermissionManagerServiceImpl.getAllPermissionsWithProtection(protection);
}
@NonNull
@Override
public ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
public List<PermissionInfo> getAllPermissionsWithProtectionFlags(
@PermissionInfo.ProtectionFlags int protectionFlags) {
return mPermissionManagerServiceImpl
.getAllPermissionsWithProtectionFlags(protectionFlags);

View File

@@ -559,8 +559,8 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
@Override
@Nullable
public PermissionInfo getPermissionInfo(@NonNull String permName, @NonNull String opPackageName,
@PackageManager.PermissionInfoFlags int flags) {
public PermissionInfo getPermissionInfo(@NonNull String permName,
@PackageManager.PermissionInfoFlags int flags, @NonNull String opPackageName) {
final int callingUid = Binder.getCallingUid();
if (mPackageManagerInt.getInstantAppPackageName(callingUid) != null) {
return null;
@@ -2127,7 +2127,7 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
for (int i = 0; i < numRequestedPermissions; i++) {
PermissionInfo permInfo = getPermissionInfo(
newPackage.getRequestedPermissions().get(i),
newPackage.getPackageName(), 0);
0, newPackage.getPackageName());
if (permInfo == null) {
continue;
}
@@ -5204,9 +5204,9 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
@NonNull
@Override
public ArrayList<PermissionInfo> getAllPermissionsWithProtection(
public List<PermissionInfo> getAllPermissionsWithProtection(
@PermissionInfo.Protection int protection) {
ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
List<PermissionInfo> matchingPermissions = new ArrayList<>();
synchronized (mLock) {
for (final Permission permission : mRegistry.getPermissions()) {
@@ -5221,9 +5221,9 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
@NonNull
@Override
public ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
public List<PermissionInfo> getAllPermissionsWithProtectionFlags(
@PermissionInfo.ProtectionFlags int protectionFlags) {
ArrayList<PermissionInfo> matchingPermissions = new ArrayList<>();
List<PermissionInfo> matchingPermissions = new ArrayList<>();
synchronized (mLock) {
for (final Permission permission : mRegistry.getPermissions()) {

View File

@@ -32,7 +32,6 @@ import com.android.server.pm.pkg.AndroidPackage;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -77,8 +76,8 @@ public interface PermissionManagerServiceInterface extends PermissionManagerInte
* @return a {@link PermissionInfo} containing information about the permission, or {@code null}
* if not found
*/
PermissionInfo getPermissionInfo(@NonNull String permName, @NonNull String opPackageName,
@PackageManager.PermissionInfoFlags int flags);
PermissionInfo getPermissionInfo(@NonNull String permName,
@PackageManager.PermissionInfoFlags int flags, @NonNull String opPackageName);
/**
* Query for all of the permissions associated with a particular group.
@@ -487,11 +486,11 @@ public interface PermissionManagerServiceInterface extends PermissionManagerInte
/** Get all permissions that have a certain protection */
@NonNull
ArrayList<PermissionInfo> getAllPermissionsWithProtection(
List<PermissionInfo> getAllPermissionsWithProtection(
@PermissionInfo.Protection int protection);
/** Get all permissions that have certain protection flags */
@NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
@NonNull List<PermissionInfo> getAllPermissionsWithProtectionFlags(
@PermissionInfo.ProtectionFlags int protectionFlags);
/**

View File

@@ -164,11 +164,12 @@ public interface PermissionManagerServiceInternal extends PermissionManagerInter
/** Get all permissions that have a certain protection */
@NonNull
ArrayList<PermissionInfo> getAllPermissionsWithProtection(
List<PermissionInfo> getAllPermissionsWithProtection(
@PermissionInfo.Protection int protection);
/** Get all permissions that have certain protection flags */
@NonNull ArrayList<PermissionInfo> getAllPermissionsWithProtectionFlags(
/** Get all permissions that have certain protection flags
* @return*/
@NonNull List<PermissionInfo> getAllPermissionsWithProtectionFlags(
@PermissionInfo.ProtectionFlags int protectionFlags);
/**

View File

@@ -232,7 +232,7 @@ public final class PermissionPolicyService extends SystemService {
}
};
final ArrayList<PermissionInfo> dangerousPerms =
final List<PermissionInfo> dangerousPerms =
mPermissionManagerInternal.getAllPermissionsWithProtection(
PermissionInfo.PROTECTION_DANGEROUS);
try {

View File

@@ -29,6 +29,8 @@ java_library_static {
],
static_libs: [
"kotlin-stdlib",
// Adds reflection-less suppressed exceptions and AutoCloseable.use().
"kotlin-stdlib-jdk7",
],
jarjar_rules: "jarjar-rules.txt",
kotlincflags: [

View File

@@ -40,46 +40,53 @@ class AccessCheckingService {
}
fun getDecision(subject: AccessUri, `object`: AccessUri): Int =
policy.getDecision(subject, `object`, state)
getState {
with(policy) { getDecision(subject, `object`) }
}
fun setDecision(subject: AccessUri, `object`: AccessUri, decision: Int) {
mutateState { oldState, newState ->
policy.setDecision(subject, `object`, decision, oldState, newState)
mutateState {
with(policy) { setDecision(subject, `object`, decision) }
}
}
fun onUserAdded(userId: Int) {
mutateState { oldState, newState ->
policy.onUserAdded(userId, oldState, newState)
mutateState {
with(policy) { onUserAdded(userId) }
}
}
fun onUserRemoved(userId: Int) {
mutateState { oldState, newState ->
policy.onUserRemoved(userId, oldState, newState)
mutateState {
with(policy) { onUserRemoved(userId) }
}
}
fun onPackageAdded(packageState: PackageState) {
mutateState { oldState, newState ->
policy.onPackageAdded(packageState, oldState, newState)
mutateState {
with(policy) { onPackageAdded(packageState) }
}
}
fun onPackageRemoved(packageState: PackageState) {
mutateState { oldState, newState ->
policy.onPackageRemoved(packageState, oldState, newState)
mutateState {
with(policy) { onPackageRemoved(packageState) }
}
}
// TODO: Replace (oldState, newState) with Kotlin context receiver once it's stabilized.
private inline fun mutateState(action: (oldState: AccessState, newState: AccessState) -> Unit) {
internal inline fun <T> getState(action: GetStateScope.() -> T): T =
GetStateScope(state).action()
internal inline fun mutateState(action: MutateStateScope.() -> Unit) {
synchronized(stateLock) {
val oldState = state
val newState = oldState.copy()
action(oldState, newState)
MutateStateScope(oldState, newState).action()
persistence.write(newState)
state = newState
}
}
internal fun getSchemePolicy(subjectScheme: String, objectScheme: String): SchemePolicy =
policy.getSchemePolicy(subjectScheme, objectScheme)
}

View File

@@ -44,13 +44,13 @@ class AccessPersistence(
systemFile.parse {
// This is the canonical way to call an extension function in a different class.
// TODO(b/259469752): Use context receiver for this when it becomes stable.
with(policy) { this@parse.parseSystemState(systemState) }
with(policy) { parseSystemState(systemState) }
}
}
private fun readUserState(userId: Int, userState: UserState) {
getUserFile(userId).parse {
with(policy) { this@parse.parseUserState(userId, userState) }
with(policy) { parseUserState(userId, userState) }
}
}
@@ -82,13 +82,13 @@ class AccessPersistence(
private fun writeSystemState(systemState: SystemState) {
systemFile.serialize {
with(policy) { this@serialize.serializeSystemState(systemState) }
with(policy) { serializeSystemState(systemState) }
}
}
private fun writeUserState(userId: Int, userState: UserState) {
getUserFile(userId).serialize {
with(policy) { this@serialize.serializeUserState(userId, userState) }
with(policy) { serializeUserState(userId, userState) }
}
}

View File

@@ -41,38 +41,35 @@ class AccessPolicy private constructor(
}
)
fun getDecision(subject: AccessUri, `object`: AccessUri, state: AccessState): Int =
getSchemePolicy(subject, `object`).getDecision(subject, `object`, state)
fun setDecision(
subject: AccessUri,
`object`: AccessUri,
decision: Int,
oldState: AccessState,
newState: AccessState
) {
getSchemePolicy(subject, `object`)
.setDecision(subject, `object`, decision, oldState, newState)
}
private fun getSchemePolicy(subject: AccessUri, `object`: AccessUri): SchemePolicy =
checkNotNull(schemePolicies[subject.scheme]?.get(`object`.scheme)) {
"Scheme policy for subject=$subject object=$`object` does not exist"
fun getSchemePolicy(subjectScheme: String, objectScheme: String): SchemePolicy =
checkNotNull(schemePolicies[subjectScheme]?.get(objectScheme)) {
"Scheme policy for $subjectScheme and $objectScheme does not exist"
}
fun onUserAdded(userId: Int, oldState: AccessState, newState: AccessState) {
fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int =
with(getSchemePolicy(subject, `object`)){ getDecision(subject, `object`) }
fun MutateStateScope.setDecision(subject: AccessUri, `object`: AccessUri, decision: Int) {
with(getSchemePolicy(subject, `object`)) { setDecision(subject, `object`, decision) }
}
fun MutateStateScope.onUserAdded(userId: Int) {
newState.systemState.userIds += userId
newState.userStates[userId] = UserState()
forEachSchemePolicy { it.onUserAdded(userId, oldState, newState) }
forEachSchemePolicy {
with(it) { onUserAdded(userId) }
}
}
fun onUserRemoved(userId: Int, oldState: AccessState, newState: AccessState) {
fun MutateStateScope.onUserRemoved(userId: Int) {
newState.systemState.userIds -= userId
newState.userStates -= userId
forEachSchemePolicy { it.onUserRemoved(userId, oldState, newState) }
forEachSchemePolicy {
with(it) { onUserRemoved(userId) }
}
}
fun onPackageAdded(packageState: PackageState, oldState: AccessState, newState: AccessState) {
fun MutateStateScope.onPackageAdded(packageState: PackageState) {
var isAppIdAdded = false
newState.systemState.apply {
packageStates[packageState.packageName] = packageState
@@ -82,12 +79,16 @@ class AccessPolicy private constructor(
}.add(packageState.packageName)
}
if (isAppIdAdded) {
forEachSchemePolicy { it.onAppIdAdded(packageState.appId, oldState, newState) }
forEachSchemePolicy {
with(it) { onAppIdAdded(packageState.appId) }
}
}
forEachSchemePolicy {
with(it) { onPackageAdded(packageState) }
}
forEachSchemePolicy { it.onPackageAdded(packageState, oldState, newState) }
}
fun onPackageRemoved(packageState: PackageState, oldState: AccessState, newState: AccessState) {
fun MutateStateScope.onPackageRemoved(packageState: PackageState) {
var isAppIdRemoved = false
newState.systemState.apply {
packageStates -= packageState.packageName
@@ -101,9 +102,13 @@ class AccessPolicy private constructor(
}
}
}
forEachSchemePolicy { it.onPackageRemoved(packageState, oldState, newState) }
forEachSchemePolicy {
with(it) { onPackageRemoved(packageState) }
}
if (isAppIdRemoved) {
forEachSchemePolicy { it.onAppIdRemoved(packageState.appId, oldState, newState) }
forEachSchemePolicy {
with(it) { onAppIdRemoved(packageState.appId) }
}
}
}
@@ -113,7 +118,7 @@ class AccessPolicy private constructor(
TAG_ACCESS -> {
forEachTag {
forEachSchemePolicy {
with(it) { this@parseSystemState.parseSystemState(systemState) }
with(it) { parseSystemState(systemState) }
}
}
}
@@ -125,7 +130,7 @@ class AccessPolicy private constructor(
fun BinaryXmlSerializer.serializeSystemState(systemState: SystemState) {
tag(TAG_ACCESS) {
forEachSchemePolicy {
with(it) { this@serializeSystemState.serializeSystemState(systemState) }
with(it) { serializeSystemState(systemState) }
}
}
}
@@ -136,7 +141,7 @@ class AccessPolicy private constructor(
TAG_ACCESS -> {
forEachTag {
forEachSchemePolicy {
with(it) { this@parseUserState.parseUserState(userId, userState) }
with(it) { parseUserState(userId, userState) }
}
}
}
@@ -153,11 +158,14 @@ class AccessPolicy private constructor(
fun BinaryXmlSerializer.serializeUserState(userId: Int, userState: UserState) {
tag(TAG_ACCESS) {
forEachSchemePolicy {
with(it) { this@serializeUserState.serializeUserState(userId, userState) }
with(it) { serializeUserState(userId, userState) }
}
}
}
private fun getSchemePolicy(subject: AccessUri, `object`: AccessUri): SchemePolicy =
getSchemePolicy(subject.scheme, `object`.scheme)
private inline fun forEachSchemePolicy(action: (SchemePolicy) -> Unit) {
schemePolicies.forEachValueIndexed { _, objectSchemePolicies ->
objectSchemePolicies.forEachValueIndexed { _, schemePolicy ->
@@ -182,14 +190,12 @@ abstract class SchemePolicy {
abstract val objectScheme: String
abstract fun getDecision(subject: AccessUri, `object`: AccessUri, state: AccessState): Int
abstract fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int
abstract fun setDecision(
abstract fun MutateStateScope.setDecision(
subject: AccessUri,
`object`: AccessUri,
decision: Int,
oldState: AccessState,
newState: AccessState
decision: Int
)
fun addOnDecisionChangedListener(listener: OnDecisionChangedListener) {
@@ -216,25 +222,17 @@ abstract class SchemePolicy {
}
}
open fun onUserAdded(userId: Int, oldState: AccessState, newState: AccessState) {}
open fun MutateStateScope.onUserAdded(userId: Int) {}
open fun onUserRemoved(userId: Int, oldState: AccessState, newState: AccessState) {}
open fun MutateStateScope.onUserRemoved(userId: Int) {}
open fun onAppIdAdded(appId: Int, oldState: AccessState, newState: AccessState) {}
open fun MutateStateScope.onAppIdAdded(appId: Int) {}
open fun onAppIdRemoved(appId: Int, oldState: AccessState, newState: AccessState) {}
open fun MutateStateScope.onAppIdRemoved(appId: Int) {}
open fun onPackageAdded(
packageState: PackageState,
oldState: AccessState,
newState: AccessState
) {}
open fun MutateStateScope.onPackageAdded(packageState: PackageState) {}
open fun onPackageRemoved(
packageState: PackageState,
oldState: AccessState,
newState: AccessState
) {}
open fun MutateStateScope.onPackageRemoved(packageState: PackageState) {}
open fun BinaryXmlPullParser.parseSystemState(systemState: SystemState) {}

View File

@@ -124,3 +124,12 @@ abstract class WritableState {
}
}
}
class GetStateScope(
val state: AccessState
)
class MutateStateScope(
val oldState: AccessState,
val newState: AccessState
)

View File

@@ -19,44 +19,43 @@ package com.android.server.permission.access.appop
import android.app.AppOpsManager
import com.android.modules.utils.BinaryXmlPullParser
import com.android.modules.utils.BinaryXmlSerializer
import com.android.server.permission.access.AccessState
import com.android.server.permission.access.AccessUri
import com.android.server.permission.access.AppOpUri
import com.android.server.permission.access.GetStateScope
import com.android.server.permission.access.MutateStateScope
import com.android.server.permission.access.SchemePolicy
import com.android.server.permission.access.UserState
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
abstract class BaseAppOpPolicy(private val persistence: BaseAppOpPersistence) : SchemePolicy() {
override fun getDecision(subject: AccessUri, `object`: AccessUri, state: AccessState): Int {
override fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int {
`object` as AppOpUri
return getModes(subject, state)
return getModes(subject)
.getWithDefault(`object`.appOpName, opToDefaultMode(`object`.appOpName))
}
override fun setDecision(
override fun MutateStateScope.setDecision(
subject: AccessUri,
`object`: AccessUri,
decision: Int,
oldState: AccessState,
newState: AccessState
decision: Int
) {
`object` as AppOpUri
val modes = getOrCreateModes(subject, newState)
val modes = getOrCreateModes(subject)
val oldMode = modes.putWithDefault(`object`.appOpName, decision,
opToDefaultMode(`object`.appOpName))
if (modes.isEmpty()) {
removeModes(subject, newState)
removeModes(subject)
}
if (oldMode != decision) {
notifyOnDecisionChangedListeners(subject, `object`, oldMode, decision)
}
}
abstract fun getModes(subject: AccessUri, state: AccessState): IndexedMap<String, Int>?
abstract fun GetStateScope.getModes(subject: AccessUri): IndexedMap<String, Int>?
abstract fun getOrCreateModes(subject: AccessUri, state: AccessState): IndexedMap<String, Int>
abstract fun MutateStateScope.getOrCreateModes(subject: AccessUri): IndexedMap<String, Int>
abstract fun removeModes(subject: AccessUri, state: AccessState)
abstract fun MutateStateScope.removeModes(subject: AccessUri)
// TODO need to check that [AppOpsManager.getSystemAlertWindowDefault] works; likely no issue
// since running in system process.

View File

@@ -16,9 +16,10 @@
package com.android.server.permission.access.appop
import com.android.server.permission.access.AccessState
import com.android.server.permission.access.AccessUri
import com.android.server.permission.access.AppOpUri
import com.android.server.permission.access.GetStateScope
import com.android.server.permission.access.MutateStateScope
import com.android.server.permission.access.PackageUri
import com.android.server.permission.access.UserState
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
@@ -31,27 +32,23 @@ class PackageAppOpPolicy : BaseAppOpPolicy(PackageAppOpPersistence()) {
override val objectScheme: String
get() = AppOpUri.SCHEME
override fun getModes(subject: AccessUri, state: AccessState): IndexedMap<String, Int>? {
override fun GetStateScope.getModes(subject: AccessUri): IndexedMap<String, Int>? {
subject as PackageUri
return state.userStates[subject.userId]?.packageAppOpModes?.get(subject.packageName)
}
override fun getOrCreateModes(subject: AccessUri, state: AccessState): IndexedMap<String, Int> {
override fun MutateStateScope.getOrCreateModes(subject: AccessUri): IndexedMap<String, Int> {
subject as PackageUri
return state.userStates.getOrPut(subject.userId) { UserState() }
return newState.userStates.getOrPut(subject.userId) { UserState() }
.packageAppOpModes.getOrPut(subject.packageName) { IndexedMap() }
}
override fun removeModes(subject: AccessUri, state: AccessState) {
override fun MutateStateScope.removeModes(subject: AccessUri) {
subject as PackageUri
state.userStates[subject.userId]?.packageAppOpModes?.remove(subject.packageName)
newState.userStates[subject.userId]?.packageAppOpModes?.remove(subject.packageName)
}
override fun onPackageRemoved(
packageState: PackageState,
oldState: AccessState,
newState: AccessState
) {
override fun MutateStateScope.onPackageRemoved(packageState: PackageState) {
newState.userStates.forEachIndexed { _, _, userState ->
userState.packageAppOpModes -= packageState.packageName
}

View File

@@ -16,9 +16,10 @@
package com.android.server.permission.access.appop
import com.android.server.permission.access.AccessState
import com.android.server.permission.access.AccessUri
import com.android.server.permission.access.AppOpUri
import com.android.server.permission.access.GetStateScope
import com.android.server.permission.access.MutateStateScope
import com.android.server.permission.access.UidUri
import com.android.server.permission.access.UserState
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
@@ -30,23 +31,23 @@ class UidAppOpPolicy : BaseAppOpPolicy(UidAppOpPersistence()) {
override val objectScheme: String
get() = AppOpUri.SCHEME
override fun getModes(subject: AccessUri, state: AccessState): IndexedMap<String, Int>? {
override fun GetStateScope.getModes(subject: AccessUri): IndexedMap<String, Int>? {
subject as UidUri
return state.userStates[subject.userId]?.uidAppOpModes?.get(subject.appId)
}
override fun getOrCreateModes(subject: AccessUri, state: AccessState): IndexedMap<String, Int> {
override fun MutateStateScope.getOrCreateModes(subject: AccessUri): IndexedMap<String, Int> {
subject as UidUri
return state.userStates.getOrPut(subject.userId) { UserState() }
return newState.userStates.getOrPut(subject.userId) { UserState() }
.uidAppOpModes.getOrPut(subject.appId) { IndexedMap() }
}
override fun removeModes(subject: AccessUri, state: AccessState) {
override fun MutateStateScope.removeModes(subject: AccessUri) {
subject as UidUri
state.userStates[subject.userId]?.uidAppOpModes?.remove(subject.appId)
newState.userStates[subject.userId]?.uidAppOpModes?.remove(subject.appId)
}
override fun onAppIdRemoved(appId: Int, oldState: AccessState, newState: AccessState) {
override fun MutateStateScope.onAppIdRemoved(appId: Int) {
newState.userStates.forEachIndexed { _, _, userState ->
userState.uidAppOpModes -= appId
}

View File

@@ -0,0 +1,456 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server.permission.access.permission
import android.content.pm.PackageManager
import android.content.pm.PackageManagerInternal
import android.content.pm.PermissionGroupInfo
import android.content.pm.PermissionInfo
import android.content.pm.permission.SplitPermissionInfoParcelable
import android.os.Binder
import android.os.Build
import android.os.Process
import android.os.UserHandle
import android.permission.IOnPermissionsChangeListener
import com.android.server.LocalManagerRegistry
import com.android.server.LocalServices
import com.android.server.pm.PackageManagerLocal
import com.android.server.pm.permission.PermissionManagerServiceInterface
import com.android.server.permission.access.AccessCheckingService
import com.android.server.permission.access.PermissionUri
import com.android.server.permission.access.UidUri
import com.android.server.permission.access.data.Permission
import com.android.server.permission.access.util.hasBits
import com.android.server.pm.permission.LegacyPermission
import com.android.server.pm.permission.LegacyPermissionSettings
import com.android.server.pm.permission.LegacyPermissionState
import com.android.server.pm.permission.PermissionManagerServiceInternal
import com.android.server.pm.pkg.AndroidPackage
import java.io.FileDescriptor
import java.io.PrintWriter
/**
* Modern implementation of [PermissionManagerServiceInterface].
*/
class ModernPermissionManagerServiceImpl(
private val service: AccessCheckingService
) : PermissionManagerServiceInterface {
private val policy =
service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as UidPermissionPolicy
private val packageManagerInternal =
LocalServices.getService(PackageManagerInternal::class.java)
private val packageManagerLocal =
LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java)
override fun getAllPermissionGroups(flags: Int): List<PermissionGroupInfo> {
TODO("Not yet implemented")
}
override fun getPermissionGroupInfo(
permissionGroupName: String,
flags: Int
): PermissionGroupInfo? {
val permissionGroup: PermissionGroupInfo
packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
val callingUid = Binder.getCallingUid()
if (snapshot.isUidInstantApp(callingUid)) {
return null
}
permissionGroup = service.getState {
with(policy) { getPermissionGroup(permissionGroupName) }
} ?: return null
val isPermissionGroupVisible =
snapshot.isPackageVisibleToUid(permissionGroup.packageName, callingUid)
if (!isPermissionGroupVisible) {
return null
}
}
return permissionGroup.generatePermissionGroupInfo(flags)
}
/**
* Generate a new [PermissionGroupInfo] from [PermissionGroupInfo] and adjust it accordingly.
*/
private fun PermissionGroupInfo.generatePermissionGroupInfo(flags: Int): PermissionGroupInfo =
@Suppress("DEPRECATION")
PermissionGroupInfo(this).apply {
if (!flags.hasBits(PackageManager.GET_META_DATA)) {
metaData = null
}
}
override fun getPermissionInfo(
permissionName: String,
flags: Int,
opPackageName: String
): PermissionInfo? {
val permission: Permission
val targetSdkVersion: Int
packageManagerLocal.withUnfilteredSnapshot().use { snapshot ->
val callingUid = Binder.getCallingUid()
if (snapshot.isUidInstantApp(callingUid)) {
return null
}
permission = service.getState {
with(policy) { getPermission(permissionName) }
} ?: return null
val isPermissionVisible =
snapshot.isPackageVisibleToUid(permission.packageName, callingUid)
if (!isPermissionVisible) {
return null
}
val callingAppId = UserHandle.getAppId(callingUid)
val opPackage = snapshot.packageStates[opPackageName]?.androidPackage
targetSdkVersion = when {
// System sees all flags.
callingAppId == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID ||
callingAppId == Process.SHELL_UID -> Build.VERSION_CODES.CUR_DEVELOPMENT
opPackage != null -> opPackage.targetSdkVersion
else -> Build.VERSION_CODES.CUR_DEVELOPMENT
}
}
return permission.generatePermissionInfo(flags, targetSdkVersion)
}
/**
* Generate a new [PermissionInfo] from [Permission] and adjust it accordingly.
*/
private fun Permission.generatePermissionInfo(
flags: Int,
targetSdkVersion: Int
): PermissionInfo =
@Suppress("DEPRECATION")
PermissionInfo(permissionInfo).apply {
if (!flags.hasBits(PackageManager.GET_META_DATA)) {
metaData = null
}
if (targetSdkVersion < Build.VERSION_CODES.O) {
val protection = protection
// Signature permission's protection flags are always reported.
if (protection != PermissionInfo.PROTECTION_SIGNATURE) {
protectionLevel = protection
}
}
}
override fun queryPermissionsByGroup(
permissionGroupName: String,
flags: Int
): List<PermissionInfo> {
TODO("Not yet implemented")
}
override fun getAllPermissionsWithProtection(protection: Int): List<PermissionInfo> {
TODO("Not yet implemented")
}
override fun getAllPermissionsWithProtectionFlags(protectionFlags: Int): List<PermissionInfo> {
TODO("Not yet implemented")
}
override fun getPermissionGids(permissionName: String, userId: Int): IntArray {
TODO("Not yet implemented")
}
override fun addPermission(permissionInfo: PermissionInfo, async: Boolean): Boolean {
TODO("Not yet implemented")
}
override fun removePermission(permissionName: String) {
TODO("Not yet implemented")
}
override fun checkPermission(packageName: String, permissionName: String, userId: Int): Int {
TODO("Not yet implemented")
}
override fun checkUidPermission(uid: Int, permissionName: String): Int {
TODO("Not yet implemented")
}
override fun getGrantedPermissions(packageName: String, userId: Int): Set<String> {
TODO("Not yet implemented")
}
override fun grantRuntimePermission(packageName: String, permissionName: String, userId: Int) {
TODO("Not yet implemented")
}
override fun revokeRuntimePermission(
packageName: String,
permissionName: String,
userId: Int,
reason: String?
) {
TODO("Not yet implemented")
}
override fun revokePostNotificationPermissionWithoutKillForTest(
packageName: String,
userId: Int
) {
TODO("Not yet implemented")
}
override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) {
TODO("Not yet implemented")
}
override fun removeOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) {
TODO("Not yet implemented")
}
override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int {
TODO("Not yet implemented")
}
override fun isPermissionRevokedByPolicy(
packageName: String,
permissionName: String,
userId: Int
): Boolean {
TODO("Not yet implemented")
}
override fun isPermissionsReviewRequired(packageName: String, userId: Int): Boolean {
TODO("Not yet implemented")
}
override fun shouldShowRequestPermissionRationale(
packageName: String,
permissionName: String,
userId: Int
): Boolean {
TODO("Not yet implemented")
}
override fun updatePermissionFlags(
packageName: String,
permissionName: String,
flagMask: Int,
flagValues: Int,
checkAdjustPolicyFlagPermission: Boolean,
userId: Int
) {
TODO("Not yet implemented")
}
override fun updatePermissionFlagsForAllApps(flagMask: Int, flagValues: Int, userId: Int) {
TODO("Not yet implemented")
}
override fun addAllowlistedRestrictedPermission(
packageName: String,
permissionName: String,
flags: Int,
userId: Int
): Boolean {
TODO("Not yet implemented")
}
override fun getAllowlistedRestrictedPermissions(
packageName: String,
flags: Int,
userId: Int
): MutableList<String> {
TODO("Not yet implemented")
}
override fun removeAllowlistedRestrictedPermission(
packageName: String,
permissionName: String,
flags: Int,
userId: Int
): Boolean {
TODO("Not yet implemented")
}
override fun resetRuntimePermissions(androidPackage: AndroidPackage, userId: Int) {
TODO("Not yet implemented")
}
override fun resetRuntimePermissionsForUser(userId: Int) {
TODO("Not yet implemented")
}
override fun addOnRuntimePermissionStateChangedListener(
listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener
) {
TODO("Not yet implemented")
}
override fun removeOnRuntimePermissionStateChangedListener(
listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener
) {
TODO("Not yet implemented")
}
override fun getSplitPermissions(): List<SplitPermissionInfoParcelable> {
TODO("Not yet implemented")
}
override fun getAppOpPermissionPackages(permissionName: String): Array<String> {
TODO("Not yet implemented")
}
override fun getAllAppOpPermissionPackages(): Map<String, Set<String>> {
TODO("Not yet implemented")
}
override fun getGidsForUid(uid: Int): IntArray {
TODO("Not yet implemented")
}
override fun backupRuntimePermissions(userId: Int): ByteArray? {
TODO("Not yet implemented")
}
override fun restoreRuntimePermissions(backup: ByteArray, userId: Int) {
TODO("Not yet implemented")
}
override fun restoreDelayedRuntimePermissions(packageName: String, userId: Int) {
TODO("Not yet implemented")
}
override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>?) {
TODO("Not yet implemented")
}
override fun getPermissionTEMP(
permissionName: String
): com.android.server.pm.permission.Permission? {
TODO("Not yet implemented")
}
override fun getLegacyPermissions(): List<LegacyPermission> {
TODO("Not yet implemented")
}
override fun readLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) {
TODO("Not yet implemented")
}
override fun writeLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) {
TODO("Not yet implemented")
}
override fun getLegacyPermissionState(appId: Int): LegacyPermissionState {
TODO("Not yet implemented")
}
override fun readLegacyPermissionStateTEMP() {
TODO("Not yet implemented")
}
override fun writeLegacyPermissionStateTEMP() {
TODO("Not yet implemented")
}
override fun onSystemReady() {
TODO("Not yet implemented")
}
override fun onUserCreated(userId: Int) {
TODO("Not yet implemented")
}
override fun onUserRemoved(userId: Int) {
TODO("Not yet implemented")
}
override fun onStorageVolumeMounted(volumeUuid: String, fingerprintChanged: Boolean) {
TODO("Not yet implemented")
}
override fun onPackageAdded(
androidPackage: AndroidPackage,
isInstantApp: Boolean,
oldPackage: AndroidPackage?
) {
TODO("Not yet implemented")
}
override fun onPackageInstalled(
androidPackage: AndroidPackage,
previousAppId: Int,
params: PermissionManagerServiceInternal.PackageInstalledParams,
userId: Int
) {
TODO("Not yet implemented")
}
override fun onPackageUninstalled(
packageName: String,
appId: Int,
androidPackage: AndroidPackage?,
sharedUserPkgs: MutableList<AndroidPackage>,
userId: Int
) {
TODO("Not yet implemented")
}
override fun onPackageRemoved(androidPackage: AndroidPackage) {
TODO("Not yet implemented")
}
/**
* Check whether a UID belongs to an instant app.
*/
private fun PackageManagerLocal.UnfilteredSnapshot.isUidInstantApp(uid: Int): Boolean {
if (Process.isIsolatedUid(uid)) {
// Unfortunately we don't have the API for getting the owner UID of an isolated UID yet,
// so for now we just keep calling the old API.
return packageManagerInternal.getInstantAppPackageName(uid) != null
}
val appId = UserHandle.getAppId(uid)
// Instant apps can't have shared UIDs, so we can just take the first package.
val firstPackageState = packageStates.values.firstOrNull { it.appId == appId }
?: return false
val userId = UserHandle.getUserId(uid)
return firstPackageState.getUserStateOrDefault(userId).isInstantApp
}
/**
* Check whether a package is visible to a UID within the same user as the UID.
*/
private fun PackageManagerLocal.UnfilteredSnapshot.isPackageVisibleToUid(
packageName: String,
uid: Int
): Boolean = isPackageVisibleToUid(packageName, UserHandle.getUserId(uid), uid)
/**
* Check whether a package in a particular user is visible to a UID.
*/
private fun PackageManagerLocal.UnfilteredSnapshot.isPackageVisibleToUid(
packageName: String,
userId: Int,
uid: Int
): Boolean {
val user = UserHandle.of(userId)
return filtered(uid, user).use { it.getPackageState(packageName) != null }
}
}

View File

@@ -18,6 +18,7 @@ package com.android.server.permission.access.permission
import android.Manifest
import android.content.pm.PackageManager
import android.content.pm.PermissionGroupInfo
import android.content.pm.PermissionInfo
import android.os.Build
import android.os.UserHandle
@@ -26,6 +27,8 @@ import com.android.modules.utils.BinaryXmlPullParser
import com.android.modules.utils.BinaryXmlSerializer
import com.android.server.permission.access.AccessState
import com.android.server.permission.access.AccessUri
import com.android.server.permission.access.GetStateScope
import com.android.server.permission.access.MutateStateScope
import com.android.server.permission.access.PermissionUri
import com.android.server.permission.access.SchemePolicy
import com.android.server.permission.access.SystemState
@@ -52,19 +55,17 @@ class UidPermissionPolicy : SchemePolicy() {
override val objectScheme: String
get() = PermissionUri.SCHEME
override fun getDecision(subject: AccessUri, `object`: AccessUri, state: AccessState): Int {
override fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int {
subject as UidUri
`object` as PermissionUri
return state.userStates[subject.userId]?.permissionFlags?.get(subject.appId)
?.get(`object`.permissionName) ?: 0
}
override fun setDecision(
override fun MutateStateScope.setDecision(
subject: AccessUri,
`object`: AccessUri,
decision: Int,
oldState: AccessState,
newState: AccessState
decision: Int
) {
subject as UidUri
`object` as PermissionUri
@@ -73,64 +74,58 @@ class UidPermissionPolicy : SchemePolicy() {
uidFlags[`object`.permissionName] = decision
}
override fun onUserAdded(userId: Int, oldState: AccessState, newState: AccessState) {
override fun MutateStateScope.onUserAdded(userId: Int) {
newState.systemState.packageStates.forEachValueIndexed { _, packageState ->
evaluateAllPermissionStatesForPackageAndUser(
packageState, null, userId, oldState, newState
)
grantImplicitPermissions(packageState, userId, oldState, newState)
evaluateAllPermissionStatesForPackageAndUser(packageState, null, userId)
grantImplicitPermissions(packageState, userId)
}
}
override fun onAppIdAdded(appId: Int, oldState: AccessState, newState: AccessState) {
override fun MutateStateScope.onAppIdAdded(appId: Int) {
newState.userStates.forEachIndexed { _, _, userState ->
userState.permissionFlags.getOrPut(appId) { IndexedMap() }
}
}
override fun onAppIdRemoved(appId: Int, oldState: AccessState, newState: AccessState) {
override fun MutateStateScope.onAppIdRemoved(appId: Int) {
newState.userStates.forEachIndexed { _, _, userState -> userState.permissionFlags -= appId }
}
override fun onPackageAdded(
packageState: PackageState,
oldState: AccessState,
newState: AccessState
) {
override fun MutateStateScope.onPackageAdded(packageState: PackageState) {
val changedPermissionNames = IndexedSet<String>()
adoptPermissions(packageState, changedPermissionNames, newState)
addPermissionGroups(packageState, newState)
addPermissions(packageState, changedPermissionNames, newState)
adoptPermissions(packageState, changedPermissionNames)
addPermissionGroups(packageState)
addPermissions(packageState, changedPermissionNames)
// TODO: revokeStoragePermissionsIfScopeExpandedInternal()
trimPermissions(packageState.packageName, newState)
changedPermissionNames.forEachIndexed { _, it ->
evaluatePermissionStateForAllPackages(it, packageState, oldState, newState)
trimPermissions(packageState.packageName)
changedPermissionNames.forEachIndexed { _, permissionName ->
evaluatePermissionStateForAllPackages(permissionName, packageState)
}
evaluateAllPermissionStatesForPackage(packageState, packageState, oldState, newState)
newState.systemState.userIds.forEachIndexed { _, it ->
grantImplicitPermissions(packageState, it, oldState, newState)
evaluateAllPermissionStatesForPackage(packageState, packageState)
newState.systemState.userIds.forEachIndexed { _, userId ->
grantImplicitPermissions(packageState, userId)
}
// TODO: add trimPermissionStates() here for removing the permission states that are
// no longer requested. (equivalent to revokeUnusedSharedUserPermissionsLocked())
}
private fun adoptPermissions(
private fun MutateStateScope.adoptPermissions(
packageState: PackageState,
changedPermissionNames: IndexedSet<String>,
newState: AccessState
changedPermissionNames: IndexedSet<String>
) {
val `package` = packageState.androidPackage!!
`package`.adoptPermissions.forEachIndexed { _, originalPackageName ->
val packageName = `package`.packageName
if (!canAdoptPermissions(packageName, originalPackageName, newState)) {
if (!canAdoptPermissions(packageName, originalPackageName)) {
return@forEachIndexed
}
newState.systemState.permissions.let { permissions ->
permissions.forEachIndexed { i, permissionName, oldPermission ->
permissions.forEachIndexed permissions@ {
permissionIndex, permissionName, oldPermission ->
if (oldPermission.packageName != originalPackageName) {
return@forEachIndexed
return@permissions
}
@Suppress("DEPRECATION")
val newPermissionInfo = PermissionInfo().apply {
@@ -140,16 +135,15 @@ class UidPermissionPolicy : SchemePolicy() {
}
val newPermission = Permission(newPermissionInfo, false, oldPermission.type, 0)
changedPermissionNames += permissionName
permissions.setValueAt(i, newPermission)
permissions.setValueAt(permissionIndex, newPermission)
}
}
}
}
private fun canAdoptPermissions(
private fun MutateStateScope.canAdoptPermissions(
packageName: String,
originalPackageName: String,
newState: AccessState
originalPackageName: String
): Boolean {
val originalPackageState = newState.systemState.packageStates[originalPackageName]
?: return false
@@ -170,7 +164,7 @@ class UidPermissionPolicy : SchemePolicy() {
return true
}
private fun addPermissionGroups(packageState: PackageState, newState: AccessState) {
private fun MutateStateScope.addPermissionGroups(packageState: PackageState) {
// Different from the old implementation, which decides whether the app is an instant app by
// the install flags, now for consistent behavior we allow adding permission groups if the
// app is non-instant in at least one user.
@@ -202,10 +196,9 @@ class UidPermissionPolicy : SchemePolicy() {
}
}
private fun addPermissions(
private fun MutateStateScope.addPermissions(
packageState: PackageState,
changedPermissionNames: IndexedSet<String>,
newState: AccessState
changedPermissionNames: IndexedSet<String>
) {
packageState.androidPackage!!.permissions.forEachIndexed { _, parsedPermission ->
// TODO:
@@ -229,7 +222,7 @@ class UidPermissionPolicy : SchemePolicy() {
// Different from the old implementation, which may add an (incomplete) signature
// permission inside another package's permission tree, we now consistently ignore such
// permissions.
val permissionTree = getPermissionTree(permissionName, newState)
val permissionTree = getPermissionTree(permissionName)
val newPackageName = newPermissionInfo.packageName
if (permissionTree != null && newPackageName != permissionTree.packageName) {
Log.w(
@@ -294,10 +287,7 @@ class UidPermissionPolicy : SchemePolicy() {
}
}
private fun trimPermissions(
packageName: String,
newState: AccessState,
) {
private fun MutateStateScope.trimPermissions(packageName: String) {
val packageState = newState.systemState.packageStates[packageName]
val androidPackage = packageState?.androidPackage
if (packageState != null && androidPackage == null) {
@@ -314,20 +304,20 @@ class UidPermissionPolicy : SchemePolicy() {
}
newState.systemState.permissions.removeAllIndexed { i, permissionName, permission ->
val updatedPermission = updatePermissionIfDynamic(permission, newState)
val updatedPermission = updatePermissionIfDynamic(permission)
newState.systemState.permissions.setValueAt(i, updatedPermission)
if (updatedPermission.packageName == packageName && (
packageState == null || androidPackage!!.permissions.noneIndexed { _, it ->
!it.isTree && it.name == permissionName
}
)) {
if (!isPermissionDeclaredByDisabledSystemPackage(permission, newState)) {
if (!isPermissionDeclaredByDisabledSystemPackage(permission)) {
newState.userStates.forEachIndexed { _, userId, userState ->
userState.permissionFlags.forEachKeyIndexed { _, appId ->
setPermissionFlags(
appId, permissionName, getPermissionFlags(
appId, permissionName, userId, newState
) and PermissionFlags.INSTALL_REVOKED, userId, newState
appId, permissionName, userId
) and PermissionFlags.INSTALL_REVOKED, userId
)
}
}
@@ -339,9 +329,8 @@ class UidPermissionPolicy : SchemePolicy() {
}
}
private fun isPermissionDeclaredByDisabledSystemPackage(
permission: Permission,
newState: AccessState
private fun MutateStateScope.isPermissionDeclaredByDisabledSystemPackage(
permission: Permission
): Boolean {
val disabledSystemPackage = newState.systemState
.disabledSystemPackageStates[permission.packageName]?.androidPackage ?: return false
@@ -350,14 +339,11 @@ class UidPermissionPolicy : SchemePolicy() {
}
}
private fun updatePermissionIfDynamic(
permission: Permission,
newState: AccessState
): Permission {
private fun MutateStateScope.updatePermissionIfDynamic(permission: Permission): Permission {
if (!permission.isDynamic) {
return permission
}
val permissionTree = getPermissionTree(permission.name, newState) ?: return permission
val permissionTree = getPermissionTree(permission.name) ?: return permission
@Suppress("DEPRECATION")
return permission.copy(
permissionInfo = PermissionInfo(permission.permissionInfo).apply {
@@ -366,7 +352,7 @@ class UidPermissionPolicy : SchemePolicy() {
)
}
private fun getPermissionTree(permissionName: String, newState: AccessState): Permission? =
private fun MutateStateScope.getPermissionTree(permissionName: String): Permission? =
newState.systemState.permissionTrees.firstNotNullOfOrNullIndexed {
_, permissionTreeName, permissionTree ->
if (permissionName.startsWith(permissionTreeName) &&
@@ -378,58 +364,48 @@ class UidPermissionPolicy : SchemePolicy() {
}
}
private fun evaluatePermissionStateForAllPackages(
private fun MutateStateScope.evaluatePermissionStateForAllPackages(
permissionName: String,
installedPackageState: PackageState?,
oldState: AccessState,
newState: AccessState
installedPackageState: PackageState?
) {
newState.systemState.userIds.forEachIndexed { _, userId ->
oldState.userStates[userId]?.permissionFlags?.forEachIndexed {
_, appId, permissionFlags ->
if (permissionName in permissionFlags) {
evaluatePermissionState(
appId, permissionName, installedPackageState, userId, oldState, newState
)
evaluatePermissionState(appId, permissionName, installedPackageState, userId)
}
}
}
}
private fun evaluateAllPermissionStatesForPackage(
private fun MutateStateScope.evaluateAllPermissionStatesForPackage(
packageState: PackageState,
installedPackageState: PackageState?,
oldState: AccessState,
newState: AccessState
installedPackageState: PackageState?
) {
newState.systemState.userIds.forEachIndexed { _, userId ->
evaluateAllPermissionStatesForPackageAndUser(
packageState, installedPackageState, userId, oldState, newState
packageState, installedPackageState, userId
)
}
}
private fun evaluateAllPermissionStatesForPackageAndUser(
private fun MutateStateScope.evaluateAllPermissionStatesForPackageAndUser(
packageState: PackageState,
installedPackageState: PackageState?,
userId: Int,
oldState: AccessState,
newState: AccessState
userId: Int
) {
packageState.androidPackage?.requestedPermissions?.forEachIndexed { _, it ->
packageState.androidPackage?.requestedPermissions?.forEachIndexed { _, permissionName ->
evaluatePermissionState(
packageState.appId, it, installedPackageState, userId, oldState, newState
packageState.appId, permissionName, installedPackageState, userId
)
}
}
private fun evaluatePermissionState(
private fun MutateStateScope.evaluatePermissionState(
appId: Int,
permissionName: String,
installedPackageState: PackageState?,
userId: Int,
oldState: AccessState,
newState: AccessState
userId: Int
) {
val packageNames = newState.systemState.appIds[appId]
val hasMissingPackage = packageNames.anyIndexed { _, packageName ->
@@ -440,17 +416,17 @@ class UidPermissionPolicy : SchemePolicy() {
return
}
val permission = newState.systemState.permissions[permissionName] ?: return
val oldFlags = getPermissionFlags(appId, permissionName, userId, newState)
val oldFlags = getPermissionFlags(appId, permissionName, userId)
if (permission.isNormal) {
val wasGranted = oldFlags.hasBits(PermissionFlags.INSTALL_GRANTED)
if (!wasGranted) {
val wasRevoked = oldFlags.hasBits(PermissionFlags.INSTALL_REVOKED)
val isRequestedByInstalledPackage = installedPackageState != null &&
permissionName in installedPackageState.androidPackage!!.requestedPermissions
val isRequestedBySystemPackage = anyPackageInAppId(appId, newState) {
val isRequestedBySystemPackage = anyPackageInAppId(appId) {
it.isSystem && permissionName in it.androidPackage!!.requestedPermissions
}
val isCompatibilityPermission = anyPackageInAppId(appId, newState) {
val isCompatibilityPermission = anyPackageInAppId(appId) {
isCompatibilityPermissionForPackage(it.androidPackage!!, permissionName)
}
// If this is an existing, non-system package,
@@ -462,7 +438,7 @@ class UidPermissionPolicy : SchemePolicy() {
} else {
PermissionFlags.INSTALL_REVOKED
}
setPermissionFlags(appId, permissionName, newFlags, userId, newState)
setPermissionFlags(appId, permissionName, newFlags, userId)
}
} else if (permission.isSignature || permission.isInternal) {
val wasProtectionGranted = oldFlags.hasBits(PermissionFlags.PROTECTION_GRANTED)
@@ -471,17 +447,17 @@ class UidPermissionPolicy : SchemePolicy() {
PermissionFlags.PROTECTION_GRANTED
} else {
val mayGrantByPrivileged = !permission.isPrivileged || (
anyPackageInAppId(appId, newState) {
checkPrivilegedPermissionAllowlist(it, permission, newState)
anyPackageInAppId(appId) {
checkPrivilegedPermissionAllowlist(it, permission)
}
)
val shouldGrantBySignature = permission.isSignature && (
anyPackageInAppId(appId, newState) {
shouldGrantPermissionBySignature(it, permission, newState)
anyPackageInAppId(appId) {
shouldGrantPermissionBySignature(it, permission)
}
)
val shouldGrantByProtectionFlags = anyPackageInAppId(appId, newState) {
shouldGrantPermissionByProtectionFlags(it, permission, newState)
val shouldGrantByProtectionFlags = anyPackageInAppId(appId) {
shouldGrantPermissionByProtectionFlags(it, permission)
}
if (mayGrantByPrivileged &&
(shouldGrantBySignature || shouldGrantByProtectionFlags)) {
@@ -501,7 +477,7 @@ class UidPermissionPolicy : SchemePolicy() {
if (permission.isRole) {
newFlags = newFlags or (oldFlags and PermissionFlags.ROLE_GRANTED)
}
setPermissionFlags(appId, permissionName, newFlags, userId, newState)
setPermissionFlags(appId, permissionName, newFlags, userId)
} else if (permission.isRuntime) {
// TODO: add runtime permissions
} else {
@@ -513,12 +489,7 @@ class UidPermissionPolicy : SchemePolicy() {
// TODO: revokePermissionsNoLongerImplicitLocked() for runtime permissions
}
private fun grantImplicitPermissions(
packageState: PackageState,
userId: Int,
oldState: AccessState,
newState: AccessState
) {
private fun MutateStateScope.grantImplicitPermissions(packageState: PackageState, userId: Int) {
val appId = packageState.appId
val androidPackage = packageState.androidPackage ?: return
androidPackage.implicitPermissions.forEachIndexed implicitPermissions@ {
@@ -530,6 +501,7 @@ class UidPermissionPolicy : SchemePolicy() {
if (!implicitPermission.isRuntime) {
return@implicitPermissions
}
// Explicitly check against the old state to determine if this permission is new.
val isNewPermission = getPermissionFlags(
appId, implicitPermissionName, userId, oldState
) == 0
@@ -544,7 +516,7 @@ class UidPermissionPolicy : SchemePolicy() {
checkNotNull(sourcePermission) {
"Unknown source permission $sourcePermissionName in split permissions"
}
val sourceFlags = getPermissionFlags(appId, sourcePermissionName, userId, newState)
val sourceFlags = getPermissionFlags(appId, sourcePermissionName, userId)
val isSourceGranted = sourceFlags.hasAnyBit(PermissionFlags.MASK_GRANTED)
val isNewGranted = newFlags.hasAnyBit(PermissionFlags.MASK_GRANTED)
val isGrantingNewFromRevoke = isSourceGranted && !isNewGranted
@@ -559,23 +531,22 @@ class UidPermissionPolicy : SchemePolicy() {
}
}
newFlags = newFlags or PermissionFlags.IMPLICIT
setPermissionFlags(appId, implicitPermissionName, newFlags, userId, newState)
setPermissionFlags(appId, implicitPermissionName, newFlags, userId)
}
}
private fun getPermissionFlags(
private fun MutateStateScope.getPermissionFlags(
appId: Int,
permissionName: String,
userId: Int,
state: AccessState
state: AccessState = newState
): Int = state.userStates[userId].permissionFlags[appId].getWithDefault(permissionName, 0)
private fun setPermissionFlags(
private fun MutateStateScope.setPermissionFlags(
appId: Int,
permissionName: String,
flags: Int,
userId: Int,
newState: AccessState
userId: Int
) {
newState.userStates[userId].permissionFlags[appId]!!
.putWithDefault(permissionName, flags, 0)
@@ -585,8 +556,9 @@ class UidPermissionPolicy : SchemePolicy() {
androidPackage: AndroidPackage,
permissionName: String
): Boolean {
for (info: CompatibilityPermissionInfo in CompatibilityPermissionInfo.COMPAT_PERMS) {
if (info.name == permissionName && androidPackage.targetSdkVersion < info.sdkVersion) {
for (compatibilityPermission in CompatibilityPermissionInfo.COMPAT_PERMS) {
if (compatibilityPermission.name == permissionName &&
androidPackage.targetSdkVersion < compatibilityPermission.sdkVersion) {
Log.i(
LOG_TAG, "Auto-granting $permissionName to old package" +
" ${androidPackage.packageName}"
@@ -597,10 +569,9 @@ class UidPermissionPolicy : SchemePolicy() {
return false
}
private fun shouldGrantPermissionBySignature(
private fun MutateStateScope.shouldGrantPermissionBySignature(
packageState: PackageState,
permission: Permission,
newState: AccessState
permission: Permission
): Boolean {
// check if the package is allow to use this signature permission. A package is allowed to
// use a signature permission if:
@@ -622,10 +593,9 @@ class UidPermissionPolicy : SchemePolicy() {
SigningDetails.CertCapabilities.PERMISSION)
}
private fun checkPrivilegedPermissionAllowlist(
private fun MutateStateScope.checkPrivilegedPermissionAllowlist(
packageState: PackageState,
permission: Permission,
newState: AccessState
permission: Permission
): Boolean {
if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) {
return true
@@ -641,10 +611,10 @@ class UidPermissionPolicy : SchemePolicy() {
newState.systemState.privilegedPermissionAllowlistSourcePackageNames) {
return true
}
if (isInSystemConfigPrivAppPermissions(androidPackage, permission.name, newState)) {
if (isInSystemConfigPrivAppPermissions(androidPackage, permission.name)) {
return true
}
if (isInSystemConfigPrivAppDenyPermissions(androidPackage, permission.name, newState)) {
if (isInSystemConfigPrivAppDenyPermissions(androidPackage, permission.name)) {
return false
}
// Updated system apps do not need to be allowlisted
@@ -655,10 +625,9 @@ class UidPermissionPolicy : SchemePolicy() {
return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE
}
private fun isInSystemConfigPrivAppPermissions(
private fun MutateStateScope.isInSystemConfigPrivAppPermissions(
androidPackage: AndroidPackage,
permissionName: String,
newState: AccessState
permissionName: String
): Boolean {
val apexModuleName = androidPackage.apexModuleName
val systemState = newState.systemState
@@ -682,10 +651,9 @@ class UidPermissionPolicy : SchemePolicy() {
return permissionNames?.contains(permissionName) == true
}
private fun isInSystemConfigPrivAppDenyPermissions(
private fun MutateStateScope.isInSystemConfigPrivAppDenyPermissions(
androidPackage: AndroidPackage,
permissionName: String,
newState: AccessState
permissionName: String
): Boolean {
// Different from the previous implementation, which may incorrectly use the APEX package
// name, we now use the APEX module name to be consistent with the allowlist.
@@ -713,22 +681,21 @@ class UidPermissionPolicy : SchemePolicy() {
return permissionNames?.contains(permissionName) == true
}
private fun anyPackageInAppId(
private fun MutateStateScope.anyPackageInAppId(
appId: Int,
newState: AccessState,
state: AccessState = newState,
predicate: (PackageState) -> Boolean
): Boolean {
val packageNames = newState.systemState.appIds[appId]
val packageNames = state.systemState.appIds[appId]
return packageNames.anyIndexed { _, packageName ->
val packageState = newState.systemState.packageStates[packageName]!!
val packageState = state.systemState.packageStates[packageName]!!
packageState.androidPackage != null && predicate(packageState)
}
}
private fun shouldGrantPermissionByProtectionFlags(
private fun MutateStateScope.shouldGrantPermissionByProtectionFlags(
packageState: PackageState,
permission: Permission,
newState: AccessState
permission: Permission
): Boolean {
val androidPackage = packageState.androidPackage!!
val knownPackages = newState.systemState.knownPackages
@@ -741,11 +708,9 @@ class UidPermissionPolicy : SchemePolicy() {
.disabledSystemPackageStates[packageState.packageName]?.androidPackage
disabledSystemPackage != null &&
permission.name in disabledSystemPackage.requestedPermissions &&
shouldGrantPrivilegedOrOemPermission(
disabledSystemPackage, permission, newState
)
shouldGrantPrivilegedOrOemPermission(disabledSystemPackage, permission)
} else {
shouldGrantPrivilegedOrOemPermission(androidPackage, permission, newState)
shouldGrantPrivilegedOrOemPermission(androidPackage, permission)
}
if (shouldGrant) {
return true
@@ -815,7 +780,7 @@ class UidPermissionPolicy : SchemePolicy() {
}
if (permission.isRetailDemo &&
packageName in knownPackages[KnownPackages.PACKAGE_RETAIL_DEMO] &&
isDeviceOrProfileOwnerUid(packageState.appId, newState)) {
isDeviceOrProfileOwnerUid(packageState.appId)) {
// Special permission granted only to the OEM specified retail demo app.
// Note that the original code was passing app ID as UID, so this behavior is kept
// unchanged.
@@ -829,10 +794,9 @@ class UidPermissionPolicy : SchemePolicy() {
return false
}
private fun shouldGrantPrivilegedOrOemPermission(
private fun MutateStateScope.shouldGrantPrivilegedOrOemPermission(
androidPackage: AndroidPackage,
permission: Permission,
state: AccessState
permission: Permission
): Boolean {
val permissionName = permission.name
val packageName = androidPackage.packageName
@@ -855,7 +819,7 @@ class UidPermissionPolicy : SchemePolicy() {
}
permission.isOem -> {
if (androidPackage.isOem) {
val isOemAllowlisted = state.systemState
val isOemAllowlisted = newState.systemState
.oemPermissions[packageName]?.get(permissionName)
checkNotNull(isOemAllowlisted) {
"OEM permission $permissionName requested by package" +
@@ -868,19 +832,15 @@ class UidPermissionPolicy : SchemePolicy() {
return false
}
private fun isDeviceOrProfileOwnerUid(uid: Int, state: AccessState): Boolean {
private fun MutateStateScope.isDeviceOrProfileOwnerUid(uid: Int): Boolean {
val userId = UserHandle.getUserId(uid)
val ownerPackageName = state.systemState.deviceAndProfileOwners[userId] ?: return false
val ownerPackageState = state.systemState.packageStates[ownerPackageName] ?: return false
val ownerPackageName = newState.systemState.deviceAndProfileOwners[userId] ?: return false
val ownerPackageState = newState.systemState.packageStates[ownerPackageName] ?: return false
val ownerUid = UserHandle.getUid(userId, ownerPackageState.appId)
return uid == ownerUid
}
override fun onPackageRemoved(
packageState: PackageState,
oldState: AccessState,
newState: AccessState
) {
override fun MutateStateScope.onPackageRemoved(packageState: PackageState) {
// TODO
}
@@ -892,6 +852,12 @@ class UidPermissionPolicy : SchemePolicy() {
with(persistence) { this@serializeSystemState.serializeSystemState(systemState) }
}
fun GetStateScope.getPermissionGroup(permissionGroupName: String): PermissionGroupInfo? =
state.systemState.permissionGroups[permissionGroupName]
fun GetStateScope.getPermission(permissionName: String): Permission? =
state.systemState.permissions[permissionName]
companion object {
private val LOG_TAG = UidPermissionPolicy::class.java.simpleName