Fix issues in the new permission & app op subsystems.

And boot with it.

- Added logging decorators for permission and app op interfaces.
- Worked around a bug in DefaultPermissionGrantPoicy that may grant
  permission unrequested by a package in a shared UID.
- Reverted to checking user ID existence first inside
  PermissionService to avoid breaking existing code that may pass user
  -1.
- Regathered known packages in package callbacks.
- Added async persistence code according to existing permission
  persistence.
- Other bug fixes.

Bug: 263504888
Test: device boots with the new subsystems enabled
Change-Id: I04517014c4a97506a35bb79513d3accd119dc5bf
This commit is contained in:
Hai Zhang
2022-12-22 11:46:49 -08:00
parent 1dac03708e
commit 08847a5eea
12 changed files with 1064 additions and 107 deletions

View File

@@ -0,0 +1,185 @@
/*
* 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.appop;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.util.ArraySet;
import android.util.Log;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import java.io.PrintWriter;
/**
* Logging decorator for {@link AppOpsCheckingServiceInterface}.
*/
public class AppOpsCheckingServiceLoggingDecorator implements AppOpsCheckingServiceInterface {
private static final String LOG_TAG =
AppOpsCheckingServiceLoggingDecorator.class.getSimpleName();
@NonNull
private final AppOpsCheckingServiceInterface mService;
public AppOpsCheckingServiceLoggingDecorator(@NonNull AppOpsCheckingServiceInterface service) {
mService = service;
}
@Override
public SparseIntArray getNonDefaultUidModes(int uid) {
Log.i(LOG_TAG, "getNonDefaultUidModes(uid = " + uid + ")");
return mService.getNonDefaultUidModes(uid);
}
@Override
public int getUidMode(int uid, int op) {
Log.i(LOG_TAG, "getUidMode(uid = " + uid + ", op = " + op + ")");
return mService.getUidMode(uid, op);
}
@Override
public boolean setUidMode(int uid, int op, int mode) {
Log.i(LOG_TAG, "setUidMode(uid = " + uid + ", op = " + op + ", mode = " + mode + ")");
return mService.setUidMode(uid, op, mode);
}
@Override
public int getPackageMode(@NonNull String packageName, int op, int userId) {
Log.i(LOG_TAG, "getPackageMode(packageName = " + packageName + ", op = " + op
+ ", userId = " + userId + ")");
return mService.getPackageMode(packageName, op, userId);
}
@Override
public void setPackageMode(@NonNull String packageName, int op, int mode, int userId) {
Log.i(LOG_TAG, "setPackageMode(packageName = " + packageName + ", op = " + op + ", mode = "
+ mode + ", userId = " + userId + ")");
mService.setPackageMode(packageName, op, mode, userId);
}
@Override
public boolean removePackage(@NonNull String packageName, int userId) {
Log.i(LOG_TAG, "removePackage(packageName = " + packageName + ", userId = " + userId + ")");
return mService.removePackage(packageName, userId);
}
@Override
public void removeUid(int uid) {
Log.i(LOG_TAG, "removeUid(uid = " + uid + ")");
mService.removeUid(uid);
}
@Override
public boolean areUidModesDefault(int uid) {
Log.i(LOG_TAG, "areUidModesDefault(uid = " + uid + ")");
return mService.areUidModesDefault(uid);
}
@Override
public boolean arePackageModesDefault(String packageName, int userId) {
Log.i(LOG_TAG, "arePackageModesDefault(packageName = " + packageName + ", userId = "
+ userId + ")");
return mService.arePackageModesDefault(packageName, userId);
}
@Override
public void clearAllModes() {
Log.i(LOG_TAG, "clearAllModes()");
mService.clearAllModes();
}
@Override
public void startWatchingOpModeChanged(@NonNull OnOpModeChangedListener changedListener,
int op) {
Log.i(LOG_TAG, "startWatchingOpModeChanged(changedListener = " + changedListener + ", op = "
+ op + ")");
mService.startWatchingOpModeChanged(changedListener, op);
}
@Override
public void startWatchingPackageModeChanged(@NonNull OnOpModeChangedListener changedListener,
@NonNull String packageName) {
Log.i(LOG_TAG, "startWatchingPackageModeChanged(changedListener = " + changedListener
+ ", packageName = " + packageName + ")");
mService.startWatchingPackageModeChanged(changedListener, packageName);
}
@Override
public void removeListener(@NonNull OnOpModeChangedListener changedListener) {
Log.i(LOG_TAG, "removeListener(changedListener = " + changedListener + ")");
mService.removeListener(changedListener);
}
@Override
public ArraySet<OnOpModeChangedListener> getOpModeChangedListeners(int op) {
Log.i(LOG_TAG, "getOpModeChangedListeners(op = " + op + ")");
return mService.getOpModeChangedListeners(op);
}
@Override
public ArraySet<OnOpModeChangedListener> getPackageModeChangedListeners(
@NonNull String packageName) {
Log.i(LOG_TAG, "getPackageModeChangedListeners(packageName = " + packageName + ")");
return mService.getPackageModeChangedListeners(packageName);
}
@Override
public void notifyWatchersOfChange(int op, int uid) {
Log.i(LOG_TAG, "notifyWatchersOfChange(op = " + op + ", uid = " + uid + ")");
mService.notifyWatchersOfChange(op, uid);
}
@Override
public void notifyOpChanged(@NonNull OnOpModeChangedListener changedListener, int op, int uid,
@Nullable String packageName) {
Log.i(LOG_TAG, "notifyOpChanged(changedListener = " + changedListener + ", op = " + op
+ ", uid = " + uid + ", packageName = " + packageName + ")");
mService.notifyOpChanged(changedListener, op, uid, packageName);
}
@Override
public void notifyOpChangedForAllPkgsInUid(int op, int uid, boolean onlyForeground,
@Nullable OnOpModeChangedListener callbackToIgnore) {
Log.i(LOG_TAG, "notifyOpChangedForAllPkgsInUid(op = " + op + ", uid = " + uid
+ ", onlyForeground = " + onlyForeground + ", callbackToIgnore = "
+ callbackToIgnore + ")");
mService.notifyOpChangedForAllPkgsInUid(op, uid, onlyForeground, callbackToIgnore);
}
@Override
public SparseBooleanArray evalForegroundUidOps(int uid, SparseBooleanArray foregroundOps) {
Log.i(LOG_TAG, "evalForegroundUidOps(uid = " + uid + ", foregroundOps = " + foregroundOps
+ ")");
return mService.evalForegroundUidOps(uid, foregroundOps);
}
@Override
public SparseBooleanArray evalForegroundPackageOps(String packageName,
SparseBooleanArray foregroundOps, int userId) {
Log.i(LOG_TAG, "evalForegroundPackageOps(packageName = " + packageName
+ ", foregroundOps = " + foregroundOps + ", userId = " + userId + ")");
return mService.evalForegroundPackageOps(packageName, foregroundOps, userId);
}
@Override
public boolean dumpListeners(int dumpOp, int dumpUid, String dumpPackage,
PrintWriter printWriter) {
Log.i(LOG_TAG, "dumpListeners(dumpOp = " + dumpOp + ", dumpUid = " + dumpUid
+ ", dumpPackage = " + dumpPackage + ", printWriter = " + printWriter + ")");
return mService.dumpListeners(dumpOp, dumpUid, dumpPackage, printWriter);
}
}

View File

@@ -956,6 +956,8 @@ public class AppOpsService extends IAppOpsService.Stub implements PersistenceSch
}
mAppOpsCheckingService =
new AppOpsCheckingServiceImpl(this, this, handler, context, mSwitchedOps);
//mAppOpsCheckingService = new AppOpsCheckingServiceLoggingDecorator(
// LocalServices.getService(AppOpsCheckingServiceInterface.class));
mAppOpsRestrictions = new AppOpsRestrictionsImpl(context, handler,
mAppOpsCheckingService);

View File

@@ -1800,6 +1800,15 @@ final class DefaultPermissionGrantPolicy {
PermissionState permState;
if (permIdx >= 0) {
permState = uidState.valueAt(permIdx);
// Quick and dirty fix for shared UID packages - we should grant permission with the
// correct package even if a previous checkPermission() used a package that isn't
// requesting the permission. Ideally we should use package manager snapshot and get
// rid of this entire inner class.
if (!ArrayUtils.contains(permState.mPkgRequestingPerm.requestedPermissions,
permission) && ArrayUtils.contains(pkg.requestedPermissions,
permission)) {
permState.mPkgRequestingPerm = pkg;
}
} else {
permState = new PermissionState(permission, pkg, user);
uidState.put(permission, permState);
@@ -1887,7 +1896,7 @@ final class DefaultPermissionGrantPolicy {
*/
private class PermissionState {
private final @NonNull String mPermission;
private final @NonNull PackageInfo mPkgRequestingPerm;
private @NonNull PackageInfo mPkgRequestingPerm;
private final @NonNull UserHandle mUser;
/** Permission flags when the state was created */

View File

@@ -119,7 +119,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private final AppOpsManager mAppOpsManager;
private final Context mContext;
private final PermissionManagerServiceImpl mPermissionManagerServiceImpl;
private final PermissionManagerServiceInterface mPermissionManagerServiceImpl;
@NonNull
private final AttributionSourceRegistry mAttributionSourceRegistry;
@@ -152,6 +152,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
mPermissionManagerServiceImpl = new PermissionManagerServiceImpl(context,
availableFeatures);
//mPermissionManagerServiceImpl = new PermissionManagerServiceLoggingDecorator(
// LocalServices.getService(PermissionManagerServiceInterface.class));
}
/**

View File

@@ -0,0 +1,433 @@
/*
* 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.pm.permission;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.permission.IOnPermissionsChangeListener;
import android.util.Log;
import com.android.server.pm.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageState;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Logging decorator for {@link PermissionManagerServiceInterface}.
*/
public class PermissionManagerServiceLoggingDecorator implements PermissionManagerServiceInterface {
private static final String LOG_TAG =
PermissionManagerServiceLoggingDecorator.class.getSimpleName();
@NonNull
private final PermissionManagerServiceInterface mService;
public PermissionManagerServiceLoggingDecorator(
@NonNull PermissionManagerServiceInterface service
) {
mService = service;
}
@Nullable
@Override
public byte[] backupRuntimePermissions(int userId) {
Log.i(LOG_TAG, "backupRuntimePermissions(userId = " + userId + ")");
return mService.backupRuntimePermissions(userId);
}
@Override
@SuppressWarnings("ArrayToString")
public void restoreRuntimePermissions(@NonNull byte[] backup, int userId) {
Log.i(LOG_TAG, "restoreRuntimePermissions(backup = " + backup + ", userId = " + userId
+ ")");
mService.restoreRuntimePermissions(backup, userId);
}
@Override
public void restoreDelayedRuntimePermissions(@NonNull String packageName, int userId) {
Log.i(LOG_TAG, "restoreDelayedRuntimePermissions(packageName = " + packageName
+ ", userId = " + userId + ")");
mService.restoreDelayedRuntimePermissions(packageName, userId);
}
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Log.i(LOG_TAG, "dump(fd = " + fd + ", pw = " + pw + ", args = " + Arrays.toString(args)
+ ")");
mService.dump(fd, pw, args);
}
@Override
public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
Log.i(LOG_TAG, "getAllPermissionGroups(flags = " + flags + ")");
return mService.getAllPermissionGroups(flags);
}
@Override
public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags) {
Log.i(LOG_TAG, "getPermissionGroupInfo(groupName = " + groupName + ", flags = " + flags
+ ")");
return mService.getPermissionGroupInfo(groupName, flags);
}
@Override
public PermissionInfo getPermissionInfo(@NonNull String permName, int flags,
@NonNull String opPackageName) {
Log.i(LOG_TAG, "getPermissionInfo(permName = " + permName + ", flags = " + flags
+ ", opPackageName = " + opPackageName + ")");
return mService.getPermissionInfo(permName, flags, opPackageName);
}
@Override
public List<PermissionInfo> queryPermissionsByGroup(String groupName, int flags) {
Log.i(LOG_TAG, "queryPermissionsByGroup(groupName = " + groupName + ", flags = " + flags
+ ")");
return mService.queryPermissionsByGroup(groupName, flags);
}
@Override
public boolean addPermission(PermissionInfo info, boolean async) {
Log.i(LOG_TAG, "addPermission(info = " + info + ", async = " + async + ")");
return mService.addPermission(info, async);
}
@Override
public void removePermission(String permName) {
Log.i(LOG_TAG, "removePermission(permName = " + permName + ")");
mService.removePermission(permName);
}
@Override
public int getPermissionFlags(String packageName, String permName, int userId) {
Log.i(LOG_TAG, "getPermissionFlags(packageName = " + packageName + ", permName = "
+ permName + ", userId = " + userId + ")");
return mService.getPermissionFlags(packageName, permName, userId);
}
@Override
public void updatePermissionFlags(String packageName, String permName, int flagMask,
int flagValues, boolean checkAdjustPolicyFlagPermission, int userId) {
Log.i(LOG_TAG, "updatePermissionFlags(packageName = " + packageName + ", permName = "
+ permName + ", flagMask = " + flagMask + ", flagValues = " + flagValues
+ ", checkAdjustPolicyFlagPermission = " + checkAdjustPolicyFlagPermission
+ ", userId = " + userId + ")");
mService.updatePermissionFlags(packageName, permName, flagMask, flagValues,
checkAdjustPolicyFlagPermission, userId);
}
@Override
public void updatePermissionFlagsForAllApps(int flagMask, int flagValues, int userId) {
Log.i(LOG_TAG, "updatePermissionFlagsForAllApps(flagMask = " + flagMask + ", flagValues = "
+ flagValues + ", userId = " + userId + ")");
mService.updatePermissionFlagsForAllApps(flagMask, flagValues, userId);
}
@Override
public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
Log.i(LOG_TAG, "addOnPermissionsChangeListener(listener = " + listener + ")");
mService.addOnPermissionsChangeListener(listener);
}
@Override
public void removeOnPermissionsChangeListener(
IOnPermissionsChangeListener listener) {
Log.i(LOG_TAG, "removeOnPermissionsChangeListener(listener = " + listener + ")");
mService.removeOnPermissionsChangeListener(listener);
}
@Override
public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
@NonNull String permName, int flags, int userId) {
Log.i(LOG_TAG, "addAllowlistedRestrictedPermission(packageName = " + packageName
+ ", permName = " + permName + ", flags = " + flags + ", userId = " + userId + ")");
return mService.addAllowlistedRestrictedPermission(packageName, permName, flags, userId);
}
@Override
public List<String> getAllowlistedRestrictedPermissions(@NonNull String packageName, int flags,
int userId) {
Log.i(LOG_TAG, "getAllowlistedRestrictedPermissions(packageName = " + packageName
+ ", flags = " + flags + ", userId = " + userId + ")");
return mService.getAllowlistedRestrictedPermissions(packageName, flags, userId);
}
@Override
public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
@NonNull String permName, int flags, int userId) {
Log.i(LOG_TAG, "removeAllowlistedRestrictedPermission(packageName = " + packageName
+ ", permName = " + permName + ", flags = " + flags + ", userId = " + userId + ")");
return mService.removeAllowlistedRestrictedPermission(packageName, permName, flags, userId);
}
@Override
public void grantRuntimePermission(String packageName, String permName, int userId) {
Log.i(LOG_TAG, "grantRuntimePermission(packageName = " + packageName + ", permName = "
+ permName + ", userId = " + userId + ")");
mService.grantRuntimePermission(packageName, permName, userId);
}
@Override
public void revokeRuntimePermission(String packageName, String permName, int userId,
String reason) {
Log.i(LOG_TAG, "revokeRuntimePermission(packageName = " + packageName + ", permName = "
+ permName + ", userId = " + userId + ", reason = " + reason + ")");
mService.revokeRuntimePermission(packageName, permName, userId, reason);
}
@Override
public void revokePostNotificationPermissionWithoutKillForTest(String packageName, int userId) {
Log.i(LOG_TAG, "revokePostNotificationPermissionWithoutKillForTest(packageName = "
+ packageName + ", userId = " + userId + ")");
mService.revokePostNotificationPermissionWithoutKillForTest(packageName, userId);
}
@Override
public boolean shouldShowRequestPermissionRationale(String packageName, String permName,
int userId) {
Log.i(LOG_TAG, "shouldShowRequestPermissionRationale(packageName = " + packageName
+ ", permName = " + permName + ", userId = " + userId + ")");
return mService.shouldShowRequestPermissionRationale(packageName, permName, userId);
}
@Override
public boolean isPermissionRevokedByPolicy(String packageName, String permName, int userId) {
Log.i(LOG_TAG, "isPermissionRevokedByPolicy(packageName = " + packageName + ", permName = "
+ permName + ", userId = " + userId + ")");
return mService.isPermissionRevokedByPolicy(packageName, permName, userId);
}
@Override
public List<SplitPermissionInfoParcelable> getSplitPermissions() {
Log.i(LOG_TAG, "getSplitPermissions()");
return mService.getSplitPermissions();
}
@Override
public int checkPermission(String pkgName, String permName, int userId) {
Log.i(LOG_TAG, "checkPermission(pkgName = " + pkgName + ", permName = " + permName
+ ", userId = " + userId + ")");
return mService.checkPermission(pkgName, permName, userId);
}
@Override
public int checkUidPermission(int uid, String permName) {
Log.i(LOG_TAG, "checkUidPermission(uid = " + uid + ", permName = " + permName + ")");
return mService.checkUidPermission(uid, permName);
}
@Override
public void addOnRuntimePermissionStateChangedListener(
@NonNull PermissionManagerServiceInternal
.OnRuntimePermissionStateChangedListener listener) {
Log.i(LOG_TAG, "addOnRuntimePermissionStateChangedListener(listener = " + listener + ")");
mService.addOnRuntimePermissionStateChangedListener(listener);
}
@Override
public void removeOnRuntimePermissionStateChangedListener(
@NonNull PermissionManagerServiceInternal
.OnRuntimePermissionStateChangedListener listener) {
Log.i(LOG_TAG, "removeOnRuntimePermissionStateChangedListener(listener = " + listener
+ ")");
mService.removeOnRuntimePermissionStateChangedListener(listener);
}
@Override
public Map<String, Set<String>> getAllAppOpPermissionPackages() {
Log.i(LOG_TAG, "getAllAppOpPermissionPackages()");
return mService.getAllAppOpPermissionPackages();
}
@Override
public boolean isPermissionsReviewRequired(@NonNull String packageName, int userId) {
Log.i(LOG_TAG, "isPermissionsReviewRequired(packageName = " + packageName + ", userId = "
+ userId + ")");
return mService.isPermissionsReviewRequired(packageName, userId);
}
@Override
public void resetRuntimePermissions(@NonNull AndroidPackage pkg, int userId) {
Log.i(LOG_TAG, "resetRuntimePermissions(pkg = " + pkg + ", userId = " + userId + ")");
mService.resetRuntimePermissions(pkg, userId);
}
@Override
public void resetRuntimePermissionsForUser(int userId) {
Log.i(LOG_TAG, "resetRuntimePermissionsForUser(userId = " + userId + ")");
mService.resetRuntimePermissionsForUser(userId);
}
@Override
public void readLegacyPermissionStateTEMP() {
Log.i(LOG_TAG, "readLegacyPermissionStateTEMP()");
mService.readLegacyPermissionStateTEMP();
}
@Override
public void writeLegacyPermissionStateTEMP() {
Log.i(LOG_TAG, "writeLegacyPermissionStateTEMP()");
mService.writeLegacyPermissionStateTEMP();
}
@NonNull
@Override
public Set<String> getGrantedPermissions(@NonNull String packageName, int userId) {
Log.i(LOG_TAG, "getGrantedPermissions(packageName = " + packageName + ", userId = "
+ userId + ")");
return mService.getGrantedPermissions(packageName, userId);
}
@NonNull
@Override
public int[] getPermissionGids(@NonNull String permissionName, int userId) {
Log.i(LOG_TAG, "getPermissionGids(permissionName = " + permissionName + ", userId = "
+ userId + ")");
return mService.getPermissionGids(permissionName, userId);
}
@NonNull
@Override
public String[] getAppOpPermissionPackages(@NonNull String permissionName) {
Log.i(LOG_TAG, "getAppOpPermissionPackages(permissionName = " + permissionName + ")");
return mService.getAppOpPermissionPackages(permissionName);
}
@Nullable
@Override
public Permission getPermissionTEMP(@NonNull String permName) {
Log.i(LOG_TAG, "getPermissionTEMP(permName = " + permName + ")");
return mService.getPermissionTEMP(permName);
}
@NonNull
@Override
public List<PermissionInfo> getAllPermissionsWithProtection(int protection) {
Log.i(LOG_TAG, "getAllPermissionsWithProtection(protection = " + protection + ")");
return mService.getAllPermissionsWithProtection(protection);
}
@NonNull
@Override
public List<PermissionInfo> getAllPermissionsWithProtectionFlags(int protectionFlags) {
Log.i(LOG_TAG, "getAllPermissionsWithProtectionFlags(protectionFlags = " + protectionFlags
+ ")");
return mService.getAllPermissionsWithProtectionFlags(protectionFlags);
}
@NonNull
@Override
public List<LegacyPermission> getLegacyPermissions() {
Log.i(LOG_TAG, "getLegacyPermissions()");
return mService.getLegacyPermissions();
}
@NonNull
@Override
public LegacyPermissionState getLegacyPermissionState(int appId) {
Log.i(LOG_TAG, "getLegacyPermissionState(appId = " + appId + ")");
return mService.getLegacyPermissionState(appId);
}
@Override
public void readLegacyPermissionsTEMP(
@NonNull LegacyPermissionSettings legacyPermissionSettings) {
Log.i(LOG_TAG, "readLegacyPermissionsTEMP(legacyPermissionSettings = "
+ legacyPermissionSettings + ")");
mService.readLegacyPermissionsTEMP(legacyPermissionSettings);
}
@Override
public void writeLegacyPermissionsTEMP(
@NonNull LegacyPermissionSettings legacyPermissionSettings) {
Log.i(LOG_TAG, "writeLegacyPermissionsTEMP(legacyPermissionSettings = "
+ legacyPermissionSettings + ")");
mService.writeLegacyPermissionsTEMP(legacyPermissionSettings);
}
@Override
public void onSystemReady() {
Log.i(LOG_TAG, "onSystemReady()");
mService.onSystemReady();
}
@Override
public void onStorageVolumeMounted(@NonNull String volumeUuid, boolean fingerprintChanged) {
Log.i(LOG_TAG, "onStorageVolumeMounted(volumeUuid = " + volumeUuid
+ ", fingerprintChanged = " + fingerprintChanged + ")");
mService.onStorageVolumeMounted(volumeUuid, fingerprintChanged);
}
@NonNull
@Override
public int[] getGidsForUid(int uid) {
Log.i(LOG_TAG, "getGidsForUid(uid = " + uid + ")");
return mService.getGidsForUid(uid);
}
@Override
public void onUserCreated(int userId) {
Log.i(LOG_TAG, "onUserCreated(userId = " + userId + ")");
mService.onUserCreated(userId);
}
@Override
public void onUserRemoved(int userId) {
Log.i(LOG_TAG, "onUserRemoved(userId = " + userId + ")");
mService.onUserRemoved(userId);
}
@Override
public void onPackageAdded(@NonNull PackageState packageState, boolean isInstantApp,
@Nullable AndroidPackage oldPkg) {
Log.i(LOG_TAG, "onPackageAdded(packageState = " + packageState + ", isInstantApp = "
+ isInstantApp + ", oldPkg = " + oldPkg + ")");
mService.onPackageAdded(packageState, isInstantApp, oldPkg);
}
@Override
public void onPackageInstalled(@NonNull AndroidPackage pkg, int previousAppId,
@NonNull PermissionManagerServiceInternal.PackageInstalledParams params, int userId) {
Log.i(LOG_TAG, "onPackageInstalled(pkg = " + pkg + ", previousAppId = " + previousAppId
+ ", params = " + params + ", userId = " + userId + ")");
mService.onPackageInstalled(pkg, previousAppId, params, userId);
}
@Override
public void onPackageRemoved(@NonNull AndroidPackage pkg) {
Log.i(LOG_TAG, "onPackageRemoved(pkg = " + pkg + ")");
mService.onPackageRemoved(pkg);
}
@Override
public void onPackageUninstalled(@NonNull String packageName, int appId,
@NonNull PackageState packageState, @NonNull AndroidPackage pkg,
@NonNull List<AndroidPackage> sharedUserPkgs, int userId) {
Log.i(LOG_TAG, "onPackageUninstalled(packageName = " + packageName + ", appId = " + appId
+ ", packageState = " + packageState + ", pkg = " + pkg + ", sharedUserPkgs = "
+ sharedUserPkgs + ", userId = " + userId + ")");
mService.onPackageUninstalled(packageName, appId, packageState, pkg, sharedUserPkgs,
userId);
}
}

View File

@@ -88,6 +88,7 @@ class AccessCheckingService(context: Context) : SystemService(context) {
configPermissions, privilegedPermissionAllowlistPackages, permissionAllowlist,
implicitToSourcePermissions
)
persistence.initialize()
persistence.read(state)
this.state = state
@@ -99,43 +100,6 @@ class AccessCheckingService(context: Context) : SystemService(context) {
permissionService.initialize()
}
private val PackageManagerInternal.knownPackages: IntMap<Array<String>>
get() = IntMap<Array<String>>().apply {
this[KnownPackages.PACKAGE_INSTALLER] = getKnownPackageNames(
KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] = getKnownPackageNames(
KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_VERIFIER] = getKnownPackageNames(
KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_SETUP_WIZARD] = getKnownPackageNames(
KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] = getKnownPackageNames(
KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_CONFIGURATOR] = getKnownPackageNames(
KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] = getKnownPackageNames(
KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_APP_PREDICTOR] = getKnownPackageNames(
KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_COMPANION] = getKnownPackageNames(
KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_RETAIL_DEMO] = getKnownPackageNames(
KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_RECENTS] = getKnownPackageNames(
KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM
)
}
private val SystemConfig.isLeanback: Boolean
get() = PackageManager.FEATURE_LEANBACK in availableFeatures
@@ -187,10 +151,12 @@ class AccessCheckingService(context: Context) : SystemService(context) {
internal fun onStorageVolumeMounted(volumeUuid: String?, isSystemUpdated: Boolean) {
val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
val knownPackages = packageManagerInternal.knownPackages
mutateState {
with(policy) {
onStorageVolumeMounted(
packageStates, disabledSystemPackageStates, volumeUuid, isSystemUpdated
packageStates, disabledSystemPackageStates, knownPackages, volumeUuid,
isSystemUpdated
)
}
}
@@ -198,35 +164,48 @@ class AccessCheckingService(context: Context) : SystemService(context) {
internal fun onPackageAdded(packageName: String) {
val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
val knownPackages = packageManagerInternal.knownPackages
mutateState {
with(policy) { onPackageAdded(packageStates, disabledSystemPackageStates, packageName) }
with(policy) {
onPackageAdded(
packageStates, disabledSystemPackageStates, knownPackages, packageName
)
}
}
}
internal fun onPackageRemoved(packageName: String, appId: Int) {
val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
val knownPackages = packageManagerInternal.knownPackages
mutateState {
with(policy) {
onPackageRemoved(packageStates, disabledSystemPackageStates, packageName, appId)
onPackageRemoved(
packageStates, disabledSystemPackageStates, knownPackages, packageName, appId
)
}
}
}
internal fun onPackageInstalled(packageName: String, userId: Int) {
val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
val knownPackages = packageManagerInternal.knownPackages
mutateState {
with(policy) {
onPackageInstalled(packageStates, disabledSystemPackageStates, packageName, userId)
onPackageInstalled(
packageStates, disabledSystemPackageStates, knownPackages, packageName, userId
)
}
}
}
internal fun onPackageUninstalled(packageName: String, appId: Int, userId: Int) {
val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates
val knownPackages = packageManagerInternal.knownPackages
mutateState {
with(policy) {
onPackageUninstalled(
packageStates, disabledSystemPackageStates, packageName, appId, userId
packageStates, disabledSystemPackageStates, knownPackages, packageName, appId,
userId
)
}
}
@@ -236,6 +215,43 @@ class AccessCheckingService(context: Context) : SystemService(context) {
Pair<Map<String, PackageState>, Map<String, PackageState>>
get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates }
private val PackageManagerInternal.knownPackages: IntMap<Array<String>>
get() = IntMap<Array<String>>().apply {
this[KnownPackages.PACKAGE_INSTALLER] = getKnownPackageNames(
KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] = getKnownPackageNames(
KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_VERIFIER] = getKnownPackageNames(
KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_SETUP_WIZARD] = getKnownPackageNames(
KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] = getKnownPackageNames(
KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_CONFIGURATOR] = getKnownPackageNames(
KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] = getKnownPackageNames(
KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_APP_PREDICTOR] = getKnownPackageNames(
KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_COMPANION] = getKnownPackageNames(
KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_RETAIL_DEMO] = getKnownPackageNames(
KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM
)
this[KnownPackages.PACKAGE_RECENTS] = getKnownPackageNames(
KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM
)
}
@OptIn(ExperimentalContracts::class)
internal inline fun <T> getState(action: GetStateScope.() -> T): T {
contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) }

View File

@@ -16,8 +16,15 @@
package com.android.server.permission.access
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.os.SystemClock
import android.os.UserHandle
import android.util.AtomicFile
import android.util.Log
import com.android.internal.annotations.GuardedBy
import com.android.internal.os.BackgroundThread
import com.android.modules.utils.BinaryXmlPullParser
import com.android.modules.utils.BinaryXmlSerializer
import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports
@@ -32,6 +39,20 @@ import java.io.FileNotFoundException
class AccessPersistence(
private val policy: AccessPolicy
) {
private val scheduleLock = Any()
@GuardedBy("scheduleLock")
private val pendingMutationTimesMillis = IntLongMap()
@GuardedBy("scheduleLock")
private val pendingStates = IntMap<AccessState>()
@GuardedBy("scheduleLock")
private lateinit var writeHandler: WriteHandler
private val writeLock = Any()
fun initialize() {
writeHandler = WriteHandler(BackgroundThread.getHandler().looper)
}
fun read(state: AccessState) {
readSystemState(state)
state.systemState.userIds.forEachIndexed { _, userId ->
@@ -64,21 +85,61 @@ class AccessPersistence(
}
fun write(state: AccessState) {
writeState(state.systemState) { writeSystemState(state) }
state.systemState.write(state, UserHandle.USER_ALL)
state.userStates.forEachIndexed { _, userId, userState ->
writeState(userState) { writeUserState(state, userId) }
userState.write(state, userId)
}
}
private inline fun <T : WritableState> writeState(state: T, write: () -> Unit) {
when (val writeMode = state.writeMode) {
private fun WritableState.write(state: AccessState, userId: Int) {
when (val writeMode = writeMode) {
WriteMode.NONE -> {}
WriteMode.SYNC -> write()
WriteMode.ASYNC -> TODO()
WriteMode.SYNC -> {
synchronized(scheduleLock) { pendingStates[userId] = state }
writePendingState(userId)
}
WriteMode.ASYNC -> {
synchronized(scheduleLock) {
writeHandler.removeMessages(userId)
pendingStates[userId] = state
// SystemClock.uptimeMillis() is used in Handler.sendMessageDelayed().
val currentTimeMillis = SystemClock.uptimeMillis()
val pendingMutationTimeMillis =
pendingMutationTimesMillis.getOrPut(userId) { currentTimeMillis }
val currentDelayMillis = currentTimeMillis - pendingMutationTimeMillis
val message = writeHandler.obtainMessage(userId)
if (currentDelayMillis > MAX_WRITE_DELAY_MILLIS) {
message.sendToTarget()
} else {
val newDelayMillis = WRITE_DELAY_TIME_MILLIS
.coerceAtMost(MAX_WRITE_DELAY_MILLIS - currentDelayMillis)
writeHandler.sendMessageDelayed(message, newDelayMillis)
}
}
}
else -> error(writeMode)
}
}
private fun writePendingState(userId: Int) {
synchronized(writeLock) {
val state: AccessState?
synchronized(scheduleLock) {
pendingMutationTimesMillis -= userId
state = pendingStates.removeReturnOld(userId)
writeHandler.removeMessages(userId)
}
if (state == null) {
return
}
if (userId == UserHandle.USER_ALL) {
writeSystemState(state)
} else {
writeUserState(state, userId)
}
}
}
private fun writeSystemState(state: AccessState) {
systemFile.serialize {
with(policy) { serializeSystemState(state) }
@@ -109,5 +170,25 @@ class AccessPersistence(
private val LOG_TAG = AccessPersistence::class.java.simpleName
private const val FILE_NAME = "access.abx"
private const val WRITE_DELAY_TIME_MILLIS = 1000L
private const val MAX_WRITE_DELAY_MILLIS = 2000L
}
private inner class WriteHandler(looper: Looper) : Handler(looper) {
fun writeAtTime(userId: Int, timeMillis: Long) {
removeMessages(userId)
val message = obtainMessage(userId)
sendMessageDelayed(message, timeMillis)
}
fun cancelWrite(userId: Int) {
removeMessages(userId)
}
override fun handleMessage(message: Message) {
val userId = message.what
writePendingState(userId)
}
}
}

View File

@@ -82,6 +82,11 @@ class AccessPolicy private constructor(
this.permissionAllowlist = permissionAllowlist
this.implicitToSourcePermissions = implicitToSourcePermissions
}
state.userStates.apply {
userIds.forEachIndexed { _, userId ->
this[userId] = UserState()
}
}
}
fun GetStateScope.onStateMutated() {
@@ -115,12 +120,29 @@ class AccessPolicy private constructor(
fun MutateStateScope.onStorageVolumeMounted(
packageStates: Map<String, PackageState>,
disabledSystemPackageStates: Map<String, PackageState>,
knownPackages: IntMap<Array<String>>,
volumeUuid: String?,
isSystemUpdated: Boolean
) {
val addedAppIds = IntSet()
newState.systemState.apply {
this.packageStates = packageStates
this.disabledSystemPackageStates = disabledSystemPackageStates
packageStates.forEach { (packageName, packageState) ->
if (packageState.volumeUuid == volumeUuid) {
val appId = packageState.appId
appIds.getOrPut(appId) {
addedAppIds += appId
IndexedListSet()
} += packageName
}
}
this.knownPackages = knownPackages
}
addedAppIds.forEachIndexed { _, appId ->
forEachSchemePolicy {
with(it) { onAppIdAdded(appId) }
}
}
forEachSchemePolicy {
with(it) { onStorageVolumeMounted(volumeUuid, isSystemUpdated) }
@@ -130,6 +152,7 @@ class AccessPolicy private constructor(
fun MutateStateScope.onPackageAdded(
packageStates: Map<String, PackageState>,
disabledSystemPackageStates: Map<String, PackageState>,
knownPackages: IntMap<Array<String>>,
packageName: String
) {
val packageState = packageStates[packageName]
@@ -145,7 +168,8 @@ class AccessPolicy private constructor(
appIds.getOrPut(appId) {
isAppIdAdded = true
IndexedListSet()
}.add(packageName)
} += packageName
this.knownPackages = knownPackages
}
if (isAppIdAdded) {
forEachSchemePolicy {
@@ -160,6 +184,7 @@ class AccessPolicy private constructor(
fun MutateStateScope.onPackageRemoved(
packageStates: Map<String, PackageState>,
disabledSystemPackageStates: Map<String, PackageState>,
knownPackages: IntMap<Array<String>>,
packageName: String,
appId: Int
) {
@@ -178,6 +203,7 @@ class AccessPolicy private constructor(
isAppIdRemoved = true
}
}
this.knownPackages = knownPackages
}
forEachSchemePolicy {
with(it) { onPackageRemoved(packageName, appId) }
@@ -192,12 +218,14 @@ class AccessPolicy private constructor(
fun MutateStateScope.onPackageInstalled(
packageStates: Map<String, PackageState>,
disabledSystemPackageStates: Map<String, PackageState>,
knownPackages: IntMap<Array<String>>,
packageName: String,
userId: Int
) {
newState.systemState.apply {
this.packageStates = packageStates
this.disabledSystemPackageStates = disabledSystemPackageStates
this.knownPackages = knownPackages
}
val packageState = packageStates[packageName]
// TODO(zhanghai): STOPSHIP: Remove check before feature enable.
@@ -212,6 +240,7 @@ class AccessPolicy private constructor(
fun MutateStateScope.onPackageUninstalled(
packageStates: Map<String, PackageState>,
disabledSystemPackageStates: Map<String, PackageState>,
knownPackages: IntMap<Array<String>>,
packageName: String,
appId: Int,
userId: Int
@@ -219,6 +248,7 @@ class AccessPolicy private constructor(
newState.systemState.apply {
this.packageStates = packageStates
this.disabledSystemPackageStates = disabledSystemPackageStates
this.knownPackages = knownPackages
}
forEachSchemePolicy {
with(it) { onPackageUninstalled(packageName, appId, userId) }

View File

@@ -0,0 +1,171 @@
/*
* 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.collection
import android.util.SparseLongArray
typealias IntLongMap = SparseLongArray
inline fun IntLongMap.allIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
forEachIndexed { index, key, value ->
if (!predicate(index, key, value)) {
return false
}
}
return true
}
inline fun IntLongMap.anyIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
forEachIndexed { index, key, value ->
if (predicate(index, key, value)) {
return true
}
}
return false
}
@Suppress("NOTHING_TO_INLINE")
inline fun IntLongMap.copy(): IntLongMap = clone()
inline fun <R> IntLongMap.firstNotNullOfOrNullIndexed(transform: (Int, Int, Long) -> R): R? {
forEachIndexed { index, key, value ->
transform(index, key, value)?.let { return it }
}
return null
}
inline fun IntLongMap.forEachIndexed(action: (Int, Int, Long) -> Unit) {
for (index in 0 until size) {
action(index, keyAt(index), valueAt(index))
}
}
inline fun IntLongMap.forEachKeyIndexed(action: (Int, Int) -> Unit) {
for (index in 0 until size) {
action(index, keyAt(index))
}
}
inline fun IntLongMap.forEachReversedIndexed(action: (Int, Int, Long) -> Unit) {
for (index in lastIndex downTo 0) {
action(index, keyAt(index), valueAt(index))
}
}
inline fun IntLongMap.forEachValueIndexed(action: (Int, Long) -> Unit) {
for (index in 0 until size) {
action(index, valueAt(index))
}
}
inline fun IntLongMap.getOrPut(key: Int, defaultValue: () -> Long): Long {
val index = indexOfKey(key)
return if (index >= 0) {
valueAt(index)
} else {
defaultValue().also { put(key, it) }
}
}
@Suppress("NOTHING_TO_INLINE")
inline fun IntLongMap?.getWithDefault(key: Int, defaultValue: Long): Long {
this ?: return defaultValue
return get(key, defaultValue)
}
inline val IntLongMap.lastIndex: Int
get() = size - 1
@Suppress("NOTHING_TO_INLINE")
inline operator fun IntLongMap.minusAssign(key: Int) {
delete(key)
}
inline fun IntLongMap.noneIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
forEachIndexed { index, key, value ->
if (predicate(index, key, value)) {
return false
}
}
return true
}
@Suppress("NOTHING_TO_INLINE")
inline fun IntLongMap.putWithDefault(key: Int, value: Long, defaultValue: Long): Long {
val index = indexOfKey(key)
if (index >= 0) {
val oldValue = valueAt(index)
if (value != oldValue) {
if (value == defaultValue) {
removeAt(index)
} else {
setValueAt(index, value)
}
}
return oldValue
} else {
if (value != defaultValue) {
put(key, value)
}
return defaultValue
}
}
fun IntLongMap.remove(key: Int) {
delete(key)
}
fun IntLongMap.remove(key: Int, defaultValue: Long): Long {
val index = indexOfKey(key)
return if (index >= 0) {
val oldValue = valueAt(index)
removeAt(index)
oldValue
} else {
defaultValue
}
}
inline fun IntLongMap.removeAllIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
var isChanged = false
forEachReversedIndexed { index, key, value ->
if (predicate(index, key, value)) {
removeAt(index)
isChanged = true
}
}
return isChanged
}
inline fun IntLongMap.retainAllIndexed(predicate: (Int, Int, Long) -> Boolean): Boolean {
var isChanged = false
forEachReversedIndexed { index, key, value ->
if (!predicate(index, key, value)) {
removeAt(index)
isChanged = true
}
}
return isChanged
}
@Suppress("NOTHING_TO_INLINE")
inline operator fun IntLongMap.set(key: Int, value: Long) {
put(key, value)
}
inline val IntLongMap.size: Int
get() = size()

View File

@@ -157,7 +157,7 @@ data class Permission(
if (areGidsPerUser) {
IntArray(gids.size) { i -> UserHandle.getUid(userId, gids[i]) }
} else {
gids.clone()
gids.copyOf()
}
companion object {

View File

@@ -137,6 +137,7 @@ class PermissionService(
userManagerService = UserManagerService.getInstance()
handlerThread = ServiceThread(LOG_TAG, Process.THREAD_PRIORITY_BACKGROUND, true)
.apply { start() }
handler = Handler(handlerThread.looper)
onPermissionsChangeListeners = OnPermissionsChangeListeners(FgThread.get().looper)
onPermissionFlagsChangedListener = OnPermissionFlagsChangedListener()
@@ -578,7 +579,7 @@ class PermissionService(
// more consistent with the pre-S-refactor behavior. This is also because we are now
// actively trimming the per-UID objects when empty.
val permissionFlags = with(policy) { getUidPermissionFlags(appId, userId) }
?: return globalGids.clone()
?: return globalGids.copyOf()
val gids = GrowingIntArray.wrap(globalGids)
permissionFlags.forEachIndexed { _, permissionName, flags ->
@@ -654,6 +655,11 @@ class PermissionService(
)
}
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "$methodName: Unknown user $userId")
return
}
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = true, enforceShellRestriction = true, methodName
)
@@ -664,11 +670,6 @@ class PermissionService(
}
context.enforceCallingOrSelfPermission(enforcedPermissionName, methodName)
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "$methodName: Unknown user $userId")
return
}
val packageState: PackageState?
val permissionControllerPackageName = packageManagerInternal.getKnownPackageNames(
KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM
@@ -870,6 +871,11 @@ class PermissionService(
}
override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int {
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "getPermissionFlags: Unknown user $userId")
return 0
}
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = true, enforceShellRestriction = false,
"getPermissionFlags"
@@ -880,11 +886,6 @@ class PermissionService(
Manifest.permission.GET_RUNTIME_PERMISSIONS
)
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "getPermissionFlags: Unknown user $userId")
return 0
}
val packageState = packageManagerLocal.withFilteredSnapshot()
.use { it.getPackageState(packageName) }
if (packageState == null) {
@@ -910,16 +911,16 @@ class PermissionService(
permissionName: String,
userId: Int
): Boolean {
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = true, enforceShellRestriction = false,
"isPermissionRevokedByPolicy"
)
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "isPermissionRevokedByPolicy: Unknown user $userId")
return false
}
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = true, enforceShellRestriction = false,
"isPermissionRevokedByPolicy"
)
val packageState = packageManagerLocal.withFilteredSnapshot(Binder.getCallingUid(), userId)
.use { it.getPackageState(packageName) } ?: return false
@@ -954,16 +955,16 @@ class PermissionService(
permissionName: String,
userId: Int
): Boolean {
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = true, enforceShellRestriction = false,
"shouldShowRequestPermissionRationale"
)
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "shouldShowRequestPermissionRationale: Unknown user $userId")
return false
}
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = true, enforceShellRestriction = false,
"shouldShowRequestPermissionRationale"
)
val callingUid = Binder.getCallingUid()
val packageState = packageManagerLocal.withFilteredSnapshot(callingUid, userId)
.use { it.getPackageState(packageName) } ?: return false
@@ -1030,6 +1031,11 @@ class PermissionService(
)
}
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "updatePermissionFlags: Unknown user $userId")
return
}
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = true, enforceShellRestriction = true,
"updatePermissionFlags"
@@ -1062,11 +1068,6 @@ class PermissionService(
}
}
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "updatePermissionFlags: Unknown user $userId")
return
}
// Using PackageManagerInternal instead of PackageManagerLocal for now due to need to access
// shared user packages.
// TODO: We probably shouldn't check the share user packages, since the package name is
@@ -1124,6 +1125,11 @@ class PermissionService(
)
}
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "updatePermissionFlagsForAllApps: Unknown user $userId")
return
}
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = true, enforceShellRestriction = true,
"updatePermissionFlagsForAllApps"
@@ -1133,11 +1139,6 @@ class PermissionService(
Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
)
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "updatePermissionFlagsForAllApps: Unknown user $userId")
return
}
val packageStates = packageManagerLocal.withUnfilteredSnapshot()
.use { it.packageStates }
service.mutateState {
@@ -1229,16 +1230,16 @@ class PermissionService(
Preconditions.checkFlagsArgument(allowlistedFlags, PERMISSION_ALLOWLIST_MASK)
Preconditions.checkArgumentNonnegative(userId, "userId cannot be null")
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = false, enforceShellRestriction = false,
"getAllowlistedRestrictedPermissions"
)
if (!userManagerInternal.exists(userId)) {
Log.w(LOG_TAG, "AllowlistedRestrictedPermission api: Unknown user $userId")
return null
}
enforceCallingOrSelfCrossUserPermission(
userId, enforceFullPermission = false, enforceShellRestriction = false,
"getAllowlistedRestrictedPermissions"
)
val callingUid = Binder.getCallingUid()
val packageState = packageManagerLocal.withFilteredSnapshot(callingUid, userId)
.use { it.getPackageState(packageName) } ?: return null
@@ -1517,11 +1518,11 @@ class PermissionService(
}
override fun resetRuntimePermissions(androidPackage: AndroidPackage, userId: Int) {
TODO("Not yet implemented")
// TODO("Not yet implemented")
}
override fun resetRuntimePermissionsForUser(userId: Int) {
TODO("Not yet implemented")
// TODO("Not yet implemented")
}
override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) {
@@ -1657,33 +1658,36 @@ class PermissionService(
override fun getPermissionTEMP(
permissionName: String
): com.android.server.pm.permission.Permission? {
TODO("Not yet implemented")
// TODO("Not yet implemented")
return null
}
override fun getLegacyPermissions(): List<LegacyPermission> {
TODO("Not yet implemented")
// TODO("Not yet implemented")
return emptyList()
}
override fun readLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) {
// Package settings has been read when this method is called.
service.initialize()
TODO("Not yet implemented")
// TODO("Not yet implemented")
}
override fun writeLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) {
TODO("Not yet implemented")
// TODO("Not yet implemented")
}
override fun getLegacyPermissionState(appId: Int): LegacyPermissionState {
TODO("Not yet implemented")
// TODO("Not yet implemented")
return LegacyPermissionState()
}
override fun readLegacyPermissionStateTEMP() {
TODO("Not yet implemented")
// TODO("Not yet implemented")
}
override fun writeLegacyPermissionStateTEMP() {
TODO("Not yet implemented")
// TODO("Not yet implemented")
}
override fun onSystemReady() {

View File

@@ -271,7 +271,12 @@ class UidPermissionPolicy : SchemePolicy() {
this.packageName = packageName
protectionLevel = oldPermission.permissionInfo.protectionLevel
}
val newPermission = Permission(newPermissionInfo, false, oldPermission.type, 0)
// Different from the old implementation, which removes the GIDs upon permission
// adoption, but adds them back on the next boot, we now just consistently keep the
// GIDs.
val newPermission = oldPermission.copy(
permissionInfo = newPermissionInfo, isReconciled = false, appId = 0
)
permissions.setValueAt(permissionIndex, newPermission)
systemState.requestWrite()
changedPermissionNames += permissionName
@@ -385,7 +390,10 @@ class UidPermissionPolicy : SchemePolicy() {
}
if (oldPermission.type == Permission.TYPE_CONFIG && !oldPermission.isReconciled) {
// It's a config permission and has no owner, take ownership now.
Permission(newPermissionInfo, true, Permission.TYPE_CONFIG, packageState.appId)
oldPermission.copy(
permissionInfo = newPermissionInfo, isReconciled = true,
appId = packageState.appId
)
} else if (systemState.packageStates[oldPackageName]?.isSystem != true) {
Log.w(
LOG_TAG, "Overriding permission $permissionName with new declaration in" +
@@ -398,8 +406,12 @@ class UidPermissionPolicy : SchemePolicy() {
setPermissionFlags(appId, userId, permissionName, 0)
}
}
// Different from the old implementation, which removes the GIDs upon permission
// override, but adds them back on the next boot, we now just consistently keep
// the GIDs.
Permission(
newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId
newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId,
oldPermission.gids, oldPermission.areGidsPerUser
)
} else {
Log.w(
@@ -413,7 +425,17 @@ class UidPermissionPolicy : SchemePolicy() {
// Different from the old implementation, which doesn't update the permission
// definition upon app update, but does update it on the next boot, we now
// consistently update the permission definition upon app update.
Permission(newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId)
@Suppress("IfThenToElvis")
if (oldPermission != null) {
oldPermission.copy(
permissionInfo = newPermissionInfo, isReconciled = true,
appId = packageState.appId
)
} else {
Permission(
newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId
)
}
}
if (parsedPermission.isTree) {
@@ -498,7 +520,7 @@ class UidPermissionPolicy : SchemePolicy() {
// TODO: STOPSHIP: Retain permissions requested by disabled system packages.
}
newState.userStates.forEachIndexed { _, userId, userState ->
userState.uidPermissionFlags[appId].forEachReversedIndexed { _, permissionName, _ ->
userState.uidPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ ->
if (permissionName !in requestedPermissions) {
setPermissionFlags(appId, userId, permissionName, 0)
}
@@ -852,10 +874,12 @@ class UidPermissionPolicy : SchemePolicy() {
permissionName: String
): Boolean? {
val permissionAllowlist = newState.systemState.permissionAllowlist
// TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName. The below is only for
// passing compilation but won't actually work.
// TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName.
// val apexModuleName = androidPackage.apexModuleName
val apexModuleName = packageState.packageName
val apexModuleName = permissionAllowlist.apexPrivilegedAppAllowlists
.firstNotNullOfOrNullIndexed { _, apexModuleName, apexAllowlist ->
if (packageState.packageName in apexAllowlist) apexModuleName else null
}
val packageName = packageState.packageName
return when {
packageState.isVendor -> permissionAllowlist.getVendorPrivilegedAppAllowlistState(
@@ -901,7 +925,7 @@ class UidPermissionPolicy : SchemePolicy() {
return targetSdkVersion
}
private fun MutateStateScope.anyPackageInAppId(
private inline fun MutateStateScope.anyPackageInAppId(
appId: Int,
state: AccessState = newState,
predicate: (PackageState) -> Boolean
@@ -913,7 +937,7 @@ class UidPermissionPolicy : SchemePolicy() {
}
}
private fun MutateStateScope.forEachPackageInAppId(
private inline fun MutateStateScope.forEachPackageInAppId(
appId: Int,
state: AccessState = newState,
action: (PackageState) -> Unit