Android - application loses sate upon resume

    Android's application typically remember the state when pushed into background and this state is used when the user resumes the application. This state is saved in framework process space instead of the application process as this is also meant to handle cases when the process gets killed by low memory killer to help Android recover memory for other foreground application's need. When user resumes this application via Launcher or Recent apps, a new process is created and the previous state is passed on to the activities hosted in the new process. The entire operation is transparent to the user and offers a seamless experience. The only prerequisite is that the applications should be coded well to save and restore instance state.

   This sounds good, however, i recently noticed few apps losing state despite saving their state. I was sure of the application as i had coded this one and the logic worked fine for most of the time and it fails only in few cases. Upon closer look, it looks like there is one scenario in which all applications (foreground and background) lose their state. Its the Android Framework reboot.

   The framework reboot is a graceful handling of a fatal failure like exceptions, memory leaks etc in the framework process. If and when this occurs, the linux kernel stays alive and framework process is killed. This is better than the user having to restart the phone explicitly. So the question is what happens to the applications when the framework reboots? After all, applications without the framework process doesn't make any sense.

   When the framework process gets killed (due to exceptions, watchdog kills etc), it generates a signal SIGCHLD. This signal is handled by zygote, being the parent process of the framework. Zygote in response to this signal kills itself.

                     Zygote  : Process 79 terminated by signal (15)
                     Zygote  : Exit zygote because system server (79) has terminated

   Now, Zygote being yet another linux process generates another SIGCHLD, meant for its parent processs init. Init handles this signal and has a logic to kill all processes of a process group corresponding to the killed one, should the killed process host any service that needs to be restarted. Zygote is a service which is defined to be restarted.

         service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
               class main
               socket zygote stream 660 root system
               onrestart write /sys/android_power/request_state wake
               onrestart write /sys/power/state on
               onrestart restart media
               onrestart restart netd

   Android applications are typically forked by zygote to leverage preloaded classes etc. These applications belong to the same process group as that of zygote. Now, when init sends a kill signal to the process group, it ends up killing all applications too and hence, these application (including foreground ones) lose their state.

         Init uses the POSIX kill api to achieve this.

                      kill(-pid, SIGKILL);

So the next time, you see applications losing state, check the list of recent apps. It most likely would be empty.

No comments: