[G1 Android Development] Fnorder:
TLDR:

holdapp.sh is a shell script that keeps the browser (or another app) from being killed. Prevents the page-reload problem.

Why:

The madness of android's system architecture means that in low-memory situations, the kernel oom-killer tends to merrily slay any app the user flips into the background, to make more room for whatever is java process is launched, and the HORDE of stuff that was automatically launched and allowed to occupy memory idle - even if that stuff is utterly useless crap that some market app spawns. In theory, murdered apps are supposed to be given enough time to record their state so that they can recover.

Unfortunately the browser does not do this, in my experience. This is especially a problem on the G1, and even moreso on the bloated pig that is android 2.x. You'll be browsing wikipedia, get a text message, flip to mms, respond, flip back, and discover that the page is reloading...or worse, the page - and all opened windows, and history - are gone, leaving you with just your homepage (laughing at you). Meanwhile, the clock app that was spawned an hour ago in response to NTP...is still there.

Screw that, I rigged it to behave with duct tape.

App murder is controlled by /proc/(pid)/oom_adj. The higher the number, the more likely something is to be killed when the kernel (hatchet in hand) goes foraging for memory. Foreground apps are 0, thus rarely killed. Connectbot stays at 1, google apps at 2. Your dead wikipedia research was 7 or 8.

How:

By default, holdapp.sh will check /proc/(browserpid)/oom_adj every second, and set it to 1 whenever it goes below 1. If it isn't running, it will look for it every 20 seconds.

Installation/Usage:

download somewhere and run:

ash /path/to/holdapp.sh

(not sh)

-or-

chmod 755 /path/to/holdapp.sh, and make sure the top #!/system/xbin/ash points to ash (not sh)

holdapp.sh can protect a different app if invoked like:

* holdapp org.example.bookreader *

The forced oom_adj level, it's 1 second check delay, and the 20 second running-check delay can be adjusted by editing the variables at the top of the script (ADJ, WAIT_RUNNING, WAIT_APPDETECT). Other variables enable logging and forced pidfile and busybox locations.

* holdapp -k or holdapp -k appname * kills the script (not the protected app)

* holdapp -c or holdapp -c appname * returns 0 if running, 1 if not.

* holdapp -n or holdapp -n appname * run in foreground.

Caveats:

* If you don't manually kill the browser, or run 'holdapp -k', it will never exit.

* This is not very efficient, for a shell script, as it reads /proc/(pid)/oom_adj every second. I have not experienced a -noticable- performance impact, however (it's minimal, compared to the dalvik stuff that runs). Using inotify won't work as it doesn't detect when a file from /proc vanishes.

* Protecting the browser comes at the cost of making -other- backgrounded apps more likely to be killed. I use the browser alot, however. If that's the case with you, it's probably a good tradeoff.

* I have mostly tested this on Donut. On that, the impact to other apps has not been crippling. I have not tested this on Froyo, and it may cut things -too- close for the G1, there. Test for a long time before sticking it in userinit.sh

Todo:

* Test higher WAIT_RUNNING values.

* Multiple app support without multiple instances.

* Look into something less cheesy for detecting oom_adj changes and app death.

* Fix the dammed browser to set it's own OOM value the right way, and add 'exit'