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 17 package com.android.settings.applications; 18 19 import static com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.Mockito.doReturn; 22 import static org.mockito.Mockito.spy; 23 import static org.mockito.Mockito.when; 24 25 import android.app.admin.DevicePolicyManager; 26 import android.content.ComponentName; 27 import android.content.Context; 28 import android.content.Intent; 29 import android.content.pm.ActivityInfo; 30 import android.content.pm.ApplicationInfo; 31 import android.content.pm.ComponentInfo; 32 import android.content.pm.IPackageManager; 33 import android.content.pm.PackageManager; 34 import android.content.pm.ResolveInfo; 35 import android.content.pm.UserInfo; 36 import android.location.LocationManager; 37 import android.os.Build; 38 import android.os.UserHandle; 39 import android.os.UserManager; 40 41 import com.android.settings.testutils.ApplicationTestUtils; 42 import com.android.settingslib.testutils.shadow.ShadowDefaultDialerManager; 43 import com.android.settingslib.testutils.shadow.ShadowSmsApplication; 44 45 import org.junit.Before; 46 import org.junit.Test; 47 import org.junit.runner.RunWith; 48 import org.mockito.Mock; 49 import org.mockito.MockitoAnnotations; 50 import org.robolectric.RobolectricTestRunner; 51 import org.robolectric.RuntimeEnvironment; 52 import org.robolectric.annotation.Config; 53 import org.robolectric.shadows.ShadowApplication; 54 import org.robolectric.util.ReflectionHelpers; 55 56 import java.util.ArrayList; 57 import java.util.Arrays; 58 import java.util.List; 59 import java.util.Set; 60 61 /** 62 * Tests for {@link ApplicationFeatureProviderImpl}. 63 */ 64 @RunWith(RobolectricTestRunner.class) 65 public final class ApplicationFeatureProviderImplTest { 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 = MANAGED_PROFILE_ID * PER_USER_UID_RANGE + 1; 73 74 private final String APP_1 = "app1"; 75 private final String APP_2 = "app2"; 76 77 private final String PERMISSION = "some.permission"; 78 79 @Mock 80 private UserManager mUserManager; 81 @Mock 82 private Context mContext; 83 @Mock 84 private PackageManager mPackageManager; 85 @Mock 86 private IPackageManager mPackageManagerService; 87 @Mock 88 private DevicePolicyManager mDevicePolicyManager; 89 @Mock 90 private LocationManager mLocationManager; 91 92 private ApplicationFeatureProvider mProvider; 93 94 private int mAppCount = -1; 95 private List<UserAppInfo> mAppList = null; 96 97 @Before setUp()98 public void setUp() { 99 MockitoAnnotations.initMocks(this); 100 101 when(mContext.getApplicationContext()).thenReturn(mContext); 102 when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 103 when(mContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); 104 105 mProvider = new ApplicationFeatureProviderImpl(mContext, mPackageManager, 106 mPackageManagerService, mDevicePolicyManager); 107 } 108 verifyCalculateNumberOfPolicyInstalledApps(boolean async)109 private void verifyCalculateNumberOfPolicyInstalledApps(boolean async) { 110 setUpUsersAndInstalledApps(); 111 112 when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID))) 113 .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN); 114 when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID))) 115 .thenReturn(PackageManager.INSTALL_REASON_POLICY); 116 117 mAppCount = -1; 118 mProvider.calculateNumberOfPolicyInstalledApps(async, (num) -> mAppCount = num); 119 if (async) { 120 ShadowApplication.runBackgroundTasks(); 121 } 122 assertThat(mAppCount).isEqualTo(1); 123 } 124 125 @Test testListPolicyInstalledApps()126 public void testListPolicyInstalledApps() { 127 setUpUsersAndInstalledApps(); 128 129 when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID))) 130 .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN); 131 when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID))) 132 .thenReturn(PackageManager.INSTALL_REASON_POLICY); 133 134 mAppList = null; 135 mProvider.listPolicyInstalledApps((list) -> mAppList = list); 136 assertThat(mAppList).isNotNull(); 137 assertThat(mAppList.size()).isEqualTo(1); 138 assertThat(mAppList.get(0).appInfo.packageName).isEqualTo(APP_2); 139 } 140 141 @Test testCalculateNumberOfInstalledAppsSync()142 public void testCalculateNumberOfInstalledAppsSync() { 143 verifyCalculateNumberOfPolicyInstalledApps(false /* async */); 144 } 145 146 @Test testCalculateNumberOfInstalledAppsAsync()147 public void testCalculateNumberOfInstalledAppsAsync() { 148 verifyCalculateNumberOfPolicyInstalledApps(true /* async */); 149 } 150 verifyCalculateNumberOfAppsWithAdminGrantedPermissions(boolean async)151 private void verifyCalculateNumberOfAppsWithAdminGrantedPermissions(boolean async) 152 throws Exception { 153 setUpUsersAndInstalledApps(); 154 155 when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION)) 156 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED); 157 when(mDevicePolicyManager.getPermissionGrantState(null, APP_2, PERMISSION)) 158 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED); 159 when(mPackageManagerService.checkUidPermission(PERMISSION, APP_1_UID)) 160 .thenReturn(PackageManager.PERMISSION_DENIED); 161 when(mPackageManagerService.checkUidPermission(PERMISSION, APP_2_UID)) 162 .thenReturn(PackageManager.PERMISSION_GRANTED); 163 when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID))) 164 .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN); 165 when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID))) 166 .thenReturn(PackageManager.INSTALL_REASON_POLICY); 167 168 mAppCount = -1; 169 mProvider.calculateNumberOfAppsWithAdminGrantedPermissions(new String[]{PERMISSION}, async, 170 (num) -> mAppCount = num); 171 if (async) { 172 ShadowApplication.runBackgroundTasks(); 173 } 174 assertThat(mAppCount).isEqualTo(2); 175 } 176 177 @Test testCalculateNumberOfAppsWithAdminGrantedPermissionsSync()178 public void testCalculateNumberOfAppsWithAdminGrantedPermissionsSync() throws Exception { 179 verifyCalculateNumberOfAppsWithAdminGrantedPermissions(false /* async */); 180 } 181 182 @Test testCalculateNumberOfAppsWithAdminGrantedPermissionsAsync()183 public void testCalculateNumberOfAppsWithAdminGrantedPermissionsAsync() throws Exception { 184 verifyCalculateNumberOfAppsWithAdminGrantedPermissions(true /* async */); 185 } 186 187 @Test testListAppsWithAdminGrantedPermissions()188 public void testListAppsWithAdminGrantedPermissions() 189 throws Exception { 190 setUpUsersAndInstalledApps(); 191 192 when(mDevicePolicyManager.getPermissionGrantState(null, APP_1, PERMISSION)) 193 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_GRANTED); 194 when(mDevicePolicyManager.getPermissionGrantState(null, APP_2, PERMISSION)) 195 .thenReturn(DevicePolicyManager.PERMISSION_GRANT_STATE_DENIED); 196 when(mPackageManagerService.checkUidPermission(PERMISSION, APP_1_UID)) 197 .thenReturn(PackageManager.PERMISSION_DENIED); 198 when(mPackageManagerService.checkUidPermission(PERMISSION, APP_2_UID)) 199 .thenReturn(PackageManager.PERMISSION_GRANTED); 200 when(mPackageManager.getInstallReason(APP_1, new UserHandle(MAIN_USER_ID))) 201 .thenReturn(PackageManager.INSTALL_REASON_UNKNOWN); 202 when(mPackageManager.getInstallReason(APP_2, new UserHandle(MANAGED_PROFILE_ID))) 203 .thenReturn(PackageManager.INSTALL_REASON_POLICY); 204 205 mAppList = null; 206 mProvider.listAppsWithAdminGrantedPermissions(new String[]{PERMISSION}, 207 (list) -> mAppList = list); 208 assertThat(mAppList).isNotNull(); 209 assertThat(mAppList.size()).isEqualTo(2); 210 assertThat(Arrays.asList(mAppList.get(0).appInfo.packageName, 211 mAppList.get(1).appInfo.packageName).containsAll(Arrays.asList(APP_1, APP_2))) 212 .isTrue(); 213 } 214 215 @Test testFindPersistentPreferredActivities()216 public void testFindPersistentPreferredActivities() throws Exception { 217 final UserInfo mainUser = new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN); 218 final UserInfo managedUser = new UserInfo(MANAGED_PROFILE_ID, "managed", 219 UserInfo.FLAG_MANAGED_PROFILE); 220 221 when(mUserManager.getUserProfiles()).thenReturn(Arrays.asList(new UserHandle(MAIN_USER_ID), 222 new UserHandle(MANAGED_PROFILE_ID))); 223 when(mUserManager.getUserInfo(MAIN_USER_ID)).thenReturn(mainUser); 224 when(mUserManager.getUserInfo(MANAGED_PROFILE_ID)).thenReturn(managedUser); 225 226 final Intent viewIntent = new Intent(Intent.ACTION_VIEW); 227 final Intent editIntent = new Intent(Intent.ACTION_EDIT); 228 final Intent sendIntent = new Intent(Intent.ACTION_SEND); 229 230 final ResolveInfo app1 = createResolveInfo(APP_1); 231 final ResolveInfo app2 = createResolveInfo(APP_2); 232 when(mPackageManagerService.findPersistentPreferredActivity(viewIntent, MAIN_USER_ID)) 233 .thenReturn(app1); 234 when(mPackageManagerService.findPersistentPreferredActivity(viewIntent, MANAGED_PROFILE_ID)) 235 .thenReturn(app1); 236 when(mPackageManagerService.findPersistentPreferredActivity(editIntent, MAIN_USER_ID)) 237 .thenReturn(null); 238 when(mPackageManagerService.findPersistentPreferredActivity(editIntent, MANAGED_PROFILE_ID)) 239 .thenReturn(app2); 240 when(mPackageManagerService.findPersistentPreferredActivity(sendIntent, MAIN_USER_ID)) 241 .thenReturn(app1); 242 when(mPackageManagerService.findPersistentPreferredActivity(sendIntent, MANAGED_PROFILE_ID)) 243 .thenReturn(null); 244 245 final List<UserAppInfo> expectedMainUserActivities = new ArrayList<>(); 246 expectedMainUserActivities.add(new UserAppInfo(mainUser, 247 new ApplicationInfo(app1.activityInfo.applicationInfo))); 248 final List<UserAppInfo> expectedManagedUserActivities = new ArrayList<>(); 249 expectedManagedUserActivities.add(new UserAppInfo(managedUser, 250 new ApplicationInfo(app1.activityInfo.applicationInfo))); 251 expectedManagedUserActivities.add(new UserAppInfo(managedUser, 252 new ApplicationInfo(app2.activityInfo.applicationInfo))); 253 254 assertThat(mProvider.findPersistentPreferredActivities(MAIN_USER_ID, 255 new Intent[]{viewIntent, editIntent, sendIntent})) 256 .isEqualTo(expectedMainUserActivities); 257 assertThat(mProvider.findPersistentPreferredActivities(MANAGED_PROFILE_ID, 258 new Intent[]{viewIntent, editIntent, sendIntent})) 259 .isEqualTo(expectedManagedUserActivities); 260 } 261 262 @Test 263 @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class}) getKeepEnabledPackages_shouldContainDefaultPhoneAndSmsAndLocationHistory()264 public void getKeepEnabledPackages_shouldContainDefaultPhoneAndSmsAndLocationHistory() { 265 final String testDialer = "com.android.test.defaultdialer"; 266 final String testSms = "com.android.test.defaultsms"; 267 final String testLocationHistory = "com.android.test.location.history"; 268 269 ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver")); 270 ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer); 271 272 // Spy the real context to mock LocationManager. 273 Context spyContext = spy(RuntimeEnvironment.application); 274 when(mLocationManager.getExtraLocationControllerPackage()).thenReturn(testLocationHistory); 275 when(spyContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); 276 277 ReflectionHelpers.setField(mProvider, "mContext", spyContext); 278 279 final Set<String> keepEnabledPackages = mProvider.getKeepEnabledPackages(); 280 281 final List<String> expectedPackages = Arrays.asList(testDialer, testSms, 282 testLocationHistory); 283 assertThat(keepEnabledPackages).containsAtLeastElementsIn(expectedPackages); 284 } 285 286 @Test 287 @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class}) getKeepEnabledPackages_hasEuiccComponent_shouldContainEuiccPackage()288 public void getKeepEnabledPackages_hasEuiccComponent_shouldContainEuiccPackage() { 289 final String testDialer = "com.android.test.defaultdialer"; 290 final String testSms = "com.android.test.defaultsms"; 291 final String testLocationHistory = "com.android.test.location.history"; 292 final String testEuicc = "com.android.test.euicc"; 293 294 ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver")); 295 ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer); 296 final ComponentInfo componentInfo = new ComponentInfo(); 297 componentInfo.packageName = testEuicc; 298 299 ApplicationFeatureProviderImpl spyProvider = spy(new ApplicationFeatureProviderImpl( 300 mContext, mPackageManager, mPackageManagerService, mDevicePolicyManager)); 301 doReturn(componentInfo).when(spyProvider).findEuiccService(mPackageManager); 302 303 // Spy the real context to mock LocationManager. 304 Context spyContext = spy(RuntimeEnvironment.application); 305 when(mLocationManager.getExtraLocationControllerPackage()).thenReturn(testLocationHistory); 306 when(spyContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); 307 308 ReflectionHelpers.setField(mProvider, "mContext", spyContext); 309 310 final Set<String> keepEnabledPackages = spyProvider.getKeepEnabledPackages(); 311 312 assertThat(keepEnabledPackages).contains(testEuicc); 313 } 314 315 @Test 316 @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class}) getKeepEnabledPackages_shouldContainSettingsIntelligence()317 public void getKeepEnabledPackages_shouldContainSettingsIntelligence() { 318 final String testDialer = "com.android.test.defaultdialer"; 319 final String testSms = "com.android.test.defaultsms"; 320 final String testLocationHistory = "com.android.test.location.history"; 321 322 ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver")); 323 ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer); 324 325 // Spy the real context to mock LocationManager. 326 Context spyContext = spy(RuntimeEnvironment.application); 327 when(mLocationManager.getExtraLocationControllerPackage()).thenReturn(testLocationHistory); 328 when(spyContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); 329 330 ReflectionHelpers.setField(mProvider, "mContext", spyContext); 331 332 final Set<String> allowlist = mProvider.getKeepEnabledPackages(); 333 334 assertThat(allowlist).contains("com.android.settings.intelligence"); 335 } 336 337 @Test 338 @Config(shadows = {ShadowSmsApplication.class, ShadowDefaultDialerManager.class}) getKeepEnabledPackages_shouldContainPackageInstaller()339 public void getKeepEnabledPackages_shouldContainPackageInstaller() { 340 final String testDialer = "com.android.test.defaultdialer"; 341 final String testSms = "com.android.test.defaultsms"; 342 final String testLocationHistory = "com.android.test.location.history"; 343 344 ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver")); 345 ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer); 346 347 // Spy the real context to mock LocationManager. 348 Context spyContext = spy(RuntimeEnvironment.application); 349 when(mLocationManager.getExtraLocationControllerPackage()).thenReturn(testLocationHistory); 350 when(spyContext.getSystemService(Context.LOCATION_SERVICE)).thenReturn(mLocationManager); 351 352 ReflectionHelpers.setField(mProvider, "mContext", spyContext); 353 354 final Set<String> allowlist = mProvider.getKeepEnabledPackages(); 355 356 assertThat(allowlist).contains("com.android.packageinstaller"); 357 } 358 setUpUsersAndInstalledApps()359 private void setUpUsersAndInstalledApps() { 360 when(mUserManager.getProfiles(UserHandle.myUserId())).thenReturn(Arrays.asList( 361 new UserInfo(MAIN_USER_ID, "main", UserInfo.FLAG_ADMIN), 362 new UserInfo(MANAGED_PROFILE_ID, "managed profile", 0))); 363 364 when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS 365 | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS 366 | PackageManager.MATCH_ANY_USER, 367 MAIN_USER_ID)).thenReturn(Arrays.asList( 368 ApplicationTestUtils.buildInfo(APP_1_UID, APP_1, 0 /* flags */, 369 Build.VERSION_CODES.M))); 370 when(mPackageManager.getInstalledApplicationsAsUser(PackageManager.GET_DISABLED_COMPONENTS 371 | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS, 372 MANAGED_PROFILE_ID)).thenReturn(Arrays.asList( 373 ApplicationTestUtils.buildInfo(APP_2_UID, APP_2, 0 /* flags */, 374 Build.VERSION_CODES.LOLLIPOP))); 375 } 376 createResolveInfo(String packageName)377 private ResolveInfo createResolveInfo(String packageName) { 378 final ApplicationInfo applicationInfo = new ApplicationInfo(); 379 applicationInfo.packageName = packageName; 380 final ActivityInfo activityInfo = new ActivityInfo(); 381 activityInfo.packageName = packageName; 382 activityInfo.applicationInfo = applicationInfo; 383 final ResolveInfo resolveInfo = new ResolveInfo(); 384 resolveInfo.activityInfo = activityInfo; 385 return resolveInfo; 386 } 387 } 388