diff options
2 files changed, 132 insertions, 3 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 83c576e9259d..dbe04b0945e0 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -58,6 +58,7 @@ import static android.content.Context.BIND_AUTO_CREATE; import static android.content.Context.BIND_FOREGROUND_SERVICE; import static android.content.Context.BIND_NOT_PERCEPTIBLE; import static android.content.pm.PackageManager.FEATURE_LEANBACK; +import static android.content.pm.PackageManager.FEATURE_TELECOM; import static android.content.pm.PackageManager.FEATURE_TELEVISION; import static android.content.pm.PackageManager.MATCH_ALL; import static android.content.pm.PackageManager.MATCH_DIRECT_BOOT_AWARE; @@ -2161,6 +2162,11 @@ public class NotificationManagerService extends SystemService { mAccessibilityManager = am; } + @VisibleForTesting + void setTelecomManager(TelecomManager tm) { + mTelecomManager = tm; + } + // TODO: All tests should use this init instead of the one-off setters above. @VisibleForTesting void init(WorkerHandler handler, RankingHandler rankingHandler, @@ -6978,8 +6984,13 @@ public class NotificationManagerService extends SystemService { private boolean isCallNotification(String pkg, int uid) { final long identity = Binder.clearCallingIdentity(); try { - return mTelecomManager.isInManagedCall() || mTelecomManager.isInSelfManagedCall( - pkg, UserHandle.getUserHandleForUid(uid)); + if (mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM) + && mTelecomManager != null) { + return mTelecomManager.isInManagedCall() + || mTelecomManager.isInSelfManagedCall( + pkg, UserHandle.getUserHandleForUid(uid)); + } + return false; } finally { Binder.restoreCallingIdentity(identity); } @@ -7405,6 +7416,7 @@ public class NotificationManagerService extends SystemService { @Override public void run() { boolean appBanned = !areNotificationsEnabledForPackageInt(pkg, uid); + boolean isCallNotification = isCallNotification(pkg, uid); synchronized (mNotificationLock) { try { NotificationRecord r = null; @@ -7423,8 +7435,10 @@ public class NotificationManagerService extends SystemService { final StatusBarNotification n = r.getSbn(); final Notification notification = n.getNotification(); + boolean isCallNotificationAndCorrectStyle = isCallNotification + && notification.isStyle(Notification.CallStyle.class); - if (!notification.isMediaNotification() + if (!(notification.isMediaNotification() || isCallNotificationAndCorrectStyle) && (appBanned || isRecordBlockedLocked(r))) { mUsageStats.registerBlocked(r); if (DBG) { diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java index c0cd7a755e25..850c9e3e6903 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -52,6 +52,7 @@ import static android.app.PendingIntent.FLAG_IMMUTABLE; import static android.app.PendingIntent.FLAG_MUTABLE; import static android.app.PendingIntent.FLAG_ONE_SHOT; import static android.content.pm.ActivityInfo.RESIZE_MODE_RESIZEABLE; +import static android.content.pm.PackageManager.FEATURE_TELECOM; import static android.content.pm.PackageManager.FEATURE_WATCH; import static android.content.pm.PackageManager.PERMISSION_DENIED; import static android.content.pm.PackageManager.PERMISSION_GRANTED; @@ -448,6 +449,8 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class)); when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0}); + when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(true); + ActivityManager.AppTask task = mock(ActivityManager.AppTask.class); List<ActivityManager.AppTask> taskList = new ArrayList<>(); ActivityManager.RecentTaskInfo taskInfo = new ActivityManager.RecentTaskInfo(); @@ -9194,6 +9197,118 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { r.getSbn().getPackageName(), r.getUser())).thenReturn(true); assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), r.getSbn().getId(), r.getSbn().getTag(), r, false)).isTrue(); + + // set telecom manager to null - blocked + mService.setTelecomManager(null); + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)) + .isFalse(); + + // set telecom feature to false - blocked + when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false); + assertThat(mService.checkDisqualifyingFeatures(r.getUserId(), r.getUid(), + r.getSbn().getId(), r.getSbn().getTag(), r, false)) + .isFalse(); + } + + @Test + public void testCallNotificationsBypassBlock_atPost() throws Exception { + when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false); + when(mAssistants.isSameUser(any(), anyInt())).thenReturn(true); + + Notification.Builder nb = + new Notification.Builder(mContext, mTestNotificationChannel.getId()) + .setContentTitle("foo") + .setSmallIcon(android.R.drawable.sym_def_app_icon) + .addAction(new Notification.Action.Builder(null, "test", null).build()); + StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, + nb.build(), UserHandle.getUserHandleForUid(mUid), null, 0); + NotificationRecord r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + mBinderService.setNotificationsEnabledForPackage( + r.getSbn().getPackageName(), r.getUid(), false); + + // normal blocked notifications - blocked + mService.addEnqueuedNotification(r); + NotificationManagerService.PostNotificationRunnable runnable = + mService.new PostNotificationRunnable(r.getKey(), r.getSbn().getPackageName(), + r.getUid(), SystemClock.elapsedRealtime()); + runnable.run(); + waitForIdle(); + + verify(mUsageStats).registerBlocked(any()); + verify(mUsageStats, never()).registerPostedByApp(any()); + + // just using the style - blocked + mService.clearNotifications(); + reset(mUsageStats); + Person person = new Person.Builder().setName("caller").build(); + nb.setStyle(Notification.CallStyle.forOngoingCall(person, mock(PendingIntent.class))); + nb.setFullScreenIntent(mock(PendingIntent.class), true); + sbn = new StatusBarNotification(PKG, PKG, 8, "tag", mUid, 0, nb.build(), + UserHandle.getUserHandleForUid(mUid), null, 0); + r = new NotificationRecord(mContext, sbn, mTestNotificationChannel); + + mService.addEnqueuedNotification(r); + runnable = mService.new PostNotificationRunnable( + r.getKey(), r.getSbn().getPackageName(), r.getUid(), SystemClock.elapsedRealtime()); + runnable.run(); + waitForIdle(); + + verify(mUsageStats).registerBlocked(any()); + verify(mUsageStats, never()).registerPostedByApp(any()); + + // style + managed call - bypasses block + mService.clearNotifications(); + reset(mUsageStats); + when(mTelecomManager.isInManagedCall()).thenReturn(true); + + mService.addEnqueuedNotification(r); + runnable.run(); + waitForIdle(); + + verify(mUsageStats, never()).registerBlocked(any()); + verify(mUsageStats).registerPostedByApp(any()); + + // style + self managed call - bypasses block + mService.clearNotifications(); + reset(mUsageStats); + when(mTelecomManager.isInSelfManagedCall(r.getSbn().getPackageName(), r.getUser())) + .thenReturn(true); + + mService.addEnqueuedNotification(r); + runnable.run(); + waitForIdle(); + + verify(mUsageStats, never()).registerBlocked(any()); + verify(mUsageStats).registerPostedByApp(any()); + + // set telecom manager to null - notifications should be blocked + // but post notifications runnable should not crash + mService.clearNotifications(); + reset(mUsageStats); + mService.setTelecomManager(null); + + mService.addEnqueuedNotification(r); + runnable.run(); + waitForIdle(); + + verify(mUsageStats).registerBlocked(any()); + verify(mUsageStats, never()).registerPostedByApp(any()); + + // set FEATURE_TELECOM to false - notifications should be blocked + // but post notifications runnable should not crash + mService.setTelecomManager(mTelecomManager); + when(mPackageManagerClient.hasSystemFeature(FEATURE_TELECOM)).thenReturn(false); + reset(mUsageStats); + mService.setTelecomManager(null); + + mService.addEnqueuedNotification(r); + runnable.run(); + waitForIdle(); + + verify(mUsageStats).registerBlocked(any()); + verify(mUsageStats, never()).registerPostedByApp(any()); } @Test |