Fix issue #6284404: ArrayIndexOutOfBoundsException in...
...FragmentManagerImpl.restoreAllState This was a bug related to the difference between the pre- and post-HC behavior of onSaveInstanceState(). Prior to HC, state was saved before calling onPause(). Starting with HC, it is saved between onPause() and onStop(). To maintain compatibility with existing applications, there is a check in ActivityThread for pre-HC to in that case emulate the behavior of old applications, still calling onSaveInstanceState() before onPause() but using the state later. One of the special cases we had to deal with in the old model of saving state before pausing was restarting an activity that is already paused. Consider, for example: you have two activities on screen, the one on top not fullscreen so you can see the one behind. The top activity is resumed, the behind activity is paused. In the pre-HC world, the behind activity would have already had its state saved. Now you rotate the screen, and we need to restart the activities. We need to destroy the behind activity and create a new instance, but the new instance has to end up in the paused state. To accompish this, we restart it with a flag saying that it should end up paused. For the pre-HC world, since it ends up paused, we need to make sure we still have its instance state kept around in case we need it because we can't regenerate it (since it is already paused). So that is what the changed code here is doing. It goes through the normal create/start/resume steps, but holds on to the current saved state so that it isn't lost when resume clears it, and then puts the activity back to paused and stuffs that old saved state back in to it. The problem is that this code was doing it for every application, even HC apps. So we end up in a bad state, when a HC app has its saved state sitting there as if it had been saved, even though it is only paused. Now if we go to restart the activity again, instead of asking it for a new saved state (as we should for a HC app as part of stopping it), we just re-use the existing saved state again. Now this wouldn't generally be a huge problem. Worst case, when we restart the activity yet again we are just instantiating it from the same saved state as we used last time, dropping whatever changes may have happened in-between. Who cares? All it has been doing is sitting there in the background, visible to the user, but not something they can interact with. If the activity made changes to its fragments, those changes will be lost, and we will restore it from the older state. However... if one of those fragements is a retained fragment, this will *not* appear in the saved state, but actually be retained across each activity instance. And now we have a problem: if the retained fragments are changed during this time, the next activity instance will be created from the most recent state for the retained fragments, but the older state for everyting else. If these are inconsistent... wham, dead app. To fix this, just don't keep the saved state for HC apps. Also includes a small optimization to ActivityStack to not push the home screen to the front redundantly. Change-Id: Ic3900b12940de25cdd7c5fb9a2a28fb1f4c6cd1a
Loading
Please register or sign in to comment