Native code in Android applications

Preview:

Citation preview

Native code in Android applications

My projects using NDK

YummLow memory overhead for image decoding

Hudriks Mathcocos2d-x; cross-platform: iOS and Android

Secure Video PlayerCritical DRM code; cross-platform code (iOS/Android/Linux/OS X/Windows);

high-performance

Overview

Android Runtime

Core Libraries (Java)

JVM (Dalvik)

LibrariesMediaSQLite OpenGLOpenSL ES

Linux Platform

/libs/armeabi/

Your Java Application

Java code

Android NDK

• Documentation

• Toolchain - ndk-build, gcc/clang, gdbserver, …

• NDK framework headers

• Build system

NDK frameworks• dl, zlib, math, log • OpenGL ES 1.x

android-4 (1.6)

• OpenGL ES 2.0

android-5 (2.0)

• JNI Graphics - java Bitmaps on low level

android-8 (2.2)

• EGL • OpenSL ES - audio library • Native Applications - native activity, etc

android-9 (2.3)

• OpenMAX

android-14 (4.0)

• OpenGL ES 3.0

android-18 (4.3)

Compilation process

compiler

source objects

.o.o.o.o.o.c/.c++ linker .so

shared library

static library

.o.o.o

.a (archive)

.so

Application structure

• jni/ (source code)

• Android.mk

• [Application.mk]

• module1/

• Android.mk

• libs/armeabi/libnative.so - compiled shared library

CPU specific

• Application Binary Interface (ABI): • armeabi - at least ARMv5TE • armeabi-v7a - Thumb-2; VFP hardware FPU; NEON • x86 • mips

• Application.mk: • APP_ABI := all • APP_ABI := armeabi armeabi-v7a

Java Native Interface

JNI in C and C++#include <jni.h>

struct JNINativeInterface { jclass (*FindClass)(JNIEnv*, const char*);}typedef const struct JNINativeInterface* JNIEnv;!JNIEnv* env;(*env)->FindClass(env, “classname”);

C

JNI in C and C++

struct _JNIEnv { jclass FindClass(const char* name) { return functions->FindClass(this, name); }}!JNIEnv* env;env->FindClass(“classname”);

C++

Mapping native functions

libnative.so- function_1()

- function_2()

- function_3()

- function_4()

- function_5()

Java.class- function_1()

- function_2()

- function_3()

- function_4()

- function_5()

Mapping native functions

public native static int testNative(int a, int b);

.java

jint Java_com_example_jnibasics_NativeDemo_testNative(JNIEnv *env, jclass obj, jint a, jint b)

.c

package name

> javah com.example.jnibasics.NativeDemo

javah

Mapping native functionsjint RegisterNatives(JNIEnv *env, jclass clazz, const JNINativeMethod *methods, jint nMethods);

typedef struct { char *name; char *signature; void *fnPtr; } JNINativeMethod;

jint addVals(JNIEnv *env, jclass obj, jint a, jint b) {…}

Mapping native functionsstatic JNINativeMethod sMethods[] = { {"testNative", "(II)I", (void*)addVals}};

jint JNI_OnLoad(JavaVM* vm, void* reserved) {

JNIEnv *env = NULL; jclass klass; if((*vm)->GetEnv(vm, (void**)&env, JNI_VERSION_1_6) != JNI_OK) return -1;! ! return JNI_VERSION_1_6;}

klass = (*env)->FindClass(env, “com/example/jnibasics/NativeDemo”);  (*env)->RegisterNatives(env, klass, gMethods, 1);

Loading .so from Java

static { System.loadLibrary("JNIBasics"); }

JNIBasics Dependency

static { System.loadLibrary("Dependency"); System.loadLibrary("JNIBasics"); }

Demo

References

jobject gObject = NULL;!void function(JNIEnv* jobject obj) { gObject = (*env)->NewGlobalRef(env, obj);}!void finish(JNIEnv* env) { (*env)->DeleteGlobalRef(env, gObject);}

Calling Java methods from native

jclass clz = (*env)->FindClass(env, “com/example/jnibasics/NativeDemo");!jmethodID method = (*env)->GetMethodID(env, clz, "methodName", “(II)Ljava/lang/String;");!jstring result = (*env)->CallObjectMethod(env, obj, method, 5, 6);

Accessing java strings

jstring jstr;const char* str;!str = (*env)->GetStringUTFChars(env, jstr, NULL);!...!(*env)->ReleaseStringUTFChars(env, jstr, str);

Further reading

• Attaching Java threads

• Creating new Java objects from native code

• Distinguish between virtual and non virtual methods

• Exception handling

• Accessing Java arrays

Using native code

Performance

• Most applications don’t need native code!

• Only for extensive calculations: games, rich media

• Take advantage of NEON CPU instructions

• Avoiding Java Garbage Collection

Cross-platform architecture

platform independent code

(no JNI)

platform dependant libraries

(network, UI, etc)

external interface (JNI/Objective-C)

Application (Java/UIKit)

Cross-platform examples

VLC

Security

1. Register as a developer (£60 per year) 2. Add device UUID to dev account 3. Generate Provisioning Profile 4. Sign APK with developer’s certificate !or Submit to Apple Store or Jailbreak device

Binary is encrypted Decryption is on OS level

Self-signed APK or not-signed at all

Decompiled Objective C: class structures assembly code

Decompiled Java: readable code

Demo

DISCLAIMER: For educational purposes only; I’m not encouraging to hack somebody else’s applications;

Summary

• Always obfuscate Java code!

• Never save passwords, use session key or hash instead

• Never keep encryption keys in clear data in memory

• Keep all critical code in native

Further protection

• Hide non-public symbols from .so files

• Strip debug information into separate files

• Expose only high-level APIs to Java

Tips

• Debugging native code is tricky

• Linux or OSX as dev platform

• Use ARM DS-5 Community Edition in Eclipse

• Android fragmentation

• separate .so files for different version

Questions?

Dmitry Matyukhin dmitry@fancygames.net

Recommended