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