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 android.app.admin.DevicePolicyManager; 20import android.content.Context; 21import android.content.pm.ApplicationInfo; 22import android.content.pm.PackageManager; 23import android.content.pm.UserInfo; 24import android.os.Build; 25import android.os.RemoteException; 26import android.os.UserHandle; 27import android.os.UserManager; 28 29import com.android.settings.testutils.SettingsRobolectricTestRunner; 30import com.android.settings.TestConfig; 31import com.android.settings.enterprise.DevicePolicyManagerWrapper; 32 33import org.junit.Before; 34import org.junit.Test; 35import org.junit.runner.RunWith; 36import org.mockito.Mock; 37import org.mockito.MockitoAnnotations; 38import org.robolectric.annotation.Config; 39import org.robolectric.shadows.ShadowApplication; 40 41import java.util.Arrays; 42 43import static com.android.settings.testutils.ApplicationTestUtils.buildInfo; 44import static com.google.common.truth.Truth.assertThat; 45import static org.mockito.Matchers.anyInt; 46import static org.mockito.Matchers.anyObject; 47import static org.mockito.Matchers.eq; 48import static org.mockito.Mockito.atLeast; 49import static org.mockito.Mockito.verify; 50import static org.mockito.Mockito.verifyNoMoreInteractions; 51import static org.mockito.Mockito.when; 52 53/** 54 * Tests for {@link InstalledAppCounter}. 55 */ 56@RunWith(SettingsRobolectricTestRunner.class) 57@Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) 58public final class AppWithAdminGrantedPermissionsCounterTest { 59 60 private final String APP_1 = "app1"; 61 private final String APP_2 = "app2"; 62 private final String APP_3 = "app3"; 63 private final String APP_4 = "app4"; 64 private final String APP_5 = "app5"; 65 private final String APP_6 = "app6"; 66 67 private final int MAIN_USER_ID = 0; 68 private final int MANAGED_PROFILE_ID = 10; 69 70 private final int PER_USER_UID_RANGE = 100000; 71 private final int APP_1_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 1; 72 private final int APP_2_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 2; 73 private final int APP_3_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 3; 74 private final int APP_4_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 4; 75 private final int APP_5_UID = MAIN_USER_ID * PER_USER_UID_RANGE + 5; 76 private final int APP_6_UID = MANAGED_PROFILE_ID * PER_USER_UID_RANGE + 1; 77 78 private final String PERMISSION_1 = "some.permission.1"; 79 private final String PERMISSION_2 = "some.permission.2"; 80 private final String[] PERMISSIONS = {PERMISSION_1, PERMISSION_2}; 81 82 @Mock private UserManager mUserManager; 83 @Mock private Context mContext; 84 @Mock private PackageManagerWrapper mPackageManager; 85 @Mock private IPackageManagerWrapper mPackageManagerService; 86 @Mock private DevicePolicyManagerWrapper 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 extends 252 AppWithAdminGrantedPermissionsCounter { 253 public 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