blob: 344c28679568da6ac831452db09a6076dc21bf0f [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);
119 final View resolverList = activity.findViewById(R.id.resolver_list);
120 final int initialResolverHeight = resolverList.getHeight();
121
122 activity.runOnUiThread(() -> {
123 ResolverDrawerLayout layout = (ResolverDrawerLayout)
124 activity.findViewById(
125 R.id.contentPanel);
126 ((ResolverDrawerLayout.LayoutParams) resolverList.getLayoutParams()).maxHeight
127 = initialResolverHeight - 1;
128 // Force a relayout
129 layout.invalidate();
130 layout.requestLayout();
131 });
132 waitForIdle();
133 assertThat("Drawer should be capped at maxHeight",
134 resolverList.getHeight() == (initialResolverHeight - 1));
135
136 activity.runOnUiThread(() -> {
137 ResolverDrawerLayout layout = (ResolverDrawerLayout)
138 activity.findViewById(
139 R.id.contentPanel);
140 ((ResolverDrawerLayout.LayoutParams) resolverList.getLayoutParams()).maxHeight
141 = 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",
148 resolverList.getHeight() == initialResolverHeight);
149 }
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);
163 final View resolverList = activity.findViewById(R.id.resolver_list);
164 final RelativeLayout profileView =
165 (RelativeLayout) activity.findViewById(R.id.profile_button).getParent();
166 assertThat("Drawer should show at bottom by default",
167 profileView.getBottom() == resolverList.getTop() && profileView.getTop() > 0);
168
169 activity.runOnUiThread(() -> {
170 ResolverDrawerLayout layout = (ResolverDrawerLayout)
171 activity.findViewById(
172 R.id.contentPanel);
173 layout.setShowAtTop(true);
174 });
175 waitForIdle();
176 assertThat("Drawer should show at top with new attribute",
177 profileView.getBottom() == resolverList.getTop() && profileView.getTop() == 0);
178 }
179
180 @Test
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800181 public void hasLastChosenActivity() throws Exception {
182 Intent sendIntent = createSendImageIntent();
183 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800184 ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800185
186 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
187 Mockito.anyBoolean(),
188 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
189 when(sOverrides.resolverListController.getLastChosen())
190 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
191
192 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
193 waitForIdle();
194
195 // The other entry is filtered to the last used slot
196 assertThat(activity.getAdapter().getCount(), is(1));
Sumir Katariadb688af2017-05-10 17:33:47 -0700197 assertThat(activity.getAdapter().getPlaceholderCount(), is(1));
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800198
199 ResolveInfo[] chosen = new ResolveInfo[1];
200 sOverrides.onSafelyStartCallback = targetInfo -> {
201 chosen[0] = targetInfo.getResolveInfo();
202 return true;
203 };
204
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800205 onView(withId(R.id.button_once)).perform(click());
206 waitForIdle();
207 assertThat(chosen[0], is(toChoose));
208 }
209
210 @Test
211 public void hasOtherProfileOneOption() throws Exception {
212 Intent sendIntent = createSendImageIntent();
213 List<ResolvedComponentInfo> resolvedComponentInfos =
214 createResolvedComponentsForTestWithOtherProfile(2);
215 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
216
217 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
218 Mockito.anyBoolean(),
219 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
220
221 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
arangelovb0802dc2019-10-18 18:03:44 +0100222 Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800223 waitForIdle();
224
225 // The other entry is filtered to the last used slot
226 assertThat(activity.getAdapter().getCount(), is(1));
227
228 ResolveInfo[] chosen = new ResolveInfo[1];
229 sOverrides.onSafelyStartCallback = targetInfo -> {
230 chosen[0] = targetInfo.getResolveInfo();
231 return true;
232 };
233
234 // Make a stable copy of the components as the original list may be modified
235 List<ResolvedComponentInfo> stableCopy =
236 createResolvedComponentsForTestWithOtherProfile(2);
237 // Check that the "Other Profile" activity is put in the right spot
238 onView(withId(R.id.profile_button)).check(matches(
239 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
240 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
241 .perform(click());
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800242 onView(withId(R.id.button_once))
243 .perform(click());
244 waitForIdle();
245 assertThat(chosen[0], is(toChoose));
246 }
247
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800248 @Test
249 public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
250 Intent sendIntent = createSendImageIntent();
251 List<ResolvedComponentInfo> resolvedComponentInfos =
252 createResolvedComponentsForTestWithOtherProfile(3);
253 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
254
255 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
256 Mockito.anyBoolean(),
257 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
258
259 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
arangelovb0802dc2019-10-18 18:03:44 +0100260 Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800261 waitForIdle();
262
263 // The other entry is filtered to the other profile slot
264 assertThat(activity.getAdapter().getCount(), is(2));
265
266 ResolveInfo[] chosen = new ResolveInfo[1];
267 sOverrides.onSafelyStartCallback = targetInfo -> {
268 chosen[0] = targetInfo.getResolveInfo();
269 return true;
270 };
271
272 // Confirm that the button bar is disabled by default
273 onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
274
275 // Make a stable copy of the components as the original list may be modified
276 List<ResolvedComponentInfo> stableCopy =
277 createResolvedComponentsForTestWithOtherProfile(2);
278
279 // Check that the "Other Profile" activity is put in the right spot
280 onView(withId(R.id.profile_button)).check(matches(
281 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
282 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
283 .perform(click());
284 onView(withId(R.id.button_once)).perform(click());
285 waitForIdle();
286 assertThat(chosen[0], is(toChoose));
287 }
288
289
290 @Test
291 public void hasLastChosenActivityAndOtherProfile() throws Exception {
292 // In this case we prefer the other profile and don't display anything about the last
293 // chosen activity.
294 Intent sendIntent = createSendImageIntent();
295 List<ResolvedComponentInfo> resolvedComponentInfos =
296 createResolvedComponentsForTestWithOtherProfile(3);
297 ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
298
299 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
300 Mockito.anyBoolean(),
301 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
302 when(sOverrides.resolverListController.getLastChosen())
303 .thenReturn(resolvedComponentInfos.get(1).getResolveInfoAt(0));
304
305 final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
arangelovb0802dc2019-10-18 18:03:44 +0100306 Espresso.registerIdlingResources(activity.getAdapter().getLabelIdlingResource());
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800307 waitForIdle();
308
309 // The other entry is filtered to the other profile slot
310 assertThat(activity.getAdapter().getCount(), is(2));
311
312 ResolveInfo[] chosen = new ResolveInfo[1];
313 sOverrides.onSafelyStartCallback = targetInfo -> {
314 chosen[0] = targetInfo.getResolveInfo();
315 return true;
316 };
317
318 // Confirm that the button bar is disabled by default
319 onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
320
321 // Make a stable copy of the components as the original list may be modified
322 List<ResolvedComponentInfo> stableCopy =
323 createResolvedComponentsForTestWithOtherProfile(2);
324
325 // Check that the "Other Profile" activity is put in the right spot
326 onView(withId(R.id.profile_button)).check(matches(
327 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
328 onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
329 .perform(click());
330 onView(withId(R.id.button_once)).perform(click());
331 waitForIdle();
332 assertThat(chosen[0], is(toChoose));
333 }
334
Mike Digmanba232682019-03-27 14:55:26 -0700335 @Test
336 public void getActivityLabelAndSubLabel() throws Exception {
337 ActivityInfoPresentationGetter pg;
338 PackageManagerMockedInfo info;
339
340 info = createPackageManagerMockedInfo(false);
341 pg = new ActivityInfoPresentationGetter(
342 info.ctx, 0, info.activityInfo);
343 assertThat("Label should match app label", pg.getLabel().equals(
344 info.setAppLabel));
345 assertThat("Sublabel should match activity label if set",
346 pg.getSubLabel().equals(info.setActivityLabel));
347
348 info = createPackageManagerMockedInfo(true);
349 pg = new ActivityInfoPresentationGetter(
350 info.ctx, 0, info.activityInfo);
351 assertThat("With override permission label should match activity label if set",
352 pg.getLabel().equals(info.setActivityLabel));
353 assertThat("With override permission sublabel should be empty",
354 TextUtils.isEmpty(pg.getSubLabel()));
355 }
356
357 @Test
358 public void getResolveInfoLabelAndSubLabel() throws Exception {
359 ResolveInfoPresentationGetter pg;
360 PackageManagerMockedInfo info;
361
362 info = createPackageManagerMockedInfo(false);
363 pg = new ResolveInfoPresentationGetter(
364 info.ctx, 0, info.resolveInfo);
365 assertThat("Label should match app label", pg.getLabel().equals(
366 info.setAppLabel));
367 assertThat("Sublabel should match resolve info label if set",
368 pg.getSubLabel().equals(info.setResolveInfoLabel));
369
370 info = createPackageManagerMockedInfo(true);
371 pg = new ResolveInfoPresentationGetter(
372 info.ctx, 0, info.resolveInfo);
373 assertThat("With override permission label should match resolve info label if set",
374 pg.getLabel().equals(info.setResolveInfoLabel));
375 assertThat("With override permission sublabel should be empty",
376 TextUtils.isEmpty(pg.getSubLabel()));
377 }
378
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800379 private Intent createSendImageIntent() {
380 Intent sendIntent = new Intent();
381 sendIntent.setAction(Intent.ACTION_SEND);
382 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
383 sendIntent.setType("image/jpeg");
384 return sendIntent;
385 }
386
387 private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
388 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
389 for (int i = 0; i < numberOfResults; i++) {
390 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
391 }
392 return infoList;
393 }
394
Hakan Seyalioglu13405c52017-01-31 19:01:31 -0800395 private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
396 int numberOfResults) {
397 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
398 for (int i = 0; i < numberOfResults; i++) {
399 if (i == 0) {
400 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
401 } else {
402 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
403 }
404 }
405 return infoList;
406 }
407
Hakan Seyalioglu9149dca2017-01-17 12:20:01 -0800408 private void waitForIdle() {
409 InstrumentationRegistry.getInstrumentation().waitForIdleSync();
410 }
Ben Lin93b86972017-10-25 11:38:40 -0700411}