• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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 static com.google.common.truth.Truth.assertThat;
20 
21 import static org.mockito.ArgumentMatchers.any;
22 import static org.mockito.ArgumentMatchers.anyInt;
23 import static org.mockito.ArgumentMatchers.anyLong;
24 import static org.mockito.Mockito.doReturn;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.spy;
27 import static org.mockito.Mockito.when;
28 
29 import android.app.usage.UsageStats;
30 import android.app.usage.UsageStatsManager;
31 import android.content.Context;
32 import android.content.Intent;
33 import android.content.pm.ApplicationInfo;
34 import android.content.pm.ModuleInfo;
35 import android.content.pm.PackageManager;
36 import android.content.pm.ResolveInfo;
37 import android.os.PowerManager;
38 import android.os.UserHandle;
39 import android.os.UserManager;
40 
41 import com.android.settingslib.applications.AppUtils;
42 import com.android.settingslib.applications.ApplicationsState;
43 import com.android.settingslib.applications.instantapps.InstantAppDataProvider;
44 
45 import org.junit.Before;
46 import org.junit.Test;
47 import org.junit.runner.RunWith;
48 import org.mockito.Mock;
49 import org.mockito.MockitoAnnotations;
50 import org.robolectric.RobolectricTestRunner;
51 import org.robolectric.RuntimeEnvironment;
52 import org.robolectric.util.ReflectionHelpers;
53 
54 import java.util.ArrayList;
55 import java.util.List;
56 
57 @RunWith(RobolectricTestRunner.class)
58 public class RecentAppStatsMixinTest {
59 
60     @Mock
61     private UsageStatsManager mUsageStatsManager;
62     @Mock
63     private UserManager mUserManager;
64     @Mock
65     private ApplicationsState mAppState;
66     @Mock
67     private PackageManager mPackageManager;
68     @Mock
69     private ApplicationsState.AppEntry mAppEntry;
70     @Mock
71     private ApplicationInfo mApplicationInfo;
72     @Mock
73     private PowerManager mPowerManager;
74 
75     private RecentAppStatsMixin mRecentAppStatsMixin;
76 
77     @Before
setUp()78     public void setUp() {
79         MockitoAnnotations.initMocks(this);
80         final Context context = spy(RuntimeEnvironment.application);
81         when(context.getApplicationContext()).thenReturn(context);
82         ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", mAppState);
83         doReturn(mUsageStatsManager).when(context).getSystemService(Context.USAGE_STATS_SERVICE);
84         doReturn(mUserManager).when(context).getSystemService(Context.USER_SERVICE);
85         doReturn(mPackageManager).when(context).getPackageManager();
86         doReturn(mPowerManager).when(context).getSystemService(PowerManager.class);
87         when(mUserManager.getProfileIdsWithDisabled(anyInt())).thenReturn(new int[]{});
88 
89         mRecentAppStatsMixin = new RecentAppStatsMixin(context, 3 /* maximumApps */);
90     }
91 
92     @Test
loadDisplayableRecentApps_oneValidRecentAppSet_shouldHaveOneRecentApp()93     public void loadDisplayableRecentApps_oneValidRecentAppSet_shouldHaveOneRecentApp() {
94         final List<UsageStats> stats = new ArrayList<>();
95         final UsageStats stat1 = new UsageStats();
96         stat1.mLastTimeUsed = System.currentTimeMillis();
97         stat1.mPackageName = "pkg.class";
98         stats.add(stat1);
99         // stat1 is valid app.
100         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
101                 .thenReturn(mAppEntry);
102         when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
103                 .thenReturn(new ResolveInfo());
104         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
105                 .thenReturn(stats);
106         mAppEntry.info = mApplicationInfo;
107 
108         mRecentAppStatsMixin.loadDisplayableRecentApps(3);
109 
110         assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1);
111     }
112 
113     @Test
loadDisplayableRecentApps_threeValidRecentAppsSet_shouldHaveThreeRecentApps()114     public void loadDisplayableRecentApps_threeValidRecentAppsSet_shouldHaveThreeRecentApps() {
115         final List<UsageStats> stats = new ArrayList<>();
116         final UsageStats stat1 = new UsageStats();
117         final UsageStats stat2 = new UsageStats();
118         final UsageStats stat3 = new UsageStats();
119         stat1.mLastTimeUsed = System.currentTimeMillis();
120         stat1.mPackageName = "pkg.class";
121         stats.add(stat1);
122 
123         stat2.mLastTimeUsed = System.currentTimeMillis();
124         stat2.mPackageName = "pkg.class2";
125         stats.add(stat2);
126 
127         stat3.mLastTimeUsed = System.currentTimeMillis();
128         stat3.mPackageName = "pkg.class3";
129         stats.add(stat3);
130 
131         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
132                 .thenReturn(mAppEntry);
133         when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
134                 .thenReturn(mAppEntry);
135         when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
136                 .thenReturn(mAppEntry);
137         when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
138                 .thenReturn(new ResolveInfo());
139         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
140                 .thenReturn(stats);
141         mAppEntry.info = mApplicationInfo;
142 
143         mRecentAppStatsMixin.loadDisplayableRecentApps(3);
144 
145         assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(3);
146     }
147 
148     @Test
loadDisplayableRecentApps_oneValidAndTwoInvalidSet_shouldHaveOneRecentApp()149     public void loadDisplayableRecentApps_oneValidAndTwoInvalidSet_shouldHaveOneRecentApp() {
150         final List<UsageStats> stats = new ArrayList<>();
151         final UsageStats stat1 = new UsageStats();
152         final UsageStats stat2 = new UsageStats();
153         final UsageStats stat3 = new UsageStats();
154         stat1.mLastTimeUsed = System.currentTimeMillis();
155         stat1.mPackageName = "pkg.class";
156         stats.add(stat1);
157 
158         stat2.mLastTimeUsed = System.currentTimeMillis();
159         stat2.mPackageName = "com.android.settings";
160         stats.add(stat2);
161 
162         stat3.mLastTimeUsed = System.currentTimeMillis();
163         stat3.mPackageName = "pkg.class3";
164         stats.add(stat3);
165 
166         // stat1, stat2 are valid apps. stat3 is invalid.
167         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
168                 .thenReturn(mAppEntry);
169         when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
170                 .thenReturn(mAppEntry);
171         when(mAppState.getEntry(stat3.mPackageName, UserHandle.myUserId()))
172                 .thenReturn(null);
173         when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
174                 .thenReturn(new ResolveInfo());
175         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
176                 .thenReturn(stats);
177         mAppEntry.info = mApplicationInfo;
178 
179         mRecentAppStatsMixin.loadDisplayableRecentApps(3);
180 
181         // Only stat1. stat2 is skipped because of the package name, stat3 skipped because
182         // it's invalid app.
183         assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1);
184     }
185 
186     @Test
loadDisplayableRecentApps_oneInstantAppSet_shouldHaveOneRecentApp()187     public void loadDisplayableRecentApps_oneInstantAppSet_shouldHaveOneRecentApp() {
188         final List<UsageStats> stats = new ArrayList<>();
189         // Instant app.
190         final UsageStats stat = new UsageStats();
191         stat.mLastTimeUsed = System.currentTimeMillis() + 200;
192         stat.mPackageName = "com.foo.barinstant";
193         stats.add(stat);
194 
195         ApplicationsState.AppEntry statEntry = mock(ApplicationsState.AppEntry.class);
196         statEntry.info = mApplicationInfo;
197 
198         when(mAppState.getEntry(stat.mPackageName, UserHandle.myUserId())).thenReturn(statEntry);
199         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
200                 .thenReturn(stats);
201 
202         // Make sure stat is considered an instant app.
203         ReflectionHelpers.setStaticField(AppUtils.class, "sInstantAppDataProvider",
204                 (InstantAppDataProvider) (ApplicationInfo info) -> info == statEntry.info);
205 
206         mRecentAppStatsMixin.loadDisplayableRecentApps(3);
207 
208         assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1);
209     }
210 
211     @Test
loadDisplayableRecentApps_withNullAppEntryOrInfo_shouldNotCrash()212     public void loadDisplayableRecentApps_withNullAppEntryOrInfo_shouldNotCrash() {
213         final List<UsageStats> stats = new ArrayList<>();
214         final UsageStats stat1 = new UsageStats();
215         final UsageStats stat2 = new UsageStats();
216         stat1.mLastTimeUsed = System.currentTimeMillis();
217         stat1.mPackageName = "pkg.class";
218         stats.add(stat1);
219 
220         stat2.mLastTimeUsed = System.currentTimeMillis();
221         stat2.mPackageName = "pkg.class2";
222         stats.add(stat2);
223 
224         // app1 has AppEntry with null info, app2 has null AppEntry.
225         mAppEntry.info = null;
226         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
227                 .thenReturn(mAppEntry);
228         when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId()))
229                 .thenReturn(null);
230 
231         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
232                 .thenReturn(stats);
233 
234         // We should not crash here.
235         mRecentAppStatsMixin.loadDisplayableRecentApps(3);
236     }
237 
238     @Test
loadDisplayableRecentApps_hiddenSystemModuleSet_shouldNotHaveHiddenSystemModule()239     public void loadDisplayableRecentApps_hiddenSystemModuleSet_shouldNotHaveHiddenSystemModule() {
240         final List<UsageStats> stats = new ArrayList<>();
241         // Regular app.
242         final UsageStats stat1 = new UsageStats();
243         stat1.mLastTimeUsed = System.currentTimeMillis();
244         stat1.mPackageName = "com.foo.bar";
245         stats.add(stat1);
246 
247         // Hidden system module.
248         final UsageStats stat2 = new UsageStats();
249         stat2.mLastTimeUsed = System.currentTimeMillis() + 200;
250         stat2.mPackageName = "com.foo.hidden";
251         stats.add(stat2);
252 
253         ApplicationsState.AppEntry stat1Entry = mock(ApplicationsState.AppEntry.class);
254         ApplicationsState.AppEntry stat2Entry = mock(ApplicationsState.AppEntry.class);
255         stat1Entry.info = mApplicationInfo;
256         stat2Entry.info = mApplicationInfo;
257 
258         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId())).thenReturn(stat1Entry);
259         when(mAppState.getEntry(stat2.mPackageName, UserHandle.myUserId())).thenReturn(stat2Entry);
260 
261         final ModuleInfo moduleInfo1 = new ModuleInfo();
262         moduleInfo1.setPackageName(stat1.mPackageName);
263         moduleInfo1.setHidden(false);
264 
265         final ModuleInfo moduleInfo2 = new ModuleInfo();
266         moduleInfo2.setPackageName(stat2.mPackageName);
267         moduleInfo2.setHidden(true);
268 
269         ReflectionHelpers.setStaticField(ApplicationsState.class, "sInstance", null);
270         final List<ModuleInfo> modules = new ArrayList<>();
271         modules.add(moduleInfo2);
272         when(mPackageManager.getInstalledModules(anyInt() /* flags */))
273                 .thenReturn(modules);
274 
275         when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
276                 .thenReturn(new ResolveInfo());
277         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
278                 .thenReturn(stats);
279 
280         mRecentAppStatsMixin.loadDisplayableRecentApps(3);
281 
282         assertThat(mRecentAppStatsMixin.mRecentApps.size()).isEqualTo(1);
283     }
284 
285     @Test
loadDisplayableRecentApps_powerSaverModeOn_shouldHaveEmptyList()286     public void loadDisplayableRecentApps_powerSaverModeOn_shouldHaveEmptyList() {
287         when(mPowerManager.isPowerSaveMode()).thenReturn(true);
288 
289         final List<UsageStats> stats = new ArrayList<>();
290         final UsageStats stat1 = new UsageStats();
291 
292         stat1.mLastTimeUsed = System.currentTimeMillis();
293         stat1.mPackageName = "pkg.class";
294         stats.add(stat1);
295 
296         // stat1, stat2 are valid apps. stat3 is invalid.
297         when(mAppState.getEntry(stat1.mPackageName, UserHandle.myUserId()))
298                 .thenReturn(mAppEntry);
299         when(mPackageManager.resolveActivity(any(Intent.class), anyInt()))
300                 .thenReturn(new ResolveInfo());
301         when(mUsageStatsManager.queryUsageStats(anyInt(), anyLong(), anyLong()))
302                 .thenReturn(stats);
303         mAppEntry.info = mApplicationInfo;
304 
305         mRecentAppStatsMixin.loadDisplayableRecentApps(3);
306 
307         assertThat(mRecentAppStatsMixin.mRecentApps).isEmpty();
308     }
309 }
310