blob: 0d44318e4aaad7669649b9b1b5fb12c52577717a [file] [log] [blame]
Dan Sandler7647f1d2018-11-26 09:56:26 -05001/*
2 * Copyright (C) 2018 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 com.android.server.notification;
18
19import static junit.framework.Assert.assertEquals;
20import static junit.framework.Assert.assertSame;
21
22import static org.hamcrest.Matchers.instanceOf;
23import static org.junit.Assert.assertThat;
24import static org.mockito.Mockito.eq;
25import static org.mockito.Mockito.spy;
26import static org.mockito.Mockito.verify;
27import static org.mockito.Mockito.when;
28
29// this is a lazy way to do in/out/err but we're not particularly interested in the output
30import static java.io.FileDescriptor.err;
31import static java.io.FileDescriptor.in;
32import static java.io.FileDescriptor.out;
33
34import android.app.INotificationManager;
35import android.app.Notification;
36import android.graphics.Bitmap;
37import android.graphics.Canvas;
38import android.graphics.Color;
39import android.graphics.drawable.GradientDrawable;
40import android.graphics.drawable.Icon;
41import android.os.Binder;
42import android.os.Handler;
43import android.os.ResultReceiver;
44import android.os.ShellCallback;
45import android.os.UserHandle;
46import android.test.suitebuilder.annotation.SmallTest;
47import android.testing.AndroidTestingRunner;
48import android.testing.TestableContext;
49import android.testing.TestableLooper;
50import android.testing.TestableLooper.RunWithLooper;
51
52import com.android.server.UiServiceTestCase;
53
54import org.junit.Before;
55import org.junit.Test;
56import org.junit.runner.RunWith;
57import org.mockito.ArgumentCaptor;
58import org.mockito.Mock;
59import org.mockito.MockitoAnnotations;
60
61import java.util.ArrayList;
62import java.util.List;
63
64@SmallTest
65@RunWith(AndroidTestingRunner.class)
66@RunWithLooper
67public class NotificationShellCmdTest extends UiServiceTestCase {
68 private final Binder mBinder = new Binder();
69 private final ShellCallback mCallback = new ShellCallback();
70 private final TestableContext mTestableContext = spy(getContext());
71 @Mock
72 NotificationManagerService mMockService;
73 @Mock
74 INotificationManager mMockBinderService;
75 private TestableLooper mTestableLooper;
76 private ResultReceiver mResultReceiver;
77
78 @Before
79 public void setUp() throws Exception {
80 MockitoAnnotations.initMocks(this);
81
82 mTestableLooper = TestableLooper.get(this);
83 mResultReceiver = new ResultReceiver(new Handler(mTestableLooper.getLooper()));
84
85 when(mMockService.getContext()).thenReturn(mTestableContext);
86 when(mMockService.getBinderService()).thenReturn(mMockBinderService);
87 }
88
89 private Bitmap createTestBitmap() {
90 final Bitmap bits = Bitmap.createBitmap(512, 512, Bitmap.Config.ARGB_8888);
91 final Canvas canvas = new Canvas(bits);
92 final GradientDrawable grad = new GradientDrawable(GradientDrawable.Orientation.TL_BR,
93 new int[]{Color.RED, Color.YELLOW, Color.GREEN,
94 Color.CYAN, Color.BLUE, Color.MAGENTA});
95 grad.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
96 grad.draw(canvas);
97 return bits;
98 }
99
100 private void doCmd(String... args) {
101 new NotificationShellCmd(mMockService)
102 .exec(mBinder, in, out, err, args, mCallback, mResultReceiver);
103 }
104
105 @Test
106 public void testNoArgs() throws Exception {
107 doCmd();
108 }
109
110 @Test
111 public void testHelp() throws Exception {
112 doCmd("--help");
113 }
114
115 Notification captureNotification(String aTag) throws Exception {
116 ArgumentCaptor<Notification> notificationCaptor =
117 ArgumentCaptor.forClass(Notification.class);
118 verify(mMockBinderService).enqueueNotificationWithTag(
Julia Reynolds1c943a22019-11-07 11:37:18 -0500119 eq(getContext().getPackageName()),
120 eq(getContext().getPackageName()),
Dan Sandler7647f1d2018-11-26 09:56:26 -0500121 eq(aTag),
122 eq(NotificationShellCmd.NOTIFICATION_ID),
123 notificationCaptor.capture(),
124 eq(UserHandle.getCallingUserId()));
125 return notificationCaptor.getValue();
126 }
127
128 @Test
129 public void testBasic() throws Exception {
130 final String aTag = "aTag";
131 final String aText = "someText";
132 final String aTitle = "theTitle";
133 doCmd("notify",
134 "--title", aTitle,
135 aTag, aText);
136 final Notification captured = captureNotification(aTag);
137 assertEquals(aText, captured.extras.getString(Notification.EXTRA_TEXT));
138 assertEquals(aTitle, captured.extras.getString(Notification.EXTRA_TITLE));
139 }
140
141 @Test
142 public void testIcon() throws Exception {
143 final String aTag = "aTag";
144 final String aText = "someText";
145 doCmd("notify", "--icon", "@android:drawable/stat_sys_adb", aTag, aText);
146 final Notification captured = captureNotification(aTag);
147 final Icon icon = captured.getSmallIcon();
148 assertEquals("android", icon.getResPackage());
149 assertEquals(com.android.internal.R.drawable.stat_sys_adb, icon.getResId());
150 }
151
152 @Test
153 public void testBigText() throws Exception {
154 final String aTag = "aTag";
155 final String aText = "someText";
156 final String bigText = "someBigText";
157 doCmd("notify",
158 "--style", "bigtext",
159 "--big-text", bigText,
160 aTag, aText);
161 final Notification captured = captureNotification(aTag);
162 assertSame(captured.getNotificationStyle(), Notification.BigTextStyle.class);
163 assertEquals(aText, captured.extras.getString(Notification.EXTRA_TEXT));
164 assertEquals(bigText, captured.extras.getString(Notification.EXTRA_BIG_TEXT));
165 }
166
167 @Test
168 public void testBigPicture() throws Exception {
169 final String aTag = "aTag";
170 final String aText = "someText";
171 final String bigPicture = "@android:drawable/default_wallpaper";
172 doCmd("notify",
173 "--style", "bigpicture",
174 "--picture", bigPicture,
175 aTag, aText);
176 final Notification captured = captureNotification(aTag);
177 assertSame(captured.getNotificationStyle(), Notification.BigPictureStyle.class);
178 final Object pic = captured.extras.get(Notification.EXTRA_PICTURE);
179 assertThat(pic, instanceOf(Bitmap.class));
180 }
181
182 @Test
183 public void testInbox() throws Exception {
184 final int n = 25;
185 final String aTag = "inboxTag";
186 final String aText = "inboxText";
187 ArrayList<String> args = new ArrayList<>();
188 args.add("notify");
189 args.add("--style");
190 args.add("inbox");
191 final int startOfLineArgs = args.size();
192 for (int i = 0; i < n; i++) {
193 args.add("--line");
194 args.add(String.format("Line %02d", i));
195 }
196 args.add(aTag);
197 args.add(aText);
198
199 doCmd(args.toArray(new String[0]));
200 final Notification captured = captureNotification(aTag);
201 assertSame(captured.getNotificationStyle(), Notification.InboxStyle.class);
202 final Notification.Builder builder =
203 Notification.Builder.recoverBuilder(mContext, captured);
204 final ArrayList<CharSequence> lines =
205 ((Notification.InboxStyle) (builder.getStyle())).getLines();
206 for (int i = 0; i < n; i++) {
207 assertEquals(lines.get(i), args.get(1 + 2 * i + startOfLineArgs));
208 }
209 }
210
211 static final String[] PEOPLE = {
212 "Alice",
213 "Bob",
214 "Charlotte"
215 };
216 static final String[] MESSAGES = {
217 "Shall I compare thee to a summer's day?",
218 "Thou art more lovely and more temperate:",
219 "Rough winds do shake the darling buds of May,",
220 "And summer's lease hath all too short a date;",
221 "Sometime too hot the eye of heaven shines,",
222 "And often is his gold complexion dimm'd;",
223 "And every fair from fair sometime declines,",
224 "By chance or nature's changing course untrimm'd;",
225 "But thy eternal summer shall not fade,",
226 "Nor lose possession of that fair thou ow'st;",
227 "Nor shall death brag thou wander'st in his shade,",
228 "When in eternal lines to time thou grow'st:",
229 " So long as men can breathe or eyes can see,",
230 " So long lives this, and this gives life to thee.",
231 };
232
233 @Test
234 public void testMessaging() throws Exception {
235 final String aTag = "messagingTag";
236 final String aText = "messagingText";
237 ArrayList<String> args = new ArrayList<>();
238 args.add("notify");
239 args.add("--style");
240 args.add("messaging");
241 args.add("--conversation");
242 args.add("Sonnet 18");
243 final int startOfLineArgs = args.size();
244 for (int i = 0; i < MESSAGES.length; i++) {
245 args.add("--message");
246 args.add(String.format("%s:%s",
247 PEOPLE[i % PEOPLE.length],
248 MESSAGES[i % MESSAGES.length]));
249 }
250 args.add(aTag);
251 args.add(aText);
252
253 doCmd(args.toArray(new String[0]));
254 final Notification captured = captureNotification(aTag);
255 assertSame(Notification.MessagingStyle.class, captured.getNotificationStyle());
256 final Notification.Builder builder =
257 Notification.Builder.recoverBuilder(mContext, captured);
258 final Notification.MessagingStyle messagingStyle =
259 (Notification.MessagingStyle) (builder.getStyle());
260
261 assertEquals("Sonnet 18", messagingStyle.getConversationTitle());
262 final List<Notification.MessagingStyle.Message> messages = messagingStyle.getMessages();
263 for (int i = 0; i < messages.size(); i++) {
264 final Notification.MessagingStyle.Message m = messages.get(i);
265 assertEquals(MESSAGES[i], m.getText());
266 assertEquals(PEOPLE[i % PEOPLE.length], m.getSenderPerson().getName());
267 }
268
269 }
270}