Merge "Fix issues in the new permission & app op subsystems."
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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) }
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) }
|
||||
|
||||
@@ -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()
|
||||
@@ -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 {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user