diff --git a/src/frontends/android/AndroidManifest.xml b/src/frontends/android/AndroidManifest.xml
index 702a15d21..63464e712 100644
--- a/src/frontends/android/AndroidManifest.xml
+++ b/src/frontends/android/AndroidManifest.xml
@@ -5,6 +5,7 @@
android:versionName="1.0" >
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/frontends/android/jni/Android.mk b/src/frontends/android/jni/Android.mk
index 74c6c6a42..e5659a4df 100644
--- a/src/frontends/android/jni/Android.mk
+++ b/src/frontends/android/jni/Android.mk
@@ -56,6 +56,7 @@ strongswan_CFLAGS += \
include $(addprefix $(LOCAL_PATH)/,$(addsuffix /Android.mk, \
vstr \
openssl \
+ libandroidbridge \
strongswan/src/libcharon \
strongswan/src/libhydra \
strongswan/src/libstrongswan \
diff --git a/src/frontends/android/jni/libandroidbridge/Android.mk b/src/frontends/android/jni/libandroidbridge/Android.mk
new file mode 100644
index 000000000..7f25a540a
--- /dev/null
+++ b/src/frontends/android/jni/libandroidbridge/Android.mk
@@ -0,0 +1,33 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+# copy-n-paste from Makefile.am
+LOCAL_SRC_FILES := \
+charonservice.c
+
+# build libandroidbridge -------------------------------------------------------
+
+LOCAL_C_INCLUDES += \
+ $(libvstr_PATH) \
+ $(strongswan_PATH)/src/libhydra \
+ $(strongswan_PATH)/src/libcharon \
+ $(strongswan_PATH)/src/libstrongswan
+
+LOCAL_CFLAGS := $(strongswan_CFLAGS) \
+ -DPLUGINS='"$(strongswan_CHARON_PLUGINS)"'
+
+LOCAL_MODULE := libandroidbridge
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_ARM_MODE := arm
+
+LOCAL_PRELINK_MODULE := false
+
+LOCAL_LDLIBS := -llog
+
+LOCAL_SHARED_LIBRARIES := libstrongswan libhydra libcharon
+
+include $(BUILD_SHARED_LIBRARY)
+
+
diff --git a/src/frontends/android/jni/libandroidbridge/charonservice.c b/src/frontends/android/jni/libandroidbridge/charonservice.c
new file mode 100644
index 000000000..ecc243481
--- /dev/null
+++ b/src/frontends/android/jni/libandroidbridge/charonservice.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2012 Tobias Brunner
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See .
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+#define JNI_PACKAGE org_strongswan_android
+
+#define JNI_METHOD_PP(pack, klass, name, ret, ...) \
+ ret Java_##pack##_##klass##_##name(JNIEnv *env, jobject this, ##__VA_ARGS__)
+
+#define JNI_METHOD_P(pack, klass, name, ret, ...) \
+ JNI_METHOD_PP(pack, klass, name, ret, ##__VA_ARGS__)
+
+#define JNI_METHOD(klass, name, ret, ...) \
+ JNI_METHOD_P(JNI_PACKAGE, klass, name, ret, ##__VA_ARGS__)
+
+/**
+ * hook in library for debugging messages
+ */
+extern void (*dbg) (debug_t group, level_t level, char *fmt, ...);
+
+/**
+ * Logging hook for library logs, using android specific logging
+ */
+static void dbg_android(debug_t group, level_t level, char *fmt, ...)
+{
+ va_list args;
+
+ if (level <= 4)
+ {
+ char sgroup[16], buffer[8192];
+ char *current = buffer, *next;
+ snprintf(sgroup, sizeof(sgroup), "%N", debug_names, group);
+ va_start(args, fmt);
+ vsnprintf(buffer, sizeof(buffer), fmt, args);
+ va_end(args);
+ while (current)
+ { /* log each line separately */
+ next = strchr(current, '\n');
+ if (next)
+ {
+ *(next++) = '\0';
+ }
+ __android_log_print(ANDROID_LOG_INFO, "charon", "00[%s] %s\n",
+ sgroup, current);
+ current = next;
+ }
+ }
+}
+
+/**
+ * Initialize charon and the libraries via JNI
+ */
+JNI_METHOD(CharonVpnService, initializeCharon, void)
+{
+ /* logging for library during initialization, as we have no bus yet */
+ dbg = dbg_android;
+
+ /* initialize library */
+ if (!library_init(NULL))
+ {
+ library_deinit();
+ return;
+ }
+
+ if (!libhydra_init("charon"))
+ {
+ libhydra_deinit();
+ library_deinit();
+ return;
+ }
+
+ if (!libcharon_init("charon") ||
+ !charon->initialize(charon, PLUGINS))
+ {
+ libcharon_deinit();
+ libhydra_deinit();
+ library_deinit();
+ return;
+ }
+
+ /* start daemon (i.e. the threads in the thread-pool) */
+ charon->start(charon);
+}
+
+/**
+ * Initialize charon and the libraries via JNI
+ */
+JNI_METHOD(CharonVpnService, deinitializeCharon, void)
+{
+ libcharon_deinit();
+ libhydra_deinit();
+ library_deinit();
+}
+
diff --git a/src/frontends/android/src/org/strongswan/android/CharonVpnService.java b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java
new file mode 100644
index 000000000..596372f9d
--- /dev/null
+++ b/src/frontends/android/src/org/strongswan/android/CharonVpnService.java
@@ -0,0 +1,50 @@
+package org.strongswan.android;
+
+import android.content.Intent;
+import android.net.VpnService;
+
+public class CharonVpnService extends VpnService {
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ // called whenever the service is started with startService
+ // create our own thread because we are running in the calling processes main thread
+ return super.onStartCommand(intent, flags, startId);
+ }
+
+ @Override
+ public void onCreate() {
+ // onCreate is only called once
+ initializeCharon();
+ super.onCreate();
+ }
+
+ @Override
+ public void onDestroy() {
+ // called once the service is to be destroyed
+ deinitializeCharon();
+ super.onDestroy();
+ }
+
+ /**
+ * Initialization of charon, provided by libandroidbridge.so
+ */
+ public native void initializeCharon();
+
+ /**
+ * Deinitialize charon, provided by libandroidbridge.so
+ */
+ public native void deinitializeCharon();
+
+ /*
+ * The libraries are extracted to /data/data/org.strongswan.android/...
+ * during installation.
+ */
+ static {
+ System.loadLibrary("crypto");
+ System.loadLibrary("strongswan");
+ System.loadLibrary("hydra");
+ System.loadLibrary("charon");
+ System.loadLibrary("androidbridge");
+ }
+}
diff --git a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java
index 16d4a0973..b4fb6f398 100644
--- a/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java
+++ b/src/frontends/android/src/org/strongswan/android/strongSwanActivity.java
@@ -1,13 +1,32 @@
package org.strongswan.android;
import android.app.Activity;
+import android.content.Intent;
+import android.net.VpnService;
import android.os.Bundle;
public class strongSwanActivity extends Activity {
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- }
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.main);
+ startVpnService();
+ }
+
+ private void startVpnService() {
+ Intent intent = VpnService.prepare(this);
+ if (intent != null) {
+ startActivityForResult(intent, 0);
+ } else {
+ onActivityResult(0, RESULT_OK, null);
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode == RESULT_OK) {
+ Intent intent = new Intent(this, CharonVpnService.class);
+ startService(intent);
+ }
+ }
}
\ No newline at end of file