blob: 7f104b1b0a145d33e686d2fbd276380a81e88115 [file] [log] [blame]
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -08001/*
2 * Copyright (C) 2016 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.internal.app;
18
Matt Pietal26038402019-01-08 07:29:34 -050019import static androidx.test.espresso.Espresso.onView;
20import static androidx.test.espresso.action.ViewActions.click;
21import static androidx.test.espresso.assertion.ViewAssertions.matches;
22import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
23import static androidx.test.espresso.matcher.ViewMatchers.withId;
24import static androidx.test.espresso.matcher.ViewMatchers.withText;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090025
26import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
27
28import static org.hamcrest.CoreMatchers.is;
29import static org.hamcrest.CoreMatchers.not;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050030import static org.hamcrest.CoreMatchers.notNullValue;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090031import static org.hamcrest.MatcherAssert.assertThat;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050032import static org.mockito.Mockito.atLeastOnce;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090033import static org.mockito.Mockito.times;
34import static org.mockito.Mockito.verify;
35import static org.mockito.Mockito.when;
36
37import android.app.usage.UsageStatsManager;
Matt Pietal26038402019-01-08 07:29:34 -050038import android.content.ClipData;
Matt Pietal1fa7d802019-01-30 10:44:15 -050039import android.content.ClipDescription;
40import android.content.ClipboardManager;
41import android.content.Context;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090042import android.content.Intent;
43import android.content.pm.ResolveInfo;
Matt Pietal26038402019-01-08 07:29:34 -050044import android.graphics.Bitmap;
45import android.graphics.Canvas;
46import android.graphics.Color;
47import android.graphics.Paint;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050048import android.metrics.LogMaker;
Matt Pietal26038402019-01-08 07:29:34 -050049import android.net.Uri;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090050
Matt Pietal26038402019-01-08 07:29:34 -050051import androidx.test.ext.junit.runners.AndroidJUnit4;
52import androidx.test.platform.app.InstrumentationRegistry;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090053import androidx.test.rule.ActivityTestRule;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090054
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080055import com.android.internal.R;
56import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050057import com.android.internal.logging.MetricsLogger;
58import com.android.internal.logging.nano.MetricsProto;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080059
60import org.junit.Before;
61import org.junit.Rule;
62import org.junit.Test;
63import org.junit.runner.RunWith;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050064import org.mockito.ArgumentCaptor;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080065import org.mockito.Mockito;
66
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080067import java.util.ArrayList;
68import java.util.List;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080069
70/**
71 * Chooser activity instrumentation tests
72 */
73@RunWith(AndroidJUnit4.class)
74public class ChooserActivityTest {
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050075
76 private static final int CONTENT_PREVIEW_IMAGE = 1;
77 private static final int CONTENT_PREVIEW_FILE = 2;
78 private static final int CONTENT_PREVIEW_TEXT = 3;
79
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080080 @Rule
81 public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
82 new ActivityTestRule<>(ChooserWrapperActivity.class, false,
83 false);
84
Makoto Onuki99302b52017-03-29 12:42:26 -070085 @Before
86 public void cleanOverrideData() {
87 sOverrides.reset();
88 }
89
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080090 @Test
91 public void customTitle() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -050092 Intent viewIntent = createViewTextIntent();
93 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
94
95 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
96 Mockito.anyBoolean(),
97 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
98 mActivityRule.launchActivity(Intent.createChooser(viewIntent, "chooser test"));
99
100 waitForIdle();
101 onView(withId(R.id.title)).check(matches(withText("chooser test")));
102 }
103
104 @Test
105 public void customTitleIgnoredForSendIntents() throws InterruptedException {
106 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800107 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
108
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800109 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
110 Mockito.anyBoolean(),
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800111 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800112 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "chooser test"));
113 waitForIdle();
Matt Pietal26038402019-01-08 07:29:34 -0500114 onView(withId(R.id.title)).check(matches(withText(R.string.whichSendApplication)));
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800115 }
116
117 @Test
118 public void emptyTitle() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500119 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800120 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
121
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800122 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
123 Mockito.anyBoolean(),
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800124 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800125 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
126 waitForIdle();
127 onView(withId(R.id.title))
128 .check(matches(withText(R.string.whichSendApplication)));
129 }
130
131 @Test
Matt Pietal26038402019-01-08 07:29:34 -0500132 public void emptyPreviewTitleAndThumbnail() throws InterruptedException {
133 Intent sendIntent = createSendTextIntentWithPreview(null, null);
134 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
135
136 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
137 Mockito.anyBoolean(),
138 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
139 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
140 waitForIdle();
141 onView(withId(R.id.content_preview_title)).check(matches(not(isDisplayed())));
142 onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
143 }
144
145 @Test
146 public void visiblePreviewTitleWithoutThumbnail() throws InterruptedException {
147 String previewTitle = "My Content Preview Title";
148 Intent sendIntent = createSendTextIntentWithPreview(previewTitle, null);
149 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
150
151 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
152 Mockito.anyBoolean(),
153 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
154 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
155 waitForIdle();
156 onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
157 onView(withId(R.id.content_preview_title)).check(matches(withText(previewTitle)));
158 onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
159 }
160
161 @Test
162 public void visiblePreviewTitleWithInvalidThumbnail() throws InterruptedException {
163 String previewTitle = "My Content Preview Title";
164 Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
165 Uri.parse("tel:(+49)12345789"));
166 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
167
168 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
169 Mockito.anyBoolean(),
170 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
171 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
172 waitForIdle();
173 onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
174 onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
175 }
176
177 @Test
178 public void visiblePreviewTitleAndThumbnail() throws InterruptedException {
179 String previewTitle = "My Content Preview Title";
180 Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
181 Uri.parse("android.resource://com.android.frameworks.coretests/"
182 + com.android.frameworks.coretests.R.drawable.test320x240));
183 sOverrides.previewThumbnail = createBitmap();
184 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
185
186 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
187 Mockito.anyBoolean(),
188 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
189 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
190 waitForIdle();
191 onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
192 onView(withId(R.id.content_preview_thumbnail)).check(matches(isDisplayed()));
193 }
194
195 @Test
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800196 public void twoOptionsAndUserSelectsOne() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500197 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800198 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
199
200 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
201 Mockito.anyBoolean(),
202 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
203
204 final ChooserWrapperActivity activity = mActivityRule
205 .launchActivity(Intent.createChooser(sendIntent, null));
206 waitForIdle();
207
208 assertThat(activity.getAdapter().getCount(), is(2));
209 onView(withId(R.id.profile_button)).check(matches(not(isDisplayed())));
210
211 ResolveInfo[] chosen = new ResolveInfo[1];
212 sOverrides.onSafelyStartCallback = targetInfo -> {
213 chosen[0] = targetInfo.getResolveInfo();
214 return true;
215 };
216
217 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
218 onView(withText(toChoose.activityInfo.name))
219 .perform(click());
220 waitForIdle();
221 assertThat(chosen[0], is(toChoose));
222 }
223
224 @Test
Kang Li9fa2a2c2017-01-06 13:33:24 -0800225 public void updateChooserCountsAndModelAfterUserSelection() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500226 Intent sendIntent = createSendTextIntent();
Kang Li64b018e2017-01-05 17:30:06 -0800227 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
228
229 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
230 Mockito.anyBoolean(),
231 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
232
233 final ChooserWrapperActivity activity = mActivityRule
234 .launchActivity(Intent.createChooser(sendIntent, null));
235 waitForIdle();
236 UsageStatsManager usm = activity.getUsageStatsManager();
237 verify(sOverrides.resolverListController, times(1))
238 .sort(Mockito.any(List.class));
239 assertThat(activity.getIsSelected(), is(false));
240 sOverrides.onSafelyStartCallback = targetInfo -> {
241 return true;
242 };
Kang Li64b018e2017-01-05 17:30:06 -0800243 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
Kang Li64b018e2017-01-05 17:30:06 -0800244 onView(withText(toChoose.activityInfo.name))
245 .perform(click());
246 waitForIdle();
247 verify(sOverrides.resolverListController, times(1))
Kang Li9fa2a2c2017-01-06 13:33:24 -0800248 .updateChooserCounts(Mockito.anyString(), Mockito.anyInt(), Mockito.anyString());
249 verify(sOverrides.resolverListController, times(1))
Kang Li64b018e2017-01-05 17:30:06 -0800250 .updateModel(toChoose.activityInfo.getComponentName());
251 assertThat(activity.getIsSelected(), is(true));
Kang Li64b018e2017-01-05 17:30:06 -0800252 }
253
254 @Test
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800255 public void noResultsFromPackageManager() {
256 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
257 Mockito.anyBoolean(),
258 Mockito.isA(List.class))).thenReturn(null);
Matt Pietal26038402019-01-08 07:29:34 -0500259 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800260 final ChooserWrapperActivity activity = mActivityRule
261 .launchActivity(Intent.createChooser(sendIntent, null));
262 waitForIdle();
263 assertThat(activity.isFinishing(), is(false));
264
265 onView(withId(R.id.empty)).check(matches(isDisplayed()));
266 onView(withId(R.id.resolver_list)).check(matches(not(isDisplayed())));
267 InstrumentationRegistry.getInstrumentation().runOnMainSync(
268 () -> activity.getAdapter().handlePackagesChanged()
269 );
270 // backward compatibility. looks like we finish when data is empty after package change
271 assertThat(activity.isFinishing(), is(true));
272 }
273
274 @Test
275 public void autoLaunchSingleResult() throws InterruptedException {
276 ResolveInfo[] chosen = new ResolveInfo[1];
277 sOverrides.onSafelyStartCallback = targetInfo -> {
278 chosen[0] = targetInfo.getResolveInfo();
279 return true;
280 };
281
282 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
283 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
284 Mockito.anyBoolean(),
285 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
286
Matt Pietal26038402019-01-08 07:29:34 -0500287 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800288 final ChooserWrapperActivity activity = mActivityRule
289 .launchActivity(Intent.createChooser(sendIntent, null));
290 waitForIdle();
291
292 assertThat(chosen[0], is(resolvedComponentInfos.get(0).getResolveInfoAt(0)));
293 assertThat(activity.isFinishing(), is(true));
294 }
295
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800296 @Test
297 public void hasOtherProfileOneOption() throws Exception {
Matt Pietal26038402019-01-08 07:29:34 -0500298 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800299 List<ResolvedComponentInfo> resolvedComponentInfos =
300 createResolvedComponentsForTestWithOtherProfile(2);
301 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
302
303 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
304 Mockito.anyBoolean(),
305 Mockito.anyBoolean(),
306 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
307
308 final ChooserWrapperActivity activity = mActivityRule
309 .launchActivity(Intent.createChooser(sendIntent, null));
310 waitForIdle();
311
312 // The other entry is filtered to the other profile slot
313 assertThat(activity.getAdapter().getCount(), is(1));
314
315 ResolveInfo[] chosen = new ResolveInfo[1];
316 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
317 chosen[0] = targetInfo.getResolveInfo();
318 return true;
319 };
Makoto Onuki99302b52017-03-29 12:42:26 -0700320
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800321 // Make a stable copy of the components as the original list may be modified
322 List<ResolvedComponentInfo> stableCopy =
323 createResolvedComponentsForTestWithOtherProfile(2);
324 // Check that the "Other Profile" activity is put in the right spot
325 onView(withId(R.id.profile_button)).check(matches(
326 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
327 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
328 .perform(click());
329 waitForIdle();
330 assertThat(chosen[0], is(toChoose));
331 }
332
333 @Test
334 public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
Matt Pietal26038402019-01-08 07:29:34 -0500335 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800336 List<ResolvedComponentInfo> resolvedComponentInfos =
337 createResolvedComponentsForTestWithOtherProfile(3);
338 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
339
340 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
341 Mockito.anyBoolean(),
342 Mockito.anyBoolean(),
343 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
344 when(ChooserWrapperActivity.sOverrides.resolverListController.getLastChosen())
345 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
346
347 final ChooserWrapperActivity activity = mActivityRule
348 .launchActivity(Intent.createChooser(sendIntent, null));
349 waitForIdle();
350
351 // The other entry is filtered to the other profile slot
352 assertThat(activity.getAdapter().getCount(), is(2));
353
354 ResolveInfo[] chosen = new ResolveInfo[1];
355 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
356 chosen[0] = targetInfo.getResolveInfo();
357 return true;
358 };
359
360 // Make a stable copy of the components as the original list may be modified
361 List<ResolvedComponentInfo> stableCopy =
362 createResolvedComponentsForTestWithOtherProfile(3);
363 // Check that the "Other Profile" activity is put in the right spot
364 onView(withId(R.id.profile_button)).check(matches(
365 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
366 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
367 .perform(click());
368 waitForIdle();
369 assertThat(chosen[0], is(toChoose));
370 }
371
372 @Test
373 public void hasLastChosenActivityAndOtherProfile() throws Exception {
Matt Pietal26038402019-01-08 07:29:34 -0500374 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800375 List<ResolvedComponentInfo> resolvedComponentInfos =
376 createResolvedComponentsForTestWithOtherProfile(3);
377 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
378
379 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
380 Mockito.anyBoolean(),
381 Mockito.anyBoolean(),
382 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
383
384 final ChooserWrapperActivity activity = mActivityRule
385 .launchActivity(Intent.createChooser(sendIntent, null));
386 waitForIdle();
387
388 // The other entry is filtered to the last used slot
389 assertThat(activity.getAdapter().getCount(), is(2));
390
391 ResolveInfo[] chosen = new ResolveInfo[1];
392 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
393 chosen[0] = targetInfo.getResolveInfo();
394 return true;
395 };
396
397 // Make a stable copy of the components as the original list may be modified
398 List<ResolvedComponentInfo> stableCopy =
399 createResolvedComponentsForTestWithOtherProfile(3);
400 // Check that the "Other Profile" activity is put in the right spot
401 onView(withId(R.id.profile_button)).check(matches(
402 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
403 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
404 .perform(click());
405 waitForIdle();
406 assertThat(chosen[0], is(toChoose));
407 }
408
Matt Pietal1fa7d802019-01-30 10:44:15 -0500409 @Test
410 public void copyTextToClipboard() throws Exception {
411 Intent sendIntent = createSendTextIntent();
Matt Pietal46d828c2019-02-05 08:07:07 -0500412 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
Matt Pietal1fa7d802019-01-30 10:44:15 -0500413
414 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500415 Mockito.anyBoolean(),
416 Mockito.anyBoolean(),
417 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Matt Pietal1fa7d802019-01-30 10:44:15 -0500418
419 final ChooserWrapperActivity activity = mActivityRule
420 .launchActivity(Intent.createChooser(sendIntent, null));
421 waitForIdle();
422
Matt Pietal46d828c2019-02-05 08:07:07 -0500423 onView(withId(R.id.copy_button)).check(matches(isDisplayed()));
Matt Pietal1fa7d802019-01-30 10:44:15 -0500424 onView(withId(R.id.copy_button)).perform(click());
Matt Pietal1fa7d802019-01-30 10:44:15 -0500425 ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(
426 Context.CLIPBOARD_SERVICE);
427 ClipData clipData = clipboard.getPrimaryClip();
428 assertThat("testing intent sending", is(clipData.getItemAt(0).getText()));
429
430 ClipDescription clipDescription = clipData.getDescription();
431 assertThat("text/plain", is(clipDescription.getMimeType(0)));
432 }
433
Matt Pietal0ea391b2019-01-30 10:44:15 -0500434 @Test
435 public void oneVisibleImagePreview() throws InterruptedException {
436 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
437 + com.android.frameworks.coretests.R.drawable.test320x240);
438
439 ArrayList<Uri> uris = new ArrayList<>();
440 uris.add(uri);
441
Matt Pietal46d828c2019-02-05 08:07:07 -0500442 Intent sendIntent = createSendUriIntentWithPreview(uris);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500443 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500444 sOverrides.isImageType = true;
Matt Pietal0ea391b2019-01-30 10:44:15 -0500445
446 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
447
448 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
449 Mockito.anyBoolean(),
450 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
451 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
452 waitForIdle();
453 onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
454 onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed())));
455 onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed())));
456 onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed())));
457 }
458
459 @Test
460 public void twoVisibleImagePreview() throws InterruptedException {
461 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
462 + com.android.frameworks.coretests.R.drawable.test320x240);
463
464 ArrayList<Uri> uris = new ArrayList<>();
465 uris.add(uri);
466 uris.add(uri);
467
Matt Pietal46d828c2019-02-05 08:07:07 -0500468 Intent sendIntent = createSendUriIntentWithPreview(uris);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500469 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500470 sOverrides.isImageType = true;
Matt Pietal0ea391b2019-01-30 10:44:15 -0500471
472 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
473
474 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
475 Mockito.anyBoolean(),
476 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
477 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
478 waitForIdle();
479 onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
480 onView(withId(R.id.content_preview_image_2_large)).check(matches(isDisplayed()));
481 onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed())));
482 onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed())));
483 }
484
485 @Test
486 public void threeOrMoreVisibleImagePreview() throws InterruptedException {
487 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
488 + com.android.frameworks.coretests.R.drawable.test320x240);
489
490 ArrayList<Uri> uris = new ArrayList<>();
491 uris.add(uri);
492 uris.add(uri);
493 uris.add(uri);
494 uris.add(uri);
495 uris.add(uri);
496
Matt Pietal46d828c2019-02-05 08:07:07 -0500497 Intent sendIntent = createSendUriIntentWithPreview(uris);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500498 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500499 sOverrides.isImageType = true;
Matt Pietal0ea391b2019-01-30 10:44:15 -0500500
501 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
502
503 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500504 Mockito.anyBoolean(),
505 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500506 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
507 waitForIdle();
508 onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
509 onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed())));
510 onView(withId(R.id.content_preview_image_2_small)).check(matches(isDisplayed()));
511 onView(withId(R.id.content_preview_image_3_small)).check(matches(isDisplayed()));
512 }
513
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500514 @Test
515 public void testOnCreateLogging() {
516 Intent sendIntent = createSendTextIntent();
517 sendIntent.setType("TestType");
518
519 MetricsLogger mockLogger = sOverrides.metricsLogger;
520 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
521 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
522 waitForIdle();
523 verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
524 assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
525 is(MetricsProto.MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
526 assertThat(logMakerCaptor
527 .getAllValues().get(0)
528 .getTaggedData(MetricsProto.MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
529 is(notNullValue()));
530 assertThat(logMakerCaptor
531 .getAllValues().get(0)
532 .getTaggedData(MetricsProto.MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
533 is("TestType"));
534 }
535
536 @Test
537 public void testEmptyPreviewLogging() {
538 Intent sendIntent = createSendTextIntentWithPreview(null, null);
539
540 MetricsLogger mockLogger = sOverrides.metricsLogger;
541 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
542 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "empty preview logger test"));
543 waitForIdle();
Matt Pietal46d828c2019-02-05 08:07:07 -0500544
545 verify(mockLogger, Mockito.times(1)).write(logMakerCaptor.capture());
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500546 // First invocation is from onCreate
Matt Pietal46d828c2019-02-05 08:07:07 -0500547 assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
548 is(MetricsProto.MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500549 }
550
551 @Test
552 public void testTitlePreviewLogging() {
553 Intent sendIntent = createSendTextIntentWithPreview("TestTitle", null);
554
555 MetricsLogger mockLogger = sOverrides.metricsLogger;
556 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
Matt Pietal46d828c2019-02-05 08:07:07 -0500557
558 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
559
560 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
561 Mockito.anyBoolean(),
562 Mockito.anyBoolean(),
563 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
564
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500565 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
566 waitForIdle();
Matt Pietal46d828c2019-02-05 08:07:07 -0500567 verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500568 // First invocation is from onCreate
569 assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
570 is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
571 assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
572 is(CONTENT_PREVIEW_TEXT));
573 }
574
575 @Test
576 public void testImagePreviewLogging() {
577 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
578 + com.android.frameworks.coretests.R.drawable.test320x240);
579
580 ArrayList<Uri> uris = new ArrayList<>();
581 uris.add(uri);
582
Matt Pietal46d828c2019-02-05 08:07:07 -0500583 Intent sendIntent = createSendUriIntentWithPreview(uris);
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500584 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500585 sOverrides.isImageType = true;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500586
587 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
588
589 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
590 Mockito.anyBoolean(),
591 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
592
593 MetricsLogger mockLogger = sOverrides.metricsLogger;
594 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
595 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
596 waitForIdle();
597 verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
598 // First invocation is from onCreate
599 assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
600 is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
601 assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
602 is(CONTENT_PREVIEW_IMAGE));
603 assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
604 is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
605 assertThat(logMakerCaptor.getAllValues().get(2).getSubtype(),
606 is(CONTENT_PREVIEW_IMAGE));
607 }
608
Matt Pietal46d828c2019-02-05 08:07:07 -0500609 @Test
610 public void oneVisibleFilePreview() throws InterruptedException {
611 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
612
613 ArrayList<Uri> uris = new ArrayList<>();
614 uris.add(uri);
615
616 Intent sendIntent = createSendUriIntentWithPreview(uris);
617
618 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
619
620 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
621 Mockito.anyBoolean(),
622 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
623 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
624 waitForIdle();
625 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
626 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
627 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
628 }
629
630
631 @Test
632 public void moreThanOneVisibleFilePreview() throws InterruptedException {
633 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
634
635 ArrayList<Uri> uris = new ArrayList<>();
636 uris.add(uri);
637 uris.add(uri);
638 uris.add(uri);
639
640 Intent sendIntent = createSendUriIntentWithPreview(uris);
641
642 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
643
644 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
645 Mockito.anyBoolean(),
646 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
647 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
648 waitForIdle();
649 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
650 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 2 files")));
651 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
652 }
653
Matt Pietal26038402019-01-08 07:29:34 -0500654 private Intent createSendTextIntent() {
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800655 Intent sendIntent = new Intent();
656 sendIntent.setAction(Intent.ACTION_SEND);
657 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800658 return sendIntent;
659 }
660
Matt Pietal26038402019-01-08 07:29:34 -0500661 private Intent createSendTextIntentWithPreview(String title, Uri imageThumbnail) {
662 Intent sendIntent = new Intent();
663 sendIntent.setAction(Intent.ACTION_SEND);
664 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
665 sendIntent.putExtra(Intent.EXTRA_TITLE, title);
666 if (imageThumbnail != null) {
667 ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
668 sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
669 }
670
671 return sendIntent;
672 }
673
Matt Pietal46d828c2019-02-05 08:07:07 -0500674 private Intent createSendUriIntentWithPreview(ArrayList<Uri> uris) {
Matt Pietal0ea391b2019-01-30 10:44:15 -0500675 Intent sendIntent = new Intent();
676
677 if (uris.size() > 1) {
678 sendIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
679 sendIntent.putExtra(Intent.EXTRA_STREAM, uris);
680 } else {
681 sendIntent.setAction(Intent.ACTION_SEND);
682 sendIntent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
683 }
684
685 return sendIntent;
686 }
687
Matt Pietal26038402019-01-08 07:29:34 -0500688 private Intent createViewTextIntent() {
689 Intent viewIntent = new Intent();
690 viewIntent.setAction(Intent.ACTION_VIEW);
691 viewIntent.putExtra(Intent.EXTRA_TEXT, "testing intent viewing");
692 return viewIntent;
693 }
694
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800695 private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
696 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
697 for (int i = 0; i < numberOfResults; i++) {
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800698 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800699 }
700 return infoList;
701 }
702
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800703 private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
704 int numberOfResults) {
705 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
706 for (int i = 0; i < numberOfResults; i++) {
707 if (i == 0) {
708 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
709 } else {
710 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
711 }
712 }
713 return infoList;
714 }
715
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800716 private void waitForIdle() {
717 InstrumentationRegistry.getInstrumentation().waitForIdleSync();
718 }
Matt Pietal26038402019-01-08 07:29:34 -0500719
720 private Bitmap createBitmap() {
721 int width = 200;
722 int height = 200;
723 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
724 Canvas canvas = new Canvas(bitmap);
725
726 Paint paint = new Paint();
727 paint.setColor(Color.RED);
728 paint.setStyle(Paint.Style.FILL);
729 canvas.drawPaint(paint);
730
731 paint.setColor(Color.WHITE);
732 paint.setAntiAlias(true);
733 paint.setTextSize(14.f);
734 paint.setTextAlign(Paint.Align.CENTER);
735 canvas.drawText("Hi!", (width / 2.f), (height / 2.f), paint);
736
737 return bitmap;
738 }
739}