blob: 767ec0e38a865c8987c47803aa73c2ea809c5c15 [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;
Matt Pietal74c6ed02019-04-18 13:38:46 -040021import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
Matt Pietal26038402019-01-08 07:29:34 -050022import static androidx.test.espresso.assertion.ViewAssertions.matches;
23import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
24import static androidx.test.espresso.matcher.ViewMatchers.withId;
25import static androidx.test.espresso.matcher.ViewMatchers.withText;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090026
27import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
28
29import static org.hamcrest.CoreMatchers.is;
30import static org.hamcrest.CoreMatchers.not;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050031import static org.hamcrest.CoreMatchers.notNullValue;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090032import static org.hamcrest.MatcherAssert.assertThat;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050033import static org.mockito.Mockito.atLeastOnce;
Matt Pietalf38e9d22019-02-15 10:01:03 -050034import static org.mockito.Mockito.mock;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090035import static org.mockito.Mockito.times;
36import static org.mockito.Mockito.verify;
37import static org.mockito.Mockito.when;
38
39import android.app.usage.UsageStatsManager;
Matt Pietal26038402019-01-08 07:29:34 -050040import android.content.ClipData;
Matt Pietal1fa7d802019-01-30 10:44:15 -050041import android.content.ClipDescription;
42import android.content.ClipboardManager;
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -040043import android.content.ComponentName;
Matt Pietal1fa7d802019-01-30 10:44:15 -050044import android.content.Context;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090045import android.content.Intent;
George Hodulik145b3a52019-03-27 11:18:43 -070046import android.content.pm.PackageManager;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090047import android.content.pm.ResolveInfo;
Matt Pietalf38e9d22019-02-15 10:01:03 -050048import android.database.Cursor;
Matt Pietal26038402019-01-08 07:29:34 -050049import android.graphics.Bitmap;
50import android.graphics.Canvas;
51import android.graphics.Color;
52import android.graphics.Paint;
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -040053import android.graphics.drawable.Icon;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050054import android.metrics.LogMaker;
Matt Pietal26038402019-01-08 07:29:34 -050055import android.net.Uri;
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -040056import android.service.chooser.ChooserTarget;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090057
Matt Pietal26038402019-01-08 07:29:34 -050058import androidx.test.platform.app.InstrumentationRegistry;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090059import androidx.test.rule.ActivityTestRule;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090060
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080061import com.android.internal.R;
62import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050063import com.android.internal.logging.MetricsLogger;
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -050064import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080065
66import org.junit.Before;
67import org.junit.Rule;
68import org.junit.Test;
69import org.junit.runner.RunWith;
George Hodulik145b3a52019-03-27 11:18:43 -070070import org.junit.runners.Parameterized;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050071import org.mockito.ArgumentCaptor;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080072import org.mockito.Mockito;
73
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080074import java.util.ArrayList;
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -040075import java.util.Arrays;
76import java.util.Collection;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080077import java.util.List;
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -040078import java.util.function.Function;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080079
80/**
81 * Chooser activity instrumentation tests
82 */
George Hodulik145b3a52019-03-27 11:18:43 -070083@RunWith(Parameterized.class)
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080084public class ChooserActivityTest {
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -050085
George Hodulik145b3a52019-03-27 11:18:43 -070086 private static final Function<PackageManager, PackageManager> DEFAULT_PM = pm -> pm;
87 private static final Function<PackageManager, PackageManager> NO_APP_PREDICTION_SERVICE_PM =
88 pm -> {
89 PackageManager mock = Mockito.spy(pm);
90 when(mock.getAppPredictionServicePackageName()).thenReturn(null);
91 return mock;
92 };
93
94 @Parameterized.Parameters
95 public static Collection packageManagers() {
96 return Arrays.asList(new Object[][] {
97 {0, "Default PackageManager", DEFAULT_PM},
98 {1, "No App Prediction Service", NO_APP_PREDICTION_SERVICE_PM}
99 });
100 }
101
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500102 private static final int CONTENT_PREVIEW_IMAGE = 1;
103 private static final int CONTENT_PREVIEW_FILE = 2;
104 private static final int CONTENT_PREVIEW_TEXT = 3;
George Hodulik145b3a52019-03-27 11:18:43 -0700105 private Function<PackageManager, PackageManager> mPackageManagerOverride;
106 private int mTestNum;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500107
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800108 @Rule
109 public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
110 new ActivityTestRule<>(ChooserWrapperActivity.class, false,
111 false);
112
George Hodulik145b3a52019-03-27 11:18:43 -0700113 public ChooserActivityTest(
114 int testNum,
115 String testName,
116 Function<PackageManager, PackageManager> packageManagerOverride) {
117 mPackageManagerOverride = packageManagerOverride;
118 mTestNum = testNum;
119 }
120
Makoto Onuki99302b52017-03-29 12:42:26 -0700121 @Before
122 public void cleanOverrideData() {
123 sOverrides.reset();
George Hodulik145b3a52019-03-27 11:18:43 -0700124 sOverrides.createPackageManager = mPackageManagerOverride;
Makoto Onuki99302b52017-03-29 12:42:26 -0700125 }
126
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800127 @Test
128 public void customTitle() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500129 Intent viewIntent = createViewTextIntent();
130 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
131
132 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
133 Mockito.anyBoolean(),
134 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Matt Pietal95574b02019-03-13 08:12:25 -0400135 final ChooserWrapperActivity activity = mActivityRule.launchActivity(
136 Intent.createChooser(viewIntent, "chooser test"));
Matt Pietal26038402019-01-08 07:29:34 -0500137
138 waitForIdle();
Matt Pietal95574b02019-03-13 08:12:25 -0400139 assertThat(activity.getAdapter().getCount(), is(2));
140 assertThat(activity.getAdapter().getServiceTargetCount(), is(0));
Matt Pietal26038402019-01-08 07:29:34 -0500141 onView(withId(R.id.title)).check(matches(withText("chooser test")));
142 }
143
144 @Test
145 public void customTitleIgnoredForSendIntents() throws InterruptedException {
146 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800147 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
148
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800149 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
150 Mockito.anyBoolean(),
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800151 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800152 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "chooser test"));
153 waitForIdle();
Matt Pietal26038402019-01-08 07:29:34 -0500154 onView(withId(R.id.title)).check(matches(withText(R.string.whichSendApplication)));
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800155 }
156
157 @Test
158 public void emptyTitle() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500159 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800160 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
161
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800162 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
163 Mockito.anyBoolean(),
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -0800164 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800165 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
166 waitForIdle();
167 onView(withId(R.id.title))
168 .check(matches(withText(R.string.whichSendApplication)));
169 }
170
171 @Test
Matt Pietal26038402019-01-08 07:29:34 -0500172 public void emptyPreviewTitleAndThumbnail() throws InterruptedException {
173 Intent sendIntent = createSendTextIntentWithPreview(null, null);
174 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
175
176 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
177 Mockito.anyBoolean(),
178 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
179 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
180 waitForIdle();
181 onView(withId(R.id.content_preview_title)).check(matches(not(isDisplayed())));
182 onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
183 }
184
185 @Test
186 public void visiblePreviewTitleWithoutThumbnail() throws InterruptedException {
187 String previewTitle = "My Content Preview Title";
188 Intent sendIntent = createSendTextIntentWithPreview(previewTitle, null);
189 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
190
191 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
192 Mockito.anyBoolean(),
193 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
194 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
195 waitForIdle();
196 onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
197 onView(withId(R.id.content_preview_title)).check(matches(withText(previewTitle)));
198 onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
199 }
200
201 @Test
202 public void visiblePreviewTitleWithInvalidThumbnail() throws InterruptedException {
203 String previewTitle = "My Content Preview Title";
204 Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
205 Uri.parse("tel:(+49)12345789"));
206 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
207
208 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
209 Mockito.anyBoolean(),
210 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
211 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
212 waitForIdle();
213 onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
214 onView(withId(R.id.content_preview_thumbnail)).check(matches(not(isDisplayed())));
215 }
216
217 @Test
218 public void visiblePreviewTitleAndThumbnail() throws InterruptedException {
219 String previewTitle = "My Content Preview Title";
220 Intent sendIntent = createSendTextIntentWithPreview(previewTitle,
221 Uri.parse("android.resource://com.android.frameworks.coretests/"
222 + com.android.frameworks.coretests.R.drawable.test320x240));
223 sOverrides.previewThumbnail = createBitmap();
224 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
225
226 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
227 Mockito.anyBoolean(),
228 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
229 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
230 waitForIdle();
231 onView(withId(R.id.content_preview_title)).check(matches(isDisplayed()));
232 onView(withId(R.id.content_preview_thumbnail)).check(matches(isDisplayed()));
233 }
234
235 @Test
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800236 public void twoOptionsAndUserSelectsOne() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500237 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800238 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
239
240 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
241 Mockito.anyBoolean(),
242 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
243
244 final ChooserWrapperActivity activity = mActivityRule
245 .launchActivity(Intent.createChooser(sendIntent, null));
246 waitForIdle();
247
248 assertThat(activity.getAdapter().getCount(), is(2));
Matt Pietal74c6ed02019-04-18 13:38:46 -0400249 onView(withId(R.id.profile_button)).check(doesNotExist());
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800250
251 ResolveInfo[] chosen = new ResolveInfo[1];
252 sOverrides.onSafelyStartCallback = targetInfo -> {
253 chosen[0] = targetInfo.getResolveInfo();
254 return true;
255 };
256
257 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
258 onView(withText(toChoose.activityInfo.name))
259 .perform(click());
260 waitForIdle();
261 assertThat(chosen[0], is(toChoose));
262 }
263
264 @Test
Kang Li9fa2a2c2017-01-06 13:33:24 -0800265 public void updateChooserCountsAndModelAfterUserSelection() throws InterruptedException {
Matt Pietal26038402019-01-08 07:29:34 -0500266 Intent sendIntent = createSendTextIntent();
Kang Li64b018e2017-01-05 17:30:06 -0800267 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
268
269 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
270 Mockito.anyBoolean(),
271 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
272
273 final ChooserWrapperActivity activity = mActivityRule
274 .launchActivity(Intent.createChooser(sendIntent, null));
275 waitForIdle();
276 UsageStatsManager usm = activity.getUsageStatsManager();
277 verify(sOverrides.resolverListController, times(1))
278 .sort(Mockito.any(List.class));
279 assertThat(activity.getIsSelected(), is(false));
280 sOverrides.onSafelyStartCallback = targetInfo -> {
281 return true;
282 };
Kang Li64b018e2017-01-05 17:30:06 -0800283 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
Kang Li64b018e2017-01-05 17:30:06 -0800284 onView(withText(toChoose.activityInfo.name))
285 .perform(click());
286 waitForIdle();
287 verify(sOverrides.resolverListController, times(1))
Kang Li9fa2a2c2017-01-06 13:33:24 -0800288 .updateChooserCounts(Mockito.anyString(), Mockito.anyInt(), Mockito.anyString());
289 verify(sOverrides.resolverListController, times(1))
Kang Li64b018e2017-01-05 17:30:06 -0800290 .updateModel(toChoose.activityInfo.getComponentName());
291 assertThat(activity.getIsSelected(), is(true));
Kang Li64b018e2017-01-05 17:30:06 -0800292 }
293
294 @Test
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800295 public void noResultsFromPackageManager() {
296 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
297 Mockito.anyBoolean(),
298 Mockito.isA(List.class))).thenReturn(null);
Matt Pietal26038402019-01-08 07:29:34 -0500299 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800300 final ChooserWrapperActivity activity = mActivityRule
301 .launchActivity(Intent.createChooser(sendIntent, null));
302 waitForIdle();
303 assertThat(activity.isFinishing(), is(false));
304
305 onView(withId(R.id.empty)).check(matches(isDisplayed()));
306 onView(withId(R.id.resolver_list)).check(matches(not(isDisplayed())));
307 InstrumentationRegistry.getInstrumentation().runOnMainSync(
308 () -> activity.getAdapter().handlePackagesChanged()
309 );
310 // backward compatibility. looks like we finish when data is empty after package change
311 assertThat(activity.isFinishing(), is(true));
312 }
313
314 @Test
315 public void autoLaunchSingleResult() throws InterruptedException {
316 ResolveInfo[] chosen = new ResolveInfo[1];
317 sOverrides.onSafelyStartCallback = targetInfo -> {
318 chosen[0] = targetInfo.getResolveInfo();
319 return true;
320 };
321
322 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
323 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
324 Mockito.anyBoolean(),
325 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
326
Matt Pietal26038402019-01-08 07:29:34 -0500327 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800328 final ChooserWrapperActivity activity = mActivityRule
329 .launchActivity(Intent.createChooser(sendIntent, null));
330 waitForIdle();
331
332 assertThat(chosen[0], is(resolvedComponentInfos.get(0).getResolveInfoAt(0)));
333 assertThat(activity.isFinishing(), is(true));
334 }
335
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800336 @Test
337 public void hasOtherProfileOneOption() throws Exception {
Matt Pietal26038402019-01-08 07:29:34 -0500338 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800339 List<ResolvedComponentInfo> resolvedComponentInfos =
340 createResolvedComponentsForTestWithOtherProfile(2);
341 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
342
343 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
344 Mockito.anyBoolean(),
345 Mockito.anyBoolean(),
346 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
347
348 final ChooserWrapperActivity activity = mActivityRule
349 .launchActivity(Intent.createChooser(sendIntent, null));
350 waitForIdle();
351
352 // The other entry is filtered to the other profile slot
353 assertThat(activity.getAdapter().getCount(), is(1));
354
355 ResolveInfo[] chosen = new ResolveInfo[1];
356 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
357 chosen[0] = targetInfo.getResolveInfo();
358 return true;
359 };
Makoto Onuki99302b52017-03-29 12:42:26 -0700360
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800361 // Make a stable copy of the components as the original list may be modified
362 List<ResolvedComponentInfo> stableCopy =
363 createResolvedComponentsForTestWithOtherProfile(2);
364 // Check that the "Other Profile" activity is put in the right spot
365 onView(withId(R.id.profile_button)).check(matches(
366 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
367 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
368 .perform(click());
369 waitForIdle();
370 assertThat(chosen[0], is(toChoose));
371 }
372
373 @Test
374 public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
Matt Pietal26038402019-01-08 07:29:34 -0500375 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800376 List<ResolvedComponentInfo> resolvedComponentInfos =
377 createResolvedComponentsForTestWithOtherProfile(3);
378 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
379
380 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
381 Mockito.anyBoolean(),
382 Mockito.anyBoolean(),
383 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
384 when(ChooserWrapperActivity.sOverrides.resolverListController.getLastChosen())
385 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
386
387 final ChooserWrapperActivity activity = mActivityRule
388 .launchActivity(Intent.createChooser(sendIntent, null));
389 waitForIdle();
390
391 // The other entry is filtered to the other profile slot
392 assertThat(activity.getAdapter().getCount(), is(2));
393
394 ResolveInfo[] chosen = new ResolveInfo[1];
395 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
396 chosen[0] = targetInfo.getResolveInfo();
397 return true;
398 };
399
400 // Make a stable copy of the components as the original list may be modified
401 List<ResolvedComponentInfo> stableCopy =
402 createResolvedComponentsForTestWithOtherProfile(3);
403 // Check that the "Other Profile" activity is put in the right spot
404 onView(withId(R.id.profile_button)).check(matches(
405 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
406 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
407 .perform(click());
408 waitForIdle();
409 assertThat(chosen[0], is(toChoose));
410 }
411
412 @Test
413 public void hasLastChosenActivityAndOtherProfile() throws Exception {
Matt Pietal26038402019-01-08 07:29:34 -0500414 Intent sendIntent = createSendTextIntent();
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800415 List<ResolvedComponentInfo> resolvedComponentInfos =
416 createResolvedComponentsForTestWithOtherProfile(3);
417 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
418
419 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
420 Mockito.anyBoolean(),
421 Mockito.anyBoolean(),
422 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
423
424 final ChooserWrapperActivity activity = mActivityRule
425 .launchActivity(Intent.createChooser(sendIntent, null));
426 waitForIdle();
427
428 // The other entry is filtered to the last used slot
429 assertThat(activity.getAdapter().getCount(), is(2));
430
431 ResolveInfo[] chosen = new ResolveInfo[1];
432 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
433 chosen[0] = targetInfo.getResolveInfo();
434 return true;
435 };
436
437 // Make a stable copy of the components as the original list may be modified
438 List<ResolvedComponentInfo> stableCopy =
439 createResolvedComponentsForTestWithOtherProfile(3);
440 // Check that the "Other Profile" activity is put in the right spot
441 onView(withId(R.id.profile_button)).check(matches(
442 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
443 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
444 .perform(click());
445 waitForIdle();
446 assertThat(chosen[0], is(toChoose));
447 }
448
Matt Pietal1fa7d802019-01-30 10:44:15 -0500449 @Test
450 public void copyTextToClipboard() throws Exception {
451 Intent sendIntent = createSendTextIntent();
Matt Pietal46d828c2019-02-05 08:07:07 -0500452 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
Matt Pietal1fa7d802019-01-30 10:44:15 -0500453
454 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500455 Mockito.anyBoolean(),
456 Mockito.anyBoolean(),
457 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Matt Pietal1fa7d802019-01-30 10:44:15 -0500458
459 final ChooserWrapperActivity activity = mActivityRule
460 .launchActivity(Intent.createChooser(sendIntent, null));
461 waitForIdle();
462
Matt Pietal46d828c2019-02-05 08:07:07 -0500463 onView(withId(R.id.copy_button)).check(matches(isDisplayed()));
Matt Pietal1fa7d802019-01-30 10:44:15 -0500464 onView(withId(R.id.copy_button)).perform(click());
Matt Pietal1fa7d802019-01-30 10:44:15 -0500465 ClipboardManager clipboard = (ClipboardManager) activity.getSystemService(
466 Context.CLIPBOARD_SERVICE);
467 ClipData clipData = clipboard.getPrimaryClip();
468 assertThat("testing intent sending", is(clipData.getItemAt(0).getText()));
469
470 ClipDescription clipDescription = clipData.getDescription();
471 assertThat("text/plain", is(clipDescription.getMimeType(0)));
472 }
473
Matt Pietal0ea391b2019-01-30 10:44:15 -0500474 @Test
475 public void oneVisibleImagePreview() throws InterruptedException {
476 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
477 + com.android.frameworks.coretests.R.drawable.test320x240);
478
479 ArrayList<Uri> uris = new ArrayList<>();
480 uris.add(uri);
481
Matt Pietal46d828c2019-02-05 08:07:07 -0500482 Intent sendIntent = createSendUriIntentWithPreview(uris);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500483 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500484 sOverrides.isImageType = true;
Matt Pietal0ea391b2019-01-30 10:44:15 -0500485
486 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
487
488 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
489 Mockito.anyBoolean(),
490 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
491 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
492 waitForIdle();
493 onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
494 onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed())));
495 onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed())));
496 onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed())));
497 }
498
499 @Test
500 public void twoVisibleImagePreview() throws InterruptedException {
501 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
502 + com.android.frameworks.coretests.R.drawable.test320x240);
503
504 ArrayList<Uri> uris = new ArrayList<>();
505 uris.add(uri);
506 uris.add(uri);
507
Matt Pietal46d828c2019-02-05 08:07:07 -0500508 Intent sendIntent = createSendUriIntentWithPreview(uris);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500509 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500510 sOverrides.isImageType = true;
Matt Pietal0ea391b2019-01-30 10:44:15 -0500511
512 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
513
514 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
515 Mockito.anyBoolean(),
516 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
517 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
518 waitForIdle();
519 onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
520 onView(withId(R.id.content_preview_image_2_large)).check(matches(isDisplayed()));
521 onView(withId(R.id.content_preview_image_2_small)).check(matches(not(isDisplayed())));
522 onView(withId(R.id.content_preview_image_3_small)).check(matches(not(isDisplayed())));
523 }
524
525 @Test
526 public void threeOrMoreVisibleImagePreview() throws InterruptedException {
527 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
528 + com.android.frameworks.coretests.R.drawable.test320x240);
529
530 ArrayList<Uri> uris = new ArrayList<>();
531 uris.add(uri);
532 uris.add(uri);
533 uris.add(uri);
534 uris.add(uri);
535 uris.add(uri);
536
Matt Pietal46d828c2019-02-05 08:07:07 -0500537 Intent sendIntent = createSendUriIntentWithPreview(uris);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500538 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500539 sOverrides.isImageType = true;
Matt Pietal0ea391b2019-01-30 10:44:15 -0500540
541 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
542
543 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500544 Mockito.anyBoolean(),
545 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Matt Pietal0ea391b2019-01-30 10:44:15 -0500546 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
547 waitForIdle();
548 onView(withId(R.id.content_preview_image_1_large)).check(matches(isDisplayed()));
549 onView(withId(R.id.content_preview_image_2_large)).check(matches(not(isDisplayed())));
550 onView(withId(R.id.content_preview_image_2_small)).check(matches(isDisplayed()));
551 onView(withId(R.id.content_preview_image_3_small)).check(matches(isDisplayed()));
552 }
553
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500554 @Test
555 public void testOnCreateLogging() {
556 Intent sendIntent = createSendTextIntent();
557 sendIntent.setType("TestType");
558
559 MetricsLogger mockLogger = sOverrides.metricsLogger;
560 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
561 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
562 waitForIdle();
563 verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
564 assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500565 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500566 assertThat(logMakerCaptor
567 .getAllValues().get(0)
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500568 .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500569 is(notNullValue()));
570 assertThat(logMakerCaptor
571 .getAllValues().get(0)
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500572 .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500573 is("TestType"));
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500574 assertThat(logMakerCaptor
575 .getAllValues().get(0)
576 .getSubtype(),
577 is(MetricsEvent.PARENT_PROFILE));
578 }
579
580 @Test
581 public void testOnCreateLoggingFromWorkProfile() {
582 Intent sendIntent = createSendTextIntent();
583 sendIntent.setType("TestType");
584 sOverrides.alternateProfileSetting = MetricsEvent.MANAGED_PROFILE;
585 MetricsLogger mockLogger = sOverrides.metricsLogger;
586 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
587 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "logger test"));
588 waitForIdle();
589 verify(mockLogger, atLeastOnce()).write(logMakerCaptor.capture());
590 assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
591 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
592 assertThat(logMakerCaptor
593 .getAllValues().get(0)
594 .getTaggedData(MetricsEvent.FIELD_TIME_TO_APP_TARGETS),
595 is(notNullValue()));
596 assertThat(logMakerCaptor
597 .getAllValues().get(0)
598 .getTaggedData(MetricsEvent.FIELD_SHARESHEET_MIMETYPE),
599 is("TestType"));
600 assertThat(logMakerCaptor
601 .getAllValues().get(0)
602 .getSubtype(),
603 is(MetricsEvent.MANAGED_PROFILE));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500604 }
605
606 @Test
607 public void testEmptyPreviewLogging() {
608 Intent sendIntent = createSendTextIntentWithPreview(null, null);
609
610 MetricsLogger mockLogger = sOverrides.metricsLogger;
611 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
612 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "empty preview logger test"));
613 waitForIdle();
Matt Pietal46d828c2019-02-05 08:07:07 -0500614
615 verify(mockLogger, Mockito.times(1)).write(logMakerCaptor.capture());
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500616 // First invocation is from onCreate
Matt Pietal46d828c2019-02-05 08:07:07 -0500617 assertThat(logMakerCaptor.getAllValues().get(0).getCategory(),
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500618 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_SHOWN));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500619 }
620
621 @Test
622 public void testTitlePreviewLogging() {
623 Intent sendIntent = createSendTextIntentWithPreview("TestTitle", null);
624
625 MetricsLogger mockLogger = sOverrides.metricsLogger;
626 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
Matt Pietal46d828c2019-02-05 08:07:07 -0500627
628 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
629
630 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
631 Mockito.anyBoolean(),
632 Mockito.anyBoolean(),
633 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
634
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500635 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
636 waitForIdle();
Matt Pietalfe28f9a2019-03-22 07:59:58 -0400637 verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500638 // First invocation is from onCreate
639 assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500640 is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500641 assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
642 is(CONTENT_PREVIEW_TEXT));
643 }
644
645 @Test
646 public void testImagePreviewLogging() {
647 Uri uri = Uri.parse("android.resource://com.android.frameworks.coretests/"
648 + com.android.frameworks.coretests.R.drawable.test320x240);
649
650 ArrayList<Uri> uris = new ArrayList<>();
651 uris.add(uri);
652
Matt Pietal46d828c2019-02-05 08:07:07 -0500653 Intent sendIntent = createSendUriIntentWithPreview(uris);
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500654 sOverrides.previewThumbnail = createBitmap();
Matt Pietal46d828c2019-02-05 08:07:07 -0500655 sOverrides.isImageType = true;
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500656
657 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
658
659 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
660 Mockito.anyBoolean(),
661 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
662
663 MetricsLogger mockLogger = sOverrides.metricsLogger;
664 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
665 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
666 waitForIdle();
Matt Pietalfe28f9a2019-03-22 07:59:58 -0400667 verify(mockLogger, Mockito.times(2)).write(logMakerCaptor.capture());
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500668 // First invocation is from onCreate
669 assertThat(logMakerCaptor.getAllValues().get(1).getCategory(),
Susi Kharraz-Post0446fab2019-02-21 09:42:31 -0500670 is(MetricsEvent.ACTION_SHARE_WITH_PREVIEW));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500671 assertThat(logMakerCaptor.getAllValues().get(1).getSubtype(),
672 is(CONTENT_PREVIEW_IMAGE));
Susi Kharraz-Post7e2115d2019-02-01 16:51:22 -0500673 }
674
Matt Pietal46d828c2019-02-05 08:07:07 -0500675 @Test
676 public void oneVisibleFilePreview() throws InterruptedException {
677 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
678
679 ArrayList<Uri> uris = new ArrayList<>();
680 uris.add(uri);
681
682 Intent sendIntent = createSendUriIntentWithPreview(uris);
683
684 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
685
686 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
687 Mockito.anyBoolean(),
688 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
689 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
690 waitForIdle();
691 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
692 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
693 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
694 }
695
696
697 @Test
698 public void moreThanOneVisibleFilePreview() throws InterruptedException {
699 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
700
701 ArrayList<Uri> uris = new ArrayList<>();
702 uris.add(uri);
703 uris.add(uri);
704 uris.add(uri);
705
706 Intent sendIntent = createSendUriIntentWithPreview(uris);
707
708 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
709
710 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
711 Mockito.anyBoolean(),
712 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
713 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
714 waitForIdle();
715 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
716 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 2 files")));
717 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
718 }
719
Matt Pietalf38e9d22019-02-15 10:01:03 -0500720 @Test
721 public void contentProviderThrowSecurityException() throws InterruptedException {
722 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
723
724 ArrayList<Uri> uris = new ArrayList<>();
725 uris.add(uri);
726
727 Intent sendIntent = createSendUriIntentWithPreview(uris);
728
729 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
730 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
731 Mockito.anyBoolean(),
732 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
733
734 sOverrides.resolverForceException = true;
735
736 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
737 waitForIdle();
738 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
739 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf")));
740 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
741 }
742
743 @Test
744 public void contentProviderReturnsNoColumns() throws InterruptedException {
745 Uri uri = Uri.parse("content://com.android.frameworks.coretests/app.pdf");
746
747 ArrayList<Uri> uris = new ArrayList<>();
748 uris.add(uri);
749 uris.add(uri);
750
751 Intent sendIntent = createSendUriIntentWithPreview(uris);
752
753 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
754 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
755 Mockito.anyBoolean(),
756 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
757
758 Cursor cursor = mock(Cursor.class);
759 when(cursor.getCount()).thenReturn(1);
760 Mockito.doNothing().when(cursor).close();
761 when(cursor.moveToFirst()).thenReturn(true);
762 when(cursor.getColumnIndex(Mockito.anyString())).thenReturn(-1);
763
764 sOverrides.resolverCursor = cursor;
765
766 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
767 waitForIdle();
768 onView(withId(R.id.content_preview_filename)).check(matches(isDisplayed()));
769 onView(withId(R.id.content_preview_filename)).check(matches(withText("app.pdf + 1 file")));
770 onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
771 }
772
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400773 // This test is too long and too slow and should not be taken as an example for future tests.
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400774 @Test
775 public void testDirectTargetSelectionLogging() throws InterruptedException {
776 Intent sendIntent = createSendTextIntent();
777 // We need app targets for direct targets to get displayed
778 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
779 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
780 Mockito.anyBoolean(),
781 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
782
783 // Set up resources
784 MetricsLogger mockLogger = sOverrides.metricsLogger;
785 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
786 // Create direct share target
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400787 List<ChooserTarget> serviceTargets = createDirectShareTargets(1, "");
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400788 ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
789
790 // Start activity
791 final ChooserWrapperActivity activity = mActivityRule
792 .launchActivity(Intent.createChooser(sendIntent, null));
793
794 // Insert the direct share target
795 InstrumentationRegistry.getInstrumentation().runOnMainSync(
796 () -> activity.getAdapter().addServiceResults(
797 activity.createTestDisplayResolveInfo(sendIntent,
798 ri,
799 "testLabel",
800 "testInfo",
801 sendIntent),
802 serviceTargets,
803 false)
804 );
805 // Thread.sleep shouldn't be a thing in an integration test but it's
806 // necessary here because of the way the code is structured
807 // TODO: restructure the tests b/129870719
808 Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
809
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400810 assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400811 activity.getAdapter().getCount(), is(3));
812 assertThat("Chooser should have exactly one selectable direct target",
813 activity.getAdapter().getSelectableServiceTargetCount(), is(1));
814 assertThat("The resolver info must match the resolver info used to create the target",
815 activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
816
817 // Click on the direct target
818 String name = serviceTargets.get(0).getTitle().toString();
819 onView(withText(name))
820 .perform(click());
821 waitForIdle();
822
823 // Currently we're seeing 3 invocations
824 // 1. ChooserActivity.onCreate()
825 // 2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
826 // 3. ChooserActivity.startSelected -- which is the one we're after
827 verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
828 assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
829 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
830 String hashedName = (String) logMakerCaptor
831 .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_HASHED_TARGET_NAME);
832 assertThat("Hash is not predictable but must be obfuscated",
833 hashedName, is(not(name)));
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400834 assertThat("The packages shouldn't match for app target and direct target", logMakerCaptor
835 .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(-1));
836 }
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400837
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400838 // This test is too long and too slow and should not be taken as an example for future tests.
839 @Test
840 public void testDirectTargetLoggingWithRankedAppTarget() throws InterruptedException {
841 Intent sendIntent = createSendTextIntent();
842 // We need app targets for direct targets to get displayed
843 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
844 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
845 Mockito.anyBoolean(),
846 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400847
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400848 // Set up resources
849 MetricsLogger mockLogger = sOverrides.metricsLogger;
850 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
851 // Create direct share target
852 List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
853 resolvedComponentInfos.get(0).getResolveInfoAt(0).activityInfo.packageName);
854 ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400855
856 // Start activity
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400857 final ChooserWrapperActivity activity = mActivityRule
858 .launchActivity(Intent.createChooser(sendIntent, null));
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400859
860 // Insert the direct share target
861 InstrumentationRegistry.getInstrumentation().runOnMainSync(
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400862 () -> activity.getAdapter().addServiceResults(
863 activity.createTestDisplayResolveInfo(sendIntent,
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400864 ri,
865 "testLabel",
866 "testInfo",
867 sendIntent),
868 serviceTargets,
869 false)
870 );
871 // Thread.sleep shouldn't be a thing in an integration test but it's
872 // necessary here because of the way the code is structured
873 // TODO: restructure the tests b/129870719
874 Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
875
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400876 assertThat("Chooser should have 3 targets (2 apps, 1 direct)",
877 activity.getAdapter().getCount(), is(3));
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400878 assertThat("Chooser should have exactly one selectable direct target",
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400879 activity.getAdapter().getSelectableServiceTargetCount(), is(1));
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400880 assertThat("The resolver info must match the resolver info used to create the target",
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400881 activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400882
883 // Click on the direct target
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400884 String name = serviceTargets.get(0).getTitle().toString();
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400885 onView(withText(name))
886 .perform(click());
887 waitForIdle();
888
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400889 // Currently we're seeing 3 invocations
890 // 1. ChooserActivity.onCreate()
891 // 2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
892 // 3. ChooserActivity.startSelected -- which is the one we're after
893 verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
894 assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400895 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -0400896 assertThat("The packages should match for app target and direct target", logMakerCaptor
897 .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(0));
898 }
899
900 // This test is too long and too slow and should not be taken as an example for future tests.
901 @Test
902 public void testDirectTargetLoggingWithAppTargetNotRanked() throws InterruptedException {
903 Intent sendIntent = createSendTextIntent();
904 // We need app targets for direct targets to get displayed
905 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(15);
906 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
907 Mockito.anyBoolean(),
908 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
909
910 // Set up resources
911 MetricsLogger mockLogger = sOverrides.metricsLogger;
912 ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
913 // Create direct share target
914 List<ChooserTarget> serviceTargets = createDirectShareTargets(1,
915 resolvedComponentInfos.get(14).getResolveInfoAt(0).activityInfo.packageName);
916 ResolveInfo ri = ResolverDataProvider.createResolveInfo(16, 0);
917
918 // Start activity
919 final ChooserWrapperActivity activity = mActivityRule
920 .launchActivity(Intent.createChooser(sendIntent, null));
921 // Insert the direct share target
922 InstrumentationRegistry.getInstrumentation().runOnMainSync(
923 () -> activity.getAdapter().addServiceResults(
924 activity.createTestDisplayResolveInfo(sendIntent,
925 ri,
926 "testLabel",
927 "testInfo",
928 sendIntent),
929 serviceTargets,
930 false)
931 );
932 // Thread.sleep shouldn't be a thing in an integration test but it's
933 // necessary here because of the way the code is structured
934 // TODO: restructure the tests b/129870719
935 Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
936
937 assertThat("Chooser should have 20 targets (4 apps, 1 direct, 15 A-Z)",
938 activity.getAdapter().getCount(), is(20));
939 assertThat("Chooser should have exactly one selectable direct target",
940 activity.getAdapter().getSelectableServiceTargetCount(), is(1));
941 assertThat("The resolver info must match the resolver info used to create the target",
942 activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
943
944 // Click on the direct target
945 String name = serviceTargets.get(0).getTitle().toString();
946 onView(withText(name))
947 .perform(click());
948 waitForIdle();
949
950 // Currently we're seeing 3 invocations
951 // 1. ChooserActivity.onCreate()
952 // 2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
953 // 3. ChooserActivity.startSelected -- which is the one we're after
954 verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
955 assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
956 is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
957 assertThat("The packages shouldn't match for app target and direct target", logMakerCaptor
958 .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_RANKED_POSITION), is(-1));
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -0400959 }
960
Matt Pietal26038402019-01-08 07:29:34 -0500961 private Intent createSendTextIntent() {
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800962 Intent sendIntent = new Intent();
963 sendIntent.setAction(Intent.ACTION_SEND);
964 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
Matt Pietalcdfcd9a2019-03-05 08:31:47 -0500965 sendIntent.setType("text/plain");
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800966 return sendIntent;
967 }
968
Matt Pietal26038402019-01-08 07:29:34 -0500969 private Intent createSendTextIntentWithPreview(String title, Uri imageThumbnail) {
970 Intent sendIntent = new Intent();
971 sendIntent.setAction(Intent.ACTION_SEND);
972 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
973 sendIntent.putExtra(Intent.EXTRA_TITLE, title);
974 if (imageThumbnail != null) {
975 ClipData.Item clipItem = new ClipData.Item(imageThumbnail);
976 sendIntent.setClipData(new ClipData("Clip Label", new String[]{"image/png"}, clipItem));
977 }
978
979 return sendIntent;
980 }
981
Matt Pietal46d828c2019-02-05 08:07:07 -0500982 private Intent createSendUriIntentWithPreview(ArrayList<Uri> uris) {
Matt Pietal0ea391b2019-01-30 10:44:15 -0500983 Intent sendIntent = new Intent();
984
985 if (uris.size() > 1) {
986 sendIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
987 sendIntent.putExtra(Intent.EXTRA_STREAM, uris);
988 } else {
989 sendIntent.setAction(Intent.ACTION_SEND);
990 sendIntent.putExtra(Intent.EXTRA_STREAM, uris.get(0));
991 }
992
993 return sendIntent;
994 }
995
Matt Pietal26038402019-01-08 07:29:34 -0500996 private Intent createViewTextIntent() {
997 Intent viewIntent = new Intent();
998 viewIntent.setAction(Intent.ACTION_VIEW);
999 viewIntent.putExtra(Intent.EXTRA_TEXT, "testing intent viewing");
1000 return viewIntent;
1001 }
1002
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -08001003 private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
1004 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
1005 for (int i = 0; i < numberOfResults; i++) {
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -08001006 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -08001007 }
1008 return infoList;
1009 }
1010
Hakan Seyalioglu13405c52017-01-31 19:01:31 -08001011 private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
1012 int numberOfResults) {
1013 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
1014 for (int i = 0; i < numberOfResults; i++) {
1015 if (i == 0) {
1016 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
1017 } else {
1018 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
1019 }
1020 }
1021 return infoList;
1022 }
1023
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -04001024 private List<ChooserTarget> createDirectShareTargets(int numberOfResults, String packageName) {
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -04001025 Icon icon = Icon.createWithBitmap(createBitmap());
1026 String testTitle = "testTitle";
1027 List<ChooserTarget> targets = new ArrayList<>();
1028 for (int i = 0; i < numberOfResults; i++) {
Susi Kharraz-Post8c14f772019-04-17 16:33:41 -04001029 ComponentName componentName;
1030 if (packageName.isEmpty()) {
1031 componentName = ResolverDataProvider.createComponentName(i);
1032 } else {
1033 componentName = new ComponentName(packageName, packageName + ".class");
1034 }
Susi Kharraz-Post14cbfcd2019-04-01 11:07:59 -04001035 ChooserTarget tempTarget = new ChooserTarget(
1036 testTitle + i,
1037 icon,
1038 (float) (1 - ((i + 1) / 10.0)),
1039 componentName,
1040 null);
1041 targets.add(tempTarget);
1042 }
1043 return targets;
1044 }
1045
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -08001046 private void waitForIdle() {
1047 InstrumentationRegistry.getInstrumentation().waitForIdleSync();
1048 }
Matt Pietal26038402019-01-08 07:29:34 -05001049
1050 private Bitmap createBitmap() {
1051 int width = 200;
1052 int height = 200;
1053 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
1054 Canvas canvas = new Canvas(bitmap);
1055
1056 Paint paint = new Paint();
1057 paint.setColor(Color.RED);
1058 paint.setStyle(Paint.Style.FILL);
1059 canvas.drawPaint(paint);
1060
1061 paint.setColor(Color.WHITE);
1062 paint.setAntiAlias(true);
1063 paint.setTextSize(14.f);
1064 paint.setTextAlign(Paint.Align.CENTER);
1065 canvas.drawText("Hi!", (width / 2.f), (height / 2.f), paint);
1066
1067 return bitmap;
1068 }
1069}