}
}
r.setVisibility(true, nv.rank, nv.count);
+ maybeRecordInterruptionLocked(r);
nv.recycle();
}
// Note that we might receive this event after notifications
@GuardedBy("mNotificationLock")
protected void maybeRecordInterruptionLocked(NotificationRecord r) {
- if (r.isInterruptive()) {
+ if (r.isInterruptive() && !r.hasRecordedInterruption()) {
mAppUsageStats.reportInterruptiveNotification(r.sbn.getPackageName(),
r.getChannel().getId(),
getRealUserId(r.sbn.getUserId()));
logRecentLocked(r);
+ r.setRecordedInterruption(true);
}
}
if (DBG) Slog.d(TAG, "Marking notification as seen " + keys[i]);
reportSeen(r);
r.setSeen();
+ maybeRecordInterruptionLocked(r);
}
}
}
if (index < 0) {
mNotificationList.add(r);
mUsageStats.registerPostedByApp(r);
- r.setInterruptive(isVisuallyInterruptive(null, r));
+ r.setInterruptive(true);
} else {
old = mNotificationList.get(index);
mNotificationList.set(index, r);
notification.flags |=
old.getNotification().flags & FLAG_FOREGROUND_SERVICE;
r.isUpdate = true;
- r.setInterruptive(isVisuallyInterruptive(old, r));
+ r.setTextChanged(isVisuallyInterruptive(old, r));
}
mNotificationsByKey.put(n.getKey(), r);
private final NotificationStats mStats;
private int mUserSentiment;
private boolean mIsInterruptive;
+ private boolean mTextChanged;
+ private boolean mRecordedInterruption;
private int mNumberOfSmartRepliesAdded;
private boolean mHasSeenSmartReplies;
/**
/** Mark the notification as seen by the user. */
public void setSeen() {
mStats.setSeen();
+ if (mTextChanged) {
+ mIsInterruptive = true;
+ }
}
public void setAuthoritativeRank(int authoritativeRank) {
mIsInterruptive = interruptive;
}
+ public void setTextChanged(boolean textChanged) {
+ mTextChanged = textChanged;
+ }
+
+ public void setRecordedInterruption(boolean recorded) {
+ mRecordedInterruption = recorded;
+ }
+
+ public boolean hasRecordedInterruption() {
+ return mRecordedInterruption;
+ }
+
public boolean isInterruptive() {
return mIsInterruptive;
}
import android.os.Bundle;
import android.os.IBinder;
import android.os.Process;
+import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.MediaStore;
import android.provider.Settings.Secure;
import android.service.notification.Adjustment;
+import android.service.notification.INotificationListener;
import android.service.notification.NotificationListenerService;
import android.service.notification.NotificationStats;
import android.service.notification.NotifyingApp;
@Mock
private NotificationUsageStats mUsageStats;
@Mock
+ private UsageStatsManagerInternal mAppUsageStats;
+ @Mock
private AudioManager mAudioManager;
@Mock
ActivityManager mActivityManager;
mPackageManager, mPackageManagerClient, mockLightsManager,
mListeners, mAssistants, mConditionProviders,
mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
- mGroupHelper, mAm, mock(UsageStatsManagerInternal.class),
+ mGroupHelper, mAm, mAppUsageStats,
mock(DevicePolicyManagerInternal.class));
} catch (SecurityException e) {
if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
assertEquals(true, mService.canUseManagedServices("d"));
}
+
+ @Test
+ public void testOnNotificationVisibilityChanged_triggersInterruptionUsageStat() {
+ final NotificationRecord r = generateNotificationRecord(
+ mTestNotificationChannel, 1, null, true);
+ r.setTextChanged(true);
+ mService.addNotification(r);
+
+ mService.mNotificationDelegate.onNotificationVisibilityChanged(new NotificationVisibility[]
+ {NotificationVisibility.obtain(r.getKey(), 1, 1, true)},
+ new NotificationVisibility[]{});
+
+ verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
+ }
+
+ @Test
+ public void testSetNotificationsShownFromListener_triggersInterruptionUsageStat()
+ throws RemoteException {
+ final NotificationRecord r = generateNotificationRecord(
+ mTestNotificationChannel, 1, null, true);
+ r.setTextChanged(true);
+ mService.addNotification(r);
+
+ mBinderService.setNotificationsShownFromListener(null, new String[] {r.getKey()});
+
+ verify(mAppUsageStats).reportInterruptiveNotification(anyString(), anyString(), anyInt());
+ }
+
+ @Test
+ public void testMybeRecordInterruptionLocked_doesNotRecordTwice()
+ throws RemoteException {
+ final NotificationRecord r = generateNotificationRecord(
+ mTestNotificationChannel, 1, null, true);
+ r.setInterruptive(true);
+ mService.addNotification(r);
+
+ mService.maybeRecordInterruptionLocked(r);
+ mService.maybeRecordInterruptionLocked(r);
+
+ verify(mAppUsageStats, times(1)).reportInterruptiveNotification(
+ anyString(), anyString(), anyInt());
+ }
}
record.setIsAppImportanceLocked(false);
assertEquals(false, record.getIsAppImportanceLocked());
}
+
+ @Test
+ public void testIsInterruptive_textChanged_notSeen() {
+ StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+ false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /* defaultLights */, null /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+ assertEquals(false, record.isInterruptive());
+
+ record.setTextChanged(true);
+ assertEquals(false, record.isInterruptive());
+ }
+
+ @Test
+ public void testIsInterruptive_textChanged_seen() {
+ StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+ false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /* defaultLights */, null /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+ assertEquals(false, record.isInterruptive());
+
+ record.setTextChanged(true);
+ record.setSeen();
+ assertEquals(true, record.isInterruptive());
+ }
+
+ @Test
+ public void testIsInterruptive_textNotChanged_seen() {
+ StatusBarNotification sbn = getNotification(false /*preO */, false /* noisy */,
+ false /* defaultSound */, false /* buzzy */, false /* defaultBuzz */,
+ false /* lights */, false /* defaultLights */, null /* group */);
+ NotificationRecord record = new NotificationRecord(mMockContext, sbn, channel);
+
+ assertEquals(false, record.isInterruptive());
+
+ record.setTextChanged(false);
+ record.setSeen();
+ assertEquals(false, record.isInterruptive());
+ }
}