Merge "Move permission methods in PackageManager to PermissionManager."

This commit is contained in:
TreeHugger Robot
2020-12-11 23:24:05 +00:00
committed by Android (Google) Code Review
7 changed files with 788 additions and 257 deletions

View File

@@ -6681,8 +6681,7 @@ public final class ActivityThread extends ClientTransactionHandler {
private InstrumentationInfo prepareInstrumentation(AppBindData data) {
final InstrumentationInfo ii;
try {
ii = new ApplicationPackageManager(
null, getPackageManager(), getPermissionManager())
ii = new ApplicationPackageManager(null, getPackageManager())
.getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(

View File

@@ -59,8 +59,6 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.PackageManager.Property;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
@@ -95,8 +93,6 @@ 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.permission.PermissionManager;
import android.provider.Settings;
import android.system.ErrnoException;
@@ -106,7 +102,6 @@ import android.system.StructStat;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.LauncherIcons;
import android.util.Log;
@@ -129,7 +124,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
@@ -137,14 +131,6 @@ import java.util.Set;
public class ApplicationPackageManager extends PackageManager {
private static final String TAG = "ApplicationPackageManager";
private static final boolean DEBUG_ICONS = false;
/**
* Note: Changing this won't do anything on it's own - you should also change the filtering in
* {@link #shouldTraceGrant}
*
* @hide
*/
public static final boolean DEBUG_TRACE_GRANTS = false;
public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false;
private static final int DEFAULT_EPHEMERAL_COOKIE_MAX_SIZE_BYTES = 16384; // 16KB
@@ -171,6 +157,8 @@ public class ApplicationPackageManager extends PackageManager {
@GuardedBy("mLock")
private UserManager mUserManager;
@GuardedBy("mLock")
private PermissionManager mPermissionManager;
@GuardedBy("mLock")
private PackageInstaller mInstaller;
@GuardedBy("mLock")
private ArtManager mArtManager;
@@ -190,6 +178,15 @@ public class ApplicationPackageManager extends PackageManager {
}
}
private PermissionManager getPermissionManager() {
synchronized (mLock) {
if (mPermissionManager == null) {
mPermissionManager = mContext.getSystemService(PermissionManager.class);
}
return mPermissionManager;
}
}
@Override
public int getUserId() {
return mContext.getUserId();
@@ -355,66 +352,41 @@ public class ApplicationPackageManager extends PackageManager {
@Override
@SuppressWarnings("unchecked")
public List<PermissionGroupInfo> getAllPermissionGroups(int flags) {
try {
final ParceledListSlice<PermissionGroupInfo> parceledList =
mPermissionManager.getAllPermissionGroups(flags);
if (parceledList == null) {
return Collections.emptyList();
}
return parceledList.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().getAllPermissionGroups(flags);
}
@Override
public PermissionGroupInfo getPermissionGroupInfo(String groupName, int flags)
throws NameNotFoundException {
try {
final PermissionGroupInfo pgi =
mPermissionManager.getPermissionGroupInfo(groupName, flags);
if (pgi != null) {
return pgi;
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
final PermissionGroupInfo permissionGroupInfo = getPermissionManager()
.getPermissionGroupInfo(groupName, flags);
if (permissionGroupInfo == null) {
throw new NameNotFoundException(groupName);
}
throw new NameNotFoundException(groupName);
return permissionGroupInfo;
}
@Override
public PermissionInfo getPermissionInfo(String permName, int flags)
throws NameNotFoundException {
try {
final String packageName = mContext.getOpPackageName();
final PermissionInfo pi =
mPermissionManager.getPermissionInfo(permName, packageName, flags);
if (pi != null) {
return pi;
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
final PermissionInfo permissionInfo = getPermissionManager().getPermissionInfo(permName,
flags);
if (permissionInfo == null) {
throw new NameNotFoundException(permName);
}
throw new NameNotFoundException(permName);
return permissionInfo;
}
@Override
@SuppressWarnings("unchecked")
public List<PermissionInfo> queryPermissionsByGroup(String groupName, int flags)
throws NameNotFoundException {
try {
final ParceledListSlice<PermissionInfo> parceledList =
mPermissionManager.queryPermissionsByGroup(groupName, flags);
if (parceledList != null) {
final List<PermissionInfo> pi = parceledList.getList();
if (pi != null) {
return pi;
}
}
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
final List<PermissionInfo> permissionInfos = getPermissionManager().queryPermissionsByGroup(
groupName, flags);
if (permissionInfos == null) {
throw new NameNotFoundException(groupName);
}
throw new NameNotFoundException(groupName);
return permissionInfos;
}
@Override
@@ -724,11 +696,7 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public boolean isPermissionRevokedByPolicy(String permName, String pkgName) {
try {
return mPermissionManager.isPermissionRevokedByPolicy(permName, pkgName, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().isPermissionRevokedByPolicy(pkgName, permName);
}
/**
@@ -750,50 +718,23 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public boolean addPermission(PermissionInfo info) {
try {
return mPermissionManager.addPermission(info, false);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().addPermission(info, false);
}
@Override
public boolean addPermissionAsync(PermissionInfo info) {
try {
return mPermissionManager.addPermission(info, true);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().addPermission(info, true);
}
@Override
public void removePermission(String name) {
try {
mPermissionManager.removePermission(name);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
getPermissionManager().removePermission(name);
}
@Override
public void grantRuntimePermission(String packageName, String permissionName,
UserHandle user) {
if (DEBUG_TRACE_GRANTS
&& shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
Log.i(TAG, "App " + mContext.getPackageName() + " is granting " + packageName + " "
+ permissionName + " for user " + user.getIdentifier(), new RuntimeException());
}
try {
mPM.grantRuntimePermission(packageName, permissionName, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide */
public static boolean shouldTraceGrant(String packageName, String permissionName, int userId) {
// To be modified when debugging
return false;
getPermissionManager().grantRuntimePermission(packageName, permissionName, user);
}
@Override
@@ -804,124 +745,55 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public void revokeRuntimePermission(String packageName, String permName, UserHandle user,
String reason) {
if (DEBUG_TRACE_PERMISSION_UPDATES
&& shouldTraceGrant(packageName, permName, user.getIdentifier())) {
Log.i(TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " "
+ permName + " for user " + user.getIdentifier() + " with reason " + reason,
new RuntimeException());
}
try {
mPermissionManager
.revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
getPermissionManager().revokeRuntimePermission(packageName, permName, user, reason);
}
@Override
public int getPermissionFlags(String permName, String packageName, UserHandle user) {
try {
return mPermissionManager
.getPermissionFlags(permName, packageName, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().getPermissionFlags(packageName, permName, user);
}
@Override
public void updatePermissionFlags(String permName, String packageName,
int flagMask, int flagValues, UserHandle user) {
if (DEBUG_TRACE_PERMISSION_UPDATES
&& shouldTraceGrant(packageName, permName, user.getIdentifier())) {
Log.i(TAG, "App " + mContext.getPackageName() + " is updating flags for "
+ packageName + " "
+ permName + " for user " + user.getIdentifier() + ": "
+ DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_", flagMask)
+ " := " + DebugUtils.flagsToString(
PackageManager.class, "FLAG_PERMISSION_", flagValues),
new RuntimeException());
}
try {
final boolean checkAdjustPolicyFlagPermission =
mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
mPermissionManager.updatePermissionFlags(permName, packageName, flagMask,
flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
getPermissionManager().updatePermissionFlags(packageName, permName, flagMask, flagValues,
user);
}
@Override
public @NonNull Set<String> getWhitelistedRestrictedPermissions(
@NonNull String packageName, @PermissionWhitelistFlags int flags) {
try {
final int userId = getUserId();
final List<String> whitelist = mPermissionManager
.getWhitelistedRestrictedPermissions(packageName, flags, userId);
if (whitelist != null) {
return new ArraySet<>(whitelist);
}
return Collections.emptySet();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().getAllowlistedRestrictedPermissions(packageName, flags);
}
@Override
public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
@NonNull String permName, @PermissionWhitelistFlags int flags) {
try {
final int userId = getUserId();
return mPermissionManager
.addWhitelistedRestrictedPermission(packageName, permName, flags, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().addAllowlistedRestrictedPermission(packageName, permName,
flags);
}
@Override
public boolean setAutoRevokeWhitelisted(
@NonNull String packageName, boolean whitelisted) {
try {
final int userId = getUserId();
return mPermissionManager.setAutoRevokeWhitelisted(packageName, whitelisted, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
public boolean setAutoRevokeWhitelisted(@NonNull String packageName, boolean whitelisted) {
return getPermissionManager().setAutoRevokeExempted(packageName, whitelisted);
}
@Override
public boolean isAutoRevokeWhitelisted(@NonNull String packageName) {
try {
final int userId = getUserId();
return mPermissionManager.isAutoRevokeWhitelisted(packageName, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().isAutoRevokeExempted(packageName);
}
@Override
public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
@NonNull String permName, @PermissionWhitelistFlags int flags) {
try {
final int userId = getUserId();
return mPermissionManager
.removeWhitelistedRestrictedPermission(packageName, permName, flags, userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().removeAllowlistedRestrictedPermission(packageName, permName,
flags);
}
@Override
@UnsupportedAppUsage
public boolean shouldShowRequestPermissionRationale(String permName) {
try {
final String packageName = mContext.getPackageName();
return mPermissionManager
.shouldShowRequestPermissionRationale(permName, packageName, getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
return getPermissionManager().shouldShowRequestPermissionRationale(permName);
}
@Override
@@ -1880,34 +1752,12 @@ public class ApplicationPackageManager extends PackageManager {
@Override
public void addOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
synchronized (mPermissionListeners) {
if (mPermissionListeners.get(listener) != null) {
return;
}
OnPermissionsChangeListenerDelegate delegate =
new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
try {
mPermissionManager.addOnPermissionsChangeListener(delegate);
mPermissionListeners.put(listener, delegate);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
getPermissionManager().addOnPermissionsChangeListener(listener);
}
@Override
public void removeOnPermissionsChangeListener(OnPermissionsChangedListener listener) {
synchronized (mPermissionListeners) {
IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
if (delegate != null) {
try {
mPermissionManager.removeOnPermissionsChangeListener(delegate);
mPermissionListeners.remove(listener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
getPermissionManager().removeOnPermissionsChangeListener(listener);
}
@UnsupportedAppUsage
@@ -1918,11 +1768,9 @@ public class ApplicationPackageManager extends PackageManager {
}
}
protected ApplicationPackageManager(ContextImpl context, IPackageManager pm,
IPermissionManager permissionManager) {
protected ApplicationPackageManager(ContextImpl context, IPackageManager pm) {
mContext = context;
mPM = pm;
mPermissionManager = permissionManager;
}
/**
@@ -3234,7 +3082,6 @@ public class ApplicationPackageManager extends PackageManager {
private final ContextImpl mContext;
@UnsupportedAppUsage
private final IPackageManager mPM;
private final IPermissionManager mPermissionManager;
/** Assume locked until we hear otherwise */
private volatile boolean mUserUnlocked = false;
@@ -3245,41 +3092,6 @@ public class ApplicationPackageManager extends PackageManager {
private static ArrayMap<ResourceName, WeakReference<CharSequence>> sStringCache
= new ArrayMap<ResourceName, WeakReference<CharSequence>>();
private final Map<OnPermissionsChangedListener, IOnPermissionsChangeListener>
mPermissionListeners = new ArrayMap<>();
public class OnPermissionsChangeListenerDelegate extends IOnPermissionsChangeListener.Stub
implements Handler.Callback{
private static final int MSG_PERMISSIONS_CHANGED = 1;
private final OnPermissionsChangedListener mListener;
private final Handler mHandler;
public OnPermissionsChangeListenerDelegate(OnPermissionsChangedListener listener,
Looper looper) {
mListener = listener;
mHandler = new Handler(looper, this);
}
@Override
public void onPermissionsChanged(int uid) {
mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
}
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_PERMISSIONS_CHANGED: {
final int uid = msg.arg1;
mListener.onPermissionsChanged(uid);
return true;
}
}
return false;
}
}
@Override
public boolean canRequestPackageInstalls() {
try {

View File

@@ -72,7 +72,6 @@ import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.permission.IPermissionManager;
import android.permission.PermissionManager;
import android.system.ErrnoException;
import android.system.Os;
@@ -370,10 +369,9 @@ class ContextImpl extends Context {
}
final IPackageManager pm = ActivityThread.getPackageManager();
final IPermissionManager permissionManager = ActivityThread.getPermissionManager();
if (pm != null && permissionManager != null) {
if (pm != null) {
// Doesn't matter if we make more than one instance.
return (mPackageManager = new ApplicationPackageManager(this, pm, permissionManager));
return (mPackageManager = new ApplicationPackageManager(this, pm));
}
return null;

View File

@@ -4438,6 +4438,7 @@ public abstract class PackageManager {
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
*/
//@Deprecated
public abstract PermissionInfo getPermissionInfo(@NonNull String permName,
@PermissionInfoFlags int flags) throws NameNotFoundException;
@@ -4450,9 +4451,10 @@ public abstract class PackageManager {
* @param flags Additional option flags to modify the data returned.
* @return Returns a list of {@link PermissionInfo} containing information
* about all of the permissions in the given group.
* @throws NameNotFoundException if a package with the given name cannot be
* @throws NameNotFoundException if a group with the given name cannot be
* found on the system.
*/
//@Deprecated
@NonNull
public abstract List<PermissionInfo> queryPermissionsByGroup(@NonNull String permissionGroup,
@PermissionInfoFlags int flags) throws NameNotFoundException;
@@ -4481,7 +4483,7 @@ public abstract class PackageManager {
* Retrieve all of the information we know about a particular group of
* permissions.
*
* @param permName The fully qualified name (i.e.
* @param groupName The fully qualified name (i.e.
* com.google.permission_group.APPS) of the permission you are
* interested in.
* @param flags Additional option flags to modify the data returned.
@@ -4490,8 +4492,9 @@ public abstract class PackageManager {
* @throws NameNotFoundException if a package with the given name cannot be
* found on the system.
*/
//@Deprecated
@NonNull
public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String permName,
public abstract PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName,
@PermissionGroupInfoFlags int flags) throws NameNotFoundException;
/**
@@ -4501,6 +4504,7 @@ public abstract class PackageManager {
* @return Returns a list of {@link PermissionGroupInfo} containing
* information about all of the known permission groups.
*/
//@Deprecated
@NonNull
public abstract List<PermissionGroupInfo> getAllPermissionGroups(
@PermissionGroupInfoFlags int flags);
@@ -4757,6 +4761,7 @@ public abstract class PackageManager {
* @return Whether the permission is restricted by policy.
*/
@CheckResult
//@Deprecated
public abstract boolean isPermissionRevokedByPolicy(@NonNull String permName,
@NonNull String packageName);
@@ -4805,6 +4810,7 @@ public abstract class PackageManager {
*
* @see #removePermission(String)
*/
//@Deprecated
public abstract boolean addPermission(@NonNull PermissionInfo info);
/**
@@ -4814,6 +4820,7 @@ public abstract class PackageManager {
* expense of no guarantee the added permission will be retained if
* the device is rebooted before it is written.
*/
//@Deprecated
public abstract boolean addPermissionAsync(@NonNull PermissionInfo info);
/**
@@ -4829,6 +4836,7 @@ public abstract class PackageManager {
*
* @see #addPermission(PermissionInfo)
*/
//@Deprecated
public abstract void removePermission(@NonNull String permName);
/**
@@ -4881,6 +4889,7 @@ public abstract class PackageManager {
*
* @hide
*/
//@Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@SystemApi
@RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
@@ -4908,6 +4917,7 @@ public abstract class PackageManager {
*
* @hide
*/
//@Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@SystemApi
@RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
@@ -4936,6 +4946,7 @@ public abstract class PackageManager {
*
* @hide
*/
//@Deprecated
@SystemApi
@RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
public void revokeRuntimePermission(@NonNull String packageName,
@@ -4953,6 +4964,7 @@ public abstract class PackageManager {
*
* @hide
*/
//@Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@SystemApi
@RequiresPermission(anyOf = {
@@ -4976,6 +4988,7 @@ public abstract class PackageManager {
*
* @hide
*/
//@Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@SystemApi
@RequiresPermission(anyOf = {
@@ -5040,6 +5053,7 @@ public abstract class PackageManager {
*
* @throws SecurityException if you try to access a whitelist that you have no access to.
*/
//@Deprecated
@RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
conditional = true)
public @NonNull Set<String> getWhitelistedRestrictedPermissions(
@@ -5106,6 +5120,7 @@ public abstract class PackageManager {
*
* @throws SecurityException if you try to modify a whitelist that you have no access to.
*/
//@Deprecated
@RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
conditional = true)
public boolean addWhitelistedRestrictedPermission(@NonNull String packageName,
@@ -5175,6 +5190,7 @@ public abstract class PackageManager {
*
* @throws SecurityException if you try to modify a whitelist that you have no access to.
*/
//@Deprecated
@RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
conditional = true)
public boolean removeWhitelistedRestrictedPermission(@NonNull String packageName,
@@ -5207,6 +5223,7 @@ public abstract class PackageManager {
*
* @throws SecurityException if you you have no access to modify this.
*/
//@Deprecated
@RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
conditional = true)
public boolean setAutoRevokeWhitelisted(@NonNull String packageName, boolean whitelisted) {
@@ -5234,6 +5251,7 @@ public abstract class PackageManager {
*
* @throws SecurityException if you you have no access to this.
*/
//@Deprecated
@RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
conditional = true)
public boolean isAutoRevokeWhitelisted(@NonNull String packageName) {
@@ -5252,6 +5270,7 @@ public abstract class PackageManager {
*
* @hide
*/
//@Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@UnsupportedAppUsage
public abstract boolean shouldShowRequestPermissionRationale(@NonNull String permName);
@@ -7554,6 +7573,7 @@ public abstract class PackageManager {
*
* @hide
*/
//@Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
@@ -7567,6 +7587,7 @@ public abstract class PackageManager {
*
* @hide
*/
//@Deprecated
@SuppressWarnings("HiddenAbstractMethod")
@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)

View File

@@ -19,6 +19,7 @@ package android.permission;
import static android.os.Build.VERSION_CODES.S;
import android.Manifest;
import android.annotation.CheckResult;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -36,11 +37,22 @@ import android.compat.annotation.EnabledAfter;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.content.pm.ParceledListSlice;
import android.content.pm.PermissionGroupInfo;
import android.content.pm.PermissionInfo;
import android.content.pm.permission.SplitPermissionInfoParcelable;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.Process;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DebugUtils;
import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.Immutable;
@@ -60,7 +72,7 @@ import java.util.Set;
@SystemApi
@SystemService(Context.PERMISSION_SERVICE)
public final class PermissionManager {
private static final String TAG = PermissionManager.class.getName();
private static final String LOG_TAG = PermissionManager.class.getName();
/** @hide */
public static final String KILL_APP_REASON_PERMISSIONS_REVOKED =
@@ -80,6 +92,18 @@ public final class PermissionManager {
@EnabledAfter(targetSdkVersion = S)
public static final long CANNOT_INSTALL_WITH_BAD_PERMISSION_GROUPS = 146211400;
/**
* Note: Changing this won't do anything on its own - you should also change the filtering in
* {@link #shouldTraceGrant}.
*
* @hide
*/
public static final boolean DEBUG_TRACE_GRANTS = false;
/**
* @hide
*/
public static final boolean DEBUG_TRACE_PERMISSION_UPDATES = false;
private final @NonNull Context mContext;
private final IPackageManager mPackageManager;
@@ -88,6 +112,9 @@ public final class PermissionManager {
private final LegacyPermissionManager mLegacyPermissionManager;
private final ArrayMap<PackageManager.OnPermissionsChangedListener,
IOnPermissionsChangeListener> mPermissionListeners = new ArrayMap<>();
private List<SplitPermissionInfo> mSplitPermissionInfos;
/**
@@ -106,6 +133,649 @@ public final class PermissionManager {
mLegacyPermissionManager = context.getSystemService(LegacyPermissionManager.class);
}
/**
* Retrieve all of the information we know about a particular permission.
*
* @param permissionName the fully qualified name (e.g. com.android.permission.LOGIN) of the
* permission you are interested in
* @param flags additional option flags to modify the data returned
* @return a {@link PermissionInfo} containing information about the permission, or {@code null}
* if not found
*
* @hide Pending API
*/
@Nullable
public PermissionInfo getPermissionInfo(@NonNull String permissionName,
@PackageManager.PermissionInfoFlags int flags) {
try {
final String packageName = mContext.getOpPackageName();
return mPermissionManager.getPermissionInfo(permissionName, packageName, flags);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Query for all of the permissions associated with a particular group.
*
* @param groupName the fully qualified name (e.g. com.android.permission.LOGIN) of the
* permission group you are interested in. Use {@code null} to find all of the
* permissions not associated with a group
* @param flags additional option flags to modify the data returned
* @return a list of {@link PermissionInfo} containing information about all of the permissions
* in the given group, or {@code null} if the group is not found
*
* @hide Pending API
*/
@Nullable
public List<PermissionInfo> queryPermissionsByGroup(@NonNull String groupName,
@PackageManager.PermissionInfoFlags int flags) {
try {
final ParceledListSlice<PermissionInfo> parceledList =
mPermissionManager.queryPermissionsByGroup(groupName, flags);
if (parceledList == null) {
return null;
}
return parceledList.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Add a new dynamic permission to the system. For this to work, your package must have defined
* a permission tree through the
* {@link android.R.styleable#AndroidManifestPermissionTree &lt;permission-tree&gt;} tag in its
* manifest. A package can only add permissions to trees that were defined by either its own
* package or another with the same user id; a permission is in a tree if it matches the name of
* the permission tree + ".": for example, "com.foo.bar" is a member of the permission tree
* "com.foo".
* <p>
* It is good to make your permission tree name descriptive, because you are taking possession
* of that entire set of permission names. Thus, it must be under a domain you control, with a
* suffix that will not match any normal permissions that may be declared in any applications
* that are part of that domain.
* <p>
* New permissions must be added before any .apks are installed that use those permissions.
* Permissions you add through this method are remembered across reboots of the device. If the
* given permission already exists, the info you supply here will be used to update it.
*
* @param permissionInfo description of the permission to be added
* @param async whether the persistence of the permission should be asynchronous, allowing it to
* return quicker and batch a series of adds, at the expense of no guarantee the
* added permission will be retained if the device is rebooted before it is
* written.
* @return {@code true} if a new permission was created, {@code false} if an existing one was
* updated
* @throws SecurityException if you are not allowed to add the given permission name
*
* @see #removePermission(String)
*
* @hide Pending API
*/
public boolean addPermission(@NonNull PermissionInfo permissionInfo, boolean async) {
try {
return mPermissionManager.addPermission(permissionInfo, async);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Removes a permission that was previously added with
* {@link #addPermission(PermissionInfo, boolean)}. The same ownership rules apply -- you are
* only allowed to remove permissions that you are allowed to add.
*
* @param permissionName the name of the permission to remove
* @throws SecurityException if you are not allowed to remove the given permission name
*
* @see #addPermission(PermissionInfo, boolean)
*
* @hide Pending API
*/
public void removePermission(@NonNull String permissionName) {
try {
mPermissionManager.removePermission(permissionName);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Retrieve all of the information we know about a particular group of permissions.
*
* @param groupName the fully qualified name (e.g. com.android.permission_group.APPS) of the
* permission you are interested in
* @param flags additional option flags to modify the data returned
* @return a {@link PermissionGroupInfo} containing information about the permission, or
* {@code null} if not found
*
* @hide Pending API
*/
@Nullable
public PermissionGroupInfo getPermissionGroupInfo(@NonNull String groupName,
@PackageManager.PermissionGroupInfoFlags int flags) {
try {
return mPermissionManager.getPermissionGroupInfo(groupName, flags);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Retrieve all of the known permission groups in the system.
*
* @param flags additional option flags to modify the data returned
* @return a list of {@link PermissionGroupInfo} containing information about all of the known
* permission groups
*
* @hide Pending API
*/
@NonNull
public List<PermissionGroupInfo> getAllPermissionGroups(
@PackageManager.PermissionGroupInfoFlags int flags) {
try {
final ParceledListSlice<PermissionGroupInfo> parceledList =
mPermissionManager.getAllPermissionGroups(flags);
if (parceledList == null) {
return Collections.emptyList();
}
return parceledList.getList();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Checks whether a particular permissions has been revoked for a package by policy. Typically
* the device owner or the profile owner may apply such a policy. The user cannot grant policy
* revoked permissions, hence the only way for an app to get such a permission is by a policy
* change.
*
* @param packageName the name of the package you are checking against
* @param permissionName the name of the permission you are checking for
*
* @return whether the permission is restricted by policy
*
* @hide Pending API
*/
@CheckResult
public boolean isPermissionRevokedByPolicy(@NonNull String packageName,
@NonNull String permissionName) {
try {
return mPermissionManager.isPermissionRevokedByPolicy(permissionName, packageName,
mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/** @hide */
public static boolean shouldTraceGrant(String packageName, String permissionName, int userId) {
// To be modified when debugging
return false;
}
/**
* Grant a runtime permission to an application which the application does not already have. The
* permission must have been requested by the application. If the application is not allowed to
* hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
* permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
* <p>
* <strong>Note: </strong>Using this API requires holding
* {@code android.permission.GRANT_RUNTIME_PERMISSIONS} and if the user ID is not the current
* user {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
*
* @param packageName the package to which to grant the permission
* @param permissionName the permission name to grant
* @param user the user for which to grant the permission
*
* @see #revokeRuntimePermission(String, String, android.os.UserHandle)
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS)
//@SystemApi
public void grantRuntimePermission(@NonNull String packageName,
@NonNull String permissionName, @NonNull UserHandle user) {
if (DEBUG_TRACE_GRANTS
&& shouldTraceGrant(packageName, permissionName, user.getIdentifier())) {
Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is granting " + packageName + " "
+ permissionName + " for user " + user.getIdentifier(), new RuntimeException());
}
try {
mPermissionManager.grantRuntimePermission(packageName, permissionName,
user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Revoke a runtime permission that was previously granted by
* {@link #grantRuntimePermission(String, String, android.os.UserHandle)}. The permission must
* have been requested by and granted to the application. If the application is not allowed to
* hold the permission, a {@link java.lang.SecurityException} is thrown. If the package or
* permission is invalid, a {@link java.lang.IllegalArgumentException} is thrown.
* <p>
* <strong>Note: </strong>Using this API requires holding
* {@code android.permission.REVOKE_RUNTIME_PERMISSIONS} and if the user ID is not the current
* user {@code android.permission.INTERACT_ACROSS_USERS_FULL}.
*
* @param packageName the package from which to revoke the permission
* @param permName the permission name to revoke
* @param user the user for which to revoke the permission
* @param reason the reason for the revoke, or {@code null} for unspecified
*
* @see #grantRuntimePermission(String, String, android.os.UserHandle)
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS)
//@SystemApi
public void revokeRuntimePermission(@NonNull String packageName,
@NonNull String permName, @NonNull UserHandle user, @Nullable String reason) {
if (DEBUG_TRACE_PERMISSION_UPDATES
&& shouldTraceGrant(packageName, permName, user.getIdentifier())) {
Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is revoking " + packageName + " "
+ permName + " for user " + user.getIdentifier() + " with reason "
+ reason, new RuntimeException());
}
try {
mPermissionManager
.revokeRuntimePermission(packageName, permName, user.getIdentifier(), reason);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Gets the state flags associated with a permission.
*
* @param packageName the package name for which to get the flags
* @param permissionName the permission for which to get the flags
* @param user the user for which to get permission flags
* @return the permission flags
*
* @hide
*/
@PackageManager.PermissionFlags
@RequiresPermission(anyOf = {
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS,
android.Manifest.permission.GET_RUNTIME_PERMISSIONS
})
//@SystemApi
public int getPermissionFlags(@NonNull String packageName, @NonNull String permissionName,
@NonNull UserHandle user) {
try {
return mPermissionManager.getPermissionFlags(permissionName, packageName,
user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Updates the flags associated with a permission by replacing the flags in the specified mask
* with the provided flag values.
*
* @param packageName The package name for which to update the flags
* @param permissionName The permission for which to update the flags
* @param flagMask The flags which to replace
* @param flagValues The flags with which to replace
* @param user The user for which to update the permission flags
*
* @hide
*/
@RequiresPermission(anyOf = {
android.Manifest.permission.GRANT_RUNTIME_PERMISSIONS,
android.Manifest.permission.REVOKE_RUNTIME_PERMISSIONS
})
//@SystemApi
public void updatePermissionFlags(@NonNull String packageName, @NonNull String permissionName,
@PackageManager.PermissionFlags int flagMask,
@PackageManager.PermissionFlags int flagValues, @NonNull UserHandle user) {
if (DEBUG_TRACE_PERMISSION_UPDATES && shouldTraceGrant(packageName, permissionName,
user.getIdentifier())) {
Log.i(LOG_TAG, "App " + mContext.getPackageName() + " is updating flags for "
+ packageName + " " + permissionName + " for user "
+ user.getIdentifier() + ": " + DebugUtils.flagsToString(
PackageManager.class, "FLAG_PERMISSION_", flagMask) + " := "
+ DebugUtils.flagsToString(PackageManager.class, "FLAG_PERMISSION_",
flagValues), new RuntimeException());
}
try {
final boolean checkAdjustPolicyFlagPermission =
mContext.getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q;
mPermissionManager.updatePermissionFlags(permissionName, packageName, flagMask,
flagValues, checkAdjustPolicyFlagPermission, user.getIdentifier());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Gets the restricted permissions that have been allowlisted and the app is allowed to have
* them granted in their full form.
* <p>
* Permissions can be hard restricted which means that the app cannot hold them or soft
* restricted where the app can hold the permission but in a weaker form. Whether a permission
* is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
* {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
* declaration. Allowlisting a hard restricted permission allows for the to hold that permission
* and allowlisting a soft restricted permission allows the app to hold the permission in its
* full, unrestricted form.
* <p>
* There are four allowlists:
* <ol>
* <li>
* One for cases where the system permission policy allowlists a permission. This list
* corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
* accessed by pre-installed holders of a dedicated permission.
* <li>
* One for cases where the system allowlists the permission when upgrading from an OS version in
* which the permission was not restricted to an OS version in which the permission is
* restricted. This list corresponds to the
* {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
* pre-installed holders of a dedicated permission or the installer on record.
* <li>
* One for cases where the installer of the package allowlists a permission. This list
* corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
* accessed by pre-installed holders of a dedicated permission or the installer on record.
* <li>
* One for cases where the system exempts the permission when granting a role. This list
* corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be
* accessed by pre-installed holders of a dedicated permission.
* </ol>
*
* @param packageName the app for which to get allowlisted permissions
* @param allowlistFlag the flag to determine which allowlist to query. Only one flag can be
* passed.
* @return the allowlisted permissions that are on any of the allowlists you query for
* @throws SecurityException if you try to access a allowlist that you have no access to
*
* @see #addAllowlistedRestrictedPermission(String, String, int)
* @see #removeAllowlistedRestrictedPermission(String, String, int)
* @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
* @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
* @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
* @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE
*
* @hide Pending API
*/
@NonNull
@RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
conditional = true)
public Set<String> getAllowlistedRestrictedPermissions(@NonNull String packageName,
@PackageManager.PermissionWhitelistFlags int allowlistFlag) {
try {
final List<String> allowlist = mPermissionManager.getWhitelistedRestrictedPermissions(
packageName, allowlistFlag, mContext.getUserId());
if (allowlist == null) {
return Collections.emptySet();
}
return new ArraySet<>(allowlist);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Adds a allowlisted restricted permission for an app.
* <p>
* Permissions can be hard restricted which means that the app cannot hold them or soft
* restricted where the app can hold the permission but in a weaker form. Whether a permission
* is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
* {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
* declaration. Allowlisting a hard restricted permission allows for the to hold that permission
* and allowlisting a soft restricted permission allows the app to hold the permission in its
* full, unrestricted form.
* <p>There are four allowlists:
* <ol>
* <li>
* One for cases where the system permission policy allowlists a permission. This list
* corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
* accessed by pre-installed holders of a dedicated permission.
* <li>
* One for cases where the system allowlists the permission when upgrading from an OS version in
* which the permission was not restricted to an OS version in which the permission is
* restricted. This list corresponds to the
* {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
* pre-installed holders of a dedicated permission or the installer on record.
* <li>
* One for cases where the installer of the package allowlists a permission. This list
* corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
* accessed by pre-installed holders of a dedicated permission or the installer on record.
* <li>
* One for cases where the system exempts the permission when granting a role. This list
* corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be
* accessed by pre-installed holders of a dedicated permission.
* </ol>
* <p>
* You need to specify the allowlists for which to set the allowlisted permissions which will
* clear the previous allowlisted permissions and replace them with the provided ones.
*
* @param packageName the app for which to get allowlisted permissions
* @param permissionName the allowlisted permission to add
* @param allowlistFlags the allowlists to which to add. Passing multiple flags updates all
* specified allowlists.
* @return whether the permission was added to the allowlist
* @throws SecurityException if you try to modify a allowlist that you have no access to.
*
* @see #getAllowlistedRestrictedPermissions(String, int)
* @see #removeAllowlistedRestrictedPermission(String, String, int)
* @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
* @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
* @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
* @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE
*
* @hide Pending API
*/
@RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
conditional = true)
public boolean addAllowlistedRestrictedPermission(@NonNull String packageName,
@NonNull String permissionName,
@PackageManager.PermissionWhitelistFlags int allowlistFlags) {
try {
return mPermissionManager.addWhitelistedRestrictedPermission(packageName,
permissionName, allowlistFlags, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Removes a allowlisted restricted permission for an app.
* <p>
* Permissions can be hard restricted which means that the app cannot hold them or soft
* restricted where the app can hold the permission but in a weaker form. Whether a permission
* is {@link PermissionInfo#FLAG_HARD_RESTRICTED hard restricted} or
* {@link PermissionInfo#FLAG_SOFT_RESTRICTED soft restricted} depends on the permission
* declaration. Allowlisting a hard restricted permission allows for the to hold that permission
* and allowlisting a soft restricted permission allows the app to hold the permission in its
* full, unrestricted form.
* <p>There are four allowlists:
* <ol>
* <li>
* One for cases where the system permission policy allowlists a permission. This list
* corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM} flag. Can only be
* accessed by pre-installed holders of a dedicated permission.
* <li>
* One for cases where the system allowlists the permission when upgrading from an OS version in
* which the permission was not restricted to an OS version in which the permission is
* restricted. This list corresponds to the
* {@link PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE} flag. Can be accessed by
* pre-installed holders of a dedicated permission or the installer on record.
* <li>
* One for cases where the installer of the package allowlists a permission. This list
* corresponds to the {@link PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER} flag. Can be
* accessed by pre-installed holders of a dedicated permission or the installer on record.
* <li>
* One for cases where the system exempts the permission when granting a role. This list
* corresponds to the {@link PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE} flag. Can be
* accessed by pre-installed holders of a dedicated permission.
* </ol>
* <p>
* You need to specify the allowlists for which to set the allowlisted permissions which will
* clear the previous allowlisted permissions and replace them with the provided ones.
*
* @param packageName the app for which to get allowlisted permissions
* @param permissionName the allowlisted permission to remove
* @param allowlistFlags the allowlists from which to remove. Passing multiple flags updates all
* specified allowlists.
* @return whether the permission was removed from the allowlist
* @throws SecurityException if you try to modify a allowlist that you have no access to.
*
* @see #getAllowlistedRestrictedPermissions(String, int)
* @see #addAllowlistedRestrictedPermission(String, String, int)
* @see PackageManager#FLAG_PERMISSION_WHITELIST_SYSTEM
* @see PackageManager#FLAG_PERMISSION_WHITELIST_UPGRADE
* @see PackageManager#FLAG_PERMISSION_WHITELIST_INSTALLER
* @see PackageManager#FLAG_PERMISSION_ALLOWLIST_ROLE
*
* @hide Pending API
*/
@RequiresPermission(value = Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS,
conditional = true)
public boolean removeAllowlistedRestrictedPermission(@NonNull String packageName,
@NonNull String permissionName,
@PackageManager.PermissionWhitelistFlags int allowlistFlags) {
try {
return mPermissionManager.removeWhitelistedRestrictedPermission(packageName,
permissionName, allowlistFlags, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Checks whether an application is exempted from having its permissions be automatically
* revoked when the app is unused for an extended period of time.
* <p>
* Only the installer on record that installed the given package, or a holder of
* {@code WHITELIST_AUTO_REVOKE_PERMISSIONS} is allowed to call this.
*
* @param packageName the app for which to set exemption
* @return whether the app is exempted
* @throws SecurityException if you you have no access to this
*
* @see #setAutoRevokeExempted
*
* @hide Pending API
*/
@RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
conditional = true)
public boolean isAutoRevokeExempted(@NonNull String packageName) {
try {
return mPermissionManager.isAutoRevokeWhitelisted(packageName, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Marks an application exempted from having its permissions be automatically revoked when the
* app is unused for an extended period of time.
* <p>
* Only the installer on record that installed the given package is allowed to call this.
* <p>
* Packages start in exempted state, and it is the installer's responsibility to un-exempt the
* packages it installs, unless auto-revoking permissions from that package would cause
* breakages beyond having to re-request the permission(s).
*
* @param packageName the app for which to set exemption
* @param exempted whether the app should be exempted
* @return whether any change took effect
* @throws SecurityException if you you have no access to modify this
*
* @see #isAutoRevokeExempted
*
* @hide Pending API
*/
@RequiresPermission(value = Manifest.permission.WHITELIST_AUTO_REVOKE_PERMISSIONS,
conditional = true)
public boolean setAutoRevokeExempted(@NonNull String packageName, boolean exempted) {
try {
return mPermissionManager.setAutoRevokeWhitelisted(packageName, exempted,
mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Get whether you should show UI with rationale for requesting a permission. You should do this
* only if you do not have the permission and the context in which the permission is requested
* does not clearly communicate to the user what would be the benefit from grating this
* permission.
*
* @param permissionName a permission your app wants to request
* @return whether you can show permission rationale UI
*
* @hide
*/
//@SystemApi(client = SystemApi.Client.MODULE_LIBRARIES)
public boolean shouldShowRequestPermissionRationale(@NonNull String permissionName) {
try {
final String packageName = mContext.getPackageName();
return mPermissionManager.shouldShowRequestPermissionRationale(permissionName,
packageName, mContext.getUserId());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
/**
* Add a listener for permission changes for installed packages.
*
* @param listener the listener to add
*
* @hide
*/
//@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
public void addOnPermissionsChangeListener(
@NonNull PackageManager.OnPermissionsChangedListener listener) {
synchronized (mPermissionListeners) {
if (mPermissionListeners.get(listener) != null) {
return;
}
final OnPermissionsChangeListenerDelegate delegate =
new OnPermissionsChangeListenerDelegate(listener, Looper.getMainLooper());
try {
mPermissionManager.addOnPermissionsChangeListener(delegate);
mPermissionListeners.put(listener, delegate);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
/**
* Remove a listener for permission changes for installed packages.
*
* @param listener the listener to remove
*
* @hide
*/
//@SystemApi
@RequiresPermission(Manifest.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS)
public void removeOnPermissionsChangeListener(
@NonNull PackageManager.OnPermissionsChangedListener listener) {
synchronized (mPermissionListeners) {
final IOnPermissionsChangeListener delegate = mPermissionListeners.get(listener);
if (delegate != null) {
try {
mPermissionManager.removeOnPermissionsChangeListener(delegate);
mPermissionListeners.remove(listener);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
}
/**
* Gets the version of the runtime permission database.
*
@@ -174,7 +844,7 @@ public final class PermissionManager {
try {
parcelableList = ActivityThread.getPermissionManager().getSplitPermissions();
} catch (RemoteException e) {
Slog.e(TAG, "Error getting split permissions", e);
Slog.e(LOG_TAG, "Error getting split permissions", e);
return Collections.emptyList();
}
@@ -403,10 +1073,11 @@ public final class PermissionManager {
// permission this is.
final int appId = UserHandle.getAppId(uid);
if (appId == Process.ROOT_UID || appId == Process.SYSTEM_UID) {
Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " holds " + permission);
Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " holds "
+ permission);
return PackageManager.PERMISSION_GRANTED;
}
Slog.w(TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
Slog.w(LOG_TAG, "Missing ActivityManager; assuming " + uid + " does not hold "
+ permission);
return PackageManager.PERMISSION_DENIED;
}
@@ -586,4 +1257,35 @@ public final class PermissionManager {
sPackageNamePermissionCache.disableLocal();
}
private final class OnPermissionsChangeListenerDelegate
extends IOnPermissionsChangeListener.Stub implements Handler.Callback{
private static final int MSG_PERMISSIONS_CHANGED = 1;
private final PackageManager.OnPermissionsChangedListener mListener;
private final Handler mHandler;
public OnPermissionsChangeListenerDelegate(
PackageManager.OnPermissionsChangedListener listener, Looper looper) {
mListener = listener;
mHandler = new Handler(looper, this);
}
@Override
public void onPermissionsChanged(int uid) {
mHandler.obtainMessage(MSG_PERMISSIONS_CHANGED, uid, 0).sendToTarget();
}
@Override
public boolean handleMessage(Message msg) {
switch (msg.what) {
case MSG_PERMISSIONS_CHANGED: {
final int uid = msg.arg1;
mListener.onPermissionsChanged(uid);
return true;
}
default:
return false;
}
}
}
}

View File

@@ -90,7 +90,7 @@ public class ApplicationPackageManagerTest extends TestCase {
private boolean mAllow3rdPartyOnInternal = true;
public MockedApplicationPackageManager() {
super(null, null, null);
super(null, null);
}
public void setForceAllowOnExternal(boolean forceAllowOnExternal) {

View File

@@ -66,7 +66,6 @@ import android.annotation.Nullable;
import android.annotation.UserIdInt;
import android.app.ActivityManager;
import android.app.AppOpsManager;
import android.app.ApplicationPackageManager;
import android.app.IActivityManager;
import android.app.admin.DevicePolicyManagerInternal;
import android.app.role.RoleManager;
@@ -795,8 +794,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private void updatePermissionFlagsInternal(String permName, String packageName, int flagMask,
int flagValues, int callingUid, int userId, boolean overridePolicy,
PermissionCallback callback) {
if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES
&& ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES
&& PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
Log.i(TAG, "System is updating flags for " + packageName + " "
+ permName + " for user " + userId + " "
+ DebugUtils.flagsToString(
@@ -1456,8 +1455,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
// TODO swap permission name and package name
private void grantRuntimePermissionInternal(String permName, String packageName,
boolean overridePolicy, int callingUid, final int userId, PermissionCallback callback) {
if (ApplicationPackageManager.DEBUG_TRACE_GRANTS
&& ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
if (PermissionManager.DEBUG_TRACE_GRANTS
&& PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
Log.i(TAG, "System is granting " + packageName + " "
+ permName + " for user " + userId + " on behalf of uid " + callingUid
+ " " + mPackageManagerInt.getNameForUid(callingUid),
@@ -1633,8 +1632,8 @@ public class PermissionManagerService extends IPermissionManager.Stub {
private void revokeRuntimePermissionInternal(String permName, String packageName,
boolean overridePolicy, int callingUid, final int userId, String reason,
PermissionCallback callback) {
if (ApplicationPackageManager.DEBUG_TRACE_PERMISSION_UPDATES
&& ApplicationPackageManager.shouldTraceGrant(packageName, permName, userId)) {
if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES
&& PermissionManager.shouldTraceGrant(packageName, permName, userId)) {
Log.i(TAG, "System is revoking " + packageName + " "
+ permName + " for user " + userId + " on behalf of uid " + callingUid
+ " " + mPackageManagerInt.getNameForUid(callingUid),