blob: f27f3f9ca427ce562eaf23ca3e8a3fc1c95b4143 [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;
Matt Pietalf38e9d22019-02-15 10:01:03 -050033import static org.mockito.Mockito.mock;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090034import static org.mockito.Mockito.times;
35import static org.mockito.Mockito.verify;
36import static org.mockito.Mockito.when;
37
38import android.app.usage.UsageStatsManager;
Matt Pietal26038402019-01-08 07:29:34 -050039import android.content.ClipData;
Matt Pietal1fa7d802019-01-30 10:44:15 -050040import android.content.ClipDescription;
41import android.content.ClipboardManager;
42import android.content.Context;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090043import android.content.Intent;
44import android.content.pm.ResolveInfo;
Matt Pietalf38e9d22019-02-15 10:01:03 -050045import android.database.Cursor;
Matt Pietal26038402019-01-08 07:29:34 -050046import android.graphics.Bitmap;
47import android.graphics.Canvas;
48import android.graphics.Color;
49import android.graphics.Paint;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050050import android.metrics.LogMaker;
Matt Pietal26038402019-01-08 07:29:34 -050051import android.net.Uri;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090052
Matt Pietal26038402019-01-08 07:29:34 -050053import androidx.test.ext.junit.runners.AndroidJUnit4;
54import androidx.test.platform.app.InstrumentationRegistry;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090055import androidx.test.rule.ActivityTestRule;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090056
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080057import com.android.internal.R;
58import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050059import com.android.internal.logging.MetricsLogger;
60import com.android.internal.logging.nano.MetricsProto;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080061
62import org.junit.Before;
63import org.junit.Rule;
64import org.junit.Test;
65import org.junit.runner.RunWith;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050066import org.mockito.ArgumentCaptor;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080067import org.mockito.Mockito;
68
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080069import java.util.ArrayList;
70import java.util.List;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080071
72/**
73 * Chooser activity instrumentation tests
74 */
75@RunWith(AndroidJUnit4.class)
76public class ChooserActivityTest {
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050077
78 private static final int CONTENT_PREVIEW_IMAGE = 1;
79 private static final int CONTENT_PREVIEW_FILE = 2;
80 private static final int CONTENT_PREVIEW_TEXT = 3;
81
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080082 @Rule
83 public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
84 new ActivityTestRule<>(ChooserWrapperActivity.class, false,
85 false);
86
Makoto Onuki99302b52017-03-29 12:42:26 -070087 @Before
88 public void cleanOverrideData() {
89 sOverrides.reset();
90 }
91
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080092 @Test
93 public void customTitle() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -050094 Intent viewIntent = createViewTextIntent();
95 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
96
97 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
98 Mockito.anyBoolean(),
99 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
100 mActivityRule.launchActivity(Intent.createChooser(viewIntent, "chooser test"));
101
102 waitForIdle();
103 onView(withId(R.id.title)).check(matches(withText("chooser test")));
104 }
105
106 @Test
107 public void customTitleIgnoredForSendIntents() throws InterruptedException {
108 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800109 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
110
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800111 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
112 Mockito.anyBoolean(),
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800113 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800114 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "chooser test"));
115 waitForIdle();
Matt Pietal26038402019-01-08 07:29:34 -0500116 onView(withId(R.id.title)).check(matches(withText(R.string.whichSendApplication)));
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800117 }
118
119 @Test
120 public void emptyTitle() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500121 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800122 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
123
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800124 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
125 Mockito.anyBoolean(),
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800126 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800127 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
128 waitForIdle();
129 onView(withId(R.id.title))
130 .check(matches(withText(R.string.whichSendApplication)));
131 }
132
133 @Test
Matt Pietal26038402019-01-08 07:29:34 -0500134 public void emptyPreviewTitleAndThumbnail() throws InterruptedException {
135 Intent sendIntent = createSendTextIntentWithPreview(null, null);
136 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
137
138 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
139 Mockito.anyBoolean(),
140 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
141 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
142 waitForIdle();
143 onView(withId(R.id.content_preview_title)).check(matches(not(isDisplayed())));
144 onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
145 }
146
147 @Test
148 public void visiblePreviewTitleWithoutThumbnail() throws InterruptedException {
149 String previewTitle = "My Content Preview Title";
150 Intent sendIntent = createSendTextIntentWithPreview(previewTitle, null);
151 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
152
153 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
154 Mockito.anyBoolean(),
155 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
156 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
157 waitForIdle();
158 onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
159 onView(withId(R.id.content_preview_title)).check(matches(withText(previewTitle)));
160 onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
161 }
162
163 @Test
164 public void visiblePreviewTitleWithInvalidThumbnail() throws InterruptedException {
165 String previewTitle = "My Content Preview Title";
166 Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
167 Uri.parse("tel:(+49)12345789"));
168 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
169
170 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
171 Mockito.anyBoolean(),
172 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
173 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
174 waitForIdle();
175 onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
176 onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
177 }
178
179 @Test
180 public void visiblePreviewTitleAndThumbnail() throws InterruptedException {
181 String previewTitle = "My Content Preview Title";
182 Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
183 Uri.parse("android.resource://com.android.frameworks.coretests/"
184 + com.android.frameworks.coretests.R.drawable.test320x240));
185 sOverrides.previewThumbnail = createBitmap();
186 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
187
188 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
189 Mockito.anyBoolean(),
190 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
191 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
192 waitForIdle();
193 onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
194 onView(withId(R.id.content_preview_thumbnail)).check(matches(isDisplayed()));
195 }
196
197 @Test
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800198 public void twoOptionsAndUserSelectsOne() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500199 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800200 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
201
202 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
203 Mockito.anyBoolean(),
204 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
205
206 final ChooserWrapperActivity activity = mActivityRule
207 .launchActivity(Intent.createChooser(sendIntent, null));
208 waitForIdle();
209
210 assertThat(activity.getAdapter().getCount(), is(2));
211 onView(withId(R.id.profile_button)).check(matches(not(isDisplayed())));
212
213 ResolveInfo[] chosen = new ResolveInfo[1];
214 sOverrides.onSafelyStartCallback = targetInfo -> {
215 chosen[0] = targetInfo.getResolveInfo();
216 return true;
217 };
218
219 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
220 onView(withText(toChoose.activityInfo.name))
221 .perform(click());
222 waitForIdle();
223 assertThat(chosen[0], is(toChoose));
224 }
225
226 @Test
Kang Li9fa2a2c2017-01-06 13:33:24 -0800227 public void updateChooserCountsAndModelAfterUserSelection() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500228 Intent sendIntent = createSendTextIntent();
Kang Li64b018e2017-01-05 17:30:06 -0800229 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
230
231 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
232 Mockito.anyBoolean(),
233 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
234
235 final ChooserWrapperActivity activity = mActivityRule
236 .launchActivity(Intent.createChooser(sendIntent, null));
237 waitForIdle();
238 UsageStatsManager usm = activity.getUsageStatsManager();
239 verify(sOverrides.resolverListController, times(1))
240 .sort(Mockito.any(List.class));
241 assertThat(activity.getIsSelected(), is(false));
242 sOverrides.onSafelyStartCallback = targetInfo -> {
243 return true;
244 };
Kang Li64b018e2017-01-05 17:30:06 -0800245 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
Kang Li64b018e2017-01-05 17:30:06 -0800246 onView(withText(toChoose.activityInfo.name))
247 .perform(click());
248 waitForIdle();
249 verify(sOverrides.resolverListController, times(1))
Kang Li9fa2a2c2017-01-06 13:33:24 -0800250 .updateChooserCounts(Mockito.anyString(), Mockito.anyInt(), Mockito.anyString());
251 verify(sOverrides.resolverListController, times(1))
Kang Li64b018e2017-01-05 17:30:06 -0800252 .updateModel(toChoose.activityInfo.getComponentName());
253 assertThat(activity.getIsSelected(), is(true));
Kang Li64b018e2017-01-05 17:30:06 -0800254 }
255
256 @Test
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800257 public void noResultsFromPackageManager() {
258 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
259 Mockito.anyBoolean(),
260 Mockito.isA(List.class))).thenReturn(null);
Matt Pietal26038402019-01-08 07:29:34 -0500261 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800262 final ChooserWrapperActivity activity = mActivityRule
263 .launchActivity(Intent.createChooser(sendIntent, null));
264 waitForIdle();
265 assertThat(activity.isFinishing(), is(false));
266
267 onView(withId(R.id.empty)).check(matches(isDisplayed()));
268 onView(withId(R.id.resolver_list)).check(matches(not(isDisplayed())));
269 InstrumentationRegistry.getInstrumentation().runOnMainSync(
270 () -> activity.getAdapter().handlePackagesChanged()
271 );
272 // backward compatibility. looks like we finish when data is empty after package change
273 assertThat(activity.isFinishing(), is(true));
274 }
275
276 @Test
277 public void autoLaunchSingleResult() throws InterruptedException {
278 ResolveInfo[] chosen = new ResolveInfo[1];
279 sOverrides.onSafelyStartCallback = targetInfo -> {
280 chosen[0] = targetInfo.getResolveInfo();
281 return true;
282 };
283
284 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
285 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
286 Mockito.anyBoolean(),
287 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
288
Matt Pietal26038402019-01-08 07:29:34 -0500289 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800290 final ChooserWrapperActivity activity = mActivityRule
291 .launchActivity(Intent.createChooser(sendIntent, null));
292 waitForIdle();
293
294 assertThat(chosen[0], is(resolvedComponentInfos.get(0).getResolveInfoAt(0)));
295 assertThat(activity.isFinishing(), is(true));
296 }
297
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800298 @Test
299 public void hasOtherProfileOneOption() throws Exception {
Matt Pietal26038402019-01-08 07:29:34 -0500300 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800301 List<ResolvedComponentInfo> resolvedComponentInfos =
302 createResolvedComponentsForTestWithOtherProfile(2);
303 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
304
305 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
306 Mockito.anyBoolean(),
307 Mockito.anyBoolean(),
308 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
309
310 final ChooserWrapperActivity activity = mActivityRule
311 .launchActivity(Intent.createChooser(sendIntent, null));
312 waitForIdle();
313
314 // The other entry is filtered to the other profile slot
315 assertThat(activity.getAdapter().getCount(), is(1));
316
317 ResolveInfo[] chosen = new ResolveInfo[1];
318 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
319 chosen[0] = targetInfo.getResolveInfo();
320 return true;
321 };
Makoto Onuki99302b52017-03-29 12:42:26 -0700322
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800323 // Make a stable copy of the components as the original list may be modified
324 List<ResolvedComponentInfo> stableCopy =
325 createResolvedComponentsForTestWithOtherProfile(2);
326 // Check that the "Other Profile" activity is put in the right spot
327 onView(withId(R.id.profile_button)).check(matches(
328 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
329 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
330 .perform(click());
331 waitForIdle();
332 assertThat(chosen[0], is(toChoose));
333 }
334
335 @Test
336 public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
Matt Pietal26038402019-01-08 07:29:34 -0500337 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800338 List<ResolvedComponentInfo> resolvedComponentInfos =
339 createResolvedComponentsForTestWithOtherProfile(3);
340 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
341
342 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
343 Mockito.anyBoolean(),
344 Mockito.anyBoolean(),
345 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
346 when(ChooserWrapperActivity.sOverrides.resolverListController.getLastChosen())
347 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
348
349 final ChooserWrapperActivity activity = mActivityRule
350 .launchActivity(Intent.createChooser(sendIntent, null));
351 waitForIdle();
352
353 // The other entry is filtered to the other profile slot
354 assertThat(activity.getAdapter().getCount(), is(2));
355
356 ResolveInfo[] chosen = new ResolveInfo[1];
357 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
358 chosen[0] = targetInfo.getResolveInfo();
359 return true;
360 };
361
362 // Make a stable copy of the components as the original list may be modified
363 List<ResolvedComponentInfo> stableCopy =
364 createResolvedComponentsForTestWithOtherProfile(3);
365 // Check that the "Other Profile" activity is put in the right spot
366 onView(withId(R.id.profile_button)).check(matches(
367 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
368 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
369 .perform(click());
370 waitForIdle();
371 assertThat(chosen[0], is(toChoose));
372 }
373
374 @Test
375 public void hasLastChosenActivityAndOtherProfile() throws Exception {
Matt Pietal26038402019-01-08 07:29:34 -0500376 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800377 List<ResolvedComponentInfo> resolvedComponentInfos =
378 createResolvedComponentsForTestWithOtherProfile(3);
379 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
380
381 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
382 Mockito.anyBoolean(),
383 Mockito.anyBoolean(),
384 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
385
386 final ChooserWrapperActivity activity = mActivityRule
387 .launchActivity(Intent.createChooser(sendIntent, null));
388 waitForIdle();
389
390 // The other entry is filtered to the last used slot
391 assertThat(activity.getAdapter().getCount(), is(2));
392
393 ResolveInfo[] chosen = new ResolveInfo[1];
394 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
395 chosen[0] = targetInfo.getResolveInfo();
396 return true;
397 };
398
399 // Make a stable copy of the components as the original list may be modified
400 List<ResolvedComponentInfo> stableCopy =
401 createResolvedComponentsForTestWithOtherProfile(3);
402 // Check that the "Other Profile" activity is put in the right spot
403 onView(withId(R.id.profile_button)).check(matches(
404 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
405 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
406 .perform(click());
407 waitForIdle();
408 assertThat(chosen[0], is(toChoose));
409 }
410
Matt Pietal1fa7d802019-01-30 10:44:15 -0500411 @Test
412 public void copyTextToClipboard() throws Exception {
413 Intent sendIntent = createSendTextIntent();
Matt Pietal46d828c2019-02-05 08:07:07 -0500414 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
Matt Pietal1fa7d802019-01-30 10:44:15 -0500415
416 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500417 Mockito.anyBoolean(),
418 Mockito.anyBoolean(),
419 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Matt Pietal1fa7d802019-01-30 10:44:15 -0500420
421 final ChooserWrapperActivity activity = mActivityRule
422 .launchActivity(Intent.createChooser(sendIntent, null));
423 waitForIdle();
424
Matt Pietal46d828c2019-02-05 08:07:07 -0500425 onView(withId(R.id.copy_button)).check(matches(isDisplayed()));
Matt Pietal1fa7d802019-01-30 10:44:15 -0500426 onView(withId(R.id.copy_button)).perform(click());
Matt Pietal1fa7d802019-01-30 10:44:15 -0500427 ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(
428 Context.CLIPBOARD_SERVICE);
429 ClipData clipData = clipboard.getPrimaryClip();
430 assertThat("testing intent sending", is(clipData.getItemAt(0).getText()));
431
432 ClipDescription clipDescription = clipData.getDescription();
433 assertThat("text/plain", is(clipDescription.getMimeType(0)));
434 }
435
Matt Pietal0ea391b2019-01-30 10:44:15 -0500436 @Test
437 public void oneVisibleImagePreview() throws InterruptedException {
438 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
439 + com.android.frameworks.coretests.R.drawable.test320x240);
440
441 ArrayList<Uri> uris = new ArrayList<>();
442 uris.add(uri);
443
Matt Pietal46d828c2019-02-05 08:07:07 -0500444 Intent sendIntent = createSendUriIntentWithPreview(uris);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500445 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500446 sOverrides.isImageType = true;
Matt Pietal0ea391b2019-01-30 10:44:15 -0500447
448 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
449
450 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
451 Mockito.anyBoolean(),
452 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
453 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
454 waitForIdle();
455 onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
456 onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed())));
457 onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed())));
458 onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed())));
459 }
460
461 @Test
462 public void twoVisibleImagePreview() throws InterruptedException {
463 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
464 + com.android.frameworks.coretests.R.drawable.test320x240);
465
466 ArrayList<Uri> uris = new ArrayList<>();
467 uris.add(uri);
468 uris.add(uri);
469
Matt Pietal46d828c2019-02-05 08:07:07 -0500470 Intent sendIntent = createSendUriIntentWithPreview(uris);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500471 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500472 sOverrides.isImageType = true;
Matt Pietal0ea391b2019-01-30 10:44:15 -0500473
474 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
475
476 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
477 Mockito.anyBoolean(),
478 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
479 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
480 waitForIdle();
481 onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
482 onView(withId(R.id.content_preview_image_2_large)).check(matches(isDisplayed()));
483 onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed())));
484 onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed())));
485 }
486
487 @Test
488 public void threeOrMoreVisibleImagePreview() throws InterruptedException {
489 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
490 + com.android.frameworks.coretests.R.drawable.test320x240);
491
492 ArrayList<Uri> uris = new ArrayList<>();
493 uris.add(uri);
494 uris.add(uri);
495 uris.add(uri);
496 uris.add(uri);
497 uris.add(uri);
498
Matt Pietal46d828c2019-02-05 08:07:07 -0500499 Intent sendIntent = createSendUriIntentWithPreview(uris);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500500 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500501 sOverrides.isImageType = true;
Matt Pietal0ea391b2019-01-30 10:44:15 -0500502
503 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
504
505 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500506 Mockito.anyBoolean(),
507 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500508 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
509 waitForIdle();
510 onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
511 onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed())));
512 onView(withId(R.id.content_preview_image_2_small)).check(matches(isDisplayed()));
513 onView(withId(R.id.content_preview_image_3_small)).check(matches(isDisplayed()));
514 }
515
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500516 @Test
517 public void testOnCreateLogging() {
518 Intent sendIntent = createSendTextIntent();
519 sendIntent.setType("TestType");
520
521 MetricsLogger mockLogger = sOverrides.metricsLogger;
522 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
523 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
524 waitForIdle();
525 verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
526 assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
527 is(MetricsProto.MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
528 assertThat(logMakerCaptor
529 .getAllValues().get(0)
530 .getTaggedData(MetricsProto.MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
531 is(notNullValue()));
532 assertThat(logMakerCaptor
533 .getAllValues().get(0)
534 .getTaggedData(MetricsProto.MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
535 is("TestType"));
536 }
537
538 @Test
539 public void testEmptyPreviewLogging() {
540 Intent sendIntent = createSendTextIntentWithPreview(null, null);
541
542 MetricsLogger mockLogger = sOverrides.metricsLogger;
543 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
544 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "empty preview logger test"));
545 waitForIdle();
Matt Pietal46d828c2019-02-05 08:07:07 -0500546
547 verify(mockLogger, Mockito.times(1)).write(logMakerCaptor.capture());
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500548 // First invocation is from onCreate
Matt Pietal46d828c2019-02-05 08:07:07 -0500549 assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
550 is(MetricsProto.MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500551 }
552
553 @Test
554 public void testTitlePreviewLogging() {
555 Intent sendIntent = createSendTextIntentWithPreview("TestTitle", null);
556
557 MetricsLogger mockLogger = sOverrides.metricsLogger;
558 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
Matt Pietal46d828c2019-02-05 08:07:07 -0500559
560 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
561
562 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
563 Mockito.anyBoolean(),
564 Mockito.anyBoolean(),
565 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
566
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500567 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
568 waitForIdle();
Matt Pietal46d828c2019-02-05 08:07:07 -0500569 verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500570 // First invocation is from onCreate
571 assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
572 is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
573 assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
574 is(CONTENT_PREVIEW_TEXT));
575 }
576
577 @Test
578 public void testImagePreviewLogging() {
579 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
580 + com.android.frameworks.coretests.R.drawable.test320x240);
581
582 ArrayList<Uri> uris = new ArrayList<>();
583 uris.add(uri);
584
Matt Pietal46d828c2019-02-05 08:07:07 -0500585 Intent sendIntent = createSendUriIntentWithPreview(uris);
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500586 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500587 sOverrides.isImageType = true;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500588
589 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
590
591 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
592 Mockito.anyBoolean(),
593 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
594
595 MetricsLogger mockLogger = sOverrides.metricsLogger;
596 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
597 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
598 waitForIdle();
599 verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
600 // First invocation is from onCreate
601 assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
602 is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
603 assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
604 is(CONTENT_PREVIEW_IMAGE));
605 assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
606 is(MetricsProto.MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
607 assertThat(logMakerCaptor.getAllValues().get(2).getSubtype(),
608 is(CONTENT_PREVIEW_IMAGE));
609 }
610
Matt Pietal46d828c2019-02-05 08:07:07 -0500611 @Test
612 public void oneVisibleFilePreview() throws InterruptedException {
613 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
614
615 ArrayList<Uri> uris = new ArrayList<>();
616 uris.add(uri);
617
618 Intent sendIntent = createSendUriIntentWithPreview(uris);
619
620 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
621
622 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
623 Mockito.anyBoolean(),
624 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
625 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
626 waitForIdle();
627 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
628 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
629 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
630 }
631
632
633 @Test
634 public void moreThanOneVisibleFilePreview() throws InterruptedException {
635 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
636
637 ArrayList<Uri> uris = new ArrayList<>();
638 uris.add(uri);
639 uris.add(uri);
640 uris.add(uri);
641
642 Intent sendIntent = createSendUriIntentWithPreview(uris);
643
644 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
645
646 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
647 Mockito.anyBoolean(),
648 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
649 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
650 waitForIdle();
651 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
652 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 2 files")));
653 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
654 }
655
Matt Pietalf38e9d22019-02-15 10:01:03 -0500656 @Test
657 public void contentProviderThrowSecurityException() throws InterruptedException {
658 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
659
660 ArrayList<Uri> uris = new ArrayList<>();
661 uris.add(uri);
662
663 Intent sendIntent = createSendUriIntentWithPreview(uris);
664
665 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
666 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
667 Mockito.anyBoolean(),
668 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
669
670 sOverrides.resolverForceException = true;
671
672 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
673 waitForIdle();
674 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
675 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
676 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
677 }
678
679 @Test
680 public void contentProviderReturnsNoColumns() throws InterruptedException {
681 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
682
683 ArrayList<Uri> uris = new ArrayList<>();
684 uris.add(uri);
685 uris.add(uri);
686
687 Intent sendIntent = createSendUriIntentWithPreview(uris);
688
689 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
690 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
691 Mockito.anyBoolean(),
692 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
693
694 Cursor cursor = mock(Cursor.class);
695 when(cursor.getCount()).thenReturn(1);
696 Mockito.doNothing().when(cursor).close();
697 when(cursor.moveToFirst()).thenReturn(true);
698 when(cursor.getColumnIndex(Mockito.anyString())).thenReturn(-1);
699
700 sOverrides.resolverCursor = cursor;
701
702 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
703 waitForIdle();
704 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
705 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 1 file")));
706 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
707 }
708
Matt Pietal26038402019-01-08 07:29:34 -0500709 private Intent createSendTextIntent() {
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800710 Intent sendIntent = new Intent();
711 sendIntent.setAction(Intent.ACTION_SEND);
712 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800713 return sendIntent;
714 }
715
Matt Pietal26038402019-01-08 07:29:34 -0500716 private Intent createSendTextIntentWithPreview(String title, Uri imageThumbnail) {
717 Intent sendIntent = new Intent();
718 sendIntent.setAction(Intent.ACTION_SEND);
719 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
720 sendIntent.putExtra(Intent.EXTRA_TITLE, title);
721 if (imageThumbnail != null) {
722 ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
723 sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
724 }
725
726 return sendIntent;
727 }
728
Matt Pietal46d828c2019-02-05 08:07:07 -0500729 private Intent createSendUriIntentWithPreview(ArrayList<Uri> uris) {
Matt Pietal0ea391b2019-01-30 10:44:15 -0500730 Intent sendIntent = new Intent();
731
732 if (uris.size() > 1) {
733 sendIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
734 sendIntent.putExtra(Intent.EXTRA_STREAM, uris);
735 } else {
736 sendIntent.setAction(Intent.ACTION_SEND);
737 sendIntent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
738 }
739
740 return sendIntent;
741 }
742
Matt Pietal26038402019-01-08 07:29:34 -0500743 private Intent createViewTextIntent() {
744 Intent viewIntent = new Intent();
745 viewIntent.setAction(Intent.ACTION_VIEW);
746 viewIntent.putExtra(Intent.EXTRA_TEXT, "testing intent viewing");
747 return viewIntent;
748 }
749
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800750 private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
751 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
752 for (int i = 0; i < numberOfResults; i++) {
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800753 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800754 }
755 return infoList;
756 }
757
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800758 private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
759 int numberOfResults) {
760 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
761 for (int i = 0; i < numberOfResults; i++) {
762 if (i == 0) {
763 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
764 } else {
765 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
766 }
767 }
768 return infoList;
769 }
770
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800771 private void waitForIdle() {
772 InstrumentationRegistry.getInstrumentation().waitForIdleSync();
773 }
Matt Pietal26038402019-01-08 07:29:34 -0500774
775 private Bitmap createBitmap() {
776 int width = 200;
777 int height = 200;
778 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
779 Canvas canvas = new Canvas(bitmap);
780
781 Paint paint = new Paint();
782 paint.setColor(Color.RED);
783 paint.setStyle(Paint.Style.FILL);
784 canvas.drawPaint(paint);
785
786 paint.setColor(Color.WHITE);
787 paint.setAntiAlias(true);
788 paint.setTextSize(14.f);
789 paint.setTextAlign(Paint.Align.CENTER);
790 canvas.drawText("Hi!", (width / 2.f), (height / 2.f), paint);
791
792 return bitmap;
793 }
794}