Merge "Log visual interruptions to usagestats." into pi-dev

am: 1c7c2bdd0b

Change-Id: I3a6497fbdddc5f728c5702f1a60e479d99fd7277
This commit is contained in:
Julia Reynolds
2018-03-21 00:08:39 +00:00
committed by android-build-merger
5 changed files with 640 additions and 4 deletions

View File

@@ -5401,6 +5401,7 @@ package android.app {
method public android.app.Notification.Builder extend(android.app.Notification.Extender);
method public android.os.Bundle getExtras();
method public deprecated android.app.Notification getNotification();
method public android.app.Notification.Style getStyle();
method public static android.app.Notification.Builder recoverBuilder(android.content.Context, android.app.Notification);
method public android.app.Notification.Builder setActions(android.app.Notification.Action...);
method public android.app.Notification.Builder setAutoCancel(boolean);

View File

@@ -89,6 +89,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Set;
/**
@@ -2598,6 +2599,80 @@ public class Notification implements Parcelable
}
};
/**
* @hide
*/
public static boolean areActionsVisiblyDifferent(Notification first, Notification second) {
Notification.Action[] firstAs = first.actions;
Notification.Action[] secondAs = second.actions;
if (firstAs == null && secondAs != null || firstAs != null && secondAs == null) {
return true;
}
if (firstAs != null && secondAs != null) {
if (firstAs.length != secondAs.length) {
return true;
}
for (int i = 0; i < firstAs.length; i++) {
if (!Objects.equals(firstAs[i].title, secondAs[i].title)) {
return true;
}
RemoteInput[] firstRs = firstAs[i].getRemoteInputs();
RemoteInput[] secondRs = secondAs[i].getRemoteInputs();
if (firstRs == null) {
firstRs = new RemoteInput[0];
}
if (secondRs == null) {
secondRs = new RemoteInput[0];
}
if (firstRs.length != secondRs.length) {
return true;
}
for (int j = 0; j < firstRs.length; j++) {
if (!Objects.equals(firstRs[j].getLabel(), secondRs[j].getLabel())) {
return true;
}
CharSequence[] firstCs = firstRs[i].getChoices();
CharSequence[] secondCs = secondRs[i].getChoices();
if (firstCs == null) {
firstCs = new CharSequence[0];
}
if (secondCs == null) {
secondCs = new CharSequence[0];
}
if (firstCs.length != secondCs.length) {
return true;
}
for (int k = 0; k < firstCs.length; k++) {
if (!Objects.equals(firstCs[k], secondCs[k])) {
return true;
}
}
}
}
}
return false;
}
/**
* @hide
*/
public static boolean areStyledNotificationsVisiblyDifferent(Builder first, Builder second) {
if (first.getStyle() == null) {
return second.getStyle() != null;
}
if (second.getStyle() == null) {
return true;
}
return first.getStyle().areNotificationsVisiblyDifferent(second.getStyle());
}
/**
* @hide
*/
public static boolean areRemoteViewsChanged(Builder first, Builder second) {
return !first.usesStandardHeader() || !second.usesStandardHeader();
}
/**
* Parcelling creates multiple copies of objects in {@code extras}. Fix them.
* <p>
@@ -4038,6 +4113,13 @@ public class Notification implements Parcelable
return this;
}
/**
* Returns the style set by {@link #setStyle(Style)}.
*/
public Style getStyle() {
return mStyle;
}
/**
* Specify the value of {@link #visibility}.
*
@@ -5867,6 +5949,11 @@ public class Notification implements Parcelable
*/
public void validate(Context context) {
}
/**
* @hide
*/
public abstract boolean areNotificationsVisiblyDifferent(Style other);
}
/**
@@ -5919,6 +6006,13 @@ public class Notification implements Parcelable
return this;
}
/**
* @hide
*/
public Bitmap getBigPicture() {
return mPicture;
}
/**
* Provide the bitmap to be used as the payload for the BigPicture notification.
*/
@@ -6059,6 +6153,18 @@ public class Notification implements Parcelable
public boolean hasSummaryInHeader() {
return false;
}
/**
* @hide
*/
@Override
public boolean areNotificationsVisiblyDifferent(Style other) {
if (other == null || getClass() != other.getClass()) {
return true;
}
BigPictureStyle otherS = (BigPictureStyle) other;
return !Objects.equals(getBigPicture(), otherS.getBigPicture());
}
}
/**
@@ -6119,6 +6225,13 @@ public class Notification implements Parcelable
return this;
}
/**
* @hide
*/
public CharSequence getBigText() {
return mBigText;
}
/**
* @hide
*/
@@ -6191,6 +6304,18 @@ public class Notification implements Parcelable
return contentView;
}
/**
* @hide
*/
@Override
public boolean areNotificationsVisiblyDifferent(Style other) {
if (other == null || getClass() != other.getClass()) {
return true;
}
BigTextStyle newS = (BigTextStyle) other;
return !Objects.equals(getBigText(), newS.getBigText());
}
static void applyBigTextContentView(Builder builder,
RemoteViews contentView, CharSequence bigTextText) {
contentView.setTextViewText(R.id.big_text, builder.processTextSpans(bigTextText));
@@ -6533,6 +6658,58 @@ public class Notification implements Parcelable
return remoteViews;
}
/**
* @hide
*/
@Override
public boolean areNotificationsVisiblyDifferent(Style other) {
if (other == null || getClass() != other.getClass()) {
return true;
}
MessagingStyle newS = (MessagingStyle) other;
List<MessagingStyle.Message> oldMs = getMessages();
List<MessagingStyle.Message> newMs = newS.getMessages();
if (oldMs == null) {
oldMs = new ArrayList<>();
}
if (newMs == null) {
newMs = new ArrayList<>();
}
int n = oldMs.size();
if (n != newMs.size()) {
return true;
}
for (int i = 0; i < n; i++) {
MessagingStyle.Message oldM = oldMs.get(i);
MessagingStyle.Message newM = newMs.get(i);
if (!Objects.equals(oldM.getText(), newM.getText())) {
return true;
}
if (!Objects.equals(oldM.getDataUri(), newM.getDataUri())) {
return true;
}
CharSequence oldSender = oldM.getSenderPerson() == null ? oldM.getSender()
: oldM.getSenderPerson().getName();
CharSequence newSender = newM.getSenderPerson() == null ? newM.getSender()
: newM.getSenderPerson().getName();
if (!Objects.equals(oldSender, newSender)) {
return true;
}
String oldKey = oldM.getSenderPerson() == null
? null : oldM.getSenderPerson().getKey();
String newKey = newM.getSenderPerson() == null
? null : newM.getSenderPerson().getKey();
if (!Objects.equals(oldKey, newKey)) {
return true;
}
// Other fields (like timestamp) intentionally excluded
}
return false;
}
private Message findLatestIncomingMessage() {
return findLatestIncomingMessage(mMessages);
}
@@ -6961,6 +7138,13 @@ public class Notification implements Parcelable
return this;
}
/**
* @hide
*/
public ArrayList<CharSequence> getLines() {
return mTexts;
}
/**
* @hide
*/
@@ -7042,6 +7226,18 @@ public class Notification implements Parcelable
return contentView;
}
/**
* @hide
*/
@Override
public boolean areNotificationsVisiblyDifferent(Style other) {
if (other == null || getClass() != other.getClass()) {
return true;
}
InboxStyle newS = (InboxStyle) other;
return !Objects.equals(getLines(), newS.getLines());
}
private void handleInboxImageMargin(RemoteViews contentView, int id, boolean first) {
int endMargin = 0;
if (first) {
@@ -7205,6 +7401,18 @@ public class Notification implements Parcelable
}
}
/**
* @hide
*/
@Override
public boolean areNotificationsVisiblyDifferent(Style other) {
if (other == null || getClass() != other.getClass()) {
return true;
}
// All fields to compare are on the Notification object
return false;
}
private RemoteViews generateMediaActionButton(Action action, int color) {
final boolean tombstone = (action.actionIntent == null);
RemoteViews button = new BuilderRemoteViews(mBuilder.mContext.getApplicationInfo(),
@@ -7414,6 +7622,18 @@ public class Notification implements Parcelable
}
remoteViews.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
}
/**
* @hide
*/
@Override
public boolean areNotificationsVisiblyDifferent(Style other) {
if (other == null || getClass() != other.getClass()) {
return true;
}
// Comparison done for all custom RemoteViews, independent of style
return false;
}
}
/**
@@ -7504,6 +7724,18 @@ public class Notification implements Parcelable
return makeBigContentViewWithCustomContent(customRemoteView);
}
/**
* @hide
*/
@Override
public boolean areNotificationsVisiblyDifferent(Style other) {
if (other == null || getClass() != other.getClass()) {
return true;
}
// Comparison done for all custom RemoteViews, independent of style
return false;
}
private RemoteViews buildIntoRemoteView(RemoteViews remoteViews, int id,
RemoteViews customContent) {
if (customContent != null) {

View File

@@ -1294,7 +1294,8 @@ public class NotificationManagerService extends SystemService {
NotificationAssistants notificationAssistants, ConditionProviders conditionProviders,
ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper,
NotificationUsageStats usageStats, AtomicFile policyFile,
ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am) {
ActivityManager activityManager, GroupHelper groupHelper, IActivityManager am,
UsageStatsManagerInternal appUsageStats) {
Resources resources = getContext().getResources();
mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1307,7 +1308,7 @@ public class NotificationManagerService extends SystemService {
mPackageManagerClient = packageManagerClient;
mAppOps = (AppOpsManager) getContext().getSystemService(Context.APP_OPS_SERVICE);
mVibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
mAppUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
mAppUsageStats = appUsageStats;
mAlarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
mCompanionManager = companionManager;
mActivityManager = activityManager;
@@ -1449,7 +1450,8 @@ public class NotificationManagerService extends SystemService {
null, snoozeHelper, new NotificationUsageStats(getContext()),
new AtomicFile(new File(systemDir, "notification_policy.xml"), "notification-policy"),
(ActivityManager) getContext().getSystemService(Context.ACTIVITY_SERVICE),
getGroupHelper(), ActivityManager.getService());
getGroupHelper(), ActivityManager.getService(),
LocalServices.getService(UsageStatsManagerInternal.class));
// register for various Intents
IntentFilter filter = new IntentFilter();
@@ -4300,6 +4302,7 @@ public class NotificationManagerService extends SystemService {
if (index < 0) {
mNotificationList.add(r);
mUsageStats.registerPostedByApp(r);
r.setInterruptive(true);
} else {
old = mNotificationList.get(index);
mNotificationList.set(index, r);
@@ -4310,6 +4313,7 @@ public class NotificationManagerService extends SystemService {
// revoke uri permissions for changed uris
revokeUriPermissions(r, old);
r.isUpdate = true;
r.setInterruptive(isVisuallyInterruptive(old, r));
}
mNotificationsByKey.put(n.getKey(), r);
@@ -4375,6 +4379,52 @@ public class NotificationManagerService extends SystemService {
}
}
/**
* If the notification differs enough visually, consider it a new interruptive notification.
*/
@GuardedBy("mNotificationLock")
@VisibleForTesting
protected boolean isVisuallyInterruptive(NotificationRecord old, NotificationRecord r) {
Notification oldN = old.sbn.getNotification();
Notification newN = r.sbn.getNotification();
if (oldN.extras == null || newN.extras == null) {
return false;
}
if (!Objects.equals(oldN.extras.get(Notification.EXTRA_TITLE),
newN.extras.get(Notification.EXTRA_TITLE))) {
return true;
}
if (!Objects.equals(oldN.extras.get(Notification.EXTRA_TEXT),
newN.extras.get(Notification.EXTRA_TEXT))) {
return true;
}
if (oldN.extras.containsKey(Notification.EXTRA_PROGRESS) && newN.hasCompletedProgress()) {
return true;
}
// Actions
if (Notification.areActionsVisiblyDifferent(oldN, newN)) {
return true;
}
try {
Notification.Builder oldB = Notification.Builder.recoverBuilder(getContext(), oldN);
Notification.Builder newB = Notification.Builder.recoverBuilder(getContext(), newN);
// Style based comparisons
if (Notification.areStyledNotificationsVisiblyDifferent(oldB, newB)) {
return true;
}
// Remote views
if (Notification.areRemoteViewsChanged(oldB, newB)) {
return true;
}
} catch (Exception e) {
Slog.w(TAG, "error recovering builder", e);
}
return false;
}
/**
* Keeps the last 5 packages that have notified, by user.
*/

View File

@@ -68,6 +68,7 @@ import android.app.Notification.MessagingStyle.Message;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.app.usage.UsageStatsManagerInternal;
import android.companion.ICompanionDeviceManager;
import android.content.ComponentName;
import android.content.Context;
@@ -264,7 +265,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
mPackageManager, mPackageManagerClient, mockLightsManager,
mListeners, mAssistants, mConditionProviders,
mCompanionMgr, mSnoozeHelper, mUsageStats, mPolicyFile, mActivityManager,
mGroupHelper, mAm);
mGroupHelper, mAm, mock(UsageStatsManagerInternal.class));
} catch (SecurityException e) {
if (!e.getMessage().contains("Permission Denial: not allowed to send broadcast")) {
throw e;
@@ -2662,4 +2663,80 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertEquals(expected, actual);
}
@Test
public void testVisualDifference_diffTitle() {
Notification.Builder nb1 = new Notification.Builder(mContext, "")
.setContentTitle("foo");
StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
nb1.build(), new UserHandle(mUid), null, 0);
NotificationRecord r1 =
new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
Notification.Builder nb2 = new Notification.Builder(mContext, "")
.setContentTitle("bar");
StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
nb2.build(), new UserHandle(mUid), null, 0);
NotificationRecord r2 =
new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
assertTrue(mService.isVisuallyInterruptive(r1, r2));
}
@Test
public void testVisualDifference_diffText() {
Notification.Builder nb1 = new Notification.Builder(mContext, "")
.setContentText("foo");
StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
nb1.build(), new UserHandle(mUid), null, 0);
NotificationRecord r1 =
new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
Notification.Builder nb2 = new Notification.Builder(mContext, "")
.setContentText("bar");
StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
nb2.build(), new UserHandle(mUid), null, 0);
NotificationRecord r2 =
new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
assertTrue(mService.isVisuallyInterruptive(r1, r2));
}
@Test
public void testVisualDifference_diffProgress() {
Notification.Builder nb1 = new Notification.Builder(mContext, "")
.setProgress(100, 90, false);
StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
nb1.build(), new UserHandle(mUid), null, 0);
NotificationRecord r1 =
new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
Notification.Builder nb2 = new Notification.Builder(mContext, "")
.setProgress(100, 100, false);
StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
nb2.build(), new UserHandle(mUid), null, 0);
NotificationRecord r2 =
new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
assertTrue(mService.isVisuallyInterruptive(r1, r2));
}
@Test
public void testVisualDifference_diffProgressNotDone() {
Notification.Builder nb1 = new Notification.Builder(mContext, "")
.setProgress(100, 90, false);
StatusBarNotification sbn1 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
nb1.build(), new UserHandle(mUid), null, 0);
NotificationRecord r1 =
new NotificationRecord(mContext, sbn1, mock(NotificationChannel.class));
Notification.Builder nb2 = new Notification.Builder(mContext, "")
.setProgress(100, 91, false);
StatusBarNotification sbn2 = new StatusBarNotification(PKG, PKG, 0, "tag", mUid, 0,
nb2.build(), new UserHandle(mUid), null, 0);
NotificationRecord r2 =
new NotificationRecord(mContext, sbn2, mock(NotificationChannel.class));
assertFalse(mService.isVisuallyInterruptive(r1, r2));
}
}

View File

@@ -20,18 +20,27 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.ActivityManager;
import android.app.Notification;
import android.app.Notification.Person;
import android.app.PendingIntent;
import android.app.RemoteInput;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Build;
import android.support.test.filters.SmallTest;
import android.support.test.runner.AndroidJUnit4;
import android.widget.RemoteViews;
import com.android.server.UiServiceTestCase;
@@ -112,5 +121,272 @@ public class NotificationTest extends UiServiceTestCase {
assertEquals(Color.RED, new Notification.CarExtender(before).getColor());
assertEquals("dismiss", new Notification.WearableExtender(before).getDismissalId());
}
@Test
public void testStyleChangeVisiblyDifferent_noStyles() {
Notification.Builder n1 = new Notification.Builder(mContext, "test");
Notification.Builder n2 = new Notification.Builder(mContext, "test");
assertFalse(Notification.areStyledNotificationsVisiblyDifferent(n1, n2));
}
@Test
public void testStyleChangeVisiblyDifferent_noStyleToStyle() {
Notification.Builder n1 = new Notification.Builder(mContext, "test");
Notification.Builder n2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.BigTextStyle());
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2));
}
@Test
public void testStyleChangeVisiblyDifferent_styleToNoStyle() {
Notification.Builder n2 = new Notification.Builder(mContext, "test");
Notification.Builder n1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.BigTextStyle());
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2));
}
@Test
public void testStyleChangeVisiblyDifferent_changeStyle() {
Notification.Builder n1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.InboxStyle());
Notification.Builder n2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.BigTextStyle());
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(n1, n2));
}
@Test
public void testInboxTextChange() {
Notification.Builder nInbox1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.InboxStyle().addLine("a").addLine("b"));
Notification.Builder nInbox2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.InboxStyle().addLine("b").addLine("c"));
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nInbox1, nInbox2));
}
@Test
public void testBigTextTextChange() {
Notification.Builder nBigText1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.BigTextStyle().bigText("something"));
Notification.Builder nBigText2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.BigTextStyle().bigText("else"));
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nBigText1, nBigText2));
}
@Test
public void testBigPictureChange() {
Notification.Builder nBigPic1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.BigPictureStyle().bigPicture(mock(Bitmap.class)));
Notification.Builder nBigPic2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.BigPictureStyle().bigPicture(mock(Bitmap.class)));
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nBigPic1, nBigPic2));
}
@Test
public void testMessagingChange_text() {
Notification.Builder nM1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
"a", 100, mock(Notification.Person.class))));
Notification.Builder nM2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
"a", 100, mock(Notification.Person.class)))
.addMessage(new Notification.MessagingStyle.Message(
"b", 100, mock(Notification.Person.class)))
);
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2));
}
@Test
public void testMessagingChange_data() {
Notification.Builder nM1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
"a", 100, mock(Person.class))
.setData("text", mock(Uri.class))));
Notification.Builder nM2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
"a", 100, mock(Person.class))));
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2));
}
@Test
public void testMessagingChange_sender() {
Person a = mock(Person.class);
when(a.getName()).thenReturn("A");
Person b = mock(Person.class);
when(b.getName()).thenReturn("b");
Notification.Builder nM1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message("a", 100, b)));
Notification.Builder nM2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message("a", 100, a)));
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2));
}
@Test
public void testMessagingChange_key() {
Person a = mock(Person.class);
when(a.getKey()).thenReturn("A");
Person b = mock(Person.class);
when(b.getKey()).thenReturn("b");
Notification.Builder nM1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message("a", 100, a)));
Notification.Builder nM2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message("a", 100, b)));
assertTrue(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2));
}
@Test
public void testMessagingChange_ignoreTimeChange() {
Notification.Builder nM1 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
"a", 100, mock(Notification.Person.class))));
Notification.Builder nM2 = new Notification.Builder(mContext, "test")
.setStyle(new Notification.MessagingStyle("")
.addMessage(new Notification.MessagingStyle.Message(
"a", 1000, mock(Notification.Person.class)))
);
assertFalse(Notification.areStyledNotificationsVisiblyDifferent(nM1, nM2));
}
@Test
public void testRemoteViews_nullChange() {
Notification.Builder n1 = new Notification.Builder(mContext, "test")
.setContent(mock(RemoteViews.class));
Notification.Builder n2 = new Notification.Builder(mContext, "test");
assertTrue(Notification.areRemoteViewsChanged(n1, n2));
n1 = new Notification.Builder(mContext, "test");
n2 = new Notification.Builder(mContext, "test")
.setContent(mock(RemoteViews.class));
assertTrue(Notification.areRemoteViewsChanged(n1, n2));
n1 = new Notification.Builder(mContext, "test")
.setCustomBigContentView(mock(RemoteViews.class));
n2 = new Notification.Builder(mContext, "test");
assertTrue(Notification.areRemoteViewsChanged(n1, n2));
n1 = new Notification.Builder(mContext, "test");
n2 = new Notification.Builder(mContext, "test")
.setCustomBigContentView(mock(RemoteViews.class));
assertTrue(Notification.areRemoteViewsChanged(n1, n2));
n1 = new Notification.Builder(mContext, "test");
n2 = new Notification.Builder(mContext, "test");
assertFalse(Notification.areRemoteViewsChanged(n1, n2));
}
@Test
public void testActionsDifferent_null() {
Notification n1 = new Notification.Builder(mContext, "test")
.build();
Notification n2 = new Notification.Builder(mContext, "test")
.build();
assertFalse(Notification.areActionsVisiblyDifferent(n1, n2));
}
@Test
public void testActionsDifferentSame() {
PendingIntent intent = mock(PendingIntent.class);
Icon icon = mock(Icon.class);
Notification n1 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build())
.build();
Notification n2 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build())
.build();
assertFalse(Notification.areActionsVisiblyDifferent(n1, n2));
}
@Test
public void testActionsDifferentText() {
PendingIntent intent = mock(PendingIntent.class);
Icon icon = mock(Icon.class);
Notification n1 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build())
.build();
Notification n2 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 2", intent).build())
.build();
assertTrue(Notification.areActionsVisiblyDifferent(n1, n2));
}
@Test
public void testActionsDifferentNumber() {
PendingIntent intent = mock(PendingIntent.class);
Icon icon = mock(Icon.class);
Notification n1 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build())
.build();
Notification n2 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 1", intent).build())
.addAction(new Notification.Action.Builder(icon, "TEXT 2", intent).build())
.build();
assertTrue(Notification.areActionsVisiblyDifferent(n1, n2));
}
@Test
public void testActionsDifferentIntent() {
PendingIntent intent1 = mock(PendingIntent.class);
PendingIntent intent2 = mock(PendingIntent.class);
Icon icon = mock(Icon.class);
Notification n1 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 1", intent1).build())
.build();
Notification n2 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 1", intent2).build())
.build();
assertFalse(Notification.areActionsVisiblyDifferent(n1, n2));
}
@Test
public void testActionsDifferentRemoteInputs() {
PendingIntent intent = mock(PendingIntent.class);
Icon icon = mock(Icon.class);
Notification n1 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 1", intent)
.addRemoteInput(new RemoteInput.Builder("a")
.setChoices(new CharSequence[] {"i", "m"})
.build())
.build())
.build();
Notification n2 = new Notification.Builder(mContext, "test")
.addAction(new Notification.Action.Builder(icon, "TEXT 1", intent)
.addRemoteInput(new RemoteInput.Builder("a")
.setChoices(new CharSequence[] {"t", "m"})
.build())
.build())
.build();
assertTrue(Notification.areActionsVisiblyDifferent(n1, n2));
}
}