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:
@@ -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",
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.content.pm;
|
||||
package android.permission;
|
||||
|
||||
/**
|
||||
* Listener for changes in the permissions for installed packages.
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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}.
|
||||
*
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user