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.managedprovisioning.common; 18 19 import static org.mockito.Mockito.any; 20 import static org.mockito.Mockito.anyInt; 21 import static org.mockito.Mockito.eq; 22 import static org.mockito.Mockito.verify; 23 import static org.mockito.Mockito.verifyNoMoreInteractions; 24 import static org.mockito.Mockito.when; 25 26 import android.accounts.AccountManager; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.content.Intent; 30 import android.content.pm.ActivityInfo; 31 import android.content.pm.ApplicationInfo; 32 import android.content.pm.IPackageManager; 33 import android.content.pm.PackageInfo; 34 import android.content.pm.PackageManager; 35 import android.content.pm.PackageManager.NameNotFoundException; 36 import android.content.pm.ParceledListSlice; 37 import android.content.pm.ResolveInfo; 38 import android.graphics.Color; 39 import android.net.ConnectivityManager; 40 import android.net.NetworkInfo; 41 import android.os.Build; 42 import android.test.AndroidTestCase; 43 import android.test.suitebuilder.annotation.SmallTest; 44 45 import org.mockito.Mock; 46 import org.mockito.MockitoAnnotations; 47 48 import java.io.FileOutputStream; 49 import java.util.Arrays; 50 import java.util.List; 51 import java.util.Set; 52 53 /** 54 * Unit-tests for {@link Utils}. 55 */ 56 @SmallTest 57 public class UtilsTest extends AndroidTestCase { 58 private static final String TEST_PACKAGE_NAME_1 = "com.test.packagea"; 59 private static final String TEST_PACKAGE_NAME_2 = "com.test.packageb"; 60 private static final String TEST_DEVICE_ADMIN_NAME = TEST_PACKAGE_NAME_1 + ".DeviceAdmin"; 61 // Another DeviceAdmin in package 1 62 private static final String TEST_DEVICE_ADMIN_NAME_2 = TEST_PACKAGE_NAME_1 + ".DeviceAdmin2"; 63 private static final ComponentName TEST_COMPONENT_NAME = 64 new ComponentName(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME); 65 private static final ComponentName TEST_COMPONENT_NAME_2 = 66 new ComponentName(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME_2); 67 private static final int TEST_USER_ID = 10; 68 private static final String TEST_FILE_NAME = "testfile"; 69 70 @Mock private Context mockContext; 71 @Mock private AccountManager mockAccountManager; 72 @Mock private IPackageManager mockIPackageManager; 73 @Mock private PackageManager mockPackageManager; 74 @Mock private ConnectivityManager mockConnectivityManager; 75 76 private Utils mUtils; 77 78 @Override 79 public void setUp() { 80 // this is necessary for mockito to work 81 System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); 82 83 MockitoAnnotations.initMocks(this); 84 85 when(mockContext.getSystemService(Context.ACCOUNT_SERVICE)).thenReturn(mockAccountManager); 86 when(mockContext.getPackageManager()).thenReturn(mockPackageManager); 87 when(mockContext.getSystemService(Context.CONNECTIVITY_SERVICE)) 88 .thenReturn(mockConnectivityManager); 89 90 mUtils = new Utils(); 91 } 92 93 @Override 94 public void tearDown() { 95 mContext.deleteFile(TEST_FILE_NAME); 96 } 97 98 public void testGetCurrentSystemApps() throws Exception { 99 // GIVEN two currently installed apps, one of which is system 100 List<ApplicationInfo> appList = Arrays.asList( 101 createApplicationInfo(TEST_PACKAGE_NAME_1, false), 102 createApplicationInfo(TEST_PACKAGE_NAME_2, true)); 103 when(mockIPackageManager.getInstalledApplications( 104 PackageManager.MATCH_UNINSTALLED_PACKAGES, TEST_USER_ID)) 105 .thenReturn(new ParceledListSlice<ApplicationInfo>(appList)); 106 // WHEN requesting the current system apps 107 Set<String> res = mUtils.getCurrentSystemApps(mockIPackageManager, TEST_USER_ID); 108 // THEN the one system app should be returned 109 assertEquals(1, res.size()); 110 assertTrue(res.contains(TEST_PACKAGE_NAME_2)); 111 } 112 113 public void testSetComponentEnabledSetting() throws Exception { 114 // GIVEN a component name and a user id 115 // WHEN disabling a component 116 mUtils.setComponentEnabledSetting(mockIPackageManager, TEST_COMPONENT_NAME, 117 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, TEST_USER_ID); 118 // THEN the correct method on mockIPackageManager gets invoked 119 verify(mockIPackageManager).setComponentEnabledSetting(eq(TEST_COMPONENT_NAME), 120 eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED), 121 eq(PackageManager.DONT_KILL_APP), 122 eq(TEST_USER_ID)); 123 verifyNoMoreInteractions(mockIPackageManager); 124 } 125 126 public void testPackageRequiresUpdate_notPresent() throws Exception { 127 // GIVEN that the requested package is not present on the device 128 // WHEN checking whether an update is required 129 when(mockPackageManager.getPackageInfo(TEST_PACKAGE_NAME_1, 0)) 130 .thenThrow(new NameNotFoundException()); 131 // THEN an update is required 132 assertTrue(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME_1, 0, mockContext)); 133 } 134 135 public void testPackageRequiresUpdate() throws Exception { 136 // GIVEN a package that is installed on the device 137 PackageInfo pi = new PackageInfo(); 138 pi.packageName = TEST_PACKAGE_NAME_1; 139 pi.versionCode = 1; 140 when(mockPackageManager.getPackageInfo(TEST_PACKAGE_NAME_1, 0)).thenReturn(pi); 141 // WHEN checking whether an update is required 142 // THEN verify that update required returns the correct result depending on the minimum 143 // version code requested. 144 assertFalse(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME_1, 0, mockContext)); 145 assertFalse(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME_1, 1, mockContext)); 146 assertTrue(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME_1, 2, mockContext)); 147 } 148 149 public void testIsConnectedToNetwork() throws Exception { 150 // GIVEN the device is currently connected to mobile network 151 setCurrentNetworkMock(ConnectivityManager.TYPE_MOBILE, true); 152 // WHEN checking connectivity 153 // THEN utils should return true 154 assertTrue(mUtils.isConnectedToNetwork(mockContext)); 155 156 // GIVEN the device is currently connected to wifi 157 setCurrentNetworkMock(ConnectivityManager.TYPE_WIFI, true); 158 // WHEN checking connectivity 159 // THEN utils should return true 160 assertTrue(mUtils.isConnectedToNetwork(mockContext)); 161 162 // GIVEN the device is currently disconnected on wifi 163 setCurrentNetworkMock(ConnectivityManager.TYPE_WIFI, false); 164 // WHEN checking connectivity 165 // THEN utils should return false 166 assertFalse(mUtils.isConnectedToNetwork(mockContext)); 167 } 168 169 public void testIsConnectedToWifi() throws Exception { 170 // GIVEN the device is currently connected to mobile network 171 setCurrentNetworkMock(ConnectivityManager.TYPE_MOBILE, true); 172 // WHEN checking whether connected to wifi 173 // THEN utils should return false 174 assertFalse(mUtils.isConnectedToWifi(mockContext)); 175 176 // GIVEN the device is currently connected to wifi 177 setCurrentNetworkMock(ConnectivityManager.TYPE_WIFI, true); 178 // WHEN checking whether connected to wifi 179 // THEN utils should return true 180 assertTrue(mUtils.isConnectedToWifi(mockContext)); 181 182 // GIVEN the device is currently disconnected on wifi 183 setCurrentNetworkMock(ConnectivityManager.TYPE_WIFI, false); 184 // WHEN checking whether connected to wifi 185 // THEN utils should return false 186 assertFalse(mUtils.isConnectedToWifi(mockContext)); 187 } 188 189 public void testGetActiveNetworkInfo() throws Exception { 190 // GIVEN the device is connected to a network. 191 final NetworkInfo networkInfo = 192 new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0, null, null); 193 when(mockConnectivityManager.getActiveNetworkInfo()).thenReturn(networkInfo); 194 // THEN calling getActiveNetworkInfo should return the correct network info. 195 assertEquals(mUtils.getActiveNetworkInfo(mockContext), networkInfo); 196 } 197 198 public void testCurrentLauncherSupportsManagedProfiles_noLauncherSet() throws Exception { 199 // GIVEN there currently is no default launcher set 200 when(mockPackageManager.resolveActivity(any(Intent.class), anyInt())) 201 .thenReturn(null); 202 // WHEN checking whether the current launcher support managed profiles 203 // THEN utils should return false 204 assertFalse(mUtils.currentLauncherSupportsManagedProfiles(mockContext)); 205 } 206 207 public void testCurrentLauncherSupportsManagedProfiles() throws Exception { 208 // GIVEN the current default launcher is built against lollipop 209 setLauncherMock(Build.VERSION_CODES.LOLLIPOP); 210 // WHEN checking whether the current launcher support managed profiles 211 // THEN utils should return true 212 assertTrue(mUtils.currentLauncherSupportsManagedProfiles(mockContext)); 213 214 // GIVEN the current default launcher is built against kitkat 215 setLauncherMock(Build.VERSION_CODES.KITKAT); 216 // WHEN checking whether the current launcher support managed profiles 217 // THEN utils should return false 218 assertFalse(mUtils.currentLauncherSupportsManagedProfiles(mockContext)); 219 } 220 221 public void testFindDeviceAdmin_ComponentName() throws Exception { 222 // GIVEN a package info with more than one device admin 223 setUpPackage(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME, TEST_DEVICE_ADMIN_NAME_2); 224 225 // THEN calling findDeviceAdmin returns the correct admin 226 assertEquals(TEST_COMPONENT_NAME_2, 227 mUtils.findDeviceAdmin(null, TEST_COMPONENT_NAME_2, mockContext, TEST_USER_ID)); 228 } 229 230 public void testFindDeviceAdmin_PackageName() throws Exception { 231 // GIVEN a package info with one device admin 232 setUpPackage(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME); 233 234 // THEN calling findDeviceAdmin returns the correct admin 235 assertEquals(TEST_COMPONENT_NAME, 236 mUtils.findDeviceAdmin( 237 TEST_PACKAGE_NAME_1, null, mockContext, TEST_USER_ID)); 238 } 239 240 public void testFindDeviceAdmin_NoPackageName() throws Exception { 241 // GIVEN no package info file 242 when(mockPackageManager.getPackageInfoAsUser(TEST_PACKAGE_NAME_1, 243 PackageManager.GET_RECEIVERS | PackageManager.MATCH_DISABLED_COMPONENTS, 244 TEST_USER_ID)) 245 .thenReturn(null); 246 247 // THEN throw IllegalProvisioningArgumentException 248 try { 249 mUtils.findDeviceAdmin( 250 TEST_PACKAGE_NAME_1, null, mockContext, TEST_USER_ID); 251 fail(); 252 } catch (IllegalProvisioningArgumentException e) { 253 // expected 254 } 255 } 256 257 public void testFindDeviceAdmin_AnotherComponentName() throws Exception { 258 // GIVEN a package info with one device admin 259 setUpPackage(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME); 260 261 // THEN looking another device admin throws IllegalProvisioningArgumentException 262 try { 263 mUtils.findDeviceAdmin( 264 null, TEST_COMPONENT_NAME_2, mockContext, TEST_USER_ID); 265 fail(); 266 } catch (IllegalProvisioningArgumentException e) { 267 // expected 268 } 269 } 270 271 public void testFindDeviceAdminInPackageInfo_Success() throws Exception { 272 // GIVEN a package info with one device admin 273 PackageInfo packageInfo = setUpPackage(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME); 274 275 // THEN calling findDeviceAdminInPackageInfo returns the correct admin 276 assertEquals(TEST_COMPONENT_NAME, 277 mUtils.findDeviceAdminInPackageInfo(TEST_PACKAGE_NAME_1, null, packageInfo)); 278 } 279 280 public void testFindDeviceAdminInPackageInfo_PackageNameMismatch() throws Exception { 281 // GIVEN a package info with one device admin 282 PackageInfo packageInfo = setUpPackage(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME); 283 284 // THEN calling findDeviceAdminInPackageInfo with the wrong package name return null 285 assertNull(mUtils.findDeviceAdminInPackageInfo(TEST_PACKAGE_NAME_2, null, packageInfo)); 286 } 287 288 public void testFindDeviceAdminInPackageInfo_NoAdmin() throws Exception { 289 // GIVEN a package info with no device admin 290 PackageInfo packageInfo = setUpPackage(TEST_PACKAGE_NAME_1); 291 292 // THEN calling findDeviceAdminInPackageInfo returns null 293 assertNull(mUtils.findDeviceAdminInPackageInfo(TEST_PACKAGE_NAME_1, null, packageInfo)); 294 } 295 296 public void testFindDeviceAdminInPackageInfo_TwoAdmins() throws Exception { 297 // GIVEN a package info with more than one device admin 298 PackageInfo packageInfo = setUpPackage(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME, 299 TEST_DEVICE_ADMIN_NAME_2); 300 301 // THEN calling findDeviceAdminInPackageInfo returns null 302 assertNull(mUtils.findDeviceAdminInPackageInfo(TEST_PACKAGE_NAME_1, null, packageInfo)); 303 } 304 305 public void testFindDeviceAdminInPackageInfo_TwoAdminsWithComponentName() throws Exception { 306 // GIVEN a package info with more than one device admin 307 PackageInfo packageInfo = setUpPackage(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME, 308 TEST_DEVICE_ADMIN_NAME_2); 309 310 // THEN calling findDeviceAdminInPackageInfo return component 1 311 assertEquals(TEST_COMPONENT_NAME, mUtils.findDeviceAdminInPackageInfo( 312 TEST_PACKAGE_NAME_1, TEST_COMPONENT_NAME, packageInfo)); 313 } 314 315 316 public void testFindDeviceAdminInPackageInfo_InvalidComponentName() throws Exception { 317 // GIVEN a package info with component 1 318 PackageInfo packageInfo = setUpPackage(TEST_PACKAGE_NAME_1, TEST_DEVICE_ADMIN_NAME); 319 320 // THEN calling findDeviceAdminInPackageInfo with component 2 returns null 321 assertNull(mUtils.findDeviceAdminInPackageInfo( 322 TEST_PACKAGE_NAME_1, TEST_COMPONENT_NAME_2, packageInfo)); 323 } 324 325 public void testComputeHashOfByteArray() { 326 // GIVEN a byte array 327 byte[] bytes = "TESTARRAY".getBytes(); 328 // GIVEN its Sha256 hash 329 byte[] sha256 = new byte[] {100, -45, -118, -68, -104, -15, 63, -60, -84, -44, -13, -63, 330 53, -50, 104, -63, 38, 122, 16, -44, -85, -50, 67, 98, 78, 121, 11, 72, 79, 40, 107, 331 125}; 332 333 // THEN computeHashOfByteArray returns the correct result 334 assertTrue(Arrays.equals(sha256, mUtils.computeHashOfByteArray(bytes))); 335 } 336 337 public void testComputeHashOfFile() { 338 // GIVEN a file with test data 339 final String fileLocation = getContext().getFilesDir().toString() + "/" + TEST_FILE_NAME; 340 String string = "Hello world!"; 341 FileOutputStream outputStream; 342 try { 343 outputStream = getContext().openFileOutput(TEST_FILE_NAME, Context.MODE_PRIVATE); 344 outputStream.write(string.getBytes()); 345 outputStream.close(); 346 } catch (Exception e) { 347 e.printStackTrace(); 348 } 349 // GIVEN the file's Sha256 hash 350 byte[] sha256 = new byte[] {-64, 83, 94, 75, -30, -73, -97, -3, -109, 41, 19, 5, 67, 107, 351 -8, -119, 49, 78, 74, 63, -82, -64, 94, -49, -4, -69, 125, -13, 26, -39, -27, 26}; 352 // GIVEN the file's Sha1 hash 353 byte[] sha1 = new byte[] {-45, 72, 106, -23, 19, 110, 120, 86, -68, 66, 33, 35, -123, -22, 354 121, 112, -108, 71, 88, 2}; 355 356 //THEN the Sha256 hash is correct 357 assertTrue( 358 Arrays.equals(sha256, mUtils.computeHashOfFile(fileLocation, Utils.SHA256_TYPE))); 359 //THEN the Sha1 hash is correct 360 assertTrue(Arrays.equals(sha1, mUtils.computeHashOfFile(fileLocation, Utils.SHA1_TYPE))); 361 } 362 363 public void testComputeHashOfFile_NotPresent() { 364 // GIVEN no file is present 365 final String fileLocation = getContext().getFilesDir().toString() + "/" + TEST_FILE_NAME; 366 getContext().deleteFile(TEST_FILE_NAME); 367 368 // THEN computeHashOfFile should return null 369 assertNull(mUtils.computeHashOfFile(fileLocation, Utils.SHA256_TYPE)); 370 assertNull(mUtils.computeHashOfFile(fileLocation, Utils.SHA1_TYPE)); 371 } 372 373 public void testBrightColors() { 374 assertTrue(mUtils.isBrightColor(Color.WHITE)); 375 assertTrue(mUtils.isBrightColor(Color.YELLOW)); 376 assertFalse(mUtils.isBrightColor(Color.BLACK)); 377 assertFalse(mUtils.isBrightColor(Color.BLUE)); 378 } 379 380 public void testCanResolveIntentAsUser() { 381 // GIVEN intent is null 382 // THEN intent should not be resolved 383 assertFalse(mUtils.canResolveIntentAsUser(mockContext, null, TEST_USER_ID)); 384 385 // GIVEN a valid intent 386 Intent intent = new Intent(); 387 388 // WHEN resolve activity as user returns null 389 when(mockPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 390 .thenReturn(null); 391 // THEN intent should not be resolved for user 392 assertFalse(mUtils.canResolveIntentAsUser(mockContext, intent, TEST_USER_ID)); 393 394 // WHEN resolve activity as user returns valid resolve info 395 when(mockPackageManager.resolveActivityAsUser(any(Intent.class), anyInt(), anyInt())) 396 .thenReturn(new ResolveInfo()); 397 // THEN intent should be resolved 398 assertTrue(mUtils.canResolveIntentAsUser(mockContext, intent, TEST_USER_ID)); 399 } 400 401 private ApplicationInfo createApplicationInfo(String packageName, boolean system) { 402 ApplicationInfo ai = new ApplicationInfo(); 403 ai.packageName = packageName; 404 if (system) { 405 ai.flags = ApplicationInfo.FLAG_SYSTEM; 406 } 407 return ai; 408 } 409 410 private void setCurrentNetworkMock(int type, boolean connected) { 411 NetworkInfo networkInfo = new NetworkInfo(type, 0, null, null); 412 networkInfo.setDetailedState( 413 connected ? NetworkInfo.DetailedState.CONNECTED 414 : NetworkInfo.DetailedState.DISCONNECTED, 415 null, null); 416 when(mockConnectivityManager.getActiveNetworkInfo()).thenReturn(networkInfo); 417 } 418 419 private void setLauncherMock(int targetSdkVersion) throws Exception { 420 ApplicationInfo appInfo = new ApplicationInfo(); 421 appInfo.targetSdkVersion = targetSdkVersion; 422 ActivityInfo actInfo = new ActivityInfo(); 423 actInfo.packageName = TEST_PACKAGE_NAME_1; 424 ResolveInfo resInfo = new ResolveInfo(); 425 resInfo.activityInfo = actInfo; 426 427 when(mockPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(resInfo); 428 when(mockPackageManager.getApplicationInfo(TEST_PACKAGE_NAME_1, 0)).thenReturn(appInfo); 429 } 430 431 private PackageInfo setUpPackage(String packageName, String... adminNames) 432 throws NameNotFoundException { 433 PackageInfo packageInfo = new PackageInfo(); 434 packageInfo.packageName = packageName; 435 packageInfo.receivers = new ActivityInfo[adminNames.length]; 436 for (int i = 0; i < adminNames.length; i++) { 437 ActivityInfo receiver = new ActivityInfo(); 438 receiver.permission = android.Manifest.permission.BIND_DEVICE_ADMIN; 439 receiver.name = adminNames[i]; 440 packageInfo.receivers[i] = receiver; 441 } 442 when(mockPackageManager.getPackageInfoAsUser(packageName, 443 PackageManager.GET_RECEIVERS | PackageManager.MATCH_DISABLED_COMPONENTS, 444 TEST_USER_ID)) 445 .thenReturn(packageInfo); 446 447 return packageInfo; 448 } 449 } 450