Nota: Este tutorial ha sido donado a la comunidad de javaHispano por Intel. Intel espera que en el futuro sus procesadores incrementen considerablemente su presencia en los terminales móviles Android, por ello ha creído que este artículo sería interesante para nuestra comunidad. El artículo puede encontrarse en la web de Intel aquí.
Este documento introduce métodos detallados para el desarrollo y migración de una aplicación Android en la plataforma Intel Atom, y describe los métodos más conocidos para desarrollar aplicaciones mediante el Kit para desarrollo nativo para Android (NDK) y para optimizar el rendimiento. Los desarrolladores para Android pueden utilizar este documento como una referencia para crear aplicaciones de alta calidad para la arquitectura Intel.
Las aplicaciones para Android pueden clasificarse en dos tipos, tal como se muestra en la Ilustración 1.
Ilustración 1: Dos tipos de aplicaciones para Android
2.1 Introducción
El Kit de desarrollo nativo para Android (NDK) es una herramienta que complementa al SDK de Android. El NDK es una herramienta poderosa para el desarrollo de aplicaciones para Android debido a que:
2.2 Descripción general de las herramientas
Durante el período de desarrollo, puede utilizar Intel® Hardware Execution Manager (HAXM) para mejorar el rendimiento del simulador para Android. HAXM es un motor de virtualización con la ayuda de hardware (hipervisor) que utiliza la Tecnología Intel® de virtualización para acelerar la emulación de aplicaciones para Android en un equipo huésped. En combinación con imágenes del emulador para Android x86 que Intel proporciona y el Administrador de Android SDK oficial, HAXM resulta en una experiencia de emulación para Android más rápida en sistemas habilitados para la Tecnología Intel® de virtualización. Para obtener más información sobre HAXM, visite: http://software.intel.com/es-es/articles/intel-hardware-accelerated-execution-manager.
2.3 Instalación de HAXM
Utilice el Administrador de Android SDK para instalar HAXM (recomendable) o, para hacerlo manualmente, descargue el instalador del sitio web de Intel. Si desea actualizarlo automáticamente, instálelo con el administrador del Android SDK, tal como se muestra en la Ilustración 2. [1]
Ilustración 2: Instalar Intel HAXM con el Administrador de Android SDK
También puede descargar un paquete de instalación adecuado desde http://software.intel.com/es-es/android a su plataforma huésped y seguir las instrucciones paso a paso para instalarlo.
2.3.1 Configuración de HAXM
Cuando se ejecuta HAXM, se requiere la imagen del sistema Android x86 que Intel proporciona. Puede descargar la imagen del sistema usando el Administrador de Android SDK o descargarla manualmente del sitio web de la Zona para desarrolladores Intel®.
Después de que las imágenes se instalan satisfactoriamente, las imágenes del emulador de Intel® x86 Android se ejecutan automáticamente utilizando el binario del “emulator-x86” proporcionado con el Android SDK. La Tecnología Intel® de virtualización acelera el emulador Android, lo cual acelera su proceso de desarrollo.
3.1 Desarrollo de aplicaciones NDK para los dispositivos basados en el procesador Intel Atom
Después de instalar el NDK satisfactoriamente, dedique unos minutos a leer los documentos del directorio <ndk>/docs/, especialmente los denominados OVERVIEW.html y CPU-X86.html, para familiarizarse con el mecanismo del NDK y cómo utilizarlo.
El desarrollo de la aplicación NDK puede dividirse en cinco pasos que se muestran en la Ilustración 3:
Ilustración 3: Proceso del desarrollo de la aplicación NDK
Para ilustrar estos cinco pasos, se utiliza la demostración de hello-jni. Puede encontrar esta demostración en la carpeta NDK Root\samples\hello-jni [5]. La demostración de Hello-jni es una aplicación simple incluida en el NDK que obtiene una cadena de un método nativo en una biblioteca compartida y la utiliza en la interfaz de usuario de la aplicación.
3.1.1. Creación del código nativo
Cree un nuevo proyecto para Android y coloque su código fuente nativo bajo <proyecto>/jni/. El contenido del proyecto se muestra en la Ilustración 4. Esta demostración incluye una simple función en código nativo denominada Java_com_example_hellojni_HelloJni_stringFromJNI(). Tal como se muestra en el código fuente, devuelve una cadena simple de JNI.
Ilustración 4: Creación del código nativo
3.1.2 Creación de MakeFile ‘Android.mk’
Las aplicaciones del NDK se crean para la plataforma ARM de manera predeterminada. Para crear aplicaciones NDK para la plataforma Intel Atom, es necesario agregar APP_ABI := x86 al MakeFile.
Ilustración 5: Creación de MakeFile
3.1.3 Compilación de código nativo
Cree un código nativo al ejecutar la secuencia de comandos 'ndk-build' desde el directorio del proyecto. Se encuentra en el directorio principal de NDK. El resultado aparece en la Ilustración 6.
Ilustración 6: Código nativo compilado
Las herramientas de creación copian automáticamente las bibliotecas compartidas esenciales a la ubicación pertinente en el directorio del proyecto de la aplicación.
3.1.4 Llamada del código nativo de Java
Cuando despliega la biblioteca compartida satisfactoriamente, puede llamar la función desde Java. El código se muestra en la Ilustración 7. Se crea una llamada de la función nativa pública stringFromJNI() en el código Java y esta función carga la biblioteca compartida con System.loadlibrary().
Ilustración 7: Llamada de código nativo desde Java
3.1.5 Depuración con GDB
Si desea depurar la aplicación NDK con GDB, es necesario satisfacer las siguientes condiciones:
Utilice el comando ndk-gdb para depurar la aplicación. Puede definir ya sea un punto de interrupción o una depuración paso a paso para realizar un seguimiento del historial de cambios de un valor variable, tal como muestra la Ilustración 8.
Ilustración 8: Depuración de la aplicación NDK con GDB
3.2 Migración de aplicaciones NDK existentes a dispositivos basados en el procesador Intel Atom
En esta sección, se asume que tiene una aplicación Android para la plataforma ARM y necesita migrarla antes de desplegarla en la plataforma Intel Atom.
La migración de las aplicaciones Android a la plataforma Intel Atom es similar al proceso de desarrollo. Los pasos se muestran en la Ilustración 9.
Ilustración 9: Migración de aplicaciones Android a la plataforma Intel Atom
3.2.1 Migración de aplicaciones Dalvik
Las aplicaciones Dalvik pueden ejecutarse directamente en los dispositivos basados en el procesador Intel Atom. La interfaz de usuario necesita ajustarse para el dispositivo de destino. Para un dispositivo de alta resolución, tales como tabletas con una resolución de 1280*800 o superior, la asignación de memoria predeterminada posiblemente no cumpla con los requisitos de la aplicación, lo cual impide que pueda lanzarse. Se recomienda el incremento de la asignación de memoria predeterminada para los dispositivos de alta resolución.
3.2.2 Migración de aplicaciones NDK para Android
La migración de aplicaciones NDK es un poco más complicada que la migración de aplicaciones Dalvik. Todas las aplicaciones NDK se pueden dividir en tres tipos según las siguientes propiedades del código nativo:
Código nativo que consiste en código C/C++ solo que no está relacionado con el hardware
Si el código nativo utiliza una biblioteca vinculada dinámica de terceros, la biblioteca compartida debe volver a compilarse en la versión x86 para la plataforma Intel Atom.
Si el código nativo incluye código ensamblador que esté altamente relacionado con las plataformas que no son de la arquitectura Intel,entonces el código debe volver a escribirse con ensamblador de la arquitectura Intel o C/C++.
4.1 Alineación de memoria forzada
Debido a diferencias entre las arquitecturas, plataformas y compiladores, puede que los tamaños de los datos de la estructura de los mismos datos en distintas plataformas sean diferentes. Sin la alineación de memoria forzada, pueden existir errores de carga para tamaños de datos incoherentes. [2]
El siguiente ejemplo describe los tamaños de datos de la misma estructura de datos en distintas plataformas:
struct TestStruct {
int mVar1;
long long mVar2;
int mVar3;
};
Esta es una estructura simple con tres variables denominadas mVar1, mVar2 y mVar3.
mVar1 es un int y utilizará 4 bytes
mVar2 es long long int que utilizará 8 bytes
mVar3 también es int, utilizará 4 bytes.
¿Cuántos espacios se necesitan en las plataformas ARM e Intel Atom?
El tamaño de los datos compilados para las plataformas ARM e Intel Atom con un interruptor de compilador predeterminado se muestra en la Ilustración 10. ARM adopta automáticamente doble malign y ocupa 24 bytes, mientras que x86 ocupa 16 bytes.
Ilustración 10: Memoria asignada por marcadores de compilación predeterminados
La variable mVar2 de 8 bytes (64 bits) resulta en un diseño distinto para TestStruct debido a que ARM requiere una alineación de 8 bytes para variables de 64 bits igual que mVar2. En la mayoría de los casos, esto no causa problemas debido a que crear para x86 vs. ARM requiere una reconstrucción completa.
No obstante, una incoherencia de tamaños podría presentarse si una aplicación serializa clases o estructuras. Por ejemplo, usted crea un archivo en una aplicación de ARM y escribe TestStruct en un archivo. Si posteriormente carga los datos desde ese archivo a una plataforma x86, el tamaño de la clase en la aplicación es diferente en el archivo. Problemas similares de alineación de memorias pueden ocurrir en el tráfico de redes que anticipa un diseño de memoria específico.
La opción “-malign-double” del compilador GCC genera la misma alineación de memoria en x86 y en ARM.
Ilustración 11: Memoria asignada cuando se agregan marcadores -malign-double
4.2.1 NEON
La tecnología NEON* de ARM se utiliza principalmente en multimedios tales como aplicaciones de smartphones y HDTV. Según la documentación de ARM, su tecnología basada en el motor SIMD de 128 bits, la cual es una extensión de ARM Cortex*–A Series, ofrece al menos 3 veces más rendimiento que la arquitectura de ARMv5 y al menos 2 veces más que la versión subsiguiente: ARMv6. Para obtener más información sobre la tecnología NEON visite: http://www.arm.com/products/processors/technologies/neon.php.
4.2.2 SSE: El equivalente de Intel
SSE es la Streaming SIMD Extension para la arquitectura Intel (IA). En la actualidad, el procesador Intel Atom es compatible con SSSE3 (Supplemental Streaming SIMD Extensions 3) y las versiones anteriores, pero todavía no es compatible con SSE4.x. SSE es un motor de 128 bits que acepta el encapsulamiento de los datos de puntos flotantes. El modelo de ejecución comenzó con la tecnología MMX y SSx es esencialmente la generación más reciente que reemplaza la necesidad de MMX. Para obtener más información, consulte la sección "Volume 1: Basic Architecture" (Volumen 1: Arquitectura básica) de los Manuales para Desarrolladores de software para las Arquitecturas Intel de 64 y 32 bits. La descripción general de SSE, que se encuentra en la sección 5.5, proporciona las instrucciones para SSE, SSE2, SSE3 y SSSE3. Estas operaciones de datos mueven valores de puntos flotantes basados en precisión y de alto contenido entre los registros de XMM o entre los registros de MMX y la memoria. Los registros de XMM fueron diseñados para usarse como un reemplazo de los registros de MMX.
4.2.3 De NEON a SSE a nivel de ensamblador
Cuando utilice el Manual para desarrolladores de software de la arquitectura Intel como una referencia cruzada para todos los mnemotécnicos SSE(x) individuales, examine también las distintas instrucciones al nivel de ensamblador de SSE ubicadas en:http://neilkemp.us/src/sse_tutorial/sse_tutorial.html. Utilice la tabla de contenido para acceder los ejemplos del código o examine los antecedentes.
De manera similar, el siguiente manual de ARM proporciona información sobre NEON y contiene pequeños fragmentos de código ensamblador en la sección 1.4,”Developing for NEON” (Desarrollo para NEON):http://infocenter.arm.com/help/topic/com.arm.doc.dht0002a/DHT0002A_introducing_neon.pdf.
Diferencias clave al comparar el código ensamblador NEON y SSE:
Nota: Estas diferencias no son todas las que existen. Puede ver otras diferencias entre NEON y SSE.
4.2.4 De NEON a SSE a nivel de C/C++
Pueden presentarse muchas dificultades de la API durante la migración del código C/C++ y NEON a SSE. Tenga en mente que asumimos que no se utilizará ensamblador inline, que en su lugar se utilizará el código C/C++ verdadero. Las instrucciones NEON también proveen algunas bibliotecas C nativas. Aunque estas instrucciones son código C, no pueden ejecutarse en la plataforma Intel Atom y deben volver a escribirse.
5.1 Ajuste de rendimiento
Durante el proceso de codificación, utilice los siguientes métodos para optimizar el rendimiento de su aplicación en la plataforma Intel Atom.
5.1.1 Uso de Inline (en línea) en lugar Frequently Used Short (corto utilizado frecuentemente)
Las funciones Inline son mejores para funciones pequeñas tales como el acceso a miembros de datos privados. Las funciones cortas son sensibles al impacto de las llamadas de funciones. Las funciones más largas demoran menos tiempo, de manera proporcionada, en la secuencia de llamadas/llamadas de regreso y se benefician menos de las funciones en línea. [4]
La función Inline (en línea) ahorra la sobrecarga en:
5.1.2 Uso de flotante en lugar de doble
FPU es una unidad de punto flotante que es una parte de un sistema especialmente diseñado para llevar a cabo operaciones en los números de puntos flotantes, tales como: suma, resta, multiplicación, división y raíz cuadrada. Algunos sistemas (especialmente las arquitecturas antiguas y basadas en microcódigo) también pueden realizar varias funciones trascendentales tales como cálculos exponenciales o trigonométricos. Los procesadores actuales realizan estos cálculos con rutinas de bibliotecas de software. En la mayoría de las arquitecturas de computadoras modernas para fines generales, una o más FPU están integradas con la CPU [6].
La plataforma Intel Atom tiene la FPU habilitada. En la mayoría de los casos, el usar puntos flotantes en lugar de dobles acelera el proceso de computación de datos y ahorra el ancho de banda de la memoria en los dispositivos basados en el procesador Intel Atom.
5.1.3 Codificación de multisubprocesos
El codificado de multisubprocesos le permite utilizar la función hyper-threading del procesador Intel Atom para aumentar los resultados y mejorar el rendimiento general. Para obtener más información sobre multisubprocesamiento, consulte: http://www.intel.com/content/www/es/es/architecture-and-technology/hyper-threading/hyper-threading-technology.html.
5.2 Creación de aplicaciones de alto rendimiento con marcadores de compilador
Como usted sabe, el código nativo es creado por GCC en aplicaciones para Android. Pero, ¿sabe cuál es el dispositivo de destino predeterminado de GCC? Es el procesador Pentium® Pro. El código binario de destino se ejecuta mejor en la plataforma Pentium Pro si no agrega ningún marcador durante la compilación del código nativo. La mayoría de las aplicaciones para Android se ejecutan en la plataforma Intel Atom en lugar de Pentium Pro. Se recomienda enfáticamente agregar marcadores específicos según su plataforma de destino. Puede agregar los siguientes marcadores recomendados durante la compilación en la plataforma Intel Atom:
-march=atom
-msse4
-mavx
-maes
Para obtener más información sobre los parámetros del compilador, consulte: http://gcc.gnu.org/onlinedocs/gcc/i386-and-x86-64-Options.html.
Este documento describe la manera de desarrollar y optimizar las aplicaciones para Android en las plataformas Intel Atom, así como la manera de desarrollar y migrar aplicaciones del NDK.
Un resumen de los puntos clave es:
Dawei es un ingeniero de aplicaciones dedicado a la habilitación de aplicaciones para móviles, incluyendo el desarrollo y optimización de aplicaciones Android para dispositivos x86, y el desarrollo de aplicaciones con HTML5 para la web. Además, Dawei también tiene amplia experiencia en el diseño de interfaces de usuario y experiencias de usuario de aplicaciones.