Merge "Unify USE_FULL_SCREEN_INTENT permission check." into udc-dev

This commit is contained in:
Hai Zhang
2023-04-07 20:28:08 +00:00
committed by Android (Google) Code Review
3 changed files with 70 additions and 39 deletions

View File

@@ -24,6 +24,7 @@ import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationHistory;
import android.app.NotificationManager;
import android.content.AttributionSource;
import android.content.ComponentName;
import android.content.Intent;
import android.content.pm.ParceledListSlice;
@@ -225,6 +226,7 @@ interface INotificationManager
void setNotificationDelegate(String callingPkg, String delegate);
String getNotificationDelegate(String callingPkg);
boolean canNotifyAsPackage(String callingPkg, String targetPkg, int userId);
boolean canUseFullScreenIntent(in AttributionSource attributionSource);
void setPrivateNotificationsAllowed(boolean allow);
boolean getPrivateNotificationsAllowed();

View File

@@ -31,7 +31,6 @@ import android.compat.annotation.UnsupportedAppUsage;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.PermissionChecker;
import android.content.pm.ParceledListSlice;
import android.content.pm.ShortcutInfo;
import android.graphics.drawable.Icon;
@@ -877,19 +876,11 @@ public class NotificationManager {
* {@link android.provider.Settings#ACTION_MANAGE_APP_USE_FULL_SCREEN_INTENT}.
*/
public boolean canUseFullScreenIntent() {
final int result = PermissionChecker.checkPermissionForPreflight(mContext,
android.Manifest.permission.USE_FULL_SCREEN_INTENT,
mContext.getAttributionSource());
switch (result) {
case PermissionChecker.PERMISSION_GRANTED:
return true;
case PermissionChecker.PERMISSION_SOFT_DENIED:
case PermissionChecker.PERMISSION_HARD_DENIED:
return false;
default:
if (localLOGV) Log.v(TAG, "Unknown PermissionChecker result: " + result);
return false;
INotificationManager service = getService();
try {
return service.canUseFullScreenIntent(mContext.getAttributionSource());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

View File

@@ -3814,6 +3814,28 @@ public class NotificationManagerService extends SystemService {
return false;
}
@Override
public boolean canUseFullScreenIntent(@NonNull AttributionSource attributionSource) {
final String packageName = attributionSource.getPackageName();
final int uid = attributionSource.getUid();
final int userId = UserHandle.getUserId(uid);
checkCallerIsSameApp(packageName, uid, userId);
final ApplicationInfo applicationInfo;
try {
applicationInfo = mPackageManagerClient.getApplicationInfoAsUser(
packageName, PackageManager.MATCH_DIRECT_BOOT_AUTO, userId);
} catch (NameNotFoundException e) {
Slog.e(TAG, "Failed to getApplicationInfo() in canUseFullScreenIntent()", e);
return false;
}
final boolean showStickyHunIfDenied = mFlagResolver.isEnabled(
SystemUiSystemPropertiesFlags.NotificationFlags
.SHOW_STICKY_HUN_FOR_DENIED_FSI);
return checkUseFullScreenIntentPermission(attributionSource, applicationInfo,
showStickyHunIfDenied /* isAppOpPermission */, false /* forDataDelivery */);
}
@Override
public void updateNotificationChannelGroupForPackage(String pkg, int uid,
NotificationChannelGroup group) throws RemoteException {
@@ -6826,36 +6848,28 @@ public class NotificationManagerService extends SystemService {
notification.flags &= ~FLAG_FSI_REQUESTED_BUT_DENIED;
if (notification.fullScreenIntent != null && ai.targetSdkVersion >= Build.VERSION_CODES.Q) {
if (notification.fullScreenIntent != null) {
final boolean forceDemoteFsiToStickyHun = mFlagResolver.isEnabled(
SystemUiSystemPropertiesFlags.NotificationFlags.FSI_FORCE_DEMOTE);
final boolean showStickyHunIfDenied = mFlagResolver.isEnabled(
SystemUiSystemPropertiesFlags.NotificationFlags.SHOW_STICKY_HUN_FOR_DENIED_FSI);
if (forceDemoteFsiToStickyHun) {
makeStickyHun(notification, pkg, userId);
} else if (showStickyHunIfDenied) {
final AttributionSource source = new AttributionSource.Builder(notificationUid)
.setPackageName(pkg)
.build();
final int permissionResult = mPermissionManager.checkPermissionForDataDelivery(
Manifest.permission.USE_FULL_SCREEN_INTENT, source, /* message= */ null);
if (permissionResult != PermissionManager.PERMISSION_GRANTED) {
makeStickyHun(notification, pkg, userId);
}
} else {
int fullscreenIntentPermission = getContext().checkPermission(
android.Manifest.permission.USE_FULL_SCREEN_INTENT, -1, notificationUid);
if (fullscreenIntentPermission != PERMISSION_GRANTED) {
notification.fullScreenIntent = null;
Slog.w(TAG, "Package " + pkg + ": Use of fullScreenIntent requires the"
+ "USE_FULL_SCREEN_INTENT permission");
final AttributionSource attributionSource =
new AttributionSource.Builder(notificationUid).setPackageName(pkg).build();
final boolean showStickyHunIfDenied = mFlagResolver.isEnabled(
SystemUiSystemPropertiesFlags.NotificationFlags
.SHOW_STICKY_HUN_FOR_DENIED_FSI);
final boolean canUseFullScreenIntent = checkUseFullScreenIntentPermission(
attributionSource, ai, showStickyHunIfDenied /* isAppOpPermission */,
true /* forDataDelivery */);
if (!canUseFullScreenIntent) {
if (showStickyHunIfDenied) {
makeStickyHun(notification, pkg, userId);
} else {
notification.fullScreenIntent = null;
Slog.w(TAG, "Package " + pkg + ": Use of fullScreenIntent requires the"
+ "USE_FULL_SCREEN_INTENT permission");
}
}
}
}
@@ -6951,6 +6965,30 @@ public class NotificationManagerService extends SystemService {
ai.packageName) == AppOpsManager.MODE_ALLOWED;
}
private boolean checkUseFullScreenIntentPermission(@NonNull AttributionSource attributionSource,
@NonNull ApplicationInfo applicationInfo, boolean isAppOpPermission,
boolean forDataDelivery) {
if (applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q) {
return true;
}
if (isAppOpPermission) {
final int permissionResult;
if (forDataDelivery) {
permissionResult = mPermissionManager.checkPermissionForDataDelivery(
permission.USE_FULL_SCREEN_INTENT, attributionSource, /* message= */ null);
} else {
permissionResult = mPermissionManager.checkPermissionForPreflight(
permission.USE_FULL_SCREEN_INTENT, attributionSource);
}
return permissionResult == PermissionManager.PERMISSION_GRANTED;
} else {
final int permissionResult = getContext().checkPermission(
permission.USE_FULL_SCREEN_INTENT, attributionSource.getPid(),
attributionSource.getUid());
return permissionResult == PERMISSION_GRANTED;
}
}
private void checkRemoteViews(String pkg, String tag, int id, Notification notification) {
if (removeRemoteView(pkg, tag, id, notification.contentView)) {
notification.contentView = null;