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