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
17package com.android.settings.applications;
18
19import android.app.admin.DevicePolicyManager;
20import android.content.Context;
21import android.content.Intent;
22import android.content.pm.ActivityInfo;
23import android.content.pm.ApplicationInfo;
24import android.content.pm.PackageManager;
25import android.content.pm.ResolveInfo;
26import android.content.pm.UserInfo;
27import android.os.Build;
28import android.os.UserHandle;
29import android.os.UserManager;
30
31import com.android.settings.SettingsRobolectricTestRunner;
32import com.android.settings.TestConfig;
33import com.android.settings.enterprise.DevicePolicyManagerWrapper;
34import com.android.settings.testutils.ApplicationTestUtils;
35import com.android.settings.testutils.shadow.ShadowUserManager;
36
37import org.junit.Before;
38import org.junit.Test;
39import org.junit.runner.RunWith;
40import org.mockito.Mock;
41import org.mockito.MockitoAnnotations;
42import org.robolectric.annotation.Config;
43import org.robolectric.shadows.ShadowApplication;
44
45import java.util.ArrayList;
46import java.util.Arrays;
47import java.util.List;
48
49import static com.google.common.truth.Truth.assertThat;
50import static org.mockito.Mockito.when;
51
52/**
53 * Tests for {@link ApplicationFeatureProviderImpl}.
54 */
55@RunWith(SettingsRobolectricTestRunner.class)
56@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION,
57        shadows = {ShadowUserManager.class})
58public final class ApplicationFeatureProviderImplTest {
59
60    private final int MAIN_USER_ID = 0;
61    private final int MANAGED_PROFILE_ID = 10;
62
63    private final int PER_USER_UID_RANGE = 100000;
64    private final int APP_1_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 1;
65    private final int APP_2_UID = MANAGED_PROFILE_ID * PER_USER_UID_RANGE + 1;
66
67    private final String APP_1 = "app1";
68    private final String APP_2 = "app2";
69
70    private final String PERMISSION = "some.permission";
71
72    private @Mock UserManager mUserManager;
73    private @Mock Context mContext;
74    private @Mock PackageManagerWrapper mPackageManager;
75    @Mock private IPackageManagerWrapper mPackageManagerService;
76    @Mock private DevicePolicyManagerWrapper mDevicePolicyManager;
77
78    private ApplicationFeatureProvider mProvider;
79
80    private int mAppCount = -1;
81    private List<UserAppInfo> mAppList = null;
82
83    @Before
84    public void setUp() {
85        MockitoAnnotations.initMocks(this);
86
87        when(mContext.getApplicationContext()).thenReturn(mContext);
88        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
89
90        mProvider = new ApplicationFeatureProviderImpl(mContext, mPackageManager,
91                mPackageManagerService, mDevicePolicyManager);
92    }
93
94    private void verifyCalculateNumberOfPolicyInstalledApps(boolean async) {
95        setUpUsersAndInstalledApps();
96
97        when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID)))
98                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
99        when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID)))
100                .thenReturn(PackageManager.INSTALL_REASON_POLICY);
101
102        mAppCount = -1;
103        mProvider.calculateNumberOfPolicyInstalledApps(async,
104                (num) -> mAppCount = num);
105        if (async) {
106            ShadowApplication.runBackgroundTasks();
107        }
108        assertThat(mAppCount).isEqualTo(1);
109    }
110
111    @Test
112    public void testListPolicyInstalledApps() {
113        setUpUsersAndInstalledApps();
114
115        when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID)))
116                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
117        when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID)))
118                .thenReturn(PackageManager.INSTALL_REASON_POLICY);
119
120        mAppList = null;
121        mProvider.listPolicyInstalledApps((list) -> mAppList = list);
122        assertThat(mAppList).isNotNull();
123        assertThat(mAppList.size()).isEqualTo(1);
124        assertThat(mAppList.get(0).appInfo.packageName).isEqualTo(APP_2);
125    }
126
127    @Test
128    public void testCalculateNumberOfInstalledAppsSync() {
129        verifyCalculateNumberOfPolicyInstalledApps(false /* async */);
130    }
131
132    @Test
133    public void testCalculateNumberOfInstalledAppsAsync() {
134        verifyCalculateNumberOfPolicyInstalledApps(true /* async */);
135    }
136
137    private void verifyCalculateNumberOfAppsWithAdminGrantedPermissions(boolean async)
138            throws Exception {
139        setUpUsersAndInstalledApps();
140
141        when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION))
142                .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
143        when(mDevicePolicyManager.getPermissionGrantState(null, APP_2, PERMISSION))
144                .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
145        when(mPackageManagerService.checkUidPermission(PERMISSION, APP_1_UID))
146                .thenReturn(PackageManager.PERMISSION_DENIED);
147        when(mPackageManagerService.checkUidPermission(PERMISSION, APP_2_UID))
148                .thenReturn(PackageManager.PERMISSION_GRANTED);
149        when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID)))
150                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
151        when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID)))
152                .thenReturn(PackageManager.INSTALL_REASON_POLICY);
153
154        mAppCount = -1;
155        mProvider.calculateNumberOfAppsWithAdminGrantedPermissions(new String[] {PERMISSION}, async,
156                (num) -> mAppCount = num);
157        if (async) {
158            ShadowApplication.runBackgroundTasks();
159        }
160        assertThat(mAppCount).isEqualTo(2);
161    }
162
163    @Test
164    public void testCalculateNumberOfAppsWithAdminGrantedPermissionsSync() throws Exception {
165        verifyCalculateNumberOfAppsWithAdminGrantedPermissions(false /* async */);
166    }
167
168    @Test
169    public void testCalculateNumberOfAppsWithAdminGrantedPermissionsAsync() throws Exception {
170        verifyCalculateNumberOfAppsWithAdminGrantedPermissions(true /* async */);
171    }
172
173    @Test
174    public void testListAppsWithAdminGrantedPermissions()
175            throws Exception {
176        setUpUsersAndInstalledApps();
177
178        when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION))
179                .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED);
180        when(mDevicePolicyManager.getPermissionGrantState(null, APP_2, PERMISSION))
181                .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED);
182        when(mPackageManagerService.checkUidPermission(PERMISSION, APP_1_UID))
183                .thenReturn(PackageManager.PERMISSION_DENIED);
184        when(mPackageManagerService.checkUidPermission(PERMISSION, APP_2_UID))
185                .thenReturn(PackageManager.PERMISSION_GRANTED);
186        when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID)))
187                .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN);
188        when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID)))
189                .thenReturn(PackageManager.INSTALL_REASON_POLICY);
190
191        mAppList = null;
192        mProvider.listAppsWithAdminGrantedPermissions(new String[] {PERMISSION},
193                (list) -> mAppList = list);
194        assertThat(mAppList).isNotNull();
195        assertThat(mAppList.size()).isEqualTo(2);
196        assertThat(Arrays.asList(mAppList.get(0).appInfo.packageName,
197                mAppList.get(1).appInfo.packageName).containsAll(Arrays.asList(APP_1, APP_2)))
198                .isTrue();
199    }
200
201    @Test
202    public void testFindPersistentPreferredActivities() throws Exception {
203        final UserInfo mainUser = new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN);
204        final UserInfo managedUser = new UserInfo(MANAGED_PROFILE_ID, "managed",
205                UserInfo.FLAG_MANAGED_PROFILE);
206
207        when(mUserManager.getUserProfiles()).thenReturn(Arrays.asList(new UserHandle(MAIN_USER_ID),
208                new UserHandle(MANAGED_PROFILE_ID)));
209        when(mUserManager.getUserInfo(MAIN_USER_ID)).thenReturn(mainUser);
210        when(mUserManager.getUserInfo(MANAGED_PROFILE_ID)).thenReturn(managedUser);
211
212        final Intent viewIntent = new Intent(Intent.ACTION_VIEW);
213        final Intent editIntent = new Intent(Intent.ACTION_EDIT);
214        final Intent sendIntent = new Intent(Intent.ACTION_SEND);
215
216        final ResolveInfo app1 = createResolveInfo(APP_1);
217        final ResolveInfo app2 = createResolveInfo(APP_2);
218        when(mPackageManagerService.findPersistentPreferredActivity(viewIntent, MAIN_USER_ID))
219                .thenReturn(app1);
220        when(mPackageManagerService.findPersistentPreferredActivity(viewIntent, MANAGED_PROFILE_ID))
221                .thenReturn(app1);
222        when(mPackageManagerService.findPersistentPreferredActivity(editIntent, MAIN_USER_ID))
223                .thenReturn(null);
224        when(mPackageManagerService.findPersistentPreferredActivity(editIntent, MANAGED_PROFILE_ID))
225                .thenReturn(app2);
226        when(mPackageManagerService.findPersistentPreferredActivity(sendIntent, MAIN_USER_ID))
227                .thenReturn(app1);
228        when(mPackageManagerService.findPersistentPreferredActivity(sendIntent, MANAGED_PROFILE_ID))
229                .thenReturn(null);
230
231        final List<UserAppInfo> expectedMainUserActivities = new ArrayList<>();
232        expectedMainUserActivities.add(new UserAppInfo(mainUser,
233                new ApplicationInfo(app1.activityInfo.applicationInfo)));
234        final List<UserAppInfo> expectedManagedUserActivities = new ArrayList<>();
235        expectedManagedUserActivities.add(new UserAppInfo(managedUser,
236                new ApplicationInfo(app1.activityInfo.applicationInfo)));
237        expectedManagedUserActivities.add(new UserAppInfo(managedUser,
238                new ApplicationInfo(app2.activityInfo.applicationInfo)));
239
240        assertThat(mProvider.findPersistentPreferredActivities(MAIN_USER_ID,
241                new Intent[] {viewIntent, editIntent, sendIntent}))
242                .isEqualTo(expectedMainUserActivities);
243        assertThat(mProvider.findPersistentPreferredActivities(MANAGED_PROFILE_ID,
244                new Intent[] {viewIntent, editIntent, sendIntent}))
245                .isEqualTo(expectedManagedUserActivities);
246    }
247
248    @Test
249    public void getKeepEnabledPackages_shouldContainNothing() {
250        assertThat(mProvider.getKeepEnabledPackages())
251                .isEmpty();
252    }
253
254    private void setUpUsersAndInstalledApps() {
255        when(mUserManager.getProfiles(UserHandle.myUserId())).thenReturn(Arrays.asList(
256                new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN),
257                new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0)));
258
259        when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
260                | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS
261                | PackageManager.MATCH_ANY_USER,
262                MAIN_USER_ID)).thenReturn(Arrays.asList(
263                        ApplicationTestUtils.buildInfo(APP_1_UID, APP_1, 0 /* flags */,
264                                Build.VERSION_CODES.M)));
265        when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS
266                | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
267                MANAGED_PROFILE_ID)).thenReturn(Arrays.asList(
268                        ApplicationTestUtils.buildInfo(APP_2_UID, APP_2, 0 /* flags */,
269                                Build.VERSION_CODES.LOLLIPOP)));
270    }
271
272    private ResolveInfo createResolveInfo(String packageName) {
273        final ApplicationInfo applicationInfo = new ApplicationInfo();
274        applicationInfo.packageName = packageName;
275        final ActivityInfo activityInfo = new ActivityInfo();
276        activityInfo.packageName = packageName;
277        activityInfo.applicationInfo = applicationInfo;
278        final ResolveInfo resolveInfo = new ResolveInfo();
279        resolveInfo.activityInfo = activityInfo;
280        return resolveInfo;
281    }
282}
283