Fully native apps on Android? - android

Is it possible to develop a native application that runs without relying on the Dalvik runtime and any of the Java libraries?
Basically, I want to make a native binary I can run via a shell that would be able to run without the system_server process running. Ideally, I want to be able to create my own Window Server by rendering stuff via the OpenGL system, instead of relying on SurfaceFlinger (which would also be dead due to the fact that system_server isn't running).
The reason I'm asking this is that I want to experiment with lower level Android development in C/C++ at which Java is simply un-necessary. So basically, I'm trying to develop a standalone app that can render things via OpenGL+Cairo and receive HID input.
PS: I know what the NDK is, and it's not what I'm looking for. I want to create standalone binaries instead of creating stuff that runs inside the Dalvik VM.

There are two possibilities to run native code on your device: either using NDK or embedding your application into the framework. As I understand the first approach is not considered, thus, I think you can have a look at the second. Here is an example how to implement the second approach.
An example of porting existing code to a custom Android device
It is due time for another technical post here on the blog. This post will be about porting existing c-libraries to Android, something I did as part of the dev board demos we are doing here at Enea.
Platform addition or NDK
There are two ways of bringing native code to an Android device, either add it to the platform itself and integrate it with the framework, or include it with an application package. The latter method have evolved a lot and with the release of NDK version 5 even allows you to hook directly into the application lifecycle http://developer.android.com/reference/android/app/NativeActivity.html from the NDK. The NDK is useful for any application where you have need of native performance, have portable C libriaries you want to reuse or just some legacy native code that could be included in your application. The NDK integrates well with the Android SDK and is a great way to include native functionality in your application. It should be the preferred way for any application that needs to be reusable across a lot of Android devices.
The other option is to include your functionality, it may be native or Java, as an API extension for all applications to use. This will only work on devices that implement these extensions and it may be a suitable option for device builders. This is the variant that we aim for here.
Analyze the existing project
Porting native code to Android is not always straight forward, especially if we are talking about C++ code due to the fact that Android uses its own c-runtime with limited support for exceptions among other things. If you want to know more about the details of bionic there is an overview in the NDK docs.
The code I wanted to port for this project was the Enea LINX for Linux framework which is a fast IPC framework. My purpose was to be able to interact with control systems running our OSE real time operating system which also implements this kind of IPC. LINX consists of a couple of kernel driver modules, a user space library and some configuration and control utilities. It is written in C. I had created a small demo with LINX in Android before where I compiled it separately and used static linking but for this project I wanted a complete port to the Android build system. It did not have any issues with bionic compatability so the port should be straight forward.
I just want to add a short disclaimer about LINX. I use it here since it is a good example of integrating a solution into Android from kernel drivers up to the API levels. This particular piece of code does add additional IPC mechanisms to the systems which more or less messes up the security model so do not use it unless you are aware of the implications. The steps needed to port code to Android described in this post are however applicable for any type of driver/framework/library that you may want to include on your product.
Adding kernel driver modules
The first step was to add the kernel modules to the Android build. One way would have built a new kernel and include them directly but for this project I chose to keep them as separate modules. Building for the kernel is not handled by the Android build system meaning that we build them as we would do with any Linux system. The target is an Atmel based development board and in the LINX module build I provide the headers and cross compilation toolchain for that kernel and architecture.
Now for the Android specific parts. We need to add the compiled kernel modules to the platform build system in some way and create an Android.mk file that includes them in the system image when we build. Add a folder in the source tree where your project will go, device or external are suitable candidates. I created a folder called linx that will hold the entire linx port and in that I added a subfolder called modules where I place the prebuilt kernel modules. Now what we need is an Android makefile to copy them to the suitable place in the out folder for system image generation. This will look like:
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := linx.ko
LOCAL_MODULE_CLASS := SHARED_LIBRARY
# This will copy the file in /system/lib/modules
#
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/modules
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
The standard location for modules on the Android system image is System/lib/modules so that is where we copy them. If we build the platform now the build system will copy our precompiled module linx.ko to the system image that we use for our device. The next step is to make sure that we have the module installed on the system when we run it. This can either be done manually via the shell or via a script that we run during init.
In this case I have created a shell script to be launched from init.rc with the following content:
#linx init
insmod /lib/modules/linx.ko
insmod /lib/modules/linx_tcp_cm.ko
netcfg eth0 up
ifconfig eth0 192.168.1.12
mktcpcon --ipaddr=192.168.1.21 ControlConn
mklink --connection=tcpcm/ControlConn control_link
This includes installing the modules and configuring the network and LINX-link. We launched this from init.rc by adding:
...
#linx init script
service linx-setup /system/etc/linx_setup.sh
oneshot
...
The setup script is added to the system image in the same way by including it as a prebuilt target.
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := linx_setup.sh
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc
LOCAL_SRC_FILES := $(LOCAL_MODULE)
include $(BUILD_PREBUILT)
Creating Android make files for the user space code
Now that we have the drivers in place the next step is to look at porting the user space libraries. The default LINX build system uses standard GNU make files but we need to create new ones adapted to the Android build system. Start out by adding the source files needed to the linx directory created in the Android source tree. This gives the following structure:
Android.mk
include
liblinx
linx_basic
linxcfg
linx_setup.sh
modules
I have the linx setup script and the main Android.mk file in the top directory and then we have the source files in separate folders and the include files in the include folder. To illustrate how the Android make files for each source component is created we can use liblinx as an example. The Android.mk file looks like:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := linx.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_MODULE := liblinx
LOCAL_PRELINK_MODULE := false
include $(BUILD_SHARED_LIBRARY)
We set our sources by specifying LOCAL_SRC_FILES and the name of the library by specifying LOCAL_MODULE. We also need to supply the header files in the include directory by specifying LOCAL_C_INCLUDES. Finally this is a shared library that we are porting so use the BUILD_SHARED_LIBRARY template. This will build the library with the Android build system and add it to the system image as a shared library with the name liblinx.so.
The rest of the code is moved to the Android build system in the same way, by creating Android.mk files and specifying type and any dependencies. As another example we may look at the syntax for building the mktcpcon configuration program. This depends on the library we just created and hence the makefile looks entry looks like:
LOCAL_SRC_FILES := mktcpcon.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../include
LOCAL_STATIC_LIBRARIES += liblinxcfg
LOCAL_SHARED_LIBRARIES += liblinx
LOCAL_MODULE := mktcpcon
include $(BUILD_EXECUTABLE)
Here we use the BUILD_EXECUTABLE template and we also need to specify static and shared libraries that we link against.
Summary
I hope that provides some insight in how you setup the build for an existing linux project to run on an Android system. The steps to follow are:
Build any kernel related things using the correct kernel build system and config for your device
Add the kernel modules (and/or kernel) to the platform build system and create Android.mk files for them using the prebuilt template.
Create config and intialization services for your drivers if needed and add them to init.
Move the rest of your code (user space) to the Android source tree and create Android.mk files for them.
If you encounter build errors work them out in the source code and see what incompatabilities your code have with the specifics of the Android C-runtime.
That wraps up my post for today. Having done this we are now able to use our added drivers and API:s from native programs running in the shell. The next step is to create a JNI layer and java library to allow regular Android applications to make use of our platform additions.
I have been away for half a year on paternal leave (nice Swedish benefit) but now it is full time Android hacking again and pushing the team to publish things. Hopefully you will see more activity here including a follow up on this post discussing applications APIs.

Yes it is possible to develop native (executable binaries) that can be executable via shell but if you trying to cross compile GNU software using NDK can be pain in ass.
I will suggest you to use CodeSourcery or Linaro toolchain any way you can take a look at my approach https://github.com/DroidPHP/DroidPHP/blob/master/docs/Compiling.md

Related

How does android build system work?

I like to have a high level understanding of how the android build system work. That is when does it complement the GNU make and the Linux build system and when and how does it differ? What I mean by this is how come sometimes we use make files to add functionality to the final image, and sometimes we use Andoroid.mk? Then again sometimes we use both. Does anyone have a good grasp of how these components work together?
For example, I used just a make file to add a simple program as a module. On the other hand, looking at the /external directory some of the modules have Android.mk file and some have a make file also. Then there is the bionic directory. Can anyone elaborate please?
# arkascha- I appreciate this but I think there is a little more to it. It seems to me that GNU make has control over the Linux kernel directories and Android.mk over the Android folders; this sounds intuitive doesn't it? I was looking for a comment that would take this further and elaborate on which files need to be updated in order to add functionality. ie. looking at my build environment I have:
0628Samsung build.sh Documentation include Makefile packages sound
abi config-backup drivers init Makefile.bak pdk system
AndroidKernel.mk COPYING drivres ipc Makefile-original Platform.tar.gz tools
arch CREDITS dtbTool Kbuild mkbootimg prebuilts usr
art crypto external Kconfig mm README vendor
bin cts files kernel modules.order REPORTING-BUGS virt
bionic dalvik firmware Kernel.tar.gz ndk samples
block developers frameworks lib net scripts
bootable development fs libcore note3 sdk
build device github-repo libnativehelper out security
build_msm8974pro_kernel.sh docs hardware MAINTAINERS output
I ask this question since there does not seem to be clear understanding of the AOSP environment. For instance, this link has a section called steps for adding a new program to the Android source tree. In it they advise updating the core/main.mk file. But my environment does not really have the lines they mention. Also sometimes one does not really have a choice of using one, make file vs. android.mk, or the other. At least that has been my experience. Maybe I missed something, but what I did was to add a sample program to the external directory. I was able to compile it with the same toolchain I used to create an image and flash my phone. But the executable did not run on my phone, which led me to believe that perhaps I needed to issue other switches and set various environment variables. So I kept trying to build the image with the program included, but the build environment did not go in that directory. After looking through other directories, I realized that most of them had an Android.mk file so I added one in, and it is chugging along right now. I'll let you know how it turns out. That is why I am asking this question. Maybe I am not looking at the right place, there is no clear stable content about how to add functionality to the final image and what are the differences between what resides in each folder. There is a high level description but no discussion on here is how you add a module to this /external, /bionic, ...and here is what the end result would be.
#Dan Albert- Thanks. I am trying to map what is in the /external directory with what is on my device in an effort to get my code into the image. I am not having much luck. I followed a set of procedures to get a simple kernel module in. But I just used a simple make file as follows:
lib_src := src
lib_headers := headers
.PHONY: all $(lib_src) $(lib_headers)
$(lib_src) :
$(MAKE) --directory=$#
$(lib_*): $(MAKE) --directory=$#
obj-$(CONFIG_TOS) += examples.o
So when you say Android just uses Android.mk, I wonder. The reason being, here I just used a make file and I was able to see the resulting code in my image. Further, I'll share another example with you. Within the Android Studio projects, in order to get some native project in, you have to create a make file as well as an Android.mk. So....? There has to be more; no? Each file does have some unique functionality within the build system; don't you agree?
Please note, I am just making this argument in an effort to get my code into the finale image.
I believe I heard what is in /external directory just goes into the /system folder of the final image. But I can not validate that. Here is what is in my external directory:
aac droiddriver hyphenation libpng nist-sip sonivox
android-clat dropbear icu4c libppp noto-fonts speex
android-mock e2fsprogs iproute2 libselinux oauth sqlite
ant-glob easymock ipsec-tools libsepol objenesis srec
antlr ebtables iptables libusb okhttp srtp
apache-harmony eclipse-basebuilder iputils libusb-compat opencv stlport
apache-http eclipse-windowbuilder jack libvorbis openfst strace
apache-qp eigen javasqlite libvpx openssh stressapptest
apache-xml elfutils javassist libxml2 openssl svox
arduino embunit jdiff libxslt open-vcdiff tagsoup
bison emma jhead libyuv oprofile tcpdump
blktrace esd jmdns linux-tools-perf pixman temp
bluetooth expat jmonkeyengine littlemock ppp timezonepicker-support
bouncycastle eyes-free jpeg llvm proguard tinyalsa
brctl fdlibm jsilver lzma protobuf tinycompress
bsdiff flac jsr305 marisa-trie qemu tinyxml
bzip2 freetype junit markdown qemu-pc-bios tinyxml2
ceres-solver fsck_msdos kernel-headers mdnsresponder regex-re2 tremolo
checkpolicy ganymed-ssh2 libcap-ng mesa3d replicaisland v8
chromium gcc-demangle libffi mksh robolectric valgrind
chromium-libpac genext2fs libgsm mockito safe-iop webkit
chromium_org giflib liblzf mockwebserver scrypt webp
chromium-trace google-diff-match-patch libmtp mp4parser sepolicy webrtc
clang grub libnfc-nci mtpd sfntly wpa_supplicant_8
compiler-rt gtest libnfc-nxp naver-fonts shahin xmlwriter
dexmaker guava libnl-headers netcat sil-fonts xmp_toolkit
dhcpcd hamcrest libogg netperf skia yaffs2
dnsmasq harfbuzz libpcap neven smack zlib
doclava harfbuzz_ng libphonenumber nist-pkits smali zxing
This is basically what I have in the external/shahin directory:
sansari#ubuntu:~/WORKING_DIRECTORY/external/shahin$ more Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= hello_world.S
LOCAL_MODULE := shahin
include $(BUILD_EXECUTABLE)
sansari#ubuntu:~/WORKING_DIRECTORY/external/shahin$ more hello_world.S
.syntax unified
.global main
main:
push {ip, lr}
ldr r0, =message
bl printf
mov r0, #0 # Return 0.
pop {ip, pc}
message:
.asciz "Hello, world.\n"
A simple assembly code and an Android.mk file. But when I issue make from the root of the project I am not sure if this is added to the final image. I don't see any object file created afterwards in this directory. Am I mistaken perhaps? My question is how do I get this into the final image?
Only Android.mk is used by the Android platform build system. There are normal makefiles in the external/ directory because those projects use make when built outside Android, and we just mirror their source. Still, we only use the Android.mk to build it for Android.
Bionic is no different than the other projects in Android, it just has somewhat more complicated Android.mk structure to deal with the complexity of CPU specific sources and various issues that come along with building low level system libraries.
Android.mk is still just make. Each include $(BUILD_*) gets handled in build/core to eventually be rewritten as a normal make rule.

Much smaller .so file for identical source code

My Android application (game) uses native C++ code for certain operations. That is, I use the Android NDK. The native C++ code is compiled for armeabi only (to the default, armeabi-v5).
The last time I built my c++ code into nativestuff.so was a few months ago, in another computer (Windows 7 + cygwin, because cygwin is recommended for compiling with Android NDK).
I just installed the NDK on my current PC (Windows 7), along with the newest cygwin, and rebuilt the c++ code for my app.
To my surprise, it generates an .so file of 14KB, while the previous .so file was 37KB. Note that the c++ source files are exactly the same (they haven't changed for a year), my project is under version control, so I'm 100% sure.
I tested the c++ functionality in the game, and it works exactly as before, without any bugs.
My C++ files use only cstring.h and jni.h as includes. My Android.mk is as follows:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := nativestuff
LOCAL_SRC_FILES := nativestuff.cpp
include $(BUILD_SHARED_LIBRARY)
Any idea why the drastic change in .so filesize?
(I added the linux tag as well to this question, because maybe it's a general thing so I want to make sure that linux gurus also check it.)
Run objdump -x file.so on both versions. This will list all the sections and their sizes. That should give you a clue as to where the problem lies. (i.e. is there a new .debug section that's 23KB long? Maybe debug mode got enabled.)
If your code sections are radically different, compare the output of objdump -d file.so. Maybe your compiler automatically inlined more code, which saved a lot of space.
If another section is new/different, post the output in another SO question.
Maybe the previous .so was generated with debugging information.
(compiled with gcc -g option)
You may try one thing: use the command size executable-name. That will give you size of the different areas of your executable code. If the previous build is available do the same to that. You may get an idea where the change is.

How to build a shared library without JNI in Android?

I develop an Android application, which needs to be a shared library. I have already made the same lib in Linux (using gcc), so I want to compile the same shared lib in Android (ARM processor). But NDK only suports JNI. Now I want to build a separate shared library without direct JNI interaction. I have a lot of C files and headers, so i cannot write JNI for everything. I want build my library for ARM processors. How can i do this?
my stuture is
----->JNI
---->myfile.c(jni c code)
----->android.mk(here i call my two shared lib)
folder1
--->include
----src
---->lib(here i will get my shared lib)
folder 2
----->include
----->src
----->lib(here i will get my 2nd shared lib)
Here I want to build my shared lib separately and then I will call it. Is it possible to build a shred lib without JNI in Android?
Android NDK makes no requirements for JNI compliance of the binaries built with it. But usually Android applications are written in Java, and when they use native components, the natural path is to use JNI.
Android NDK provides a rich and easy to use ndk-build command, which requires you to prepare at least one Android.mk file that is used by their make system. In many cases it is worth the effort to prepare such file based on your makefile(s). But if the project that you port from another platform uses advanced configure or Cmake features, you can skip the Android.mk completely, and use the standalone toolchain which is part of the NDK, as described in NDK official documentation. Note that Android does not support full Linux glibc, but rather a subset called bionic. The STL support is also not obvious, you have to choose one of the 7 options!
You can stop right here, get the shared library or an executable file and use them in traditional Linux manner. You can build your Android application all in C++.
But the easiest approach is to build a Java Android application using Android SDK, and call some native methods via JDK. You will need a wrapper .so for that, a library that exports JNI functions to Java and calls the non-JNI libraries in turn. In Android.mk you can refer to these libraries with LOCAL_SHARED_LIBRARIES. You may find the following question useful for this part: ndk build library outside main project source tree.
You will need to load the native libraries "manually" in your Java code. The system loader only searches for unresolved references in /system/lib folder.
The conventional place is the static constructor of the Java class that uses the native methods. The order of loading is important. If libone.so depends on libtwo.so, and libjni.so depends on libone and on libtwo, you will have something like
{
System.Load("two");
System.Load("one");
System.Load("jni");
}
You should also make sure that the Android SDK builder finds the files in libs/armeabi or libs-armeabi-v7a directory when it creates the APK file.
It is possible to build native library without writing any JNI specific C-code. You need to create Android.mk and Application.mk files for your library. You have a valid makefile ready, so you can use it to make an Android.mk.
Application.mk can be as follows:
APP_OPTIM := release
APP_PLATFORM := android-7
APP_STL := gnustl_static
APP_CPPFLAGS += -frtti
APP_CPPFLAGS += -fexceptions
APP_CPPFLAGS += -DANDROID
APP_ABI := armeabi-v7a
APP_MODULES := <put-the-name-of-your-library-here>
Use ndk-build to compile the library.

NDK build C++ only application

I am trying to build a native daemon on Android. The purpose to to control some specific hardware, and Java applications will be able to communicate to this daemon using sockets.
I have been using cmake meanwhile to compile my libraries, demos and the real daemon (which works fine BTW). I am now trying to do 2 different things:
Build the same apps using ndk-build.
Port the C++ daemon to an Android service, by making JNI calls very similar to the way the c++ daemon works.
As far as I understand, ndk-build cannot make native applications, but only native libraries, which in turn can be loaded by the Java GUI... am I correct? For step1 I don't really need java (and I have proven it already), but I have yet found a way for ndk-build to spit an elf application.
For reference - I am using cmake, as described here: http://opekar.blogspot.com/2011/06/android-cmake-is-much-easier-in-ndk-r5b.html
This way I can have builds for "normal" linux, and also android using out of source builds. Quite nice hack if you ask me.
An alternative is to use the script make-standalone-toolchain.sh bundled with the NDK to create a stand-alone toolchain, then use it to compile your project. The shell code below illustrates how to use it:
# Assumed path to the NDK, change it to suit your environment.
NDK_HOME=$HOME/bin/android-ndk-r8e
# Desired API and NDK versions and destination folder of
# the stand-alone toolchain, change them to suit your needs.
api=14
ver=4.7
folder=$HOME/bin/android-$api-ndk-$ver
# Create folder if it doesn't already exist.
mkdir -p $folder
$NDK_HOME/build/tools/make-standalone-toolchain.sh \
--toolchain=arm-linux-androideabi-$ver \
--platform=android-$api --install-dir=$folder
Running the lines above will generate a new stand-alone toolchain at $HOME/bin/android-14-ndk-4.7, which you can then use as any regular C/C++ cross-compilation toolchain.
The advantage of working with a stand-alone toolchain is that it makes cross-compiling Linux projects to Android a breeze; see for example my port of Valgrind to Android ARMv7.
As mentioned by #Mārtiņš Možeik in one of the comments, this pice of Android.mk will work:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := my_daemon
LOCAL_C_INCLUDES := src
LOCAL_SRC_FILES := src/daemon.c
include $(BUILD_EXECUTABLE)
One thing I do notice is that the binary produced by this "makefile" is 130k, while the binary produced by cmake was ~40 kb. This is because I used -s as a C_FLAG and then gcc will strip the produced object on the fly. This can be done later on by calling $NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi-strip or the corresponding strip for your arch.
As I have not found documentation of this feature on the internet, some more words:
This works quite good, no problem here :)
This must be saved in a file called jni/Android.mk.
The code must be saved inside the JNI directory
If your code is outside of the jni directory this get ugly, but not impossible. You just need to prefix the code with the corresponding prefixes, don't forget to modify also the include path. This is left to the reader as an exercise.
Still unsure why the code generated from Android build system is larger then the code generated by cmake. I previously said that strip is not called - but it is called before the *.so are copied to the lib directory.
Still don't know how to package that binary into an android package, and not even how to run it (for example when the system is up) without modifying the Android code. I assume I can write a Java service that starts on boot and then execvps the daemon.
Your option 2 is the only way to do it AFAIK.

Debug vs. Release builds in the Android NDK

I'm working on a large game engine that must be ported to Android. All the code is C/C++, so we are porting via the NDK. I've got everything building, but after lots of scouring, I'm still uncertain what the best method is for building Debug vs. Release versions of our .so file. Changing things by hand every time is getting old.
Do you have different Application.mk files for each target? Or is there some way to include multiple targets in a single Android.mk file under the jni/ directory? Or perhaps a third option might be to write a standard makefile that sets environment variables that the Android.mk file uses to inform the build process?
Finally, one last question regarding the android:debuggable flag that must be set in the AndroidManifest.xml file. What this actually have any effect on the generated native code that's copied to the device?
Best and thanks,
Kevin
Do you have different Application.mk files for each target?
No. Separate subdirectories, all with their own Android.mk (shared and static libs) but only one Application.mk for me.
My Application.mk is just:
APP_STL := gnustl_static
APP_OPTIM := debug
I'm still uncertain what the best method is for building Debug vs. Release versions of our .so file. Changing things by hand every time is getting old.
It's a bit spread out, for me at least, using the jni/Android.mk + Application.mk layout.
Application.mk has APP_OPTIM := debug
Then in the application element of AndroidManifest.xml I have android:debuggable="true"
When you build with ndk-build, it uses this manifest flag to determine optimization (which is useful to turn off or on, off for profiling, etc.)
(A Little Off topic) I recently ran across
https://code.google.com/p/android-ndk-profiler/
Which, when combined with http://code.google.com/p/jrfonseca/wiki/Gprof2Dot
Generates some pretty images to help my little mind grasp how things are running over on the phone itself.
You're not required to use the Android.mk system to build your .so's. Personally, I use my own Makefile's with the targets I need and this allows for very standardized debug vs. release build specification.
I use a single file to build a library for diferent targets. In the Application.mk add this "APP_ABI := armeabi armeabi-v7a" it works for me.

Categories

Resources