diff --git a/core/api/current.txt b/core/api/current.txt
index 0aa2176f3d66c..422888f90131b 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -119,6 +119,7 @@ package android {
field public static final String NFC_TRANSACTION_EVENT = "android.permission.NFC_TRANSACTION_EVENT";
field public static final String PACKAGE_USAGE_STATS = "android.permission.PACKAGE_USAGE_STATS";
field @Deprecated public static final String PERSISTENT_ACTIVITY = "android.permission.PERSISTENT_ACTIVITY";
+ field public static final String POST_NOTIFICATIONS = "android.permission.POST_NOTIFICATIONS";
field @Deprecated public static final String PROCESS_OUTGOING_CALLS = "android.permission.PROCESS_OUTGOING_CALLS";
field public static final String QUERY_ALL_PACKAGES = "android.permission.QUERY_ALL_PACKAGES";
field public static final String READ_CALENDAR = "android.permission.READ_CALENDAR";
@@ -204,6 +205,7 @@ package android {
field public static final String LOCATION = "android.permission-group.LOCATION";
field public static final String MICROPHONE = "android.permission-group.MICROPHONE";
field public static final String NEARBY_DEVICES = "android.permission-group.NEARBY_DEVICES";
+ field public static final String NOTIFICATIONS = "android.permission-group.NOTIFICATIONS";
field public static final String PHONE = "android.permission-group.PHONE";
field public static final String SENSORS = "android.permission-group.SENSORS";
field public static final String SMS = "android.permission-group.SMS";
@@ -35270,6 +35272,7 @@ package android.provider {
field public static final String ACTION_ACCESSIBILITY_SETTINGS = "android.settings.ACCESSIBILITY_SETTINGS";
field public static final String ACTION_ADD_ACCOUNT = "android.settings.ADD_ACCOUNT_SETTINGS";
field public static final String ACTION_AIRPLANE_MODE_SETTINGS = "android.settings.AIRPLANE_MODE_SETTINGS";
+ field public static final String ACTION_ALL_APPS_NOTIFICATION_SETTINGS = "android.settings.ALL_APPS_NOTIFICATION_SETTINGS";
field public static final String ACTION_APN_SETTINGS = "android.settings.APN_SETTINGS";
field public static final String ACTION_APPLICATION_DETAILS_SETTINGS = "android.settings.APPLICATION_DETAILS_SETTINGS";
field public static final String ACTION_APPLICATION_DEVELOPMENT_SETTINGS = "android.settings.APPLICATION_DEVELOPMENT_SETTINGS";
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index d932a29beca61..a17a89be83238 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1819,6 +1819,8 @@ public class AppOpsManager {
OP_BLUETOOTH_CONNECT,
OP_BLUETOOTH_ADVERTISE,
OP_UWB_RANGING,
+ // Notifications
+ OP_POST_NOTIFICATION,
// APPOP PERMISSIONS
OP_ACCESS_NOTIFICATIONS,
@@ -2227,7 +2229,7 @@ public class AppOpsManager {
android.Manifest.permission.READ_CALENDAR,
android.Manifest.permission.WRITE_CALENDAR,
android.Manifest.permission.ACCESS_WIFI_STATE,
- null, // no permission required for notifications
+ android.Manifest.permission.POST_NOTIFICATIONS,
null, // neighboring cells shares the coarse location perm
android.Manifest.permission.CALL_PHONE,
android.Manifest.permission.READ_SMS,
diff --git a/core/java/android/content/pm/permission/CompatibilityPermissionInfo.java b/core/java/android/content/pm/permission/CompatibilityPermissionInfo.java
index 9198b95a6f71b..7370823da6f22 100644
--- a/core/java/android/content/pm/permission/CompatibilityPermissionInfo.java
+++ b/core/java/android/content/pm/permission/CompatibilityPermissionInfo.java
@@ -39,10 +39,15 @@ public class CompatibilityPermissionInfo extends ParsedUsesPermission {
/**
* List of new permissions that have been added since 1.0.
*
+ * NOTE: These must be declared in SDK version order, with permissions
+ * added to newer SDKs appearing before those added to older SDKs.
+ *
* @hide
*/
public static final CompatibilityPermissionInfo[] COMPAT_PERMS =
new CompatibilityPermissionInfo[]{
+ new CompatibilityPermissionInfo(Manifest.permission.POST_NOTIFICATIONS,
+ android.os.Build.VERSION_CODES.TIRAMISU, 0 /*usesPermissionFlags*/),
new CompatibilityPermissionInfo(Manifest.permission.WRITE_EXTERNAL_STORAGE,
android.os.Build.VERSION_CODES.DONUT, 0 /*usesPermissionFlags*/),
new CompatibilityPermissionInfo(Manifest.permission.READ_PHONE_STATE,
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 2d10adec0e26c..cbd405e3e7ea2 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1919,7 +1919,6 @@ public final class Settings {
/**
* Activity Action: Show app listing settings, filtered by those that send notifications.
*
- * @hide
*/
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_ALL_APPS_NOTIFICATION_SETTINGS =
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index c2c82399fea65..c1de2f42c0154 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1488,6 +1488,28 @@
android:description="@string/permdesc_useBiometric"
android:protectionLevel="normal" />
+
+
+
+
+
+
+
+
+
+
+
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4c1cc87960a3d..b774dc486bcd5 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -837,6 +837,11 @@
access sensor data about your vital signs
+
+ Notifications
+
+ show notifications
+
Retrieve window content
@@ -1518,6 +1523,11 @@
screen lock is not stored in plaintext so the app does not know the exact password.
+
+ show notifications
+
+ Allows the app to show notifications
+
use biometric hardware
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index e503f212480c5..9af09bb191f37 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -222,6 +222,12 @@ public class PermissionManagerService extends IPermissionManager.Stub {
/** All nearby devices permissions */
private static final List NEARBY_DEVICES_PERMISSIONS = new ArrayList<>();
+ /**
+ * All permissions that should be granted with the REVOKE_WHEN_REQUESTED flag, if they are
+ * implicitly added to a package
+ */
+ private static final List IMPLICIT_GRANTED_PERMISSIONS = new ArrayList<>();
+
/** If the permission of the value is granted, so is the key */
private static final Map FULLER_PERMISSION_MAP = new HashMap<>();
@@ -240,6 +246,7 @@ public class PermissionManagerService extends IPermissionManager.Stub {
NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_ADVERTISE);
NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_CONNECT);
NEARBY_DEVICES_PERMISSIONS.add(Manifest.permission.BLUETOOTH_SCAN);
+ IMPLICIT_GRANTED_PERMISSIONS.add(Manifest.permission.POST_NOTIFICATIONS);
}
/** Set of source package names for Privileged Permission Allowlist */
@@ -3309,6 +3316,22 @@ public class PermissionManagerService extends IPermissionManager.Stub {
inheritPermissionStateToNewImplicitPermissionLocked(sourcePerms, newPerm, ps,
pkg);
}
+ } else if (IMPLICIT_GRANTED_PERMISSIONS.contains(newPerm)
+ && !origPs.hasPermissionState(newPerm)) {
+ Permission bp = mRegistry.getPermission(newPerm);
+ if (bp == null) {
+ throw new IllegalStateException("Unknown new permission " + newPerm);
+ }
+ if ((ps.getPermissionState(newPerm).getFlags()
+ & FLAG_PERMISSION_REVIEW_REQUIRED) != 0) {
+ // No need to grant if review is required
+ continue;
+ }
+ updatedUserIds = ArrayUtils.appendInt(updatedUserIds, userId);
+ ps.updatePermissionFlags(bp,
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESTED,
+ FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
+ ps.grantPermission(bp);
}
}