blob: 923ce3e3935dadc865c3bdfc902fc2fda3f87ec6 [file] [log] [blame]
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -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. Takaoka7a4047f2019-02-02 09:55:59 +090019import 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.isEnabled;
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
Mike Digmanba232682019-03-27 14:55:26 -070026import static com.android.internal.app.ResolverDataProvider.createPackageManagerMockedInfo;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090027import static com.android.internal.app.ResolverWrapperActivity.sOverrides;
28
29import static org.hamcrest.CoreMatchers.is;
30import static org.hamcrest.CoreMatchers.not;
31import static org.hamcrest.MatcherAssert.assertThat;
32import static org.mockito.Mockito.when;
33
34import android.content.Intent;
35import android.content.pm.ResolveInfo;
Mike Digmanba232682019-03-27 14:55:26 -070036import android.text.TextUtils;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090037import android.view.View;
38import android.widget.RelativeLayout;
39
40import androidx.test.InstrumentationRegistry;
Zhen Zhangcb55c8a2019-10-22 14:49:09 -070041import androidx.test.espresso.Espresso;
Tadashi G. Takaokab4470f22019-01-15 18:29:15 +090042import androidx.test.rule.ActivityTestRule;
43import androidx.test.runner.AndroidJUnit4;
44
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -080045import com.android.internal.R;
46import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
Mike Digmanba232682019-03-27 14:55:26 -070047import com.android.internal.app.ResolverDataProvider.PackageManagerMockedInfo;
arangelovb0802dc2019-10-18 18:03:44 +010048import com.android.internal.app.ResolverListAdapter.ActivityInfoPresentationGetter;
49import com.android.internal.app.ResolverListAdapter.ResolveInfoPresentationGetter;
Ben Lin93b86972017-10-25 11:38:40 -070050import com.android.internal.widget.ResolverDrawerLayout;
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -080051
52import org.junit.Before;
Alison Cichowlasc1a1bfe2019-11-21 15:52:27 -050053import org.junit.Ignore;
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -080054import org.junit.Rule;
55import org.junit.Test;
56import org.junit.runner.RunWith;
57import org.mockito.Mockito;
58
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -080059import java.util.ArrayList;
60import java.util.List;
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -080061
62/**
63 * Resolver activity instrumentation tests
64 */
65@RunWith(AndroidJUnit4.class)
66public class ResolverActivityTest {
67 @Rule
68 public ActivityTestRule<ResolverWrapperActivity> mActivityRule =
69 new ActivityTestRule<>(ResolverWrapperActivity.class, false,
70 false);
71
72 @Before
73 public void cleanOverrideData() {
74 sOverrides.reset();
75 }
76
77 @Test
78 public void twoOptionsAndUserSelectsOne() throws InterruptedException {
79 Intent sendIntent = createSendImageIntent();
80 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
81
82 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
83 Mockito.anyBoolean(),
84 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
85
86 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
arangelovb0802dc2019-10-18 18:03:44 +010087 Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -080088 waitForIdle();
89
90 assertThat(activity.getAdapter().getCount(), is(2));
91
92 ResolveInfo[] chosen = new ResolveInfo[1];
93 sOverrides.onSafelyStartCallback = targetInfo -> {
94 chosen[0] = targetInfo.getResolveInfo();
95 return true;
96 };
97
98 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
99 onView(withText(toChoose.activityInfo.name))
100 .perform(click());
101 onView(withId(R.id.button_once))
102 .perform(click());
103 waitForIdle();
104 assertThat(chosen[0], is(toChoose));
105 }
106
Alison Cichowlasc1a1bfe2019-11-21 15:52:27 -0500107 @Ignore // Failing - b/144929805
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800108 @Test
Ben Lin058ab3e2018-02-23 11:28:09 -0800109 public void setMaxHeight() throws Exception {
110 Intent sendIntent = createSendImageIntent();
111 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
112
113 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
114 Mockito.anyBoolean(),
115 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
116 waitForIdle();
117
118 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
arangelov2c1c37a2019-12-06 14:43:34 +0000119 final View viewPager = activity.findViewById(R.id.profile_pager);
120 final int initialResolverHeight = viewPager.getHeight();
Ben Lin058ab3e2018-02-23 11:28:09 -0800121
122 activity.runOnUiThread(() -> {
123 ResolverDrawerLayout layout = (ResolverDrawerLayout)
124 activity.findViewById(
125 R.id.contentPanel);
arangelov2c1c37a2019-12-06 14:43:34 +0000126 ((ResolverDrawerLayout.LayoutParams) viewPager.getLayoutParams()).maxHeight
Ben Lin058ab3e2018-02-23 11:28:09 -0800127 = initialResolverHeight - 1;
128 // Force a relayout
129 layout.invalidate();
130 layout.requestLayout();
131 });
132 waitForIdle();
133 assertThat("Drawer should be capped at maxHeight",
arangelov2c1c37a2019-12-06 14:43:34 +0000134 viewPager.getHeight() == (initialResolverHeight - 1));
Ben Lin058ab3e2018-02-23 11:28:09 -0800135
136 activity.runOnUiThread(() -> {
137 ResolverDrawerLayout layout = (ResolverDrawerLayout)
138 activity.findViewById(
139 R.id.contentPanel);
arangelov2c1c37a2019-12-06 14:43:34 +0000140 ((ResolverDrawerLayout.LayoutParams) viewPager.getLayoutParams()).maxHeight
Ben Lin058ab3e2018-02-23 11:28:09 -0800141 = initialResolverHeight + 1;
142 // Force a relayout
143 layout.invalidate();
144 layout.requestLayout();
145 });
146 waitForIdle();
147 assertThat("Drawer should not change height if its height is less than maxHeight",
arangelov2c1c37a2019-12-06 14:43:34 +0000148 viewPager.getHeight() == initialResolverHeight);
Ben Lin058ab3e2018-02-23 11:28:09 -0800149 }
150
Alison Cichowlasc1a1bfe2019-11-21 15:52:27 -0500151 @Ignore // Failing - b/144929805
Ben Lin058ab3e2018-02-23 11:28:09 -0800152 @Test
Ben Lin93b86972017-10-25 11:38:40 -0700153 public void setShowAtTopToTrue() throws Exception {
154 Intent sendIntent = createSendImageIntent();
155 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
156
157 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
158 Mockito.anyBoolean(),
159 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
160 waitForIdle();
161
162 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
arangelov2c1c37a2019-12-06 14:43:34 +0000163 final View viewPager = activity.findViewById(R.id.profile_pager);
164 final View divider = activity.findViewById(R.id.divider);
Ben Lin93b86972017-10-25 11:38:40 -0700165 final RelativeLayout profileView =
166 (RelativeLayout) activity.findViewById(R.id.profile_button).getParent();
167 assertThat("Drawer should show at bottom by default",
arangelov2c1c37a2019-12-06 14:43:34 +0000168 profileView.getBottom() + divider.getHeight() == viewPager.getTop()
169 && profileView.getTop() > 0);
Ben Lin93b86972017-10-25 11:38:40 -0700170
171 activity.runOnUiThread(() -> {
172 ResolverDrawerLayout layout = (ResolverDrawerLayout)
173 activity.findViewById(
174 R.id.contentPanel);
175 layout.setShowAtTop(true);
176 });
177 waitForIdle();
178 assertThat("Drawer should show at top with new attribute",
arangelov2c1c37a2019-12-06 14:43:34 +0000179 profileView.getBottom() + divider.getHeight() == viewPager.getTop()
180 && profileView.getTop() == 0);
Ben Lin93b86972017-10-25 11:38:40 -0700181 }
182
183 @Test
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800184 public void hasLastChosenActivity() throws Exception {
185 Intent sendIntent = createSendImageIntent();
186 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800187 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800188
189 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
190 Mockito.anyBoolean(),
191 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
192 when(sOverrides.resolverListController.getLastChosen())
193 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
194
195 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
196 waitForIdle();
197
198 // The other entry is filtered to the last used slot
199 assertThat(activity.getAdapter().getCount(), is(1));
Sumir Katariadb688af2017-05-10 17:33:47 -0700200 assertThat(activity.getAdapter().getPlaceholderCount(), is(1));
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800201
202 ResolveInfo[] chosen = new ResolveInfo[1];
203 sOverrides.onSafelyStartCallback = targetInfo -> {
204 chosen[0] = targetInfo.getResolveInfo();
205 return true;
206 };
207
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800208 onView(withId(R.id.button_once)).perform(click());
209 waitForIdle();
210 assertThat(chosen[0], is(toChoose));
211 }
212
213 @Test
214 public void hasOtherProfileOneOption() throws Exception {
215 Intent sendIntent = createSendImageIntent();
216 List<ResolvedComponentInfo> resolvedComponentInfos =
217 createResolvedComponentsForTestWithOtherProfile(2);
218 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
219
220 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
221 Mockito.anyBoolean(),
222 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
223
224 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
arangelovb0802dc2019-10-18 18:03:44 +0100225 Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800226 waitForIdle();
227
228 // The other entry is filtered to the last used slot
229 assertThat(activity.getAdapter().getCount(), is(1));
230
231 ResolveInfo[] chosen = new ResolveInfo[1];
232 sOverrides.onSafelyStartCallback = targetInfo -> {
233 chosen[0] = targetInfo.getResolveInfo();
234 return true;
235 };
236
237 // Make a stable copy of the components as the original list may be modified
238 List<ResolvedComponentInfo> stableCopy =
239 createResolvedComponentsForTestWithOtherProfile(2);
240 // Check that the "Other Profile" activity is put in the right spot
241 onView(withId(R.id.profile_button)).check(matches(
242 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
243 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
244 .perform(click());
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800245 onView(withId(R.id.button_once))
246 .perform(click());
247 waitForIdle();
248 assertThat(chosen[0], is(toChoose));
249 }
250
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800251 @Test
252 public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
253 Intent sendIntent = createSendImageIntent();
254 List<ResolvedComponentInfo> resolvedComponentInfos =
255 createResolvedComponentsForTestWithOtherProfile(3);
256 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
257
258 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
259 Mockito.anyBoolean(),
260 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
261
262 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
arangelovb0802dc2019-10-18 18:03:44 +0100263 Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800264 waitForIdle();
265
266 // The other entry is filtered to the other profile slot
267 assertThat(activity.getAdapter().getCount(), is(2));
268
269 ResolveInfo[] chosen = new ResolveInfo[1];
270 sOverrides.onSafelyStartCallback = targetInfo -> {
271 chosen[0] = targetInfo.getResolveInfo();
272 return true;
273 };
274
275 // Confirm that the button bar is disabled by default
276 onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
277
278 // Make a stable copy of the components as the original list may be modified
279 List<ResolvedComponentInfo> stableCopy =
280 createResolvedComponentsForTestWithOtherProfile(2);
281
282 // Check that the "Other Profile" activity is put in the right spot
283 onView(withId(R.id.profile_button)).check(matches(
284 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
285 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
286 .perform(click());
287 onView(withId(R.id.button_once)).perform(click());
288 waitForIdle();
289 assertThat(chosen[0], is(toChoose));
290 }
291
292
293 @Test
294 public void hasLastChosenActivityAndOtherProfile() throws Exception {
295 // In this case we prefer the other profile and don't display anything about the last
296 // chosen activity.
297 Intent sendIntent = createSendImageIntent();
298 List<ResolvedComponentInfo> resolvedComponentInfos =
299 createResolvedComponentsForTestWithOtherProfile(3);
300 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
301
302 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
303 Mockito.anyBoolean(),
304 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
305 when(sOverrides.resolverListController.getLastChosen())
306 .thenReturn(resolvedComponentInfos.get(1).getResolveInfoAt(0));
307
308 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
arangelovb0802dc2019-10-18 18:03:44 +0100309 Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800310 waitForIdle();
311
312 // The other entry is filtered to the other profile slot
313 assertThat(activity.getAdapter().getCount(), is(2));
314
315 ResolveInfo[] chosen = new ResolveInfo[1];
316 sOverrides.onSafelyStartCallback = targetInfo -> {
317 chosen[0] = targetInfo.getResolveInfo();
318 return true;
319 };
320
321 // Confirm that the button bar is disabled by default
322 onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
323
324 // Make a stable copy of the components as the original list may be modified
325 List<ResolvedComponentInfo> stableCopy =
326 createResolvedComponentsForTestWithOtherProfile(2);
327
328 // Check that the "Other Profile" activity is put in the right spot
329 onView(withId(R.id.profile_button)).check(matches(
330 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
331 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
332 .perform(click());
333 onView(withId(R.id.button_once)).perform(click());
334 waitForIdle();
335 assertThat(chosen[0], is(toChoose));
336 }
337
Mike Digmanba232682019-03-27 14:55:26 -0700338 @Test
339 public void getActivityLabelAndSubLabel() throws Exception {
340 ActivityInfoPresentationGetter pg;
341 PackageManagerMockedInfo info;
342
343 info = createPackageManagerMockedInfo(false);
344 pg = new ActivityInfoPresentationGetter(
345 info.ctx, 0, info.activityInfo);
346 assertThat("Label should match app label", pg.getLabel().equals(
347 info.setAppLabel));
348 assertThat("Sublabel should match activity label if set",
349 pg.getSubLabel().equals(info.setActivityLabel));
350
351 info = createPackageManagerMockedInfo(true);
352 pg = new ActivityInfoPresentationGetter(
353 info.ctx, 0, info.activityInfo);
354 assertThat("With override permission label should match activity label if set",
355 pg.getLabel().equals(info.setActivityLabel));
356 assertThat("With override permission sublabel should be empty",
357 TextUtils.isEmpty(pg.getSubLabel()));
358 }
359
360 @Test
361 public void getResolveInfoLabelAndSubLabel() throws Exception {
362 ResolveInfoPresentationGetter pg;
363 PackageManagerMockedInfo info;
364
365 info = createPackageManagerMockedInfo(false);
366 pg = new ResolveInfoPresentationGetter(
367 info.ctx, 0, info.resolveInfo);
368 assertThat("Label should match app label", pg.getLabel().equals(
369 info.setAppLabel));
370 assertThat("Sublabel should match resolve info label if set",
371 pg.getSubLabel().equals(info.setResolveInfoLabel));
372
373 info = createPackageManagerMockedInfo(true);
374 pg = new ResolveInfoPresentationGetter(
375 info.ctx, 0, info.resolveInfo);
376 assertThat("With override permission label should match resolve info label if set",
377 pg.getLabel().equals(info.setResolveInfoLabel));
378 assertThat("With override permission sublabel should be empty",
379 TextUtils.isEmpty(pg.getSubLabel()));
380 }
381
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800382 private Intent createSendImageIntent() {
383 Intent sendIntent = new Intent();
384 sendIntent.setAction(Intent.ACTION_SEND);
385 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
386 sendIntent.setType("image/jpeg");
387 return sendIntent;
388 }
389
390 private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
391 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
392 for (int i = 0; i < numberOfResults; i++) {
393 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
394 }
395 return infoList;
396 }
397
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800398 private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
399 int numberOfResults) {
400 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
401 for (int i = 0; i < numberOfResults; i++) {
402 if (i == 0) {
403 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
404 } else {
405 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
406 }
407 }
408 return infoList;
409 }
410
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800411 private void waitForIdle() {
412 InstrumentationRegistry.getInstrumentation().waitForIdleSync();
413 }
Ben Lin93b86972017-10-25 11:38:40 -0700414}