Adding x86 target to your Android App Xavier Hallade, Technical Marketing Engineer, Intel
Oct 20, 2014
Adding x86 target to your Android App
Xavier Hallade, Technical Marketing Engineer, Intel
What we are working on for Android*
Key AOSP and Kernel Contributor
Optimized Drivers & Firmware
Highly Tuned Dalvik Runtime
Porting and Optimizing
Browser and Apps
NDK Apps Bridging Technology
64-Bit
64bit
Our devices are already fully compatible with
established Android* ecosystemAndroid* Dalvik* apps
These will directly work, Dalvik has been
optimized for Intel® platforms.
Android NDK apps
Most will run without any recompilation on consumer platforms.
Android NDK provides an x86 toolchain since 2011
A simple recompile using the Android NDK yields the best performance
If there is specific processor dependent code, porting may be necessary
Android Runtime
Core Libraries
Dalvik Virtual
Machine
Most of the time, it just works !
What’s a NDK app ?
It’s an Android* application that uses native libraries.
Native libraries are .so files, usually found inside libs/CPU_ABI/.
An application can use some calls to these native libraries, or rely almost exclusively on these.
These libs can be generated from native sources inside jni folder, game engines, or required by other 3rd party libraries.
There is no 100% native application. Even an application purely written in C/C++, using native_app_glue.h, will be executed in the context of the Dalvik Virtual Machine.
Intel® devices on the market
Smartphones with Intel Inside - 2012
Motorola* RAZR i ZTE* Grand X IN
Lava* Xolo X900 Megafon* Mint
Lenovo* K800
Orange* San Diego (UK)
Orange* avec Intel Inside (FR)
Z2460
Smartphones with Intel Inside - 2013
Intel® Yolo
Acer* Liquid C1
Z2420 Z2580Z2560
Lenovo* K900 – 5.5”
ASUS Fonepad™ Note FHD - 6”
ZTE* Grand X2 In – 4.5”
ZTE* Geek – 5”
…
Etisalat E-20*
Tablets with Intel Inside - 2013
ASUS* MeMO Pad FHD 10”
(Z2560)
ASUS* Fonepad™ 7”
(Z2420/Z2560)
Dell* Venue 7/8
(Z2560)
Samsung* Galaxy™ Tab 3 10.1”
(Z2560)
LTE version now available
Future Android* platforms based on Intel*
Silvermont microarchitecture
New 22nm tri-gate microarchitecture
~3X more peak performance or ~5X lower power than previous Atom microarchitecture
Intel® Atom™ Processor Z3000 Series
(Bay Trail) Next Generation Tablets
Merrifield
Next Generation Smartphones
How to target multiple platforms (incl. x86)
from NDK apps ?
If you have the source code of your native libraries, you can compile it for several CPU architectures by setting APP_ABI to all in the Makefile “jni/Application.mk”:
APP_ABI=all
The NDK will generate optimized code for all target ABIs
You can also pass APP_ABI variable directly to ndk-build, and specify each ABI:
ndk-build APP_ABI=x86
Configuring NDK Target ABIs
ARM v7a libs are built
ARM v5 libs are built
x86 libs are built
mips libs are built
Put APP_ABI=all inside
Application.mk
Run ndk-build…
PSI
TS
PIDs
Packaging APKs for Multiple CPU Architectures
Two options:
One package for all (“fat binary”)
Embed native libraries for each architecture in one APK
Easiest and preferred way to go
Multiple APKs
One APK per architecture
If you have good reasons to do so (i.e., your fat binary APK would be larger than 50MB)
Fat Binaries
By default, an APK contains libraries for every supported ABIs.
Use lib/armeabi libraries
Use lib/armeabi-v7a
libraries
Use lib/x86
libraries
libs/armeabi-v7a
libs/x86
libs/armeabi
APK file
…
The application will be filtered during installation (after download)
Recommended
Multiple APKs
Google Play* supports multiple APKs for the same application.
What compatible APK will be chosen for a device entirely depends on the android:VersionCode
Using this convention, the chosen APK will be the one that run best on the
device:
• If you have multiple APKs only for multiple ABIs, you can simply prefix
your current version code with a digit representing the ABI:
2310 6310
Uploading Multiple APKs to the store
Switch to Advanced mode before
uploading the second APK.
The interface almost doesn’t change.
But if you upload a new apk in
simple mode, it will overwrite the
former one.
You can get the same screen than on
the right. even if the new package
will not overwrite the previous one.
Uploading Multiple APKs to the store
Don’t forget to use different version codes for your different APKs.
Third party libraries x86 support on
Android*
3rd party libraries x86 support
Game engines/libraries with x86 support:
• Havok Anarchy SDK: android x86 target available
• Unreal Engine 3: android x86 target available
• Marmalade: android x86 target available
• Cocos2Dx: set APP_ABI in Application.mk
• FMOD: x86 lib already included, set ABIs in Application.mk
• AppGameKit: x86 lib already included, set ABIs in Application.mk
• libgdx: x86 lib now available in latest releases
• …
No x86 support but works on consumer devices:
• Corona
• Unity
3rd party libraries x86 support
3rd party projects don’t always provide pre-compiled x86 android .so
files.
You may compile/port it yourself, starting by adding x86 target to
APP_ABI in jni/Application.mk Makefile and running ndk-build.
If you run into troubles, usually it’s a matter of fixing the build
system, with the help of TARGET_ARCH_ABI var:
ifeq ($(TARGET_ARCH_ABI),x86)
…
else
…
endif
Porting processor specific code to x86 on
Android*
SIMD Instructions
NEON* instruction set on ARM* platforms
MMX™, Intel® SSE, SSE2, SSE3, SSSE3 on Intel® Atom™ processor based platforms
http://intel.ly/10JjuY4 - NEONvsSSE.h : wrap NEON functions and intrinsics to
SSE3 – 100% covered
Optimization Notice
Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and SSSE3 instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors. Certain optimizations not specific to Intel microarchitecture are reserved for Intel microprocessors. Please refer to the applicable product User and Reference Guides for more information regarding the specific instruction sets covered by this notice.
Notice revision #20110804
//******* definition sample *****************
int8x8_t vadd_s8(int8x8_t a, int8x8_t b); // VADD.I8 d0,d0,d0
#ifdef USE_MMX
#define vadd_s8 _mm_add_pi8 //MMX
#else
#define vadd_s8 _mm_add_epi8
#endif
//…
Intel® Streaming SIMD Extensions (Intel® SSE)Supplemental Streaming SIMD Extensions (SSSE)
Memory Alignment
By default
Easy fix
struct TestStruct {
int mVar1;
long long mVar2;
int mVar3;
};
struct TestStruct {
int mVar1;
long long mVar2 __attribute__ ((aligned(8)));
int mVar3;
};
Optimizing for x86 platforms
VectorizationSIMD instructions up to SSSE3 available on current Intel® Atom™ processor based platforms, Intel® SSE4.2 on the next one that uses Silvermont Microarchitecture
On ARM*, you can get vectorization through the ARM NEON* instructions
Two classic ways to use these instructions:
Compiler auto-vectorization
Compiler intrinsics
Optimization Notice
Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and SSSE3 instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors. Certain optimizations not specific to Intel microarchitecture are reserved for Intel microprocessors. Please refer to the applicable product User and Reference Guides for more information regarding the specific instruction sets covered by this notice.
Notice revision #20110804
SSSE3, SSE4.2Vector size: 128 bit
Data types:
• 8, 16, 32, 64 bit integer
• 32 and 64 bit float
VL: 2, 4, 8, 16
X2
Y2
X2◦Y2
X1
Y1
X1◦Y1
X4
Y4
X4◦Y4
X3
Y3
X3◦Y3
127 0
Intel® Streaming SIMD Extensions (Intel® SSE)
Supplemental Streaming SIMD Extensions (SSSE)
GCC Flags
ffast-math influence round-off of fp arithmetic and so breaks strict IEEE compliance
The other optimizations are totally safe
Add -ftree-vectorizer-verbose to get a vectorization report
ifeq ($(TARGET_ARCH_ABI),x86)
LOCAL_CFLAGS += -O3 -ffast-math -mtune=atom -mssse3 -mfpmath=sse
else
LOCAL_CFLAGS += ...
endif
NDK_TOOLCHAIN_VERSION=4.8
LOCAL_CFLAGS += -O3 -ffast-math -mtune=slm -msse4.2 -mfpmath=sse
To optimize for Intel Silvermont Microarchitecture (available starting with NDK r9
gcc-4.8 toolchain):
Optimization Notice
Intel's compilers may or may not optimize to the same degree for non-Intel microprocessors for optimizations that are not unique to Intel microprocessors. These optimizations include SSE2, SSE3, and SSSE3 instruction sets and other optimizations. Intel does not guarantee the availability, functionality, or effectiveness of any optimization on microprocessors not manufactured by Intel. Microprocessor-dependent optimizations in this product are intended for use with Intel microprocessors. Certain optimizations not specific to Intel microarchitecture are reserved for Intel microprocessors. Please refer to the applicable product User and Reference Guides for more information regarding the specific instruction sets covered by this notice.
Notice revision #20110804
Debugging
Debugging with logcatNDK provides log API in <android/log.h>:
Usually used through this sort of macro:
#define LOGI(...)
((void)__android_log_print(ANDROID_LOG_INFO, "APPTAG",
__VA_ARGS__))
Example:
LOGI("accelerometer: x=%f y=%f z=%f", x, y, z);
int __android_log_print(int prio, const char *tag,
const char *fmt, ...)
Debugging with logcat
To get more information on native code execution:
adb shell setprop debug.checkjni 1
(already enabled by default in the emulator)
And to get memory debug information (root only):
adb shell setprop libc.debug.malloc 1
-> leak detection
adb shell setprop libc.debug.malloc 10
-> overruns detection
adb shell start/stop -> reload environment
Debugging with GDB and EclipseNative support must be added to your project
Pass NDK_DEBUG=1 to the ndk-build command, from the project
properties:
NDK_DEBUG flag is supposed to be automatically set for a debug
build, but this is not currently the case.
Debugging with GDB and Eclipse*
When NDK_DEBUG=1 is specified, a “gdbserver” file is added to your
libraries
Debugging with GDB and Eclipse*
Debug your project as a native Android* application:
Debugging with GDB and Eclipse
From Eclipse “Debug” perspective, you can manipulate breakpoints and debug your project
Your application will run before the debugger is attached, hence breakpoints you set near application launch will be ignored
ValgrindThe Valgrind tool suite provides a number of debugging and profiling tools that help you make your
programs faster and more correct.
Memcheck : It can detect many memory-related errors that are common in C and C++ programs and
that can lead to crashes and unpredictable behavior.
Setting up Valgrind
Download latest version on Valgrind from http://valgrind.org/downloads/
./configure
Make
Sudo make install
Steps above should install valgrind.
Compile your program with -g to include debugging information so that Memcheck's error messages
include exact line numbers.
gcc myprog.c
valgrind --leak-check=yes myprog arg1 arg2 ; Memcheck is the default tool. The --leak-check option
turns on the detailed memory leak detector. You can also invoke the leak check like this
Valgrind ./a.out
Use “–o” to optimize the program while compiling. Any other option slows down Valgrind to a
significant extent.
Interpreting Valgrind error messages
Example of output message from Valgrind Memcheck
==19182== Invalid write of size 4
==19182== at 0x804838F: f (example.c:6) ==19182== by 0x80483AB: main (example.c:11)
19182 : Process ID
“Invalid write..” is the error message
6 and 11 are line numbers
Add “--gen-suppressions=yes ” to suppress errors arising out of pre compiled libs and other mem leak errors that you cannot make changes to.
Memcheck cannot detect every memory error your program has. For example, it can't detect out-of-range reads or writes to arrays that are allocated statically or on the stack. But it should detect many errors that could crash your program
Suggested reading : http://valgrind.org/docs/manual/manual.html
Valgrind Screenshot
Valgrind on Android x86Installing Valgrind
Download this package: https://my.syncplicity.com/share/7cse0vnb43auckm/valgrind-x86-android-emulator
Unzip and enter root of the unzipped package.
Install valgrind on the emulator using these commands:
adb push Inst /
adb shell chmod 777 /data/local/Inst
adb shell chmod 755 /data/local/Inst/bin/*
adb shell chmod 755 /data/local/Inst/lib/valgrind/*
Setting up a program to be run with Valgrind
adb shell setprop wrap.com.example.hellojni "logwrapper /data/local/Inst/bin/valgrind“ #Replace package name with your package name
Next startups of your app will be wrapped by valgrind and you'll see the output inside logcat.
Please note
These binaries are compatible with Intel HAXM 4.0.3 x86 emulator, not the 4.3.
You can use any OS as host
To use valgrind on a real device, you need to recompile valgrind for it (you can read the .sh file inside the zip to get the right cmd and adapt it) and you need to be root on it.
Tools for Android* apps developersHAXM, TBB, GPA, XDK and others
Most of our tools are relevant even if you’re not targeting x86 platforms!
Intel x86 Emulator
Accelerator
Intel x86 Atom
System Image
Faster Android* Emulation on Intel® Architecture
Based Host PC
Pre-built Intel® Atom™ Processor Images
Android* SDK manager has x86 emulation images
built-in
To emulate an Intel Atom processor based Android
phone, install the “Intel Atom x86 System Image”
available in the Android SDK Manager
Much Faster Emulation
Intel® Hardware Accelerated Execution Manager (Intel®
HAXM) for Mac and Windows uses Intel®
Virtualization Technology (Intel® VT) to accelerate
Android emulator
Intel VT is already supported in Linux* by qemu -kvm
ARM and x86 Emulators running AnTuTu*
Benchmark
Intel® Threading Building Blocks (TBB)
Specify tasks instead of manipulating threads
Intel® Threading Building Blocks (Intel® TBB) maps your logical tasks onto
threads with full support for nested parallelism
Targets threading for scalable performance
Uses proven efficient parallel patterns
Uses work-stealing to support the load balance of unknown execution
time for tasks
Open source and licensed versions available on Linux*, Windows*, Mac OS
X*, Android*…
Open Source version available on: threadingbuildingblocks.org
Licensed version available on: software.intel.com/en-us/intel-tbb
Intel® TBB - Example
#include <tbb/parallel_reduce.h>
#include <tbb/blocked_range.h>
double getPi() {
const int num_steps = 10000000;
const double step = 1./num_steps;
double pi = tbb::parallel_reduce(
tbb::blocked_range<int>(0, num_steps), //Range
double(0), //Value
//function
[&](const tbb::blocked_range<int>& r, double current_sum ) ->
double {
for (size_t i=r.begin(); i!=r.end(); ++i) {
double x = (i+0.5)*step;
current_sum += 4.0/(1.0 + x*x);
}
return current_sum; // updated value of the accumulator
},
[]( double s1, double s2 ) { //Reduction
return s1+s2;
}
);
return pi*step;
}
Computes reduction
over a range
Defining a one-
dimensional range
Lambda function with
range and initial value as
parm
Calculating a part of Pi
within the range r
Defining a reduction
function
Intel® Graphics Performance Analyzers
• Profiles performance and Power
• Real-time charts of CPU, GPU and power metrics
• Conduct real-time experiments with OpenGL-ES* (with state overrides) to help narrow down problems
• Triage system-level performance with CPU, GPU and Power metrics
Available freely on intel.com/software/gpa
1. Install APK, and
connect to Host
PC via adb
2. Run Intel® GPA System
Analyzer on
development machine
3. View Profile
Intel® Graphics Performance Analyzers
Preparing an Application for Analysis
Non-analyzable applications does not have the proper permissions and need
to be modified.
To analyze an application from the Non-analyzable applications list, you
need to modify the application’s permissions:
• Open the AndroidManifest.xml file of your application:
• Enable the Internet connection permission:
<uses-permission android:name="android.permission.INTERNET">
• Enable the debuggable permission:
<application android:debuggable="true">
Other tools and libs for Android*
• Intel Beacon Mountain
• Intel IPP Preview
• Intel Compiler
• Intel XDK New
• Project Anarchy