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