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