Home | History | Annotate | Download | only in app
      1 /*
      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 
     17 package com.android.internal.app;
     18 
     19 import com.android.internal.R;
     20 import com.android.internal.app.ResolverActivity.ResolvedComponentInfo;
     21 
     22 import org.junit.Before;
     23 import org.junit.Rule;
     24 import org.junit.Test;
     25 import org.junit.runner.RunWith;
     26 import org.mockito.Mockito;
     27 
     28 import android.app.usage.UsageStats;
     29 import android.app.usage.UsageStatsManager;
     30 import android.content.Intent;
     31 import android.content.pm.ResolveInfo;
     32 import android.os.UserHandle;
     33 import android.support.test.InstrumentationRegistry;
     34 import android.support.test.rule.ActivityTestRule;
     35 import android.support.test.runner.AndroidJUnit4;
     36 
     37 import java.util.ArrayList;
     38 import java.util.List;
     39 import java.util.Map;
     40 
     41 import static android.os.SystemClock.sleep;
     42 import static android.support.test.espresso.Espresso.onView;
     43 import static android.support.test.espresso.action.ViewActions.click;
     44 import static android.support.test.espresso.assertion.ViewAssertions.matches;
     45 import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
     46 import static android.support.test.espresso.matcher.ViewMatchers.isEnabled;
     47 import static android.support.test.espresso.matcher.ViewMatchers.withId;
     48 import static android.support.test.espresso.matcher.ViewMatchers.withText;
     49 import static com.android.internal.app.ResolverWrapperActivity.sOverrides;
     50 import static org.hamcrest.CoreMatchers.is;
     51 import static org.hamcrest.CoreMatchers.not;
     52 import static org.hamcrest.MatcherAssert.assertThat;
     53 import static org.mockito.Mockito.mock;
     54 import static org.mockito.Mockito.times;
     55 import static org.mockito.Mockito.verify;
     56 import static org.mockito.Mockito.when;
     57 
     58 /**
     59  * Resolver activity instrumentation tests
     60  */
     61 @RunWith(AndroidJUnit4.class)
     62 public class ResolverActivityTest {
     63     @Rule
     64     public ActivityTestRule<ResolverWrapperActivity> mActivityRule =
     65             new ActivityTestRule<>(ResolverWrapperActivity.class, false,
     66                     false);
     67 
     68     @Before
     69     public void cleanOverrideData() {
     70         sOverrides.reset();
     71     }
     72 
     73     @Test
     74     public void twoOptionsAndUserSelectsOne() throws InterruptedException {
     75         Intent sendIntent = createSendImageIntent();
     76         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
     77 
     78         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
     79                 Mockito.anyBoolean(),
     80                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
     81 
     82         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
     83         waitForIdle();
     84 
     85         assertThat(activity.getAdapter().getCount(), is(2));
     86 
     87         ResolveInfo[] chosen = new ResolveInfo[1];
     88         sOverrides.onSafelyStartCallback = targetInfo -> {
     89             chosen[0] = targetInfo.getResolveInfo();
     90             return true;
     91         };
     92 
     93         ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
     94         onView(withText(toChoose.activityInfo.name))
     95                 .perform(click());
     96         onView(withId(R.id.button_once))
     97                 .perform(click());
     98         waitForIdle();
     99         assertThat(chosen[0], is(toChoose));
    100     }
    101 
    102     @Test
    103     public void hasLastChosenActivity() throws Exception {
    104         Intent sendIntent = createSendImageIntent();
    105         List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
    106         ResolveInfo toChoose = resolvedComponentInfos.get(0).getResolveInfoAt(0);
    107 
    108         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
    109                 Mockito.anyBoolean(),
    110                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
    111         when(sOverrides.resolverListController.getLastChosen())
    112                 .thenReturn(resolvedComponentInfos.get(0).getResolveInfoAt(0));
    113 
    114         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
    115         waitForIdle();
    116 
    117         // The other entry is filtered to the last used slot
    118         assertThat(activity.getAdapter().getCount(), is(1));
    119         assertThat(activity.getAdapter().getPlaceholderCount(), is(1));
    120 
    121         ResolveInfo[] chosen = new ResolveInfo[1];
    122         sOverrides.onSafelyStartCallback = targetInfo -> {
    123             chosen[0] = targetInfo.getResolveInfo();
    124             return true;
    125         };
    126 
    127         onView(withId(R.id.button_once)).perform(click());
    128         waitForIdle();
    129         assertThat(chosen[0], is(toChoose));
    130     }
    131 
    132     @Test
    133     public void hasOtherProfileOneOption() throws Exception {
    134         Intent sendIntent = createSendImageIntent();
    135         List<ResolvedComponentInfo> resolvedComponentInfos =
    136                 createResolvedComponentsForTestWithOtherProfile(2);
    137         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
    138 
    139         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
    140                 Mockito.anyBoolean(),
    141                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
    142 
    143         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
    144         waitForIdle();
    145 
    146         // The other entry is filtered to the last used slot
    147         assertThat(activity.getAdapter().getCount(), is(1));
    148 
    149         ResolveInfo[] chosen = new ResolveInfo[1];
    150         sOverrides.onSafelyStartCallback = targetInfo -> {
    151             chosen[0] = targetInfo.getResolveInfo();
    152             return true;
    153         };
    154 
    155         // Make a stable copy of the components as the original list may be modified
    156         List<ResolvedComponentInfo> stableCopy =
    157                 createResolvedComponentsForTestWithOtherProfile(2);
    158         // Check that the "Other Profile" activity is put in the right spot
    159         onView(withId(R.id.profile_button)).check(matches(
    160                 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
    161         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
    162                 .perform(click());
    163         onView(withId(R.id.button_once))
    164                 .perform(click());
    165         waitForIdle();
    166         assertThat(chosen[0], is(toChoose));
    167     }
    168 
    169     @Test
    170     public void hasOtherProfileTwoOptionsAndUserSelectsOne() throws Exception {
    171         Intent sendIntent = createSendImageIntent();
    172         List<ResolvedComponentInfo> resolvedComponentInfos =
    173                 createResolvedComponentsForTestWithOtherProfile(3);
    174         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
    175 
    176         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
    177                 Mockito.anyBoolean(),
    178                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
    179 
    180         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
    181         waitForIdle();
    182 
    183         // The other entry is filtered to the other profile slot
    184         assertThat(activity.getAdapter().getCount(), is(2));
    185 
    186         ResolveInfo[] chosen = new ResolveInfo[1];
    187         sOverrides.onSafelyStartCallback = targetInfo -> {
    188             chosen[0] = targetInfo.getResolveInfo();
    189             return true;
    190         };
    191 
    192         // Confirm that the button bar is disabled by default
    193         onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
    194 
    195         // Make a stable copy of the components as the original list may be modified
    196         List<ResolvedComponentInfo> stableCopy =
    197                 createResolvedComponentsForTestWithOtherProfile(2);
    198 
    199         // Check that the "Other Profile" activity is put in the right spot
    200         onView(withId(R.id.profile_button)).check(matches(
    201                 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
    202         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
    203                 .perform(click());
    204         onView(withId(R.id.button_once)).perform(click());
    205         waitForIdle();
    206         assertThat(chosen[0], is(toChoose));
    207     }
    208 
    209 
    210     @Test
    211     public void hasLastChosenActivityAndOtherProfile() throws Exception {
    212         // In this case we prefer the other profile and don't display anything about the last
    213         // chosen activity.
    214         Intent sendIntent = createSendImageIntent();
    215         List<ResolvedComponentInfo> resolvedComponentInfos =
    216                 createResolvedComponentsForTestWithOtherProfile(3);
    217         ResolveInfo toChoose = resolvedComponentInfos.get(1).getResolveInfoAt(0);
    218 
    219         when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
    220                 Mockito.anyBoolean(),
    221                 Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
    222         when(sOverrides.resolverListController.getLastChosen())
    223                 .thenReturn(resolvedComponentInfos.get(1).getResolveInfoAt(0));
    224 
    225         final ResolverWrapperActivity activity = mActivityRule.launchActivity(sendIntent);
    226         waitForIdle();
    227 
    228         // The other entry is filtered to the other profile slot
    229         assertThat(activity.getAdapter().getCount(), is(2));
    230 
    231         ResolveInfo[] chosen = new ResolveInfo[1];
    232         sOverrides.onSafelyStartCallback = targetInfo -> {
    233             chosen[0] = targetInfo.getResolveInfo();
    234             return true;
    235         };
    236 
    237         // Confirm that the button bar is disabled by default
    238         onView(withId(R.id.button_once)).check(matches(not(isEnabled())));
    239 
    240         // Make a stable copy of the components as the original list may be modified
    241         List<ResolvedComponentInfo> stableCopy =
    242                 createResolvedComponentsForTestWithOtherProfile(2);
    243 
    244         // Check that the "Other Profile" activity is put in the right spot
    245         onView(withId(R.id.profile_button)).check(matches(
    246                 withText(stableCopy.get(0).getResolveInfoAt(0).activityInfo.name)));
    247         onView(withText(stableCopy.get(1).getResolveInfoAt(0).activityInfo.name))
    248                 .perform(click());
    249         onView(withId(R.id.button_once)).perform(click());
    250         waitForIdle();
    251         assertThat(chosen[0], is(toChoose));
    252     }
    253 
    254     private Intent createSendImageIntent() {
    255         Intent sendIntent = new Intent();
    256         sendIntent.setAction(Intent.ACTION_SEND);
    257         sendIntent.putExtra(Intent.EXTRA_TEXT, "testing intent sending");
    258         sendIntent.setType("image/jpeg");
    259         return sendIntent;
    260     }
    261 
    262     private List<ResolvedComponentInfo> createResolvedComponentsForTest(int numberOfResults) {
    263         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
    264         for (int i = 0; i < numberOfResults; i++) {
    265             infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
    266         }
    267         return infoList;
    268     }
    269 
    270     private List<ResolvedComponentInfo> createResolvedComponentsForTestWithOtherProfile(
    271             int numberOfResults) {
    272         List<ResolvedComponentInfo> infoList = new ArrayList<>(numberOfResults);
    273         for (int i = 0; i < numberOfResults; i++) {
    274             if (i == 0) {
    275                 infoList.add(ResolverDataProvider.createResolvedComponentInfoWithOtherId(i));
    276             } else {
    277                 infoList.add(ResolverDataProvider.createResolvedComponentInfo(i));
    278             }
    279         }
    280         return infoList;
    281     }
    282 
    283     private void waitForIdle() {
    284         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
    285     }
    286 }