A missing manual for Android.
1. Preface. A missing manual for Android.
1.1. Motivation
The motivation for this text is somehow bizarre. I am by no means an Android expert, but I have been using computers for a long time, and over that time I have found that despite superficial UX and command-line differences, the basic principles behind most programming systems are the same. So switching to a new system in most cases just requires thoroughly reading a manual, and you are good to go.
And, from most perspectives, Android is not at all different. It is generally a normal operating system, it can run processes, organise IPC, multiplex windows, sounds, and services.
But its official documentation is just a giant pile of AI-generated slop, and nobody seems to have written an unofficial version, which really baffles me. Seriously, WinAPI has good books about it, not even mentioning user-level books, UNIX has an insane amount of books, starting from “The UNIX Programming Environment” and ending with Michael Kerrisk’s “The Linux Programming Interface”.
Android, in its turn, is not even a bit simpler than WinAPI or UNIX, but, despite being the most popular OS in the world, seems to be lacking a decent manual.
Of course, I cannot write a book on something I did not take part in developing (nobody should), but due to such a horrible lack of materials I had the bravery to guess that even my humble jottings might be helpful to someone learning to efficiently use this wonderfully interesting system.
1.2. Basic principles
Writing down this book, I tried to follow the Occam’s razor in its (allegedly attributed to Albert Einstein) formulation: “Everything should be kept as simple as possible, but no simpler.”
When applied to computing, it becomes the following:
“I already have everything working the way I like it to be working on my desktop machine, now I just need to extend exactly the same things to my new portable device, spending as little effort as possible.”
The rest of this HOWTO is dedicated to implementing this principle.
2. Main body
2.1. TODO Building the system
2.1.1. TODO Make
2.1.2. TODO Soong
2.1.3. TODO ckati
2.1.4. TODO Gradle
2.3. TODO Storage
Android storage is really mind-boggling.
Background reading: https://www.kernel.org/doc/Documentation/filesystems/sharedsubtree.txt
2.3.1. FHS
- /data/local/tmp – some developer-related temp directory? manuals recommend placing
lldb-server,frida-server, and such there
2.5. TODO Debugging Android applications
Android’s default debugger on newer releases is lldb.
Older releases used gdb.
They are quite similar, but since newer Androids use lldb, I will pay more attention to it.
You need to get familiar with lldb itself:
While it is probably possible to run lldb on the device itself.
2.5.1. Using the default debugger interface
You need to push a static build of lldb-server onto the device.
I found that using the one shipped with Android is easier than building myself.
lldb-server is in prebuilts/clang/host/linux-x86/clang-r530567/runtimes_ndk_cxx/aarch64/lldb-server.
What exactly is specifically good about the build 530567 I have no idea, but other builds failed for me, the debugger stopping unexpectedly and the program being incredibly slow, too slow to debug.
With respect to a system-wide lldb, I had an issue with it, it didn’t disassemble aarch64 code, I do not know why.
adb push prebuilts/clang/host/linux-x86/clang-r530567/runtimes_ndk_cxx/aarch64/lldb-server ./lldb-server platform --listen "*:54321" --server adb forward tcp:54321 tcp:54321 PYTHONHOME=prebuilts/clang/host/linux-x86/clang-r530567/python3/ LD_LIBRARY_PATH=prebuilts/clang/host/linux-x86/clang-r530567/python3/lib PYTHONPATH=prebuilts/clang/host/linux-x86/clang-r547379/lib/python3.11/site-packages/ ./prebuilts/clang/host/linux-x86/clang-r530567/bin/lldb # in lldb platform select remote-android platform connect connect://:54321 process handle --pass true --stop false --notify true SIGSEGV process handle --pass true --stop false --notify true SIGBUS
In principle you can do something similar with GDB, you just need to find a static build of GDB.
2.5.2. Use the Ghidra debugger
After you have set up the default lldb, you can connect a GUI to it, for example a Ghidra-debugger, because GUI software is better for data inspection.
https://github.com/NationalSecurityAgency/ghidra/issues/6386
adb -s a740e4ea forward tcp:54321 jdwp:20971
2.6. TODO getprop
This is a kind of “Registry” for system properties.
"getprop" -T -Z.
They have something like selinux attributes attached to them (crazy!), so you need to understand SELinux first, before doing anything useful with them.
There is also setprop.
2.7. TODO init.rc
This is something like what Android has instead of init.d (why would you reinvent the wheel again?). Magisk can plug into this file without making the system go insane, but I guess it is better to use Magisk’s services anyway.
2.8. Security
https://android.stackexchange.com/questions/210139/what-is-the-u-everybody-uid/210159#210159
Selinux?
https://android.stackexchange.com/questions/210139/what-is-the-u-everybody-uid/
Runtime permissions
https://source.android.com/devices/storage#runtime_permissions
Namespaces
https://developer.android.com/training/data-storage#scoped-storage
2.9. List of Java apps:
/data/system/packages.list
2.10. am (Activity Manager)
Some command for activities/services management.
For example, you can restart “Airplane Mode” by typing:
#!/system/bin/sh settings put global airplane_mode_on 1 sleep 1 am broadcast -a android.intent.action.AIRPLANE_MODE sleep 1 settings put global airplane_mode_on 0 sleep 1 am broadcast -a android.intent.action.AIRPLANE_MODE
2.11. pm (Package Manager)
2.12. dalvikvm64
2.13. tombstones
2.14. interactive debugging
3. Application-level development
3.1. Unset _JAVA_OPTIONS
Because Android Studio is shit and broken.
3.2. Delete all Android Studio data when updating
Otherwise very weird symptoms occur
- ~/.config/
3.3. when you change applicationId, it is not enough to re-sync Gradle
You also have to manually delete all run configurations and re-sync, otherwise weird errors occur.
~/.config/Google/AndroidStudio2024.2/
3.5. Sometimes adb server fails
The symptom is
Adb connection Error:EOF Cannot reach ADB server, attempting to reconnect daemon not running; starting now at tcp:5037
I fixed this by switching from openscreen to bonjour in Debugger settings.
This also makes the emulator start/stop buttons work again.
3.6. Camera APP in the emulator crashes.
This is because Google has a broken AOSP Marshmallow (Android 6.0) image. Use the Google API enabled one.
3.7. More emulator tweaks
3.8. View vs Fragments
3.11. Dagger
3.12. Mortar
4. Debugging weird stuff
- Program restarting with SIGBUS https://stackoverflow.com/questions/78044084/android-app-paused-while-debugging-due-to-sigbus-signal
- Program restarting with SIGSEGV https://stackoverflow.com/questions/52377562/how-do-you-create-a-lldb-script-to-ignore-sigsegv-and-sigbus
- Life instrumentation – use Frida https://cilynx.com/vulnerabilities/exploring-native-functions-on-android-and-runtime-analyses-using-jadx-ghidra-and-frida/1565/
- Debugging Android aarch64 with Ghidra https://blog.nviso.eu/2024/01/15/deobfuscating-android-arm64-strings-with-ghidra-emulating-patching-and-automating/