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