Home | History | Annotate | Download | only in common
      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