Merge "Add information to grant permissions intent for continue messages"

This commit is contained in:
Nate Myren
2022-02-10 16:26:18 +00:00
committed by Android (Google) Code Review
8 changed files with 111 additions and 24 deletions

View File

@@ -3321,6 +3321,7 @@ package android.content.pm {
method @Deprecated @RequiresPermission(android.Manifest.permission.INTENT_FILTER_VERIFICATION_AGENT) public abstract void verifyIntentFilter(int, int, @NonNull java.util.List<java.lang.String>);
field public static final String ACTION_REQUEST_PERMISSIONS = "android.content.pm.action.REQUEST_PERMISSIONS";
field public static final String ACTION_REQUEST_PERMISSIONS_FOR_OTHER = "android.content.pm.action.REQUEST_PERMISSIONS_FOR_OTHER";
field public static final String EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES";
field public static final String EXTRA_REQUEST_PERMISSIONS_NAMES = "android.content.pm.extra.REQUEST_PERMISSIONS_NAMES";
field public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS = "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
field public static final String FEATURE_BROADCAST_RADIO = "android.hardware.broadcastradio";

View File

@@ -2061,7 +2061,7 @@ package android.permission {
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData();
method @NonNull @RequiresPermission(android.Manifest.permission.GET_APP_OPS_STATS) public java.util.List<android.permission.PermGroupUsage> getIndicatorAppOpUsageData(boolean);
method @NonNull public android.content.AttributionSource registerAttributionSource(@NonNull android.content.AttributionSource);
method public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String, int);
method @RequiresPermission(android.Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL) public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String, int);
}
}

View File

@@ -4341,6 +4341,21 @@ public abstract class PackageManager {
public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS
= "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";
/**
* Indicates that the package requesting permissions has legacy access for some permissions,
* or had it, but it was recently revoked. These request dialogs may show different text,
* indicating that the app is requesting continued access to a permission. Will be cleared
* from any permission request intent, if set by a non-system server app.
* <p>
* <strong>Type:</strong> String[]
* </p>
*
* @hide
*/
@SystemApi
public static final String EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES
= "android.content.pm.extra.REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES";
/**
* String extra for {@link PackageInstallObserver} in the 'extras' Bundle in case of
* {@link #INSTALL_FAILED_DUPLICATE_PERMISSION}. This extra names the package which provides

View File

@@ -16,6 +16,12 @@
package android.permission;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
import static android.content.pm.PackageManager.FLAG_PERMISSION_GRANTED_BY_ROLE;
import static android.content.pm.PackageManager.FLAG_PERMISSION_POLICY_FIXED;
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.os.Build.VERSION_CODES.S;
import android.Manifest;
@@ -106,6 +112,16 @@ public final class PermissionManager {
*/
public static final int PERMISSION_HARD_DENIED = 2;
/**
* The set of flags that indicate that a permission state has been explicitly set
*
* @hide
*/
public static final int EXPLICIT_SET_FLAGS = FLAG_PERMISSION_USER_SET
| FLAG_PERMISSION_USER_FIXED | FLAG_PERMISSION_POLICY_FIXED
| FLAG_PERMISSION_SYSTEM_FIXED | FLAG_PERMISSION_GRANTED_BY_DEFAULT
| FLAG_PERMISSION_GRANTED_BY_ROLE;
/**
* Activity action: Launch UI to review permission decisions.
* <p>
@@ -1447,6 +1463,7 @@ public final class PermissionManager {
* @hide
*/
@TestApi
@RequiresPermission(Manifest.permission.REVOKE_POST_NOTIFICATIONS_WITHOUT_KILL)
public void revokePostNotificationPermissionWithoutKillForTest(@NonNull String packageName,
int userId) {
try {

View File

@@ -179,7 +179,7 @@ public final class PermissionHelper {
assertFlag();
final long callingId = Binder.clearCallingIdentity();
try {
if (grant) {
if (grant && !reviewRequired) {
mPermManager.grantRuntimePermission(packageName, NOTIFICATION_PERMISSION, userId);
} else {
mPermManager.revokeRuntimePermission(packageName, NOTIFICATION_PERMISSION, userId,
@@ -210,8 +210,10 @@ public final class PermissionHelper {
if (pkgPerm == null || pkgPerm.packageName == null) {
return;
}
setNotificationPermission(pkgPerm.packageName, pkgPerm.userId, pkgPerm.granted,
pkgPerm.userSet, !pkgPerm.userSet);
if (!isPermissionFixed(pkgPerm.packageName, pkgPerm.userId)) {
setNotificationPermission(pkgPerm.packageName, pkgPerm.userId, pkgPerm.granted,
pkgPerm.userSet, !pkgPerm.userSet);
}
}
public boolean isPermissionFixed(String packageName, @UserIdInt int userId) {
@@ -239,7 +241,8 @@ public final class PermissionHelper {
try {
int flags = mPermManager.getPermissionFlags(packageName, NOTIFICATION_PERMISSION,
userId);
return (flags & PackageManager.FLAG_PERMISSION_USER_SET) != 0;
return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
| PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
} catch (RemoteException e) {
Slog.e(TAG, "Could not reach system server", e);
}

View File

@@ -17,6 +17,7 @@
package com.android.server.pm.permission;
import static android.Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY;
import static android.Manifest.permission.POST_NOTIFICATIONS;
import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.content.pm.PackageManager.FLAGS_PERMISSION_RESTRICTION_ANY_EXEMPT;
@@ -752,11 +753,14 @@ public class PermissionManagerServiceImpl implements PermissionManagerServiceInt
flagValues &= ~PackageManager.FLAG_PERMISSION_SYSTEM_FIXED;
flagMask &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
flagValues &= ~PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT;
flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
flagValues &= ~FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT;
flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
// REVIEW_REQUIRED can only be set by non-system apps for for POST_NOTIFICATIONS
if (!POST_NOTIFICATIONS.equals(permName)) {
flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
}
}
final AndroidPackage pkg = mPackageManagerInt.getPackage(packageName);

View File

@@ -37,7 +37,7 @@ import android.app.AppOpsManagerInternal;
import android.app.TaskInfo;
import android.app.compat.CompatChanges;
import android.compat.annotation.ChangeId;
import android.compat.annotation.EnabledSince;
import android.compat.annotation.EnabledAfter;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
@@ -58,6 +58,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
import android.permission.PermissionControllerManager;
import android.permission.PermissionManager;
import android.provider.Settings;
import android.provider.Telephony;
import android.telecom.TelecomManager;
@@ -141,7 +142,7 @@ public final class PermissionPolicyService extends SystemService {
* This change reflects the presence of the new Notification Permission
*/
@ChangeId
@EnabledSince(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.S_V2)
private static final long NOTIFICATION_PERM_CHANGE_ID = 194833441L;
private List<String> mAppOpPermissions;
@@ -149,7 +150,6 @@ public final class PermissionPolicyService extends SystemService {
private Context mContext;
private PackageManagerInternal mPackageManagerInternal;
private NotificationManagerInternal mNotificationManager;
private PermissionManagerServiceInternal mPermissionManagerService;
private final PackageManager mPackageManager;
public PermissionPolicyService(@NonNull Context context) {
@@ -1001,13 +1001,48 @@ public final class PermissionPolicyService extends SystemService {
private class Internal extends PermissionPolicyInternal {
private ActivityInterceptorCallback mActivityInterceptorCallback =
// UIDs that, if a grant dialog is shown for POST_NOTIFICATIONS before next reboot,
// should display a "continue allowing" message, rather than an "allow" message
private final ArraySet<Integer> mContinueNotifGrantMessageUids = new ArraySet<>();
private final ActivityInterceptorCallback mActivityInterceptorCallback =
new ActivityInterceptorCallback() {
@Nullable
@Override
public ActivityInterceptorCallback.ActivityInterceptResult intercept(
ActivityInterceptorInfo info) {
return null;
String action = info.intent.getAction();
ActivityInterceptResult result = null;
if (!PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action)
&& !PackageManager.ACTION_REQUEST_PERMISSIONS.equals(action)) {
return null;
}
// Only this interceptor can add LEGACY_ACCESS_PERMISSION_NAMES
if (info.intent.getStringArrayExtra(PackageManager
.EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES)
!= null) {
result = new ActivityInterceptResult(
new Intent(info.intent), info.checkedOptions);
result.intent.removeExtra(PackageManager
.EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES);
}
if (PackageManager.ACTION_REQUEST_PERMISSIONS.equals(action)
&& !mContinueNotifGrantMessageUids.contains(info.realCallingUid)) {
return result;
}
if (PackageManager.ACTION_REQUEST_PERMISSIONS_FOR_OTHER.equals(action)) {
String otherPkg = info.intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
if (otherPkg == null || (mPackageManager.getPermissionFlags(
POST_NOTIFICATIONS, otherPkg, UserHandle.of(info.userId))
& FLAG_PERMISSION_REVIEW_REQUIRED) == 0) {
return result;
}
}
mContinueNotifGrantMessageUids.remove(info.realCallingUid);
return new ActivityInterceptResult(info.intent.putExtra(PackageManager
.EXTRA_REQUEST_PERMISSIONS_LEGACY_ACCESS_PERMISSION_NAMES,
new String[] { POST_NOTIFICATIONS }), info.checkedOptions);
}
@Override
@@ -1057,12 +1092,21 @@ public final class PermissionPolicyService extends SystemService {
launchNotificationPermissionRequestDialog(packageName, user, taskId);
}
private void clearNotificationReviewFlagsIfNeeded(String packageName, UserHandle userId) {
if (!CompatChanges.isChangeEnabled(NOTIFICATION_PERM_CHANGE_ID, packageName, userId)) {
private void clearNotificationReviewFlagsIfNeeded(String packageName, UserHandle user) {
if (!CompatChanges.isChangeEnabled(NOTIFICATION_PERM_CHANGE_ID, packageName, user)
|| ((mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, packageName, user)
& FLAG_PERMISSION_REVIEW_REQUIRED) == 0)) {
return;
}
mPackageManager.updatePermissionFlags(POST_NOTIFICATIONS, packageName,
FLAG_PERMISSION_REVIEW_REQUIRED, 0, userId);
try {
int uid = mPackageManager.getPackageUidAsUser(packageName, 0,
user.getIdentifier());
mContinueNotifGrantMessageUids.add(uid);
mPackageManager.updatePermissionFlags(POST_NOTIFICATIONS, packageName,
FLAG_PERMISSION_REVIEW_REQUIRED, 0, user);
} catch (PackageManager.NameNotFoundException e) {
// Do nothing
}
}
private void launchNotificationPermissionRequestDialog(String pkgName, UserHandle user,
@@ -1142,8 +1186,10 @@ public final class PermissionPolicyService extends SystemService {
if (pkg == null || pkg.getPackageName() == null
|| Objects.equals(pkgName, mPackageManager.getPermissionControllerPackageName())
|| pkg.getTargetSdkVersion() < Build.VERSION_CODES.M) {
Slog.w(LOG_TAG, "Cannot check for Notification prompt, no package for "
+ pkgName + " or pkg is Permission Controller");
if (pkg == null) {
Slog.w(LOG_TAG, "Cannot check for Notification prompt, no package for "
+ pkgName);
}
return false;
}
@@ -1175,9 +1221,10 @@ public final class PermissionPolicyService extends SystemService {
}
boolean hasCreatedNotificationChannels = mNotificationManager
.getNumNotificationChannelsForPackage(pkg.getPackageName(), uid, true) > 0;
boolean needsReview = (mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, pkgName,
user) & FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
return hasCreatedNotificationChannels && needsReview;
int flags = mPackageManager.getPermissionFlags(POST_NOTIFICATIONS, pkgName, user);
boolean explicitlySet = (flags & PermissionManager.EXPLICIT_SET_FLAGS) != 0;
boolean needsReview = (flags & FLAG_PERMISSION_REVIEW_REQUIRED) != 0;
return hasCreatedNotificationChannels && (needsReview || !explicitlySet);
}
}
}

View File

@@ -233,8 +233,8 @@ public class PermissionHelperTest extends UiServiceTestCase {
public void testSetNotificationPermission_grantReviewRequired() throws Exception {
mPermissionHelper.setNotificationPermission("pkg", 10, true, false, true);
verify(mPermManager).grantRuntimePermission(
"pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
verify(mPermManager).revokeRuntimePermission(
"pkg", Manifest.permission.POST_NOTIFICATIONS, 10, "PermissionHelper");
verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
FLAG_PERMISSION_REVIEW_REQUIRED, FLAG_PERMISSION_REVIEW_REQUIRED, true, 10);
}
@@ -245,8 +245,8 @@ public class PermissionHelperTest extends UiServiceTestCase {
"pkg", 10, true, false);
mPermissionHelper.setNotificationPermission(pkgPerm);
verify(mPermManager).grantRuntimePermission(
"pkg", Manifest.permission.POST_NOTIFICATIONS, 10);
verify(mPermManager).revokeRuntimePermission(
"pkg", Manifest.permission.POST_NOTIFICATIONS, 10, "PermissionHelper");
verify(mPermManager).updatePermissionFlags("pkg", Manifest.permission.POST_NOTIFICATIONS,
FLAG_PERMISSION_REVIEW_REQUIRED, FLAG_PERMISSION_REVIEW_REQUIRED, true, 10);
}