Android - Foreground service notification and recent app removal

    Android framework supports restarting application services if they are started as sticky. This helps application resume background tasks after a low memory kill etc. However, its not clear as to what happens when users remove the application (hosting the service) from the recent apps list. Ideally, the service shouldn't even be restarted as the user has requested for the app to be killed, hoping to recover some memory and keep the least recently used app list clear. Developers often tend to miss this use case especially when the application has a foreground service.

   An application hosting a foreground service is considered to be important even when the application is in background. The process schedule group is set to default (Process.THREAD_GROUP_DEFAULT) and not as background (Process.THREAD_GROUP_BG_NONINTERACTIVE). Android framework tries to clean up activities and services as and when the application is removed from the recent app list and eventually kills the process too. The process is killed only when its schedule group is Process.THREAD_GROUP_BG_NONINTERACTIVE. If not, the process is just marked to be killed later when possible.

                if (pr.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
                    pr.kill("remove task", true);
                } else {
                    pr.waitingToKill = "remove task";
                }

  So the default behavior for an application hosting foreground service is that its not killed despite the explicit removal request by the user. The process continues to be in the foreground state with an active notification. However, there are few apps in the play store like Amazon Music which exhibit a different behavior. Its playback notification would be removed and the process would be killed by the framework.

             ActivityManager: Killing 5313:com.amazon.mp3/u0a138 (adj 0): remove task

  Android SDK doesn't offer any APIs to customize this behavior. So how exactly is the music playback service cleaned up? Amazon music is probably using the onDestroy() callback of the activity to finish the foreground service. This is probably why the playback continues for few seconds even after removing the app. Stopping the foreground service from Activity.onDestroy() causes the notification to be removed and the process schedule group to be updated from THREAD_GROUP_DEFAULT to THREAD_GROUP_BG_NONINTERACTIVE. Eventually, this change causes the process to be killed when Activity Manger Service tries to compute oom adj values.

            if (app.waitingToKill != null &&
                    app.setSchedGroup == Process.THREAD_GROUP_BG_NONINTERACTIVE) {
                app.kill(app.waitingToKill, true);
                success = false;
            }

No comments: