Skip to content

Commit

Permalink
Add OP_RECEIVE_SENSITIVE_NOTIFICATIONS
Browse files Browse the repository at this point in the history
This app op is used for the same purpose as the permission of the same
name, but doesn't require the app to declare anything, in order to function.

Flag: android.service.notification.redact_sensitive_notifications_from_untrusted_listeners
Fixes: 346644214
Test: atest SensitiveNotificationRedactionTest
Change-Id: Ieefcbb5f0d6944993d99e929d02a36bb4d7a2b17
  • Loading branch information
Nate Myren committed Jun 14, 2024
1 parent b915c23 commit a7e2878
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 2 deletions.
1 change: 1 addition & 0 deletions core/api/test-current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,7 @@ package android.app {
field public static final String OPSTR_ACTIVITY_RECOGNITION = "android:activity_recognition";
field public static final String OPSTR_ACTIVITY_RECOGNITION_SOURCE = "android:activity_recognition_source";
field public static final String OPSTR_MANAGE_ONGOING_CALLS = "android:manage_ongoing_calls";
field @FlaggedApi("android.service.notification.redact_sensitive_notifications_from_untrusted_listeners") public static final String OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS = "android:receive_sensitive_notifications";
field public static final String OPSTR_RECORD_AUDIO_HOTWORD = "android:record_audio_hotword";
field public static final String OPSTR_RESERVED_FOR_TESTING = "android:reserved_for_testing";
field public static final String OPSTR_USE_ICC_AUTH_WITH_DEVICE_IDENTIFIER = "android:use_icc_auth_with_device_identifier";
Expand Down
29 changes: 28 additions & 1 deletion core/java/android/app/AppOpsManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import static android.location.flags.Flags.FLAG_LOCATION_BYPASS;
import static android.media.audio.Flags.roForegroundAudioControl;
import static android.permission.flags.Flags.FLAG_OP_ENABLE_MOBILE_DATA_BY_USER;
import static android.service.notification.Flags.FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS;
import static android.view.contentprotection.flags.Flags.FLAG_CREATE_ACCESSIBILITY_OVERLAY_APP_OP_ENABLED;
import static android.view.contentprotection.flags.Flags.FLAG_RAPID_CLEAR_NOTIFICATIONS_BY_LISTENER_APP_OP_ENABLED;

Expand Down Expand Up @@ -1597,9 +1598,19 @@ public static String flagsToString(@OpFlags int flags) {
*/
public static final int OP_EMERGENCY_LOCATION = AppProtoEnums.APP_OP_EMERGENCY_LOCATION;

/**
* Allows apps with a NotificationListenerService to receive notifications with sensitive
* information
* <p>Apps with a NotificationListenerService without this permission will not be able
* to view certain types of sensitive information contained in notifications
* @hide
*/
public static final int OP_RECEIVE_SENSITIVE_NOTIFICATIONS =
AppProtoEnums.APP_OP_RECEIVE_SENSITIVE_NOTIFICATIONS;

/** @hide */
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int _NUM_OP = 148;
public static final int _NUM_OP = 149;

/**
* All app ops represented as strings.
Expand Down Expand Up @@ -1751,6 +1762,7 @@ public static String flagsToString(@OpFlags int flags) {
OPSTR_ARCHIVE_ICON_OVERLAY,
OPSTR_UNARCHIVAL_CONFIRMATION,
OPSTR_EMERGENCY_LOCATION,
OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS,
})
public @interface AppOpString {}

Expand Down Expand Up @@ -2476,6 +2488,18 @@ public static String flagsToString(@OpFlags int flags) {
@FlaggedApi(FLAG_LOCATION_BYPASS)
public static final String OPSTR_EMERGENCY_LOCATION = "android:emergency_location";

/**
* Allows apps with a NotificationListenerService to receive notifications with sensitive
* information
* <p>Apps with a NotificationListenerService without this permission will not be able
* to view certain types of sensitive information contained in notifications
* @hide
*/
@TestApi
@FlaggedApi(FLAG_REDACT_SENSITIVE_NOTIFICATIONS_FROM_UNTRUSTED_LISTENERS)
public static final String OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS =
"android:receive_sensitive_notifications";

/** {@link #sAppOpsToNote} not initialized yet for this op */
private static final byte SHOULD_COLLECT_NOTE_OP_NOT_INITIALIZED = 0;
/** Should not collect noting of this app-op in {@link #sAppOpsToNote} */
Expand Down Expand Up @@ -3055,6 +3079,9 @@ public static String flagsToString(@OpFlags int flags) {
// even though this has a permission associated, this op is only used for tracking,
// and the client is responsible for checking the LOCATION_BYPASS permission.
.setPermission(Manifest.permission.LOCATION_BYPASS).build(),
new AppOpInfo.Builder(OP_RECEIVE_SENSITIVE_NOTIFICATIONS,
OPSTR_RECEIVE_SENSITIVE_NOTIFICATIONS, "RECEIVE_SENSITIVE_NOTIFICATIONS")
.setDefaultMode(MODE_IGNORED).build(),
};

// The number of longs needed to form a full bitmask of app ops
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import static android.app.ActivityManagerInternal.ServiceNotificationPolicy.NOT_FOREGROUND_SERVICE;
import static android.app.AppOpsManager.MODE_ALLOWED;
import static android.app.AppOpsManager.MODE_DEFAULT;
import static android.app.AppOpsManager.OP_RECEIVE_SENSITIVE_NOTIFICATIONS;
import static android.app.Flags.FLAG_LIFETIME_EXTENSION_REFACTOR;
import static android.app.Flags.lifetimeExtensionRefactor;
import static android.app.Flags.sortSectionByTime;
Expand Down Expand Up @@ -11933,7 +11934,10 @@ boolean isAppTrustedNotificationListenerService(int uid, String pkg) {
long token = Binder.clearCallingIdentity();
try {
if (mPackageManager.checkUidPermission(RECEIVE_SENSITIVE_NOTIFICATIONS, uid)
== PERMISSION_GRANTED || mPackageManagerInternal.isPlatformSigned(pkg)) {
== PERMISSION_GRANTED || mPackageManagerInternal.isPlatformSigned(pkg)
|| mAppOps
.noteOpNoThrow(OP_RECEIVE_SENSITIVE_NOTIFICATIONS, uid, pkg, null, null)
== MODE_ALLOWED) {
return true;
}

Expand Down

0 comments on commit a7e2878

Please sign in to comment.