blob: 3578bc0c911d19c90a5970961712d92bdd7c6f20 [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;
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -050060import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
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(),
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500527 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500528 assertThat(logMakerCaptor
529 .getAllValues().get(0)
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500530 .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500531 is(notNullValue()));
532 assertThat(logMakerCaptor
533 .getAllValues().get(0)
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500534 .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500535 is("TestType"));
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500536 assertThat(logMakerCaptor
537 .getAllValues().get(0)
538 .getSubtype(),
539 is(MetricsEvent.PARENT_PROFILE));
540 }
541
542 @Test
543 public void testOnCreateLoggingFromWorkProfile() {
544 Intent sendIntent = createSendTextIntent();
545 sendIntent.setType("TestType");
546 sOverrides.alternateProfileSetting = MetricsEvent.MANAGED_PROFILE;
547 MetricsLogger mockLogger = sOverrides.metricsLogger;
548 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
549 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
550 waitForIdle();
551 verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
552 assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
553 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
554 assertThat(logMakerCaptor
555 .getAllValues().get(0)
556 .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
557 is(notNullValue()));
558 assertThat(logMakerCaptor
559 .getAllValues().get(0)
560 .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
561 is("TestType"));
562 assertThat(logMakerCaptor
563 .getAllValues().get(0)
564 .getSubtype(),
565 is(MetricsEvent.MANAGED_PROFILE));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500566 }
567
568 @Test
569 public void testEmptyPreviewLogging() {
570 Intent sendIntent = createSendTextIntentWithPreview(null, null);
571
572 MetricsLogger mockLogger = sOverrides.metricsLogger;
573 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
574 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "empty preview logger test"));
575 waitForIdle();
Matt Pietal46d828c2019-02-05 08:07:07 -0500576
577 verify(mockLogger, Mockito.times(1)).write(logMakerCaptor.capture());
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500578 // First invocation is from onCreate
Matt Pietal46d828c2019-02-05 08:07:07 -0500579 assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500580 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500581 }
582
583 @Test
584 public void testTitlePreviewLogging() {
585 Intent sendIntent = createSendTextIntentWithPreview("TestTitle", null);
586
587 MetricsLogger mockLogger = sOverrides.metricsLogger;
588 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
Matt Pietal46d828c2019-02-05 08:07:07 -0500589
590 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
591
592 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
593 Mockito.anyBoolean(),
594 Mockito.anyBoolean(),
595 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
596
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500597 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
598 waitForIdle();
Matt Pietal46d828c2019-02-05 08:07:07 -0500599 verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500600 // First invocation is from onCreate
601 assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500602 is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500603 assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
604 is(CONTENT_PREVIEW_TEXT));
605 }
606
607 @Test
608 public void testImagePreviewLogging() {
609 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
610 + com.android.frameworks.coretests.R.drawable.test320x240);
611
612 ArrayList<Uri> uris = new ArrayList<>();
613 uris.add(uri);
614
Matt Pietal46d828c2019-02-05 08:07:07 -0500615 Intent sendIntent = createSendUriIntentWithPreview(uris);
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500616 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500617 sOverrides.isImageType = true;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500618
619 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
620
621 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
622 Mockito.anyBoolean(),
623 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
624
625 MetricsLogger mockLogger = sOverrides.metricsLogger;
626 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
627 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
628 waitForIdle();
629 verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
630 // First invocation is from onCreate
631 assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500632 is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500633 assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
634 is(CONTENT_PREVIEW_IMAGE));
635 assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500636 is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500637 assertThat(logMakerCaptor.getAllValues().get(2).getSubtype(),
638 is(CONTENT_PREVIEW_IMAGE));
639 }
640
Matt Pietal46d828c2019-02-05 08:07:07 -0500641 @Test
642 public void oneVisibleFilePreview() throws InterruptedException {
643 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
644
645 ArrayList<Uri> uris = new ArrayList<>();
646 uris.add(uri);
647
648 Intent sendIntent = createSendUriIntentWithPreview(uris);
649
650 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
651
652 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
653 Mockito.anyBoolean(),
654 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
655 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
656 waitForIdle();
657 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
658 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
659 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
660 }
661
662
663 @Test
664 public void moreThanOneVisibleFilePreview() throws InterruptedException {
665 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
666
667 ArrayList<Uri> uris = new ArrayList<>();
668 uris.add(uri);
669 uris.add(uri);
670 uris.add(uri);
671
672 Intent sendIntent = createSendUriIntentWithPreview(uris);
673
674 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
675
676 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
677 Mockito.anyBoolean(),
678 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
679 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
680 waitForIdle();
681 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
682 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 2 files")));
683 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
684 }
685
Matt Pietalf38e9d22019-02-15 10:01:03 -0500686 @Test
687 public void contentProviderThrowSecurityException() throws InterruptedException {
688 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
689
690 ArrayList<Uri> uris = new ArrayList<>();
691 uris.add(uri);
692
693 Intent sendIntent = createSendUriIntentWithPreview(uris);
694
695 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
696 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
697 Mockito.anyBoolean(),
698 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
699
700 sOverrides.resolverForceException = true;
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")));
706 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
707 }
708
709 @Test
710 public void contentProviderReturnsNoColumns() throws InterruptedException {
711 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
712
713 ArrayList<Uri> uris = new ArrayList<>();
714 uris.add(uri);
715 uris.add(uri);
716
717 Intent sendIntent = createSendUriIntentWithPreview(uris);
718
719 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
720 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
721 Mockito.anyBoolean(),
722 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
723
724 Cursor cursor = mock(Cursor.class);
725 when(cursor.getCount()).thenReturn(1);
726 Mockito.doNothing().when(cursor).close();
727 when(cursor.moveToFirst()).thenReturn(true);
728 when(cursor.getColumnIndex(Mockito.anyString())).thenReturn(-1);
729
730 sOverrides.resolverCursor = cursor;
731
732 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
733 waitForIdle();
734 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
735 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 1 file")));
736 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
737 }
738
Matt Pietal26038402019-01-08 07:29:34 -0500739 private Intent createSendTextIntent() {
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800740 Intent sendIntent = new Intent();
741 sendIntent.setAction(Intent.ACTION_SEND);
742 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
Matt Pietalcdfcd9a2019-03-05 08:31:47 -0500743 sendIntent.setType("text/plain");
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800744 return sendIntent;
745 }
746
Matt Pietal26038402019-01-08 07:29:34 -0500747 private Intent createSendTextIntentWithPreview(String title, Uri imageThumbnail) {
748 Intent sendIntent = new Intent();
749 sendIntent.setAction(Intent.ACTION_SEND);
750 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
751 sendIntent.putExtra(Intent.EXTRA_TITLE, title);
752 if (imageThumbnail != null) {
753 ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
754 sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
755 }
756
757 return sendIntent;
758 }
759
Matt Pietal46d828c2019-02-05 08:07:07 -0500760 private Intent createSendUriIntentWithPreview(ArrayList<Uri> uris) {
Matt Pietal0ea391b2019-01-30 10:44:15 -0500761 Intent sendIntent = new Intent();
762
763 if (uris.size() > 1) {
764 sendIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
765 sendIntent.putExtra(Intent.EXTRA_STREAM, uris);
766 } else {
767 sendIntent.setAction(Intent.ACTION_SEND);
768 sendIntent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
769 }
770
771 return sendIntent;
772 }
773
Matt Pietal26038402019-01-08 07:29:34 -0500774 private Intent createViewTextIntent() {
775 Intent viewIntent = new Intent();
776 viewIntent.setAction(Intent.ACTION_VIEW);
777 viewIntent.putExtra(Intent.EXTRA_TEXT, "testing intent viewing");
778 return viewIntent;
779 }
780
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800781 private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
782 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
783 for (int i = 0; i < numberOfResults; i++) {
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800784 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800785 }
786 return infoList;
787 }
788
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800789 private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
790 int numberOfResults) {
791 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
792 for (int i = 0; i < numberOfResults; i++) {
793 if (i == 0) {
794 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
795 } else {
796 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
797 }
798 }
799 return infoList;
800 }
801
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800802 private void waitForIdle() {
803 InstrumentationRegistry.getInstrumentation().waitForIdleSync();
804 }
Matt Pietal26038402019-01-08 07:29:34 -0500805
806 private Bitmap createBitmap() {
807 int width = 200;
808 int height = 200;
809 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
810 Canvas canvas = new Canvas(bitmap);
811
812 Paint paint = new Paint();
813 paint.setColor(Color.RED);
814 paint.setStyle(Paint.Style.FILL);
815 canvas.drawPaint(paint);
816
817 paint.setColor(Color.WHITE);
818 paint.setAntiAlias(true);
819 paint.setTextSize(14.f);
820 paint.setTextAlign(Paint.Align.CENTER);
821 canvas.drawText("Hi!", (width / 2.f), (height / 2.f), paint);
822
823 return bitmap;
824 }
825}