Home | History | Annotate | Download | only in applications
      1 /*
      2  * Copyright (C) 2017 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.settings.applications;
     18 
     19 import android.app.Application;
     20 import android.app.usage.UsageStats;
     21 import android.app.usage.UsageStatsManager;
     22 import android.content.Context;
     23 import android.content.Intent;
     24 import android.content.pm.ResolveInfo;
     25 import android.content.res.Configuration;
     26 import android.os.UserHandle;
     27 import android.os.UserManager;
     28 import android.support.v7.preference.Preference;
     29 import android.support.v7.preference.PreferenceCategory;
     30 import android.support.v7.preference.PreferenceScreen;
     31 import android.text.TextUtils;
     32 
     33 import com.android.settings.R;
     34 import com.android.settings.testutils.SettingsRobolectricTestRunner;
     35 import com.android.settings.TestConfig;
     36 import com.android.settingslib.applications.ApplicationsState;
     37 
     38 import org.junit.Before;
     39 import org.junit.Test;
     40 import org.junit.runner.RunWith;
     41 import org.mockito.Answers;
     42 import org.mockito.ArgumentMatcher;
     43 import org.mockito.Mock;
     44 import org.mockito.MockitoAnnotations;
     45 import org.robolectric.RuntimeEnvironment;
     46 import org.robolectric.annotation.Config;
     47 
     48 import java.util.ArrayList;
     49 import java.util.List;
     50 import java.util.Locale;
     51 
     52 import static com.google.common.truth.Truth.assertThat;
     53 import static org.mockito.Matchers.any;
     54 import static org.mockito.Matchers.anyInt;
     55 import static org.mockito.Matchers.anyLong;
     56 import static org.mockito.Matchers.anyString;
     57 import static org.mockito.Matchers.argThat;
     58 import static org.mockito.Matchers.eq;
     59 import static org.mockito.Mockito.doNothing;
     60 import static org.mockito.Mockito.mock;
     61 import static org.mockito.Mockito.never;
     62 import static org.mockito.Mockito.spy;
     63 import static org.mockito.Mockito.times;
     64 import static org.mockito.Mockito.verify;
     65 import static org.mockito.Mockito.when;
     66 
     67 @RunWith(SettingsRobolectricTestRunner.class)
     68 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
     69 public class RecentAppsPreferenceControllerTest {
     70 
     71     @Mock
     72     private PreferenceScreen mScreen;
     73     @Mock
     74     private PreferenceCategory mCategory;
     75     @Mock
     76     private Preference mSeeAllPref;
     77     @Mock
     78     private PreferenceCategory mDivider;
     79     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
     80     private Context mMockContext;
     81     @Mock
     82     private UsageStatsManager mUsageStatsManager;
     83     @Mock
     84     private UserManager mUserManager;
     85     @Mock
     86     private ApplicationsState mAppState;
     87 
     88     private Context mContext;
     89     private RecentAppsPreferenceController mController;
     90 
     91     @Before
     92     public void setUp() {
     93         MockitoAnnotations.initMocks(this);
     94         when(mMockContext.getSystemService(Context.USAGE_STATS_SERVICE))
     95                 .thenReturn(mUsageStatsManager);
     96         when(mMockContext.getSystemService(Context.USER_SERVICE))
     97                 .thenReturn(mUserManager);
     98 
     99         mContext = RuntimeEnvironment.application;
    100         mController = new RecentAppsPreferenceController(mContext, mAppState, null);
    101         when(mScreen.findPreference(anyString())).thenReturn(mCategory);
    102 
    103         when(mScreen.findPreference(RecentAppsPreferenceController.KEY_SEE_ALL))
    104                 .thenReturn(mSeeAllPref);
    105         when(mScreen.findPreference(RecentAppsPreferenceController.KEY_DIVIDER))
    106                 .thenReturn(mDivider);
    107         when(mCategory.getContext()).thenReturn(mContext);
    108     }
    109 
    110     @Test
    111     public void isAlwaysAvailable() {
    112         assertThat(mController.isAvailable()).isTrue();
    113     }
    114 
    115     @Test
    116     public void doNotIndexCategory() {
    117         final List<String> nonIndexable = new ArrayList<>();
    118 
    119         mController.updateNonIndexableKeys(nonIndexable);
    120 
    121         assertThat(nonIndexable).containsAllOf(mController.getPreferenceKey(),
    122                 RecentAppsPreferenceController.KEY_DIVIDER);
    123     }
    124 
    125     @Test
    126     public void onDisplayAndUpdateState_shouldRefreshUi() {
    127         mController = spy(
    128                 new RecentAppsPreferenceController(mMockContext, (Application) null, null));
    129 
    130         doNothing().when(mController).refreshUi(mContext);
    131 
    132         mController.displayPreference(mScreen);
    133         mController.updateState(mCategory);
    134 
    135         verify(mController, times(2)).refreshUi(mContext);
    136     }
    137 
    138     @Test
    139     public void display_shouldNotShowRecents_showAppInfoPreference() {
    140         mController = new RecentAppsPreferenceController(mMockContext, mAppState, null);
    141         when(mMockContext.getResources().getBoolean(R.bool.config_display_recent_apps))
    142                 .thenReturn(false);
    143 
    144         mController.displayPreference(mScreen);
    145 
    146         verify(mCategory, never()).addPreference(any(Preference.class));
    147         verify(mCategory).setTitle(null);
    148         verify(mSeeAllPref).setTitle(R.string.applications_settings);
    149         verify(mSeeAllPref).setIcon(null);
    150         verify(mDivider).setVisible(false);
    151     }
    152 
    153     @Test
    154     public void display_showRecents() {
    155         when(mMockContext.getResources().getBoolean(R.bool.config_display_recent_apps))
    156                 .thenReturn(true);
    157         final List<UsageStats> stats = new ArrayList<>();
    158         final UsageStats stat1 = new UsageStats();
    159         final UsageStats stat2 = new UsageStats();
    160         final UsageStats stat3 = new UsageStats();
    161         stat1.mLastTimeUsed = System.currentTimeMillis();
    162         stat1.mPackageName = "pkg.class";
    163         stats.add(stat1);
    164 
    165         stat2.mLastTimeUsed = System.currentTimeMillis();
    166         stat2.mPackageName = "com.android.settings";
    167         stats.add(stat2);
    168 
    169         stat3.mLastTimeUsed = System.currentTimeMillis();
    170         stat3.mPackageName = "pkg.class2";
    171         stats.add(stat3);
    172 
    173         // stat1, stat2 are valid apps. stat3 is invalid.
    174         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
    175                 .thenReturn(mock(ApplicationsState.AppEntry.class));
    176         when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
    177                 .thenReturn(mock(ApplicationsState.AppEntry.class));
    178         when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
    179                 .thenReturn(null);
    180         when(mMockContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
    181                 .thenReturn(new ResolveInfo());
    182         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
    183                 .thenReturn(stats);
    184         final Configuration configuration = new Configuration();
    185         configuration.locale = Locale.US;
    186         when(mMockContext.getResources().getConfiguration()).thenReturn(configuration);
    187 
    188         mController = new RecentAppsPreferenceController(mMockContext, mAppState, null);
    189         mController.displayPreference(mScreen);
    190 
    191         verify(mCategory).setTitle(R.string.recent_app_category_title);
    192         // Only add stat1. stat2 is skipped because of the package name, stat3 skipped because
    193         // it's invalid app.
    194         verify(mCategory, times(1)).addPreference(any(Preference.class));
    195 
    196         verify(mSeeAllPref).setSummary(null);
    197         verify(mSeeAllPref).setIcon(R.drawable.ic_chevron_right_24dp);
    198         verify(mDivider).setVisible(true);
    199     }
    200 
    201     @Test
    202     public void display_hasRecentButNoneDisplayable_showAppInfo() {
    203         when(mMockContext.getResources().getBoolean(R.bool.config_display_recent_apps))
    204                 .thenReturn(true);
    205         final List<UsageStats> stats = new ArrayList<>();
    206         final UsageStats stat1 = new UsageStats();
    207         final UsageStats stat2 = new UsageStats();
    208         stat1.mLastTimeUsed = System.currentTimeMillis();
    209         stat1.mPackageName = "com.android.phone";
    210         stats.add(stat1);
    211 
    212         stat2.mLastTimeUsed = System.currentTimeMillis();
    213         stat2.mPackageName = "com.android.settings";
    214         stats.add(stat2);
    215 
    216         // stat1, stat2 are not displayable
    217         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
    218                 .thenReturn(mock(ApplicationsState.AppEntry.class));
    219         when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
    220                 .thenReturn(mock(ApplicationsState.AppEntry.class));
    221         when(mMockContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
    222                 .thenReturn(new ResolveInfo());
    223         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
    224                 .thenReturn(stats);
    225 
    226         mController = new RecentAppsPreferenceController(mMockContext, mAppState, null);
    227         mController.displayPreference(mScreen);
    228 
    229         verify(mCategory, never()).addPreference(any(Preference.class));
    230         verify(mCategory).setTitle(null);
    231         verify(mSeeAllPref).setTitle(R.string.applications_settings);
    232         verify(mSeeAllPref).setIcon(null);
    233     }
    234 
    235     @Test
    236     public void display_showRecents_formatSummary() {
    237         when(mMockContext.getResources().getBoolean(R.bool.config_display_recent_apps))
    238             .thenReturn(true);
    239         final List<UsageStats> stats = new ArrayList<>();
    240         final UsageStats stat1 = new UsageStats();
    241         stat1.mLastTimeUsed = System.currentTimeMillis();
    242         stat1.mPackageName = "pkg.class";
    243         stats.add(stat1);
    244 
    245         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
    246             .thenReturn(mock(ApplicationsState.AppEntry.class));
    247         when(mMockContext.getPackageManager().resolveActivity(any(Intent.class), anyInt()))
    248             .thenReturn(new ResolveInfo());
    249         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
    250             .thenReturn(stats);
    251 
    252         when(mMockContext.getResources().getText(eq(R.string.recent_app_summary)))
    253             .thenReturn(mContext.getResources().getText(R.string.recent_app_summary));
    254         final Configuration configuration = new Configuration();
    255         configuration.locale = Locale.US;
    256         when(mMockContext.getResources().getConfiguration()).thenReturn(configuration);
    257 
    258         mController = new RecentAppsPreferenceController(mMockContext, mAppState, null);
    259         mController.displayPreference(mScreen);
    260 
    261         verify(mCategory).addPreference(argThat(summaryMatches("0m ago")));
    262     }
    263 
    264     private static ArgumentMatcher<Preference> summaryMatches(String expected) {
    265         return preference -> TextUtils.equals(expected, preference.getSummary());
    266     }
    267 
    268 }
    269