How a single unprivileged app can brick the whole Android system
Posted on by Daniel Kulesz
This article is highly subjective and only states the author’s opinion based on actual observations and “wild” assumptions. Unlike stated in the title, it might apply only to LineageOS and not to the original AOSP. Better explanations and corrections are warmly welcome!
Motivation
After updating an App from the F-Droid store (OpenCamera), my Android device was completely unusable. In this state, the only feasible option for a typical end-user to recover the device (who does not know how to get to safe mode in order to remove or downgrade the app [5]) would have been to wipe data in recovery, loosing all data.
How can such a disaster happen? In this article, I argue why I have serious doubts about the memory management approach taken in Android.
The failure
After updating the OpenCamera app to the recently released version 1.42, my Android device ran into a bootloop that was hard to recover from. I was able to repeatingly reproduce the failure on a different device, namely the following:
- Device: Samsung Galaxy S3 (i9300)
- ROM: Lineage OS 13 (Android 6.0), freshly built from latest sources, commit 42f4b851c9b2d08709a065c3931f6370fd78b2b0 [1]
Steps to reproduce:
Expected:
The install completes and the app is available. If installation fails (for whatever reason), an error message is shown but the device is still working
Actual:
The install freezes, the LineageOS splash screen appears and re-initializes all apps; this happens several times and after aprox 10-15 minutes the device is back “working”; when trying to start apps they crash or even the launcher (“Trebuchet”) crashes. After rebooting the device, it is stuck in an infinite loop initializing apps.
The fault (what happens under the hood?)
When installing OpenCamera, the following is printed in the log:
12-10 14:48:30.915 4034 5483 I ActivityManager: START u0 {act=org.fdroid.fdroid.installer.DefaultInstaller.action.INSTALL_PACKAGE dat=file:///data/user/0/org.fdroid.fdroid/files/Open Camera-1.42.apk cmp=org.fdroid.fdroid/.installer.DefaultInstallerActivity (has extras)} from uid 10070 on display 0
12-10 14:48:30.915 4034 5483 W ActivityManager: startActivity called from non-Activity context; forcing Intent.FLAG_ACTIVITY_NEW_TASK for: Intent { act=org.fdroid.fdroid.installer.DefaultInstaller.action.INSTALL_PACKAGE dat=file:///data/user/0/org.fdroid.fdroid/files/Open Camera-1.42.apk cmp=org.fdroid.fdroid/.installer.DefaultInstallerActivity (has extras) }
12-10 14:48:30.925 4034 5483 D lights : set_light_buttons: 2
12-10 14:48:30.955 4034 5649 I ActivityManager: START u0 {act=android.intent.action.INSTALL_PACKAGE dat=file:///data/user/0/org.fdroid.fdroid/files/Open Camera-1.42.apk cmp=com.android.packageinstaller/.PackageInstallerActivity (has extras)} from uid 10070 on display 0
12-10 14:48:31.085 6740 6740 W ResourceType: Failure getting entry for 0x7f0c0001 (t=11 e=1) (error -75)
12-10 14:48:31.700 4034 4093 I ActivityManager: Displayed com.android.packageinstaller/.PackageInstallerActivity: +724ms (total +758ms)
12-10 14:48:36.770 4034 4362 D lights : set_light_buttons: 1
12-10 14:48:36.840 4034 4938 I ActivityManager: START u0 {dat=file:///data/user/0/org.fdroid.fdroid/files/Open Camera-1.42.apk flg=0x2000000 cmp=com.android.packageinstaller/.InstallAppProgress (has extras)} from uid 10018 on display 0
12-10 14:48:36.850 3499 3895 D audio_hw_primary: select_output_device: AUDIO_DEVICE_OUT_SPEAKER
12-10 14:48:36.955 6863 6874 D DefContainer: Copying /data/user/0/org.fdroid.fdroid/files/Open Camera-1.42.apk to base.apk
12-10 14:48:37.100 4034 4093 I ActivityManager: Displayed com.android.packageinstaller/.InstallAppProgress: +251ms
12-10 14:48:37.155 6740 6753 D OpenGLRenderer: endAllStagingAnimators on 0x486226f0 (RippleDrawable) with handle 0x48604d28
12-10 14:48:37.170 4034 4100 W ResourceType: Failure getting entry for 0x7f0c0001 (t=11 e=1) (error -75)
12-10 14:48:37.465 4034 4100 I PackageManager.DexOptimizer: Running dexopt (dex2oat) on: /data/app/vmdl872450731.tmp/base.apk pkg=net.sourceforge.opencamera isa=arm vmSafeMode=false debuggable=false oatDir = /data/app/vmdl872450731.tmp/oat bootComplete=true
12-10 14:48:37.585 7205 7205 I dex2oat : Starting dex2oat.
12-10 14:48:37.585 7205 7205 E cutils-trace: Error opening trace file: No such file or directory (2)
12-10 14:48:42.405 7205 7205 I dex2oat : dex2oat took 4.815s (threads: 4) arena alloc=5MB java alloc=2023KB native alloc=13MB free=1122KB
12-10 14:48:42.415 4034 4100 D lights : set_light_buttons: 2
12-10 14:48:42.680 4034 4100 V BackupManagerService: restoreAtInstall pkg=net.sourceforge.opencamera token=3 restoreSet=0
12-10 14:48:42.680 4034 4100 W BackupManagerService: Requested unavailable transport: com.google.android.gms/.backup.BackupTransportService
12-10 14:48:42.680 4034 4100 W BackupManagerService: No transport
12-10 14:48:42.680 4034 4100 V BackupManagerService: Finishing install immediately
12-10 14:48:42.705 4034 4100 W Settings: Setting install_non_market_apps has moved from android.provider.Settings.Global to android.provider.Settings.Secure, returning read-only value.
12-10 14:48:42.705 4034 4100 I art : Starting a blocking GC Explicit
12-10 14:48:42.805 4034 4100 I art : Explicit concurrent mark sweep GC freed 52637(2MB) AllocSpace objects, 20(424KB) LOS objects, 33% free, 14MB/21MB, paused 2.239ms total 96.416ms
12-10 14:48:42.835 4034 4363 I InputReader: Reconfiguring input devices. changes=0x00000010
12-10 14:48:42.935 5420 5420 D CarrierServiceBindHelper: Receive action: android.intent.action.PACKAGE_ADDED
12-10 14:48:42.940 5420 5420 D CarrierServiceBindHelper: mHandler: 3
12-10 14:48:42.940 5420 5420 D CarrierConfigLoader: mHandler: 9 phoneId: 0
12-10 14:48:42.945 4034 4034 F libc : invalid address or address of corrupt block 0x120 passed to dlfree
12-10 14:48:42.945 4034 4034 F libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 4034 (system_server)
12-10 14:48:42.950 3496 3496 I DEBUG : property debug.db.uid not set; NOT waiting for gdb.
12-10 14:48:42.950 3496 3496 I DEBUG : HINT: adb shell setprop debug.db.uid 100000
12-10 14:48:42.950 3496 3496 I DEBUG : HINT: adb forward tcp:5039 tcp:5039
12-10 14:48:42.975 3496 3496 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
12-10 14:48:42.975 3496 3496 F DEBUG : LineageOS Version: '13.0-20171125-UNOFFICIAL-i9300'
12-10 14:48:42.975 3496 3496 F DEBUG : Build fingerprint: 'samsung/m0xx/m0:4.3/JSS15J/I9300XXUGMJ9:user/release-keys'
12-10 14:48:42.975 3496 3496 F DEBUG : Revision: '0'
12-10 14:48:42.975 3496 3496 F DEBUG : ABI: 'arm'
12-10 14:48:42.975 3496 3496 F DEBUG : pid: 4034, tid: 4034, name: system_server >>> system_server <<<
12-10 14:48:42.975 3496 3496 F DEBUG : signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdeadbaad
12-10 14:48:43.030 3496 3496 F DEBUG : Abort message: 'invalid address or address of corrupt block 0x120 passed to dlfree'
12-10 14:48:43.030 3496 3496 F DEBUG : r0 00000000 r1 00000000 r2 00000000 r3 00000002
12-10 14:48:43.030 3496 3496 F DEBUG : r4 00000120 r5 deadbaad r6 404e0f38 r7 40005000
12-10 14:48:43.030 3496 3496 F DEBUG : r8 00000128 r9 bee01b0c sl 40358be3 fp 40358bec
12-10 14:48:43.030 3496 3496 F DEBUG : ip 404db5d8 sp bee019f8 lr 404abfab pc 404abfaa cpsr 60070030
12-10 14:48:43.045 3496 3496 F DEBUG :
12-10 14:48:43.045 3496 3496 F DEBUG : backtrace:
12-10 14:48:43.045 3496 3496 F DEBUG : #00 pc 00030faa /system/lib/libc.so (dlfree+1285)
12-10 14:48:43.045 3496 3496 F DEBUG : #01 pc 000158df /system/lib/libandroidfw.so (_ZN7android13ResStringPool6uninitEv+38)
12-10 14:48:43.045 3496 3496 F DEBUG : #02 pc 0001662b /system/lib/libandroidfw.so (_ZN7android10ResXMLTree6uninitEv+12)
12-10 14:48:43.045 3496 3496 F DEBUG : #03 pc 00016649 /system/lib/libandroidfw.so (_ZN7android10ResXMLTreeD1Ev+4)
12-10 14:48:43.045 3496 3496 F DEBUG : #04 pc 00013373 /system/lib/libandroidfw.so (_ZN7android12AssetManager10getPkgNameEPKc+258)
12-10 14:48:43.045 3496 3496 F DEBUG : #05 pc 000133cf /system/lib/libandroidfw.so (_ZN7android12AssetManager18getBasePackageNameEj+62)
12-10 14:48:43.045 3496 3496 F DEBUG : #06 pc 00088b33 /system/lib/libandroid_runtime.so
12-10 14:48:43.045 3496 3496 F DEBUG : #07 pc 72cb9011 /data/dalvik-cache/arm/system@framework@boot.oat (offset 0x1f78000)
12-10 14:48:50.095 3496 3496 F DEBUG :
12-10 14:48:50.095 3496 3496 F DEBUG : Tombstone written to: /data/tombstones/tombstone_00
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'statusbar' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'netstats' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'power' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'media_projection' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'network_management' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'window' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'consumer_ir' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'telecom' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'cmpartnerinterface' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'package' died
12-10 14:48:50.185 1912 1912 I ServiceManager: service 'user' died
Since Open Camera needs some background service and is started on bootup, I assume that after installation the system tries to restart this service. However, it appears that there is some memory issue with the app, as it requests so much memory that Android starts killing other apps to make this memory available. In case Android does not manage to provide this space, the device is rebooted. Since OpenCamera is started at bootup, it again tries to allocate (too much) memory and the device is stuck in an infinite loop.
Looking at Android’s memory management
I expected that the following excerpt from the log above might lead to some useful hints:
12-10 14:48:42.945 4034 4034 F libc : invalid address or address of corrupt block 0x120 passed to dlfree
12-10 14:48:42.945 4034 4034 F libc : Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadbaad in tid 4034 (system_server)
After searching on the net, I found an interesting discussion [2] suggesting the following:
“A likely cause of this is that you have ran out of memory, maybe because a memory leak or simply used up all memory. This can be caused by a bug you are using in a plugin that uses native C/C++ code through NDK.”
To rule out hardware issues, I also exchanged the storage (I run /data from sdcard) and compiled memtester [3] to test the device’s RAM. When experimenting with memtester, I noticed a striking difference between running memtester on a regular GNU/Linux system and running it on Android/LineageOS. When giving memtester less memory than actually available, there is no difference. However, when giving memtester more RAM than acutally available, the following happens on GNU/Linux:
# free -h
total used free shared buff/cache available
Mem: 28G 124M 28G 8.5M 219M 28G
Swap: 0B 0B 0B
# memtester 40G
memtester version 4.3.0 (64-bit)
Copyright (C) 2001-2012 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).
pagesize is 4096
pagesizemask is 0xfffffffffffff000
want 40960MB (42949672960 bytes)
got 29075MB (30488387584 bytes), trying mlock ...Killed
#
Killed
[1]+ Stopped sh
While on Android the device suddenly reboots after trying to mlock the memory:
root@i9300:/ # free -h
total used free shared buffers
Mem: 828M 754M 74M 0 1.3M
-/+ buffers/cache: 752M 75M
Swap: 400M 18M 382M
root@i9300:/ # /sbin/memtester 2G
memtester version 4.3.0 (32-bit)
Copyright (C) 2001-2012 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).
pagesize is 4096
pagesizemask is 0xfffff000
want 2048MB (2147483648 bytes)
got 2008MB (2105921536 bytes), trying mlock ...</pre>
This is what is printed to logcat:
<pre>01-01 01:10:29.485 4933 4933 D su : su invoked.
01-01 01:10:29.485 4933 4933 E su : SU from: shell
01-01 01:10:29.490 4933 4933 D su : Allowing shell.
01-01 01:10:29.490 4933 4933 D su : 2000 /system/bin/sh executing 0 /system/bin/sh using binary /system/bin/sh : sh
01-01 01:10:29.490 4933 4933 D su : Waiting for pid 4934.
01-01 01:10:44.840 2478 3264 D LightsService: Excessive delay setting light: 81ms
01-01 01:10:44.925 2478 3264 D LightsService: Excessive delay setting light: 82ms
01-01 01:10:45.010 2478 3264 D LightsService: Excessive delay setting light: 82ms
01-01 01:10:45.090 2478 3264 D LightsService: Excessive delay setting light: 82ms
01-01 01:10:45.175 2478 3264 D LightsService: Excessive delay setting light: 82ms
01-01 01:10:45.260 2478 3264 D LightsService: Excessive delay setting light: 82ms
01-01 01:10:45.340 2478 3264 D LightsService: Excessive delay setting light: 82ms
01-01 01:10:50.735 2478 2538 I PowerManagerService: Going to sleep due to screen timeout (uid 1000)...
01-01 01:10:50.785 2478 2538 E : Device driver API match
01-01 01:10:50.785 2478 2538 E : Device driver API version: 29
01-01 01:10:50.785 2478 2538 E : User space API version: 29
01-01 01:10:50.785 2478 2538 E : mali: REVISION=Linux-r3p2-01rel3 BUILD_DATE=Tue Aug 26 17:05:16 KST 2014
01-01 01:10:52.000 2478 2538 V KeyguardServiceDelegate: onScreenTurnedOff()
01-01 01:10:52.040 2478 2538 E libEGL : call to OpenGL ES API with no current context (logged once per thread)
01-01 01:10:52.045 2478 2536 I DisplayManagerService: Display device changed: DisplayDeviceInfo{"Integrierter Bildschirm": uniqueId="local:0", 720 x 1280, modeId 1, defaultModeId 1, supportedModes [{id=1, width=720, height=1280, fps=60.002}], colorTransformId 1, defaultColorTransformId 1, supportedColorTransforms [{id=1, colorTransform=0}], density 320, 304.8 x 306.71698 dpi, appVsyncOff 0, presDeadline 17666111, touch INTERNAL, rotation 0, type BUILT_IN, state OFF, FLAG_DEFAULT_DISPLAY, FLAG_ROTATES_WITH_CONTENT, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}
01-01 01:10:52.060 1915 1915 D SurfaceFlinger: Set power mode=0, type=0 flinger=0x411dadf0
01-01 01:10:52.160 2478 2538 I PowerManagerService: Sleeping (uid 1000)...
01-01 01:10:52.165 2478 3231 D WifiConfigStore: Retrieve network priorities after PNO.
01-01 01:10:52.170 1938 3241 E bt_a2dp_hw: adev_set_parameters: ERROR: set param called even when stream out is null
01-01 01:10:52.170 2478 3231 E native : do suspend false
01-01 01:10:52.175 2478 3231 D WifiConfigStore: No blacklist allowed without epno enabled
01-01 01:10:52.190 3846 4968 D NfcService: Discovery configuration equal, not updating.
01-01 01:10:52.435 2478 3231 D WifiConfigStore: Retrieve network priorities before PNO. Max priority: 0
01-01 01:10:52.435 1938 1938 E bt_a2dp_hw: adev_set_parameters: ERROR: set param called even when stream out is null
01-01 01:10:52.440 2478 3231 E WifiStateMachine: Fail to set up pno, want true now false
01-01 01:10:52.440 2478 3231 E native : do suspend true
01-01 01:10:52.670 2478 3231 D WifiStateMachine: Disconnected CMD_START_SCAN source -2 3, 4 -> obsolete
01-01 01:10:54.160 2478 2538 W PowerManagerService: Sandman unresponsive, releasing suspend blocker
01-01 01:10:55.825 2478 3362 D CryptdConnector: SND -> {3 cryptfs getpw}
01-01 01:10:55.825 1903 1999 D VoldCryptCmdListener: cryptfs getpw
01-01 01:10:55.825 1903 1999 I Ext4Crypt: ext4 crypto complete called on /data
01-01 01:10:55.825 1903 1999 I Ext4Crypt: No master key, so not ext4enc
01-01 01:10:55.830 1903 1999 I Ext4Crypt: ext4 crypto complete called on /data
01-01 01:10:55.830 1903 1999 I Ext4Crypt: No master key, so not ext4enc
01-01 01:10:55.830 2478 2798 D CryptdConnector: RCV {4 cryptfs clearpw}
01-01 01:10:55.835 1903 1999 D VoldCryptCmdListener: cryptfs clearpw
01-01 01:10:55.835 1903 1999 I Ext4Crypt: ext4 crypto complete called on /data
01-01 01:10:55.835 1903 1999 I Ext4Crypt: No master key, so not ext4enc
01-01 01:10:55.835 2478 2798 D CryptdConnector: RCV <- {200 4 0}
01-01 01:10:55.925 3417 3417 D PhoneStatusBar: disable:
01-01 01:10:56.020 3417 3417 D PhoneStatusBar: disable:
01-01 01:10:56.330 3417 3417 D PhoneStatusBar: disable:
01-01 01:11:44.875 2478 4667 I ActivityManager: Process com.android.messaging (pid 4607) has died
01-01 01:11:44.920 2478 4667 D ActivityManager: cleanUpApplicationRecord -- 4607
01-01 01:11:45.860 2478 3356 W art : Long monitor contention event with owner method=void com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied() from ActivityManagerService.java:1359 waiters=0 for 907ms
01-01 01:11:45.890 2478 3356 I ActivityManager: Process org.cyanogenmod.profiles (pid 4593) has died
01-01 01:11:45.900 2478 3356 D ActivityManager: cleanUpApplicationRecord -- 4593
01-01 01:11:45.955 2478 2529 W art : Long monitor contention event with owner method=void com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied() from ActivityManagerService.java:1359 waiters=1 for 914ms
01-01 01:11:45.960 1913 1913 E lowmemorykiller: Error opening /proc/3662/oom_score_adj; errno=2
01-01 01:11:45.970 2478 2529 I ActivityManager: Process com.android.exchange (pid 3662) has died
01-01 01:11:45.970 2478 2529 D ActivityManager: cleanUpApplicationRecord -- 3662
01-01 01:11:45.985 2478 3943 W art : Long monitor contention event with owner method=void com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied() from ActivityManagerService.java:1359 waiters=2 for 611ms
01-01 01:11:45.995 2478 3943 I ActivityManager: Process com.android.calendar (pid 4415) has died
01-01 01:11:45.995 2478 3943 D ActivityManager: cleanUpApplicationRecord -- 4415
01-01 01:11:46.000 2478 2532 W art : Long monitor contention event with owner method=void com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied() from ActivityManagerService.java:1359 waiters=3 for 537ms
01-01 01:11:46.025 2478 3362 W art : Long monitor contention event with owner method=void com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied() from ActivityManagerService.java:1359 waiters=4 for 378ms
01-01 01:11:46.045 2478 3362 I ActivityManager: Process org.lineageos.updater (pid 4449) has died
01-01 01:11:46.045 2478 3362 D ActivityManager: cleanUpApplicationRecord -- 4449
01-01 01:11:46.045 1913 1913 E lowmemorykiller: Error writing /proc/3938/oom_score_adj; errno=22
01-01 01:11:46.050 2478 3413 W art : Long monitor contention event with owner method=void com.android.server.am.ActivityManagerService$AppDeathRecipient.binderDied() from ActivityManagerService.java:1359 waiters=5 for 372ms
01-01 01:11:46.505 2478 3232 D WifiService: Client connection lost with reason: 4
01-01 01:11:47.165 2478 4666 D GraphicsStats: Buffer count: 3
01-01 01:11:47.400 2478 2532 W art : Long monitor contention event with owner method=int com.android.server.am.ActivityManagerService.broadcastIntent(android.app.IApplicationThread, android.content.Intent, java.lang.String, android.content.IIntentReceiver, int, java.lang.String, android.os.Bundle, java.lang.String[], int, android.os.Bundle, boolean, boolean, int) from ActivityManagerService.java:17497 waiters=0 for 667ms
01-01 01:11:47.465 2478 4664 W art : Long monitor contention event with owner method=int com.android.server.am.ActivityManagerService.broadcastIntent(android.app.IApplicationThread, android.content.Intent, java.lang.String, android.content.IIntentReceiver, int, java.lang.String, android.os.Bundle, java.lang.String[], int, android.os.Bundle, boolean, boolean, int) from ActivityManagerService.java:17497 waiters=1 for 858ms
01-01 01:11:47.465 2478 3412 W art : Long monitor contention event with owner method=int com.android.server.am.ActivityManagerService.broadcastIntent(android.app.IApplicationThread, android.content.Intent, java.lang.String, android.content.IIntentReceiver, int, java.lang.String, android.os.Bundle, java.lang.String[], int, android.os.Bundle, boolean, boolean, int) from ActivityManagerService.java:17497 waiters=2 for 859ms
01-01 01:11:47.475 2478 4665 I ActivityManager: Process com.android.providers.calendar (pid 4434) has died
01-01 01:11:47.480 2478 4665 D ActivityManager: cleanUpApplicationRecord -- 4434
01-01 01:11:47.545 1913 1913 E lowmemorykiller: Error opening /proc/3938/oom_score_adj; errno=2
01-01 01:11:47.545 1913 1913 E lowmemorykiller: Error opening /proc/4014/oom_score_adj; errno=2
01-01 01:11:47.550 1913 1913 E lowmemorykiller: Error opening /proc/4542/oom_score_adj; errno=2
01-01 01:11:47.550 2478 3943 W art : Long monitor contention event with owner method=int com.android.server.am.ActivityManagerService.broadcastIntent(android.app.IApplicationThread, android.content.Intent, java.lang.String, android.content.IIntentReceiver, int, java.lang.String, android.os.Bundle, java.lang.String[], int, android.os.Bundle, boolean, boolean, int) from ActivityManagerService.java:17497 waiters=3 for 894ms
01-01 01:11:47.560 2478 3943 I ActivityManager: Process org.cyanogenmod.themes.provider (pid 3497) has died
01-01 01:11:47.560 2478 3943 D ActivityManager: cleanUpApplicationRecord -- 3497
01-01 01:11:47.560 2478 2529 W art : Long monitor contention event with owner method=int com.android.server.am.ActivityManagerService.broadcastIntent(android.app.IApplicationThread, android.content.Intent, java.lang.String, android.content.IIntentReceiver, int, java.lang.String, android.os.Bundle, java.lang.String[], int, android.os.Bundle, boolean, boolean, int) from ActivityManagerService.java:17497 waiters=4 for 673ms
01-01 01:11:47.570 2478 2529 I ActivityManager: Process com.svox.pico (pid 4014) has died
01-01 01:11:47.570 2478 2529 D ActivityManager: cleanUpApplicationRecord -- 4014
01-01 01:11:48.325 2478 2529 W ActivityManager: Scheduling restart of crashed service com.svox.pico/.PicoService in 1000ms
Verdict
I wasted lots of time with this issue, but was finally able to reproduce it and to recover all of my data. At least, I have an explanation now for various random reboots I experienced in the past in similar low-memory conditions.
Overall, I am really shocked that a simple, unprivileged Android app that is scheduled to start on bootup can ruin a working system so badly. Further research indicates that there are more apps known to cause such behavior [4]. I hope that a device based on a GNU/Linux system instead of Android (such as the announced Librem5) will not suffer from such a severe flaw.
External References
(The providers of these resources are solely responsible for them - see legal notice).