Merge "Revert "Make PermPolicySvc based on uid""

This commit is contained in:
Philip P. Moltmann
2020-02-19 00:55:28 +00:00
committed by Android (Google) Code Review

View File

@@ -39,7 +39,9 @@ import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PermissionInfo;
import android.content.pm.parsing.AndroidPackage;
import android.os.Build;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
@@ -50,15 +52,14 @@ import android.telecom.TelecomManager;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.LongSparseLongArray;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseBooleanArray;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.app.IAppOpsCallback;
import com.android.internal.app.IAppOpsService;
import com.android.internal.infra.AndroidFuture;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IntPair;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
@@ -69,7 +70,6 @@ import com.android.server.policy.PermissionPolicyInternal.OnInitializedCallback;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
/**
@@ -100,7 +100,7 @@ public final class PermissionPolicyService extends SystemService {
* scheduled for a package/user.
*/
@GuardedBy("mLock")
private final ArraySet<Integer> mIsPackageSyncsScheduled = new ArraySet<>();
private final ArraySet<Pair<String, Integer>> mIsPackageSyncsScheduled = new ArraySet<>();
public PermissionPolicyService(@NonNull Context context) {
super(context);
@@ -125,8 +125,10 @@ public final class PermissionPolicyService extends SystemService {
@Override
public void onPackageChanged(String packageName, int uid) {
if (isStarted(UserHandle.getUserId(uid))) {
synchronizePackagePermissionsAndAppOpsForUser(uid);
final int userId = UserHandle.getUserId(uid);
if (isStarted(userId)) {
synchronizePackagePermissionsAndAppOpsForUser(packageName, userId);
}
}
@@ -137,21 +139,12 @@ public final class PermissionPolicyService extends SystemService {
});
permManagerInternal.addOnRuntimePermissionStateChangedListener(
(packageName, userId) -> {
int uid;
try {
uid = getContext().getPackageManager().getPackageUidAsUser(packageName, 0,
userId);
} catch (NameNotFoundException e) {
Slog.e(LOG_TAG, "Cannot synchronize changed package " + packageName, e);
return;
}
synchronizeUidPermissionsAndAppOpsAsync(uid);
});
this::synchronizePackagePermissionsAndAppOpsAsyncForUser);
mAppOpsCallback = new IAppOpsCallback.Stub() {
public void opChanged(int op, int uid, String packageName) {
synchronizeUidPermissionsAndAppOpsAsync(uid);
synchronizePackagePermissionsAndAppOpsAsyncForUser(packageName,
UserHandle.getUserId(uid));
}
};
@@ -201,17 +194,19 @@ public final class PermissionPolicyService extends SystemService {
return AppOpsManager.opToSwitch(op);
}
private void synchronizeUidPermissionsAndAppOpsAsync(int uid) {
if (isStarted(UserHandle.getUserId(uid))) {
private void synchronizePackagePermissionsAndAppOpsAsyncForUser(@NonNull String packageName,
@UserIdInt int changedUserId) {
if (isStarted(changedUserId)) {
synchronized (mLock) {
if (mIsPackageSyncsScheduled.add(uid)) {
if (mIsPackageSyncsScheduled.add(new Pair<>(packageName, changedUserId))) {
FgThread.getHandler().sendMessage(PooledLambda.obtainMessage(
PermissionPolicyService
::synchronizePackagePermissionsAndAppOpsForUser,
this, uid));
this, packageName, changedUserId));
} else {
if (DEBUG) {
Slog.v(LOG_TAG, "sync for " + uid + " already scheduled");
Slog.v(LOG_TAG, "sync for " + packageName + "/" + changedUserId
+ " already scheduled");
}
}
}
@@ -340,20 +335,39 @@ public final class PermissionPolicyService extends SystemService {
/**
* Synchronize a single package.
*/
private void synchronizePackagePermissionsAndAppOpsForUser(int uid) {
private void synchronizePackagePermissionsAndAppOpsForUser(@NonNull String packageName,
@UserIdInt int userId) {
synchronized (mLock) {
mIsPackageSyncsScheduled.remove(uid);
mIsPackageSyncsScheduled.remove(new Pair<>(packageName, userId));
}
if (DEBUG) {
Slog.v(LOG_TAG,
"synchronizePackagePermissionsAndAppOpsForUser(" + uid + ")");
"synchronizePackagePermissionsAndAppOpsForUser(" + packageName + ", "
+ userId + ")");
}
final PackageManagerInternal packageManagerInternal = LocalServices.getService(
PackageManagerInternal.class);
final PackageInfo pkg = packageManagerInternal.getPackageInfo(packageName, 0,
Process.SYSTEM_UID, userId);
if (pkg == null) {
return;
}
final PermissionToOpSynchroniser synchroniser = new PermissionToOpSynchroniser(
getUserContext(getContext(), UserHandle.getUserHandleForUid(uid)));
synchroniser.addUid(uid);
synchroniser.syncUids();
getUserContext(getContext(), UserHandle.of(userId)));
synchroniser.addPackage(pkg.packageName);
final String[] sharedPkgNames = packageManagerInternal.getSharedUserPackagesForPackage(
pkg.packageName, userId);
for (String sharedPkgName : sharedPkgNames) {
final AndroidPackage sharedPkg = packageManagerInternal
.getPackage(sharedPkgName);
if (sharedPkg != null) {
synchroniser.addPackage(sharedPkg.getPackageName());
}
}
synchroniser.syncPackages();
}
/**
@@ -367,8 +381,8 @@ public final class PermissionPolicyService extends SystemService {
final PermissionToOpSynchroniser synchronizer = new PermissionToOpSynchroniser(
getUserContext(getContext(), UserHandle.of(userId)));
packageManagerInternal.forEachPackage(
(pkg) -> synchronizer.addUid(pkg.getUid()));
synchronizer.syncUids();
(pkg) -> synchronizer.addPackage(pkg.getPackageName()));
synchronizer.syncPackages();
}
/**
@@ -383,51 +397,37 @@ public final class PermissionPolicyService extends SystemService {
private final @NonNull ArrayMap<String, PermissionInfo> mRuntimePermissionInfos;
// Cache uid -> packageNames
private SparseArray<String[]> mUidToPkg = new SparseArray<>();
/**
* All ops that need to be flipped to allow.
*
* @see #syncUids
* @see #syncPackages
*/
private final @NonNull ArraySet<OpToChange> mOpsToAllow = new ArraySet<>();
private final @NonNull ArrayList<OpToChange> mOpsToAllow = new ArrayList<>();
/**
* All ops that need to be flipped to ignore.
*
* @see #syncUids
* @see #syncPackages
*/
private final @NonNull ArraySet<OpToChange> mOpsToIgnore = new ArraySet<>();
private final @NonNull ArrayList<OpToChange> mOpsToIgnore = new ArrayList<>();
/**
* All ops that need to be flipped to ignore if not allowed.
*
* Currently, only used by soft restricted permissions logic.
*
* @see #syncUids
* @see #syncPackages
*/
private final @NonNull ArraySet<OpToChange> mOpsToIgnoreIfNotAllowed = new ArraySet<>();
private final @NonNull ArrayList<OpToChange> mOpsToIgnoreIfNotAllowed = new ArrayList<>();
/**
* All ops that need to be flipped to foreground.
*
* Currently, only used by the foreground/background permissions logic.
*
* @see #syncUids
* @see #syncPackages
*/
private final @NonNull ArraySet<OpToChange> mOpsToForeground = new ArraySet<>();
private @Nullable String[] getPackageNamesForUid(int uid) {
String[] pkgs = mUidToPkg.get(uid);
if (pkgs != null) {
return pkgs;
}
pkgs = mPackageManager.getPackagesForUid(uid);
mUidToPkg.put(uid, pkgs);
return pkgs;
}
private final @NonNull ArrayList<OpToChange> mOpsToForeground = new ArrayList<>();
PermissionToOpSynchroniser(@NonNull Context context) {
mContext = context;
@@ -449,11 +449,11 @@ public final class PermissionPolicyService extends SystemService {
}
/**
* Set app ops that were added in {@link #addUid}.
* Set app ops that were added in {@link #addPackage}.
*
* <p>This processes ops previously added by {@link #addAppOps(PackageInfo, String)}
*/
private void syncUids() {
private void syncPackages() {
// Remember which ops were already set. This makes sure that we always set the most
// permissive mode if two OpChanges are scheduled. This can e.g. happen if two
// permissions change the same op. See {@link #getSwitchOp}.
@@ -461,42 +461,42 @@ public final class PermissionPolicyService extends SystemService {
final int allowCount = mOpsToAllow.size();
for (int i = 0; i < allowCount; i++) {
final OpToChange op = mOpsToAllow.valueAt(i);
final OpToChange op = mOpsToAllow.get(i);
setUidModeAllowed(op.code, op.uid);
setUidModeAllowed(op.code, op.uid, op.packageName);
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
final int foregroundCount = mOpsToForeground.size();
for (int i = 0; i < foregroundCount; i++) {
final OpToChange op = mOpsToForeground.valueAt(i);
final OpToChange op = mOpsToForeground.get(i);
if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
continue;
}
setUidModeForeground(op.code, op.uid);
setUidModeForeground(op.code, op.uid, op.packageName);
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
final int ignoreCount = mOpsToIgnore.size();
for (int i = 0; i < ignoreCount; i++) {
final OpToChange op = mOpsToIgnore.valueAt(i);
final OpToChange op = mOpsToIgnore.get(i);
if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
continue;
}
setUidModeIgnored(op.code, op.uid);
setUidModeIgnored(op.code, op.uid, op.packageName);
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
final int ignoreIfNotAllowedCount = mOpsToIgnoreIfNotAllowed.size();
for (int i = 0; i < ignoreIfNotAllowedCount; i++) {
final OpToChange op = mOpsToIgnoreIfNotAllowed.valueAt(i);
final OpToChange op = mOpsToIgnoreIfNotAllowed.get(i);
if (alreadySetAppOps.indexOfKey(IntPair.of(op.uid, op.code)) >= 0) {
continue;
}
boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid);
boolean wasSet = setUidModeIgnoredIfNotAllowed(op.code, op.uid, op.packageName);
if (wasSet) {
alreadySetAppOps.put(IntPair.of(op.uid, op.code), 1);
}
@@ -555,7 +555,7 @@ public final class PermissionPolicyService extends SystemService {
}
int uid = packageInfo.applicationInfo.uid;
OpToChange opToChange = new OpToChange(uid, appOpCode);
OpToChange opToChange = new OpToChange(uid, packageName, appOpCode);
switch (appOpMode) {
case MODE_ALLOWED:
mOpsToAllow.add(opToChange);
@@ -618,7 +618,8 @@ public final class PermissionPolicyService extends SystemService {
}
int uid = packageInfo.applicationInfo.uid;
OpToChange extraOpToChange = new OpToChange(uid, extraOpCode);
String packageName = packageInfo.packageName;
OpToChange extraOpToChange = new OpToChange(uid, packageName, extraOpCode);
if (policy.mayAllowExtraAppOp()) {
mOpsToAllow.add(extraOpToChange);
} else {
@@ -631,56 +632,45 @@ public final class PermissionPolicyService extends SystemService {
}
/**
* Add a Uid for {@link #syncUids() processing} later.
* Add a package for {@link #syncPackages() processing} later.
*
* <p>Note: Called with the package lock held. Do <u>not</u> call into app-op manager.
*
* @param uid The uid to add for later processing.
* @param pkgName The package to add for later processing.
*/
void addUid(int uid) {
String[] pkgNames = getPackageNamesForUid(uid);
if (pkgNames == null) {
void addPackage(@NonNull String pkgName) {
final PackageInfo pkg;
try {
pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
} catch (NameNotFoundException e) {
return;
}
for (String pkgName : pkgNames) {
final PackageInfo pkg;
try {
pkg = mPackageManager.getPackageInfo(pkgName, GET_PERMISSIONS);
} catch (NameNotFoundException e) {
continue;
}
if (pkg.requestedPermissions == null) {
return;
}
if (pkg.requestedPermissions == null) {
continue;
}
for (String permission : pkg.requestedPermissions) {
addAppOps(pkg, permission);
}
for (String permission : pkg.requestedPermissions) {
addAppOps(pkg, permission);
}
}
private void setUidModeAllowed(int opCode, int uid) {
setUidMode(opCode, uid, MODE_ALLOWED);
private void setUidModeAllowed(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_ALLOWED, packageName);
}
private void setUidModeForeground(int opCode, int uid) {
setUidMode(opCode, uid, MODE_FOREGROUND);
private void setUidModeForeground(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_FOREGROUND, packageName);
}
private void setUidModeIgnored(int opCode, int uid) {
setUidMode(opCode, uid, MODE_IGNORED);
private void setUidModeIgnored(int opCode, int uid, @NonNull String packageName) {
setUidMode(opCode, uid, MODE_IGNORED, packageName);
}
private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid) {
String[] pkgsOfUid = getPackageNamesForUid(uid);
if (ArrayUtils.isEmpty(pkgsOfUid)) {
return false;
}
private boolean setUidModeIgnoredIfNotAllowed(int opCode, int uid,
@NonNull String packageName) {
final int currentMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
opCode), uid, pkgsOfUid[0]);
opCode), uid, packageName);
if (currentMode != MODE_ALLOWED) {
if (currentMode != MODE_IGNORED) {
mAppOpsManagerInternal.setUidModeFromPermissionPolicy(opCode, uid, MODE_IGNORED,
@@ -691,24 +681,20 @@ public final class PermissionPolicyService extends SystemService {
return false;
}
private void setUidMode(int opCode, int uid, int mode) {
String[] pkgsOfUid = getPackageNamesForUid(uid);
if (ArrayUtils.isEmpty(pkgsOfUid)) {
return;
}
private void setUidMode(int opCode, int uid, int mode,
@NonNull String packageName) {
final int oldMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
opCode), uid, pkgsOfUid[0]);
opCode), uid, packageName);
if (oldMode != mode) {
mAppOpsManagerInternal.setUidModeFromPermissionPolicy(opCode, uid, mode,
mAppOpsCallback);
final int newMode = mAppOpsManager.unsafeCheckOpRaw(AppOpsManager.opToPublicName(
opCode), uid, pkgsOfUid[0]);
opCode), uid, packageName);
if (newMode != mode) {
// Work around incorrectly-set package mode. It never makes sense for app ops
// related to runtime permissions, but can get in the way and we have to reset
// it.
mAppOpsManagerInternal.setModeFromPermissionPolicy(opCode, uid, pkgsOfUid[0],
mAppOpsManagerInternal.setModeFromPermissionPolicy(opCode, uid, packageName,
AppOpsManager.opToDefaultMode(opCode), mAppOpsCallback);
}
}
@@ -716,30 +702,14 @@ public final class PermissionPolicyService extends SystemService {
private class OpToChange {
final int uid;
final @NonNull String packageName;
final int code;
OpToChange(int uid, int code) {
OpToChange(int uid, @NonNull String packageName, int code) {
this.uid = uid;
this.packageName = packageName;
this.code = code;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
OpToChange other = (OpToChange) o;
return uid == other.uid && code == other.code;
}
@Override
public int hashCode() {
return Objects.hash(uid, code);
}
}
}