1 /*
2  * Copyright (C) 2021 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.systemui.people;
18 
19 import static android.app.Notification.CATEGORY_MISSED_CALL;
20 import static android.app.people.ConversationStatus.ACTIVITY_ANNIVERSARY;
21 import static android.app.people.ConversationStatus.ACTIVITY_BIRTHDAY;
22 import static android.app.people.ConversationStatus.ACTIVITY_GAME;
23 import static android.app.people.ConversationStatus.ACTIVITY_NEW_STORY;
24 import static android.app.people.ConversationStatus.AVAILABILITY_AVAILABLE;
25 import static android.app.people.PeopleSpaceTile.BLOCK_CONVERSATIONS;
26 import static android.app.people.PeopleSpaceTile.SHOW_CONTACTS;
27 import static android.app.people.PeopleSpaceTile.SHOW_IMPORTANT_CONVERSATIONS;
28 import static android.app.people.PeopleSpaceTile.SHOW_STARRED_CONTACTS;
29 
30 import static com.android.systemui.people.PeopleSpaceUtils.STARRED_CONTACT;
31 import static com.android.systemui.people.PeopleSpaceUtils.VALID_CONTACT;
32 
33 import static com.google.common.truth.Truth.assertThat;
34 
35 import static org.junit.Assert.assertEquals;
36 import static org.mockito.ArgumentMatchers.anyString;
37 import static org.mockito.Mockito.mock;
38 import static org.mockito.Mockito.when;
39 
40 import android.app.people.ConversationStatus;
41 import android.app.people.PeopleSpaceTile;
42 import android.content.Context;
43 import android.content.Intent;
44 import android.content.pm.PackageManager;
45 import android.content.res.Configuration;
46 import android.content.res.Resources;
47 import android.graphics.drawable.Icon;
48 import android.net.Uri;
49 import android.os.UserHandle;
50 import android.testing.AndroidTestingRunner;
51 import android.util.DisplayMetrics;
52 import android.view.View;
53 import android.widget.RemoteViews;
54 import android.widget.TextView;
55 
56 import androidx.test.filters.SmallTest;
57 
58 import com.android.systemui.R;
59 import com.android.systemui.SysuiTestCase;
60 import com.android.systemui.people.widget.PeopleTileKey;
61 
62 import org.junit.Before;
63 import org.junit.Test;
64 import org.junit.runner.RunWith;
65 import org.mockito.Mock;
66 import org.mockito.MockitoAnnotations;
67 
68 import java.time.Duration;
69 import java.util.Arrays;
70 
71 @RunWith(AndroidTestingRunner.class)
72 @SmallTest
73 public class PeopleTileViewHelperTest extends SysuiTestCase {
74 
75     private static final String SHORTCUT_ID_1 = "101";
76     private static final String NOTIFICATION_KEY = "notification_key";
77     private static final String NOTIFICATION_CONTENT = "notification_content";
78     private static final Uri URI = Uri.parse("fake_uri");
79     private static final Icon ICON = Icon.createWithResource("package", R.drawable.ic_android);
80     private static final String GAME_DESCRIPTION = "Playing a game!";
81     private static final CharSequence MISSED_CALL = "Custom missed call message";
82     private static final String NAME = "username";
83     private static final UserHandle USER = new UserHandle(0);
84     private static final String SENDER = "sender";
85 
86     private static final CharSequence EMOJI_BR_FLAG = "\ud83c\udde7\ud83c\uddf7";
87     private static final CharSequence EMOJI_BEAR = "\ud83d\udc3b";
88     private static final CharSequence EMOJI_THUMBS_UP_BROWN_SKIN = "\uD83D\uDC4D\uD83C\uDFFD";
89     private static final CharSequence EMOJI_JOY = "\uD83D\uDE02";
90     private static final CharSequence EMOJI_FAMILY =
91             "\ud83d\udc69\u200d\ud83d\udc69\u200d\ud83d\udc67\u200d\ud83d\udc67";
92 
93     private static final PeopleSpaceTile PERSON_TILE_WITHOUT_NOTIFICATION =
94             new PeopleSpaceTile
95                     .Builder(SHORTCUT_ID_1, NAME, ICON, new Intent())
96                     .setLastInteractionTimestamp(0L)
97                     .setUserHandle(USER)
98                     .build();
99     private static final PeopleSpaceTile PERSON_TILE =
100             new PeopleSpaceTile
101                     .Builder(SHORTCUT_ID_1, NAME, ICON, new Intent())
102                     .setLastInteractionTimestamp(123L)
103                     .setNotificationKey(NOTIFICATION_KEY)
104                     .setNotificationContent(NOTIFICATION_CONTENT)
105                     .setNotificationDataUri(URI)
106                     .setUserHandle(USER)
107                     .build();
108     private static final PeopleSpaceTile PERSON_TILE_WITH_SENDER =
109             new PeopleSpaceTile
110                     .Builder(SHORTCUT_ID_1, NAME, ICON, new Intent())
111                     .setLastInteractionTimestamp(123L)
112                     .setNotificationKey(NOTIFICATION_KEY)
113                     .setNotificationContent(NOTIFICATION_CONTENT)
114                     .setNotificationSender(SENDER)
115                     .setUserHandle(USER)
116                     .build();
117     private static final ConversationStatus GAME_STATUS =
118             new ConversationStatus
119                     .Builder(PERSON_TILE.getId(), ACTIVITY_GAME)
120                     .setDescription(GAME_DESCRIPTION)
121                     .build();
122     private static final ConversationStatus NEW_STORY_WITH_AVAILABILITY =
123             new ConversationStatus
124                     .Builder(PERSON_TILE.getId(), ACTIVITY_NEW_STORY)
125                     .setAvailability(AVAILABILITY_AVAILABLE)
126                     .build();
127 
128     @Mock
129     private Icon mIcon;
130 
131     @Mock
132     private Context mMockContext;
133     @Mock
134     private PackageManager mPackageManager;
135 
136     private int mWidth;
137     private int mHeight;
138     private PeopleTileViewHelper mPeopleTileViewHelper;
139 
140     @Before
setUp()141     public void setUp() throws Exception {
142         MockitoAnnotations.initMocks(this);
143 
144         when(mMockContext.getString(R.string.birthday_status)).thenReturn(
145                 mContext.getString(R.string.birthday_status));
146         when(mMockContext.getPackageManager()).thenReturn(mPackageManager);
147         when(mMockContext.getString(R.string.over_two_weeks_timestamp)).thenReturn(
148                 mContext.getString(R.string.over_two_weeks_timestamp));
149         Configuration configuration = mock(Configuration.class);
150         DisplayMetrics displayMetrics = mock(DisplayMetrics.class);
151         Resources resources = mock(Resources.class);
152         when(mMockContext.getResources()).thenReturn(resources);
153         when(resources.getConfiguration()).thenReturn(configuration);
154         when(resources.getDisplayMetrics()).thenReturn(displayMetrics);
155         TextView textView = mock(TextView.class);
156         when(textView.getLineHeight()).thenReturn(16);
157         when(mPackageManager.getApplicationIcon(anyString())).thenReturn(null);
158 
159         mWidth = getSizeInDp(R.dimen.default_width);
160         mHeight = getSizeInDp(R.dimen.default_height);
161         mPeopleTileViewHelper = getPeopleTileViewHelper(PERSON_TILE);
162     }
163 
164     @Test
testCreateRemoteViewsWithLastInteractionTimeUnderOneDayHidden()165     public void testCreateRemoteViewsWithLastInteractionTimeUnderOneDayHidden() {
166         RemoteViews views = getPeopleTileViewHelper(PERSON_TILE_WITHOUT_NOTIFICATION).getViews();
167         View result = views.apply(mContext, null);
168 
169         // Not showing last interaction.
170         assertEquals(View.GONE, result.findViewById(R.id.last_interaction).getVisibility());
171 
172         mWidth = getSizeInDp(R.dimen.required_width_for_large);
173         mHeight = getSizeInDp(R.dimen.required_height_for_large);
174         RemoteViews largeView = getPeopleTileViewHelper(
175                 PERSON_TILE_WITHOUT_NOTIFICATION).getViews();
176         View largeResult = largeView.apply(mContext, null);
177 
178         // Not showing last interaction.
179         assertEquals(View.GONE, largeResult.findViewById(R.id.last_interaction).getVisibility());
180     }
181 
182     @Test
testLastInteractionTime()183     public void testLastInteractionTime() {
184         long now = System.currentTimeMillis();
185         long fiveDaysAgo = now - Duration.ofDays(5).toMillis();
186         String lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
187                 fiveDaysAgo);
188         assertThat(lastInteractionString).isEqualTo("5 days ago");
189 
190         long lessThanOneDayAgo = now - Duration.ofHours(20).toMillis();
191         lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
192                 lessThanOneDayAgo);
193         assertThat(lastInteractionString).isNull();
194 
195         long overOneWeekAgo = now - Duration.ofDays(8).toMillis();
196         lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
197                 overOneWeekAgo);
198         assertThat(lastInteractionString).isEqualTo("Over 1 week ago");
199 
200         long overTwoWeeksAgo = now - Duration.ofDays(15).toMillis();
201         lastInteractionString = PeopleTileViewHelper.getLastInteractionString(mContext,
202                 overTwoWeeksAgo);
203         assertThat(lastInteractionString).isEqualTo("Over 2 weeks ago");
204     }
205 
206     @Test
testCreateRemoteViewsWithLastInteractionTime()207     public void testCreateRemoteViewsWithLastInteractionTime() {
208         PeopleSpaceTile tileWithLastInteraction =
209                 PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setLastInteractionTimestamp(
210                         123445L).build();
211         RemoteViews views = getPeopleTileViewHelper(tileWithLastInteraction).getViews();
212         View result = views.apply(mContext, null);
213 
214         TextView name = (TextView) result.findViewById(R.id.name);
215         assertEquals(name.getText(), NAME);
216         // Has last interaction.
217         assertEquals(View.VISIBLE, result.findViewById(R.id.last_interaction).getVisibility());
218         TextView lastInteraction = (TextView) result.findViewById(R.id.last_interaction);
219         assertEquals(lastInteraction.getText(), "Over 2 weeks ago");
220         // No availability.
221         assertEquals(View.GONE, result.findViewById(R.id.availability).getVisibility());
222         // Shows person icon.
223         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
224         // No status.
225         assertThat((View) result.findViewById(R.id.text_content)).isNull();
226 
227         mWidth = getSizeInDp(R.dimen.required_width_for_medium) - 1;
228         RemoteViews smallView = getPeopleTileViewHelper(tileWithLastInteraction).getViews();
229         View smallResult = smallView.apply(mContext, null);
230 
231         // Show name over predefined icon.
232         assertEquals(View.VISIBLE, smallResult.findViewById(R.id.name).getVisibility());
233         assertEquals(View.GONE, smallResult.findViewById(R.id.predefined_icon).getVisibility());
234         // Shows person icon.
235         assertEquals(View.VISIBLE, smallResult.findViewById(R.id.person_icon).getVisibility());
236         // No messages count.
237         assertEquals(View.GONE, smallResult.findViewById(R.id.messages_count).getVisibility());
238 
239         mHeight = getSizeInDp(R.dimen.required_height_for_medium) - 1;
240         RemoteViews smallViewHorizontal = getPeopleTileViewHelper(
241                 tileWithLastInteraction).getViews();
242         View smallResultHorizontal = smallViewHorizontal.apply(mContext, null);
243 
244         // Show name over predefined icon.
245         assertEquals(View.VISIBLE, smallResultHorizontal.findViewById(R.id.name).getVisibility());
246         assertEquals(View.GONE,
247                 smallResultHorizontal.findViewById(R.id.predefined_icon).getVisibility());
248         // Shows person icon.
249         assertEquals(View.VISIBLE,
250                 smallResultHorizontal.findViewById(R.id.person_icon).getVisibility());
251         // No messages count.
252         assertEquals(View.GONE,
253                 smallResultHorizontal.findViewById(R.id.messages_count).getVisibility());
254 
255         mWidth = getSizeInDp(R.dimen.required_width_for_large);
256         mHeight = getSizeInDp(R.dimen.required_height_for_large);
257         RemoteViews largeView = getPeopleTileViewHelper(
258                 tileWithLastInteraction).getViews();
259         View largeResult = largeView.apply(mContext, null);
260 
261         name = (TextView) largeResult.findViewById(R.id.name);
262         assertEquals(name.getText(), NAME);
263         // Has last interaction.
264         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.last_interaction).getVisibility());
265         lastInteraction = (TextView) result.findViewById(R.id.last_interaction);
266         assertEquals(lastInteraction.getText(), "Over 2 weeks ago");
267         // No availability.
268         assertEquals(View.GONE, result.findViewById(R.id.availability).getVisibility());
269         // Shows person icon.
270         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
271         // No status.
272         assertThat((View) result.findViewById(R.id.text_content)).isNull();
273     }
274 
275     @Test
testCreateRemoteViewsWithGameTypeOnlyIsIgnored()276     public void testCreateRemoteViewsWithGameTypeOnlyIsIgnored() {
277         PeopleSpaceTile tileWithAvailabilityAndNewStory =
278                 PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setStatuses(
279                         Arrays.asList(NEW_STORY_WITH_AVAILABILITY,
280                                 new ConversationStatus.Builder(
281                                         PERSON_TILE_WITHOUT_NOTIFICATION.getId(),
282                                         ACTIVITY_GAME).build())).build();
283         RemoteViews views = getPeopleTileViewHelper(tileWithAvailabilityAndNewStory).getViews();
284         View result = views.apply(mContext, null);
285 
286         TextView name = (TextView) result.findViewById(R.id.name);
287         assertEquals(name.getText(), NAME);
288         // Has last interaction over status.
289         assertEquals(View.GONE, result.findViewById(R.id.last_interaction).getVisibility());
290         // Has availability.
291         assertEquals(View.VISIBLE, result.findViewById(R.id.availability).getVisibility());
292         assertEquals(result.findViewById(R.id.availability).getContentDescription(),
293                 mContext.getString(R.string.person_available));
294         // Has person icon.
295         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
296         // No status.
297         assertThat((View) result.findViewById(R.id.text_content)).isNull();
298 
299         mWidth = getSizeInDp(R.dimen.required_width_for_medium) - 1;
300         RemoteViews smallView = getPeopleTileViewHelper(tileWithAvailabilityAndNewStory).getViews();
301         View smallResult = smallView.apply(mContext, null);
302 
303         // Show name rather than game type.
304         assertEquals(View.VISIBLE, smallResult.findViewById(R.id.name).getVisibility());
305         assertEquals(View.GONE, smallResult.findViewById(R.id.predefined_icon).getVisibility());
306         // Has person icon.
307         assertEquals(View.VISIBLE,
308                 smallResult.findViewById(R.id.person_icon).getVisibility());
309         // No messages count.
310         assertEquals(View.GONE, smallResult.findViewById(R.id.messages_count).getVisibility());
311 
312         mHeight = getSizeInDp(R.dimen.required_height_for_medium) - 1;
313         RemoteViews smallViewHorizontal = getPeopleTileViewHelper(
314                 tileWithAvailabilityAndNewStory).getViews();
315         View smallResultHorizontal = smallViewHorizontal.apply(mContext, null);
316 
317         // Show name over predefined icon.
318         assertEquals(View.VISIBLE, smallResultHorizontal.findViewById(R.id.name).getVisibility());
319         assertEquals(View.GONE,
320                 smallResultHorizontal.findViewById(R.id.predefined_icon).getVisibility());
321         // Shows person icon.
322         assertEquals(View.VISIBLE,
323                 smallResultHorizontal.findViewById(R.id.person_icon).getVisibility());
324         // No messages count.
325         assertEquals(View.GONE,
326                 smallResultHorizontal.findViewById(R.id.messages_count).getVisibility());
327 
328         mWidth = getSizeInDp(R.dimen.required_width_for_large);
329         mHeight = getSizeInDp(R.dimen.required_height_for_large);
330         RemoteViews largeView = getPeopleTileViewHelper(tileWithAvailabilityAndNewStory).getViews();
331         View largeResult = largeView.apply(mContext, null);
332 
333         name = (TextView) largeResult.findViewById(R.id.name);
334         assertEquals(name.getText(), NAME);
335         // Has last interaction.
336         assertEquals(View.GONE, largeResult.findViewById(R.id.last_interaction).getVisibility());
337         // Has availability.
338         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.availability).getVisibility());
339         assertEquals(largeResult.findViewById(R.id.availability).getContentDescription(),
340                 mContext.getString(R.string.person_available));
341         // Shows person icon.
342         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.person_icon).getVisibility());
343         // No status.
344         assertThat((View) largeResult.findViewById(R.id.text_content)).isNull();
345     }
346 
347     @Test
testCreateRemoteViewsWithBirthdayTypeOnlyIsNotIgnored()348     public void testCreateRemoteViewsWithBirthdayTypeOnlyIsNotIgnored() {
349         PeopleSpaceTile tileWithStatusTemplate =
350                 PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setStatuses(
351                         Arrays.asList(
352                                 NEW_STORY_WITH_AVAILABILITY, new ConversationStatus.Builder(
353                                         PERSON_TILE_WITHOUT_NOTIFICATION.getId(),
354                                         ACTIVITY_BIRTHDAY).build())).build();
355         RemoteViews views = getPeopleTileViewHelper(tileWithStatusTemplate).getViews();
356         View result = views.apply(mContext, null);
357 
358         TextView name = (TextView) result.findViewById(R.id.name);
359         assertEquals(name.getText(), NAME);
360         assertEquals(View.GONE, result.findViewById(R.id.subtext).getVisibility());
361         assertEquals(View.VISIBLE, result.findViewById(R.id.predefined_icon).getVisibility());
362         // Has availability.
363         assertEquals(View.VISIBLE, result.findViewById(R.id.availability).getVisibility());
364         // Has person icon.
365         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
366         // Has status text from backup text.
367         TextView statusContent = (TextView) result.findViewById(R.id.text_content);
368         assertEquals(View.VISIBLE, statusContent.getVisibility());
369         assertEquals(statusContent.getText(), mContext.getString(R.string.birthday_status));
370         assertThat(statusContent.getMaxLines()).isEqualTo(2);
371         assertThat(statusContent.getContentDescription().toString()).isEqualTo(
372                 mContext.getString(R.string.new_status_content_description, NAME,
373                         mContext.getString(R.string.birthday_status_content_description, NAME)));
374 
375         mWidth = getSizeInDp(R.dimen.required_width_for_medium) - 1;
376         RemoteViews smallView = getPeopleTileViewHelper(tileWithStatusTemplate).getViews();
377         View smallResult = smallView.apply(mContext, null);
378 
379         // Show icon instead of name.
380         assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
381         assertEquals(View.VISIBLE,
382                 smallResult.findViewById(R.id.predefined_icon).getVisibility());
383         assertThat(smallResult.findViewById(
384                 R.id.predefined_icon).getContentDescription().toString()).isEqualTo(
385                 mContext.getString(R.string.new_status_content_description, NAME,
386                         mContext.getString(R.string.birthday_status_content_description, NAME)));
387         // Has person icon.
388         assertEquals(View.VISIBLE,
389                 smallResult.findViewById(R.id.person_icon).getVisibility());
390         // No messages count.
391         assertEquals(View.GONE, smallResult.findViewById(R.id.messages_count).getVisibility());
392 
393         mHeight = getSizeInDp(R.dimen.required_height_for_medium) - 1;
394         RemoteViews smallViewHorizontal = getPeopleTileViewHelper(
395                 tileWithStatusTemplate).getViews();
396         View smallResultHorizontal = smallViewHorizontal.apply(mContext, null);
397 
398         // Show name over predefined icon.
399         assertEquals(View.GONE, smallResultHorizontal.findViewById(R.id.name).getVisibility());
400         assertEquals(View.VISIBLE,
401                 smallResultHorizontal.findViewById(R.id.predefined_icon).getVisibility());
402         // Shows person icon.
403         assertEquals(View.VISIBLE,
404                 smallResultHorizontal.findViewById(R.id.person_icon).getVisibility());
405         // No messages count.
406         assertEquals(View.GONE,
407                 smallResultHorizontal.findViewById(R.id.messages_count).getVisibility());
408 
409         mWidth = getSizeInDp(R.dimen.required_width_for_large);
410         mHeight = getSizeInDp(R.dimen.required_height_for_large);
411         RemoteViews largeView = getPeopleTileViewHelper(tileWithStatusTemplate).getViews();
412         View largeResult = largeView.apply(mContext, null);
413 
414         name = (TextView) largeResult.findViewById(R.id.name);
415         assertEquals(name.getText(), NAME);
416         assertEquals(View.GONE, largeResult.findViewById(R.id.subtext).getVisibility());
417         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.predefined_icon).getVisibility());
418         // Has availability.
419         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.availability).getVisibility());
420         // Has person icon.
421         View personIcon = largeResult.findViewById(R.id.person_icon);
422         assertEquals(View.VISIBLE, personIcon.getVisibility());
423         // Has notification content.
424         statusContent = (TextView) largeResult.findViewById(R.id.text_content);
425         assertEquals(View.VISIBLE, statusContent.getVisibility());
426         assertEquals(statusContent.getText(), mContext.getString(R.string.birthday_status));
427         assertThat(statusContent.getMaxLines()).isEqualTo(2);
428         assertThat(statusContent.getContentDescription().toString()).isEqualTo(
429                 mContext.getString(R.string.new_status_content_description, NAME,
430                         mContext.getString(R.string.birthday_status_content_description, NAME)));
431     }
432 
433     @Test
testCreateRemoteViewsWithStatusTemplate()434     public void testCreateRemoteViewsWithStatusTemplate() {
435         PeopleSpaceTile tileWithStatusTemplate =
436                 PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setStatuses(
437                         Arrays.asList(GAME_STATUS,
438                                 NEW_STORY_WITH_AVAILABILITY)).build();
439         RemoteViews views = getPeopleTileViewHelper(tileWithStatusTemplate).getViews();
440         View result = views.apply(mContext, null);
441 
442         TextView name = (TextView) result.findViewById(R.id.name);
443         assertEquals(name.getText(), NAME);
444         assertEquals(View.GONE, result.findViewById(R.id.subtext).getVisibility());
445         assertEquals(View.VISIBLE, result.findViewById(R.id.predefined_icon).getVisibility());
446         assertEquals(View.GONE, result.findViewById(R.id.scrim_layout).getVisibility());
447         assertEquals(View.GONE, result.findViewById(R.id.image).getVisibility());
448         // Has availability.
449         assertEquals(View.VISIBLE, result.findViewById(R.id.availability).getVisibility());
450         // Has person icon.
451         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
452         // Has status.
453         TextView statusContent = (TextView) result.findViewById(R.id.text_content);
454         assertEquals(statusContent.getText(), GAME_DESCRIPTION);
455         assertThat(statusContent.getMaxLines()).isEqualTo(2);
456         assertThat(statusContent.getContentDescription().toString()).isEqualTo(
457                 mContext.getString(R.string.new_status_content_description, NAME,
458                         GAME_DESCRIPTION));
459 
460         mWidth = getSizeInDp(R.dimen.required_width_for_medium) - 1;
461         RemoteViews smallView = getPeopleTileViewHelper(tileWithStatusTemplate).getViews();
462         View smallResult = smallView.apply(mContext, null);
463 
464         // Show icon instead of name.
465         assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
466         assertEquals(View.VISIBLE,
467                 smallResult.findViewById(R.id.predefined_icon).getVisibility());
468         assertThat(smallResult.findViewById(
469                 R.id.predefined_icon).getContentDescription().toString()).isEqualTo(
470                 mContext.getString(R.string.new_status_content_description, NAME,
471                         GAME_DESCRIPTION));
472         // Has person icon.
473         assertEquals(View.VISIBLE,
474                 smallResult.findViewById(R.id.person_icon).getVisibility());
475         // No messages count.
476         assertEquals(View.GONE, smallResult.findViewById(R.id.messages_count).getVisibility());
477 
478         mHeight = getSizeInDp(R.dimen.required_height_for_medium) - 1;
479         RemoteViews smallViewHorizontal = getPeopleTileViewHelper(
480                 tileWithStatusTemplate).getViews();
481         View smallResultHorizontal = smallViewHorizontal.apply(mContext, null);
482 
483         // Show name over predefined icon.
484         assertEquals(View.GONE, smallResultHorizontal.findViewById(R.id.name).getVisibility());
485         assertEquals(View.VISIBLE,
486                 smallResultHorizontal.findViewById(R.id.predefined_icon).getVisibility());
487         // Shows person icon.
488         assertEquals(View.VISIBLE,
489                 smallResultHorizontal.findViewById(R.id.person_icon).getVisibility());
490         // No messages count.
491         assertEquals(View.GONE,
492                 smallResultHorizontal.findViewById(R.id.messages_count).getVisibility());
493 
494         mWidth = getSizeInDp(R.dimen.required_width_for_large);
495         mHeight = getSizeInDp(R.dimen.required_height_for_large);
496         RemoteViews largeView = getPeopleTileViewHelper(tileWithStatusTemplate).getViews();
497         View largeResult = largeView.apply(mContext, null);
498 
499         name = (TextView) largeResult.findViewById(R.id.name);
500         assertEquals(name.getText(), NAME);
501         assertEquals(View.GONE, largeResult.findViewById(R.id.subtext).getVisibility());
502         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.predefined_icon).getVisibility());
503         assertEquals(View.GONE, largeResult.findViewById(R.id.scrim_layout).getVisibility());
504         assertEquals(View.GONE, largeResult.findViewById(R.id.image).getVisibility());
505         // Has availability.
506         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.availability).getVisibility());
507         // Has person icon.
508         View personIcon = largeResult.findViewById(R.id.person_icon);
509         assertEquals(View.VISIBLE, personIcon.getVisibility());
510         // Has notification content.
511         statusContent = (TextView) largeResult.findViewById(R.id.text_content);
512         assertEquals(View.VISIBLE, statusContent.getVisibility());
513         assertEquals(statusContent.getText(), GAME_DESCRIPTION);
514         assertThat(statusContent.getMaxLines()).isEqualTo(2);
515         assertThat(statusContent.getContentDescription().toString()).isEqualTo(
516                 mContext.getString(R.string.new_status_content_description, NAME,
517                         GAME_DESCRIPTION));
518     }
519 
520     @Test
testCreateRemoteViewsWithStatusTemplateWithImageOnMediumAndLarge()521     public void testCreateRemoteViewsWithStatusTemplateWithImageOnMediumAndLarge() {
522         PeopleSpaceTile tileWithIconInStatusTemplate =
523                 PERSON_TILE_WITHOUT_NOTIFICATION.toBuilder().setStatuses(
524                         Arrays.asList(new ConversationStatus.Builder(PERSON_TILE.getId(),
525                                 ACTIVITY_ANNIVERSARY).setDescription("Anniversary").setAvailability(
526                                 AVAILABILITY_AVAILABLE).setIcon(mIcon).build())).build();
527         RemoteViews views = getPeopleTileViewHelper(
528                 tileWithIconInStatusTemplate).getViews();
529         View result = views.apply(mContext, null);
530 
531         assertEquals(View.GONE, result.findViewById(R.id.subtext).getVisibility());
532         assertEquals(View.VISIBLE, result.findViewById(R.id.predefined_icon).getVisibility());
533         assertEquals(View.VISIBLE, result.findViewById(R.id.scrim_layout).getVisibility());
534         assertEquals(View.GONE, result.findViewById(R.id.image).getVisibility());
535         // Has availability.
536         assertEquals(View.VISIBLE, result.findViewById(R.id.availability).getVisibility());
537         // Has person icon.
538         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
539         // Has status.
540         TextView statusContent = (TextView) result.findViewById(R.id.name);
541         assertEquals(statusContent.getText(), "Anniversary");
542         // Since the image is showing which removes name, we need to manually include the name.
543         assertThat(statusContent.getContentDescription().toString()).isEqualTo(
544                 mContext.getString(R.string.new_status_content_description, NAME, "Anniversary"));
545         assertThat(statusContent.getMaxLines()).isEqualTo(1);
546 
547         mWidth = getSizeInDp(R.dimen.required_width_for_large);
548         mHeight = getSizeInDp(R.dimen.required_height_for_large);
549         RemoteViews largeView = getPeopleTileViewHelper(tileWithIconInStatusTemplate).getViews();
550         View largeResult = largeView.apply(mContext, null);
551 
552         assertEquals(View.GONE, largeResult.findViewById(R.id.subtext).getVisibility());
553         assertEquals(View.GONE, largeResult.findViewById(R.id.name).getVisibility());
554         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.predefined_icon).getVisibility());
555         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.scrim_layout).getVisibility());
556         assertEquals(View.GONE, largeResult.findViewById(R.id.image).getVisibility());
557         // Has availability.
558         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.availability).getVisibility());
559         // Has person icon.
560         View personIcon = largeResult.findViewById(R.id.person_icon);
561         assertEquals(View.VISIBLE, personIcon.getVisibility());
562         // Has status content.
563         statusContent = (TextView) largeResult.findViewById(R.id.text_content);
564         assertEquals(View.VISIBLE, statusContent.getVisibility());
565         assertEquals(statusContent.getText(), "Anniversary");
566         // Since the image is showing which removes name, we need to manually include the name.
567         assertThat(statusContent.getContentDescription().toString()).isEqualTo(
568                 mContext.getString(R.string.new_status_content_description, NAME, "Anniversary"));
569         assertThat(statusContent.getMaxLines()).isEqualTo(2);
570     }
571 
572     @Test
testCreateRemoteViewsWithPackageSuspended()573     public void testCreateRemoteViewsWithPackageSuspended() {
574         PeopleSpaceTile tile = PERSON_TILE.toBuilder()
575                 .setIsPackageSuspended(true)
576                 .build();
577         RemoteViews views = getPeopleTileViewHelper(tile).getViews();
578         View result = views.apply(mContext, null);
579 
580         assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_suppressed_layout);
581     }
582 
583     @Test
testCreateRemoteViewsWithUserQuieted()584     public void testCreateRemoteViewsWithUserQuieted() {
585         PeopleSpaceTile tile = PERSON_TILE.toBuilder()
586                 .setIsUserQuieted(true)
587                 .build();
588         RemoteViews views = getPeopleTileViewHelper(tile).getViews();
589         View result = views.apply(mContext, null);
590 
591         assertEquals(result.getSourceLayoutResId(), R.layout.people_tile_work_profile_quiet_layout);
592     }
593 
594     @Test
testCreateRemoteViewsWithDndBlocking()595     public void testCreateRemoteViewsWithDndBlocking() {
596         PeopleSpaceTile tileWithDndBlocking = PERSON_TILE.toBuilder()
597                 .setNotificationPolicyState(BLOCK_CONVERSATIONS)
598                 .build();
599         RemoteViews views = getPeopleTileViewHelper(tileWithDndBlocking).getViews();
600         View result = views.apply(mContext, null);
601 
602         assertResourcesEqual(
603                 result.getSourceLayoutResId(),
604                 R.layout.people_tile_with_suppression_detail_content_horizontal);
605 
606         tileWithDndBlocking = PERSON_TILE.toBuilder()
607                 .setNotificationPolicyState(BLOCK_CONVERSATIONS)
608                 .setCanBypassDnd(true)
609                 .build();
610         views = getPeopleTileViewHelper(tileWithDndBlocking).getViews();
611         result = views.apply(mContext, null);
612 
613         assertResourcesNotEqual(
614                 result.getSourceLayoutResId(),
615                 R.layout.people_tile_with_suppression_detail_content_horizontal);
616 
617         tileWithDndBlocking = PERSON_TILE.toBuilder()
618                 .setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS)
619                 .build();
620         views = getPeopleTileViewHelper(tileWithDndBlocking).getViews();
621         result = views.apply(mContext, null);
622 
623         assertResourcesEqual(
624                 result.getSourceLayoutResId(),
625                 R.layout.people_tile_with_suppression_detail_content_horizontal);
626 
627         tileWithDndBlocking = PERSON_TILE.toBuilder()
628                 .setNotificationPolicyState(SHOW_IMPORTANT_CONVERSATIONS)
629                 .setIsImportantConversation(true)
630                 .build();
631         views = getPeopleTileViewHelper(tileWithDndBlocking).getViews();
632         result = views.apply(mContext, null);
633 
634         assertResourcesNotEqual(
635                 result.getSourceLayoutResId(),
636                 R.layout.people_tile_with_suppression_detail_content_horizontal);
637 
638         tileWithDndBlocking = PERSON_TILE.toBuilder()
639                 .setNotificationPolicyState(SHOW_STARRED_CONTACTS)
640                 .setContactAffinity(VALID_CONTACT)
641                 .build();
642         views = getPeopleTileViewHelper(tileWithDndBlocking).getViews();
643         result = views.apply(mContext, null);
644 
645         assertResourcesEqual(
646                 result.getSourceLayoutResId(),
647                 R.layout.people_tile_with_suppression_detail_content_horizontal);
648 
649         tileWithDndBlocking = PERSON_TILE.toBuilder()
650                 .setNotificationPolicyState(SHOW_STARRED_CONTACTS)
651                 .setContactAffinity(STARRED_CONTACT)
652                 .build();
653         views = getPeopleTileViewHelper(tileWithDndBlocking).getViews();
654         result = views.apply(mContext, null);
655 
656         assertResourcesNotEqual(
657                 result.getSourceLayoutResId(),
658                 R.layout.people_tile_with_suppression_detail_content_horizontal);
659 
660         tileWithDndBlocking = PERSON_TILE.toBuilder()
661                 .setNotificationPolicyState(SHOW_CONTACTS)
662                 .setContactAffinity(STARRED_CONTACT)
663                 .build();
664         views = getPeopleTileViewHelper(tileWithDndBlocking).getViews();
665         result = views.apply(mContext, null);
666 
667         assertResourcesNotEqual(
668                 result.getSourceLayoutResId(),
669                 R.layout.people_tile_with_suppression_detail_content_horizontal);
670 
671         tileWithDndBlocking = PERSON_TILE.toBuilder()
672                 .setNotificationPolicyState(SHOW_CONTACTS)
673                 .setContactAffinity(VALID_CONTACT)
674                 .build();
675         views = getPeopleTileViewHelper(tileWithDndBlocking).getViews();
676         result = views.apply(mContext, null);
677 
678         assertResourcesNotEqual(
679                 result.getSourceLayoutResId(),
680                 R.layout.people_tile_with_suppression_detail_content_horizontal);
681 
682         tileWithDndBlocking = PERSON_TILE.toBuilder()
683                 .setNotificationPolicyState(SHOW_CONTACTS)
684                 .build();
685         views = getPeopleTileViewHelper(tileWithDndBlocking).getViews();
686         result = views.apply(mContext, null);
687 
688         assertResourcesEqual(
689                 result.getSourceLayoutResId(),
690                 R.layout.people_tile_with_suppression_detail_content_horizontal);
691         assertThat(result.<TextView>findViewById(R.id.text_content).getText().toString())
692                 .isEqualTo(mContext.getString(R.string.paused_by_dnd));
693     }
694 
695     @Test
testCreateRemoteViewsWithMissedCallNotification()696     public void testCreateRemoteViewsWithMissedCallNotification() {
697         PeopleSpaceTile tileWithMissedCallNotification = PERSON_TILE.toBuilder()
698                 .setNotificationDataUri(null)
699                 .setNotificationCategory(CATEGORY_MISSED_CALL)
700                 .setNotificationContent(MISSED_CALL)
701                 .build();
702         RemoteViews views = getPeopleTileViewHelper(tileWithMissedCallNotification).getViews();
703         View result = views.apply(mContext, null);
704 
705         TextView name = (TextView) result.findViewById(R.id.name);
706         assertEquals(name.getText(), NAME);
707         assertEquals(View.GONE, result.findViewById(R.id.subtext).getVisibility());
708         assertEquals(View.VISIBLE, result.findViewById(R.id.predefined_icon).getVisibility());
709         // Has availability.
710         assertEquals(View.GONE, result.findViewById(R.id.availability).getVisibility());
711         // Has person icon.
712         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
713         // Has missed call notification content.
714         TextView statusContent = (TextView) result.findViewById(R.id.text_content);
715         assertEquals(View.VISIBLE, statusContent.getVisibility());
716         assertEquals(statusContent.getText(), MISSED_CALL);
717         assertEquals(statusContent.getContentDescription(), mContext.getString(
718                 R.string.new_notification_text_content_description, NAME, MISSED_CALL));
719         assertThat(statusContent.getMaxLines()).isEqualTo(2);
720 
721         mWidth = getSizeInDp(R.dimen.required_width_for_medium) - 1;
722         RemoteViews smallView = getPeopleTileViewHelper(
723                 tileWithMissedCallNotification).getViews();
724         View smallResult = smallView.apply(mContext, null);
725 
726         // Show icon instead of name.
727         assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
728         assertEquals(View.VISIBLE,
729                 smallResult.findViewById(R.id.predefined_icon).getVisibility());
730         assertEquals(smallResult.findViewById(R.id.predefined_icon).getContentDescription(),
731                 mContext.getString(
732                         R.string.new_notification_text_content_description, NAME, MISSED_CALL));
733         // Has person icon.
734         assertEquals(View.VISIBLE, smallResult.findViewById(R.id.person_icon).getVisibility());
735         // No messages count.
736         assertEquals(View.GONE, smallResult.findViewById(R.id.messages_count).getVisibility());
737 
738         mWidth = getSizeInDp(R.dimen.required_width_for_large);
739         mHeight = getSizeInDp(R.dimen.required_height_for_large);
740         RemoteViews largeView = getPeopleTileViewHelper(tileWithMissedCallNotification).getViews();
741         View largeResult = largeView.apply(mContext, null);
742 
743         name = (TextView) largeResult.findViewById(R.id.name);
744         assertEquals(name.getText(), NAME);
745         assertEquals(View.GONE, largeResult.findViewById(R.id.subtext).getVisibility());
746         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.predefined_icon).getVisibility());
747         // Has availability.
748         assertEquals(View.GONE, largeResult.findViewById(R.id.availability).getVisibility());
749         // Has person icon.
750         View personIcon = largeResult.findViewById(R.id.person_icon);
751         assertEquals(View.VISIBLE, personIcon.getVisibility());
752         // Has notification content.
753         statusContent = (TextView) largeResult.findViewById(R.id.text_content);
754         assertEquals(View.VISIBLE, statusContent.getVisibility());
755         assertEquals(statusContent.getText(), MISSED_CALL);
756         assertEquals(statusContent.getContentDescription(), mContext.getString(
757                 R.string.new_notification_text_content_description, NAME, MISSED_CALL));
758         assertThat(statusContent.getMaxLines()).isEqualTo(2);
759     }
760 
761     @Test
testCreateRemoteViewsWithNotificationTemplate()762     public void testCreateRemoteViewsWithNotificationTemplate() {
763         PeopleSpaceTile tileWithStatusAndNotification = PERSON_TILE.toBuilder()
764                 .setNotificationDataUri(null)
765                 .setStatuses(Arrays.asList(GAME_STATUS,
766                         NEW_STORY_WITH_AVAILABILITY)).build();
767         RemoteViews views = getPeopleTileViewHelper(
768                 tileWithStatusAndNotification).getViews();
769         View result = views.apply(mContext, null);
770 
771         TextView name = (TextView) result.findViewById(R.id.name);
772         assertEquals(name.getText(), NAME);
773         assertEquals(View.GONE, result.findViewById(R.id.subtext).getVisibility());
774         assertEquals(View.GONE, result.findViewById(R.id.predefined_icon).getVisibility());
775         assertEquals(View.GONE, result.findViewById(R.id.scrim_layout).getVisibility());
776         // Has availability.
777         assertEquals(View.VISIBLE, result.findViewById(R.id.availability).getVisibility());
778         // Has person icon.
779         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
780         // Has notification content.
781         TextView statusContent = (TextView) result.findViewById(R.id.text_content);
782         assertEquals(View.VISIBLE, statusContent.getVisibility());
783         assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
784         assertEquals(statusContent.getContentDescription(), mContext.getString(
785                 R.string.new_notification_text_content_description, NAME, NOTIFICATION_CONTENT));
786         assertThat(statusContent.getMaxLines()).isEqualTo(2);
787 
788         // Has a single message, no count shown.
789         assertEquals(View.GONE, result.findViewById(R.id.messages_count).getVisibility());
790 
791         mWidth = getSizeInDp(R.dimen.required_width_for_medium) - 1;
792         RemoteViews smallView = getPeopleTileViewHelper(
793                 tileWithStatusAndNotification).getViews();
794         View smallResult = smallView.apply(mContext, null);
795 
796         // Show icon instead of name.
797         assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
798         assertEquals(View.VISIBLE,
799                 smallResult.findViewById(R.id.predefined_icon).getVisibility());
800         assertEquals(smallResult.findViewById(R.id.predefined_icon).getContentDescription(),
801                 mContext.getString(R.string.new_notification_text_content_description, NAME,
802                         NOTIFICATION_CONTENT));
803         // Has person icon.
804         assertEquals(View.VISIBLE,
805                 smallResult.findViewById(R.id.person_icon).getVisibility());
806 
807         // Has a single message, no count shown.
808         assertEquals(View.GONE, smallResult.findViewById(R.id.messages_count).getVisibility());
809 
810         mWidth = getSizeInDp(R.dimen.required_width_for_large);
811         mHeight = getSizeInDp(R.dimen.required_height_for_large);
812         RemoteViews largeView = getPeopleTileViewHelper(
813                 tileWithStatusAndNotification).getViews();
814         View largeResult = largeView.apply(mContext, null);
815 
816         name = (TextView) largeResult.findViewById(R.id.name);
817         assertEquals(name.getText(), NAME);
818         assertEquals(View.GONE, largeResult.findViewById(R.id.subtext).getVisibility());
819         assertEquals(View.GONE, largeResult.findViewById(R.id.predefined_icon).getVisibility());
820         assertEquals(largeResult.findViewById(R.id.scrim_layout), null);
821         // Has availability.
822         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.availability).getVisibility());
823         // Has person icon.
824         View personIcon = largeResult.findViewById(R.id.person_icon);
825         assertEquals(View.VISIBLE, personIcon.getVisibility());
826         // Has notification content.
827         statusContent = (TextView) largeResult.findViewById(R.id.text_content);
828         assertEquals(View.VISIBLE, statusContent.getVisibility());
829         assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
830         assertEquals(statusContent.getContentDescription(), mContext.getString(
831                 R.string.new_notification_text_content_description, NAME, NOTIFICATION_CONTENT));
832         assertThat(statusContent.getMaxLines()).isEqualTo(2);
833         // Has a single message, no count shown.
834         assertEquals(View.GONE, largeResult.findViewById(R.id.messages_count).getVisibility());
835 
836     }
837 
838     @Test
testCreateRemoteViewsWithNotificationWithSenderTemplate()839     public void testCreateRemoteViewsWithNotificationWithSenderTemplate() {
840         PeopleSpaceTile tileWithStatusAndNotification = PERSON_TILE_WITH_SENDER.toBuilder()
841                 .setNotificationDataUri(null)
842                 .setStatuses(Arrays.asList(GAME_STATUS,
843                         NEW_STORY_WITH_AVAILABILITY)).build();
844         RemoteViews views = getPeopleTileViewHelper(
845                 tileWithStatusAndNotification).getViews();
846         View result = views.apply(mContext, null);
847 
848         TextView name = (TextView) result.findViewById(R.id.name);
849         assertEquals(name.getText(), NAME);
850         TextView subtext = (TextView) result.findViewById(R.id.subtext);
851         assertEquals(View.VISIBLE, result.findViewById(R.id.subtext).getVisibility());
852         assertEquals(subtext.getText(), SENDER);
853         assertEquals(View.GONE, result.findViewById(R.id.predefined_icon).getVisibility());
854         // Has availability.
855         assertEquals(View.VISIBLE, result.findViewById(R.id.availability).getVisibility());
856         // Has person icon.
857         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
858         // Has notification content.
859         TextView statusContent = (TextView) result.findViewById(R.id.text_content);
860         assertEquals(View.VISIBLE, statusContent.getVisibility());
861         assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
862         assertEquals(statusContent.getContentDescription(), mContext.getString(
863                 R.string.new_notification_text_content_description, SENDER, NOTIFICATION_CONTENT));
864 
865         // Subtract one from lines because sender is included.
866         assertThat(statusContent.getMaxLines()).isEqualTo(1);
867 
868         // Has a single message, no count shown.
869         assertEquals(View.GONE, result.findViewById(R.id.messages_count).getVisibility());
870 
871         mWidth = getSizeInDp(R.dimen.required_width_for_medium) - 1;
872         RemoteViews smallView = getPeopleTileViewHelper(
873                 tileWithStatusAndNotification).getViews();
874         View smallResult = smallView.apply(mContext, null);
875 
876         // Show icon instead of name.
877         assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
878         assertEquals(View.VISIBLE,
879                 smallResult.findViewById(R.id.predefined_icon).getVisibility());
880         assertEquals(smallResult.findViewById(R.id.predefined_icon).getContentDescription(),
881                 mContext.getString(
882                         R.string.new_notification_text_content_description, SENDER,
883                         NOTIFICATION_CONTENT));
884         // Has person icon.
885         assertEquals(View.VISIBLE,
886                 smallResult.findViewById(R.id.person_icon).getVisibility());
887 
888         // Has a single message, no count shown.
889         assertEquals(View.GONE, smallResult.findViewById(R.id.messages_count).getVisibility());
890 
891         mWidth = getSizeInDp(R.dimen.required_width_for_large);
892         mHeight = getSizeInDp(R.dimen.required_height_for_large);
893         RemoteViews largeView = getPeopleTileViewHelper(
894                 tileWithStatusAndNotification).getViews();
895         View largeResult = largeView.apply(mContext, null);
896 
897         name = (TextView) largeResult.findViewById(R.id.name);
898         assertEquals(name.getText(), NAME);
899         subtext = (TextView) largeResult.findViewById(R.id.subtext);
900         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.subtext).getVisibility());
901         assertEquals(subtext.getText(), SENDER);
902         assertEquals(View.GONE, largeResult.findViewById(R.id.predefined_icon).getVisibility());
903         // Has availability.
904         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.availability).getVisibility());
905         // Has person icon.
906         View personIcon = largeResult.findViewById(R.id.person_icon);
907         assertEquals(View.VISIBLE, personIcon.getVisibility());
908         // Has notification content.
909         statusContent = (TextView) largeResult.findViewById(R.id.text_content);
910         assertEquals(View.VISIBLE, statusContent.getVisibility());
911         assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
912         assertEquals(statusContent.getContentDescription(), mContext.getString(
913                 R.string.new_notification_text_content_description, SENDER, NOTIFICATION_CONTENT));
914 
915         // Subtract one from lines because sender is included.
916         assertThat(statusContent.getMaxLines()).isEqualTo(1);
917 
918         // Has a single message, no count shown.
919         assertEquals(View.GONE, largeResult.findViewById(R.id.messages_count).getVisibility());
920 
921     }
922 
923     @Test
testCreateRemoteViewsWithNotificationTemplateTwoMessages()924     public void testCreateRemoteViewsWithNotificationTemplateTwoMessages() {
925         PeopleSpaceTile tileWithStatusAndNotification = PERSON_TILE.toBuilder()
926                 .setNotificationDataUri(null)
927                 .setStatuses(Arrays.asList(GAME_STATUS,
928                         NEW_STORY_WITH_AVAILABILITY))
929                 .setMessagesCount(2).build();
930         RemoteViews views = getPeopleTileViewHelper(
931                 tileWithStatusAndNotification).getViews();
932         View result = views.apply(mContext, null);
933 
934         TextView name = (TextView) result.findViewById(R.id.name);
935         assertEquals(name.getText(), NAME);
936         assertEquals(View.GONE, result.findViewById(R.id.subtext).getVisibility());
937         assertEquals(View.GONE, result.findViewById(R.id.predefined_icon).getVisibility());
938         // Has availability.
939         assertEquals(View.VISIBLE, result.findViewById(R.id.availability).getVisibility());
940         // Has person icon.
941         assertEquals(View.VISIBLE, result.findViewById(R.id.person_icon).getVisibility());
942         // Has notification content.
943         TextView statusContent = (TextView) result.findViewById(R.id.text_content);
944         assertEquals(View.VISIBLE, statusContent.getVisibility());
945         assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
946         assertThat(statusContent.getMaxLines()).isEqualTo(2);
947 
948         // Has two messages, show count.
949         assertEquals(View.VISIBLE, result.findViewById(R.id.messages_count).getVisibility());
950 
951         mWidth = getSizeInDp(R.dimen.required_width_for_medium) - 1;
952         RemoteViews smallView = getPeopleTileViewHelper(
953                 tileWithStatusAndNotification).getViews();
954         View smallResult = smallView.apply(mContext, null);
955 
956         // Show icon instead of name.
957         assertEquals(View.GONE, smallResult.findViewById(R.id.name).getVisibility());
958         assertEquals(View.GONE,
959                 smallResult.findViewById(R.id.predefined_icon).getVisibility());
960         // Has person icon.
961         assertEquals(View.VISIBLE,
962                 smallResult.findViewById(R.id.person_icon).getVisibility());
963 
964         // Has two messages, show count.
965         assertEquals(View.VISIBLE, smallResult.findViewById(R.id.messages_count).getVisibility());
966 
967         mWidth = getSizeInDp(R.dimen.required_width_for_large);
968         mHeight = getSizeInDp(R.dimen.required_height_for_large);
969         RemoteViews largeView = getPeopleTileViewHelper(
970                 tileWithStatusAndNotification).getViews();
971         View largeResult = largeView.apply(mContext, null);
972 
973         name = (TextView) largeResult.findViewById(R.id.name);
974         assertEquals(name.getText(), NAME);
975         assertEquals(View.GONE, largeResult.findViewById(R.id.subtext).getVisibility());
976         assertEquals(View.GONE, largeResult.findViewById(R.id.predefined_icon).getVisibility());
977         // Has availability.
978         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.availability).getVisibility());
979         // Has person icon.
980         View personIcon = largeResult.findViewById(R.id.person_icon);
981         assertEquals(View.VISIBLE, personIcon.getVisibility());
982         // Has notification content.
983         statusContent = (TextView) largeResult.findViewById(R.id.text_content);
984         assertEquals(View.VISIBLE, statusContent.getVisibility());
985         assertEquals(statusContent.getText(), NOTIFICATION_CONTENT);
986         assertThat(statusContent.getMaxLines()).isEqualTo(2);
987 
988         // Has two messages, show count.
989         assertEquals(View.VISIBLE, largeResult.findViewById(R.id.messages_count).getVisibility());
990     }
991 
992 
993     @Test
testGetDoublePunctuationNoPunctuation()994     public void testGetDoublePunctuationNoPunctuation() {
995         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation("test");
996 
997         assertThat(backgroundText).isNull();
998     }
999 
1000     @Test
testGetDoublePunctuationSingleExclamation()1001     public void testGetDoublePunctuationSingleExclamation() {
1002         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation("test!");
1003 
1004         assertThat(backgroundText).isNull();
1005     }
1006 
1007     @Test
testGetDoublePunctuationSingleQuestion()1008     public void testGetDoublePunctuationSingleQuestion() {
1009         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation("?test");
1010 
1011         assertThat(backgroundText).isNull();
1012     }
1013 
1014     @Test
testGetDoublePunctuationSeparatedMarks()1015     public void testGetDoublePunctuationSeparatedMarks() {
1016         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation("test! right!");
1017 
1018         assertThat(backgroundText).isNull();
1019     }
1020 
1021     @Test
testGetDoublePunctuationDoubleExclamation()1022     public void testGetDoublePunctuationDoubleExclamation() {
1023         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation("!!test");
1024 
1025         assertThat(backgroundText).isEqualTo("!");
1026     }
1027 
1028     @Test
testGetDoublePunctuationDoubleQuestion()1029     public void testGetDoublePunctuationDoubleQuestion() {
1030         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation("test??");
1031 
1032         assertThat(backgroundText).isEqualTo("?");
1033     }
1034 
1035     @Test
testGetDoublePunctuationMixed()1036     public void testGetDoublePunctuationMixed() {
1037         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation("test?!");
1038 
1039         assertThat(backgroundText).isEqualTo("!?");
1040     }
1041 
1042     @Test
testGetDoublePunctuationMixedInTheMiddle()1043     public void testGetDoublePunctuationMixedInTheMiddle() {
1044         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation(
1045                 "test!? in the middle");
1046 
1047         assertThat(backgroundText).isEqualTo("!?");
1048     }
1049 
1050     @Test
testGetDoublePunctuationMixedDifferentOrder()1051     public void testGetDoublePunctuationMixedDifferentOrder() {
1052         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation(
1053                 "test!? in the middle");
1054 
1055         assertThat(backgroundText).isEqualTo("!?");
1056     }
1057 
1058     @Test
testGetDoublePunctuationMultiple()1059     public void testGetDoublePunctuationMultiple() {
1060         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation(
1061                 "test!?!!? in the middle");
1062 
1063         assertThat(backgroundText).isEqualTo("!?");
1064     }
1065 
1066     @Test
testGetDoublePunctuationQuestionFirst()1067     public void testGetDoublePunctuationQuestionFirst() {
1068         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation(
1069                 "test?? in the middle!!");
1070 
1071         assertThat(backgroundText).isEqualTo("?");
1072     }
1073 
1074     @Test
testGetDoublePunctuationExclamationFirst()1075     public void testGetDoublePunctuationExclamationFirst() {
1076         CharSequence backgroundText = mPeopleTileViewHelper.getDoublePunctuation(
1077                 "test!! in the middle??");
1078 
1079         assertThat(backgroundText).isEqualTo("!");
1080     }
1081 
1082     @Test
testGetDoubleEmojisNoEmojis()1083     public void testGetDoubleEmojisNoEmojis() {
1084         CharSequence backgroundText = mPeopleTileViewHelper
1085                 .getDoubleEmoji("This string has no emojis.");
1086         assertThat(backgroundText).isNull();
1087     }
1088 
1089     @Test
testGetDoubleEmojisSingleEmoji()1090     public void testGetDoubleEmojisSingleEmoji() {
1091         CharSequence backgroundText = mPeopleTileViewHelper.getDoubleEmoji(
1092                 "This string has one emoji " + EMOJI_JOY + " in the middle.");
1093         assertThat(backgroundText).isNull();
1094     }
1095 
1096     @Test
testGetDoubleEmojisSingleEmojiThenTwoEmojis()1097     public void testGetDoubleEmojisSingleEmojiThenTwoEmojis() {
1098         CharSequence backgroundText = mPeopleTileViewHelper.getDoubleEmoji(
1099                 "This string has one emoji " + EMOJI_JOY + " in the middle, then two "
1100                         + EMOJI_BEAR + EMOJI_BEAR);
1101         assertEquals(backgroundText, EMOJI_BEAR);
1102     }
1103 
1104     @Test
testGetDoubleEmojisTwoEmojisWithModifier()1105     public void testGetDoubleEmojisTwoEmojisWithModifier() {
1106         CharSequence backgroundText = mPeopleTileViewHelper.getDoubleEmoji(
1107                 "Yes! " + EMOJI_THUMBS_UP_BROWN_SKIN + EMOJI_THUMBS_UP_BROWN_SKIN + " Sure.");
1108         assertEquals(backgroundText, EMOJI_THUMBS_UP_BROWN_SKIN);
1109     }
1110 
1111     @Test
testGetDoubleEmojisTwoFlagEmojis()1112     public void testGetDoubleEmojisTwoFlagEmojis() {
1113         CharSequence backgroundText = mPeopleTileViewHelper.getDoubleEmoji(
1114                 "Let's travel to " + EMOJI_BR_FLAG + EMOJI_BR_FLAG + " next year.");
1115         assertEquals(backgroundText, EMOJI_BR_FLAG);
1116     }
1117 
1118     @Test
testGetDoubleEmojiTwoBears()1119     public void testGetDoubleEmojiTwoBears() {
1120         CharSequence backgroundText = mPeopleTileViewHelper.getDoubleEmoji(
1121                 EMOJI_BEAR.toString() + EMOJI_BEAR.toString() + "bears!");
1122         assertEquals(backgroundText, EMOJI_BEAR);
1123     }
1124 
1125     @Test
testGetDoubleEmojiTwoEmojisTwice()1126     public void testGetDoubleEmojiTwoEmojisTwice() {
1127         CharSequence backgroundText = mPeopleTileViewHelper.getDoubleEmoji(
1128                 "Two sets of two emojis: " + EMOJI_FAMILY + EMOJI_FAMILY + EMOJI_BEAR + EMOJI_BEAR);
1129         assertEquals(backgroundText, EMOJI_FAMILY);
1130     }
1131 
1132     @Test
testGetDoubleEmojiTwoEmojisSeparated()1133     public void testGetDoubleEmojiTwoEmojisSeparated() {
1134         CharSequence backgroundText = mPeopleTileViewHelper.getDoubleEmoji(
1135                 "Two emojis " + EMOJI_BEAR + " separated " + EMOJI_BEAR + ".");
1136         assertThat(backgroundText).isNull();
1137     }
1138 
getSizeInDp(int dimenResourceId)1139     private int getSizeInDp(int dimenResourceId) {
1140         return (int) (mContext.getResources().getDimension(dimenResourceId)
1141                 / mContext.getResources().getDisplayMetrics().density);
1142     }
1143 
getPeopleTileViewHelper( PeopleSpaceTile tile)1144     private PeopleTileViewHelper getPeopleTileViewHelper(
1145             PeopleSpaceTile tile) {
1146         return new PeopleTileViewHelper(mContext, tile, 0, mWidth, mHeight,
1147                 new PeopleTileKey(tile.getId(), 0, tile.getPackageName()));
1148     }
1149 
assertResourcesEqual(int expected, int actual)1150     private void assertResourcesEqual(int expected, int actual) {
1151         assertThat(getResourceName(actual)).isEqualTo(getResourceName(expected));
1152     }
1153 
assertResourcesNotEqual(int expected, int actual)1154     private void assertResourcesNotEqual(int expected, int actual) {
1155         assertThat(getResourceName(actual)).isNotEqualTo(getResourceName(expected));
1156     }
1157 
getResourceName(int resId)1158     private String getResourceName(int resId) {
1159         Resources resources = mContext.getResources();
1160         try {
1161             return resources.getResourceEntryName(resId);
1162         } catch (Resources.NotFoundException e) {
1163             return String.valueOf(resId);
1164         }
1165     }
1166 }
1167