blob: aab4698fc49a16f49a04038796b4b23b8baf2486 [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
19import com.android.internal.R;
20import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
21
22import org.junit.Before;
23import org.junit.Rule;
24import org.junit.Test;
25import org.junit.runner.RunWith;
26import org.mockito.Mockito;
27
Kang Li64b018e2017-01-05 17:30:06 -080028import android.app.usage.UsageStats;
29import android.app.usage.UsageStatsManager;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080030import android.content.Intent;
31import android.content.pm.ResolveInfo;
Kang Li64b018e2017-01-05 17:30:06 -080032import android.os.UserHandle;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080033import android.support.test.InstrumentationRegistry;
34import android.support.test.rule.ActivityTestRule;
35import android.support.test.runner.AndroidJUnit4;
36
37import java.util.ArrayList;
38import java.util.List;
Kang Li64b018e2017-01-05 17:30:06 -080039import java.util.Map;
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -080040
41import static android.support.test.espresso.Espresso.onView;
42import static android.support.test.espresso.action.ViewActions.click;
43import static android.support.test.espresso.assertion.ViewAssertions.matches;
44import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
45import static android.support.test.espresso.matcher.ViewMatchers.withId;
46import static android.support.test.espresso.matcher.ViewMatchers.withText;
47import static com.android.internal.app.ChooserWrapperActivity.sOverrides;
48import static org.hamcrest.CoreMatchers.is;
49import static org.hamcrest.CoreMatchers.not;
50import static org.hamcrest.MatcherAssert.assertThat;
51import static org.mockito.Mockito.when;
Kang Li64b018e2017-01-05 17:30:06 -080052import static org.mockito.Mockito.verify;
53import static org.mockito.Mockito.times;
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
65 @Before
66 public void cleanOverrideData() {
67 sOverrides.reset();
68 }
69
70 @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
157 public void reportChooserSelection() throws InterruptedException {
158 Intent sendIntent = createSendImageIntent();
159 final ChooserWrapperActivity activity = mActivityRule
160 .launchActivity(Intent.createChooser(sendIntent, null));
161 waitForIdle();
162 UsageStatsManager usm = activity.getUsageStatsManager();
163 String packageName = "test_package";
164 String action = "test_action";
165 String annotation = "test_annotation";
166 long beforeReport = getCount(usm, packageName, action, annotation);
167 usm.reportChooserSelection(packageName, activity.getUserId(), annotation, null, action);
168 long afterReport = getCount(usm, packageName, action, annotation);
169 assertThat(afterReport, is(beforeReport + 1l));
170 }
171
172 @Test
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800173 public void noResultsFromPackageManager() {
174 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
175 Mockito.anyBoolean(),
176 Mockito.isA(List.class))).thenReturn(null);
177 Intent sendIntent = createSendImageIntent();
178 final ChooserWrapperActivity activity = mActivityRule
179 .launchActivity(Intent.createChooser(sendIntent, null));
180 waitForIdle();
181 assertThat(activity.isFinishing(), is(false));
182
183 onView(withId(R.id.empty)).check(matches(isDisplayed()));
184 onView(withId(R.id.resolver_list)).check(matches(not(isDisplayed())));
185 InstrumentationRegistry.getInstrumentation().runOnMainSync(
186 () -> activity.getAdapter().handlePackagesChanged()
187 );
188 // backward compatibility. looks like we finish when data is empty after package change
189 assertThat(activity.isFinishing(), is(true));
190 }
191
192 @Test
193 public void autoLaunchSingleResult() throws InterruptedException {
194 ResolveInfo[] chosen = new ResolveInfo[1];
195 sOverrides.onSafelyStartCallback = targetInfo -> {
196 chosen[0] = targetInfo.getResolveInfo();
197 return true;
198 };
199
200 List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(1);
201 when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
202 Mockito.anyBoolean(),
203 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
204
205 Intent sendIntent = createSendImageIntent();
206 final ChooserWrapperActivity activity = mActivityRule
207 .launchActivity(Intent.createChooser(sendIntent, null));
208 waitForIdle();
209
210 assertThat(chosen[0], is(resolvedComponentInfos.get(0).getResolveInfoAt(0)));
211 assertThat(activity.isFinishing(), is(true));
212 }
213
214 private Intent createSendImageIntent() {
215 Intent sendIntent = new Intent();
216 sendIntent.setAction(Intent.ACTION_SEND);
217 sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
218 sendIntent.setType("image/jpeg");
219 return sendIntent;
220 }
221
222 private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
223 List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
224 for (int i = 0; i < numberOfResults; i++) {
225 infoList.add(ChooserDataProvider.createResolvedComponentInfo(i));
226 }
227 return infoList;
228 }
229
230 private void waitForIdle() {
231 InstrumentationRegistry.getInstrumentation().waitForIdleSync();
232 }
Kang Li64b018e2017-01-05 17:30:06 -0800233
234 private Integer getCount(
235 UsageStatsManager usm, String packageName, String action, String annotation) {
236 if (usm == null) {
237 return 0;
238 }
239 Map<String, UsageStats> stats =
240 usm.queryAndAggregateUsageStats(Long.MIN_VALUE, Long.MAX_VALUE);
241 UsageStats packageStats = stats.get(packageName);
242 if (packageStats == null || packageStats.mChooserCounts == null
243 || packageStats.mChooserCounts.get(action) == null) {
244 return 0;
245 }
246 return packageStats.mChooserCounts.get(action).getOrDefault(annotation, 0);
247 }
Hakan Seyalioglue1276bf2016-12-07 16:38:57 -0800248}