1 /* 2 * Copyright 2019, 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.finalization; 18 19 import static android.app.admin.DevicePolicyManager.ACTION_ADMIN_POLICY_COMPLIANCE; 20 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_DEVICE; 21 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_PROFILE; 22 import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE; 23 24 import static com.android.managedprovisioning.TestUtils.createTestAdminExtras; 25 26 import static com.google.common.truth.Truth.assertThat; 27 28 import static org.mockito.ArgumentMatchers.anyString; 29 import static org.mockito.Matchers.any; 30 import static org.mockito.Matchers.anyInt; 31 import static org.mockito.Matchers.eq; 32 import static org.mockito.Mockito.mock; 33 import static org.mockito.Mockito.never; 34 import static org.mockito.Mockito.times; 35 import static org.mockito.Mockito.verify; 36 import static org.mockito.Mockito.verifyNoMoreInteractions; 37 import static org.mockito.Mockito.verifyZeroInteractions; 38 import static org.mockito.Mockito.when; 39 40 import android.accounts.Account; 41 import android.app.Activity; 42 import android.app.admin.DevicePolicyManager; 43 import android.content.ComponentName; 44 import android.content.Context; 45 import android.content.Intent; 46 import android.content.ServiceConnection; 47 import android.content.SharedPreferences; 48 import android.content.pm.PackageManager; 49 import android.os.Bundle; 50 import android.os.PersistableBundle; 51 import android.os.UserHandle; 52 import android.os.UserManager; 53 import android.test.AndroidTestCase; 54 import android.test.suitebuilder.annotation.SmallTest; 55 56 import androidx.test.InstrumentationRegistry; 57 58 import com.android.managedprovisioning.TestUtils; 59 import com.android.managedprovisioning.analytics.DeferredMetricsReader; 60 import com.android.managedprovisioning.analytics.ProvisioningAnalyticsTracker; 61 import com.android.managedprovisioning.common.NotificationHelper; 62 import com.android.managedprovisioning.common.PolicyComplianceUtils; 63 import com.android.managedprovisioning.common.SettingsFacade; 64 import com.android.managedprovisioning.common.TransitionHelper; 65 import com.android.managedprovisioning.common.Utils; 66 import com.android.managedprovisioning.model.ProvisioningParams; 67 68 import org.mockito.ArgumentCaptor; 69 import org.mockito.Mock; 70 import org.mockito.MockitoAnnotations; 71 72 /** 73 * Unit tests for {@link FinalizationInsideSuwControllerLogic}. 74 */ 75 public class FinalizationInsideSuwControllerTest extends AndroidTestCase { 76 private static final UserHandle MANAGED_PROFILE_USER_HANDLE = UserHandle.of(123); 77 private static final String TEST_MDM_PACKAGE_NAME = "mdm.package.name"; 78 private static final String TEST_MDM_ADMIN_RECEIVER = TEST_MDM_PACKAGE_NAME + ".AdminReceiver"; 79 private static final ComponentName TEST_MDM_ADMIN = new ComponentName(TEST_MDM_PACKAGE_NAME, 80 TEST_MDM_ADMIN_RECEIVER); 81 private static final PersistableBundle TEST_MDM_EXTRA_BUNDLE = createTestAdminExtras(); 82 private static final Account TEST_ACCOUNT = new Account("test@account.com", "account.type"); 83 private static final Intent ACTIVITY_INTENT = 84 new Intent("android.app.action.PROVISION_FINALIZATION_INSIDE_SUW"); 85 86 @Mock private Activity mActivity; 87 @Mock private Utils mUtils; 88 @Mock private SettingsFacade mSettingsFacade; 89 @Mock private UserProvisioningStateHelper mHelper; 90 @Mock private NotificationHelper mNotificationHelper; 91 @Mock private DeferredMetricsReader mDeferredMetricsReader; 92 @Mock private ProvisioningAnalyticsTracker mProvisioningAnalyticsTracker; 93 @Mock private UserManager mUserManager; 94 @Mock private DevicePolicyManager mDevicePolicyManager; 95 @Mock private SharedPreferences mSharedPreferences; 96 97 private PreFinalizationController mPreFinalizationController; 98 private FinalizationController mFinalizationController; 99 private final Context mTargetContext = InstrumentationRegistry.getTargetContext(); 100 @Mock private TransitionHelper mTransitionHelper; 101 102 @Override setUp()103 public void setUp() throws Exception { 104 // this is necessary for mockito to work 105 System.setProperty("dexmaker.dexcache", getContext().getCacheDir().toString()); 106 MockitoAnnotations.initMocks(this); 107 when(mActivity.getSystemService(Context.DEVICE_POLICY_SERVICE)) 108 .thenReturn(mDevicePolicyManager); 109 when(mActivity.getSystemServiceName(DevicePolicyManager.class)) 110 .thenReturn(Context.DEVICE_POLICY_SERVICE); 111 when(mUtils.canResolveIntentAsUser(any(Context.class), any(Intent.class), anyInt())) 112 .thenReturn(true); 113 when(mActivity.getFilesDir()).thenReturn(getContext().getFilesDir()); 114 when(mActivity.getIntent()).thenReturn(ACTIVITY_INTENT); 115 when(mActivity.bindService(any(Intent.class), any(ServiceConnection.class), anyInt())) 116 .thenReturn(false); 117 when(mActivity.getSystemServiceName(UserManager.class)) 118 .thenReturn(Context.USER_SERVICE); 119 when(mActivity.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager); 120 when(mActivity.getSharedPreferences(anyString(), anyInt())).thenReturn(mSharedPreferences); 121 when(mActivity.getResources()).thenReturn(mTargetContext.getResources()); 122 when(mUserManager.isUserUnlocked(anyInt())).thenReturn(true); 123 when(mUserManager.isUserUnlocked(any(UserHandle.class))).thenReturn(true); 124 125 final ProvisioningParamsUtils provisioningParamsUtils = new ProvisioningParamsUtils(); 126 mPreFinalizationController = new PreFinalizationController( 127 mActivity, mUtils, mSettingsFacade, mHelper, 128 provisioningParamsUtils, new SendDpcBroadcastServiceUtils()); 129 mFinalizationController = new FinalizationController( 130 mActivity, 131 new FinalizationInsideSuwControllerLogic( 132 mActivity, 133 mUtils, 134 new PolicyComplianceUtils(), 135 mProvisioningAnalyticsTracker, 136 mTransitionHelper), 137 mUtils, mSettingsFacade, mHelper, mNotificationHelper, mDeferredMetricsReader, 138 provisioningParamsUtils); 139 } 140 141 @Override tearDown()142 public void tearDown() throws Exception { 143 mFinalizationController.clearParamsFile(); 144 } 145 146 @SmallTest testFinalized_alreadyCalled()147 public void testFinalized_alreadyCalled() { 148 // GIVEN that deviceManagementEstablished has already been called 149 when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(true); 150 final ProvisioningParams params = createProvisioningParams( 151 ACTION_PROVISION_MANAGED_PROFILE, false); 152 153 // WHEN calling provisioningFinalized and commitFinalizedState 154 mFinalizationController.provisioningFinalized(); 155 mFinalizationController.commitFinalizedState(); 156 157 // THEN nothing should happen 158 verify(mHelper, never()).markUserProvisioningStateInitiallyDone(params); 159 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 160 verifyZeroInteractions(mDeferredMetricsReader); 161 } 162 163 @SmallTest testFinalized_noParamsStored()164 public void testFinalized_noParamsStored() { 165 // GIVEN that the user provisioning state is correct 166 when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(false); 167 168 // WHEN calling provisioningFinalized and commitFinalizedState 169 mFinalizationController.provisioningFinalized(); 170 mFinalizationController.commitFinalizedState(); 171 172 // THEN nothing should happen 173 verify(mHelper, never()) 174 .markUserProvisioningStateInitiallyDone(any(ProvisioningParams.class)); 175 verify(mHelper, never()).markUserProvisioningStateFinalized(any(ProvisioningParams.class)); 176 verifyZeroInteractions(mDeferredMetricsReader); 177 } 178 179 @SmallTest testManagedProfileFinalizationDuringSuw()180 public void testManagedProfileFinalizationDuringSuw() { 181 // GIVEN that the DPC is not available on the primary profile 182 when(mUtils.canResolveIntentAsUser(eq(mActivity), any(Intent.class), 183 eq(UserHandle.USER_SYSTEM))).thenReturn(false); 184 // GIVEN that deviceManagementEstablished has never been called 185 when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(true); 186 // GIVEN that we've provisioned a managed profile after SUW 187 final ProvisioningParams params = createProvisioningParams( 188 ACTION_PROVISION_MANAGED_PROFILE, true); 189 when(mSettingsFacade.isUserSetupCompleted(mActivity)).thenReturn(false); 190 when(mSettingsFacade.isDuringSetupWizard(mActivity)).thenReturn(true); 191 when(mUtils.getManagedProfile(mActivity)).thenReturn(MANAGED_PROFILE_USER_HANDLE); 192 193 // WHEN calling deviceManagementEstablished 194 mPreFinalizationController.deviceManagementEstablished(params); 195 196 // THEN the user provisioning state should be marked as initially done 197 verify(mHelper).markUserProvisioningStateInitiallyDone(params); 198 // THEN the provisioning params have been stored and will be read in provisioningFinalized 199 200 // GIVEN that the provisioning state is now incomplete 201 when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(false); 202 203 // WHEN we save and restore controller state 204 saveAndRestoreControllerState(); 205 206 // THEN the user provisioning state is not yet finalized 207 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 208 209 // THEN no intent should be sent to the dpc. 210 verify(mTransitionHelper, never()).startActivityForResultAsUserWithTransition( 211 eq(mActivity), any(Intent.class), anyInt(), eq(MANAGED_PROFILE_USER_HANDLE)); 212 213 // WHEN calling provisioningFinalized 214 mFinalizationController.provisioningFinalized(); 215 216 // THEN the user provisioning state is not yet finalized 217 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 218 219 // THEN intent should be sent to the dpc. 220 verifyDpcLaunchedForUser(MANAGED_PROFILE_USER_HANDLE, 1); 221 222 // WHEN calling provisioningFinalized again 223 mFinalizationController.provisioningFinalized(); 224 225 // THEN the user provisioning state is not yet finalized 226 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 227 228 // THEN intent should not be sent to the dpc again 229 verifyDpcLaunchedForUser(MANAGED_PROFILE_USER_HANDLE, 1); 230 231 // WHEN simulating a DPC cancel by calling activityDestroyed(true), and then 232 // provisioningFinalized again 233 mFinalizationController.activityDestroyed(true); 234 mFinalizationController.provisioningFinalized(); 235 236 // THEN the user provisioning state is not yet finalized 237 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 238 239 // THEN intent should be sent to the dpc again 240 verifyDpcLaunchedForUser(MANAGED_PROFILE_USER_HANDLE, 2); 241 242 // WHEN we save and restore controller state, and then call provisioningFinalized again 243 saveAndRestoreControllerState(); 244 mFinalizationController.provisioningFinalized(); 245 246 // THEN the user provisioning state is not yet finalized 247 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 248 249 // THEN intent is not sent to the dpc again 250 verifyDpcLaunchedForUser(MANAGED_PROFILE_USER_HANDLE, 2); 251 252 // WHEN the provisioning state changes are now committed 253 mFinalizationController.commitFinalizedState(); 254 255 // THEN deferred metrics have been written exactly once 256 verify(mDeferredMetricsReader).scheduleDumpMetrics(any(Context.class)); 257 verifyNoMoreInteractions(mDeferredMetricsReader); 258 259 // THEN the user provisioning state is finalized 260 verify(mHelper).markUserProvisioningStateFinalized(params); 261 262 // THEN the service which starts the DPC, has never been started. 263 verifySendDpcServiceNotStarted(); 264 } 265 266 @SmallTest testDeviceOwnerFinalizationDuringSuw()267 public void testDeviceOwnerFinalizationDuringSuw() { 268 // GIVEN that deviceManagementEstablished has never been called 269 when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(true); 270 // GIVEN that we've provisioned a device owner during SUW 271 final ProvisioningParams params = createProvisioningParams( 272 ACTION_PROVISION_MANAGED_DEVICE, false); 273 when(mSettingsFacade.isUserSetupCompleted(mActivity)).thenReturn(false); 274 when(mSettingsFacade.isDuringSetupWizard(mActivity)).thenReturn(true); 275 276 // WHEN calling deviceManagementEstablished 277 mPreFinalizationController.deviceManagementEstablished(params); 278 279 // THEN the user provisioning state should be marked as initially done 280 verify(mHelper).markUserProvisioningStateInitiallyDone(params); 281 // THEN the provisioning params have been stored and will be read in provisioningFinalized 282 283 // GIVEN that the provisioning state is now incomplete 284 when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(false); 285 286 // WHEN we save and restore controller state 287 saveAndRestoreControllerState(); 288 289 // THEN the user provisioning state is not yet finalized 290 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 291 292 // THEN no intent should be sent to the dpc. 293 verify(mTransitionHelper, never()).startActivityForResultAsUserWithTransition( 294 eq(mActivity), any(Intent.class), anyInt(), 295 eq(UserHandle.of(UserHandle.myUserId()))); 296 297 // WHEN calling provisioningFinalized 298 mFinalizationController.provisioningFinalized(); 299 300 // THEN the user provisioning state is not yet finalized 301 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 302 303 // THEN intent should be sent to the dpc. 304 verifyDpcLaunchedForUser(UserHandle.of(UserHandle.myUserId()), 1); 305 306 // WHEN calling provisioningFinalized again 307 mFinalizationController.provisioningFinalized(); 308 309 // THEN the user provisioning state is not yet finalized 310 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 311 312 // THEN intent should not be sent to the dpc again 313 verifyDpcLaunchedForUser(UserHandle.of(UserHandle.myUserId()), 1); 314 315 // WHEN simulating a DPC cancel by calling activityDestroyed(true), and then 316 // provisioningFinalized again 317 mFinalizationController.activityDestroyed(true); 318 mFinalizationController.provisioningFinalized(); 319 320 // THEN the user provisioning state is not yet finalized 321 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 322 323 // THEN intent should be sent to the dpc again 324 verifyDpcLaunchedForUser(UserHandle.of(UserHandle.myUserId()), 2); 325 326 // WHEN we save and restore controller state, and then call provisioningFinalized again 327 saveAndRestoreControllerState(); 328 mFinalizationController.provisioningFinalized(); 329 330 // THEN the user provisioning state is not yet finalized 331 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 332 333 // THEN intent should not be sent to the dpc again 334 verifyDpcLaunchedForUser(UserHandle.of(UserHandle.myUserId()), 2); 335 336 // WHEN the provisioning state changes are now committed 337 mFinalizationController.commitFinalizedState(); 338 339 // THEN deferred metrics have been written exactly once 340 verify(mDeferredMetricsReader).scheduleDumpMetrics(any(Context.class)); 341 verifyNoMoreInteractions(mDeferredMetricsReader); 342 343 // THEN the user provisioning state is finalized 344 verify(mHelper).markUserProvisioningStateFinalized(params); 345 346 // THEN a privacy reminder is shown to the user exactly once 347 verify(mNotificationHelper).showPrivacyReminderNotification(eq(mActivity), anyInt()); 348 349 // THEN no broadcast was ever sent to the primary user 350 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 351 verify(mActivity, never()).sendBroadcast(intentCaptor.capture()); 352 } 353 354 @SmallTest testCorpOwnedManagedProfileDuringSuw()355 public void testCorpOwnedManagedProfileDuringSuw() throws PackageManager.NameNotFoundException { 356 // GIVEN that deviceManagementEstablished has never been called 357 when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(true); 358 // GIVEN that we're provisioning a corp-owned managed profile DURING SUW 359 final ProvisioningParams params = 360 createProvisioningParamsBuilder(ACTION_PROVISION_MANAGED_PROFILE, true) 361 .setIsOrganizationOwnedProvisioning(true) 362 .setFlowType(ProvisioningParams.FLOW_TYPE_ADMIN_INTEGRATED) 363 .build(); 364 365 when(mSettingsFacade.isUserSetupCompleted(mActivity)).thenReturn(false); 366 when(mSettingsFacade.isDuringSetupWizard(mActivity)).thenReturn(true); 367 when(mUtils.getManagedProfile(mActivity)) 368 .thenReturn(MANAGED_PROFILE_USER_HANDLE); 369 370 final int managedProfileUserId = MANAGED_PROFILE_USER_HANDLE.getIdentifier(); 371 when(mDevicePolicyManager.getProfileOwnerAsUser(managedProfileUserId)) 372 .thenReturn(TEST_MDM_ADMIN); 373 374 // Actual Device IDs access is granted to the DPM of the managed profile, in the context 375 // of the managed profile. 376 final Context profileContext = mock(Context.class); 377 when(mActivity.createPackageContextAsUser(mActivity.getPackageName(), /*flags=*/ 0, 378 MANAGED_PROFILE_USER_HANDLE)).thenReturn(profileContext); 379 when(profileContext.getSystemServiceName(DevicePolicyManager.class)) 380 .thenReturn(Context.DEVICE_POLICY_SERVICE); 381 final DevicePolicyManager mockProfileDpm = mock(DevicePolicyManager.class); 382 when(profileContext.getSystemService(DevicePolicyManager.class)).thenReturn(mockProfileDpm); 383 384 // WHEN calling deviceManagementEstablished 385 mPreFinalizationController.deviceManagementEstablished(params); 386 387 // THEN the user provisioning state should be marked as initially done 388 verify(mHelper).markUserProvisioningStateInitiallyDone(params); 389 390 // GIVEN that the provisioning state is now incomplete 391 when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(false); 392 393 // WHEN calling provisioningFinalized 394 mFinalizationController.provisioningFinalized(); 395 396 // THEN the user provisioning state is not yet finalized 397 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 398 399 // THEN the DPC policy compliance screen should be shown on the work profile. 400 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 401 verify(mTransitionHelper).startActivityForResultAsUserWithTransition( 402 eq(mActivity), intentCaptor.capture(), anyInt(), eq(MANAGED_PROFILE_USER_HANDLE)); 403 assertThat(intentCaptor.getValue().getAction()) 404 .isEqualTo(DevicePolicyManager.ACTION_ADMIN_POLICY_COMPLIANCE); 405 406 // WHEN calling provisioningFinalized again 407 mFinalizationController.provisioningFinalized(); 408 409 // THEN the user provisioning state is not yet finalized 410 verify(mHelper, never()).markUserProvisioningStateFinalized(params); 411 412 // THEN the DPC policy compliance screen should be shown on the work profile. 413 intentCaptor = ArgumentCaptor.forClass(Intent.class); 414 verify(mTransitionHelper).startActivityForResultAsUserWithTransition( 415 eq(mActivity), intentCaptor.capture(), anyInt(), eq(MANAGED_PROFILE_USER_HANDLE)); 416 assertThat(intentCaptor.getValue().getAction()) 417 .isEqualTo(DevicePolicyManager.ACTION_ADMIN_POLICY_COMPLIANCE); 418 419 // WHEN the provisioning state changes are now committed 420 mFinalizationController.commitFinalizedState(); 421 422 // THEN deferred metrics are written exactly once 423 verify(mDeferredMetricsReader).scheduleDumpMetrics(any(Context.class)); 424 verifyNoMoreInteractions(mDeferredMetricsReader); 425 426 // THEN the user provisioning state is finalized 427 verify(mHelper).markUserProvisioningStateFinalized(params); 428 } 429 verifyDpcLaunchedForUser(UserHandle userHandle, int numTimes)430 private void verifyDpcLaunchedForUser(UserHandle userHandle, int numTimes) { 431 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 432 verify(mTransitionHelper, times(numTimes)).startActivityForResultAsUserWithTransition( 433 eq(mActivity), intentCaptor.capture(), anyInt(), eq(userHandle)); 434 final String intentAction = intentCaptor.getValue().getAction(); 435 // THEN the intent should be ACTION_PROVISIONING_SUCCESSFUL 436 assertEquals(ACTION_ADMIN_POLICY_COMPLIANCE, intentAction); 437 // THEN the intent should only be sent to the dpc 438 assertEquals(TEST_MDM_PACKAGE_NAME, intentCaptor.getValue().getPackage()); 439 // THEN the admin extras bundle should contain mdm extras 440 assertExtras(intentCaptor.getValue()); 441 // THEN a metric should be logged 442 verify(mProvisioningAnalyticsTracker, times(numTimes)).logDpcSetupStarted( 443 eq(mActivity), eq(intentAction)); 444 } 445 verifySendDpcServiceNotStarted()446 private void verifySendDpcServiceNotStarted() { 447 ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class); 448 verify(mActivity, never()).startService(intentCaptor.capture()); 449 } 450 assertExtras(Intent intent)451 private void assertExtras(Intent intent) { 452 assertTrue(TestUtils.bundleEquals(TEST_MDM_EXTRA_BUNDLE, 453 (PersistableBundle) intent.getExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE))); 454 } 455 createProvisioningParams(String action, boolean migrateAccount)456 private ProvisioningParams createProvisioningParams(String action, boolean migrateAccount) { 457 return createProvisioningParamsBuilder(action, migrateAccount).build(); 458 } 459 createProvisioningParamsBuilder(String action, boolean migrateAccount)460 private ProvisioningParams.Builder createProvisioningParamsBuilder(String action, 461 boolean migrateAccount) { 462 ProvisioningParams.Builder builder = new ProvisioningParams.Builder() 463 .setDeviceAdminComponentName(TEST_MDM_ADMIN) 464 .setProvisioningAction(action) 465 .setAdminExtrasBundle(TEST_MDM_EXTRA_BUNDLE) 466 .setReturnBeforePolicyCompliance(true); 467 468 if (migrateAccount) { 469 builder.setAccountToMigrate(TEST_ACCOUNT); 470 builder.setKeepAccountMigrated(false); 471 } 472 473 return builder; 474 } 475 saveAndRestoreControllerState()476 private void saveAndRestoreControllerState() { 477 final Bundle savedInstanceState = new Bundle(); 478 mFinalizationController.saveInstanceState(savedInstanceState); 479 mFinalizationController.activityDestroyed(false); 480 mFinalizationController.restoreInstanceState(savedInstanceState); 481 } 482 } 483