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 android.accounts.Account;
     20 import android.accounts.AccountManager;
     21 import android.accounts.AccountManagerCallback;
     22 import android.accounts.AccountManagerFuture;
     23 import android.accounts.OperationCanceledException;
     24 import android.content.ComponentName;
     25 import android.content.Context;
     26 import android.content.Intent;
     27 import android.content.pm.ActivityInfo;
     28 import android.content.pm.ApplicationInfo;
     29 import android.content.pm.IPackageManager;
     30 import android.content.pm.PackageManager;
     31 import android.content.pm.PackageManager.NameNotFoundException;
     32 import android.content.pm.PackageInfo;
     33 import android.content.pm.ParceledListSlice;
     34 import android.content.pm.ResolveInfo;
     35 import android.graphics.Color;
     36 import android.net.ConnectivityManager;
     37 import android.net.NetworkInfo;
     38 import android.os.Build;
     39 import android.os.Handler;
     40 import android.os.UserHandle;
     41 import android.test.AndroidTestCase;
     42 import android.test.suitebuilder.annotation.SmallTest;
     43 
     44 import org.mockito.Mock;
     45 import org.mockito.MockitoAnnotations;
     46 
     47 import java.util.Arrays;
     48 import java.util.concurrent.TimeUnit;
     49 import java.util.List;
     50 import java.util.Set;
     51 
     52 import static org.mockito.Mockito.any;
     53 import static org.mockito.Mockito.anyInt;
     54 import static org.mockito.Mockito.anyLong;
     55 import static org.mockito.Mockito.eq;
     56 import static org.mockito.Mockito.mock;
     57 import static org.mockito.Mockito.verify;
     58 import static org.mockito.Mockito.verifyNoMoreInteractions;
     59 import static org.mockito.Mockito.verifyZeroInteractions;
     60 import static org.mockito.Mockito.when;
     61 
     62 /**
     63  * Unit-tests for {@link Utils}.
     64  */
     65 @SmallTest
     66 public class UtilsTest extends AndroidTestCase {
     67     private static final String TEST_PACKAGE_NAME_1 = "com.test.packagea";
     68     private static final String TEST_PACKAGE_NAME_2 = "com.test.packageb";
     69     private static final ComponentName TEST_COMPONENT_NAME = new ComponentName(TEST_PACKAGE_NAME_1,
     70             ".MainActivity");
     71     private static final int TEST_USER_ID = 10;
     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     public void testGetCurrentSystemApps() throws Exception {
     97         // GIVEN two currently installed apps, one of which is system
     98         List<ApplicationInfo> appList = Arrays.asList(
     99                 createApplicationInfo(TEST_PACKAGE_NAME_1, false),
    100                 createApplicationInfo(TEST_PACKAGE_NAME_2, true));
    101         when(mockIPackageManager.getInstalledApplications(
    102                 PackageManager.GET_UNINSTALLED_PACKAGES, TEST_USER_ID))
    103                 .thenReturn(new ParceledListSlice(appList));
    104         // WHEN requesting the current system apps
    105         Set<String> res = mUtils.getCurrentSystemApps(mockIPackageManager, TEST_USER_ID);
    106         // THEN the one system app should be returned
    107         assertEquals(1, res.size());
    108         assertTrue(res.contains(TEST_PACKAGE_NAME_2));
    109     }
    110 
    111     public void testSetComponentEnabledSetting() throws Exception {
    112         // GIVEN a component name and a user id
    113         // WHEN disabling a component
    114         mUtils.setComponentEnabledSetting(mockIPackageManager, TEST_COMPONENT_NAME,
    115                 PackageManager.COMPONENT_ENABLED_STATE_DISABLED, TEST_USER_ID);
    116         // THEN the correct method on mockIPackageManager gets invoked
    117         verify(mockIPackageManager).setComponentEnabledSetting(eq(TEST_COMPONENT_NAME),
    118                 eq(PackageManager.COMPONENT_ENABLED_STATE_DISABLED),
    119                 eq(PackageManager.DONT_KILL_APP),
    120                 eq(TEST_USER_ID));
    121         verifyNoMoreInteractions(mockIPackageManager);
    122     }
    123 
    124     public void testPackageRequiresUpdate_notPresent() throws Exception {
    125         // GIVEN that the requested package is not present on the device
    126         // WHEN checking whether an update is required
    127         when(mockPackageManager.getPackageInfo(TEST_PACKAGE_NAME_1, 0))
    128                 .thenThrow(new NameNotFoundException());
    129         // THEN an update is required
    130         assertTrue(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME_1, 0, mockContext));
    131     }
    132 
    133     public void testPackageRequiresUpdate() throws Exception {
    134         // GIVEN a package that is installed on the device
    135         PackageInfo pi = new PackageInfo();
    136         pi.packageName = TEST_PACKAGE_NAME_1;
    137         pi.versionCode = 1;
    138         when(mockPackageManager.getPackageInfo(TEST_PACKAGE_NAME_1, 0)).thenReturn(pi);
    139         // WHEN checking whether an update is required
    140         // THEN verify that update required returns the correct result depending on the minimum
    141         // version code requested.
    142         assertFalse(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME_1, 0, mockContext));
    143         assertFalse(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME_1, 1, mockContext));
    144         assertTrue(mUtils.packageRequiresUpdate(TEST_PACKAGE_NAME_1, 2, mockContext));
    145     }
    146 
    147     public void testMaybeCopyAccount_success() throws Exception {
    148         // GIVEN an account on the source user and a managed profile present and no timeout
    149         // or error during migration
    150         Account testAccount = new Account("test (at) afw-test.com", "com.google");
    151         UserHandle primaryUser = UserHandle.of(0);
    152         UserHandle managedProfile = UserHandle.of(10);
    153 
    154         AccountManagerFuture mockResult = mock(AccountManagerFuture.class);
    155         when(mockResult.getResult(anyLong(), any(TimeUnit.class))).thenReturn(true);
    156         when(mockAccountManager.copyAccountToUser(any(Account.class), any(UserHandle.class),
    157                 any(UserHandle.class), any(AccountManagerCallback.class), any(Handler.class)))
    158                 .thenReturn(mockResult);
    159 
    160         // WHEN copying the account from the source user to the target user
    161         // THEN the account migration succeeds
    162         assertTrue(mUtils.maybeCopyAccount(mockContext, testAccount, primaryUser, managedProfile));
    163         verify(mockAccountManager).copyAccountToUser(eq(testAccount), eq(primaryUser),
    164                 eq(managedProfile), any(AccountManagerCallback.class), any(Handler.class));
    165         verify(mockResult).getResult(anyLong(), any(TimeUnit.class));
    166     }
    167 
    168     public void testMaybeCopyAccount_error() throws Exception {
    169         // GIVEN an account on the source user and a target user present and an error occurs
    170         // during migration
    171         Account testAccount = new Account("test (at) afw-test.com", "com.google");
    172         UserHandle primaryUser = UserHandle.of(0);
    173         UserHandle managedProfile = UserHandle.of(10);
    174 
    175         AccountManagerFuture mockResult = mock(AccountManagerFuture.class);
    176         when(mockResult.getResult(anyLong(), any(TimeUnit.class))).thenReturn(false);
    177         when(mockAccountManager.copyAccountToUser(any(Account.class), any(UserHandle.class),
    178                 any(UserHandle.class), any(AccountManagerCallback.class), any(Handler.class)))
    179                 .thenReturn(mockResult);
    180 
    181         // WHEN copying the account from the source user to the target user
    182         // THEN the account migration fails
    183         assertFalse(mUtils.maybeCopyAccount(mockContext, testAccount, primaryUser, managedProfile));
    184         verify(mockAccountManager).copyAccountToUser(eq(testAccount), eq(primaryUser),
    185                 eq(managedProfile), any(AccountManagerCallback.class), any(Handler.class));
    186         verify(mockResult).getResult(anyLong(), any(TimeUnit.class));
    187     }
    188 
    189     public void testMaybeCopyAccount_timeout() throws Exception {
    190         // GIVEN an account on the source user and a target user present and a timeout occurs
    191         // during migration
    192         Account testAccount = new Account("test (at) afw-test.com", "com.google");
    193         UserHandle primaryUser = UserHandle.of(0);
    194         UserHandle managedProfile = UserHandle.of(10);
    195 
    196         AccountManagerFuture mockResult = mock(AccountManagerFuture.class);
    197         // the AccountManagerFuture throws an OperationCanceledException after timeout
    198         when(mockResult.getResult(anyLong(), any(TimeUnit.class)))
    199                 .thenThrow(new OperationCanceledException());
    200         when(mockAccountManager.copyAccountToUser(any(Account.class), any(UserHandle.class),
    201                 any(UserHandle.class), any(AccountManagerCallback.class), any(Handler.class)))
    202                 .thenReturn(mockResult);
    203 
    204         // WHEN copying the account from the source user to the target user
    205         // THEN the account migration fails
    206         assertFalse(mUtils.maybeCopyAccount(mockContext, testAccount, primaryUser, managedProfile));
    207         verify(mockAccountManager).copyAccountToUser(eq(testAccount), eq(primaryUser),
    208                 eq(managedProfile), any(AccountManagerCallback.class), any(Handler.class));
    209         verify(mockResult).getResult(anyLong(), any(TimeUnit.class));
    210     }
    211 
    212     public void testMaybeCopyAccount_nullAccount() {
    213         // GIVEN a device with two users present
    214         UserHandle primaryUser = UserHandle.of(0);
    215         UserHandle managedProfile = UserHandle.of(10);
    216 
    217         // WHEN trying to copy a null account from the source user to the target user
    218         // THEN request is ignored
    219         assertFalse(mUtils.maybeCopyAccount(mockContext, null /* accountToMigrate */, primaryUser,
    220                 managedProfile));
    221         verifyZeroInteractions(mockAccountManager);
    222     }
    223 
    224     public void testMaybeCopyAccount_sameUser() {
    225         // GIVEN an account on a user
    226         Account testAccount = new Account("test (at) afw-test.com", "com.google");
    227         UserHandle primaryUser = UserHandle.of(0);
    228 
    229         // WHEN trying to invoke copying an account with the same user id for source and target user
    230         // THEN request is ignored
    231         assertFalse(mUtils.maybeCopyAccount(mockContext, testAccount, primaryUser, primaryUser));
    232         verifyZeroInteractions(mockAccountManager);
    233     }
    234 
    235     public void testIsConnectedToNetwork() throws Exception {
    236         // GIVEN the device is currently connected to mobile network
    237         setCurrentNetworkMock(ConnectivityManager.TYPE_MOBILE, true);
    238         // WHEN checking connectivity
    239         // THEN utils should return true
    240         assertTrue(mUtils.isConnectedToNetwork(mockContext));
    241 
    242         // GIVEN the device is currently connected to wifi
    243         setCurrentNetworkMock(ConnectivityManager.TYPE_WIFI, true);
    244         // WHEN checking connectivity
    245         // THEN utils should return true
    246         assertTrue(mUtils.isConnectedToNetwork(mockContext));
    247 
    248         // GIVEN the device is currently disconnected on wifi
    249         setCurrentNetworkMock(ConnectivityManager.TYPE_WIFI, false);
    250         // WHEN checking connectivity
    251         // THEN utils should return false
    252         assertFalse(mUtils.isConnectedToNetwork(mockContext));
    253     }
    254 
    255     public void testIsConnectedToWifi() throws Exception {
    256         // GIVEN the device is currently connected to mobile network
    257         setCurrentNetworkMock(ConnectivityManager.TYPE_MOBILE, true);
    258         // WHEN checking whether connected to wifi
    259         // THEN utils should return false
    260         assertFalse(mUtils.isConnectedToWifi(mockContext));
    261 
    262         // GIVEN the device is currently connected to wifi
    263         setCurrentNetworkMock(ConnectivityManager.TYPE_WIFI, true);
    264         // WHEN checking whether connected to wifi
    265         // THEN utils should return true
    266         assertTrue(mUtils.isConnectedToWifi(mockContext));
    267 
    268         // GIVEN the device is currently disconnected on wifi
    269         setCurrentNetworkMock(ConnectivityManager.TYPE_WIFI, false);
    270         // WHEN checking whether connected to wifi
    271         // THEN utils should return false
    272         assertFalse(mUtils.isConnectedToWifi(mockContext));
    273     }
    274 
    275     public void testCurrentLauncherSupportsManagedProfiles_noLauncherSet() throws Exception {
    276         // GIVEN there currently is no default launcher set
    277         when(mockPackageManager.resolveActivity(any(Intent.class), anyInt()))
    278                 .thenReturn(null);
    279         // WHEN checking whether the current launcher support managed profiles
    280         // THEN utils should return false
    281         assertFalse(mUtils.currentLauncherSupportsManagedProfiles(mockContext));
    282     }
    283 
    284     public void testCurrentLauncherSupportsManagedProfiles() throws Exception {
    285         // GIVEN the current default launcher is built against lollipop
    286         setLauncherMock(Build.VERSION_CODES.LOLLIPOP);
    287         // WHEN checking whether the current launcher support managed profiles
    288         // THEN utils should return true
    289         assertTrue(mUtils.currentLauncherSupportsManagedProfiles(mockContext));
    290 
    291         // GIVEN the current default launcher is built against kitkat
    292         setLauncherMock(Build.VERSION_CODES.KITKAT);
    293         // WHEN checking whether the current launcher support managed profiles
    294         // THEN utils should return false
    295         assertFalse(mUtils.currentLauncherSupportsManagedProfiles(mockContext));
    296     }
    297 
    298     private ApplicationInfo createApplicationInfo(String packageName, boolean system) {
    299         ApplicationInfo ai = new ApplicationInfo();
    300         ai.packageName = packageName;
    301         if (system) {
    302             ai.flags = ApplicationInfo.FLAG_SYSTEM;
    303         }
    304         return ai;
    305     }
    306 
    307     private void setCurrentNetworkMock(int type, boolean connected) {
    308         NetworkInfo networkInfo = new NetworkInfo(type, 0, null, null);
    309         networkInfo.setDetailedState(
    310                 connected ? NetworkInfo.DetailedState.CONNECTED
    311                         : NetworkInfo.DetailedState.DISCONNECTED,
    312                 null, null);
    313         when(mockConnectivityManager.getActiveNetworkInfo()).thenReturn(networkInfo);
    314     }
    315 
    316     private void setLauncherMock(int targetSdkVersion) throws Exception {
    317         ApplicationInfo appInfo = new ApplicationInfo();
    318         appInfo.targetSdkVersion = targetSdkVersion;
    319         ActivityInfo actInfo = new ActivityInfo();
    320         actInfo.packageName = TEST_PACKAGE_NAME_1;
    321         ResolveInfo resInfo = new ResolveInfo();
    322         resInfo.activityInfo = actInfo;
    323 
    324         when(mockPackageManager.resolveActivity(any(Intent.class), anyInt())).thenReturn(resInfo);
    325         when(mockPackageManager.getApplicationInfo(TEST_PACKAGE_NAME_1, 0)).thenReturn(appInfo);
    326     }
    327 }
    328