summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTreeHugger Robot <treehugger-gerrit@google.com>2020-09-22 22:18:40 +0000
committerAndroid (Google) Code Review <android-gerrit@google.com>2020-09-22 22:18:40 +0000
commitfbffe3f137dfcd10f0166ed41c446ac7fc7fa4d3 (patch)
treedf3691be0d065683daf99010ca0bb8c30c1aa1eb
parentcc848e93c1f97ff7ff2a12d8f7fa727b89932e84 (diff)
parent36744c716794df4b64f3975f165a2d7b2299316d (diff)
Merge "Refactor PermissionsState to be a data class for migration."
-rw-r--r--core/java/android/util/IntArray.java11
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java17
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java4
-rw-r--r--services/core/java/com/android/server/pm/SettingBase.java10
-rw-r--r--services/core/java/com/android/server/pm/Settings.java230
-rw-r--r--services/core/java/com/android/server/pm/permission/AppIdPermissionState.java320
-rw-r--r--services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java44
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java129
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java14
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionsState.java970
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java31
11 files changed, 591 insertions, 1189 deletions
diff --git a/core/java/android/util/IntArray.java b/core/java/android/util/IntArray.java
index 5a74ec0e52c0..b77265b0ebf6 100644
--- a/core/java/android/util/IntArray.java
+++ b/core/java/android/util/IntArray.java
@@ -144,6 +144,17 @@ public class IntArray implements Cloneable {
}
/**
+ * Adds the values in the specified array to this array.
+ */
+ public void addAll(int[] values) {
+ final int count = values.length;
+ ensureCapacity(count);
+
+ System.arraycopy(values, 0, mValues, mSize, count);
+ mSize += count;
+ }
+
+ /**
* Ensures capacity to append at least <code>count</code> values.
*/
private void ensureCapacity(int count) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 697c31a78ec7..16424d214995 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1849,7 +1849,6 @@ public class PackageManagerService extends IPackageManager.Stub
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mLock) {
removeMessages(WRITE_PACKAGE_LIST);
- mPermissionManager.writeStateToPackageSettingsTEMP();
mSettings.writePackageListLPr(msg.arg1);
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
@@ -2686,7 +2685,8 @@ public class PackageManagerService extends IPackageManager.Stub
(i, pm) ->
new Settings(Environment.getDataDirectory(),
i.getPermissionManagerServiceInternal().getPermissionSettings(),
- RuntimePermissionsPersistence.createInstance(), lock),
+ RuntimePermissionsPersistence.createInstance(),
+ i.getPermissionManagerServiceInternal(), lock),
new Injector.LocalServicesProducer<>(ActivityTaskManagerInternal.class),
new Injector.LocalServicesProducer<>(ActivityManagerInternal.class),
new Injector.LocalServicesProducer<>(DeviceIdleInternal.class),
@@ -4486,8 +4486,8 @@ public class PackageManagerService extends IPackageManager.Stub
AndroidPackage p = ps.pkg;
if (p != null) {
// Compute GIDs only if requested
- final int[] gids = (flags & PackageManager.GET_GIDS) == 0
- ? EMPTY_INT_ARRAY : mPermissionManager.getPackageGids(ps.name, userId);
+ final int[] gids = (flags & PackageManager.GET_GIDS) == 0 ? EMPTY_INT_ARRAY
+ : mPermissionManager.getGidsForUid(UserHandle.getUid(userId, ps.appId));
// Compute granted permissions only if package has requested permissions
final Set<String> permissions = ArrayUtils.isEmpty(p.getRequestedPermissions())
? Collections.emptySet()
@@ -4962,13 +4962,13 @@ public class PackageManagerService extends IPackageManager.Stub
}
// TODO: Shouldn't this be checking for package installed state for userId and
// return null?
- return mPermissionManager.getPackageGids(packageName, userId);
+ return mPermissionManager.getGidsForUid(UserHandle.getUid(userId, ps.appId));
}
if ((flags & MATCH_KNOWN_PACKAGES) != 0) {
final PackageSetting ps = mSettings.mPackages.get(packageName);
if (ps != null && ps.isMatch(flags)
&& !shouldFilterApplicationLocked(ps, callingUid, userId)) {
- return mPermissionManager.getPackageGids(packageName, userId);
+ return mPermissionManager.getGidsForUid(UserHandle.getUid(userId, ps.appId));
}
}
}
@@ -18983,7 +18983,7 @@ public class PackageManagerService extends IPackageManager.Stub
}
if ((deletedPs.sharedUser == null || deletedPs.sharedUser.packages.size() == 0)
&& !isUpdatedSystemApp(deletedPs)) {
- mPermissionManager.removePermissionsStateTEMP(removedAppId);
+ mPermissionManager.removeAppIdStateTEMP(removedAppId);
}
mPermissionManager.updatePermissions(deletedPs.name, null);
if (deletedPs.sharedUser != null) {
@@ -21854,8 +21854,6 @@ public class PackageManagerService extends IPackageManager.Stub
protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
- mPermissionManager.writeStateToPackageSettingsTEMP();
-
DumpState dumpState = new DumpState();
boolean fullPreferred = false;
boolean checkin = false;
@@ -23734,7 +23732,6 @@ public class PackageManagerService extends IPackageManager.Stub
mDirtyUsers.remove(userId);
mUserNeedsBadging.delete(userId);
mPermissionManager.onUserRemoved(userId);
- mPermissionManager.writeStateToPackageSettingsTEMP();
mSettings.removeUserLPw(userId);
mPendingBroadcasts.remove(userId);
mInstantAppRegistry.onUserRemovedLPw(userId);
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 276f88082df0..855a5ff524fd 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -28,7 +28,7 @@ import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.pm.parsing.pkg.AndroidPackage;
-import com.android.server.pm.permission.PermissionsState;
+import com.android.server.pm.permission.AppIdPermissionState;
import com.android.server.pm.pkg.PackageStateUnserialized;
import java.io.File;
@@ -215,7 +215,7 @@ public class PackageSetting extends PackageSettingBase {
}
@Override
- public PermissionsState getPermissionsState() {
+ public AppIdPermissionState getPermissionsState() {
return (sharedUser != null)
? sharedUser.getPermissionsState()
: super.getPermissionsState();
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 3e2ab05e83ec..c1258b1efd48 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -19,23 +19,23 @@ package com.android.server.pm;
import android.content.pm.ApplicationInfo;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.server.pm.permission.PermissionsState;
+import com.android.server.pm.permission.AppIdPermissionState;
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
public abstract class SettingBase {
int pkgFlags;
int pkgPrivateFlags;
- protected final PermissionsState mPermissionsState;
+ protected final AppIdPermissionState mPermissionsState;
SettingBase(int pkgFlags, int pkgPrivateFlags) {
setFlags(pkgFlags);
setPrivateFlags(pkgPrivateFlags);
- mPermissionsState = new PermissionsState();
+ mPermissionsState = new AppIdPermissionState();
}
SettingBase(SettingBase orig) {
- mPermissionsState = new PermissionsState();
+ mPermissionsState = new AppIdPermissionState();
doCopy(orig);
}
@@ -49,7 +49,7 @@ public abstract class SettingBase {
mPermissionsState.copyFrom(orig.mPermissionsState);
}
- public PermissionsState getPermissionsState() {
+ public AppIdPermissionState getPermissionsState() {
return mPermissionsState;
}
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 965430727d3c..bae36b2ad353 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -79,6 +79,7 @@ import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
+import android.util.IntArray;
import android.util.Log;
import android.util.LogPrinter;
import android.util.Pair;
@@ -106,10 +107,11 @@ import com.android.server.pm.Installer.InstallerException;
import com.android.server.pm.parsing.PackageInfoUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.parsing.pkg.AndroidPackageUtils;
+import com.android.server.pm.permission.AppIdPermissionState;
+import com.android.server.pm.permission.AppIdPermissionState.PermissionState;
import com.android.server.pm.permission.BasePermission;
+import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.permission.PermissionSettings;
-import com.android.server.pm.permission.PermissionsState;
-import com.android.server.pm.permission.PermissionsState.PermissionState;
import com.android.server.utils.TimingsTraceAndSlog;
import libcore.io.IoUtils;
@@ -416,9 +418,12 @@ public final class Settings {
private final File mSystemDir;
public final KeySetManagerService mKeySetManagerService = new KeySetManagerService(mPackages);
+
/** Settings and other information about permissions */
final PermissionSettings mPermissions;
+ private final LegacyPermissionDataProvider mPermissionDataProvider;
+
@VisibleForTesting(visibility = VisibleForTesting.Visibility.PRIVATE)
public Settings(Map<String, PackageSetting> pkgSettings) {
mLock = new Object();
@@ -426,6 +431,7 @@ public final class Settings {
mSystemDir = null;
mPermissions = null;
mRuntimePermissionsPersistence = null;
+ mPermissionDataProvider = null;
mSettingsFilename = null;
mBackupSettingsFilename = null;
mPackageListFilename = null;
@@ -434,12 +440,14 @@ public final class Settings {
mKernelMappingFilename = null;
}
- Settings(File dataDir, PermissionSettings permission,
- RuntimePermissionsPersistence runtimePermissionsPersistence, Object lock) {
+ Settings(File dataDir, PermissionSettings permissionSettings,
+ RuntimePermissionsPersistence runtimePermissionsPersistence,
+ LegacyPermissionDataProvider permissionDataProvider, Object lock) {
mLock = lock;
- mPermissions = permission;
+ mPermissions = permissionSettings;
mRuntimePermissionsPersistence = new RuntimePermissionPersistence(
- runtimePermissionsPersistence, mLock);
+ runtimePermissionsPersistence);
+ mPermissionDataProvider = permissionDataProvider;
mSystemDir = new File(dataDir, "system");
mSystemDir.mkdirs();
@@ -1239,7 +1247,7 @@ public final class Settings {
void writeAllRuntimePermissionsLPr() {
for (int userId : UserManagerService.getInstance().getUserIds()) {
- mRuntimePermissionsPersistence.writePermissionsForUserAsyncLPr(userId);
+ mRuntimePermissionsPersistence.writeStateForUserAsyncLPr(userId);
}
}
@@ -2102,7 +2110,7 @@ public final class Settings {
}
void readInstallPermissionsLPr(XmlPullParser parser,
- PermissionsState permissionsState) throws IOException, XmlPullParserException {
+ AppIdPermissionState permissionsState) throws IOException, XmlPullParserException {
int outerDepth = parser.getDepth();
int type;
while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
@@ -2131,25 +2139,7 @@ public final class Settings {
final int flags = (flagsStr != null)
? Integer.parseInt(flagsStr, 16) : 0;
- if (granted) {
- if (permissionsState.grantInstallPermission(bp) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- Slog.w(PackageManagerService.TAG, "Permission already added: " + name);
- XmlUtils.skipCurrentTag(parser);
- } else {
- permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
- }
- } else {
- if (permissionsState.revokeInstallPermission(bp) ==
- PermissionsState.PERMISSION_OPERATION_FAILURE) {
- Slog.w(PackageManagerService.TAG, "Permission already added: " + name);
- XmlUtils.skipCurrentTag(parser);
- } else {
- permissionsState.updatePermissionFlags(bp, UserHandle.USER_ALL,
- PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
- }
- }
+ permissionsState.putInstallPermissionState(new PermissionState(bp, granted, flags));
} else {
Slog.w(PackageManagerService.TAG, "Unknown element under <permissions>: "
+ parser.getName());
@@ -2158,7 +2148,7 @@ public final class Settings {
}
}
- void writePermissionsLPr(XmlSerializer serializer, List<PermissionState> permissionStates)
+ void writePermissionsLPr(XmlSerializer serializer, Collection<PermissionState> permissionStates)
throws IOException {
if (permissionStates.isEmpty()) {
return;
@@ -2641,7 +2631,11 @@ public final class Settings {
}
final boolean isDebug = pkg.pkg.isDebuggable();
- final int[] gids = pkg.getPermissionsState().computeGids(userIds);
+ final IntArray gids = new IntArray();
+ for (final int userId : userIds) {
+ gids.addAll(mPermissionDataProvider.getGidsForUid(UserHandle.getUid(userId,
+ pkg.appId)));
+ }
// Avoid any application that has a space in its path.
if (dataPath.indexOf(' ') >= 0)
@@ -2673,11 +2667,12 @@ public final class Settings {
sb.append(" ");
sb.append(AndroidPackageUtils.getSeInfo(pkg.pkg, pkg));
sb.append(" ");
- if (gids != null && gids.length > 0) {
- sb.append(gids[0]);
- for (int i = 1; i < gids.length; i++) {
+ final int gidsSize = gids.size();
+ if (gids != null && gids.size() > 0) {
+ sb.append(gids.get(0));
+ for (int i = 1; i < gidsSize; i++) {
sb.append(",");
- sb.append(gids[i]);
+ sb.append(gids.get(i));
}
} else {
sb.append("none");
@@ -4482,8 +4477,9 @@ public final class Settings {
}
void dumpPackageLPr(PrintWriter pw, String prefix, String checkinTag,
- ArraySet<String> permissionNames, PackageSetting ps, SimpleDateFormat sdf,
- Date date, List<UserInfo> users, boolean dumpAll, boolean dumpAllComponents) {
+ ArraySet<String> permissionNames, PackageSetting ps,
+ AppIdPermissionState permissionsState, SimpleDateFormat sdf, Date date,
+ List<UserInfo> users, boolean dumpAll, boolean dumpAllComponents) {
AndroidPackage pkg = ps.pkg;
if (checkinTag != null) {
pw.print(checkinTag);
@@ -4810,7 +4806,6 @@ public final class Settings {
}
if (ps.sharedUser == null || permissionNames != null || dumpAll) {
- PermissionsState permissionsState = ps.getPermissionsState();
dumpInstallPermissionsLPr(pw, prefix + " ", permissionNames, permissionsState);
}
@@ -4889,8 +4884,8 @@ public final class Settings {
}
if (ps.sharedUser == null) {
- PermissionsState permissionsState = ps.getPermissionsState();
- dumpGidsLPr(pw, prefix + " ", permissionsState.computeGids(user.id));
+ dumpGidsLPr(pw, prefix + " ", mPermissionDataProvider.getGidsForUid(
+ UserHandle.getUid(user.id, ps.appId)));
dumpRuntimePermissionsLPr(pw, prefix + " ", permissionNames, permissionsState
.getRuntimePermissionStates(user.id), dumpAll);
}
@@ -4933,8 +4928,10 @@ public final class Settings {
&& !packageName.equals(ps.name)) {
continue;
}
+ final AppIdPermissionState permissionsState =
+ mPermissionDataProvider.getAppIdPermissionState(ps.appId);
if (permissionNames != null
- && !ps.getPermissionsState().hasRequestedPermission(permissionNames)) {
+ && !permissionsState.hasPermissionState(permissionNames)) {
continue;
}
@@ -4948,8 +4945,8 @@ public final class Settings {
pw.println("Packages:");
printedSomething = true;
}
- dumpPackageLPr(pw, " ", checkin ? "pkg" : null, permissionNames, ps, sdf, date, users,
- packageName != null, dumpAllComponents);
+ dumpPackageLPr(pw, " ", checkin ? "pkg" : null, permissionNames, ps, permissionsState,
+ sdf, date, users, packageName != null, dumpAllComponents);
}
printedSomething = false;
@@ -4989,8 +4986,10 @@ public final class Settings {
pw.println("Hidden system packages:");
printedSomething = true;
}
- dumpPackageLPr(pw, " ", checkin ? "dis" : null, permissionNames, ps, sdf, date,
- users, packageName != null, dumpAllComponents);
+ final AppIdPermissionState permissionsState =
+ mPermissionDataProvider.getAppIdPermissionState(ps.appId);
+ dumpPackageLPr(pw, " ", checkin ? "dis" : null, permissionNames, ps,
+ permissionsState, sdf, date, users, packageName != null, dumpAllComponents);
}
}
}
@@ -5018,8 +5017,10 @@ public final class Settings {
if (packageName != null && su != dumpState.getSharedUser()) {
continue;
}
+ final AppIdPermissionState permissionsState =
+ mPermissionDataProvider.getAppIdPermissionState(su.userId);
if (permissionNames != null
- && !su.getPermissionsState().hasRequestedPermission(permissionNames)) {
+ && !permissionsState.hasPermissionState(permissionNames)) {
continue;
}
if (!checkin) {
@@ -5054,12 +5055,12 @@ public final class Settings {
continue;
}
- final PermissionsState permissionsState = su.getPermissionsState();
dumpInstallPermissionsLPr(pw, prefix, permissionNames, permissionsState);
for (int userId : UserManagerService.getInstance().getUserIds()) {
- final int[] gids = permissionsState.computeGids(userId);
- final List<PermissionState> permissions =
+ final int[] gids = mPermissionDataProvider.getGidsForUid(UserHandle.getUid(
+ userId, su.userId));
+ final Collection<PermissionState> permissions =
permissionsState.getRuntimePermissionStates(userId);
if (!ArrayUtils.isEmpty(gids) || !permissions.isEmpty()) {
pw.print(prefix); pw.print("User "); pw.print(userId); pw.println(": ");
@@ -5120,7 +5121,7 @@ public final class Settings {
}
void dumpRuntimePermissionsLPr(PrintWriter pw, String prefix, ArraySet<String> permissionNames,
- List<PermissionState> permissionStates, boolean dumpAll) {
+ Collection<PermissionState> permissionStates, boolean dumpAll) {
if (!permissionStates.isEmpty() || dumpAll) {
pw.print(prefix); pw.println("runtime permissions:");
for (PermissionState permissionState : permissionStates) {
@@ -5161,8 +5162,9 @@ public final class Settings {
}
void dumpInstallPermissionsLPr(PrintWriter pw, String prefix, ArraySet<String> permissionNames,
- PermissionsState permissionsState) {
- List<PermissionState> permissionStates = permissionsState.getInstallPermissionStates();
+ AppIdPermissionState permissionsState) {
+ Collection<PermissionState> permissionStates =
+ permissionsState.getInstallPermissionStates();
if (!permissionStates.isEmpty()) {
pw.print(prefix); pw.println("install permissions:");
for (PermissionState permissionState : permissionStates) {
@@ -5202,9 +5204,9 @@ public final class Settings {
public void writeRuntimePermissionsForUserLPr(int userId, boolean sync) {
if (sync) {
- mRuntimePermissionsPersistence.writePermissionsForUserSyncLPr(userId);
+ mRuntimePermissionsPersistence.writeStateForUserSyncLPr(userId);
} else {
- mRuntimePermissionsPersistence.writePermissionsForUserAsyncLPr(userId);
+ mRuntimePermissionsPersistence.writeStateForUserAsyncLPr(userId);
}
}
@@ -5292,8 +5294,6 @@ public final class Settings {
private final Handler mHandler = new MyHandler();
- private final Object mPersistenceLock;
-
@GuardedBy("mLock")
private final SparseBooleanArray mWriteScheduled = new SparseBooleanArray();
@@ -5313,10 +5313,8 @@ public final class Settings {
// The mapping keys are user ids.
private final SparseBooleanArray mPermissionUpgradeNeeded = new SparseBooleanArray();
- public RuntimePermissionPersistence(RuntimePermissionsPersistence persistence,
- Object persistenceLock) {
+ public RuntimePermissionPersistence(RuntimePermissionsPersistence persistence) {
mPersistence = persistence;
- mPersistenceLock = persistenceLock;
}
@GuardedBy("Settings.this.mLock")
@@ -5327,7 +5325,7 @@ public final class Settings {
@GuardedBy("Settings.this.mLock")
void setVersionLPr(int version, int userId) {
mVersions.put(userId, version);
- writePermissionsForUserAsyncLPr(userId);
+ writeStateForUserAsyncLPr(userId);
}
@GuardedBy("Settings.this.mLock")
@@ -5342,7 +5340,7 @@ public final class Settings {
+ "set before trying to update the fingerprint.");
}
mFingerprints.put(userId, mExtendedFingerprint);
- writePermissionsForUserAsyncLPr(userId);
+ writeStateForUserAsyncLPr(userId);
}
public void setPermissionControllerVersion(long version) {
@@ -5361,13 +5359,7 @@ public final class Settings {
return Build.FINGERPRINT + "?pc_version=" + version;
}
- public void writePermissionsForUserSyncLPr(int userId) {
- mHandler.removeMessages(userId);
- writePermissionsSync(userId);
- }
-
- @GuardedBy("Settings.this.mLock")
- public void writePermissionsForUserAsyncLPr(int userId) {
+ public void writeStateForUserAsyncLPr(int userId) {
final long currentTimeMillis = SystemClock.uptimeMillis();
if (mWriteScheduled.get(userId)) {
@@ -5399,59 +5391,53 @@ public final class Settings {
}
}
- private void writePermissionsSync(int userId) {
- RuntimePermissionsState runtimePermissions;
- synchronized (mPersistenceLock) {
- mWriteScheduled.delete(userId);
-
- int version = mVersions.get(userId, INITIAL_VERSION);
+ public void writeStateForUserSyncLPr(int userId) {
+ mHandler.removeMessages(userId);
+ mWriteScheduled.delete(userId);
- String fingerprint = mFingerprints.get(userId);
+ int version = mVersions.get(userId, INITIAL_VERSION);
- Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions =
- new ArrayMap<>();
- int packagesSize = mPackages.size();
- for (int i = 0; i < packagesSize; i++) {
- String packageName = mPackages.keyAt(i);
- PackageSetting packageSetting = mPackages.valueAt(i);
- if (packageSetting.sharedUser == null) {
- List<RuntimePermissionsState.PermissionState> permissions =
- getPermissionsFromPermissionsState(
- packageSetting.getPermissionsState(), userId);
- packagePermissions.put(packageName, permissions);
- }
- }
+ String fingerprint = mFingerprints.get(userId);
- Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions =
- new ArrayMap<>();
- final int sharedUsersSize = mSharedUsers.size();
- for (int i = 0; i < sharedUsersSize; i++) {
- String sharedUserName = mSharedUsers.keyAt(i);
- SharedUserSetting sharedUserSetting = mSharedUsers.valueAt(i);
+ Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions =
+ new ArrayMap<>();
+ int packagesSize = mPackages.size();
+ for (int i = 0; i < packagesSize; i++) {
+ String packageName = mPackages.keyAt(i);
+ PackageSetting packageSetting = mPackages.valueAt(i);
+ if (packageSetting.sharedUser == null) {
List<RuntimePermissionsState.PermissionState> permissions =
getPermissionsFromPermissionsState(
- sharedUserSetting.getPermissionsState(), userId);
- sharedUserPermissions.put(sharedUserName, permissions);
+ packageSetting.getPermissionsState(), userId);
+ packagePermissions.put(packageName, permissions);
}
+ }
- runtimePermissions = new RuntimePermissionsState(version, fingerprint,
- packagePermissions, sharedUserPermissions);
+ Map<String, List<RuntimePermissionsState.PermissionState>> sharedUserPermissions =
+ new ArrayMap<>();
+ final int sharedUsersSize = mSharedUsers.size();
+ for (int i = 0; i < sharedUsersSize; i++) {
+ String sharedUserName = mSharedUsers.keyAt(i);
+ SharedUserSetting sharedUserSetting = mSharedUsers.valueAt(i);
+ List<RuntimePermissionsState.PermissionState> permissions =
+ getPermissionsFromPermissionsState(
+ sharedUserSetting.getPermissionsState(), userId);
+ sharedUserPermissions.put(sharedUserName, permissions);
}
+ RuntimePermissionsState runtimePermissions = new RuntimePermissionsState(version,
+ fingerprint, packagePermissions, sharedUserPermissions);
+
mPersistence.writeForUser(runtimePermissions, UserHandle.of(userId));
}
@NonNull
private List<RuntimePermissionsState.PermissionState> getPermissionsFromPermissionsState(
- @NonNull PermissionsState permissionsState, @UserIdInt int userId) {
- List<PermissionState> permissionStates = permissionsState.getRuntimePermissionStates(
- userId);
- List<RuntimePermissionsState.PermissionState> permissions =
- new ArrayList<>();
- int permissionStatesSize = permissionStates.size();
- for (int i = 0; i < permissionStatesSize; i++) {
- PermissionState permissionState = permissionStates.get(i);
-
+ @NonNull AppIdPermissionState permissionsState, @UserIdInt int userId) {
+ Collection<PermissionState> permissionStates =
+ permissionsState.getRuntimePermissionStates(userId);
+ List<RuntimePermissionsState.PermissionState> permissions = new ArrayList<>();
+ for (PermissionState permissionState : permissionStates) {
RuntimePermissionsState.PermissionState permission =
new RuntimePermissionsState.PermissionState(permissionState.getName(),
permissionState.isGranted(), permissionState.getFlags());
@@ -5480,7 +5466,7 @@ public final class Settings {
userId));
if (runtimePermissions == null) {
readLegacyStateForUserSyncLPr(userId);
- writePermissionsForUserAsyncLPr(userId);
+ writeStateForUserAsyncLPr(userId);
return;
}
@@ -5536,7 +5522,7 @@ public final class Settings {
private void readPermissionsStateLpr(
@NonNull List<RuntimePermissionsState.PermissionState> permissions,
- @NonNull PermissionsState permissionsState, @UserIdInt int userId) {
+ @NonNull AppIdPermissionState permissionsState, @UserIdInt int userId) {
int permissionsSize = permissions.size();
for (int i = 0; i < permissionsSize; i++) {
RuntimePermissionsState.PermissionState permission = permissions.get(i);
@@ -5550,14 +5536,8 @@ public final class Settings {
boolean granted = permission.isGranted();
int flags = permission.getFlags();
- if (granted) {
- permissionsState.grantRuntimePermission(basePermission, userId);
- permissionsState.updatePermissionFlags(basePermission, userId,
- PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
- } else {
- permissionsState.updatePermissionFlags(basePermission, userId,
- PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
- }
+ permissionsState.putRuntimePermissionState(new PermissionState(basePermission,
+ granted, flags), userId);
}
}
@@ -5638,8 +5618,9 @@ public final class Settings {
}
}
- private void parsePermissionsLPr(XmlPullParser parser, PermissionsState permissionsState,
- int userId) throws IOException, XmlPullParserException {
+ private void parsePermissionsLPr(XmlPullParser parser,
+ AppIdPermissionState permissionsState, int userId)
+ throws IOException, XmlPullParserException {
final int outerDepth = parser.getDepth();
int type;
while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -5666,15 +5647,8 @@ public final class Settings {
final int flags = (flagsStr != null)
? Integer.parseInt(flagsStr, 16) : 0;
- if (granted) {
- permissionsState.grantRuntimePermission(bp, userId);
- permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
- } else {
- permissionsState.updatePermissionFlags(bp, userId,
- PackageManager.MASK_PERMISSION_FLAGS_ALL, flags);
- }
-
+ permissionsState.putRuntimePermissionState(new PermissionState(bp, granted,
+ flags), userId);
}
break;
}
@@ -5690,7 +5664,9 @@ public final class Settings {
public void handleMessage(Message message) {
final int userId = message.what;
Runnable callback = (Runnable) message.obj;
- writePermissionsSync(userId);
+ synchronized (mLock) {
+ writeStateForUserSyncLPr(userId);
+ }
if (callback != null) {
callback.run();
}
diff --git a/services/core/java/com/android/server/pm/permission/AppIdPermissionState.java b/services/core/java/com/android/server/pm/permission/AppIdPermissionState.java
new file mode 100644
index 000000000000..aabdafdd453a
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/AppIdPermissionState.java
@@ -0,0 +1,320 @@
+/*
+ * Copyright (C) 2015 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.annotation.UserIdInt;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Objects;
+
+/**
+ * Legacy permission state that was associated with packages or shared users.
+ */
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public final class AppIdPermissionState {
+ // Maps from user IDs to user states.
+ @NonNull
+ private final SparseArray<UserState> mUserStates = new SparseArray<>();
+
+ // Keyed by user IDs.
+ @NonNull
+ private final SparseBooleanArray mMissing = new SparseBooleanArray();
+
+ /**
+ * Copy from another permission state.
+ *
+ * @param other the other permission state.
+ *
+ * @hide
+ */
+ public void copyFrom(@NonNull AppIdPermissionState other) {
+ if (other == this) {
+ return;
+ }
+
+ mUserStates.clear();
+ final int userStatesSize = other.mUserStates.size();
+ for (int i = 0; i < userStatesSize; i++) {
+ mUserStates.put(other.mUserStates.keyAt(i),
+ new UserState(other.mUserStates.valueAt(i)));
+ }
+
+ mMissing.clear();
+ final int missingSize = other.mMissing.size();
+ for (int i = 0; i < missingSize; i++) {
+ mMissing.put(other.mMissing.keyAt(i), other.mMissing.valueAt(i));
+ }
+ }
+
+ /**
+ * Reset this permission state.
+ *
+ * @hide
+ */
+ public void reset() {
+ mUserStates.clear();
+ mMissing.clear();
+ }
+
+ @Override
+ public boolean equals(@Nullable Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (object == null) {
+ return false;
+ }
+ if (getClass() != object.getClass()) {
+ return false;
+ }
+ final AppIdPermissionState other = (AppIdPermissionState) object;
+ return Objects.equals(mUserStates, other.mUserStates)
+ && Objects.equals(mMissing, other.mMissing);
+ }
+
+ /**
+ * Put a install permission state.
+ *
+ * @param permissionState the permission state
+ */
+ public void putInstallPermissionState(@NonNull PermissionState permissionState) {
+ putPermissionState(permissionState, UserHandle.USER_ALL);
+ }
+
+ /**
+ * Put a runtime permission state for a user.
+ *
+ * @param permissionState the permission state
+ * @param userId the user ID
+ */
+ public void putRuntimePermissionState(@NonNull PermissionState permissionState,
+ @UserIdInt int userId) {
+ checkUserId(userId);
+ putPermissionState(permissionState, userId);
+ }
+
+ private void putPermissionState(@NonNull PermissionState permissionState,
+ @UserIdInt int userId) {
+ UserState userState = mUserStates.get(userId);
+ if (userState == null) {
+ userState = new UserState();
+ mUserStates.put(userId, userState);
+ }
+ userState.putPermissionState(permissionState);
+ }
+
+ /**
+ * Check whether there are any permission states for the given permissions.
+ *
+ * @param permissionNames the permission names
+ * @return whether there are any permission states
+ *
+ * @hide
+ */
+ public boolean hasPermissionState(@NonNull Collection<String> permissionNames) {
+ final int userStatesSize = mUserStates.size();
+ for (int i = 0; i < userStatesSize; i++) {
+ final UserState userState = mUserStates.valueAt(i);
+ for (final String permissionName : permissionNames) {
+ if (userState.getPermissionState(permissionName) != null) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Get all the install permission states.
+ *
+ * @return the install permission states
+ */
+ @NonNull
+ public Collection<PermissionState> getInstallPermissionStates() {
+ return getPermissionStates(UserHandle.USER_ALL);
+ }
+
+ /**
+ * Get all the runtime permission states for a user.
+ *
+ * @param userId the user ID
+ * @return the runtime permission states
+ */
+ @NonNull
+ public Collection<PermissionState> getRuntimePermissionStates(@UserIdInt int userId) {
+ checkUserId(userId);
+ return getPermissionStates(userId);
+ }
+
+ @NonNull
+ private Collection<PermissionState> getPermissionStates(@UserIdInt int userId) {
+ final UserState userState = mUserStates.get(userId);
+ if (userState == null) {
+ return Collections.emptyList();
+ }
+ return userState.getPermissionStates();
+ }
+
+ /**
+ * Check whether the permission state is missing for a user.
+ * <p>
+ * This can happen if permission state is rolled back and we'll need to generate a reasonable
+ * default state to keep the app usable.
+ *
+ * @param userId the user ID
+ * @return whether the permission state is missing
+ */
+ public boolean isMissing(@UserIdInt int userId) {
+ checkUserId(userId);
+ return mMissing.get(userId);
+ }
+
+ /**
+ * Set whether the permission state is missing for a user.
+ * <p>
+ * This can happen if permission state is rolled back and we'll need to generate a reasonable
+ * default state to keep the app usable.
+ *
+ * @param missing whether the permission state is missing
+ * @param userId the user ID
+ */
+ public void setMissing(boolean missing, @UserIdInt int userId) {
+ checkUserId(userId);
+ if (missing) {
+ mMissing.put(userId, true);
+ } else {
+ mMissing.delete(userId);
+ }
+ }
+
+ private static void checkUserId(@UserIdInt int userId) {
+ if (userId < 0) {
+ throw new IllegalArgumentException("Invalid user ID " + userId);
+ }
+ }
+
+ /**
+ * Legacy state for permissions for a user.
+ */
+ private static final class UserState {
+ // Maps from permission names to permission states.
+ @NonNull
+ private final ArrayMap<String, PermissionState> mPermissionStates = new ArrayMap<>();
+
+ public UserState() {}
+
+ public UserState(@NonNull UserState other) {
+ final int permissionStatesSize = other.mPermissionStates.size();
+ for (int i = 0; i < permissionStatesSize; i++) {
+ mPermissionStates.put(other.mPermissionStates.keyAt(i),
+ new PermissionState(other.mPermissionStates.valueAt(i)));
+ }
+ }
+
+ @Nullable
+ public PermissionState getPermissionState(@NonNull String permissionName) {
+ return mPermissionStates.get(permissionName);
+ }
+
+ public void putPermissionState(@NonNull PermissionState permissionState) {
+ mPermissionStates.put(permissionState.getName(), permissionState);
+ }
+
+ @NonNull
+ public Collection<PermissionState> getPermissionStates() {
+ return Collections.unmodifiableCollection(mPermissionStates.values());
+ }
+ }
+
+ /**
+ * Legacy state for a single permission.
+ */
+ public static final class PermissionState {
+ @NonNull
+ private final BasePermission mPermission;
+
+ private final boolean mGranted;
+
+ private final int mFlags;
+
+ /**
+ * Create a new instance of this class.
+ *
+ * @param permission the {@link BasePermission} for the permission
+ * @param granted whether the permission is granted
+ * @param flags the permission flags
+ */
+ public PermissionState(@NonNull BasePermission permission, boolean granted, int flags) {
+ mPermission = permission;
+ mGranted = granted;
+ mFlags = flags;
+ }
+
+ private PermissionState(@NonNull PermissionState other) {
+ mPermission = other.mPermission;
+ mGranted = other.mGranted;
+ mFlags = other.mFlags;
+ }
+
+ /**
+ * Get the {@link BasePermission} for the permission.
+ *
+ * @return the {@link BasePermission}
+ */
+ @NonNull
+ public BasePermission getPermission() {
+ return mPermission;
+ }
+
+ /**
+ * Get the permission name.
+ *
+ * @return the permission name
+ */
+ @NonNull
+ public String getName() {
+ return mPermission.getName();
+ }
+
+ /**
+ * Get whether the permission is granted.
+ *
+ * @return whether the permission is granted
+ */
+ @NonNull
+ public boolean isGranted() {
+ return mGranted;
+ }
+
+ /**
+ * Get the permission flags.
+ *
+ * @return the permission flags
+ */
+ @NonNull
+ public int getFlags() {
+ return mFlags;
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java
new file mode 100644
index 000000000000..7452b522b20a
--- /dev/null
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionDataProvider.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2020 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.AppIdInt;
+import android.annotation.NonNull;
+
+/**
+ * An interface for legacy code to read permission data in order to maintain compatibility.
+ */
+//@SystemApi(client = SystemApi.Client.SYSTEM_SERVER)
+public interface LegacyPermissionDataProvider {
+ /**
+ * Get the legacy permission state of an app ID, either a package or a shared user.
+ *
+ * @param appId the app ID
+ * @return the legacy permission state
+ */
+ @NonNull
+ public abstract AppIdPermissionState getAppIdPermissionState(@AppIdInt int appId);
+
+ /**
+ * Get the GIDs computed from the permission state of a UID, either a package or a shared user.
+ *
+ * @param uid the UID
+ * @return the GIDs for the UID
+ */
+ @NonNull
+ public abstract int[] getGidsForUid(int uid);
+}
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 2f9e199bc506..544f1225916e 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -58,6 +58,7 @@ import static com.android.server.pm.permission.UidPermissionState.PERMISSION_OPE
import static java.util.concurrent.TimeUnit.SECONDS;
import android.Manifest;
+import android.annotation.AppIdInt;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -2514,20 +2515,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return permission.computeGids(userId);
}
- @Nullable
- private int[] getPackageGids(@NonNull String packageName, @UserIdInt int userId) {
- final PackageSetting ps = mPackageManagerInt.getPackageSetting(packageName);
- if (ps == null) {
- return null;
- }
- final UidPermissionState uidState = getUidState(ps, userId);
- if (uidState == null) {
- Slog.e(TAG, "Missing permissions state for " + packageName + " and user " + userId);
- return null;
- }
- return uidState.computeGids(userId);
- }
-
/**
* Restore the permission state for a package.
*
@@ -4766,7 +4753,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- private void removeAppState(int appId) {
+ private void removeAppIdState(@AppIdInt int appId) {
synchronized (mLock) {
final int[] userIds = mState.getUserIds();
for (final int userId : userIds) {
@@ -4780,7 +4767,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int[] userIds = getAllUserIds();
mPackageManagerInt.forEachPackageSetting(ps -> {
final int appId = ps.getAppId();
- final PermissionsState permissionsState = ps.getPermissionsState();
+ final AppIdPermissionState appIdState = ps.getPermissionsState();
synchronized (mLock) {
for (final int userId : userIds) {
@@ -4789,25 +4776,22 @@ public class PermissionManagerService extends IPermissionManager.Stub {
userState.setInstallPermissionsFixed(ps.name, ps.areInstallPermissionsFixed());
final UidPermissionState uidState = userState.getOrCreateUidState(appId);
uidState.reset();
- uidState.setGlobalGids(permissionsState.getGlobalGids());
- uidState.setMissing(permissionsState.isMissing(userId));
+ uidState.setMissing(appIdState.isMissing(userId));
readStateFromPermissionStates(uidState,
- permissionsState.getInstallPermissionStates(), false);
+ appIdState.getInstallPermissionStates(), false);
readStateFromPermissionStates(uidState,
- permissionsState.getRuntimePermissionStates(userId), true);
+ appIdState.getRuntimePermissionStates(userId), true);
}
}
});
}
private void readStateFromPermissionStates(@NonNull UidPermissionState uidState,
- @NonNull List<PermissionsState.PermissionState> permissionStates, boolean isRuntime) {
- final int permissionStatesSize = permissionStates.size();
- for (int i = 0; i < permissionStatesSize; i++) {
- final PermissionsState.PermissionState permissionState = permissionStates.get(i);
- final BasePermission permission = permissionState.getPermission();
- uidState.putPermissionState(permission, isRuntime, permissionState.isGranted(),
- permissionState.getFlags());
+ @NonNull Collection<AppIdPermissionState.PermissionState> permissionStates,
+ boolean isRuntime) {
+ for (final AppIdPermissionState.PermissionState permissionState : permissionStates) {
+ uidState.putPermissionState(permissionState.getPermission(), isRuntime,
+ permissionState.isGranted(), permissionState.getFlags());
}
}
@@ -4815,8 +4799,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final int[] userIds = mState.getUserIds();
mPackageManagerInt.forEachPackageSetting(ps -> {
ps.setInstallPermissionsFixed(false);
- final PermissionsState permissionsState = ps.getPermissionsState();
- permissionsState.reset();
+ final AppIdPermissionState appIdState = ps.getPermissionsState();
+ appIdState.reset();
final int appId = ps.getAppId();
synchronized (mLock) {
@@ -4838,27 +4822,21 @@ public class PermissionManagerService extends IPermissionManager.Stub {
continue;
}
- permissionsState.setGlobalGids(uidState.getGlobalGids());
- permissionsState.setMissing(uidState.isMissing(), userId);
+ appIdState.setMissing(uidState.isMissing(), userId);
final List<PermissionState> permissionStates = uidState.getPermissionStates();
final int permissionStatesSize = permissionStates.size();
for (int i = 0; i < permissionStatesSize; i++) {
final PermissionState permissionState = permissionStates.get(i);
- final BasePermission permission = permissionState.getPermission();
- if (permissionState.isGranted()) {
- if (permissionState.isRuntime()) {
- permissionsState.grantRuntimePermission(permission, userId);
- } else {
- permissionsState.grantInstallPermission(permission);
- }
- }
- final int flags = permissionState.getFlags();
- if (flags != 0) {
- final int flagsUserId = permissionState.isRuntime() ? userId
- : UserHandle.USER_ALL;
- permissionsState.updatePermissionFlags(permission, flagsUserId, flags,
- flags);
+ final AppIdPermissionState.PermissionState legacyPermissionState =
+ new AppIdPermissionState.PermissionState(
+ permissionState.getPermission(),
+ permissionState.isGranted(), permissionState.getFlags());
+ if (permissionState.isRuntime()) {
+ appIdState.putRuntimePermissionState(legacyPermissionState,
+ userId);
+ } else {
+ appIdState.putInstallPermissionState(legacyPermissionState);
}
}
}
@@ -4866,6 +4844,48 @@ public class PermissionManagerService extends IPermissionManager.Stub {
});
}
+ @NonNull
+ private AppIdPermissionState getAppIdPermissionState(@AppIdInt int appId) {
+ final AppIdPermissionState appIdState = new AppIdPermissionState();
+ final int[] userIds = mState.getUserIds();
+ for (final int userId : userIds) {
+ final UidPermissionState uidState = getUidState(appId, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for app ID " + appId + " and user ID "
+ + userId);
+ continue;
+ }
+
+ final List<PermissionState> permissionStates = uidState.getPermissionStates();
+ final int permissionStatesSize = permissionStates.size();
+ for (int i = 0; i < permissionStatesSize; i++) {
+ final PermissionState permissionState = permissionStates.get(i);
+
+ final AppIdPermissionState.PermissionState legacyPermissionState =
+ new AppIdPermissionState.PermissionState(permissionState.getPermission(),
+ permissionState.isGranted(), permissionState.getFlags());
+ if (permissionState.isRuntime()) {
+ appIdState.putRuntimePermissionState(legacyPermissionState, userId);
+ } else if (userId == UserHandle.USER_SYSTEM) {
+ appIdState.putInstallPermissionState(legacyPermissionState);
+ }
+ }
+ }
+ return appIdState;
+ }
+
+ @NonNull
+ private int[] getGidsForUid(int uid) {
+ final int appId = UserHandle.getAppId(uid);
+ final int userId = UserHandle.getUserId(uid);
+ final UidPermissionState uidState = getUidState(appId, userId);
+ if (uidState == null) {
+ Slog.e(TAG, "Missing permissions state for app ID " + appId + " and user ID " + userId);
+ return EMPTY_INT_ARRAY;
+ }
+ return uidState.computeGids(userId);
+ }
+
private class PermissionManagerServiceInternalImpl extends PermissionManagerServiceInternal {
@Override
public void systemReady() {
@@ -4910,8 +4930,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
PermissionManagerService.this.onUserRemoved(userId);
}
@Override
- public void removePermissionsStateTEMP(int appId) {
- PermissionManagerService.this.removeAppState(appId);
+ public void removeAppIdStateTEMP(@AppIdInt int appId) {
+ PermissionManagerService.this.removeAppIdState(appId);
}
@Override
@UserIdInt
@@ -4931,11 +4951,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
public int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId) {
return PermissionManagerService.this.getPermissionGids(permissionName, userId);
}
- @Nullable
- @Override
- public int[] getPackageGids(@NonNull String packageName, @UserIdInt int userId) {
- return PermissionManagerService.this.getPackageGids(packageName, userId);
- }
@Override
public void grantRequestedRuntimePermissions(AndroidPackage pkg, int[] userIds,
String[] grantedPermissions, int callingUid) {
@@ -5263,6 +5278,16 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
}
+
+ @NonNull
+ public AppIdPermissionState getAppIdPermissionState(@AppIdInt int appId) {
+ return PermissionManagerService.this.getAppIdPermissionState(appId);
+ }
+
+ @NonNull
+ public int[] getGidsForUid(int uid) {
+ return PermissionManagerService.this.getGidsForUid(uid);
+ }
}
private static final class OnPermissionChangeListeners extends Handler {
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
index 6d9bd2a1b30d..5ea3458fcbfa 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -37,8 +37,8 @@ import java.util.function.Consumer;
*
* TODO: Should be merged into PermissionManagerInternal, but currently uses internal classes.
*/
-public abstract class PermissionManagerServiceInternal extends PermissionManagerInternal {
-
+public abstract class PermissionManagerServiceInternal extends PermissionManagerInternal
+ implements LegacyPermissionDataProvider {
/**
* Provider for package names.
*/
@@ -288,13 +288,13 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
public abstract void onUserRemoved(@UserIdInt int userId);
/**
- * Remove the {@code PermissionsState} associated with an app ID, called the same time as the
+ * Remove the permission state associated with an app ID, called the same time as the
* removal of a {@code PackageSetitng}.
*
* TODO(zhanghai): This is a temporary method before we figure out a way to get notified of app
* ID removal via API.
*/
- public abstract void removePermissionsStateTEMP(int appId);
+ public abstract void removeAppIdStateTEMP(@AppIdInt int appId);
/**
* Update the shared user setting when a package with a shared user id is removed. The gids
@@ -324,12 +324,6 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
@Nullable
public abstract int[] getPermissionGids(@NonNull String permissionName, @UserIdInt int userId);
- /**
- * Get the GIDs computed from the permission state of a package.
- */
- @Nullable
- public abstract int[] getPackageGids(@NonNull String packageName, @UserIdInt int userId);
-
/** Retrieve the packages that have requested the given app op permission */
public abstract @Nullable String[] getAppOpPermissionPackages(
@NonNull String permName, int callingUid);
diff --git a/services/core/java/com/android/server/pm/permission/PermissionsState.java b/services/core/java/com/android/server/pm/permission/PermissionsState.java
deleted file mode 100644
index 4fb2d5fc200e..000000000000
--- a/services/core/java/com/android/server/pm/permission/PermissionsState.java
+++ /dev/null
@@ -1,970 +0,0 @@
-/*
- * Copyright (C) 2015 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.Nullable;
-import android.annotation.UserIdInt;
-import android.content.pm.PackageManager;
-import android.os.UserHandle;
-import android.util.ArrayMap;
-import android.util.ArraySet;
-import android.util.SparseArray;
-import android.util.SparseBooleanArray;
-
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.util.ArrayUtils;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-
-/**
- * This class encapsulates the permissions for a package or a shared user.
- * <p>
- * There are two types of permissions: install (granted at installation)
- * and runtime (granted at runtime). Install permissions are granted to
- * all device users while runtime permissions are granted explicitly to
- * specific users.
- * </p>
- * <p>
- * The permissions are kept on a per device user basis. For example, an
- * application may have some runtime permissions granted under the device
- * owner but not granted under the secondary user.
- * <p>
- * This class is also responsible for keeping track of the Linux gids per
- * user for a package or a shared user. The gids are computed as a set of
- * the gids for all granted permissions' gids on a per user basis.
- * </p>
- */
-public final class PermissionsState {
-
- /** The permission operation failed. */
- public static final int PERMISSION_OPERATION_FAILURE = -1;
-
- /** The permission operation succeeded and no gids changed. */
- public static final int PERMISSION_OPERATION_SUCCESS = 0;
-
- /** The permission operation succeeded and gids changed. */
- public static final int PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED = 1;
-
- private static final int[] NO_GIDS = {};
-
- private final Object mLock = new Object();
-
- @GuardedBy("mLock")
- private ArrayMap<String, PermissionData> mPermissions;
-
- private int[] mGlobalGids = NO_GIDS;
-
- @Nullable
- private SparseBooleanArray mMissing;
-
- private SparseBooleanArray mPermissionReviewRequired;
-
- public PermissionsState() {
- /* do nothing */
- }
-
- public PermissionsState(PermissionsState prototype) {
- copyFrom(prototype);
- }
-
- public int[] getGlobalGids() {
- return mGlobalGids;
- }
-
- /**
- * Sets the global gids, applicable to all users.
- *
- * @param globalGids The global gids.
- */
- public void setGlobalGids(int[] globalGids) {
- if (!ArrayUtils.isEmpty(globalGids)) {
- mGlobalGids = Arrays.copyOf(globalGids, globalGids.length);
- }
- }
-
- private static void invalidateCache() {
- PackageManager.invalidatePackageInfoCache();
- }
-
- /**
- * Initialized this instance from another one.
- *
- * @param other The other instance.
- */
- public void copyFrom(PermissionsState other) {
- if (other == this) {
- return;
- }
-
- synchronized (mLock) {
- if (mPermissions != null) {
- if (other.mPermissions == null) {
- mPermissions = null;
- } else {
- mPermissions.clear();
- }
- }
- if (other.mPermissions != null) {
- if (mPermissions == null) {
- mPermissions = new ArrayMap<>();
- }
- final int permissionCount = other.mPermissions.size();
- for (int i = 0; i < permissionCount; i++) {
- String name = other.mPermissions.keyAt(i);
- PermissionData permissionData = other.mPermissions.valueAt(i);
- mPermissions.put(name, new PermissionData(permissionData));
- }
- }
- }
-
- mGlobalGids = NO_GIDS;
- if (other.mGlobalGids != NO_GIDS) {
- mGlobalGids = Arrays.copyOf(other.mGlobalGids,
- other.mGlobalGids.length);
- }
-
- if (mMissing != null) {
- if (other.mMissing == null) {
- mMissing = null;
- } else {
- mMissing.clear();
- }
- }
- if (other.mMissing != null) {
- if (mMissing == null) {
- mMissing = new SparseBooleanArray();
- }
- final int missingSize = other.mMissing.size();
- for (int i = 0; i < missingSize; i++) {
- mMissing.put(other.mMissing.keyAt(i), other.mMissing.valueAt(i));
- }
- }
-
- if (mPermissionReviewRequired != null) {
- if (other.mPermissionReviewRequired == null) {
- mPermissionReviewRequired = null;
- } else {
- mPermissionReviewRequired.clear();
- }
- }
- if (other.mPermissionReviewRequired != null) {
- if (mPermissionReviewRequired == null) {
- mPermissionReviewRequired = new SparseBooleanArray();
- }
- final int userCount = other.mPermissionReviewRequired.size();
- for (int i = 0; i < userCount; i++) {
- final boolean reviewRequired = other.mPermissionReviewRequired.valueAt(i);
- mPermissionReviewRequired.put(other.mPermissionReviewRequired.keyAt(i),
- reviewRequired);
- }
- }
- }
-
- @Override
- public boolean equals(Object obj) {
- if (this == obj) {
- return true;
- }
- if (obj == null) {
- return false;
- }
- if (getClass() != obj.getClass()) {
- return false;
- }
- final PermissionsState other = (PermissionsState) obj;
-
- synchronized (mLock) {
- if (mPermissions == null) {
- if (other.mPermissions != null) {
- return false;
- }
- } else if (!mPermissions.equals(other.mPermissions)) {
- return false;
- }
- }
-
- if (!Objects.equals(mMissing, other.mMissing)) {
- return false;
- }
-
- if (mPermissionReviewRequired == null) {
- if (other.mPermissionReviewRequired != null) {
- return false;
- }
- } else if (!mPermissionReviewRequired.equals(other.mPermissionReviewRequired)) {
- return false;
- }
- return Arrays.equals(mGlobalGids, other.mGlobalGids);
- }
-
- /**
- * Check whether the permissions state is missing for a user. This can happen if permission
- * state is rolled back and we'll need to generate a reasonable default state to keep the app
- * usable.
- */
- public boolean isMissing(@UserIdInt int userId) {
- return mMissing != null && mMissing.get(userId);
- }
-
- /**
- * Set whether the permissions state is missing for a user. This can happen if permission state
- * is rolled back and we'll need to generate a reasonable default state to keep the app usable.
- */
- public void setMissing(boolean missing, @UserIdInt int userId) {
- if (missing) {
- if (mMissing == null) {
- mMissing = new SparseBooleanArray();
- }
- mMissing.put(userId, true);
- } else {
- if (mMissing != null) {
- mMissing.delete(userId);
- if (mMissing.size() == 0) {
- mMissing = null;
- }
- }
- }
- }
-
- public boolean isPermissionReviewRequired(int userId) {
- return mPermissionReviewRequired != null && mPermissionReviewRequired.get(userId);
- }
-
- /**
- * Grant an install permission.
- *
- * @param permission The permission to grant.
- * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
- * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
- * #PERMISSION_OPERATION_FAILURE}.
- */
- public int grantInstallPermission(BasePermission permission) {
- return grantPermission(permission, UserHandle.USER_ALL);
- }
-
- /**
- * Revoke an install permission.
- *
- * @param permission The permission to revoke.
- * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
- * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
- * #PERMISSION_OPERATION_FAILURE}.
- */
- public int revokeInstallPermission(BasePermission permission) {
- return revokePermission(permission, UserHandle.USER_ALL);
- }
-
- /**
- * Grant a runtime permission for a given device user.
- *
- * @param permission The permission to grant.
- * @param userId The device user id.
- * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
- * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
- * #PERMISSION_OPERATION_FAILURE}.
- */
- public int grantRuntimePermission(BasePermission permission, int userId) {
- enforceValidUserId(userId);
- if (userId == UserHandle.USER_ALL) {
- return PERMISSION_OPERATION_FAILURE;
- }
- return grantPermission(permission, userId);
- }
-
- /**
- * Revoke a runtime permission for a given device user.
- *
- * @param permission The permission to revoke.
- * @param userId The device user id.
- * @return The operation result which is either {@link #PERMISSION_OPERATION_SUCCESS},
- * or {@link #PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED}, or {@link
- * #PERMISSION_OPERATION_FAILURE}.
- */
- public int revokeRuntimePermission(BasePermission permission, int userId) {
- enforceValidUserId(userId);
- if (userId == UserHandle.USER_ALL) {
- return PERMISSION_OPERATION_FAILURE;
- }
- return revokePermission(permission, userId);
- }
-
- /**
- * Gets whether this state has a given runtime permission for a
- * given device user id.
- *
- * @param name The permission name.
- * @param userId The device user id.
- * @return Whether this state has the permission.
- */
- public boolean hasRuntimePermission(String name, int userId) {
- enforceValidUserId(userId);
- return !hasInstallPermission(name) && hasPermission(name, userId);
- }
-
- /**
- * Gets whether this state has a given install permission.
- *
- * @param name The permission name.
- * @return Whether this state has the permission.
- */
- public boolean hasInstallPermission(String name) {
- return hasPermission(name, UserHandle.USER_ALL);
- }
-
- /**
- * Gets whether the state has a given permission for the specified
- * user, regardless if this is an install or a runtime permission.
- *
- * @param name The permission name.
- * @param userId The device user id.
- * @return Whether the user has the permission.
- */
- public boolean hasPermission(String name, int userId) {
- enforceValidUserId(userId);
-
- synchronized (mLock) {
- if (mPermissions == null) {
- return false;
- }
- PermissionData permissionData = mPermissions.get(name);
-
- return permissionData != null && permissionData.isGranted(userId);
- }
-
- }
-
- /**
- * Returns whether the state has any known request for the given permission name,
- * whether or not it has been granted.
- */
- public boolean hasRequestedPermission(ArraySet<String> names) {
- synchronized (mLock) {
- if (mPermissions == null) {
- return false;
- }
- for (int i=names.size()-1; i>=0; i--) {
- if (mPermissions.get(names.valueAt(i)) != null) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- /**
- * Returns whether the state has any known request for the given permission name,
- * whether or not it has been granted.
- */
- public boolean hasRequestedPermission(String name) {
- return mPermissions != null && (mPermissions.get(name) != null);
- }
- /**
- * Gets all permissions for a given device user id regardless if they
- * are install time or runtime permissions.
- *
- * @param userId The device user id.
- * @return The permissions or an empty set.
- */
- public Set<String> getPermissions(int userId) {
- enforceValidUserId(userId);
-
- synchronized (mLock) {
- if (mPermissions == null) {
- return Collections.emptySet();
- }
-
- Set<String> permissions = new ArraySet<>(mPermissions.size());
-
- final int permissionCount = mPermissions.size();
- for (int i = 0; i < permissionCount; i++) {
- String permission = mPermissions.keyAt(i);
-
- if (hasInstallPermission(permission)) {
- permissions.add(permission);
- continue;
- }
-
- if (userId != UserHandle.USER_ALL) {
- if (hasRuntimePermission(permission, userId)) {
- permissions.add(permission);
- }
- }
- }
-
- return permissions;
- }
- }
-
- /**
- * Gets the state for an install permission or null if no such.
- *
- * @param name The permission name.
- * @return The permission state.
- */
- public PermissionState getInstallPermissionState(String name) {
- return getPermissionState(name, UserHandle.USER_ALL);
- }
-
- /**
- * Gets the state for a runtime permission or null if no such.
- *
- * @param name The permission name.
- * @param userId The device user id.
- * @return The permission state.
- */
- public PermissionState getRuntimePermissionState(String name, int userId) {
- enforceValidUserId(userId);
- return getPermissionState(name, userId);
- }
-
- /**
- * Gets all install permission states.
- *
- * @return The permission states or an empty set.
- */
- public List<PermissionState> getInstallPermissionStates() {
- return getPermissionStatesInternal(UserHandle.USER_ALL);
- }
-
- /**
- * Gets all runtime permission states.
- *
- * @return The permission states or an empty set.
- */
- public List<PermissionState> getRuntimePermissionStates(int userId) {
- enforceValidUserId(userId);
- return getPermissionStatesInternal(userId);
- }
-
- /**
- * Gets the flags for a permission regardless if it is install or
- * runtime permission.
- *
- * @param name The permission name.
- * @return The permission state or null if no such.
- */
- public int getPermissionFlags(String name, int userId) {
- PermissionState installPermState = getInstallPermissionState(name);
- if (installPermState != null) {
- return installPermState.getFlags();
- }
- PermissionState runtimePermState = getRuntimePermissionState(name, userId);
- if (runtimePermState != null) {
- return runtimePermState.getFlags();
- }
- return 0;
- }
-
- /**
- * Update the flags associated with a given permission.
- * @param permission The permission whose flags to update.
- * @param userId The user for which to update.
- * @param flagMask Mask for which flags to change.
- * @param flagValues New values for the mask flags.
- * @return Whether the permission flags changed.
- */
- public boolean updatePermissionFlags(BasePermission permission, int userId,
- int flagMask, int flagValues) {
- enforceValidUserId(userId);
-
- final boolean mayChangeFlags = flagValues != 0 || flagMask != 0;
-
- synchronized (mLock) {
- if (mPermissions == null) {
- if (!mayChangeFlags) {
- return false;
- }
- ensurePermissionData(permission);
- }
- }
-
- PermissionData permissionData = null;
- synchronized (mLock) {
- permissionData = mPermissions.get(permission.getName());
- }
-
- if (permissionData == null) {
- if (!mayChangeFlags) {
- return false;
- }
- permissionData = ensurePermissionData(permission);
- }
-
- final int oldFlags = permissionData.getFlags(userId);
-
- final boolean updated = permissionData.updateFlags(userId, flagMask, flagValues);
- if (updated) {
- final int newFlags = permissionData.getFlags(userId);
- if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0
- && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
- if (mPermissionReviewRequired == null) {
- mPermissionReviewRequired = new SparseBooleanArray();
- }
- mPermissionReviewRequired.put(userId, true);
- } else if ((oldFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0
- && (newFlags & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
- if (mPermissionReviewRequired != null && !hasPermissionRequiringReview(userId)) {
- mPermissionReviewRequired.delete(userId);
- if (mPermissionReviewRequired.size() <= 0) {
- mPermissionReviewRequired = null;
- }
- }
- }
- }
- return updated;
- }
-
- private boolean hasPermissionRequiringReview(int userId) {
- synchronized (mLock) {
- final int permissionCount = mPermissions.size();
- for (int i = 0; i < permissionCount; i++) {
- final PermissionData permission = mPermissions.valueAt(i);
- if ((permission.getFlags(userId)
- & PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
- return true;
- }
- }
- }
-
- return false;
- }
-
- public boolean updatePermissionFlagsForAllPermissions(
- int userId, int flagMask, int flagValues) {
- enforceValidUserId(userId);
-
- synchronized (mLock) {
- if (mPermissions == null) {
- return false;
- }
- boolean changed = false;
- final int permissionCount = mPermissions.size();
- for (int i = 0; i < permissionCount; i++) {
- PermissionData permissionData = mPermissions.valueAt(i);
- changed |= permissionData.updateFlags(userId, flagMask, flagValues);
- }
-
- return changed;
- }
- }
-
- /**
- * Compute the Linux gids for a given device user from the permissions
- * granted to this user. Note that these are computed to avoid additional
- * state as they are rarely accessed.
- *
- * @param userId The device user id.
- * @return The gids for the device user.
- */
- public int[] computeGids(int userId) {
- enforceValidUserId(userId);
-
- int[] gids = mGlobalGids;
-
- synchronized (mLock) {
- if (mPermissions != null) {
- final int permissionCount = mPermissions.size();
- for (int i = 0; i < permissionCount; i++) {
- String permission = mPermissions.keyAt(i);
- if (!hasPermission(permission, userId)) {
- continue;
- }
- PermissionData permissionData = mPermissions.valueAt(i);
- final int[] permGids = permissionData.computeGids(userId);
- if (permGids != NO_GIDS) {
- gids = appendInts(gids, permGids);
- }
- }
- }
- }
-
- return gids;
- }
-
- /**
- * Compute the Linux gids for all device users from the permissions
- * granted to these users.
- *
- * @return The gids for all device users.
- */
- public int[] computeGids(int[] userIds) {
- int[] gids = mGlobalGids;
-
- for (int userId : userIds) {
- final int[] userGids = computeGids(userId);
- gids = appendInts(gids, userGids);
- }
-
- return gids;
- }
-
- /**
- * Resets the internal state of this object.
- */
- public void reset() {
- mGlobalGids = NO_GIDS;
-
- synchronized (mLock) {
- mPermissions = null;
- invalidateCache();
- }
-
- mMissing = null;
- mPermissionReviewRequired = null;
- }
-
- private PermissionState getPermissionState(String name, int userId) {
- synchronized (mLock) {
- if (mPermissions == null) {
- return null;
- }
- PermissionData permissionData = mPermissions.get(name);
- if (permissionData == null) {
- return null;
- }
-
- return permissionData.getPermissionState(userId);
- }
- }
-
- private List<PermissionState> getPermissionStatesInternal(int userId) {
- enforceValidUserId(userId);
-
- synchronized (mLock) {
- if (mPermissions == null) {
- return Collections.emptyList();
- }
-
- List<PermissionState> permissionStates = new ArrayList<>();
-
- final int permissionCount = mPermissions.size();
- for (int i = 0; i < permissionCount; i++) {
- PermissionData permissionData = mPermissions.valueAt(i);
-
- PermissionState permissionState = permissionData.getPermissionState(userId);
- if (permissionState != null) {
- permissionStates.add(permissionState);
- }
- }
-
- return permissionStates;
- }
- }
-
- private int grantPermission(BasePermission permission, int userId) {
- if (hasPermission(permission.getName(), userId)) {
- return PERMISSION_OPERATION_SUCCESS;
- }
-
- final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
- final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;
-
- PermissionData permissionData = ensurePermissionData(permission);
-
- if (!permissionData.grant(userId)) {
- return PERMISSION_OPERATION_FAILURE;
- }
-
- if (hasGids) {
- final int[] newGids = computeGids(userId);
- if (oldGids.length != newGids.length) {
- return PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
- }
- }
-
- return PERMISSION_OPERATION_SUCCESS;
- }
-
- private int revokePermission(BasePermission permission, int userId) {
- final String permName = permission.getName();
- if (!hasPermission(permName, userId)) {
- return PERMISSION_OPERATION_SUCCESS;
- }
-
- final boolean hasGids = !ArrayUtils.isEmpty(permission.computeGids(userId));
- final int[] oldGids = hasGids ? computeGids(userId) : NO_GIDS;
-
- PermissionData permissionData = null;
- synchronized (mLock) {
- permissionData = mPermissions.get(permName);
- }
-
- if (!permissionData.revoke(userId)) {
- return PERMISSION_OPERATION_FAILURE;
- }
-
- if (permissionData.isDefault()) {
- ensureNoPermissionData(permName);
- }
-
- if (hasGids) {
- final int[] newGids = computeGids(userId);
- if (oldGids.length != newGids.length) {
- return PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED;
- }
- }
-
- return PERMISSION_OPERATION_SUCCESS;
- }
-
- // TODO: fix this to use arraycopy and append all ints in one go
- private static int[] appendInts(int[] current, int[] added) {
- if (current != null && added != null) {
- for (int guid : added) {
- current = ArrayUtils.appendInt(current, guid);
- }
- }
- return current;
- }
-
- private static void enforceValidUserId(int userId) {
- if (userId != UserHandle.USER_ALL && userId < 0) {
- throw new IllegalArgumentException("Invalid userId:" + userId);
- }
- }
-
- private PermissionData ensurePermissionData(BasePermission permission) {
- final String permName = permission.getName();
-
- synchronized (mLock) {
- if (mPermissions == null) {
- mPermissions = new ArrayMap<>();
- }
- PermissionData permissionData = mPermissions.get(permName);
- if (permissionData == null) {
- permissionData = new PermissionData(permission);
- mPermissions.put(permName, permissionData);
- }
- return permissionData;
- }
-
- }
-
- private void ensureNoPermissionData(String name) {
- synchronized (mLock) {
- if (mPermissions == null) {
- return;
- }
- mPermissions.remove(name);
- if (mPermissions.isEmpty()) {
- mPermissions = null;
- }
- }
-
- }
-
- private static final class PermissionData {
-
- private final Object mLock = new Object();
-
- private final BasePermission mPerm;
- @GuardedBy("mLock")
- private SparseArray<PermissionState> mUserStates = new SparseArray<>();
-
- public PermissionData(BasePermission perm) {
- mPerm = perm;
- }
-
- public PermissionData(PermissionData other) {
- this(other.mPerm);
-
- synchronized (mLock) {
- final int otherStateCount = other.mUserStates.size();
- for (int i = 0; i < otherStateCount; i++) {
- final int otherUserId = other.mUserStates.keyAt(i);
- PermissionState otherState = other.mUserStates.valueAt(i);
- mUserStates.put(otherUserId, new PermissionState(otherState));
- }
- }
- }
-
- public int[] computeGids(int userId) {
- return mPerm.computeGids(userId);
- }
-
- public boolean isGranted(int userId) {
- synchronized (mLock) {
- if (isInstallPermission()) {
- userId = UserHandle.USER_ALL;
- }
-
- PermissionState userState = mUserStates.get(userId);
- if (userState == null) {
- return false;
- }
-
- return userState.mGranted;
- }
- }
-
- public boolean grant(int userId) {
- synchronized (mLock) {
- if (!isCompatibleUserId(userId)) {
- return false;
- }
-
- if (isGranted(userId)) {
- return false;
- }
-
- PermissionState userState = mUserStates.get(userId);
- if (userState == null) {
- userState = new PermissionState(mPerm);
- mUserStates.put(userId, userState);
- }
-
- userState.mGranted = true;
-
- invalidateCache();
- return true;
- }
- }
-
- public boolean revoke(int userId) {
- synchronized (mLock) {
- if (!isCompatibleUserId(userId)) {
- return false;
- }
-
- if (!isGranted(userId)) {
- return false;
- }
-
- PermissionState userState = mUserStates.get(userId);
- userState.mGranted = false;
-
- if (userState.isDefault()) {
- mUserStates.remove(userId);
- }
-
- invalidateCache();
- return true;
- }
- }
-
- public PermissionState getPermissionState(int userId) {
- synchronized (mLock) {
- return mUserStates.get(userId);
- }
- }
-
- public int getFlags(int userId) {
- synchronized (mLock) {
- PermissionState userState = mUserStates.get(userId);
- if (userState != null) {
- return userState.mFlags;
- }
- return 0;
- }
- }
-
- public boolean isDefault() {
- synchronized (mLock) {
- return mUserStates.size() <= 0;
- }
- }
-
- public static boolean isInstallPermissionKey(int userId) {
- return userId == UserHandle.USER_ALL;
- }
-
- public boolean updateFlags(int userId, int flagMask, int flagValues) {
- synchronized (mLock) {
- if (isInstallPermission()) {
- userId = UserHandle.USER_ALL;
- }
-
- if (!isCompatibleUserId(userId)) {
- return false;
- }
-
- final int newFlags = flagValues & flagMask;
-
- // Okay to do before the modification because we hold the lock.
- invalidateCache();
-
- PermissionState userState = mUserStates.get(userId);
- if (userState != null) {
- final int oldFlags = userState.mFlags;
- userState.mFlags = (userState.mFlags & ~flagMask) | newFlags;
- if (userState.isDefault()) {
- mUserStates.remove(userId);
- }
- return userState.mFlags != oldFlags;
- } else if (newFlags != 0) {
- userState = new PermissionState(mPerm);
- userState.mFlags = newFlags;
- mUserStates.put(userId, userState);
- return true;
- }
-
- return false;
- }
- }
-
- private boolean isCompatibleUserId(int userId) {
- return isDefault() || !(isInstallPermission() ^ isInstallPermissionKey(userId));
- }
-
- private boolean isInstallPermission() {
- return mUserStates.size() == 1
- && mUserStates.get(UserHandle.USER_ALL) != null;
- }
- }
-
- public static final class PermissionState {
- private final BasePermission mPermission;
- private boolean mGranted;
- private int mFlags;
-
- public PermissionState(BasePermission permission) {
- mPermission = permission;
- }
-
- public PermissionState(PermissionState other) {
- mPermission = other.mPermission;
- mGranted = other.mGranted;
- mFlags = other.mFlags;
- }
-
- public boolean isDefault() {
- return !mGranted && mFlags == 0;
- }
-
- public BasePermission getPermission() {
- return mPermission;
- }
-
- public String getName() {
- return mPermission.getName();
- }
-
- public boolean isGranted() {
- return mGranted;
- }
-
- public int getFlags() {
- return mFlags;
- }
- }
-}
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
index dac05424e01f..bc747832e253 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -62,6 +62,7 @@ import com.android.permission.persistence.RuntimePermissionsPersistence;
import com.android.server.LocalServices;
import com.android.server.pm.parsing.pkg.PackageImpl;
import com.android.server.pm.parsing.pkg.ParsedPackage;
+import com.android.server.pm.permission.LegacyPermissionDataProvider;
import com.android.server.pm.permission.PermissionSettings;
import com.google.common.truth.Truth;
@@ -94,6 +95,8 @@ public class PackageManagerSettingsTests {
PermissionSettings mPermissionSettings;
@Mock
RuntimePermissionsPersistence mRuntimePermissionsPersistence;
+ @Mock
+ LegacyPermissionDataProvider mPermissionDataProvider;
@Before
public void initializeMocks() {
@@ -115,7 +118,7 @@ public class PackageManagerSettingsTests {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
- mRuntimePermissionsPersistence, lock);
+ mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
verifyKeySetMetaData(settings);
}
@@ -129,7 +132,7 @@ public class PackageManagerSettingsTests {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
- mRuntimePermissionsPersistence, lock);
+ mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
// write out, read back in and verify the same
@@ -145,7 +148,7 @@ public class PackageManagerSettingsTests {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
- mRuntimePermissionsPersistence, lock);
+ mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
assertThat(settings.getPackageLPr(PACKAGE_NAME_3), is(notNullValue()));
assertThat(settings.getPackageLPr(PACKAGE_NAME_1), is(notNullValue()));
@@ -167,13 +170,13 @@ public class PackageManagerSettingsTests {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
- mRuntimePermissionsPersistence, lock);
+ mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
settings.writeLPr();
// Create Settings again to make it read from the new files
settings = new Settings(context.getFilesDir(), mPermissionSettings,
- mRuntimePermissionsPersistence, lock);
+ mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
PackageSetting ps = settings.getPackageLPr(PACKAGE_NAME_2);
@@ -196,7 +199,8 @@ public class PackageManagerSettingsTests {
writePackageRestrictions_noSuspendingPackageXml(0);
final Object lock = new Object();
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, lock);
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, null,
+ lock);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settingsUnderTest.mPackages.put(PACKAGE_NAME_2, createPackageSetting(PACKAGE_NAME_2));
settingsUnderTest.readPackageRestrictionsLPr(0);
@@ -219,7 +223,8 @@ public class PackageManagerSettingsTests {
writePackageRestrictions_noSuspendParamsMapXml(0);
final Object lock = new Object();
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, lock);
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, null,
+ lock);
settingsUnderTest.mPackages.put(PACKAGE_NAME_1, createPackageSetting(PACKAGE_NAME_1));
settingsUnderTest.readPackageRestrictionsLPr(0);
@@ -246,7 +251,7 @@ public class PackageManagerSettingsTests {
@Test
public void testReadWritePackageRestrictions_suspendInfo() {
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, null,
new Object());
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
@@ -344,7 +349,7 @@ public class PackageManagerSettingsTests {
@Test
public void testReadWritePackageRestrictions_distractionFlags() {
final Context context = InstrumentationRegistry.getTargetContext();
- final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null,
+ final Settings settingsUnderTest = new Settings(context.getFilesDir(), null, null, null,
new Object());
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
final PackageSetting ps2 = createPackageSetting(PACKAGE_NAME_2);
@@ -389,7 +394,7 @@ public class PackageManagerSettingsTests {
final Context context = InstrumentationRegistry.getTargetContext();
final Object lock = new Object();
final Settings settingsUnderTest = new Settings(context.getFilesDir(), mPermissionSettings,
- mRuntimePermissionsPersistence, lock);
+ mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
final PackageSetting ps1 = createPackageSetting(PACKAGE_NAME_1);
ps1.appId = Process.FIRST_APPLICATION_UID;
ps1.pkg = ((ParsedPackage) PackageImpl.forTesting(PACKAGE_NAME_1).hideAsParsed())
@@ -465,7 +470,7 @@ public class PackageManagerSettingsTests {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
Settings settings = new Settings(context.getFilesDir(), mPermissionSettings,
- mRuntimePermissionsPersistence, lock);
+ mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
assertThat(settings.readLPw(createFakeUsers()), is(true));
// Enable/Disable a package
@@ -638,7 +643,7 @@ public class PackageManagerSettingsTests {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
final Settings testSettings01 = new Settings(context.getFilesDir(), mPermissionSettings,
- mRuntimePermissionsPersistence, lock);
+ mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
testSettings01, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
final PackageSetting testPkgSetting01 =
@@ -748,7 +753,7 @@ public class PackageManagerSettingsTests {
final Context context = InstrumentationRegistry.getContext();
final Object lock = new Object();
final Settings testSettings01 = new Settings(context.getFilesDir(), mPermissionSettings,
- mRuntimePermissionsPersistence, lock);
+ mRuntimePermissionsPersistence, mPermissionDataProvider, lock);
final SharedUserSetting testUserSetting01 = createSharedUserSetting(
testSettings01, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
final PackageSetting testPkgSetting01 = Settings.createNewSetting(