Arquitectura Software de Android
Contents
Arranque de Android
Nada mejor que comenzar a entender la arquitectura software de Android que estudiando su arranque. Android tiene diversas formas de iniciar:
- Normal: Es el proceso que se sigue cuando se inicia pulsando sólo el botón de arrancar.
- Fastboot USB: permite enviar comandos desde el host por USB para controlar como se arranca.
- Recovery: inicia utilizando la partición de Recovery que tiene una imagen especial.
Arranque Normal
El arranque en general de las arquitecturas basadas en ARM lo podemos ver documentado en el núcleo Linux.
El arranque en Android tiene dos fases (IPL y SPL):
- IPL: Initial Program Loader (dentro de CPU). Pequeño programa que se encarga de cargar el SPL.
SPL: Second Program Loader. Controla que se puede carga el la FLASH RAM del dispositivo entre otras cosas. Es conocido como HBOOT también. El SPL es el que permite o no permite que instalemos actualizaciones del sistema ya que puede evitar instalar actualizaciones no firmadas de forma oficial.
Hasta donde he investigado el SPL no se encuentra disponible en código fuente y las versiones que existen son evoluciones unas de otras, modificadas con editores hexadecimales probablemente.
Algunas referencias:
Particiones
Una vez iniciado el sistema tenemos el siguiente esquema de particiones:
# cat /proc/mtd dev: size erasesize name mtd0: 000e0000 00020000 "misc" mtd1: 00500000 00020000 "recovery" mtd2: 00280000 00020000 "boot" mtd3: 09100000 00020000 "system" mtd4: 05f00000 00020000 "cache" mtd5: 0c440000 00020000 "userdata" mtd6: 20000000 00020000 "msm_nand"
De todas estas particiones las que están montadas son:
# mount | grep mtd /dev/block/mtdblock3 on /system type yaffs2 (ro,relatime) /dev/block/mtdblock5 on /data type yaffs2 (rw,nosuid,nodev,relatime) /dev/block/mtdblock4 on /cache type yaffs2 (rw,nosuid,nodev,relatime)
e inicialmente tienen la ocupación en Cyanogen:
# df -h Filesystem Size Used Available Use% Mounted on /dev/block/mtdblock3 145.0M 95.7M 49.3M 66% /system /dev/block/mtdblock5 196.3M 2.2M 194.0M 1% /data /dev/block/mtdblock4 95.0M 24.1M 70.9M 25% /cache
Las particiones son de tipo "yaffs2" y el almacenamiento "/dev/block/mtdblock" es un disco FLASH RAM de tipo MTD. La FLASH que lleva el N1 es de 512 MB. En el N1 y viendo las trazas del núcleo vemos que es una NAND FLASH (msm_nand).
Estructura de directorios
Me he compilado el comando "tree" para que funcione en Android. Dejo adjunto a este fichero el "tree.c" modificado para que compile para Android y el binario compilado.
# tree -L 2 -I "proc|sys|sdcard|dev"
.
|-- cache
| |-- dalvik-cache
| |-- lost+found
| `-- recovery
|-- config
|-- d -> /sys/kernel/debug
|-- data
| |-- anr
| |-- app
| |-- app-private
| |-- backup
| |-- dalvik-cache
| |-- data
| |-- dontpanic
| |-- local
| |-- lost+found
| |-- misc
| |-- property
| `-- system
|-- default.prop
|-- etc -> /system/etc
|-- init
|-- init.goldfish.rc
|-- init.mahimahi.rc
|-- init.rc
|-- root
|-- sbin
| `-- adbd
|-- sqlite_stmt_journals
`-- system
|-- app
|-- bin
|-- build.prop
|-- etc
|-- fonts
|-- framework
|-- lib
|-- lost+found
|-- media
|-- usr
`-- xbin
34 directories, 7 filesLa estructura de directorios no es la habitual en una distribución de GNU/Linux y se ve que está poco pulida. Por ejemplo, si consultamos el PATH que viene definido por defecto definido en init.rc
/usr/bin:/usr/sbin:/bin:/sbin:/system/sbin:/system/bin:/system/xbin:/system/xbin/bb:/data/local/bin
hay directorios que no existen, como "/usr/*" o "/data/local/bin". ¿Qué motivación habrá llevado a no seguir FHS adoptado por LSB y seguido en las distros de Linux?
Despliegue de aplicaciones
Vamos a tomar como ejemplo una aplicación y veamos como está distribuida. Por ejemplo, el Navegador que se incluye por defecto que es software libre. Si lanzamos el navegador utilizando la interfaz de android y vemos los procesos en ejecución:
# ps | grep browser app_31 516 75 167272 29596 ffffffff afe0dc84 S com.android.browser
Vemos que es una aplicación lanzada desde una clase Java "com.android.browser". Las aplicaciones Android que funcionan por encima de Dalvik, las normales, las encontramos en el directorio:
# pwd /system/app # ls AccountAndSyncSettings.apk MagicSmokeWallpapers.apk ApplicationsProvider.apk MediaProvider.apk Bluetooth.apk MediaUploader.apk Browser.apk Mms.apk Calculator.apk Music.apk Calendar.apk PackageInstaller.apk CalendarProvider.apk Phone.apk Camera.apk PicoTts.apk CertInstaller.apk Provision.apk Contacts.apk Settings.apk ContactsProvider.apk SettingsProvider.apk DeskClock.apk SoundRecorder.apk Development.apk SpareParts.apk DownloadProvider.apk Superuser.apk DrmProvider.apk TelephonyProvider.apk Email.apk Term.apk Gallery3D.apk TtsService.apk GenieWidget.apk UserDictionaryProvider.apk GlobalSearch.apk VisualizationWallpapers.apk GoogleSearch.apk VoiceDialer.apk HTMLViewer.apk VpnServices.apk HtcCopyright.apk com.amazon.mp3.apk LatinIME.apk googlevoice.apk Launcher2.apk kickback.apk LiveWallpapers.apk soundback.apk LiveWallpapersPicker.apk talkback.apk
Ya veremos que las que instalemos nosotros van al directorio "/data/app".
Las aplicaciones están empaquetadas según el formato "apk". Si nos fijamos en nuestra aplicación:
# ls -l Browser.apk -rw-r--r-- 1 root root 724753 Aug 1 2008 Browser.apk
Si la copiamos al ordenador y estudiamos este fichero:
adb pull /system/app/Browser.apk . file Browser.apk Browser.apk: Zip archive data, at least v2.0 to extract mkdir Browser cd Browser unzip ../Browser.apk Archive: ../Browser.apk inflating: META-INF/MANIFEST.MF ... tree -L 2 . |-- AndroidManifest.xml |-- META-INF | |-- CERT.RSA | |-- CERT.SF | `-- MANIFEST.MF |-- assets | `-- html |-- classes.dex |-- res | |-- anim | |-- drawable | |-- drawable-hdpi | |-- layout | |-- layout-land | |-- menu | `-- xml `-- resources.arsc
Vemos el fichero "AndroidManifest.xml" en formato XML binario (tiene interés su modificación para personalizar cosas), la firma (keytool -printcert META-INF/CERT.RSA para verla), el directorio assets (no tengo claro su objetivo), las clases de la aplicación y los recursos.
El fichero que contiene las clases es "classes.dex". Para ver sus contenidos hay que utilizar la herramienta dexdump que podemos obtener del entorno de compilación de Android
ls -l cupcake/out/host/linux-x86/bin/dexdump -rwxr-xr-x 1 acs acs 200598 2010-02-16 00:07 cupcake/out/host/linux-x86/bin/dexdump acs@rayito:/tmp/Browser$ dexdump classes.dex | grep "Class descriptor" Class descriptor : 'Lcom/android/browser/ActiveTabsPage$1;' Class descriptor : 'Lcom/android/browser/ActiveTabsPage$CloseHolder;' ... Class descriptor : 'Lcom/google/android/providers/GoogleSettings;'
Con la opción "-d" además de mostrar la información de las clases, nos muestra el código de las mismas. El fichero ".dex" se genera de forma automática desde las clases Java con la herramienta "dx".
Arquitectura Detallada de una aplicación Android
Creación de una Distribución/ROM completa de Android
Con todo lo estudiado hasta el momento estamos en posición de ver que hace falta para crear una distribución Android completa.
- Cargadores IPL, SPL: esto viene fijado en gran medida por el fabricante de hardware. El SPL sí tiene algunas versiones.
- Núcleo de la distribución
- Aplicaciones incluidas
- Aspecto gráfico
Un sistema Android iniciado en modo normal tiene tres bloques fundamentales:
- boot.img: incluye el núcleo y el ramdisk de arranque del sistema, que se encuentra en "/".
- system.img: incluye todos los ficheros del sistema dentro de "/system"
- data.img: incluye todas las aplicaciones y los datos de usuario.
Si miramos que incluye una ROM de Android, en este caso la de Cyanogen:
unzip -l update-cm-5.0.4.1-N1-signed.zip > Ficheros
vi Ficheros
Archive: update-cm-5.0.4.1-N1-signed.zip
Length Date Time Name
--------- ---------- ----- ----
57852 2008-02-28 21:33 META-INF/MANIFEST.MF
57905 2008-02-28 21:33 META-INF/CERT.SF
1714 2008-02-28 21:33 META-INF/CERT.RSA
8057 2010-02-13 17:48 META-INF/com/google/android/update-script
2388 2010-02-26 09:32 backuptool.sh
2428928 2010-02-27 05:27 boot.img
171511 2010-02-26 10:41 system/app/AccountAndSyncSettings.apk
...
5416 2010-02-26 09:07 system/xbin/timeinfo
--------- -------
96353022 672 filesVemos que lleva la imagen con el núcleo y el ramdisk de inicio y luego el directorio "/system" sin llevar aplicaciones específicas de usuario.
¿Cómo se hace el boot.img? Esto está descrito en este documento. Utilizando las herramientas indicadas podemos analizar ese boot.img:
unzip update-cm-5.0.4.1-N1-signed.zip boot.img Archive: update-cm-5.0.4.1-N1-signed.zip inflating: boot.img ./unpack-bootimg.pl boot.img kernel written to boot.img-kernel.gz ramdisk written to boot.img-ramdisk.cpio.gz 502 bloques extracted ramdisk contents to directory boot.img-ramdisk/ ls -l boot.img-kernel.gz -rw-r--r-- 1 acs acs 2265088 2010-03-07 15:15 boot.img-kernel.gz tree boot.img-ramdisk boot.img-ramdisk |-- data |-- default.prop |-- dev |-- init |-- init.goldfish.rc |-- init.mahimahi.rc |-- init.rc |-- proc |-- sbin | `-- adbd |-- sys `-- system
Si queremos por ejemplo modificar el inicio de la distro, basta con modificar los contenidos del ramdisk y crear una nueva boot.img con el kernel y ese nuevo ramdisk.
Vamos a comenzar a trabajar con la comunidad de Cyanogen en todos estos temas.
Tablets
A parte de los móviles vamos a comenzar a trabajar también con tabletas:
Actualizaciones a un sistema Android
Núcleo: Boot images
- Aplicaciones
- Sistema de arranque
- Otras