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 
55 import androidx.test.InstrumentationRegistry;
56 import androidx.test.filters.SmallTest;
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 =
126                 new ProvisioningParamsUtils(
127                         ProvisioningParamsUtils.DEFAULT_PROVISIONING_PARAMS_FILE_PROVIDER);
128         mPreFinalizationController = new PreFinalizationController(
129                 mActivity, mUtils, mSettingsFacade, mHelper,
130                 provisioningParamsUtils, new SendDpcBroadcastServiceUtils());
131         mFinalizationController = new FinalizationController(
132                 mActivity,
133                 new FinalizationInsideSuwControllerLogic(
134                         mActivity,
135                         mUtils,
136                         new PolicyComplianceUtils(),
137                         mProvisioningAnalyticsTracker,
138                         mTransitionHelper),
139                 mUtils, mSettingsFacade, mHelper, mNotificationHelper, mDeferredMetricsReader,
140                 provisioningParamsUtils);
141     }
142 
143     @Override
tearDown()144     public void tearDown() throws Exception {
145         mFinalizationController.clearParamsFile();
146     }
147 
148     @SmallTest
testFinalized_alreadyCalled()149     public void testFinalized_alreadyCalled() {
150         // GIVEN that deviceManagementEstablished has already been called
151         when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(true);
152         final ProvisioningParams params = createProvisioningParams(
153                 ACTION_PROVISION_MANAGED_PROFILE, false);
154 
155         // WHEN calling provisioningFinalized and commitFinalizedState
156         mFinalizationController.provisioningFinalized();
157         mFinalizationController.commitFinalizedState();
158 
159         // THEN nothing should happen
160         verify(mHelper, never()).markUserProvisioningStateInitiallyDone(params);
161         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
162         verifyZeroInteractions(mDeferredMetricsReader);
163     }
164 
165     @SmallTest
testFinalized_noParamsStored()166     public void testFinalized_noParamsStored() {
167         // GIVEN that the user provisioning state is correct
168         when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(false);
169 
170         // WHEN calling provisioningFinalized and commitFinalizedState
171         mFinalizationController.provisioningFinalized();
172         mFinalizationController.commitFinalizedState();
173 
174         // THEN nothing should happen
175         verify(mHelper, never())
176                 .markUserProvisioningStateInitiallyDone(any(ProvisioningParams.class));
177         verify(mHelper, never()).markUserProvisioningStateFinalized(any(ProvisioningParams.class));
178         verifyZeroInteractions(mDeferredMetricsReader);
179     }
180 
181     @SmallTest
testManagedProfileFinalizationDuringSuw()182     public void testManagedProfileFinalizationDuringSuw() {
183         // GIVEN that the DPC is not available on the primary profile
184         when(mUtils.canResolveIntentAsUser(eq(mActivity), any(Intent.class),
185                 eq(UserHandle.USER_SYSTEM))).thenReturn(false);
186         // GIVEN that deviceManagementEstablished has never been called
187         when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(true);
188         // GIVEN that we've provisioned a managed profile after SUW
189         final ProvisioningParams params = createProvisioningParams(
190                 ACTION_PROVISION_MANAGED_PROFILE, true);
191         when(mSettingsFacade.isUserSetupCompleted(mActivity)).thenReturn(false);
192         when(mSettingsFacade.isDuringSetupWizard(mActivity)).thenReturn(true);
193         when(mUtils.getManagedProfile(mActivity)).thenReturn(MANAGED_PROFILE_USER_HANDLE);
194 
195         // WHEN calling deviceManagementEstablished
196         mPreFinalizationController.deviceManagementEstablished(params);
197 
198         // THEN the user provisioning state should be marked as initially done
199         verify(mHelper).markUserProvisioningStateInitiallyDone(params);
200         // THEN the provisioning params have been stored and will be read in provisioningFinalized
201 
202         // GIVEN that the provisioning state is now incomplete
203         when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(false);
204 
205         // WHEN we save and restore controller state
206         saveAndRestoreControllerState();
207 
208         // THEN the user provisioning state is not yet finalized
209         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
210 
211         // THEN no intent should be sent to the dpc.
212         verify(mTransitionHelper, never()).startActivityForResultAsUserWithTransition(
213                 eq(mActivity), any(Intent.class), anyInt(), eq(MANAGED_PROFILE_USER_HANDLE));
214 
215         // WHEN calling provisioningFinalized
216         mFinalizationController.provisioningFinalized();
217 
218         // THEN the user provisioning state is not yet finalized
219         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
220 
221         // THEN intent should be sent to the dpc.
222         verifyDpcLaunchedForUser(MANAGED_PROFILE_USER_HANDLE, 1);
223 
224         // WHEN calling provisioningFinalized again
225         mFinalizationController.provisioningFinalized();
226 
227         // THEN the user provisioning state is not yet finalized
228         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
229 
230          // THEN intent should not be sent to the dpc again
231         verifyDpcLaunchedForUser(MANAGED_PROFILE_USER_HANDLE, 1);
232 
233         // WHEN simulating a DPC cancel by calling activityDestroyed(true), and then
234         // provisioningFinalized again
235         mFinalizationController.activityDestroyed(true);
236         mFinalizationController.provisioningFinalized();
237 
238         // THEN the user provisioning state is not yet finalized
239         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
240 
241         // THEN intent should be sent to the dpc again
242         verifyDpcLaunchedForUser(MANAGED_PROFILE_USER_HANDLE, 2);
243 
244         // WHEN we save and restore controller state, and then call provisioningFinalized again
245         saveAndRestoreControllerState();
246         mFinalizationController.provisioningFinalized();
247 
248         // THEN the user provisioning state is not yet finalized
249         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
250 
251         // THEN intent is not sent to the dpc again
252         verifyDpcLaunchedForUser(MANAGED_PROFILE_USER_HANDLE, 2);
253 
254         // WHEN the provisioning state changes are now committed
255         mFinalizationController.commitFinalizedState();
256 
257         // THEN deferred metrics have been written exactly once
258         verify(mDeferredMetricsReader).scheduleDumpMetrics(any(Context.class));
259         verifyNoMoreInteractions(mDeferredMetricsReader);
260 
261         // THEN the user provisioning state is finalized
262         verify(mHelper).markUserProvisioningStateFinalized(params);
263 
264         // THEN the service which starts the DPC, has never been started.
265         verifySendDpcServiceNotStarted();
266     }
267 
268     @SmallTest
testDeviceOwnerFinalizationDuringSuw()269     public void testDeviceOwnerFinalizationDuringSuw() {
270         // GIVEN that deviceManagementEstablished has never been called
271         when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(true);
272         // GIVEN that we've provisioned a device owner during SUW
273         final ProvisioningParams params = createProvisioningParams(
274                 ACTION_PROVISION_MANAGED_DEVICE, false);
275         when(mSettingsFacade.isUserSetupCompleted(mActivity)).thenReturn(false);
276         when(mSettingsFacade.isDuringSetupWizard(mActivity)).thenReturn(true);
277 
278         // WHEN calling deviceManagementEstablished
279         mPreFinalizationController.deviceManagementEstablished(params);
280 
281         // THEN the user provisioning state should be marked as initially done
282         verify(mHelper).markUserProvisioningStateInitiallyDone(params);
283         // THEN the provisioning params have been stored and will be read in provisioningFinalized
284 
285         // GIVEN that the provisioning state is now incomplete
286         when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(false);
287 
288         // WHEN we save and restore controller state
289         saveAndRestoreControllerState();
290 
291         // THEN the user provisioning state is not yet finalized
292         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
293 
294         // THEN no intent should be sent to the dpc.
295         verify(mTransitionHelper, never()).startActivityForResultAsUserWithTransition(
296                 eq(mActivity), any(Intent.class), anyInt(),
297                         eq(UserHandle.of(UserHandle.myUserId())));
298 
299         // WHEN calling provisioningFinalized
300         mFinalizationController.provisioningFinalized();
301 
302         // THEN the user provisioning state is not yet finalized
303         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
304 
305         // THEN intent should be sent to the dpc.
306         verifyDpcLaunchedForUser(UserHandle.of(UserHandle.myUserId()), 1);
307 
308         // WHEN calling provisioningFinalized again
309         mFinalizationController.provisioningFinalized();
310 
311         // THEN the user provisioning state is not yet finalized
312         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
313 
314         // THEN intent should not be sent to the dpc again
315         verifyDpcLaunchedForUser(UserHandle.of(UserHandle.myUserId()), 1);
316 
317         // WHEN simulating a DPC cancel by calling activityDestroyed(true), and then
318         // provisioningFinalized again
319         mFinalizationController.activityDestroyed(true);
320         mFinalizationController.provisioningFinalized();
321 
322         // THEN the user provisioning state is not yet finalized
323         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
324 
325         // THEN intent should be sent to the dpc again
326         verifyDpcLaunchedForUser(UserHandle.of(UserHandle.myUserId()), 2);
327 
328         // WHEN we save and restore controller state, and then call provisioningFinalized again
329         saveAndRestoreControllerState();
330         mFinalizationController.provisioningFinalized();
331 
332         // THEN the user provisioning state is not yet finalized
333         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
334 
335         // THEN intent should not be sent to the dpc again
336         verifyDpcLaunchedForUser(UserHandle.of(UserHandle.myUserId()), 2);
337 
338         // WHEN the provisioning state changes are now committed
339         mFinalizationController.commitFinalizedState();
340 
341         // THEN deferred metrics have been written exactly once
342         verify(mDeferredMetricsReader).scheduleDumpMetrics(any(Context.class));
343         verifyNoMoreInteractions(mDeferredMetricsReader);
344 
345         // THEN the user provisioning state is finalized
346         verify(mHelper).markUserProvisioningStateFinalized(params);
347 
348         // THEN a privacy reminder is shown to the user exactly once
349         verify(mNotificationHelper).showPrivacyReminderNotification(eq(mActivity), anyInt());
350 
351         // THEN no broadcast was ever sent to the primary user
352         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
353         verify(mActivity, never()).sendBroadcast(intentCaptor.capture());
354     }
355 
356     @SmallTest
testCorpOwnedManagedProfileDuringSuw()357     public void testCorpOwnedManagedProfileDuringSuw() throws PackageManager.NameNotFoundException {
358         // GIVEN that deviceManagementEstablished has never been called
359         when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(true);
360         // GIVEN that we're provisioning a corp-owned managed profile DURING SUW
361         final ProvisioningParams params =
362                 createProvisioningParamsBuilder(ACTION_PROVISION_MANAGED_PROFILE, true)
363                         .setIsOrganizationOwnedProvisioning(true)
364                         .setFlowType(ProvisioningParams.FLOW_TYPE_ADMIN_INTEGRATED)
365                         .build();
366 
367         when(mSettingsFacade.isUserSetupCompleted(mActivity)).thenReturn(false);
368         when(mSettingsFacade.isDuringSetupWizard(mActivity)).thenReturn(true);
369         when(mUtils.getManagedProfile(mActivity))
370                 .thenReturn(MANAGED_PROFILE_USER_HANDLE);
371 
372         final int managedProfileUserId = MANAGED_PROFILE_USER_HANDLE.getIdentifier();
373         when(mDevicePolicyManager.getProfileOwnerAsUser(managedProfileUserId))
374                 .thenReturn(TEST_MDM_ADMIN);
375 
376         // Actual Device IDs access is  granted to the DPM of the managed profile, in the context
377         // of the managed profile.
378         final Context profileContext = mock(Context.class);
379         when(mActivity.createPackageContextAsUser(mActivity.getPackageName(), /*flags=*/ 0,
380                 MANAGED_PROFILE_USER_HANDLE)).thenReturn(profileContext);
381         when(profileContext.getSystemServiceName(DevicePolicyManager.class))
382                 .thenReturn(Context.DEVICE_POLICY_SERVICE);
383         final DevicePolicyManager mockProfileDpm = mock(DevicePolicyManager.class);
384         when(profileContext.getSystemService(DevicePolicyManager.class)).thenReturn(mockProfileDpm);
385 
386         // WHEN calling deviceManagementEstablished
387         mPreFinalizationController.deviceManagementEstablished(params);
388 
389         // THEN the user provisioning state should be marked as initially done
390         verify(mHelper).markUserProvisioningStateInitiallyDone(params);
391 
392         // GIVEN that the provisioning state is now incomplete
393         when(mHelper.isStateUnmanagedOrFinalized()).thenReturn(false);
394 
395         // WHEN calling provisioningFinalized
396         mFinalizationController.provisioningFinalized();
397 
398         // THEN the user provisioning state is not yet finalized
399         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
400 
401         // THEN the DPC policy compliance screen should be shown on the work profile.
402         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
403         verify(mTransitionHelper).startActivityForResultAsUserWithTransition(
404                 eq(mActivity), intentCaptor.capture(), anyInt(), eq(MANAGED_PROFILE_USER_HANDLE));
405         assertThat(intentCaptor.getValue().getAction())
406                 .isEqualTo(DevicePolicyManager.ACTION_ADMIN_POLICY_COMPLIANCE);
407 
408         // WHEN calling provisioningFinalized again
409         mFinalizationController.provisioningFinalized();
410 
411         // THEN the user provisioning state is not yet finalized
412         verify(mHelper, never()).markUserProvisioningStateFinalized(params);
413 
414         // THEN the DPC policy compliance screen should be shown on the work profile.
415         intentCaptor = ArgumentCaptor.forClass(Intent.class);
416         verify(mTransitionHelper).startActivityForResultAsUserWithTransition(
417                 eq(mActivity), intentCaptor.capture(), anyInt(), eq(MANAGED_PROFILE_USER_HANDLE));
418         assertThat(intentCaptor.getValue().getAction())
419                 .isEqualTo(DevicePolicyManager.ACTION_ADMIN_POLICY_COMPLIANCE);
420 
421         // WHEN the provisioning state changes are now committed
422         mFinalizationController.commitFinalizedState();
423 
424         // THEN deferred metrics are written exactly once
425         verify(mDeferredMetricsReader).scheduleDumpMetrics(any(Context.class));
426         verifyNoMoreInteractions(mDeferredMetricsReader);
427 
428         // THEN the user provisioning state is finalized
429         verify(mHelper).markUserProvisioningStateFinalized(params);
430     }
431 
verifyDpcLaunchedForUser(UserHandle userHandle, int numTimes)432     private void verifyDpcLaunchedForUser(UserHandle userHandle, int numTimes) {
433         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
434         verify(mTransitionHelper, times(numTimes)).startActivityForResultAsUserWithTransition(
435                 eq(mActivity), intentCaptor.capture(), anyInt(), eq(userHandle));
436         final String intentAction = intentCaptor.getValue().getAction();
437         // THEN the intent should be ACTION_PROVISIONING_SUCCESSFUL
438         assertEquals(ACTION_ADMIN_POLICY_COMPLIANCE, intentAction);
439         // THEN the intent should only be sent to the dpc
440         assertEquals(TEST_MDM_PACKAGE_NAME, intentCaptor.getValue().getPackage());
441         // THEN the admin extras bundle should contain mdm extras
442         assertExtras(intentCaptor.getValue());
443         // THEN a metric should be logged
444         verify(mProvisioningAnalyticsTracker, times(numTimes)).logDpcSetupStarted(
445                 eq(mActivity), eq(intentAction));
446     }
447 
verifySendDpcServiceNotStarted()448     private void verifySendDpcServiceNotStarted() {
449         ArgumentCaptor<Intent> intentCaptor = ArgumentCaptor.forClass(Intent.class);
450         verify(mActivity, never()).startService(intentCaptor.capture());
451     }
452 
assertExtras(Intent intent)453     private void assertExtras(Intent intent) {
454         assertTrue(TestUtils.bundleEquals(TEST_MDM_EXTRA_BUNDLE,
455                 (PersistableBundle) intent.getExtra(EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE)));
456     }
457 
createProvisioningParams(String action, boolean migrateAccount)458     private ProvisioningParams createProvisioningParams(String action, boolean migrateAccount) {
459         return createProvisioningParamsBuilder(action, migrateAccount).build();
460     }
461 
createProvisioningParamsBuilder(String action, boolean migrateAccount)462     private ProvisioningParams.Builder createProvisioningParamsBuilder(String action,
463             boolean migrateAccount) {
464         ProvisioningParams.Builder builder = new ProvisioningParams.Builder()
465                 .setDeviceAdminComponentName(TEST_MDM_ADMIN)
466                 .setProvisioningAction(action)
467                 .setAdminExtrasBundle(TEST_MDM_EXTRA_BUNDLE)
468                 .setReturnBeforePolicyCompliance(true);
469 
470         if (migrateAccount) {
471             builder.setAccountToMigrate(TEST_ACCOUNT);
472             builder.setKeepAccountMigrated(false);
473         }
474 
475         return builder;
476     }
477 
saveAndRestoreControllerState()478     private void saveAndRestoreControllerState() {
479         final Bundle savedInstanceState = new Bundle();
480         mFinalizationController.saveInstanceState(savedInstanceState);
481         mFinalizationController.activityDestroyed(false);
482         mFinalizationController.restoreInstanceState(savedInstanceState);
483     }
484 }
485