Revert "Make PermPolicySvc based on uid"
This reverts commit 4018617220.
Reason for revert: Did not improve performance, actually regressed it in most cases
Fixes: 149255086
Change-Id: Id89935e565b44110ae186757e9a2a7795aa5d56d
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user