Android
From infidel
In March 2009 I purchased an HTC Dream smart-phone running Google's Android operating system.
Contents |
Applications
My favourite third-party applications:
- Hungry! shopping list
- ToggleWifi
- TimeTracker
Command Line
Standard Commands
The following Linux commands work in a fairly standard way, though with fewer options:
- cat
- chmod
- cmp
- date
- dd
- df
- dhcpcd
- dmesg
- id
- ifconfig
- insmod
- kill
- ln
- ls
- lsmod
- mkdir
- mkdosfs
- mount
- mv
- netstat
- ping
- printenv
- ps
- reboot
- renice
- rm
- rmdir
- rmmod
- setconsole
- sh
- sleep
- sync
- top
- umount
- vmstat
Other Commands
Other interesting commands (in terminal emulator or adb shell):
| cat source > destination | Copy a file, in the absence of "cp" |
| dalvikvm -classpath apk_path class_name | Launch a command-line Java program (static main()) |
| fillup percentage | Fills up the /data file system to a certain percentage, for testing purposes |
| getevent | Continuously monitors and prints out input device events |
| getprop | Display the values of the system properties |
| hd file | Display a hex dump of the contents of a file |
| iftop | Like "top" but displays network activity counters |
| input text string | Simulates keyboard events to type the specified text |
| input keyevent keycode | Simulates pressing the specified key |
| log message | Write a message to the Android logging system |
| logwrapper command [args]... | Executes a command and redirects stdout/stderr to the Android logging system |
| netcfg | Displays a list of network interfaces, whether they are up or down, and the IP address and netmask |
| pm list packages | Displays a list of installed packages (applications) |
| pm -l | Same as "pm list packages" |
| pm list packages -f | Displays the paths to the APK files for all packages |
| printenv | Display the environment variables |
| schedtop | Displays thread scheduling and timing statistics |
| sdutil | This command is used for controlling whether the SD card is mounted or used for USB mass storage |
| service list | List the installed services in the system |
| setprop | Set the value of a system property |
| svc power stayon true | Enables the 'Stay awake while charging' setting |
The following commands are documented by Google:
- dumpcrash
- dumpstate
- dumpsys
- logcat
- monkey
The following programs are part of the operating system, and are not designed to be invoked from the command line:
- dbus-daemon
- hcid
- hostapd
- installd
- linker
- mediaserver
- mountd
- rild
- qemud
- servicemanager
- smd
- surfaceflinger
- system_server
- toolbox
I don't know the exact purpose of the following commands:
- app_process
- debuggerd
- debug_tool
- dexopt
- dvz
- flash_image
- hciattach - related to Bluetooth
- hostapd_cli
- htclogkernel
- ioctl
- itr - something to do with "instrumentation"
- notify
- playmp3
- radiooptions
- route
- sdptool - something to do with Service Discovery Protocol
- sendevent
- ssltest
- start
- stop
- wipe
- watchprops
File and Directory Permissions
Mount table:
rootfs / rootfs ro 0 0 tmpfs /dev tmpfs rw,mode=755 0 0 devpts /dev/pts devpts rw,mode=600 0 0 proc /proc proc rw 0 0 sysfs /sys sysfs rw 0 0 tmpfs /sqlite_stmt_journals tmpfs rw,size=4096k 0 0 /dev/block/mtdblock3 /system yaffs2 ro 0 0 /dev/block/mtdblock5 /data yaffs2 rw,nosuid,nodev 0 0 /dev/block/mtdblock4 /cache yaffs2 rw,nosuid,nodev 0 0 /dev/block/mmcblk0p1 /sdcard vfat rw,dirsync,nosuid,nodev,noexec,uid=1000,gid=1000,fmask=0711,dmask=0700,codepage=cp437,iocharset=iso8859-1,utf8 0 0
As you can see, the "/sdcard" directory has a lot of restrictions:
- All files and directories on the card appear to be owned by "system"
- All directories on the card have mode ""d---rwxrwx"
- All files on the card have mode "----rw-rw-"
- You can't execute native executables from the card
The following directories are world-writable and permit execution, which can be useful for temporary storage during development:
- In RAM:
- /sqlite_stmt_journals (restricted deletion bit is set)
- In internal flash memory:
- /data/anr
The following directories are writable by the "shell" user and/or group, which means that you can write to them from an adb shell:
- /data/local
- /data/local/tmp
The following executables have the "setgid" bit set:
- /system/bin/ping, group "net_raw"
- /system/bin/netcfg, group "inet"
Directory Structure
Internal Flash Memory Layout
The layout of the internal flash memory is configured in the Memory Technology Device (MTD) table:
$ cat /proc/mtd dev: size erasesize name mtd0: 00040000 00020000 "misc" mtd1: 00500000 00020000 "recovery" mtd2: 00280000 00020000 "boot" mtd3: 04380000 00020000 "system" mtd4: 04380000 00020000 "cache" mtd5: 04ac0000 00020000 "userdata"
Mount Table
Mount table:
rootfs / rootfs ro 0 0 tmpfs /dev tmpfs rw,mode=755 0 0 devpts /dev/pts devpts rw,mode=600 0 0 proc /proc proc rw 0 0 sysfs /sys sysfs rw 0 0 tmpfs /sqlite_stmt_journals tmpfs rw,size=4096k 0 0 /dev/block/mtdblock3 /system yaffs2 ro 0 0 /dev/block/mtdblock5 /data yaffs2 rw,nosuid,nodev 0 0 /dev/block/mtdblock4 /cache yaffs2 rw,nosuid,nodev 0 0 /dev/block/mmcblk0p1 /sdcard vfat rw,dirsync,nosuid,nodev,noexec,uid=1000,gid=1000,fmask=0711,dmask=0700,codepage=cp437,iocharset=iso8859-1,utf8 0 0
Root Directories
The following directories work in the standard Linux way:
- /dev
- /proc
- /sys
Other directories in the root:
- /
- Read-only container
- /cache
- 67.5 MB of internal flash memory
- I don't know what this is used for
- /data
- 74.5 MB of internal flash memory
- All user and application data is stored here
- /sqlite_stmt_journals
- 4 MB RAM-based storage for SQLite database transaction journals
- Storing journals in RAM seems a bit dangerous; a database could become corrupted if the battery fails or if the OS crashes
- /system
- 67.5 MB of internal flash memory, mounted read only
- The operating system is stored here, and is analogous to the standard Linux root directory in many ways
Structure of /system
To Do
Structure of /data
On a normal HTC Dream, /data is not world-readable so you can't list its contents, but the emulator does allow it:
drwxrwx--x system system 2009-02-05 23:46 app drwxrwx--t system misc 2009-02-11 11:56 misc drwxrwx--x shell shell 2009-02-11 11:56 local drwxrwx--x system system 2009-02-11 11:56 data drwxrwx--x system system 2009-02-11 11:56 app-private drwx------ root root 2009-02-11 11:56 property drwxrwxrwx system system 2009-02-11 11:56 anr drwxrwx--x system system 2009-02-11 11:56 dalvik-cache drwxrwxr-x system system 2009-02-11 11:56 system drwxrwx--- root root 2009-02-11 11:56 lost+found
The purpose of each directory is:
- /data/anr - contains a text file "traces.txt" recording debugging information when an Application Not Responding (ANR) error occurs
- /data/app - contains the .apk files for all non-copy-protected applications that have been installed by the user
- /data/app-private - contains the .apk files for all copy-protected installed applications
- /data/dalvik-cache - caches uncompressed copies of classes.dex for all applications (including built-in system applications and libraries)
- For example, /data/dalvik-cache/system@app@AlarmClock.apk@classes.dex was extracted from /system/app/AlarmClock.apk
- This is necessary because .apk files are compressed, but Dalvik reads .dex files using memory-mapped file I/O
- /data/data - see the separate section below
- For example, /data/data/com.android.alarmclock stores data for the Alarm Clock application
- /data/local - ? (contains only a subdirectory "tmp")
- /data/local/tmp - ? (empty)
- /data/misc - ? (contains only a subdirectory "hcid", owned by "bluetooth")
- /data/misc/hcid - ? (empty)
- /data/property - ?
- /data/system - see the separate section below
- /data/lost+found - see http://tldp.org/LDP/Linux-Filesystem-Hierarchy/html/lostfound.html
Structure of /data/data
Contains a subdirectory for storing the data for each application, including built-in system applications.
Partial example listing:
drwxr-xr-x app_0 app_0 2009-02-11 11:56 com.google.android.apps.maps drwxr-xr-x app_1 app_1 2009-02-11 11:57 com.android.alarmclock drwxr-xr-x app_2 app_2 2009-02-11 11:57 com.android.bugreport drwxr-xr-x app_3 app_3 2009-02-11 11:57 com.android.calculator2 drwxr-xr-x app_4 app_4 2009-02-11 11:57 com.android.camera drwxr-xr-x app_5 app_5 2009-02-11 11:57 com.android.contacts drwxr-xr-x app_5 app_5 2009-02-11 11:57 com.android.providers.contacts
Each directory corresponds to an application or system package, and in most cases each directory is owned by a special app_x user. The typical subdirectories are:
- cache
- Created when Context.getCacheDir() is first called
- Applications can store any files that they wish here, but they may be deleted by the system at any time if storage space is running low
- databases
- Used for storing an application's SQLite databases
- Returned by Context.getDatabasePath()
- Used by Context.openOrCreateDatabase(), etc.
- files
- Created when Context.getFilesDir() is first called
- Used by Context.openFileOutput(), etc.
- Applications may use it to store any files that they wish
- lib - ?
- shared_prefs
- Used to store XML preferences by the SharedPreferences object as returned by Context.getSharedPreferences()
- Applications can specify the name of the preferences file, except for the file extension which is always .xml
Applications can create additional subdirectories by calling Context.getDir(), but in such cases the name of the directory will begin with "app_".
Structure of /data/system
Listing:
-rw-rw-r-- system system 38121 2009-04-03 03:00 packages.xml -rw------- system system 76 2009-04-03 03:00 batterystats.bin -rw-rw---- system system 14336 2009-04-03 03:00 syncmanager.db -rw------- system system 8 2009-04-03 03:00 syncmanager.prefs -rw-rw---- system system 12288 2009-04-03 03:00 checkin.db
Purpose:
- packages.xml - contains metadata about all applications, including signatures, permissions, etc.
- batterystats.bin - ?
- syncmanager.db - ?
- syncmanager.prefs - ?
- checkin.db - ?
Structure of /cache
To Do
dalvikvm
The only way that "dalvikvm" command (which is Android's equivalent of the "java" command) can be used is to execute a class within an APK that is properly installed inside the "/data/app" directory. All other locations result a "class not found" error. The reason for this is that code in an APK cannot be executed directly and must first be decompressed into a DEX file because Dalvik uses memory mapped file I/O to access the DEX file. Dalvik looks for the DEX file in /data/dalvik-cache, but this directory is only writable by "system" so an APK file can only be executed if it has been properly installed.
See also: http://code.google.com/p/android/issues/detail?id=966
As an example, suppose that an Android application package "com.example.hello" has been installed, and that it contains a class "com.example.hello.HelloWorld" with a static main() function (in addition to the Activity class that usually runs). You can execute this command-line main() with:
dalvikvm -classpath /data/app/com.example.hello.apk com.example.hello.HelloWorld
Native Code Development
There are two possible approaches to building native code for Android:
- Put the C/C++ code in a directory under the Android source tree, create Android.mk files and run "make"
- Install a third-party ARM GCC toolchain and use that to compile the code, with whatever build system is appropriate (e.g. autoconf)
I have so far only been using the first method, because it has the following advantages:
- Since the compiler toolchain comes from Google, I have more confidence that it will work with Android
- It is easy to "install"; just get the full source tree using "repo" and run "make"
- While Android.mk is unfamiliar, it is quite simple and effective
- Linking against Android's shared libraries is easy; dependencies are automatic
The possible disadvantages are:
- Android's build system can often cause several seconds delay as the large set of Makefiles are loaded
- The full Android repository takes a few gigabytes of disk space
Debugging
I found this article to be a useful starting point for remote debugging of native code using GDB:
http://honeypod.blogspot.com/2008/01/debug-native-application-for-android.html
Since I have been using the prebuilt toolchain from the Android source repository, the steps are a bit simpler
- Copy the executable to be debugged onto the device
- Copy prebuilt/android-arm/gdbserver onto the device in the same directory
- Find the IP address of the device, e.g. by running "netcfg" in an adb shell
- Run gdbserver from a device shell such as "adb shell", e.g.:
- ./gdbserver 192.168.0.2:1234 hello_world
- Run GDB on the PC:
- prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-gdb hello_world
- Type the GDB command:
- target remote 192.168.0.2:1234
Bionic C Library Problems
The worst problem I have encountered so far was when trying to build Lua. I did read the article at http://www.damonkohler.com/2008/12/lua-on-android.html but I naively tried to build it without applying the patches from the article, just to see what would happen.
The first problem is that the header files in Android's C library (named "Bionic") contain:
/* Make libstdc++-v3 happy. */
struct lconv { };
struct lconv *localeconv(void);
http://android.git.kernel.org/?p=platform/bionic.git;a=blob;f=libc/include/locale.h;hb=HEAD
These declarations are silly because localeconv() is not defined anywhere, so you would get a linker error when calling it.
The second problem is much more insidious: strcoll() is declared and defined in the latest version of Bionic, but it is not defined in the libc.so on my HTC Dream. This means that compiling and linking will succeed but it will fail at runtime. The symptom is that the program simply exits before reaching main() with error code 255 as the only indication of a problem. There are no error messages on the screen or in the logs, so it is very difficult to tell that there was a dynamic linking error, let alone figure out which symbol is missing from which library.
This thread contains a useful tip from David Given for manually finding unresolved dynamic symbols:
Scripting
To Do
Java Native Access
Java Native Access (JNA) is a library allowing Java code to directly invoke C functions in native shared libraries without the need for compile-time translation such as JNI. The JNA project is hosted at https://jna.dev.java.net/
I have been experimenting with porting JNA to Android, and I have done the following so far:
- Hacked the Java part of JNA to avoid AWT and other APIs that are not available on Android
- Hacked the native part of JNA, replacing calls to NewWeakGlobalRef() with calls to NewGlobalRef()
- http://groups.google.com/group/android-platform/browse_thread/thread/d0f91853db7bad20
- Note that attempting to call NewWeakGlobalRef() logs an error message and deliberately crashes dalvikvm
- Compiled the native part of JNA using the Android platform build system (Android.mk)
- Created a dummy Android application that includes JNA, as well as the JNA test suite
- Manually copied libtestlib.so into /data/data/<package>/files
- Hacked com.sun.jna.NativeTest.main() to call NativeLibrary.addSearchPath() to set the correct path to libtestlib.so
- Ran a few test cases from the command line
Many tests fail with:
java.lang.Error: This VM does not store fields in a predictable order; you must use setFieldOrder: The Android Project, 0 at com.sun.jna.Structure.calculateSize(Structure.java:855)
Presumably this means that the test cases need to be modified to call setFieldOrder(). I wonder if someone has already done this?
