blob: 513c1629a7a7c5bea567b39d2a31d5688ee7ec34 [file] [log] [blame]
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.app.cts;
import static android.app.Notification.FLAG_BUBBLE;
import static android.graphics.drawable.Icon.TYPE_ADAPTIVE_BITMAP;
import static android.graphics.drawable.Icon.TYPE_RESOURCE;
import android.app.Notification;
import android.app.Notification.Action.Builder;
import android.app.Notification.MessagingStyle;
import android.app.Notification.MessagingStyle.Message;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Person;
import android.app.RemoteInput;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.Icon;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.StrictMode;
import android.test.AndroidTestCase;
import android.widget.RemoteViews;
import androidx.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
public class NotificationTest extends AndroidTestCase {
private static final String TEXT_RESULT_KEY = "text";
private static final String DATA_RESULT_KEY = "data";
private static final String DATA_AND_TEXT_RESULT_KEY = "data and text";
private Notification.Action mAction;
private Notification mNotification;
private Context mContext;
private static final String TICKER_TEXT = "tickerText";
private static final String CONTENT_TITLE = "contentTitle";
private static final String CONTENT_TEXT = "contentText";
private static final String URI_STRING = "uriString";
private static final String ACTION_TITLE = "actionTitle";
private static final int BUBBLE_HEIGHT = 300;
private static final int BUBBLE_HEIGHT_RESID = 31415;
private static final String BUBBLE_SHORTCUT_ID = "bubbleShortcutId";
private static final int TOLERANCE = 200;
private static final long TIMEOUT = 4000;
private static final NotificationChannel CHANNEL = new NotificationChannel("id", "name",
NotificationManager.IMPORTANCE_HIGH);
private static final String SHORTCUT_ID = "shortcutId";
private static final String SETTING_TEXT = "work chats";
private static final boolean ALLOW_SYS_GEN_CONTEXTUAL_ACTIONS = false;
@Override
protected void setUp() throws Exception {
super.setUp();
mContext = getContext();
mNotification = new Notification();
}
public void testConstructor() {
mNotification = null;
mNotification = new Notification();
assertNotNull(mNotification);
assertTrue(System.currentTimeMillis() - mNotification.when < TOLERANCE);
mNotification = null;
final int notificationTime = 200;
mNotification = new Notification(0, TICKER_TEXT, notificationTime);
assertEquals(notificationTime, mNotification.when);
assertEquals(0, mNotification.icon);
assertEquals(TICKER_TEXT, mNotification.tickerText);
assertEquals(0, mNotification.number);
}
public void testBuilderConstructor() {
mNotification = new Notification.Builder(mContext, CHANNEL.getId()).build();
assertEquals(CHANNEL.getId(), mNotification.getChannelId());
assertEquals(Notification.BADGE_ICON_NONE, mNotification.getBadgeIconType());
assertNull(mNotification.getShortcutId());
assertEquals(Notification.GROUP_ALERT_ALL, mNotification.getGroupAlertBehavior());
assertEquals((long) 0, mNotification.getTimeoutAfter());
}
public void testDescribeContents() {
final int expected = 0;
mNotification = new Notification();
assertEquals(expected, mNotification.describeContents());
}
public void testCategories() {
assertNotNull(Notification.CATEGORY_ALARM);
assertNotNull(Notification.CATEGORY_CALL);
assertNotNull(Notification.CATEGORY_EMAIL);
assertNotNull(Notification.CATEGORY_ERROR);
assertNotNull(Notification.CATEGORY_EVENT);
assertNotNull(Notification.CATEGORY_MESSAGE);
assertNotNull(Notification.CATEGORY_NAVIGATION);
assertNotNull(Notification.CATEGORY_PROGRESS);
assertNotNull(Notification.CATEGORY_PROMO);
assertNotNull(Notification.CATEGORY_RECOMMENDATION);
assertNotNull(Notification.CATEGORY_REMINDER);
assertNotNull(Notification.CATEGORY_SERVICE);
assertNotNull(Notification.CATEGORY_SOCIAL);
assertNotNull(Notification.CATEGORY_STATUS);
assertNotNull(Notification.CATEGORY_SYSTEM);
assertNotNull(Notification.CATEGORY_TRANSPORT);
assertNotNull(Notification.CATEGORY_WORKOUT);
assertNotNull(Notification.CATEGORY_LOCATION_SHARING);
assertNotNull(Notification.CATEGORY_STOPWATCH);
assertNotNull(Notification.CATEGORY_MISSED_CALL);
}
public void testWriteToParcel() {
Notification.BubbleMetadata bubble = makeBubbleMetadata();
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setBadgeIconType(Notification.BADGE_ICON_SMALL)
.setShortcutId(SHORTCUT_ID)
.setTimeoutAfter(TIMEOUT)
.setSettingsText(SETTING_TEXT)
.setGroupAlertBehavior(Notification.GROUP_ALERT_CHILDREN)
.setBubbleMetadata(bubble)
.setAllowSystemGeneratedContextualActions(ALLOW_SYS_GEN_CONTEXTUAL_ACTIONS)
.build();
mNotification.icon = 0;
mNotification.number = 1;
final Intent intent = new Intent();
final PendingIntent pendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
mNotification.contentIntent = pendingIntent;
final Intent deleteIntent = new Intent();
final PendingIntent delPendingIntent = PendingIntent.getBroadcast(
mContext, 0, deleteIntent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
mNotification.deleteIntent = delPendingIntent;
mNotification.tickerText = TICKER_TEXT;
final RemoteViews contentView = new RemoteViews(mContext.getPackageName(),
android.R.layout.simple_list_item_1);
mNotification.contentView = contentView;
mNotification.defaults = 0;
mNotification.flags = 0;
final Uri uri = Uri.parse(URI_STRING);
mNotification.sound = uri;
mNotification.audioStreamType = 0;
final long[] longArray = { 1l, 2l, 3l };
mNotification.vibrate = longArray;
mNotification.ledARGB = 0;
mNotification.ledOnMS = 0;
mNotification.ledOffMS = 0;
mNotification.iconLevel = 0;
Parcel parcel = Parcel.obtain();
mNotification.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
// Test Notification(Parcel)
Notification result = new Notification(parcel);
assertEquals(mNotification.icon, result.icon);
assertEquals(mNotification.when, result.when);
assertEquals(mNotification.number, result.number);
assertNotNull(result.contentIntent);
assertNotNull(result.deleteIntent);
assertEquals(mNotification.tickerText, result.tickerText);
assertNotNull(result.contentView);
assertEquals(mNotification.defaults, result.defaults);
assertEquals(mNotification.flags, result.flags);
assertNotNull(result.sound);
assertEquals(mNotification.audioStreamType, result.audioStreamType);
assertEquals(mNotification.vibrate[0], result.vibrate[0]);
assertEquals(mNotification.vibrate[1], result.vibrate[1]);
assertEquals(mNotification.vibrate[2], result.vibrate[2]);
assertEquals(mNotification.ledARGB, result.ledARGB);
assertEquals(mNotification.ledOnMS, result.ledOnMS);
assertEquals(mNotification.ledOffMS, result.ledOffMS);
assertEquals(mNotification.iconLevel, result.iconLevel);
assertEquals(mNotification.getShortcutId(), result.getShortcutId());
assertEquals(mNotification.getBadgeIconType(), result.getBadgeIconType());
assertEquals(mNotification.getTimeoutAfter(), result.getTimeoutAfter());
assertEquals(mNotification.getChannelId(), result.getChannelId());
assertEquals(mNotification.getSettingsText(), result.getSettingsText());
assertEquals(mNotification.getGroupAlertBehavior(), result.getGroupAlertBehavior());
assertNotNull(result.getBubbleMetadata());
assertEquals(mNotification.getAllowSystemGeneratedContextualActions(),
result.getAllowSystemGeneratedContextualActions());
mNotification.contentIntent = null;
parcel = Parcel.obtain();
mNotification.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
result = new Notification(parcel);
assertNull(result.contentIntent);
mNotification.deleteIntent = null;
parcel = Parcel.obtain();
mNotification.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
result = new Notification(parcel);
assertNull(result.deleteIntent);
mNotification.tickerText = null;
parcel = Parcel.obtain();
mNotification.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
result = new Notification(parcel);
assertNull(result.tickerText);
mNotification.contentView = null;
parcel = Parcel.obtain();
mNotification.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
result = new Notification(parcel);
assertNull(result.contentView);
mNotification.sound = null;
parcel = Parcel.obtain();
mNotification.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
result = new Notification(parcel);
assertNull(result.sound);
}
public void testColorizeNotification() {
mNotification = new Notification.Builder(mContext, "channel_id")
.setSmallIcon(1)
.setContentTitle(CONTENT_TITLE)
.setColorized(true).setColor(Color.WHITE)
.build();
assertTrue(mNotification.extras.getBoolean(Notification.EXTRA_COLORIZED));
}
public void testBuilder() {
final Intent intent = new Intent();
final PendingIntent contentIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
Notification.BubbleMetadata bubble = makeBubbleMetadata();
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setSmallIcon(1)
.setContentTitle(CONTENT_TITLE)
.setContentText(CONTENT_TEXT)
.setContentIntent(contentIntent)
.setBadgeIconType(Notification.BADGE_ICON_SMALL)
.setShortcutId(SHORTCUT_ID)
.setTimeoutAfter(TIMEOUT)
.setSettingsText(SETTING_TEXT)
.setGroupAlertBehavior(Notification.GROUP_ALERT_SUMMARY)
.setBubbleMetadata(bubble)
.setAllowSystemGeneratedContextualActions(ALLOW_SYS_GEN_CONTEXTUAL_ACTIONS)
.build();
assertEquals(CONTENT_TEXT, mNotification.extras.getString(Notification.EXTRA_TEXT));
assertEquals(CONTENT_TITLE, mNotification.extras.getString(Notification.EXTRA_TITLE));
assertEquals(1, mNotification.icon);
assertEquals(contentIntent, mNotification.contentIntent);
assertEquals(CHANNEL.getId(), mNotification.getChannelId());
assertEquals(Notification.BADGE_ICON_SMALL, mNotification.getBadgeIconType());
assertEquals(SHORTCUT_ID, mNotification.getShortcutId());
assertEquals(TIMEOUT, mNotification.getTimeoutAfter());
assertEquals(SETTING_TEXT, mNotification.getSettingsText());
assertEquals(Notification.GROUP_ALERT_SUMMARY, mNotification.getGroupAlertBehavior());
assertEquals(bubble, mNotification.getBubbleMetadata());
assertEquals(ALLOW_SYS_GEN_CONTEXTUAL_ACTIONS,
mNotification.getAllowSystemGeneratedContextualActions());
}
public void testBuilder_getStyle() {
MessagingStyle ms = new MessagingStyle(new Person.Builder().setName("Test name").build());
Notification.Builder builder = new Notification.Builder(mContext, CHANNEL.getId());
builder.setStyle(ms);
assertEquals(ms, builder.getStyle());
}
public void testActionBuilder() {
final Intent intent = new Intent();
final PendingIntent actionIntent = PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_MUTABLE_UNAUDITED);
mAction = null;
mAction = new Notification.Action.Builder(0, ACTION_TITLE, actionIntent)
.setAuthenticationRequired(true)
.build();
assertEquals(ACTION_TITLE, mAction.title);
assertEquals(actionIntent, mAction.actionIntent);
assertEquals(true, mAction.getAllowGeneratedReplies());
assertTrue(mAction.isAuthenticationRequired());
}
public void testNotification_addPerson() {
String name = "name";
String key = "key";
String uri = "name:name";
Person person = new Person.Builder()
.setName(name)
.setIcon(Icon.createWithResource(mContext, 1))
.setKey(key)
.setUri(uri)
.build();
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setSmallIcon(1)
.setContentTitle(CONTENT_TITLE)
.addPerson(person)
.build();
ArrayList<Person> restoredPeople = mNotification.extras.getParcelableArrayList(
Notification.EXTRA_PEOPLE_LIST);
assertNotNull(restoredPeople);
Person restoredPerson = restoredPeople.get(0);
assertNotNull(restoredPerson);
assertNotNull(restoredPerson.getIcon());
assertEquals(name, restoredPerson.getName());
assertEquals(key, restoredPerson.getKey());
assertEquals(uri, restoredPerson.getUri());
}
public void testNotification_MessagingStyle_people() {
String name = "name";
String key = "key";
String uri = "name:name";
Person user = new Person.Builder()
.setName(name)
.setIcon(Icon.createWithResource(mContext, 1))
.setKey(key)
.setUri(uri)
.build();
Person participant = new Person.Builder().setName("sender").build();
Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle(user)
.addMessage("text", 0, participant)
.addMessage(new Message("text 2", 0, participant));
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setSmallIcon(1)
.setStyle(messagingStyle)
.build();
Person restoredPerson = mNotification.extras.getParcelable(
Notification.EXTRA_MESSAGING_PERSON);
assertNotNull(restoredPerson);
assertNotNull(restoredPerson.getIcon());
assertEquals(name, restoredPerson.getName());
assertEquals(key, restoredPerson.getKey());
assertEquals(uri, restoredPerson.getUri());
assertNotNull(mNotification.extras.getParcelableArray(Notification.EXTRA_MESSAGES));
}
public void testMessagingStyle_historicMessages() {
Message referenceMessage = new Message("historic text", 0, "historic sender");
Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
.addMessage("text", 0, "sender")
.addMessage(new Message("image", 0, "sender")
.setData("image/png", Uri.parse("http://example.com/image.png")))
.addHistoricMessage(referenceMessage)
.setConversationTitle("title");
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setSmallIcon(1)
.setContentTitle(CONTENT_TITLE)
.setStyle(messagingStyle)
.build();
List<Message> historicMessages = messagingStyle.getHistoricMessages();
assertNotNull(historicMessages);
assertEquals(1, historicMessages.size());
Message message = historicMessages.get(0);
assertEquals(referenceMessage, message);
assertNotNull(
mNotification.extras.getParcelableArray(Notification.EXTRA_HISTORIC_MESSAGES));
}
public void testMessagingStyle_isGroupConversation() {
mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
.setGroupConversation(true)
.setConversationTitle("test conversation title");
Notification notification = new Notification.Builder(mContext, "test id")
.setSmallIcon(1)
.setContentTitle("test title")
.setStyle(messagingStyle)
.build();
assertTrue(messagingStyle.isGroupConversation());
assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
}
public void testMessagingStyle_isGroupConversation_noConversationTitle() {
mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
.setGroupConversation(true)
.setConversationTitle(null);
Notification notification = new Notification.Builder(mContext, "test id")
.setSmallIcon(1)
.setContentTitle("test title")
.setStyle(messagingStyle)
.build();
assertTrue(messagingStyle.isGroupConversation());
assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
}
public void testMessagingStyle_isGroupConversation_withConversationTitle_legacy() {
// In legacy (version < P), isGroupConversation is controlled by conversationTitle.
mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O;
Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
.setGroupConversation(false)
.setConversationTitle("test conversation title");
Notification notification = new Notification.Builder(mContext, "test id")
.setSmallIcon(1)
.setContentTitle("test title")
.setStyle(messagingStyle)
.build();
assertTrue(messagingStyle.isGroupConversation());
assertFalse(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
}
public void testMessagingStyle_isGroupConversation_withoutConversationTitle_legacy() {
// In legacy (version < P), isGroupConversation is controlled by conversationTitle.
mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O;
Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
.setGroupConversation(true)
.setConversationTitle(null);
Notification notification = new Notification.Builder(mContext, "test id")
.setSmallIcon(1)
.setContentTitle("test title")
.setStyle(messagingStyle)
.build();
assertFalse(messagingStyle.isGroupConversation());
assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
}
public void testMessagingStyle_getUser() {
Person user = new Person.Builder().setName("Test name").build();
MessagingStyle messagingStyle = new MessagingStyle(user);
assertEquals(user, messagingStyle.getUser());
}
public void testMessagingStyle_getConversationTitle() {
final String title = "test conversation title";
Person user = new Person.Builder().setName("Test name").build();
MessagingStyle messagingStyle = new MessagingStyle(user).setConversationTitle(title);
Notification notification = new Notification.Builder(mContext, CHANNEL.getId())
.setSmallIcon(1)
.setContentTitle(CONTENT_TITLE)
.setStyle(messagingStyle)
.build();
assertEquals(title, messagingStyle.getConversationTitle());
assertEquals(title, notification.extras.getString(Notification.EXTRA_CONVERSATION_TITLE));
}
public void testMessage() {
String senderName = "Test name";
Person sender = new Person.Builder().setName(senderName).build();
String text = "Test message";
long timestamp = 400;
Message message = new Message(text, timestamp, sender);
assertEquals(text, message.getText());
assertEquals(timestamp, message.getTimestamp());
assertEquals(sender, message.getSenderPerson());
assertEquals(senderName, message.getSender());
}
public void testMessageData() {
Person sender = new Person.Builder().setName("Test name").build();
String text = "Test message";
long timestamp = 400;
Message message = new Message(text, timestamp, sender);
String mimeType = "image/png";
Uri uri = Uri.parse("http://example.com/image.png");
message.setData(mimeType, uri);
assertEquals(mimeType, message.getDataMimeType());
assertEquals(uri, message.getDataUri());
}
public void testToString() {
mNotification = new Notification();
assertNotNull(mNotification.toString());
mNotification = null;
}
public void testNotificationActionBuilder_setDataOnlyRemoteInput() throws Throwable {
Notification.Action a = newActionBuilder()
.addRemoteInput(newDataOnlyRemoteInput()).build();
RemoteInput[] textInputs = a.getRemoteInputs();
assertTrue(textInputs == null || textInputs.length == 0);
verifyRemoteInputArrayHasSingleResult(a.getDataOnlyRemoteInputs(), DATA_RESULT_KEY);
}
public void testNotificationActionBuilder_setTextAndDataOnlyRemoteInput() throws Throwable {
Notification.Action a = newActionBuilder()
.addRemoteInput(newDataOnlyRemoteInput())
.addRemoteInput(newTextRemoteInput())
.build();
verifyRemoteInputArrayHasSingleResult(a.getRemoteInputs(), TEXT_RESULT_KEY);
verifyRemoteInputArrayHasSingleResult(a.getDataOnlyRemoteInputs(), DATA_RESULT_KEY);
}
public void testNotificationActionBuilder_setTextAndDataOnlyAndBothRemoteInput()
throws Throwable {
Notification.Action a = newActionBuilder()
.addRemoteInput(newDataOnlyRemoteInput())
.addRemoteInput(newTextRemoteInput())
.addRemoteInput(newTextAndDataRemoteInput())
.build();
assertTrue(a.getRemoteInputs() != null && a.getRemoteInputs().length == 2);
assertEquals(TEXT_RESULT_KEY, a.getRemoteInputs()[0].getResultKey());
assertFalse(a.getRemoteInputs()[0].isDataOnly());
assertEquals(DATA_AND_TEXT_RESULT_KEY, a.getRemoteInputs()[1].getResultKey());
assertFalse(a.getRemoteInputs()[1].isDataOnly());
verifyRemoteInputArrayHasSingleResult(a.getDataOnlyRemoteInputs(), DATA_RESULT_KEY);
assertTrue(a.getDataOnlyRemoteInputs()[0].isDataOnly());
}
public void testAction_builder_hasDefault() {
Notification.Action action = makeNotificationAction(null);
assertEquals(Notification.Action.SEMANTIC_ACTION_NONE, action.getSemanticAction());
}
public void testAction_builder_setSemanticAction() {
Notification.Action action = makeNotificationAction(
builder -> builder.setSemanticAction(Notification.Action.SEMANTIC_ACTION_REPLY));
assertEquals(Notification.Action.SEMANTIC_ACTION_REPLY, action.getSemanticAction());
}
public void testAction_builder_contextualAction_nullIcon() {
PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED);
Notification.Action.Builder builder =
new Notification.Action.Builder(null /* icon */, "title", pendingIntent)
.setContextual(true);
try {
builder.build();
fail("Creating a semantic Action with a null icon should cause a NullPointerException");
} catch (NullPointerException e) {
// Expected
}
}
public void testAction_builder_contextualAction_nullIntent() {
Notification.Action.Builder builder =
new Notification.Action.Builder(0 /* icon */, "title", null /* intent */)
.setContextual(true);
try {
builder.build();
fail("Creating a semantic Action with a null PendingIntent should cause a "
+ "NullPointerException");
} catch (NullPointerException e) {
// Expected
}
}
public void testAction_parcel() {
Notification.Action action = writeAndReadParcelable(
makeNotificationAction(builder -> {
builder.setSemanticAction(Notification.Action.SEMANTIC_ACTION_ARCHIVE);
builder.setAllowGeneratedReplies(true);
}));
assertEquals(Notification.Action.SEMANTIC_ACTION_ARCHIVE, action.getSemanticAction());
assertTrue(action.getAllowGeneratedReplies());
}
public void testAction_clone() {
Notification.Action action = makeNotificationAction(
builder -> builder.setSemanticAction(Notification.Action.SEMANTIC_ACTION_DELETE));
assertEquals(
Notification.Action.SEMANTIC_ACTION_DELETE,
action.clone().getSemanticAction());
}
public void testBuildStrictMode() {
try {
StrictMode.setThreadPolicy(
new StrictMode.ThreadPolicy.Builder().detectAll().penaltyDeath().build());
Notification.Action a = newActionBuilder()
.addRemoteInput(newDataOnlyRemoteInput())
.addRemoteInput(newTextRemoteInput())
.addRemoteInput(newTextAndDataRemoteInput())
.build();
Notification.Builder b = new Notification.Builder(mContext, "id")
.setStyle(new Notification.BigTextStyle().setBigContentTitle("Big content"))
.setContentTitle("title")
.setActions(a);
b.build();
} finally {
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().permitAll().build());
}
}
public void testGetAllowSystemGeneratedContextualActions_trueByDefault() {
Notification notification = new Notification.Builder(mContext, CHANNEL.getId()).build();
assertTrue(notification.getAllowSystemGeneratedContextualActions());
}
public void testGetAllowSystemGeneratedContextualActions() {
Notification notification = new Notification.Builder(mContext, CHANNEL.getId())
.setAllowSystemGeneratedContextualActions(false)
.build();
assertFalse(notification.getAllowSystemGeneratedContextualActions());
}
public void testBubbleMetadataBuilder() {
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_MUTABLE);
PendingIntent deleteIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_IMMUTABLE);
Icon icon = Icon.createWithResource(mContext, 1);
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder(bubbleIntent, icon)
.setDesiredHeight(BUBBLE_HEIGHT)
.setSuppressableBubble(false)
.setDeleteIntent(deleteIntent);
Notification.BubbleMetadata data = metadataBuilder.build();
assertEquals(BUBBLE_HEIGHT, data.getDesiredHeight());
assertEquals(icon, data.getIcon());
assertEquals(bubbleIntent, data.getIntent());
assertEquals(deleteIntent, data.getDeleteIntent());
assertFalse(data.isNotificationSuppressed());
assertFalse(data.isBubbleSuppressable());
assertFalse(data.getAutoExpandBubble());
}
public void testBubbleMetadata_parcel() {
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_MUTABLE);
PendingIntent deleteIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_IMMUTABLE);
Icon icon = Icon.createWithResource(mContext, 1);
Notification.BubbleMetadata metadata =
new Notification.BubbleMetadata.Builder(bubbleIntent, icon)
.setDesiredHeight(BUBBLE_HEIGHT)
.setAutoExpandBubble(true)
.setSuppressNotification(true)
.setSuppressableBubble(true)
.setDeleteIntent(deleteIntent)
.build();
writeAndReadParcelable(metadata);
assertEquals(BUBBLE_HEIGHT, metadata.getDesiredHeight());
assertEquals(icon, metadata.getIcon());
assertEquals(bubbleIntent, metadata.getIntent());
assertEquals(deleteIntent, metadata.getDeleteIntent());
assertTrue(metadata.getAutoExpandBubble());
assertTrue(metadata.isNotificationSuppressed());
assertTrue(metadata.isBubbleSuppressable());
}
public void testBubbleMetadataBuilder_shortcutId() {
PendingIntent deleteIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_IMMUTABLE);
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder(BUBBLE_SHORTCUT_ID)
.setDesiredHeight(BUBBLE_HEIGHT)
.setSuppressableBubble(true)
.setDeleteIntent(deleteIntent);
Notification.BubbleMetadata data = metadataBuilder.build();
assertEquals(BUBBLE_HEIGHT, data.getDesiredHeight());
assertEquals(BUBBLE_SHORTCUT_ID, data.getShortcutId());
assertEquals(deleteIntent, data.getDeleteIntent());
assertTrue(data.isBubbleSuppressable());
assertFalse(data.isNotificationSuppressed());
assertFalse(data.getAutoExpandBubble());
}
public void testBubbleMetadataBuilder_parcelShortcutId() {
PendingIntent deleteIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_IMMUTABLE);
Notification.BubbleMetadata metadata =
new Notification.BubbleMetadata.Builder(BUBBLE_SHORTCUT_ID)
.setDesiredHeight(BUBBLE_HEIGHT)
.setAutoExpandBubble(true)
.setSuppressableBubble(true)
.setSuppressNotification(true)
.setDeleteIntent(deleteIntent)
.build();
writeAndReadParcelable(metadata);
assertEquals(BUBBLE_HEIGHT, metadata.getDesiredHeight());
assertEquals(deleteIntent, metadata.getDeleteIntent());
assertEquals(BUBBLE_SHORTCUT_ID, metadata.getShortcutId());
assertTrue(metadata.isBubbleSuppressable());
assertTrue(metadata.getAutoExpandBubble());
assertTrue(metadata.isNotificationSuppressed());
}
public void testBubbleMetadata_parcelResId() {
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_IMMUTABLE);
Icon icon = Icon.createWithResource(mContext, 1);
Notification.BubbleMetadata metadata =
new Notification.BubbleMetadata.Builder(bubbleIntent, icon)
.setDesiredHeightResId(BUBBLE_HEIGHT_RESID)
.build();
writeAndReadParcelable(metadata);
assertEquals(BUBBLE_HEIGHT_RESID, metadata.getDesiredHeightResId());
assertEquals(icon, metadata.getIcon());
assertEquals(bubbleIntent, metadata.getIntent());
assertFalse(metadata.getAutoExpandBubble());
assertFalse(metadata.isBubbleSuppressable());
assertFalse(metadata.isNotificationSuppressed());
}
public void testBubbleMetadataBuilder_throwForNoIntentNoShortcut() {
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder();
try {
metadataBuilder.build();
fail("Should have thrown exception, no pending intent or shortcutId");
} catch (NullPointerException e) {
// expected
}
}
public void testBubbleMetadataBuilder_noThrowWithShortcut() {
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder(BUBBLE_SHORTCUT_ID)
.setDesiredHeight(BUBBLE_HEIGHT);
Notification.BubbleMetadata metadata = metadataBuilder.build();
assertNotNull(metadata.getShortcutId());
assertNull(metadata.getIcon());
assertNull(metadata.getIntent());
}
public void testBubbleMetadataBuilder_shortcutBuilder_throwsForSetIntent() {
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_MUTABLE);
try {
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder(BUBBLE_SHORTCUT_ID)
.setDesiredHeightResId(BUBBLE_HEIGHT_RESID)
.setIntent(bubbleIntent);
fail("Should have thrown exception, can't set intent on shortcut builder");
} catch (Exception e) {
// expected
}
}
public void testBubbleMetadataBuilder_shortcutBuilder_throwsForSetIcon() {
try {
Icon icon = Icon.createWithResource(mContext, 1);
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder(BUBBLE_SHORTCUT_ID)
.setDesiredHeightResId(BUBBLE_HEIGHT_RESID)
.setIcon(icon);
fail("Should have thrown exception, can't set icon on shortcut builder");
} catch (Exception e) {
// expected
}
}
public void testBubbleMetadataBuilder_notifBubbleShortcutIds_match_noThrow() {
Notification.BubbleMetadata metadata =
new Notification.BubbleMetadata.Builder(BUBBLE_SHORTCUT_ID).build();
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setSmallIcon(1)
.setContentTitle(CONTENT_TITLE)
.setShortcutId(BUBBLE_SHORTCUT_ID)
.setBubbleMetadata(metadata)
.build();
assertEquals(mNotification.getShortcutId(), BUBBLE_SHORTCUT_ID);
assertEquals(mNotification.getBubbleMetadata().getShortcutId(),
mNotification.getShortcutId());
}
public void testBubbleMetadataBuilder_notifBubbleShortcutIds_different_throw() {
Notification.BubbleMetadata metadata =
new Notification.BubbleMetadata.Builder(BUBBLE_SHORTCUT_ID).build();
Notification.Builder nb = new Notification.Builder(mContext, CHANNEL.getId())
.setSmallIcon(1)
.setContentTitle(CONTENT_TITLE)
.setShortcutId("a different shortcut id")
.setBubbleMetadata(metadata);
try {
nb.build();
fail("Should have thrown IllegalArgumentException, "
+ "notif & bubble shortcutIds mismatch");
} catch (IllegalArgumentException e) {
// expected
}
}
public void testBubbleMetadataBuilder_noThrowForAdaptiveBitmapIcon() {
Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
new Canvas(b).drawColor(0xffff0000);
Icon icon = Icon.createWithAdaptiveBitmap(b);
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_MUTABLE);
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder(bubbleIntent, icon);
Notification.BubbleMetadata metadata = metadataBuilder.build();
assertNotNull(metadata.getIcon());
assertEquals(TYPE_ADAPTIVE_BITMAP, metadata.getIcon().getType());
}
public void testBubbleMetadataBuilder_noThrowForNonBitmapIcon() {
Icon icon = Icon.createWithResource(mContext, R.drawable.ic_android);
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_MUTABLE);
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder(bubbleIntent, icon);
Notification.BubbleMetadata metadata = metadataBuilder.build();
assertNotNull(metadata.getIcon());
assertEquals(TYPE_RESOURCE, metadata.getIcon().getType());
}
public void testBubbleMetadataBuilder_replaceHeightRes() {
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_MUTABLE);
PendingIntent deleteIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_IMMUTABLE);
Icon icon = Icon.createWithResource(mContext, 1);
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder(bubbleIntent, icon)
.setDesiredHeight(BUBBLE_HEIGHT)
.setDesiredHeightResId(BUBBLE_HEIGHT_RESID)
.setDeleteIntent(deleteIntent);
Notification.BubbleMetadata data = metadataBuilder.build();
// Desired height should be cleared
assertEquals(0, data.getDesiredHeight());
// Res id should be used
assertEquals(BUBBLE_HEIGHT_RESID, data.getDesiredHeightResId());
}
public void testBubbleMetadataBuilder_replaceHeightDp() {
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_MUTABLE);
PendingIntent deleteIntent = PendingIntent.getActivity(mContext, 0, new Intent(),
PendingIntent.FLAG_IMMUTABLE);
Icon icon = Icon.createWithResource(mContext, 1);
Notification.BubbleMetadata.Builder metadataBuilder =
new Notification.BubbleMetadata.Builder(bubbleIntent, icon)
.setDesiredHeightResId(BUBBLE_HEIGHT_RESID)
.setDesiredHeight(BUBBLE_HEIGHT)
.setDeleteIntent(deleteIntent);
Notification.BubbleMetadata data = metadataBuilder.build();
// Desired height should be used
assertEquals(BUBBLE_HEIGHT, data.getDesiredHeight());
// Res id should be cleared
assertEquals(0, data.getDesiredHeightResId());
}
public void testFlagBubble() {
Notification n = new Notification();
assertFalse((n.flags & FLAG_BUBBLE) != 0);
n.flags |= FLAG_BUBBLE;
assertTrue((n.flags & FLAG_BUBBLE) != 0);
}
public void testGetMessagesFromBundleArray() {
Person sender = new Person.Builder().setName("Sender").build();
Notification.MessagingStyle.Message firstExpectedMessage =
new Notification.MessagingStyle.Message("hello", /* timestamp= */ 123, sender);
Notification.MessagingStyle.Message secondExpectedMessage =
new Notification.MessagingStyle.Message("hello2", /* timestamp= */ 456, sender);
Notification.MessagingStyle messagingStyle =
new Notification.MessagingStyle("self name")
.addMessage(firstExpectedMessage)
.addMessage(secondExpectedMessage);
Notification notification = new Notification.Builder(mContext, "test id")
.setSmallIcon(1)
.setContentTitle("test title")
.setStyle(messagingStyle)
.build();
List<Notification.MessagingStyle.Message> actualMessages =
Notification.MessagingStyle.Message.getMessagesFromBundleArray(
notification.extras.getParcelableArray(Notification.EXTRA_MESSAGES));
assertEquals(2, actualMessages.size());
assertMessageEquals(firstExpectedMessage, actualMessages.get(0));
assertMessageEquals(secondExpectedMessage, actualMessages.get(1));
}
public void testNotification_isBigPictureStyle_pictureContentDescriptionSet() {
final String contentDescription = "content description";
final Notification.BigPictureStyle bigPictureStyle = new Notification.BigPictureStyle()
.setContentDescription(contentDescription);
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setStyle(bigPictureStyle)
.build();
final CharSequence notificationContentDescription =
mNotification.extras.getCharSequence(
Notification.EXTRA_PICTURE_CONTENT_DESCRIPTION);
assertEquals(contentDescription, notificationContentDescription);
}
public void testHasImage_messagingStyle() {
Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
.addMessage(new Message("image", 0, "sender")
.setData("image/png", Uri.parse("http://example.com/image.png")));
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setStyle(messagingStyle)
.build();
assertTrue(mNotification.hasImage());
}
public void testHasImage_largeIcon() {
Bitmap b = Bitmap.createBitmap(50, 25, Bitmap.Config.ARGB_8888);
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setLargeIcon(b)
.build();
assertTrue(mNotification.hasImage());
}
public void testHasImage_backgroundImage() {
final Uri backgroundImage = Uri.parse("content://com.example/background");
Bundle extras = new Bundle();
extras.putString(Notification.EXTRA_BACKGROUND_IMAGE_URI, backgroundImage.toString());
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.addExtras(extras)
.build();
assertTrue(mNotification.hasImage());
}
public void testHasImage_smallIcon() {
mNotification = new Notification.Builder(mContext, CHANNEL.getId())
.setSmallIcon(1)
.build();
assertFalse(mNotification.hasImage());
}
private static void assertMessageEquals(
Notification.MessagingStyle.Message expected,
Notification.MessagingStyle.Message actual) {
assertEquals(expected.getText(), actual.getText());
assertEquals(expected.getTimestamp(), actual.getTimestamp());
assertEquals(expected.getSenderPerson(), actual.getSenderPerson());
}
private static RemoteInput newDataOnlyRemoteInput() {
return new RemoteInput.Builder(DATA_RESULT_KEY)
.setAllowFreeFormInput(false)
.setAllowDataType("mimeType", true)
.build();
}
private static RemoteInput newTextAndDataRemoteInput() {
return new RemoteInput.Builder(DATA_AND_TEXT_RESULT_KEY)
.setAllowDataType("mimeType", true)
.build(); // allowFreeForm defaults to true
}
private static RemoteInput newTextRemoteInput() {
return new RemoteInput.Builder(TEXT_RESULT_KEY).build(); // allowFreeForm defaults to true
}
private static void verifyRemoteInputArrayHasSingleResult(
RemoteInput[] remoteInputs, String expectedResultKey) {
assertTrue(remoteInputs != null && remoteInputs.length == 1);
assertEquals(expectedResultKey, remoteInputs[0].getResultKey());
}
private static Notification.Action.Builder newActionBuilder() {
return new Notification.Action.Builder(0, "title", null);
}
/**
* Writes an arbitrary {@link Parcelable} into a {@link Parcel} using its writeToParcel
* method before reading it out again to check that it was sent properly.
*/
private static <T extends Parcelable> T writeAndReadParcelable(T original) {
Parcel p = Parcel.obtain();
p.writeParcelable(original, /* flags */ 0);
p.setDataPosition(0);
return p.readParcelable(/* classLoader */ null);
}
/**
* Creates a Notification.Action by mocking initial dependencies and then applying
* transformations if they're defined.
*/
private Notification.Action makeNotificationAction(
@Nullable Consumer<Builder> transformation) {
Notification.Action.Builder actionBuilder =
new Notification.Action.Builder(null, "Test Title", null);
if (transformation != null) {
transformation.accept(actionBuilder);
}
return actionBuilder.build();
}
private Notification.BubbleMetadata makeBubbleMetadata() {
PendingIntent bubbleIntent = PendingIntent.getActivity(mContext, 0, new Intent(), PendingIntent.FLAG_MUTABLE_UNAUDITED);
return new Notification.BubbleMetadata.Builder(bubbleIntent,
Icon.createWithResource(mContext, 1))
.setDesiredHeight(BUBBLE_HEIGHT)
.build();
}
}