Move whitelist permissions to permission manager

Also while doing this, it made sense to move the permission change
listener to the permission manager [it resulted in fewer hacks to
get the two sides to talk to one another].

Bug: 135279435
Test: atest PermissionUpdateListenerTest
Test: android.content.pm.cts.PackageManagerTest
Test: android.permission2.cts.RestrictedPermissionsTest
Change-Id: Ie08701dfe999cd435335103f4b4daeaa0b31ef10
This commit is contained in:
Todd Kennedy
2019-07-08 10:34:29 -07:00
parent ca1ea17a3e
commit 7e3dd3afe2
11 changed files with 467 additions and 441 deletions

View File

@@ -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",

View File

@@ -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();

View File

@@ -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(

View File

@@ -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);
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package android.content.pm;
package android.permission;
/**
* Listener for changes in the permissions for installed packages.

View File

@@ -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);
}

View File

@@ -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}.
*

View File

@@ -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");
@@ -5726,228 +5719,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) {
@@ -5988,27 +5759,6 @@ public class PackageManagerService extends IPackageManager.Stub
return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
}
@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
@@ -6170,29 +5920,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
@@ -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 {
@@ -24894,11 +24568,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")

View File

@@ -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();
}
}

View File

@@ -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();
}
}
}
}

View File

@@ -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(