blob: aaa624e6b25eadcf57295e0bb78b89a81ca69c5f [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
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090019import static android.support.test.espresso.Espresso.onView;
20import static android.support.test.espresso.action.ViewActions.click;
21import static android.support.test.espresso.assertion.ViewAssertions.matches;
22import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
23import static android.support.test.espresso.matcher.ViewMatchers.withId;
24import static android.support.test.espresso.matcher.ViewMatchers.withText;
25
26import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
27
28import static org.hamcrest.CoreMatchers.is;
29import static org.hamcrest.CoreMatchers.not;
30import static org.hamcrest.MatcherAssert.assertThat;
31import static org.mockito.Mockito.times;
32import static org.mockito.Mockito.verify;
33import static org.mockito.Mockito.when;
34
35import android.app.usage.UsageStatsManager;
36import android.content.Intent;
37import android.content.pm.ResolveInfo;
38
39import androidx.test.InstrumentationRegistry;
40import androidx.test.rule.ActivityTestRule;
41import androidx.test.runner.AndroidJUnit4;
42
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080043import com.android.internal.R;
44import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
45
46import org.junit.Before;
47import org.junit.Rule;
48import org.junit.Test;
49import org.junit.runner.RunWith;
50import org.mockito.Mockito;
51
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080052import java.util.ArrayList;
53import java.util.List;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080054
55/**
56 * Chooser activity instrumentation tests
57 */
58@RunWith(AndroidJUnit4.class)
59public class ChooserActivityTest {
60 @Rule
61 public ActivityTestRule<ChooserWrapperActivity> mActivityRule =
62 new ActivityTestRule<>(ChooserWrapperActivity.class, false,
63 false);
64
Makoto Onuki99302b52017-03-29 12:42:26 -070065 @Before
66 public void cleanOverrideData() {
67 sOverrides.reset();
68 }
69
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080070 @Test
71 public void customTitle() throws InterruptedException {
72 Intent sendIntent = createSendImageIntent();
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -080073 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
74
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080075 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
76 Mockito.anyBoolean(),
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -080077 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080078 mActivityRule.launchActivity(Intent.createChooser(sendIntent, "chooser test"));
79 waitForIdle();
80 onView(withId(R.id.title)).check(matches(withText("chooser test")));
81 }
82
83 @Test
84 public void emptyTitle() throws InterruptedException {
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080085 Intent sendIntent = createSendImageIntent();
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -080086 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
87
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080088 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
89 Mockito.anyBoolean(),
Hakan Seyalioglu79b69f02017-01-12 17:08:02 -080090 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080091 mActivityRule.launchActivity(Intent.createChooser(sendIntent, null));
92 waitForIdle();
93 onView(withId(R.id.title))
94 .check(matches(withText(R.string.whichSendApplication)));
95 }
96
97 @Test
98 public void twoOptionsAndUserSelectsOne() throws InterruptedException {
99 Intent sendIntent = createSendImageIntent();
100 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
101
102 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
103 Mockito.anyBoolean(),
104 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
105
106 final ChooserWrapperActivity activity = mActivityRule
107 .launchActivity(Intent.createChooser(sendIntent, null));
108 waitForIdle();
109
110 assertThat(activity.getAdapter().getCount(), is(2));
111 onView(withId(R.id.profile_button)).check(matches(not(isDisplayed())));
112
113 ResolveInfo[] chosen = new ResolveInfo[1];
114 sOverrides.onSafelyStartCallback = targetInfo -> {
115 chosen[0] = targetInfo.getResolveInfo();
116 return true;
117 };
118
119 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
120 onView(withText(toChoose.activityInfo.name))
121 .perform(click());
122 waitForIdle();
123 assertThat(chosen[0], is(toChoose));
124 }
125
126 @Test
Kang Li9fa2a2c2017-01-06 13:33:24 -0800127 public void updateChooserCountsAndModelAfterUserSelection() throws InterruptedException {
Kang Li64b018e2017-01-05 17:30:06 -0800128 Intent sendIntent = createSendImageIntent();
129 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
130
131 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
132 Mockito.anyBoolean(),
133 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
134
135 final ChooserWrapperActivity activity = mActivityRule
136 .launchActivity(Intent.createChooser(sendIntent, null));
137 waitForIdle();
138 UsageStatsManager usm = activity.getUsageStatsManager();
139 verify(sOverrides.resolverListController, times(1))
140 .sort(Mockito.any(List.class));
141 assertThat(activity.getIsSelected(), is(false));
142 sOverrides.onSafelyStartCallback = targetInfo -> {
143 return true;
144 };
Kang Li64b018e2017-01-05 17:30:06 -0800145 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
Kang Li64b018e2017-01-05 17:30:06 -0800146 onView(withText(toChoose.activityInfo.name))
147 .perform(click());
148 waitForIdle();
149 verify(sOverrides.resolverListController, times(1))
Kang Li9fa2a2c2017-01-06 13:33:24 -0800150 .updateChooserCounts(Mockito.anyString(), Mockito.anyInt(), Mockito.anyString());
151 verify(sOverrides.resolverListController, times(1))
Kang Li64b018e2017-01-05 17:30:06 -0800152 .updateModel(toChoose.activityInfo.getComponentName());
153 assertThat(activity.getIsSelected(), is(true));
Kang Li64b018e2017-01-05 17:30:06 -0800154 }
155
156 @Test
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800157 public void noResultsFromPackageManager() {
158 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
159 Mockito.anyBoolean(),
160 Mockito.isA(List.class))).thenReturn(null);
161 Intent sendIntent = createSendImageIntent();
162 final ChooserWrapperActivity activity = mActivityRule
163 .launchActivity(Intent.createChooser(sendIntent, null));
164 waitForIdle();
165 assertThat(activity.isFinishing(), is(false));
166
167 onView(withId(R.id.empty)).check(matches(isDisplayed()));
168 onView(withId(R.id.resolver_list)).check(matches(not(isDisplayed())));
169 InstrumentationRegistry.getInstrumentation().runOnMainSync(
170 () -> activity.getAdapter().handlePackagesChanged()
171 );
172 // backward compatibility. looks like we finish when data is empty after package change
173 assertThat(activity.isFinishing(), is(true));
174 }
175
176 @Test
177 public void autoLaunchSingleResult() throws InterruptedException {
178 ResolveInfo[] chosen = new ResolveInfo[1];
179 sOverrides.onSafelyStartCallback = targetInfo -> {
180 chosen[0] = targetInfo.getResolveInfo();
181 return true;
182 };
183
184 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
185 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
186 Mockito.anyBoolean(),
187 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
188
189 Intent sendIntent = createSendImageIntent();
190 final ChooserWrapperActivity activity = mActivityRule
191 .launchActivity(Intent.createChooser(sendIntent, null));
192 waitForIdle();
193
194 assertThat(chosen[0], is(resolvedComponentInfos.get(0).getResolveInfoAt(0)));
195 assertThat(activity.isFinishing(), is(true));
196 }
197
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800198 @Test
199 public void hasOtherProfileOneOption() throws Exception {
200 Intent sendIntent = createSendImageIntent();
201 List<ResolvedComponentInfo> resolvedComponentInfos =
202 createResolvedComponentsForTestWithOtherProfile(2);
203 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
204
205 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
206 Mockito.anyBoolean(),
207 Mockito.anyBoolean(),
208 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
209
210 final ChooserWrapperActivity activity = mActivityRule
211 .launchActivity(Intent.createChooser(sendIntent, null));
212 waitForIdle();
213
214 // The other entry is filtered to the other profile slot
215 assertThat(activity.getAdapter().getCount(), is(1));
216
217 ResolveInfo[] chosen = new ResolveInfo[1];
218 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
219 chosen[0] = targetInfo.getResolveInfo();
220 return true;
221 };
Makoto Onuki99302b52017-03-29 12:42:26 -0700222
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800223 // Make a stable copy of the components as the original list may be modified
224 List<ResolvedComponentInfo> stableCopy =
225 createResolvedComponentsForTestWithOtherProfile(2);
226 // Check that the "Other Profile" activity is put in the right spot
227 onView(withId(R.id.profile_button)).check(matches(
228 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
229 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
230 .perform(click());
231 waitForIdle();
232 assertThat(chosen[0], is(toChoose));
233 }
234
235 @Test
236 public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
237 Intent sendIntent = createSendImageIntent();
238 List<ResolvedComponentInfo> resolvedComponentInfos =
239 createResolvedComponentsForTestWithOtherProfile(3);
240 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
241
242 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
243 Mockito.anyBoolean(),
244 Mockito.anyBoolean(),
245 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
246 when(ChooserWrapperActivity.sOverrides.resolverListController.getLastChosen())
247 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
248
249 final ChooserWrapperActivity activity = mActivityRule
250 .launchActivity(Intent.createChooser(sendIntent, null));
251 waitForIdle();
252
253 // The other entry is filtered to the other profile slot
254 assertThat(activity.getAdapter().getCount(), is(2));
255
256 ResolveInfo[] chosen = new ResolveInfo[1];
257 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
258 chosen[0] = targetInfo.getResolveInfo();
259 return true;
260 };
261
262 // Make a stable copy of the components as the original list may be modified
263 List<ResolvedComponentInfo> stableCopy =
264 createResolvedComponentsForTestWithOtherProfile(3);
265 // Check that the "Other Profile" activity is put in the right spot
266 onView(withId(R.id.profile_button)).check(matches(
267 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
268 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
269 .perform(click());
270 waitForIdle();
271 assertThat(chosen[0], is(toChoose));
272 }
273
274 @Test
275 public void hasLastChosenActivityAndOtherProfile() throws Exception {
276 Intent sendIntent = createSendImageIntent();
277 List<ResolvedComponentInfo> resolvedComponentInfos =
278 createResolvedComponentsForTestWithOtherProfile(3);
279 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
280
281 when(ChooserWrapperActivity.sOverrides.resolverListController.getResolversForIntent(
282 Mockito.anyBoolean(),
283 Mockito.anyBoolean(),
284 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
285
286 final ChooserWrapperActivity activity = mActivityRule
287 .launchActivity(Intent.createChooser(sendIntent, null));
288 waitForIdle();
289
290 // The other entry is filtered to the last used slot
291 assertThat(activity.getAdapter().getCount(), is(2));
292
293 ResolveInfo[] chosen = new ResolveInfo[1];
294 ChooserWrapperActivity.sOverrides.onSafelyStartCallback = targetInfo -> {
295 chosen[0] = targetInfo.getResolveInfo();
296 return true;
297 };
298
299 // Make a stable copy of the components as the original list may be modified
300 List<ResolvedComponentInfo> stableCopy =
301 createResolvedComponentsForTestWithOtherProfile(3);
302 // Check that the "Other Profile" activity is put in the right spot
303 onView(withId(R.id.profile_button)).check(matches(
304 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
305 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
306 .perform(click());
307 waitForIdle();
308 assertThat(chosen[0], is(toChoose));
309 }
310
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800311 private Intent createSendImageIntent() {
312 Intent sendIntent = new Intent();
313 sendIntent.setAction(Intent.ACTION_SEND);
314 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
315 sendIntent.setType("image/jpeg");
316 return sendIntent;
317 }
318
319 private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
320 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
321 for (int i = 0; i < numberOfResults; i++) {
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800322 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800323 }
324 return infoList;
325 }
326
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800327 private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
328 int numberOfResults) {
329 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
330 for (int i = 0; i < numberOfResults; i++) {
331 if (i == 0) {
332 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
333 } else {
334 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
335 }
336 }
337 return infoList;
338 }
339
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800340 private void waitForIdle() {
341 InstrumentationRegistry.getInstrumentation().waitForIdleSync();
342 }
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800343}