Add ModernPermissionManagerServiceImpl skeleton and two methods.
Also allow compatibility layer to talk to policy directly by introducing scopes for getting and mutating state, because compatibility layer shouldn't have direct access to states, while scope also allows getting rid of a lot of boilerplate for passing states around. Bug: 182523293 Test: presubmit Change-Id: I36f53383c261b51372178d8c183c190bdb3c7132
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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()) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -232,7 +232,7 @@ public final class PermissionPolicyService extends SystemService {
|
||||
}
|
||||
};
|
||||
|
||||
final ArrayList<PermissionInfo> dangerousPerms =
|
||||
final List<PermissionInfo> dangerousPerms =
|
||||
mPermissionManagerInternal.getAllPermissionsWithProtection(
|
||||
PermissionInfo.PROTECTION_DANGEROUS);
|
||||
try {
|
||||
|
||||
@@ -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: [
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {}
|
||||
|
||||
|
||||
@@ -124,3 +124,12 @@ abstract class WritableState {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class GetStateScope(
|
||||
val state: AccessState
|
||||
)
|
||||
|
||||
class MutateStateScope(
|
||||
val oldState: AccessState,
|
||||
val newState: AccessState
|
||||
)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user