Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/.classpath
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/.classpath	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/.classpath	(revision 4289)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="src" path="gen"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
+	<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
+	<classpathentry kind="output" path="bin/classes"/>
+</classpath>
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/.project
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/.project	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/.project	(revision 4289)
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>org.pjsip.apjloader.MainActivity</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
+			<triggers>clean,full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ResourceManagerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.PreCompilerBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>com.android.ide.eclipse.adt.ApkBuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+		<buildCommand>
+			<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
+			<triggers>full,incremental,</triggers>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>com.android.ide.eclipse.adt.AndroidNature</nature>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+		<nature>org.eclipse.cdt.core.cnature</nature>
+		<nature>org.eclipse.cdt.core.ccnature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
+		<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
+	</natures>
+</projectDescription>
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/AndroidManifest.xml
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/AndroidManifest.xml	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/AndroidManifest.xml	(revision 4289)
@@ -0,0 +1,53 @@
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+    package="org.pjsip.apjloader"
+    android:versionCode="1"
+    android:versionName="1.0" >
+
+    <uses-sdk
+        android:minSdkVersion="15"
+        android:targetSdkVersion="15" />
+    
+    <uses-permission android:name="android.permission.INTERNET" />
+    <uses-permission android:name="android.permission.RECORD_AUDIO" />
+    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
+    <uses-permission android:name="android.permission.PROCESS_OUTGOING_CALLS" />
+    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
+    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
+    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
+    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
+    <uses-permission android:name="android.permission.READ_CONTACTS" />
+    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
+    <uses-permission android:name="android.permission.CALL_PHONE" />
+    <uses-permission android:name="android.permission.WAKE_LOCK" />
+    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
+    <uses-permission android:name="android.permission.VIBRATE" />
+    <uses-permission android:name="android.permission.BLUETOOTH" />
+    <uses-permission android:name="android.permission.READ_LOGS" />
+    <uses-permission android:name="android.permission.USE_SIP" />
+    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
+    <uses-permission android:name="android.permission.CAMERA" />
+    <uses-permission android:name="android.permission.BROADCAST_STICKY" />
+    <uses-permission android:name="android.permission.READ_PROFILE" />
+ 
+    <uses-feature android:name="android.hardware.sip.voip" android:required="true" />
+    <uses-feature android:name="android.hardware.microphone" android:required="true" />
+    
+    <application
+        android:icon="@drawable/ic_launcher"
+        android:label="@string/app_name"
+        android:theme="@android:style/Theme.DeviceDefault.NoActionBar" >
+        <activity
+            android:screenOrientation="portrait"
+            android:configChanges="keyboardHidden|orientation|screenLayout"
+            android:name=".MainActivity"
+            android:label="@string/title_activity_main" >
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+    </application>
+
+</manifest>
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/jni/Android.mk
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/jni/Android.mk	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/jni/Android.mk	(revision 4289)
@@ -0,0 +1,61 @@
+# $id$
+
+LOCAL_PATH	:= $(call my-dir)
+include $(CLEAR_VARS)
+
+# Get PJ build settings
+include ../../../build.mak
+include $(PJDIR)/build/common.mak
+
+# Path to SWIG
+MY_SWIG		:= swig
+
+#========================================================================
+# Choose console application to load
+#========================================================================
+
+# pjlib test
+MY_MODULE :=  $(PJDIR)/pjlib/build/output/pjlib-test-$(TARGET_NAME)/*.o
+
+# pjlib-util test
+#MY_MODULE :=  $(PJDIR)/pjlib-util/build/output/pjlib-util-test-$(TARGET_NAME)/*.o
+
+# pjsip test
+#MY_MODULE :=  $(PJDIR)/pjsip/build/output/pjsip-test-$(TARGET_NAME)/*.o
+
+# pjnath test
+#MY_MODULE :=  $(PJDIR)/pjnath/build/output/pjnath-test-$(TARGET_NAME)/*.o
+
+# pjmedia test
+# Note: jbuf test requires Jbtest.dat, this jbuf test must be disabled (for now).
+#MY_MODULE :=  $(PJDIR)/pjmedia/build/output/pjmedia-test-$(TARGET_NAME)/*.o
+
+# pjsystest app (not supported yet)
+# Todo: this test requires some input and output files (log & WAV).
+#MY_MODULE := $(PJDIR)/pjsip-apps/build/output/pjsystest-$(TARGET_NAME)/*.o
+
+# pjsua app
+# Note: must set USE_GUI to zero in config_site.h
+#MY_MODULE := $(PJDIR)/pjsip-apps/build/output/pjsua-$(TARGET_NAME)/*.o
+
+#========================================================================
+
+# Constants
+MY_JNI_WRAP	:= apjloader_wrap.c
+MY_JNI_DIR	:= jni
+
+# Android build settings
+LOCAL_MODULE    := libapjloader
+LOCAL_CFLAGS    := -Werror $(APP_CFLAGS)
+LOCAL_LDFLAGS   := $(APP_LDFLAGS)
+LOCAL_LDLIBS    := $(MY_MODULE) $(APP_LDLIBS)
+LOCAL_SRC_FILES := $(MY_JNI_WRAP) apjloader_pipe.c
+
+# Invoke SWIG
+$(MY_JNI_DIR)/$(MY_JNI_WRAP):
+	@echo "Invoking SWIG..."
+	$(MY_SWIG) -o $(MY_JNI_DIR)/$(MY_JNI_WRAP) -package org.pjsip.apjloader -outdir src/org/pjsip/apjloader -java $(MY_JNI_DIR)/apjloader.i
+
+.PHONY: $(MY_JNI_DIR)/$(MY_JNI_WRAP)
+
+include $(BUILD_SHARED_LIBRARY)
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/jni/apjloader.i
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/jni/apjloader.i	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/jni/apjloader.i	(revision 4289)
@@ -0,0 +1,30 @@
+%module apjloader
+
+%{
+int main(int argc, char **argv);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+    int init_stdio_pipe();
+    void destroy_stdio_pipe();
+    int read_from_stdout(char *ch);
+    int write_to_stdin(const char *st);
+#ifdef __cplusplus
+}
+#endif
+
+%}
+
+%include "various.i"
+
+%apply char **STRING_ARRAY { char **argv };
+int main(int argc, char **argv);
+
+%include "typemaps.i"
+%apply signed char *INOUT { char *ch };
+
+int init_stdio_pipe();
+void destroy_stdio_pipe();
+int read_from_stdout(char *ch);
+int write_to_stdin(const char *st);
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/jni/apjloader_pipe.c
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/jni/apjloader_pipe.c	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/jni/apjloader_pipe.c	(revision 4289)
@@ -0,0 +1,93 @@
+/* $id$ */
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+#define READ    0
+#define WRITE   1
+#define STATUS  2
+
+static int stdout_pipe[3];
+static int stdin_pipe[3];
+
+void destroy_stdio_pipe();
+
+int init_stdio_pipe()
+{
+    int rc;
+
+    /* Set stdout no buffer */
+    setvbuf(stdout, NULL, _IONBF, 0);
+
+    rc = pipe(stdout_pipe);
+    if (rc != 0)
+        goto on_error;
+
+    stdout_pipe[STATUS] = 1;
+
+    rc = dup2(stdout_pipe[WRITE], 1);
+    if (rc < 0)
+        goto on_error;
+
+    rc = pipe(stdin_pipe);
+    if (rc != 0)
+        goto on_error;
+
+    stdin_pipe[STATUS] = 1;
+
+    rc = dup2(stdin_pipe[READ], 0);
+    if (rc < 0)
+        goto on_error;
+
+    return 0;
+
+on_error:
+    rc = errno;
+    destroy_stdio_pipe();
+    return rc;
+}
+
+void destroy_stdio_pipe()
+{
+    if (stdout_pipe[STATUS]) {
+        close(stdout_pipe[READ]);
+        close(stdout_pipe[WRITE]);
+    }
+    stdout_pipe[STATUS] = 0;
+
+    if (stdin_pipe[STATUS]) {
+        close(stdin_pipe[READ]);
+        close(stdin_pipe[WRITE]);
+    }
+    stdin_pipe[STATUS] = 0;
+}
+
+int read_from_stdout(char *ch)
+{
+    int rc;
+
+    rc = read(stdout_pipe[READ], ch, 1);
+    if (rc == 0) {
+        /* EOF */
+        return -1;
+    } else if (rc == -1) {
+        /* ERROR */
+        return -2;
+    }
+
+    return 0;
+}
+
+int write_to_stdin(const char *st)
+{
+    int rc;
+    char buf[100];
+    int len;
+
+    len = snprintf(buf, sizeof(buf), "%s\r\n", st);
+    rc = write(stdin_pipe[WRITE], buf, len);
+
+    return rc;
+}
+
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/lint.xml
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/lint.xml	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/lint.xml	(revision 4289)
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+</lint>
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/proguard-project.txt
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/proguard-project.txt	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/proguard-project.txt	(revision 4289)
@@ -0,0 +1,20 @@
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+#   http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+#   public *;
+#}
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/project.properties
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/project.properties	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/project.properties	(revision 4289)
@@ -0,0 +1,14 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-15
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/layout/activity_main.xml
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/layout/activity_main.xml	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/layout/activity_main.xml	(revision 4289)
@@ -0,0 +1,50 @@
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:orientation="vertical" >
+    
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content" >
+        	
+        <Button
+            android:id="@+id/send_cmd_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Send:" />
+        
+        <EditText
+            android:id="@+id/input_cmd"
+            android:layout_width="0dip"
+            android:layout_height="wrap_content"
+            android:layout_weight="1"
+            android:maxLines="1"
+            android:text="" 
+            android:hint="Type string to send">
+        </EditText>
+
+        <Button
+            android:id="@+id/quit_button"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Quit" />
+        
+    </LinearLayout>
+	
+	    <ScrollView
+		    android:id="@+id/output_scroller"
+		    android:layout_width="match_parent"
+		    android:layout_height="wrap_content"
+		    android:scrollbars="vertical"
+		    android:fillViewport="true" >
+	    
+		    <TextView
+		        android:id="@+id/output"
+		        android:layout_width="match_parent"
+		        android:layout_height="wrap_content"
+		        android:textSize="7dip"
+		        android:typeface="monospace" />
+	
+	    </ScrollView>
+
+</LinearLayout>
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values-v11/styles.xml
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values-v11/styles.xml	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values-v11/styles.xml	(revision 4289)
@@ -0,0 +1,5 @@
+<resources>
+
+    <style name="AppTheme" parent="android:Theme.Holo.Light" />
+
+</resources>
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values-v14/styles.xml
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values-v14/styles.xml	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values-v14/styles.xml	(revision 4289)
@@ -0,0 +1,5 @@
+<resources>
+
+    <style name="AppTheme" parent="android:Theme.Holo.Light.DarkActionBar" />
+
+</resources>
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values/strings.xml
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values/strings.xml	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values/strings.xml	(revision 4289)
@@ -0,0 +1,6 @@
+<resources>
+
+    <string name="app_name">Console Loader</string>
+    <string name="title_activity_main">MainActivity</string>
+
+</resources>
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values/styles.xml
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values/styles.xml	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/res/values/styles.xml	(revision 4289)
@@ -0,0 +1,5 @@
+<resources>
+
+    <style name="AppTheme" parent="android:Theme.Light" />
+
+</resources>
Index: /pjproject/branches/projects/android/pjsip-apps/src/apjloader/src/org/pjsip/apjloader/MainActivity.java
===================================================================
--- /pjproject/branches/projects/android/pjsip-apps/src/apjloader/src/org/pjsip/apjloader/MainActivity.java	(revision 4289)
+++ /pjproject/branches/projects/android/pjsip-apps/src/apjloader/src/org/pjsip/apjloader/MainActivity.java	(revision 4289)
@@ -0,0 +1,254 @@
+// $id$
+
+package org.pjsip.apjloader;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.text.method.ScrollingMovementMethod;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ScrollView;
+import android.widget.TextView;
+
+class CONST {
+	public static final String LIB_FILENAME = "apjloader";
+	public static final String TAG = "apjloader";
+	public static final String NEWLINE = "\r\n";
+	public static final Boolean AUTOKILL_ON_FINISHED = true;
+	public enum MSG_TYPE {
+		STR_INFO,
+		STR_ERROR,
+		QUIT
+	};
+}
+
+class LOG {
+	public static void INFO(Handler h, String str) {
+		Message msg = Message.obtain(h, CONST.MSG_TYPE.STR_INFO.ordinal(), str);
+		msg.sendToTarget();
+	}
+	public static void ERROR(Handler h, String str) {
+		Message msg = Message.obtain(h, CONST.MSG_TYPE.STR_ERROR.ordinal(), str);
+		msg.sendToTarget();
+	}
+}
+
+class LoaderThread extends Thread {
+	private Handler ui_handler;
+
+	public LoaderThread(Handler ui_handler_) {
+		ui_handler = ui_handler_;
+	}
+	
+	public void run() {
+		// Console application's params. Note that, the first param will be
+		// ignored (it is supposed to contain the app path).
+		// Here we just put some pjsua app params, this sample params will be
+		// ignored by PJSIP test apps such as pjlib-test, pjsystest, etc.
+		String argv[] = {"",
+						 "--clock-rate=8000",
+						 "--auto-answer=200",
+						};
+		
+		LOG.INFO(ui_handler, "Starting module.." + CONST.NEWLINE);
+		int rc = apjloader.main(argv.length, argv);
+		LOG.INFO(ui_handler, "Module finished with return code: " + 
+				 Integer.toString(rc) + CONST.NEWLINE);
+		
+		apjloader.destroy_stdio_pipe();
+
+		if (CONST.AUTOKILL_ON_FINISHED) {
+			Message msg = Message.obtain(ui_handler, CONST.MSG_TYPE.QUIT.ordinal());
+			ui_handler.sendMessageDelayed(msg, 2000);
+		}
+	}
+}
+
+class OutputThread extends Thread {
+	private Handler ui_handler;
+	
+	public OutputThread(Handler ui_handler_) {
+		ui_handler  = ui_handler_;
+	}
+	
+	public void run() {
+		final int BUFFERSIZE = 200;
+		StringBuilder sb = new StringBuilder(BUFFERSIZE);
+		
+		while (true) 
+		{
+			byte ch[] = new byte[1];
+			int rc = apjloader.read_from_stdout(ch);
+			
+			if (rc == 0) {
+				if (ch[0]=='\r' || ch[0]== '\n') {
+					if (sb.length() > 0) {
+						LOG.INFO(ui_handler, sb.toString()+CONST.NEWLINE);
+						sb.delete(0, sb.length());
+					}
+				} else {
+					sb.append((char)ch[0]);
+				}					
+			} else {
+				LOG.INFO(ui_handler, "Stdout pipe stopped, rc="+Integer.toString(rc)+CONST.NEWLINE);
+				break;
+			}
+		}
+	}
+}
+
+
+public class MainActivity extends Activity {
+	private TextView log_view;
+	private ScrollView log_scroll_view;
+	EditText input_cmd;
+
+	/** Called when the activity is first created. */
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+    	setContentView(R.layout.activity_main);
+
+        init_view();
+        
+        print_log("Loading module.." + CONST.NEWLINE);
+        int rc = init_lib();
+        if (rc != 0)
+        	print_log("Failed loading module: " + Integer.toString(rc) + CONST.NEWLINE);
+	}
+
+    private View.OnClickListener on_send_cmd_click = new View.OnClickListener() {
+    	public void onClick(View v) {
+        	String cmd = input_cmd.getText().toString().trim();
+        	input_cmd.setText("");
+    		send_cmd(cmd);
+    	}
+    };
+    
+    private View.OnClickListener on_quit_click = new View.OnClickListener() {
+    	public void onClick(View v) {
+    		/* Send quit command, only for pjsua-app */
+    		send_cmd("q");
+    		
+    		print_log("Quitting..");
+    		Message msg = Message.obtain(ui_handler, CONST.MSG_TYPE.QUIT.ordinal());
+    		ui_handler.sendMessageDelayed(msg, 2000);
+    	}
+    };
+    
+    private View.OnKeyListener on_input_cmd_key = new View.OnKeyListener() {
+		
+		public boolean onKey(View v, int keyCode, KeyEvent event) {
+			if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
+    			(keyCode == KeyEvent.KEYCODE_ENTER))
+    		{
+	        	String cmd = input_cmd.getText().toString().trim();
+	        	input_cmd.setText("");
+				send_cmd(cmd);
+    			return true;
+    		}
+    		return false;
+		}
+	};
+	
+    private void print_log(String st) {
+    	log_view.append(st);
+    	//Log.i(CONST.TAG, st);
+
+    	log_view.post(new Runnable() {
+            public void run() {
+            	log_scroll_view.fullScroll(View.FOCUS_DOWN);
+            }
+        });   	
+    }
+    
+    private Handler ui_handler = new Handler() {
+		@Override
+		public void handleMessage(Message m) {
+			if (m.what == CONST.MSG_TYPE.STR_INFO.ordinal() ||
+				m.what == CONST.MSG_TYPE.STR_ERROR.ordinal())
+			{
+				print_log((String)m.obj);
+			} else if (m.what == CONST.MSG_TYPE.QUIT.ordinal()) {
+				finish();
+				System.gc();
+				android.os.Process.killProcess(android.os.Process.myPid());
+			}
+		}
+    };
+
+    private void hide_soft_keyboard() {
+        InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
+        imm.hideSoftInputFromWindow(input_cmd.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
+    }
+    
+	private void init_view() {
+        Button send_cmd_button = (Button)findViewById(R.id.send_cmd_button);
+        send_cmd_button.setOnClickListener(on_send_cmd_click);
+
+        Button quit_button = (Button)findViewById(R.id.quit_button);
+        quit_button.setOnClickListener(on_quit_click);
+
+        input_cmd = (EditText)findViewById(R.id.input_cmd);
+        input_cmd.setOnKeyListener(on_input_cmd_key);
+        
+        log_view = (TextView)findViewById(R.id.output);
+        log_view.setMovementMethod(new ScrollingMovementMethod());
+        log_view.setText("");
+        
+        log_scroll_view = (ScrollView)findViewById(R.id.output_scroller);
+	}
+	
+	private int init_stdio_pipes() {
+		int rc = apjloader.init_stdio_pipe();
+		if (rc != 0)
+			return rc;
+		
+		return 0;
+	}
+	
+	private int init_lib() {
+		try {
+			System.loadLibrary(CONST.LIB_FILENAME);
+		} catch (UnsatisfiedLinkError e) {
+			print_log("UnsatisfiedLinkError: " + e.getMessage() + CONST.NEWLINE);
+			return -1;
+		}
+		
+		// Wait for GDB to init
+		if ((getApplicationInfo().flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
+			try {
+				Thread.sleep(5000);
+	        } catch (InterruptedException e) {
+				print_log("InterruptedException: " + e.getMessage() + CONST.NEWLINE);
+	        }
+		}
+		
+        int rc = init_stdio_pipes();
+        print_log("Stdio pipes inited: " + Integer.toString(rc) + CONST.NEWLINE);
+        
+    	OutputThread ot = new OutputThread(ui_handler);
+		ot.start();
+		
+        LoaderThread lt = new LoaderThread(ui_handler);
+        lt.start();
+        
+		return 0;
+	}
+	
+    private void send_cmd(String cmd) {
+		hide_soft_keyboard();
+    	if (cmd == "")
+    		return;
+    	
+		print_log("Sending command: " + cmd + CONST.NEWLINE);
+		apjloader.write_to_stdin(cmd);
+    }
+}
