ART: Native bridge command-line parameter

Add a command-line parameter for the native bridge library, slight
refactor/cleanup.

Add run-test 115 to test the native bridge interface. Currently the
tests are black-listed for the target, as the setup for the test
is too complicated in the current infrastructure.

Change-Id: I6ccf19485e8c30b96e9f2fd5425278cb1ebd403f
diff --git a/test/115-native-bridge/expected.txt b/test/115-native-bridge/expected.txt
new file mode 100644
index 0000000..f852620
--- /dev/null
+++ b/test/115-native-bridge/expected.txt
@@ -0,0 +1,13 @@
+Ready for native bridge tests.
+Native bridge initialized.
+Checking for support.
+Getting trampoline.
+Getting trampoline.
+Getting trampoline.
+Getting trampoline.
+Getting trampoline.
+Getting trampoline.
+Getting trampoline.
+Getting trampoline.
+Getting trampoline.
+Getting trampoline.
diff --git a/test/115-native-bridge/info.txt b/test/115-native-bridge/info.txt
new file mode 100644
index 0000000..ccac7ae
--- /dev/null
+++ b/test/115-native-bridge/info.txt
@@ -0,0 +1 @@
+Test for the native bridge interface.
diff --git a/test/115-native-bridge/nativebridge.cc b/test/115-native-bridge/nativebridge.cc
new file mode 100644
index 0000000..bd3ae13
--- /dev/null
+++ b/test/115-native-bridge/nativebridge.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// A simple implementation of the native-bridge interface.
+
+#include <algorithm>
+#include <dlfcn.h>
+#include <vector>
+
+#include "jni.h"
+#include "stdio.h"
+#include "string.h"
+#include "unistd.h"
+
+#include "native_bridge.h"
+
+
+// Native bridge interfaces...
+
+struct NativeBridgeArtCallbacks {
+  const char* (*getMethodShorty)(JNIEnv* env, jmethodID mid);
+  int (*getNativeMethodCount)(JNIEnv* env, jclass clazz);
+  int (*getNativeMethods)(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
+       uint32_t method_count);
+};
+
+struct NativeBridgeCallbacks {
+  bool (*initialize)(NativeBridgeArtCallbacks* art_cbs);
+  void* (*loadLibrary)(const char* libpath, int flag);
+  void* (*getTrampoline)(void* handle, const char* name, const char* shorty, uint32_t len);
+  bool (*isSupported)(const char* libpath);
+};
+
+
+
+static std::vector<void*> symbols;
+
+// NativeBridgeCallbacks implementations
+extern "C" bool native_bridge_initialize(NativeBridgeArtCallbacks* art_cbs) {
+  printf("Native bridge initialized.\n");
+  return true;
+}
+
+extern "C" void* native_bridge_loadLibrary(const char* libpath, int flag) {
+  size_t len = strlen(libpath);
+  char* tmp = new char[len + 10];
+  strncpy(tmp, libpath, len);
+  tmp[len - 3] = '2';
+  tmp[len - 2] = '.';
+  tmp[len - 1] = 's';
+  tmp[len] = 'o';
+  tmp[len + 1] = 0;
+  void* handle = dlopen(tmp, flag);
+  delete[] tmp;
+
+  if (handle == nullptr) {
+    printf("Handle = nullptr!\n");
+    printf("Was looking for %s.\n", libpath);
+    printf("Error = %s.\n", dlerror());
+    char cwd[1024];
+    if (getcwd(cwd, sizeof(cwd)) != nullptr) {
+      printf("Current working dir: %s\n", cwd);
+    }
+  }
+  return handle;
+}
+
+extern "C" void* native_bridge_getTrampoline(void* handle, const char* name, const char* shorty,
+                                             uint32_t len) {
+  printf("Getting trampoline.\n");
+
+  // The name here is actually the JNI name, so we can directly do the lookup.
+  void* sym = dlsym(handle, name);
+  if (sym != nullptr) {
+    symbols.push_back(sym);
+  }
+
+  // As libarttest is the same arch as the host, we can actually directly use the code and do not
+  // need to create a trampoline. :-)
+  return sym;
+}
+
+extern "C" bool native_bridge_isSupported(const char* libpath) {
+  printf("Checking for support.\n");
+
+  if (libpath == nullptr) {
+    return false;
+  }
+  // We don't want to hijack javacore. So we should get libarttest...
+  return strcmp(libpath, "libjavacore.so") != 0;
+}
+
+NativeBridgeCallbacks NativeBridgeItf {
+  .initialize = &native_bridge_initialize,
+  .loadLibrary = &native_bridge_loadLibrary,
+  .getTrampoline = &native_bridge_getTrampoline,
+  .isSupported = &native_bridge_isSupported
+};
+
+
+
diff --git a/test/115-native-bridge/run b/test/115-native-bridge/run
new file mode 100644
index 0000000..e475cd6
--- /dev/null
+++ b/test/115-native-bridge/run
@@ -0,0 +1,29 @@
+#!/bin/sh
+#
+# Copyright (C) 2012 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+ARGS=${@}
+
+# Use libnativebridgetest as a native bridge, start NativeBridgeMain (Main is JniTest main file).
+LIBPATH=$(echo ${ARGS} | sed -r 's/.*Djava.library.path=([^ ]*) .*/\1/')
+cp ${LIBPATH}/libnativebridgetest.so .
+touch libarttest.so
+cp ${LIBPATH}/libarttest.so libarttest2.so
+
+# pwd likely has /, so it's a pain to put that into a sed rule.
+LEFT=$(echo ${ARGS} | sed -r 's/-Djava.library.path.*//')
+RIGHT=$(echo ${ARGS} | sed -r 's/.*Djava.library.path[^ ]* //')
+MODARGS="${LEFT} -Djava.library.path=`pwd` ${RIGHT}"
+exec ${RUN} --runtime-option -XX:NativeBridge=libnativebridgetest.so ${MODARGS} NativeBridgeMain
diff --git a/test/115-native-bridge/src/NativeBridgeMain.java b/test/115-native-bridge/src/NativeBridgeMain.java
new file mode 100644
index 0000000..a531f92
--- /dev/null
+++ b/test/115-native-bridge/src/NativeBridgeMain.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.reflect.Method;
+
+// This is named Main as it is a copy of JniTest, so that we can re-use the native implementations
+// from libarttest.
+class Main {
+    public static void main(String[] args) {
+        testFindClassOnAttachedNativeThread();
+        testFindFieldOnAttachedNativeThread();
+        testCallStaticVoidMethodOnSubClass();
+        testGetMirandaMethod();
+        testZeroLengthByteBuffers();
+        testByteMethod();
+        testShortMethod();
+        testBooleanMethod();
+        testCharMethod();
+    }
+
+    public static native void testFindClassOnAttachedNativeThread();
+
+    public static boolean testFindFieldOnAttachedNativeThreadField;
+
+    public static void testFindFieldOnAttachedNativeThread() {
+      testFindFieldOnAttachedNativeThreadNative();
+      if (!testFindFieldOnAttachedNativeThreadField) {
+            throw new AssertionError();
+        }
+    }
+
+    private static native void testFindFieldOnAttachedNativeThreadNative();
+
+    private static void testCallStaticVoidMethodOnSubClass() {
+        testCallStaticVoidMethodOnSubClassNative();
+        if (!testCallStaticVoidMethodOnSubClass_SuperClass.executed) {
+            throw new AssertionError();
+        }
+    }
+
+    private static native void testCallStaticVoidMethodOnSubClassNative();
+
+    private static class testCallStaticVoidMethodOnSubClass_SuperClass {
+        private static boolean executed = false;
+        private static void execute() {
+            executed = true;
+        }
+    }
+
+    private static class testCallStaticVoidMethodOnSubClass_SubClass
+        extends testCallStaticVoidMethodOnSubClass_SuperClass {
+    }
+
+    private static native Method testGetMirandaMethodNative();
+
+    private static void testGetMirandaMethod() {
+        Method m = testGetMirandaMethodNative();
+        if (m.getDeclaringClass() != testGetMirandaMethod_MirandaInterface.class) {
+            throw new AssertionError();
+        }
+    }
+
+    private static native void testZeroLengthByteBuffers();
+
+    private static abstract class testGetMirandaMethod_MirandaAbstract implements testGetMirandaMethod_MirandaInterface {
+        public boolean inAbstract() {
+            return true;
+        }
+    }
+
+    private static interface testGetMirandaMethod_MirandaInterface {
+        public boolean inInterface();
+    }
+
+    // Test sign-extension for values < 32b
+
+    native static byte byteMethod(byte b1, byte b2, byte b3, byte b4, byte b5, byte b6, byte b7,
+        byte b8, byte b9, byte b10);
+
+    public static void testByteMethod() {
+      byte returns[] = { 0, 1, 2, 127, -1, -2, -128 };
+      for (int i = 0; i < returns.length; i++) {
+        byte result = byteMethod((byte)i, (byte)2, (byte)(-3), (byte)4, (byte)(-5), (byte)6,
+            (byte)(-7), (byte)8, (byte)(-9), (byte)10);
+        if (returns[i] != result) {
+          System.out.println("Run " + i + " with " + returns[i] + " vs " + result);
+          throw new AssertionError();
+        }
+      }
+    }
+
+    native static short shortMethod(short s1, short s2, short s3, short s4, short s5, short s6, short s7,
+        short s8, short s9, short s10);
+
+    private static void testShortMethod() {
+      short returns[] = { 0, 1, 2, 127, 32767, -1, -2, -128, -32768 };
+      for (int i = 0; i < returns.length; i++) {
+        short result = shortMethod((short)i, (short)2, (short)(-3), (short)4, (short)(-5), (short)6,
+            (short)(-7), (short)8, (short)(-9), (short)10);
+        if (returns[i] != result) {
+          System.out.println("Run " + i + " with " + returns[i] + " vs " + result);
+          throw new AssertionError();
+        }
+      }
+    }
+
+    // Test zero-extension for values < 32b
+
+    native static boolean booleanMethod(boolean b1, boolean b2, boolean b3, boolean b4, boolean b5, boolean b6, boolean b7,
+        boolean b8, boolean b9, boolean b10);
+
+    public static void testBooleanMethod() {
+      if (booleanMethod(false, true, false, true, false, true, false, true, false, true)) {
+        throw new AssertionError();
+      }
+
+      if (!booleanMethod(true, true, false, true, false, true, false, true, false, true)) {
+        throw new AssertionError();
+      }
+    }
+
+    native static char charMethod(char c1, char c2, char c3, char c4, char c5, char c6, char c7,
+        char c8, char c9, char c10);
+
+    private static void testCharMethod() {
+      char returns[] = { (char)0, (char)1, (char)2, (char)127, (char)255, (char)256, (char)15000,
+          (char)34000 };
+      for (int i = 0; i < returns.length; i++) {
+        char result = charMethod((char)i, 'a', 'b', 'c', '0', '1', '2', (char)1234, (char)2345,
+            (char)3456);
+        if (returns[i] != result) {
+          System.out.println("Run " + i + " with " + (int)returns[i] + " vs " + (int)result);
+          throw new AssertionError();
+        }
+      }
+    }
+}
+
+public class NativeBridgeMain {
+    static public void main(String[] args) throws Exception {
+        System.out.println("Ready for native bridge tests.");
+
+        System.loadLibrary("arttest");
+
+        Main.main(null);
+    }
+}
diff --git a/test/Android.libnativebridgetest.mk b/test/Android.libnativebridgetest.mk
new file mode 100644
index 0000000..dd7255a
--- /dev/null
+++ b/test/Android.libnativebridgetest.mk
@@ -0,0 +1,87 @@
+#
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+
+include art/build/Android.common_build.mk
+
+LIBNATIVEBRIDGETEST_COMMON_SRC_FILES := \
+  115-native-bridge/nativebridge.cc
+
+ART_TARGET_LIBNATIVEBRIDGETEST_$(ART_PHONY_TEST_TARGET_SUFFIX) += $(ART_TARGET_TEST_OUT)/$(TARGET_ARCH)/libnativebridgetest.so
+ifdef TARGET_2ND_ARCH
+  ART_TARGET_LIBNATIVEBRIDGETEST_$(2ND_ART_PHONY_TEST_TARGET_SUFFIX) += $(ART_TARGET_TEST_OUT)/$(TARGET_2ND_ARCH)/libnativebridgetest.so
+endif
+
+# $(1): target or host
+define build-libnativebridgetest
+  ifneq ($(1),target)
+    ifneq ($(1),host)
+      $$(error expected target or host for argument 1, received $(1))
+    endif
+  endif
+
+  art_target_or_host := $(1)
+
+  include $(CLEAR_VARS)
+  LOCAL_CPP_EXTENSION := $(ART_CPP_EXTENSION)
+  LOCAL_MODULE := libnativebridgetest
+  ifeq ($$(art_target_or_host),target)
+    LOCAL_MODULE_TAGS := tests
+  endif
+  LOCAL_SRC_FILES := $(LIBNATIVEBRIDGETEST_COMMON_SRC_FILES)
+  LOCAL_SHARED_LIBRARIES += libartd
+  LOCAL_C_INCLUDES += $(ART_C_INCLUDES) art/runtime
+  LOCAL_ADDITIONAL_DEPENDENCIES := art/build/Android.common_build.mk
+  LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.libnativebridgetest.mk
+  include external/libcxx/libcxx.mk
+  ifeq ($$(art_target_or_host),target)
+    $(call set-target-local-clang-vars)
+    $(call set-target-local-cflags-vars,debug)
+    LOCAL_SHARED_LIBRARIES += libdl libcutils
+    LOCAL_STATIC_LIBRARIES := libgtest
+    LOCAL_MULTILIB := both
+    LOCAL_MODULE_PATH_32 := $(ART_TARGET_TEST_OUT)/$(ART_TARGET_ARCH_32)
+    LOCAL_MODULE_PATH_64 := $(ART_TARGET_TEST_OUT)/$(ART_TARGET_ARCH_64)
+    LOCAL_MODULE_TARGET_ARCH := $(ART_SUPPORTED_ARCH)
+    include $(BUILD_SHARED_LIBRARY)
+  else # host
+    LOCAL_CLANG := $(ART_HOST_CLANG)
+    LOCAL_CFLAGS := $(ART_HOST_CFLAGS) $(ART_HOST_DEBUG_CFLAGS)
+    LOCAL_STATIC_LIBRARIES := libcutils
+    LOCAL_LDLIBS += -ldl -lpthread
+    ifeq ($(HOST_OS),linux)
+      LOCAL_LDLIBS += -lrt
+    endif
+    LOCAL_IS_HOST_MODULE := true
+    LOCAL_MULTILIB := both
+    include $(BUILD_HOST_SHARED_LIBRARY)
+  endif
+
+  # Clear locally used variables.
+  art_target_or_host :=
+endef
+
+ifeq ($(ART_BUILD_TARGET),true)
+  $(eval $(call build-libnativebridgetest,target))
+endif
+ifeq ($(ART_BUILD_HOST),true)
+  $(eval $(call build-libnativebridgetest,host))
+endif
+
+# Clear locally used variables.
+LOCAL_PATH :=
+LIBNATIVEBRIDGETEST_COMMON_SRC_FILES :=
diff --git a/test/Android.run-test.mk b/test/Android.run-test.mk
index 78493dc..6fa5df1 100644
--- a/test/Android.run-test.mk
+++ b/test/Android.run-test.mk
@@ -40,6 +40,16 @@
   test-art-target-run-test$(2)-interpreter$(3)-$(1)64
 endef  # all-run-test-names
 
+# Subset of the above for target only.
+define all-run-test-target-names
+  test-art-target-run-test$(2)-default$(3)-$(1)32 \
+  test-art-target-run-test$(2)-optimizing$(3)-$(1)32 \
+  test-art-target-run-test$(2)-interpreter$(3)-$(1)32 \
+  test-art-target-run-test$(2)-default$(3)-$(1)64 \
+  test-art-target-run-test$(2)-optimizing$(3)-$(1)64 \
+  test-art-target-run-test$(2)-interpreter$(3)-$(1)64
+endef  # all-run-test-target-names
+
 # Tests that are timing sensitive and flaky on heavily loaded systems.
 TEST_ART_TIMING_SENSITIVE_RUN_TESTS := \
   053-wait-some \
@@ -120,6 +130,27 @@
 ART_TEST_KNOWN_BROKEN += $(foreach test, $(TEST_ART_BROKEN_GCSTRESS_RUN_TESTS), $(call all-run-test-names,$(test),-gcstress,-norelocate))
 ART_TEST_KNOWN_BROKEN += $(foreach test, $(TEST_ART_BROKEN_GCSTRESS_RUN_TESTS), $(call all-run-test-names,$(test),-gcstress,))
 
+# 115-native-bridge setup is complicated. Need to implement it correctly for the target.
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,,)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-trace,)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcverify,)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcstress,)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,,-relocate)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-trace,-relocate)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcverify,-relocate)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcstress,-relocate)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,,-norelocate)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-trace,-norelocate)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcverify,-norelocate)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcstress,-norelocate)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,,-prebuild)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-trace,-prebuild)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcverify,-prebuild)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcstress,-prebuild)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,,-no-prebuild)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-trace,-no-prebuild)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcverify,-no-prebuild)
+ART_TEST_KNOWN_BROKEN += $(call all-run-test-target-names,115-native-bridge,-gcstress,-no-prebuild)
 
 # The path where build only targets will be output, e.g.
 # out/target/product/generic_x86_64/obj/PACKAGING/art-run-tests_intermediates/DATA
@@ -290,16 +321,24 @@
 TEST_ART_TARGET_SYNC_DEPS += $(ART_TARGET_TEST_OUT)/$(TARGET_2ND_ARCH)/libarttest.so
 endif
 
+# Also need libnativebridgetest.
+TEST_ART_TARGET_SYNC_DEPS += $(ART_TARGET_TEST_OUT)/$(TARGET_ARCH)/libnativebridgetest.so
+ifdef TARGET_2ND_ARCH
+TEST_ART_TARGET_SYNC_DEPS += $(ART_TARGET_TEST_OUT)/$(TARGET_2ND_ARCH)/libnativebridgetest.so
+endif
+
 # All tests require the host executables and the core images.
 ART_TEST_HOST_RUN_TEST_DEPENDENCIES := \
   $(ART_HOST_EXECUTABLES) \
   $(ART_HOST_OUT_SHARED_LIBRARIES)/libarttest$(ART_HOST_SHLIB_EXTENSION) \
+  $(ART_HOST_OUT_SHARED_LIBRARIES)/libnativebridgetest$(ART_HOST_SHLIB_EXTENSION) \
   $(ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$(ART_HOST_SHLIB_EXTENSION) \
   $(HOST_CORE_IMG_OUT)
 
 ifneq ($(HOST_PREFER_32_BIT),true)
 ART_TEST_HOST_RUN_TEST_DEPENDENCIES += \
   $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libarttest$(ART_HOST_SHLIB_EXTENSION) \
+  $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libnativebridgetest$(ART_HOST_SHLIB_EXTENSION) \
   $(2ND_ART_HOST_OUT_SHARED_LIBRARIES)/libjavacore$(ART_HOST_SHLIB_EXTENSION) \
   $(2ND_HOST_CORE_IMG_OUT)
 endif
@@ -831,6 +870,9 @@
 # include libarttest build rules.
 include $(LOCAL_PATH)/Android.libarttest.mk
 
+# Include libnativebridgetest build rules.
+include art/test/Android.libnativebridgetest.mk
+
 define-test-art-run-test :=
 define-test-art-run-test-group-rule :=
 define-test-art-run-test-group :=
diff --git a/test/etc/host-run-test-jar b/test/etc/host-run-test-jar
index d72e997..2241f85 100755
--- a/test/etc/host-run-test-jar
+++ b/test/etc/host-run-test-jar
@@ -24,6 +24,7 @@
 COMPILER_FLAGS=""
 BUILD_BOOT_OPT=""
 exe="${ANDROID_HOST_OUT}/bin/dalvikvm32"
+main="Main"
 
 while true; do
     if [ "x$1" = "x--quiet" ]; then
@@ -112,6 +113,12 @@
     fi
 done
 
+if [ "x$1" = "x" ] ; then
+  main="Main"
+else
+  main="$1"
+fi
+
 msg "------------------------------"
 
 export ANDROID_PRINTF_LOG=brief
@@ -171,7 +178,7 @@
 fi
 
 JNI_OPTS="-Xjnigreflimit:512 -Xcheck:jni"
-cmdline="$INVOKE_WITH $gdb $exe $gdbargs -XXlib:$LIB $JNI_OPTS $FLAGS $INT_OPTS $DEBUGGER_OPTS $BOOT_OPT -cp $DEX_LOCATION/$TEST_NAME.jar Main"
+cmdline="$INVOKE_WITH $gdb $exe $gdbargs -XXlib:$LIB $JNI_OPTS $FLAGS $INT_OPTS $DEBUGGER_OPTS $BOOT_OPT -cp $DEX_LOCATION/$TEST_NAME.jar $main"
 if [ "$DEV_MODE" = "y" ]; then
   if [ "$PREBUILD" = "y" ]; then
     echo "$mkdir_cmd && $prebuild_cmd && $cmdline"
diff --git a/test/run-test b/test/run-test
index 0e42efe..ae613d9 100755
--- a/test/run-test
+++ b/test/run-test
@@ -377,6 +377,9 @@
   file_size_limit=5120
 elif echo "$test_dir" | grep 083; then
   file_size_limit=5120
+elif echo "$test_dir" | grep 115; then
+# Native bridge test copies libarttest.so into its directory, which needs 2MB already.
+  file_size_limit=5120
 fi
 if ! ulimit -S "$file_size_limit"; then
    echo "ulimit file size setting failed"