diff options
| -rw-r--r-- | Android.bp | 2 | ||||
| -rw-r--r-- | core/java/android/app/ApplicationPackageManager.java | 27 | ||||
| -rw-r--r-- | core/java/android/content/pm/IPackageManager.aidl | 14 | ||||
| -rw-r--r-- | core/java/android/content/pm/PackageManagerInternal.java | 8 | ||||
| -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.aidl | 14 | ||||
| -rw-r--r-- | core/java/android/permission/PermissionManager.java | 3 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerService.java | 371 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/PackageManagerServiceUtils.java | 13 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/permission/PermissionManagerService.java | 444 | ||||
| -rw-r--r-- | services/core/java/com/android/server/pm/permission/PermissionManagerServiceInternal.java | 10 |
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( |