• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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 
17 package com.android.server.notification;
18 
19 import static junit.framework.Assert.assertEquals;
20 import static junit.framework.Assert.assertSame;
21 
22 import static org.hamcrest.Matchers.instanceOf;
23 import static org.junit.Assert.assertThat;
24 import static org.mockito.Mockito.eq;
25 import static org.mockito.Mockito.spy;
26 import static org.mockito.Mockito.verify;
27 import 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
30 import static java.io.FileDescriptor.err;
31 import static java.io.FileDescriptor.in;
32 import static java.io.FileDescriptor.out;
33 
34 import android.app.INotificationManager;
35 import android.app.Notification;
36 import android.graphics.Bitmap;
37 import android.graphics.Canvas;
38 import android.graphics.Color;
39 import android.graphics.drawable.GradientDrawable;
40 import android.graphics.drawable.Icon;
41 import android.os.Binder;
42 import android.os.Handler;
43 import android.os.ResultReceiver;
44 import android.os.ShellCallback;
45 import android.os.UserHandle;
46 import android.test.suitebuilder.annotation.SmallTest;
47 import android.testing.AndroidTestingRunner;
48 import android.testing.TestableContext;
49 import android.testing.TestableLooper;
50 import android.testing.TestableLooper.RunWithLooper;
51 
52 import com.android.server.UiServiceTestCase;
53 
54 import org.junit.Before;
55 import org.junit.Test;
56 import org.junit.runner.RunWith;
57 import org.mockito.ArgumentCaptor;
58 import org.mockito.Mock;
59 import org.mockito.MockitoAnnotations;
60 
61 import java.util.ArrayList;
62 import java.util.List;
63 
64 @SmallTest
65 @RunWith(AndroidTestingRunner.class)
66 @RunWithLooper
67 public 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
setUp()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 
createTestBitmap()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 
doCmd(String... args)100     private void doCmd(String... args) {
101         new NotificationShellCmd(mMockService)
102                 .exec(mBinder, in, out, err, args, mCallback, mResultReceiver);
103     }
104 
105     @Test
testNoArgs()106     public void testNoArgs() throws Exception {
107         doCmd();
108     }
109 
110     @Test
testHelp()111     public void testHelp() throws Exception {
112         doCmd("--help");
113     }
114 
captureNotification(String aTag)115     Notification captureNotification(String aTag) throws Exception {
116         ArgumentCaptor<Notification> notificationCaptor =
117                 ArgumentCaptor.forClass(Notification.class);
118         verify(mMockBinderService).enqueueNotificationWithTag(
119                 eq(NotificationShellCmd.NOTIFICATION_PACKAGE),
120                 eq("android"),
121                 eq(aTag),
122                 eq(NotificationShellCmd.NOTIFICATION_ID),
123                 notificationCaptor.capture(),
124                 eq(UserHandle.getCallingUserId()));
125         return notificationCaptor.getValue();
126     }
127 
128     @Test
testBasic()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
testIcon()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
testBigText()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
testBigPicture()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
testInbox()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
testMessaging()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 }
271