blob: b51c677e74ff8fad5cc70af3c68fc1fc20bf93fb [file] [log] [blame]
Selim Cinek389edcd2017-05-11 19:16:44 -07001/*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License
15 */
16
17package android.app;
18
19import static com.android.internal.util.NotificationColorUtil.satisfiesTextContrast;
20
Julia Reynoldsd71c5a92017-06-30 13:34:01 -040021import static org.junit.Assert.assertFalse;
Robin Leead7e72a2017-12-04 15:45:46 +010022import static org.junit.Assert.assertNotSame;
23import static org.junit.Assert.assertSame;
Selim Cinek389edcd2017-05-11 19:16:44 -070024import static org.junit.Assert.assertTrue;
25
26import android.content.Context;
Adrian Roosfb921842017-10-26 14:49:56 +020027import android.content.Intent;
Robin Leead7e72a2017-12-04 15:45:46 +010028import android.graphics.BitmapFactory;
29import android.graphics.drawable.Icon;
Selim Cinek389edcd2017-05-11 19:16:44 -070030import android.media.session.MediaSession;
Kodlee Yin14656422017-12-22 17:00:46 -080031import android.os.Build;
Adrian Roosfb921842017-10-26 14:49:56 +020032import android.os.Parcel;
Robin Leead7e72a2017-12-04 15:45:46 +010033import android.os.Parcelable;
Selim Cinek389edcd2017-05-11 19:16:44 -070034import android.support.test.InstrumentationRegistry;
35import android.support.test.filters.SmallTest;
36import android.support.test.runner.AndroidJUnit4;
Adrian Roosfb921842017-10-26 14:49:56 +020037import android.widget.RemoteViews;
Selim Cinek389edcd2017-05-11 19:16:44 -070038
Selim Cinek389edcd2017-05-11 19:16:44 -070039import org.junit.Before;
40import org.junit.Test;
41import org.junit.runner.RunWith;
42
43@RunWith(AndroidJUnit4.class)
44@SmallTest
45public class NotificationTest {
46
47 private Context mContext;
48
49 @Before
50 public void setUp() {
51 mContext = InstrumentationRegistry.getContext();
52 }
53
54 @Test
Julia Reynoldsd71c5a92017-06-30 13:34:01 -040055 public void testColorizedByPermission() {
56 Notification n = new Notification.Builder(mContext, "test")
57 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
58 .setColorized(true)
59 .build();
60 assertTrue(n.isColorized());
61
62 n = new Notification.Builder(mContext, "test")
63 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
64 .build();
65 assertFalse(n.isColorized());
66
67 n = new Notification.Builder(mContext, "test")
68 .setFlag(Notification.FLAG_CAN_COLORIZE, false)
69 .setColorized(true)
70 .build();
71 assertFalse(n.isColorized());
72 }
73
74 @Test
75 public void testColorizedByForeground() {
76 Notification n = new Notification.Builder(mContext, "test")
77 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
78 .setColorized(true)
79 .build();
80 assertTrue(n.isColorized());
81
82 n = new Notification.Builder(mContext, "test")
83 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, true)
84 .build();
85 assertFalse(n.isColorized());
86
87 n = new Notification.Builder(mContext, "test")
88 .setFlag(Notification.FLAG_FOREGROUND_SERVICE, false)
89 .setColorized(true)
90 .build();
91 assertFalse(n.isColorized());
92 }
93
94 @Test
Selim Cinek389edcd2017-05-11 19:16:44 -070095 public void testColorSatisfiedWhenBgDarkTextDarker() {
96 Notification.Builder builder = getMediaNotification();
Julia Reynoldsd71c5a92017-06-30 13:34:01 -040097 Notification n = builder.build();
98
99 assertTrue(n.isColorized());
Selim Cinek389edcd2017-05-11 19:16:44 -0700100
101 // An initial guess where the foreground color is actually darker than an already dark bg
102 int backgroundColor = 0xff585868;
103 int initialForegroundColor = 0xff505868;
104 builder.setColorPalette(backgroundColor, initialForegroundColor);
105 int primaryTextColor = builder.getPrimaryTextColor();
106 assertTrue(satisfiesTextContrast(primaryTextColor, backgroundColor));
107 int secondaryTextColor = builder.getSecondaryTextColor();
108 assertTrue(satisfiesTextContrast(secondaryTextColor, backgroundColor));
109 }
110
Julia Reynolds6ad0aec2017-07-05 08:47:03 -0400111 @Test
112 public void testHasCompletedProgress_noProgress() {
113 Notification n = new Notification.Builder(mContext).build();
114
115 assertFalse(n.hasCompletedProgress());
116 }
117
118 @Test
119 public void testHasCompletedProgress_complete() {
120 Notification n = new Notification.Builder(mContext)
121 .setProgress(100, 100, true)
122 .build();
123 Notification n2 = new Notification.Builder(mContext)
124 .setProgress(10, 10, false)
125 .build();
126 assertTrue(n.hasCompletedProgress());
127 assertTrue(n2.hasCompletedProgress());
128 }
129
130 @Test
131 public void testHasCompletedProgress_notComplete() {
132 Notification n = new Notification.Builder(mContext)
133 .setProgress(100, 99, true)
134 .build();
135 Notification n2 = new Notification.Builder(mContext)
136 .setProgress(10, 4, false)
137 .build();
138 assertFalse(n.hasCompletedProgress());
139 assertFalse(n2.hasCompletedProgress());
140 }
141
142 @Test
143 public void testHasCompletedProgress_zeroMax() {
144 Notification n = new Notification.Builder(mContext)
145 .setProgress(0, 0, true)
146 .build();
147 assertFalse(n.hasCompletedProgress());
148 }
149
Adrian Roosfb921842017-10-26 14:49:56 +0200150 @Test
Robin Leead7e72a2017-12-04 15:45:46 +0100151 public void largeIconMultipleReferences_keptAfterParcelling() {
152 Icon originalIcon = Icon.createWithBitmap(BitmapFactory.decodeResource(
153 mContext.getResources(), com.android.frameworks.coretests.R.drawable.test128x96));
154
155 Notification n = new Notification.Builder(mContext).setLargeIcon(originalIcon).build();
156 assertSame(n.getLargeIcon(), originalIcon);
157
158 Notification q = writeAndReadParcelable(n);
159 assertNotSame(q.getLargeIcon(), n.getLargeIcon());
160
161 assertTrue(q.getLargeIcon().getBitmap().sameAs(n.getLargeIcon().getBitmap()));
162 assertSame(q.getLargeIcon(), q.extras.getParcelable(Notification.EXTRA_LARGE_ICON));
163 }
164
165 @Test
166 public void largeIconReferenceInExtrasOnly_keptAfterParcelling() {
167 Icon originalIcon = Icon.createWithBitmap(BitmapFactory.decodeResource(
168 mContext.getResources(), com.android.frameworks.coretests.R.drawable.test128x96));
169
170 Notification n = new Notification.Builder(mContext).build();
171 n.extras.putParcelable(Notification.EXTRA_LARGE_ICON, originalIcon);
172 assertSame(n.getLargeIcon(), null);
173
174 Notification q = writeAndReadParcelable(n);
175 assertSame(q.getLargeIcon(), null);
176 assertTrue(((Icon) q.extras.getParcelable(Notification.EXTRA_LARGE_ICON)).getBitmap()
177 .sameAs(originalIcon.getBitmap()));
178 }
179
180 @Test
Adrian Roosfb921842017-10-26 14:49:56 +0200181 public void allPendingIntents_recollectedAfterReusingBuilder() {
182 PendingIntent intent1 = PendingIntent.getActivity(mContext, 0, new Intent("test1"), 0);
183 PendingIntent intent2 = PendingIntent.getActivity(mContext, 0, new Intent("test2"), 0);
184
185 Notification.Builder builder = new Notification.Builder(mContext, "channel");
186 builder.setContentIntent(intent1);
187
188 Parcel p = Parcel.obtain();
189
190 Notification n1 = builder.build();
191 n1.writeToParcel(p, 0);
192
193 builder.setContentIntent(intent2);
194 Notification n2 = builder.build();
195 n2.writeToParcel(p, 0);
196
197 assertTrue(n2.allPendingIntents.contains(intent2));
198 }
199
200 @Test
201 public void allPendingIntents_containsCustomRemoteViews() {
202 PendingIntent intent = PendingIntent.getActivity(mContext, 0, new Intent("test"), 0);
203
204 RemoteViews contentView = new RemoteViews(mContext.getPackageName(), 0 /* layoutId */);
205 contentView.setOnClickPendingIntent(1 /* id */, intent);
206
207 Notification.Builder builder = new Notification.Builder(mContext, "channel");
208 builder.setCustomContentView(contentView);
209
210 Parcel p = Parcel.obtain();
211
212 Notification n = builder.build();
213 n.writeToParcel(p, 0);
214
215 assertTrue(n.allPendingIntents.contains(intent));
216 }
217
Kodlee Yin9ac617c2017-12-19 11:20:50 -0800218 @Test
Kodlee Yin14656422017-12-22 17:00:46 -0800219 public void messagingStyle_isGroupConversation() {
220 mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
Kodlee Yin9ac617c2017-12-19 11:20:50 -0800221 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
Kodlee Yin14656422017-12-22 17:00:46 -0800222 .setGroupConversation(true)
223 .setConversationTitle("test conversation title");
Kodlee Yin9ac617c2017-12-19 11:20:50 -0800224 Notification notification = new Notification.Builder(mContext, "test id")
225 .setSmallIcon(1)
226 .setContentTitle("test title")
227 .setStyle(messagingStyle)
228 .build();
229
230 assertTrue(messagingStyle.isGroupConversation());
231 assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
232 }
233
Kodlee Yin14656422017-12-22 17:00:46 -0800234 @Test
235 public void messagingStyle_isGroupConversation_noConversationTitle() {
236 mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.P;
237 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
238 .setGroupConversation(true)
239 .setConversationTitle(null);
240 Notification notification = new Notification.Builder(mContext, "test id")
241 .setSmallIcon(1)
242 .setContentTitle("test title")
243 .setStyle(messagingStyle)
244 .build();
245
246 assertTrue(messagingStyle.isGroupConversation());
247 assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
248 }
249
250 @Test
251 public void messagingStyle_isGroupConversation_withConversationTitle_legacy() {
252 // In legacy (version < P), isGroupConversation is controlled by conversationTitle.
253 mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O;
254 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
255 .setGroupConversation(false)
256 .setConversationTitle("test conversation title");
257 Notification notification = new Notification.Builder(mContext, "test id")
258 .setSmallIcon(1)
259 .setContentTitle("test title")
260 .setStyle(messagingStyle)
261 .build();
262
263 assertTrue(messagingStyle.isGroupConversation());
264 assertFalse(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
265 }
266
267 @Test
268 public void messagingStyle_isGroupConversation_withoutConversationTitle_legacy() {
269 // In legacy (version < P), isGroupConversation is controlled by conversationTitle.
270 mContext.getApplicationInfo().targetSdkVersion = Build.VERSION_CODES.O;
271 Notification.MessagingStyle messagingStyle = new Notification.MessagingStyle("self name")
272 .setGroupConversation(true)
273 .setConversationTitle(null);
274 Notification notification = new Notification.Builder(mContext, "test id")
275 .setSmallIcon(1)
276 .setContentTitle("test title")
277 .setStyle(messagingStyle)
278 .build();
279
280 assertFalse(messagingStyle.isGroupConversation());
281 assertTrue(notification.extras.getBoolean(Notification.EXTRA_IS_GROUP_CONVERSATION));
282 }
283
Selim Cinek389edcd2017-05-11 19:16:44 -0700284 private Notification.Builder getMediaNotification() {
285 MediaSession session = new MediaSession(mContext, "test");
286 return new Notification.Builder(mContext, "color")
287 .setSmallIcon(com.android.internal.R.drawable.emergency_icon)
288 .setContentTitle("Title")
289 .setContentText("Text")
290 .setStyle(new Notification.MediaStyle().setMediaSession(session.getSessionToken()));
291 }
Robin Leead7e72a2017-12-04 15:45:46 +0100292
293 /**
294 * Writes an arbitrary {@link Parcelable} into a {@link Parcel} using its writeToParcel
295 * method before reading it out again to check that it was sent properly.
296 */
297 private static <T extends Parcelable> T writeAndReadParcelable(T original) {
298 Parcel p = Parcel.obtain();
299 p.writeParcelable(original, /* flags */ 0);
300 p.setDataPosition(0);
301 return p.readParcelable(/* classLoader */ null);
302 }
Selim Cinek389edcd2017-05-11 19:16:44 -0700303}