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 17package com.android.settings.applications; 18 19import static com.android.settings.testutils.ApplicationTestUtils.buildInfo; 20import static com.google.common.truth.Truth.assertThat; 21import static org.mockito.Matchers.anyInt; 22import static org.mockito.Matchers.anyObject; 23import static org.mockito.Matchers.eq; 24import static org.mockito.Mockito.atLeast; 25import static org.mockito.Mockito.verify; 26import static org.mockito.Mockito.verifyNoMoreInteractions; 27import static org.mockito.Mockito.when; 28 29import android.app.admin.DevicePolicyManager; 30import android.content.Context; 31import android.content.pm.ApplicationInfo; 32import android.content.pm.IPackageManager; 33import android.content.pm.PackageManager; 34import android.content.pm.UserInfo; 35import android.os.Build; 36import android.os.RemoteException; 37import android.os.UserHandle; 38import android.os.UserManager; 39 40import com.android.settings.testutils.SettingsRobolectricTestRunner; 41import com.android.settingslib.wrapper.PackageManagerWrapper; 42 43import org.junit.Before; 44import org.junit.Test; 45import org.junit.runner.RunWith; 46import org.mockito.Mock; 47import org.mockito.MockitoAnnotations; 48import org.robolectric.shadows.ShadowApplication; 49 50import java.util.Arrays; 51 52@RunWith(SettingsRobolectricTestRunner.class) 53public final class AppWithAdminGrantedPermissionsCounterTest { 54 55 private final String APP_1 = "app1"; 56 private final String APP_2 = "app2"; 57 private final String APP_3 = "app3"; 58 private final String APP_4 = "app4"; 59 private final String APP_5 = "app5"; 60 private final String APP_6 = "app6"; 61 62 private final int MAIN_USER_ID = 0; 63 private final int MANAGED_PROFILE_ID = 10; 64 65 private final int PER_USER_UID_RANGE = 100000; 66 private final int APP_1_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 1; 67 private final int APP_2_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 2; 68 private final int APP_3_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 3; 69 private final int APP_4_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 4; 70 private final int APP_5_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 5; 71 private final int APP_6_UID = MANAGED_PROFILE_ID * PER_USER_UID_RANGE + 1; 72 73 private final String PERMISSION_1 = "some.permission.1"; 74 private final String PERMISSION_2 = "some.permission.2"; 75 private final String[] PERMISSIONS = {PERMISSION_1, PERMISSION_2}; 76 77 @Mock 78 private UserManager mUserManager; 79 @Mock 80 private Context mContext; 81 @Mock 82 private PackageManagerWrapper mPackageManager; 83 @Mock 84 private IPackageManager mPackageManagerService; 85 @Mock 86 private DevicePolicyManager mDevicePolicyManager; 87 88 private int mAppCount = -1; 89 private ApplicationInfo mApp1; 90 private ApplicationInfo mApp2; 91 private ApplicationInfo mApp3; 92 private ApplicationInfo mApp4; 93 private ApplicationInfo mApp5; 94 private ApplicationInfo mApp6; 95 96 @Before 97 public void setUp() { 98 MockitoAnnotations.initMocks(this); 99 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 100 101 mApp1 = buildInfo(APP_1_UID, APP_1, 0 /* flags */, Build.VERSION_CODES.M); 102 mApp2 = buildInfo(APP_2_UID, APP_2, 0 /* flags */, Build.VERSION_CODES.M); 103 mApp3 = buildInfo(APP_3_UID, APP_3, 0 /* flags */, Build.VERSION_CODES.LOLLIPOP); 104 mApp4 = buildInfo(APP_4_UID, APP_4, 0 /* flags */, Build.VERSION_CODES.LOLLIPOP); 105 mApp5 = buildInfo(APP_5_UID, APP_5, 0 /* flags */, Build.VERSION_CODES.LOLLIPOP); 106 mApp6 = buildInfo(APP_6_UID, APP_6, 0 /* flags */, Build.VERSION_CODES.M); 107 } 108 109 private void verifyCountInstalledApps(boolean async) throws Exception { 110 configureUserManager(); 111 configurePackageManager(); 112 configureRunTimePermissions(); 113 configureInstallTimePermissions(); 114 115 // Count the number of all apps installed that were granted on or more permissions by the 116 // admin. 117 if (async) { 118 (new AppWithAdminGrantedPermissionsCounterTestable(PERMISSIONS)).execute(); 119 // Wait for the background task to finish. 120 ShadowApplication.runBackgroundTasks(); 121 } else { 122 (new AppWithAdminGrantedPermissionsCounterTestable(PERMISSIONS)).executeInForeground(); 123 } 124 assertThat(mAppCount).isEqualTo(3); 125 126 // Verify that installed packages were retrieved the current user and the user's managed 127 // profile only. 128 verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(), eq(MAIN_USER_ID)); 129 verify(mPackageManager).getInstalledApplicationsAsUser(anyInt(), 130 eq(MANAGED_PROFILE_ID)); 131 verify(mPackageManager, atLeast(0)).getInstallReason(anyObject(), anyObject()); 132 verifyNoMoreInteractions(mPackageManager); 133 } 134 135 @Test 136 public void testIncludeInCount() throws Exception { 137 configurePackageManager(); 138 configureRunTimePermissions(); 139 configureInstallTimePermissions(); 140 141 assertThat(AppWithAdminGrantedPermissionsCounter.includeInCount(PERMISSIONS, 142 mDevicePolicyManager, mPackageManager, mPackageManagerService, mApp1)).isTrue(); 143 144 assertThat(AppWithAdminGrantedPermissionsCounter.includeInCount(PERMISSIONS, 145 mDevicePolicyManager, mPackageManager, mPackageManagerService, mApp2)).isFalse(); 146 147 assertThat(AppWithAdminGrantedPermissionsCounter.includeInCount(PERMISSIONS, 148 mDevicePolicyManager, mPackageManager, mPackageManagerService, mApp3)).isTrue(); 149 150 assertThat(AppWithAdminGrantedPermissionsCounter.includeInCount(PERMISSIONS, 151 mDevicePolicyManager, mPackageManager, mPackageManagerService, mApp4)).isFalse(); 152 153 assertThat(AppWithAdminGrantedPermissionsCounter.includeInCount(PERMISSIONS, 154 mDevicePolicyManager, mPackageManager, mPackageManagerService, mApp5)).isFalse(); 155 } 156 157 @Test 158 public void testCountInstalledAppsSync() throws Exception { 159 verifyCountInstalledApps(false /* async */); 160 } 161 162 @Test 163 public void testCountInstalledAppsAync() throws Exception { 164 verifyCountInstalledApps(true /* async */); 165 } 166 167 private void configureInstallTimePermissions() throws RemoteException { 168 when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_1_UID))) 169 .thenReturn(PackageManager.PERMISSION_DENIED); 170 when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_2_UID))) 171 .thenReturn(PackageManager.PERMISSION_DENIED); 172 when(mPackageManagerService.checkUidPermission(PERMISSION_1, APP_3_UID)) 173 .thenReturn(PackageManager.PERMISSION_DENIED); 174 when(mPackageManagerService.checkUidPermission(PERMISSION_2, APP_3_UID)) 175 .thenReturn(PackageManager.PERMISSION_GRANTED); 176 when(mPackageManagerService.checkUidPermission(PERMISSION_1, APP_4_UID)) 177 .thenReturn(PackageManager.PERMISSION_DENIED); 178 when(mPackageManagerService.checkUidPermission(PERMISSION_2, APP_4_UID)) 179 .thenReturn(PackageManager.PERMISSION_GRANTED); 180 when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_5_UID))) 181 .thenReturn(PackageManager.PERMISSION_DENIED); 182 when(mPackageManagerService.checkUidPermission(anyObject(), eq(APP_6_UID))) 183 .thenReturn(PackageManager.PERMISSION_DENIED); 184 } 185 186 private void configureRunTimePermissions() { 187 when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION_1)) 188 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED); 189 when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION_2)) 190 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED); 191 when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_2), anyObject())) 192 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED); 193 when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_3), anyObject())) 194 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED); 195 when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_4), anyObject())) 196 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED); 197 when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_5), anyObject())) 198 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED); 199 when(mDevicePolicyManager.getPermissionGrantState(eq(null), eq(APP_6), anyObject())) 200 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED); 201 } 202 203 private void configurePackageManager() { 204 // The first user has five apps installed: 205 // * app1 uses run-time permissions. It has been granted one of the permissions by the 206 // admin. It should be counted. 207 // * app2 uses run-time permissions. It has not been granted any of the permissions by the 208 // admin. It should not be counted. 209 // * app3 uses install-time permissions. It was installed by the admin and requested one of 210 // the permissions. It should be counted. 211 // * app4 uses install-time permissions. It was not installed by the admin but did request 212 // one of the permissions. It should not be counted. 213 // * app5 uses install-time permissions. It was installed by the admin but did not request 214 // any of the permissions. It should not be counted. 215 when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS 216 | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS 217 | PackageManager.MATCH_ANY_USER, 218 MAIN_USER_ID)).thenReturn(Arrays.asList(mApp1, mApp2, mApp3, mApp4, mApp5)); 219 // The second user has one app installed. This app uses run-time permissions. It has been 220 // granted both permissions by the admin. It should be counted. 221 when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS 222 | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, 223 MANAGED_PROFILE_ID)).thenReturn(Arrays.asList(mApp6)); 224 225 // app3 and app5 were installed by enterprise policy. 226 final UserHandle mainUser = new UserHandle(MAIN_USER_ID); 227 when(mPackageManager.getInstallReason(APP_1, mainUser)) 228 .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN); 229 when(mPackageManager.getInstallReason(APP_2, mainUser)) 230 .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN); 231 when(mPackageManager.getInstallReason(APP_3, mainUser)) 232 .thenReturn(PackageManager.INSTALL_REASON_POLICY); 233 when(mPackageManager.getInstallReason(APP_4, mainUser)) 234 .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN); 235 when(mPackageManager.getInstallReason(APP_5, mainUser)) 236 .thenReturn(PackageManager.INSTALL_REASON_POLICY); 237 // app6 was not installed by enterprise policy. 238 final UserHandle managedProfileUser = new UserHandle(MANAGED_PROFILE_ID); 239 when(mPackageManager.getInstallReason(APP_6, managedProfileUser)) 240 .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN); 241 242 } 243 244 private void configureUserManager() { 245 // There are two users. 246 when(mUserManager.getProfiles(UserHandle.myUserId())).thenReturn(Arrays.asList( 247 new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN), 248 new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0))); 249 } 250 251 private class AppWithAdminGrantedPermissionsCounterTestable 252 extends AppWithAdminGrantedPermissionsCounter { 253 private AppWithAdminGrantedPermissionsCounterTestable(String[] permissions) { 254 super(mContext, permissions, mPackageManager, mPackageManagerService, 255 mDevicePolicyManager); 256 } 257 258 @Override 259 protected void onCountComplete(int num) { 260 mAppCount = num; 261 } 262 } 263} 264