oppia / oppia-android

A free, online & offline learning platform to make quality education accessible for all.
https://www.oppia.org
Apache License 2.0
315 stars 517 forks source link

Make app resilient to state loss due to low-memory process deaths #2571

Open BenHenning opened 3 years ago

BenHenning commented 3 years ago

Android will kill apps when they are backgrounded & the system runs low on memory. This manifests as a process death, and returning to the app (e.g. via backstack navigation or from the launcher) will trigger the app reopening & restoring via a bundle that the OS had captured & persisted on-disk prior to process death.

Note that we can simulate this scenario by (note that this requires a rooted device/emulator):

Non-rooted way to simulate this (thanks to https://stackoverflow.com/a/17829677):

Bash one-liner:

adb shell run-as org.oppia.android kill -9 "$(adb shell ps -A | grep oppia | awk '{print $2}')"

(The current flow causes a crash in Oppia when in an exploration).

We can fix this issue by:

This requires some architectural considerations both in the domain & app layer, so considering this to be a 'mini project'.

prayutsu commented 3 years ago

@BenHenning I am interested to work on this.

kartikeysaran commented 3 years ago

@BenHenning Can I work on this project if no one working on this !

rt4914 commented 3 years ago

@prayutsu Can you please confirm if you are working on this or not, else it can be assigned to @kartikeysaran

prayutsu commented 3 years ago

@rt4914 As I am busy with other issues, I may not be able to prioritize this, so @kartikeysaran can take it. Thanks!

kartikeysaran commented 3 years ago

@rt4914 , I am working on this issue

FareesHussain commented 3 years ago

@kartikeysaran any updates on this?

kartikeysaran commented 3 years ago

Was working on other issues will work on this

BenHenning commented 3 years ago

@kartikeysaran I suggest starting with a starter or second issue before working on this. This project involves changing a lot of files across the codebase, and is likely going to be quite a bit trickier than starter issues. If after completing a few more issues you still want to work on this, please let us know. :)

kartikeysaran commented 3 years ago

@kartikeysaran I suggest starting with a starter or second issue before working on this. This project involves changing a lot of files across the codebase, and is likely going to be quite a bit trickier than starter issues. If after completing a few more issues you still want to work on this, please let us know. :)

Okay i will work on some started issues , Yes i want to still work on this issue

BenHenning commented 3 years ago

Idea: some state in the domain layer will require loading data from the filesystem. In addition to storing state in bundles (or perhaps in place of it), we may need to detect this state & temporarily transition to a loading activity that blocks on a special data provider which tracks restoring all domain layer state before returning & resuming in the UI.

BenHenning commented 2 years ago

Another idea that maybe ties a bit better to UI components (and needs some thinking in how it interoperates with systems like Jetpack Compose and databinding): if we have assurances that all mutable data only exists in view models (though some thinking needs to be done for temporary references to activities, fragments, views, etc. since these can't go in view models) with proper view models implemented (per #1051), then we could introduce a serialization mechanism for view models that provides/derives from a proto (acting sort of similar to Android's parcelable). If we have a way to register these view models as UI-kept singletons, then the view model states can be serialized on disk for future proofing against process death.

This idea isn't necessarily exclusive from the one above. We still need a way to retain domain data, but it probably needs to happen more on a "session" basis.

One way to consolidate the two ideas might be to "register" session-tied lifecycle data both in the domain and UI layer such that the session's data can be serialized into one proto blob and restored from that blob. This is going to be highly dependent on the solution for #1051 as it's not yet clear how to hook up view models to the Dagger hierarchy since the current approach causes a context leak, and view models very likely need access to sub-singleton components in the graph.