summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Android.bp2
-rw-r--r--core/java/android/app/ApplicationPackageManager.java27
-rw-r--r--core/java/android/content/pm/IPackageManager.aidl14
-rw-r--r--core/java/android/content/pm/PackageManagerInternal.java8
-rw-r--r--core/java/android/permission/IOnPermissionsChangeListener.aidl (renamed from core/java/android/content/pm/IOnPermissionsChangeListener.aidl)2
-rw-r--r--core/java/android/permission/IPermissionManager.aidl14
-rw-r--r--core/java/android/permission/PermissionManager.java3
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java371
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerServiceUtils.java13
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerService.java444
-rw-r--r--services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java10
11 files changed, 467 insertions, 441 deletions
diff --git a/Android.bp b/Android.bp
index ee3b39681ea2..29d6c91eb8f8 100644
--- a/Android.bp
+++ b/Android.bp
@@ -136,7 +136,6 @@ java_defaults {
"core/java/android/content/pm/IDexModuleRegisterCallback.aidl",
"core/java/android/content/pm/ILauncherApps.aidl",
"core/java/android/content/pm/IOnAppsChangedListener.aidl",
- "core/java/android/content/pm/IOnPermissionsChangeListener.aidl",
"core/java/android/content/pm/IOtaDexopt.aidl",
"core/java/android/content/pm/IPackageDataObserver.aidl",
"core/java/android/content/pm/IPackageDeleteObserver.aidl",
@@ -278,6 +277,7 @@ java_defaults {
"core/java/android/os/storage/IStorageEventListener.aidl",
"core/java/android/os/storage/IStorageShutdownObserver.aidl",
"core/java/android/os/storage/IObbActionListener.aidl",
+ "core/java/android/permission/IOnPermissionsChangeListener.aidl",
"core/java/android/permission/IPermissionController.aidl",
"core/java/android/permission/IPermissionManager.aidl",
":keystore_aidl",
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index f930621d624c..accf32202503 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -34,7 +34,6 @@ import android.content.pm.ApplicationInfo;
import android.content.pm.ChangedPackages;
import android.content.pm.ComponentInfo;
import android.content.pm.FeatureInfo;
-import android.content.pm.IOnPermissionsChangeListener;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageManager;
@@ -82,6 +81,7 @@ import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
+import android.permission.IOnPermissionsChangeListener;
import android.permission.IPermissionManager;
import android.provider.Settings;
import android.system.ErrnoException;
@@ -755,10 +755,11 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public @NonNull Set<String> getWhitelistedRestrictedPermissions(
- @NonNull String packageName, @PermissionWhitelistFlags int whitelistFlags) {
+ @NonNull String packageName, @PermissionWhitelistFlags int flags) {
try {
- final List<String> whitelist = mPM.getWhitelistedRestrictedPermissions(
- packageName, whitelistFlags, getUserId());
+ final int userId = getUserId();
+ final List<String> whitelist = mPermissionManager
+ .getWhitelistedRestrictedPermissions(packageName, flags, userId);
if (whitelist != null) {
return new ArraySet<>(whitelist);
}
@@ -770,10 +771,11 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
- @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags) {
+ @NonNull String permName, @PermissionWhitelistFlags int flags) {
try {
- return mPM.addWhitelistedRestrictedPermission(packageName, permission,
- whitelistFlags, getUserId());
+ final int userId = getUserId();
+ return mPermissionManager
+ .addWhitelistedRestrictedPermission(packageName, permName, flags, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -781,10 +783,11 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
- @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags) {
+ @NonNull String permName, @PermissionWhitelistFlags int flags) {
try {
- return mPM.removeWhitelistedRestrictedPermission(packageName, permission,
- whitelistFlags, getUserId());
+ final int userId = getUserId();
+ return mPermissionManager
+ .removeWhitelistedRestrictedPermission(packageName, permName, flags, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1624,7 +1627,7 @@ public class ApplicationPackageManager extends PackageManager {
OnPermissionsChangeListenerDelegate delegate =
new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
try {
- mPM.addOnPermissionsChangeListener(delegate);
+ mPermissionManager.addOnPermissionsChangeListener(delegate);
mPermissionListeners.put(listener, delegate);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
@@ -1638,7 +1641,7 @@ public class ApplicationPackageManager extends PackageManager {
IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
if (delegate != null) {
try {
- mPM.removeOnPermissionsChangeListener(delegate);
+ mPermissionManager.removeOnPermissionsChangeListener(delegate);
mPermissionListeners.remove(listener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index 65c83777b6ff..bef59a62b96c 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -32,7 +32,6 @@ import android.content.pm.IPackageDeleteObserver2;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
-import android.content.pm.IOnPermissionsChangeListener;
import android.content.pm.IntentFilterVerificationInfo;
import android.content.pm.InstrumentationInfo;
import android.content.pm.KeySet;
@@ -103,16 +102,7 @@ interface IPackageManager {
void resetRuntimePermissions();
- List<String> getWhitelistedRestrictedPermissions(String packageName, int flags,
- int userId);
-
- boolean addWhitelistedRestrictedPermission(String packageName, String permission,
- int whitelistFlags, int userId);
-
- boolean removeWhitelistedRestrictedPermission(String packageName, String permission,
- int whitelistFlags, int userId);
-
- boolean shouldShowRequestPermissionRationale(String permissionName,
+ boolean shouldShowRequestPermissionRationale(String permName,
String packageName, int userId);
boolean isProtectedBroadcast(String actionName);
@@ -647,8 +637,6 @@ interface IPackageManager {
boolean isPackageSignedByKeySet(String packageName, in KeySet ks);
boolean isPackageSignedByKeySetExactly(String packageName, in KeySet ks);
- void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
- void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
void grantDefaultPermissionsToEnabledCarrierApps(in String[] packageNames, int userId);
void grantDefaultPermissionsToEnabledImsServices(in String[] packageNames, int userId);
void grantDefaultPermissionsToEnabledTelephonyDataServices(
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 126e1751221f..6e429a4e79c9 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -974,6 +974,10 @@ public abstract class PackageManagerInternal {
*/
public abstract int getTargetSdk(int uid);
- /** HACK. Remove when listeners move to the permission manager */
- public abstract void onPermissionsChangedTEMP(int uid);
+ /**
+ * Returns {@code true} if the caller is the installer of record for the given package.
+ * Otherwise, {@code false}.
+ */
+ public abstract boolean isCallerInstallerOfRecord(
+ @NonNull PackageParser.Package pkg, int callingUid);
}
diff --git a/core/java/android/content/pm/IOnPermissionsChangeListener.aidl b/core/java/android/permission/IOnPermissionsChangeListener.aidl
index 7791b5099654..cc52a7210737 100644
--- a/core/java/android/content/pm/IOnPermissionsChangeListener.aidl
+++ b/core/java/android/permission/IOnPermissionsChangeListener.aidl
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package android.content.pm;
+package android.permission;
/**
* Listener for changes in the permissions for installed packages.
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 475cf4a6f744..2d984851f0f4 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -19,6 +19,7 @@ package android.permission;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
+import android.permission.IOnPermissionsChangeListener;
/**
* Interface to communicate directly with the permission manager service.
@@ -50,4 +51,17 @@ interface IPermissionManager {
int checkPermission(String permName, String pkgName, int userId);
int checkUidPermission(String permName, int uid);
+
+ void addOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
+
+ void removeOnPermissionsChangeListener(in IOnPermissionsChangeListener listener);
+
+ List<String> getWhitelistedRestrictedPermissions(String packageName,
+ int flags, int userId);
+
+ boolean addWhitelistedRestrictedPermission(String packageName, String permName,
+ int flags, int userId);
+
+ boolean removeWhitelistedRestrictedPermission(String packageName, String permName,
+ int flags, int userId);
}
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 182a2ffa5221..8d53493de71a 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -43,6 +43,9 @@ import java.util.Objects;
@SystemApi
@SystemService(Context.PERMISSION_SERVICE)
public final class PermissionManager {
+ /** @hide */
+ public static final String KILL_APP_REASON_PERMISSIONS_REVOKED = "permissions revoked";
+
/**
* {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
*
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 61bdb74a304f..d422828d842d 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -42,6 +42,7 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_REVOKE_ON_UPGRAD
import static android.content.pm.PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_FIXED;
import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
+import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER;
import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
@@ -90,6 +91,7 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
+import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_MANAGED_PROFILE;
import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
@@ -111,6 +113,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.getCompressedFile
import static com.android.server.pm.PackageManagerServiceUtils.getLastModifiedTime;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
+import static com.android.server.pm.permission.PermissionManagerService.killUid;
import android.Manifest;
import android.annotation.IntDef;
@@ -144,7 +147,6 @@ import android.content.pm.ComponentInfo;
import android.content.pm.FallbackCategoryProvider;
import android.content.pm.FeatureInfo;
import android.content.pm.IDexModuleRegisterCallback;
-import android.content.pm.IOnPermissionsChangeListener;
import android.content.pm.IPackageDataObserver;
import android.content.pm.IPackageDeleteObserver;
import android.content.pm.IPackageDeleteObserver2;
@@ -168,7 +170,6 @@ import android.content.pm.PackageList;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.LegacyPackageDeleteObserver;
import android.content.pm.PackageManager.ModuleInfoFlags;
-import android.content.pm.PackageManager.PermissionWhitelistFlags;
import android.content.pm.PackageManagerInternal;
import android.content.pm.PackageManagerInternal.PackageListObserver;
import android.content.pm.PackageParser;
@@ -582,9 +583,6 @@ public class PackageManagerService extends IPackageManager.Stub
private static final String KILL_APP_REASON_GIDS_CHANGED =
"permission grant or revoke changed gids";
- private static final String KILL_APP_REASON_PERMISSIONS_REVOKED =
- "permissions revoked";
-
private static final String PACKAGE_MIME_TYPE = "application/vnd.android.package-archive";
private static final String PACKAGE_SCHEME = "package";
@@ -914,8 +912,6 @@ public class PackageManagerService extends IPackageManager.Stub
private AtomicInteger mNextMoveId = new AtomicInteger();
private final MoveCallbacks mMoveCallbacks;
- private final OnPermissionChangeListeners mOnPermissionChangeListeners;
-
// Cache of users who need badging.
private final SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray();
@@ -1770,7 +1766,7 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public void onPermissionGranted(int uid, @UserIdInt int userId) {
- mOnPermissionChangeListeners.onPermissionsChanged(uid);
+ mPermissionManager.notifyPermissionsChangedTEMP(uid);
// Not critical; if this is lost, the application has to request again.
synchronized (mPackages) {
@@ -1787,7 +1783,7 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public void onPermissionRevoked(int uid, @UserIdInt int userId) {
- mOnPermissionChangeListeners.onPermissionsChanged(uid);
+ mPermissionManager.notifyPermissionsChangedTEMP(uid);
synchronized (mPackages) {
// Critical; after this call the application should never have the permission
@@ -1818,7 +1814,7 @@ public class PackageManagerService extends IPackageManager.Stub
public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
int uid) {
onPermissionUpdated(updatedUserIds, sync);
- mOnPermissionChangeListeners.onPermissionsChanged(uid);
+ mPermissionManager.notifyPermissionsChangedTEMP(uid);
}
@Override
@@ -1831,7 +1827,7 @@ public class PackageManagerService extends IPackageManager.Stub
@Override
public void onInstallPermissionUpdatedNotifyListener(int uid) {
onInstallPermissionUpdated();
- mOnPermissionChangeListeners.onPermissionsChanged(uid);
+ mPermissionManager.notifyPermissionsChangedTEMP(uid);
}
@Override
@@ -1862,7 +1858,7 @@ public class PackageManagerService extends IPackageManager.Stub
&& !whitelistedRestrictedPermissions.isEmpty()) {
mPermissionManager.setWhitelistedRestrictedPermissions(
res.pkg, res.newUsers, whitelistedRestrictedPermissions,
- Process.myUid(), PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER,
+ Process.myUid(), FLAG_PERMISSION_WHITELIST_INSTALLER,
mPermissionCallback);
}
@@ -2493,9 +2489,6 @@ public class PackageManagerService extends IPackageManager.Stub
mViewCompiler = new ViewCompiler(mInstallLock, mInstaller);
- mOnPermissionChangeListeners = new OnPermissionChangeListeners(
- FgThread.get().getLooper());
-
getDefaultDisplayMetrics(context, mMetrics);
t.traceBegin("get system config");
@@ -5727,228 +5720,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
- public @Nullable List<String> getWhitelistedRestrictedPermissions(@NonNull String packageName,
- @PermissionWhitelistFlags int whitelistFlags, @UserIdInt int userId) {
- Preconditions.checkNotNull(packageName);
- Preconditions.checkFlagsArgument(whitelistFlags,
- PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
- | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
- | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
- Preconditions.checkArgumentNonNegative(userId, null);
-
- if (UserHandle.getCallingUserId() != userId) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.INTERACT_ACROSS_USERS,
- "getWhitelistedRestrictedPermissions for user " + userId);
- }
-
- final PackageParser.Package pkg;
-
- synchronized (mPackages) {
- final PackageSetting packageSetting = mSettings.mPackages.get(packageName);
- if (packageSetting == null) {
- Slog.w(TAG, "Unknown package: " + packageName);
- return null;
- }
-
- pkg = packageSetting.pkg;
-
- final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
- Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
- == PackageManager.PERMISSION_GRANTED;
- final PackageSetting installerPackageSetting = mSettings.mPackages.get(
- packageSetting.installerPackageName);
- final boolean isCallerInstallerOnRecord = installerPackageSetting != null
- && UserHandle.isSameApp(installerPackageSetting.appId, Binder.getCallingUid());
-
- if ((whitelistFlags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
- && !isCallerPrivileged) {
- throw new SecurityException("Querying system whitelist requires "
- + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
- }
-
- if ((whitelistFlags & (PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
- | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) != 0) {
- if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
- throw new SecurityException("Querying upgrade or installer whitelist"
- + " requires being installer on record or "
- + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
- }
- }
-
- if (filterAppAccessLPr(packageSetting, Binder.getCallingUid(),
- UserHandle.getCallingUserId())) {
- return null;
- }
- }
-
- final long identity = Binder.clearCallingIdentity();
- try {
- return mPermissionManager.getWhitelistedRestrictedPermissions(
- pkg, whitelistFlags, userId);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- @Override
- public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
- @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags,
- @UserIdInt int userId) {
- // Other argument checks are done in get/setWhitelistedRestrictedPermissions
- Preconditions.checkNotNull(permission);
-
- if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permission)) {
- return false;
- }
-
- List<String> permissions = getWhitelistedRestrictedPermissions(packageName,
- whitelistFlags, userId);
- if (permissions == null) {
- permissions = new ArrayList<>(1);
- }
- if (permissions.indexOf(permission) < 0) {
- permissions.add(permission);
- return setWhitelistedRestrictedPermissions(packageName, permissions,
- whitelistFlags, userId);
- }
- return false;
- }
-
- private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
- @NonNull String permission) {
- synchronized (mPackages) {
- final BasePermission bp = mPermissionManager.getPermissionTEMP(permission);
- if (bp == null) {
- Slog.w(TAG, "No such permissions: " + permission);
- return false;
- }
- if (bp.isHardOrSoftRestricted() && bp.isImmutablyRestricted()
- && mContext.checkCallingOrSelfPermission(
- Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
- != PackageManager.PERMISSION_GRANTED) {
- throw new SecurityException("Cannot modify whitelisting of an immutably "
- + "restricted permission: " + permission);
- }
- return true;
- }
- }
-
- @Override
- public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
- @NonNull String permission, @PermissionWhitelistFlags int whitelistFlags,
- @UserIdInt int userId) {
- // Other argument checks are done in get/setWhitelistedRestrictedPermissions
- Preconditions.checkNotNull(permission);
-
- if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permission)) {
- return false;
- }
-
- final List<String> permissions = getWhitelistedRestrictedPermissions(packageName,
- whitelistFlags, userId);
- if (permissions != null && permissions.remove(permission)) {
- return setWhitelistedRestrictedPermissions(packageName, permissions,
- whitelistFlags, userId);
- }
- return false;
- }
-
- private boolean setWhitelistedRestrictedPermissions(@NonNull String packageName,
- @Nullable List<String> permissions, @PermissionWhitelistFlags int whitelistFlag,
- @UserIdInt int userId) {
- Preconditions.checkNotNull(packageName);
- Preconditions.checkFlagsArgument(whitelistFlag,
- PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
- | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
- | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
- Preconditions.checkArgument(Integer.bitCount(whitelistFlag) == 1);
- Preconditions.checkArgumentNonNegative(userId, null);
-
- if (UserHandle.getCallingUserId() != userId) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.INTERACT_ACROSS_USERS,
- "setWhitelistedRestrictedPermissions for user " + userId);
- }
-
- final PackageParser.Package pkg;
-
- synchronized (mPackages) {
- final PackageSetting packageSetting = mSettings.mPackages.get(packageName);
- if (packageSetting == null) {
- Slog.w(TAG, "Unknown package: " + packageName);
- return false;
- }
-
- pkg = packageSetting.pkg;
-
- final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
- Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
- == PackageManager.PERMISSION_GRANTED;
- final PackageSetting installerPackageSetting = mSettings.mPackages.get(
- packageSetting.installerPackageName);
- final boolean isCallerInstallerOnRecord = installerPackageSetting != null
- && UserHandle.isSameApp(installerPackageSetting.appId, Binder.getCallingUid());
-
- if ((whitelistFlag & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
- && !isCallerPrivileged) {
- throw new SecurityException("Modifying system whitelist requires "
- + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
- }
-
- if ((whitelistFlag & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
- if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
- throw new SecurityException("Modifying upgrade whitelist requires"
- + " being installer on record or "
- + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
- }
- final List<String> whitelistedPermissions = getWhitelistedRestrictedPermissions(
- packageName, whitelistFlag, userId);
- if (permissions == null || permissions.isEmpty()) {
- if (whitelistedPermissions == null || whitelistedPermissions.isEmpty()) {
- return true;
- }
- } else {
- // Only the system can add and remove while the installer can only remove.
- final int permissionCount = permissions.size();
- for (int i = 0; i < permissionCount; i++) {
- if ((whitelistedPermissions == null
- || !whitelistedPermissions.contains(permissions.get(i)))
- && !isCallerPrivileged) {
- throw new SecurityException("Adding to upgrade whitelist requires"
- + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
- }
- }
- }
- }
-
- if ((whitelistFlag & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
- if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
- throw new SecurityException("Modifying installer whitelist requires"
- + " being installer on record or "
- + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
- }
- }
-
- if (filterAppAccessLPr(packageSetting, Binder.getCallingUid(),
- UserHandle.getCallingUserId())) {
- return false;
- }
- }
-
- final long identity = Binder.clearCallingIdentity();
- try {
- mPermissionManager.setWhitelistedRestrictedPermissions(pkg,
- new int[]{userId}, permissions, Process.myUid(), whitelistFlag,
- mPermissionCallback);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
-
- return true;
- }
-
- @Override
public boolean shouldShowRequestPermissionRationale(String permName,
String packageName, int userId) {
if (UserHandle.getCallingUserId() != userId) {
@@ -5989,27 +5760,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
- public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
- "addOnPermissionsChangeListener");
-
- synchronized (mPackages) {
- mOnPermissionChangeListeners.addListenerLocked(listener);
- }
- }
-
- @Override
- public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
- if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
- throw new SecurityException("Instant applications don't have access to this method");
- }
- synchronized (mPackages) {
- mOnPermissionChangeListeners.removeListenerLocked(listener);
- }
- }
-
- @Override
public boolean isProtectedBroadcast(String actionName) {
// allow instant applications
synchronized (mProtectedBroadcasts) {
@@ -6171,29 +5921,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
/**
- * This method should typically only be used when granting or revoking
- * permissions, since the app may immediately restart after this call.
- * <p>
- * If you're doing surgery on app code/data, use {@link PackageFreezer} to
- * guard your work against the app being relaunched.
- */
- private void killUid(int appId, int userId, String reason) {
- final long identity = Binder.clearCallingIdentity();
- try {
- IActivityManager am = ActivityManager.getService();
- if (am != null) {
- try {
- am.killUid(appId, userId, reason);
- } catch (RemoteException e) {
- /* ignore - same process */
- }
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- }
-
- /**
* If the database version for this type of package (internal storage or
* external storage) is less than the version where package signatures
* were updated, return true.
@@ -13443,8 +13170,8 @@ public class PackageManagerService extends IPackageManager.Stub
!= 0 && pkgSetting.pkg != null) {
whiteListedPermissions = pkgSetting.pkg.requestedPermissions;
}
- setWhitelistedRestrictedPermissions(packageName, whiteListedPermissions,
- PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
+ mPermissionManager.setWhitelistedRestrictedPermissions(packageName,
+ whiteListedPermissions, FLAG_PERMISSION_WHITELIST_INSTALLER, userId);
if (pkgSetting.pkg != null) {
synchronized (mInstallLock) {
@@ -19844,7 +19571,7 @@ public class PackageManagerService extends IPackageManager.Stub
int revocationUID = IntPair.first(revokedPermissions.valueAt(i));
int revocationUserId = IntPair.second(revokedPermissions.valueAt(i));
- mOnPermissionChangeListeners.onPermissionsChanged(revocationUID);
+ mPermissionManager.notifyPermissionsChangedTEMP(revocationUID);
// Kill app later as we are holding mPackages
mHandler.post(() -> killUid(UserHandle.getAppId(revocationUID), revocationUserId,
@@ -23888,59 +23615,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
- private final static class OnPermissionChangeListeners extends Handler {
- private static final int MSG_ON_PERMISSIONS_CHANGED = 1;
-
- private final RemoteCallbackList<IOnPermissionsChangeListener> mPermissionListeners =
- new RemoteCallbackList<>();
-
- public OnPermissionChangeListeners(Looper looper) {
- super(looper);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_ON_PERMISSIONS_CHANGED: {
- final int uid = msg.arg1;
- handleOnPermissionsChanged(uid);
- } break;
- }
- }
-
- public void addListenerLocked(IOnPermissionsChangeListener listener) {
- mPermissionListeners.register(listener);
-
- }
-
- public void removeListenerLocked(IOnPermissionsChangeListener listener) {
- mPermissionListeners.unregister(listener);
- }
-
- public void onPermissionsChanged(int uid) {
- if (mPermissionListeners.getRegisteredCallbackCount() > 0) {
- obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
- }
- }
-
- private void handleOnPermissionsChanged(int uid) {
- final int count = mPermissionListeners.beginBroadcast();
- try {
- for (int i = 0; i < count; i++) {
- IOnPermissionsChangeListener callback = mPermissionListeners
- .getBroadcastItem(i);
- try {
- callback.onPermissionsChanged(uid);
- } catch (RemoteException e) {
- Log.e(TAG, "Permission listener is dead", e);
- }
- }
- } finally {
- mPermissionListeners.finishBroadcast();
- }
- }
- }
-
private class PackageManagerNative extends IPackageManagerNative.Stub {
@Override
public String[] getNamesForUids(int[] uids) throws RemoteException {
@@ -24895,11 +24569,6 @@ public class PackageManagerService extends IPackageManager.Stub
}
@Override
- public void onPermissionsChangedTEMP(int uid) {
- mOnPermissionChangeListeners.onPermissionsChanged(uid);
- }
-
- @Override
public int getTargetSdk(int uid) {
int userId = UserHandle.getUserId(uid);
@@ -24930,6 +24599,24 @@ public class PackageManagerService extends IPackageManager.Stub
return 0;
}
}
+
+ @Override
+ public boolean isCallerInstallerOfRecord(
+ @NonNull PackageParser.Package pkg, int callingUid) {
+ synchronized (mPackages) {
+ if (pkg == null) {
+ return false;
+ }
+ final PackageSetting packageSetting = (PackageSetting) pkg.mExtras;
+ if (packageSetting == null) {
+ return false;
+ }
+ final PackageSetting installerPackageSetting =
+ mSettings.mPackages.get(packageSetting.installerPackageName);
+ return installerPackageSetting != null
+ && UserHandle.isSameApp(installerPackageSetting.appId, callingUid);
+ }
+ }
}
@GuardedBy("mPackages")
diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
index 45b6834e601b..f56e1ef0de09 100644
--- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
+++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java
@@ -62,6 +62,7 @@ import com.android.internal.util.FastPrintWriter;
import com.android.server.EventLogTags;
import com.android.server.pm.dex.DexManager;
import com.android.server.pm.dex.PackageDexUsage;
+import com.android.server.pm.permission.PermissionsState;
import dalvik.system.VMRuntime;
@@ -885,4 +886,16 @@ public class PackageManagerServiceUtils {
IoUtils.closeQuietly(source);
}
}
+
+ /**
+ * Returns the {@link PermissionsState} for the given package. If the {@link PermissionsState}
+ * could not be found, {@code null} will be returned.
+ */
+ public static PermissionsState getPermissionsState(PackageParser.Package pkg) {
+ final PackageSetting packageSetting = (PackageSetting) pkg.mExtras;
+ if (packageSetting == null) {
+ return null;
+ }
+ return packageSetting.getPermissionsState();
+ }
}
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 8d735a6c2fda..bbacac91ba43 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -33,6 +33,7 @@ import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
import static android.content.pm.PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE;
import static android.content.pm.PackageManager.MASK_PERMISSION_FLAGS_ALL;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
+import static android.permission.PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
@@ -48,7 +49,9 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.UserIdInt;
+import android.app.ActivityManager;
import android.app.ApplicationPackageManager;
+import android.app.IActivityManager;
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.PermissionGroupInfoFlags;
@@ -65,7 +68,11 @@ import android.os.Binder;
import android.os.Build;
import android.os.Handler;
import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
import android.os.Process;
+import android.os.RemoteCallbackList;
+import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Trace;
import android.os.UserHandle;
@@ -73,6 +80,7 @@ import android.os.UserManager;
import android.os.UserManagerInternal;
import android.os.storage.StorageManager;
import android.os.storage.StorageManagerInternal;
+import android.permission.IOnPermissionsChangeListener;
import android.permission.IPermissionManager;
import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
@@ -94,6 +102,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.os.RoSystemProperties;
import com.android.internal.util.ArrayUtils;
+import com.android.internal.util.Preconditions;
import com.android.internal.util.function.pooled.PooledLambda;
import com.android.server.FgThread;
import com.android.server.LocalServices;
@@ -234,6 +243,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
@GuardedBy("mLock")
private CheckPermissionDelegate mCheckPermissionDelegate;
+ @GuardedBy("mLock")
+ private final OnPermissionChangeListeners mOnPermissionChangeListeners;
+
// TODO: Take a look at the methods defined in the callback.
// The callback was initially created to support the split between permission
// manager and the package manager. However, it's started to be used for other
@@ -247,7 +259,10 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
public void onPermissionGranted(int uid, int userId) {
- // TODO: implement when methods have been fully migrated
+ mOnPermissionChangeListeners.onPermissionsChanged(uid);
+
+ // Not critical; if this is lost, the application has to request again.
+ mPackageManagerInt.writeSettings(true);
}
@Override
public void onInstallPermissionGranted() {
@@ -255,7 +270,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
@Override
public void onPermissionRevoked(int uid, int userId) {
- // TODO: implement when methods have been fully migrated
+ mOnPermissionChangeListeners.onPermissionsChanged(uid);
+
+ // Critical; after this call the application should never have the permission
+ mPackageManagerInt.writeSettings(false);
+ final int appId = UserHandle.getAppId(uid);
+ killUid(appId, userId, KILL_APP_REASON_PERMISSIONS_REVOKED);
}
@Override
public void onInstallPermissionRevoked() {
@@ -276,11 +296,11 @@ public class PermissionManagerService extends IPermissionManager.Stub {
public void onPermissionUpdatedNotifyListener(@UserIdInt int[] updatedUserIds, boolean sync,
int uid) {
onPermissionUpdated(updatedUserIds, sync);
- mPackageManagerInt.onPermissionsChangedTEMP(uid);
+ mOnPermissionChangeListeners.onPermissionsChanged(uid);
}
public void onInstallPermissionUpdatedNotifyListener(int uid) {
onInstallPermissionUpdated();
- mPackageManagerInt.onPermissionsChangedTEMP(uid);
+ mOnPermissionChangeListeners.onPermissionsChanged(uid);
}
};
@@ -303,6 +323,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
SystemConfig systemConfig = SystemConfig.getInstance();
mSystemPermissions = systemConfig.getSystemPermissions();
mGlobalGids = systemConfig.getGlobalGids();
+ mOnPermissionChangeListeners = new OnPermissionChangeListeners(FgThread.get().getLooper());
// propagate permission configuration
final ArrayMap<String, SystemConfig.PermissionEntry> permConfig =
@@ -353,6 +374,29 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return LocalServices.getService(PermissionManagerServiceInternal.class);
}
+ /**
+ * This method should typically only be used when granting or revoking
+ * permissions, since the app may immediately restart after this call.
+ * <p>
+ * If you're doing surgery on app code/data, use {@link PackageFreezer} to
+ * guard your work against the app being relaunched.
+ */
+ public static void killUid(int appId, int userId, String reason) {
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ IActivityManager am = ActivityManager.getService();
+ if (am != null) {
+ try {
+ am.killUid(appId, userId, reason);
+ } catch (RemoteException e) {
+ /* ignore - same process */
+ }
+ }
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
@Nullable BasePermission getPermission(String permName) {
synchronized (mLock) {
return mSettings.getPermissionLocked(permName);
@@ -705,7 +749,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
final PermissionsState permissionsState = ps.getPermissionsState();
changed[0] |= permissionsState.updatePermissionFlagsForAllPermissions(
userId, effectiveFlagMask, effectiveFlagValues);
- mPackageManagerInt.onPermissionsChangedTEMP(pkg.applicationInfo.uid);
+ mOnPermissionChangeListeners.onPermissionsChanged(pkg.applicationInfo.uid);
}
});
@@ -839,6 +883,260 @@ public class PermissionManagerService extends IPermissionManager.Stub {
return PackageManager.PERMISSION_DENIED;
}
+ @Override
+ public void addOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS,
+ "addOnPermissionsChangeListener");
+
+ synchronized (mLock) {
+ mOnPermissionChangeListeners.addListenerLocked(listener);
+ }
+ }
+
+ @Override
+ public void removeOnPermissionsChangeListener(IOnPermissionsChangeListener listener) {
+ if (mPackageManagerInt.getInstantAppPackageName(Binder.getCallingUid()) != null) {
+ throw new SecurityException("Instant applications don't have access to this method");
+ }
+ synchronized (mLock) {
+ mOnPermissionChangeListeners.removeListenerLocked(listener);
+ }
+ }
+
+ @Override
+ @Nullable public List<String> getWhitelistedRestrictedPermissions(@NonNull String packageName,
+ @PermissionWhitelistFlags int flags, @UserIdInt int userId) {
+ Preconditions.checkNotNull(packageName);
+ Preconditions.checkFlagsArgument(flags,
+ PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
+ | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+ Preconditions.checkArgumentNonNegative(userId, null);
+
+ if (UserHandle.getCallingUserId() != userId) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.INTERACT_ACROSS_USERS,
+ "getWhitelistedRestrictedPermissions for user " + userId);
+ }
+
+ final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
+ if (pkg == null) {
+ return null;
+ }
+
+ final int callingUid = Binder.getCallingUid();
+ if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
+ return null;
+ }
+ final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
+ Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
+ == PackageManager.PERMISSION_GRANTED;
+ final boolean isCallerInstallerOnRecord =
+ mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
+
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
+ && !isCallerPrivileged) {
+ throw new SecurityException("Querying system whitelist requires "
+ + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+ }
+
+ if ((flags & (PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) != 0) {
+ if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
+ throw new SecurityException("Querying upgrade or installer whitelist"
+ + " requires being installer on record or "
+ + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+ }
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ final PermissionsState permissionsState =
+ PackageManagerServiceUtils.getPermissionsState(pkg);
+ if (permissionsState == null) {
+ return null;
+ }
+
+ int queryFlags = 0;
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
+ queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
+ }
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
+ queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
+ }
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
+ queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
+ }
+
+ ArrayList<String> whitelistedPermissions = null;
+
+ final int permissionCount = pkg.requestedPermissions.size();
+ for (int i = 0; i < permissionCount; i++) {
+ final String permissionName = pkg.requestedPermissions.get(i);
+ final int currentFlags =
+ permissionsState.getPermissionFlags(permissionName, userId);
+ if ((currentFlags & queryFlags) != 0) {
+ if (whitelistedPermissions == null) {
+ whitelistedPermissions = new ArrayList<>();
+ }
+ whitelistedPermissions.add(permissionName);
+ }
+ }
+
+ return whitelistedPermissions;
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+ }
+
+ @Override
+ public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
+ @NonNull String permName, @PermissionWhitelistFlags int flags,
+ @UserIdInt int userId) {
+ // Other argument checks are done in get/setWhitelistedRestrictedPermissions
+ Preconditions.checkNotNull(permName);
+
+ if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
+ return false;
+ }
+
+ List<String> permissions =
+ getWhitelistedRestrictedPermissions(packageName, flags, userId);
+ if (permissions == null) {
+ permissions = new ArrayList<>(1);
+ }
+ if (permissions.indexOf(permName) < 0) {
+ permissions.add(permName);
+ return setWhitelistedRestrictedPermissionsInternal(packageName, permissions,
+ flags, userId);
+ }
+ return false;
+ }
+
+ private boolean checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(
+ @NonNull String permName) {
+ synchronized (mLock) {
+ final BasePermission bp = mSettings.getPermissionLocked(permName);
+ if (bp == null) {
+ Slog.w(TAG, "No such permissions: " + permName);
+ return false;
+ }
+ if (bp.isHardOrSoftRestricted() && bp.isImmutablyRestricted()
+ && mContext.checkCallingOrSelfPermission(
+ Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
+ != PackageManager.PERMISSION_GRANTED) {
+ throw new SecurityException("Cannot modify whitelisting of an immutably "
+ + "restricted permission: " + permName);
+ }
+ return true;
+ }
+ }
+
+ @Override
+ public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
+ @NonNull String permName, @PermissionWhitelistFlags int flags,
+ @UserIdInt int userId) {
+ // Other argument checks are done in get/setWhitelistedRestrictedPermissions
+ Preconditions.checkNotNull(permName);
+
+ if (!checkExistsAndEnforceCannotModifyImmutablyRestrictedPermission(permName)) {
+ return false;
+ }
+
+ final List<String> permissions =
+ getWhitelistedRestrictedPermissions(packageName, flags, userId);
+ if (permissions != null && permissions.remove(permName)) {
+ return setWhitelistedRestrictedPermissionsInternal(packageName, permissions,
+ flags, userId);
+ }
+ return false;
+ }
+
+ private boolean setWhitelistedRestrictedPermissionsInternal(@NonNull String packageName,
+ @Nullable List<String> permissions, @PermissionWhitelistFlags int flags,
+ @UserIdInt int userId) {
+ Preconditions.checkNotNull(packageName);
+ Preconditions.checkFlagsArgument(flags,
+ PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE
+ | PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM
+ | PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER);
+ Preconditions.checkArgument(Integer.bitCount(flags) == 1);
+ Preconditions.checkArgumentNonNegative(userId, null);
+
+ if (UserHandle.getCallingUserId() != userId) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.INTERACT_ACROSS_USERS,
+ "setWhitelistedRestrictedPermissions for user " + userId);
+ }
+
+ final PackageParser.Package pkg = mPackageManagerInt.getPackage(packageName);
+ if (pkg == null) {
+ return false;
+ }
+
+ final int callingUid = Binder.getCallingUid();
+ if (mPackageManagerInt.filterAppAccess(pkg, callingUid, UserHandle.getCallingUserId())) {
+ return false;
+ }
+
+ final boolean isCallerPrivileged = mContext.checkCallingOrSelfPermission(
+ Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS)
+ == PackageManager.PERMISSION_GRANTED;
+ final boolean isCallerInstallerOnRecord =
+ mPackageManagerInt.isCallerInstallerOfRecord(pkg, callingUid);
+
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0
+ && !isCallerPrivileged) {
+ throw new SecurityException("Modifying system whitelist requires "
+ + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+ }
+
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
+ if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
+ throw new SecurityException("Modifying upgrade whitelist requires"
+ + " being installer on record or "
+ + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+ }
+ final List<String> whitelistedPermissions =
+ getWhitelistedRestrictedPermissions(pkg.packageName, flags, userId);
+ if (permissions == null || permissions.isEmpty()) {
+ if (whitelistedPermissions == null || whitelistedPermissions.isEmpty()) {
+ return true;
+ }
+ } else {
+ // Only the system can add and remove while the installer can only remove.
+ final int permissionCount = permissions.size();
+ for (int i = 0; i < permissionCount; i++) {
+ if ((whitelistedPermissions == null
+ || !whitelistedPermissions.contains(permissions.get(i)))
+ && !isCallerPrivileged) {
+ throw new SecurityException("Adding to upgrade whitelist requires"
+ + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+ }
+ }
+ }
+
+ if ((flags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
+ if (!isCallerPrivileged && !isCallerInstallerOnRecord) {
+ throw new SecurityException("Modifying installer whitelist requires"
+ + " being installer on record or "
+ + Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS);
+ }
+ }
+ }
+
+ final long identity = Binder.clearCallingIdentity();
+ try {
+ setWhitelistedRestrictedPermissionsForUser(
+ pkg, userId, permissions, Process.myUid(), flags, mDefaultPermissionCallback);
+ } finally {
+ Binder.restoreCallingIdentity(identity);
+ }
+
+ return true;
+ }
+
/**
* Get the state of the runtime permissions as xml file.
*
@@ -2317,54 +2615,6 @@ public class PermissionManagerService extends IPermissionManager.Stub {
}
}
- private @Nullable List<String> getWhitelistedRestrictedPermissions(
- @NonNull PackageParser.Package pkg, @PermissionWhitelistFlags int whitelistFlags,
- @UserIdInt int userId) {
- final PackageSetting packageSetting = (PackageSetting) pkg.mExtras;
- if (packageSetting == null) {
- return null;
- }
-
- final PermissionsState permissionsState = packageSetting.getPermissionsState();
-
- int queryFlags = 0;
- if ((whitelistFlags & PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) != 0) {
- queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
- }
- if ((whitelistFlags & PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE) != 0) {
- queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
- }
- if ((whitelistFlags & PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER) != 0) {
- queryFlags |= PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
- }
-
- ArrayList<String> whitelistedPermissions = null;
-
- final int permissionCount = pkg.requestedPermissions.size();
- for (int i = 0; i < permissionCount; i++) {
- final String permissionName = pkg.requestedPermissions.get(i);
- final int currentFlags = permissionsState.getPermissionFlags(permissionName, userId);
- if ((currentFlags & queryFlags) != 0) {
- if (whitelistedPermissions == null) {
- whitelistedPermissions = new ArrayList<>();
- }
- whitelistedPermissions.add(permissionName);
- }
- }
-
- return whitelistedPermissions;
- }
-
- private void setWhitelistedRestrictedPermissions(@NonNull PackageParser.Package pkg,
- @NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
- @PackageManager.PermissionWhitelistFlags int whitelistFlags,
- @NonNull PermissionCallback callback) {
- for (int userId : userIds) {
- setWhitelistedRestrictedPermissionsForUser(pkg, userId, permissions,
- callingUid, whitelistFlags, callback);
- }
- }
-
private void grantRequestedRuntimePermissionsForUser(PackageParser.Package pkg, int userId,
String[] grantedPermissions, int callingUid, PermissionCallback callback) {
PackageSetting ps = (PackageSetting) pkg.mExtras;
@@ -2661,13 +2911,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private void setWhitelistedRestrictedPermissionsForUser(@NonNull PackageParser.Package pkg,
@UserIdInt int userId, @Nullable List<String> permissions, int callingUid,
@PermissionWhitelistFlags int whitelistFlags, PermissionCallback callback) {
- final PackageSetting ps = (PackageSetting) pkg.mExtras;
- if (ps == null) {
+ final PermissionsState permissionsState =
+ PackageManagerServiceUtils.getPermissionsState(pkg);
+ if (permissionsState == null) {
return;
}
- final PermissionsState permissionsState = ps.getPermissionsState();
-
ArraySet<String> oldGrantedRestrictedPermissions = null;
boolean updatePermissions = false;
@@ -2769,7 +3018,9 @@ public class PermissionManagerService extends IPermissionManager.Stub {
for (int i = 0; i < oldGrantedCount; i++) {
final String permission = oldGrantedRestrictedPermissions.valueAt(i);
// Sometimes we create a new permission state instance during update.
- if (!ps.getPermissionsState().hasPermission(permission, userId)) {
+ final PermissionsState newPermissionsState =
+ PackageManagerServiceUtils.getPermissionsState(pkg);
+ if (!newPermissionsState.hasPermission(permission, userId)) {
callback.onPermissionRevoked(pkg.applicationInfo.uid, userId);
break;
}
@@ -3333,18 +3584,20 @@ public class PermissionManagerService extends IPermissionManager.Stub {
pkg, userIds, grantedPermissions, callingUid, callback);
}
@Override
- public List<String> getWhitelistedRestrictedPermissions(PackageParser.Package pkg,
- @PackageManager.PermissionWhitelistFlags int whitelistFlags, int userId) {
- return PermissionManagerService.this.getWhitelistedRestrictedPermissions(pkg,
- whitelistFlags, userId);
- }
- @Override
public void setWhitelistedRestrictedPermissions(@NonNull PackageParser.Package pkg,
@NonNull int[] userIds, @Nullable List<String> permissions, int callingUid,
- @PackageManager.PermissionWhitelistFlags int whitelistFlags,
+ @PackageManager.PermissionWhitelistFlags int flags,
@NonNull PermissionCallback callback) {
- PermissionManagerService.this.setWhitelistedRestrictedPermissions(
- pkg, userIds, permissions, callingUid, whitelistFlags, callback);
+ for (int userId : userIds) {
+ setWhitelistedRestrictedPermissionsForUser(pkg, userId, permissions,
+ callingUid, flags, callback);
+ }
+ }
+ @Override
+ public void setWhitelistedRestrictedPermissions(String packageName,
+ List<String> permissions, int flags, int userId) {
+ PermissionManagerService.this.setWhitelistedRestrictedPermissionsInternal(
+ packageName, permissions, flags, userId);
}
@Override
public void grantRuntimePermissionsGrantedToDisabledPackage(PackageParser.Package pkg,
@@ -3487,5 +3740,62 @@ public class PermissionManagerService extends IPermissionManager.Stub {
mCheckPermissionDelegate = delegate;
}
}
+ @Override
+ public void notifyPermissionsChangedTEMP(int uid) {
+ mOnPermissionChangeListeners.onPermissionsChanged(uid);
+ }
+ }
+
+ private static final class OnPermissionChangeListeners extends Handler {
+ private static final int MSG_ON_PERMISSIONS_CHANGED = 1;
+
+ private final RemoteCallbackList<IOnPermissionsChangeListener> mPermissionListeners =
+ new RemoteCallbackList<>();
+
+ OnPermissionChangeListeners(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_ON_PERMISSIONS_CHANGED: {
+ final int uid = msg.arg1;
+ handleOnPermissionsChanged(uid);
+ } break;
+ }
+ }
+
+ public void addListenerLocked(IOnPermissionsChangeListener listener) {
+ mPermissionListeners.register(listener);
+
+ }
+
+ public void removeListenerLocked(IOnPermissionsChangeListener listener) {
+ mPermissionListeners.unregister(listener);
+ }
+
+ public void onPermissionsChanged(int uid) {
+ if (mPermissionListeners.getRegisteredCallbackCount() > 0) {
+ obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
+ }
+ }
+
+ private void handleOnPermissionsChanged(int uid) {
+ final int count = mPermissionListeners.beginBroadcast();
+ try {
+ for (int i = 0; i < count; i++) {
+ IOnPermissionsChangeListener callback = mPermissionListeners
+ .getBroadcastItem(i);
+ try {
+ callback.onPermissionsChanged(uid);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Permission listener is dead", e);
+ }
+ }
+ } finally {
+ mPermissionListeners.finishBroadcast();
+ }
+ }
}
}
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 3b7341348a63..445524b3a099 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java
@@ -83,14 +83,15 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
@NonNull PackageParser.Package pkg, @NonNull int[] userIds,
@NonNull String[] grantedPermissions, int callingUid,
@Nullable PermissionCallback callback);
- public abstract @Nullable List<String> getWhitelistedRestrictedPermissions(
- @NonNull PackageParser.Package pkg,
- @PackageManager.PermissionWhitelistFlags int whitelistFlags, int userId);
public abstract void setWhitelistedRestrictedPermissions(
@NonNull PackageParser.Package pkg, @NonNull int[] userIds,
@NonNull List<String> permissions, int callingUid,
@PackageManager.PermissionWhitelistFlags int whitelistFlags,
@Nullable PermissionCallback callback);
+ /** Sets the whitelisted, restricted permissions for the given package. */
+ public abstract void setWhitelistedRestrictedPermissions(
+ @NonNull String packageName, @NonNull List<String> permissions,
+ @PackageManager.PermissionWhitelistFlags int flags, @NonNull int userId);
public abstract void revokeRuntimePermission(@NonNull String permName,
@NonNull String packageName, boolean overridePolicy, int userId,
@Nullable PermissionCallback callback);
@@ -193,6 +194,9 @@ public abstract class PermissionManagerServiceInternal extends PermissionManager
/** HACK HACK methods to allow for partial migration of data to the PermissionManager class */
public abstract @Nullable BasePermission getPermissionTEMP(@NonNull String permName);
+ /** HACK HACK notify the permission listener; this shouldn't be needed after permissions
+ * are fully removed from the package manager */
+ public abstract void notifyPermissionsChangedTEMP(int uid);
/** Get all permission that have a certain protection level */
public abstract @NonNull ArrayList<PermissionInfo> getAllPermissionWithProtectionLevel(