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