Add support for oat_process for use as a wrap.* launcher
Add test support for running Calculator
Change-Id: I7ec0681febe6f6c836452e8afb4c12a2ebfa0ea8
diff --git a/Android.mk b/Android.mk
index 49e0706..5801447 100644
--- a/Android.mk
+++ b/Android.mk
@@ -59,6 +59,11 @@
ART_HOST_TEST_DEPENDENCIES := $(ART_HOST_TEST_EXECUTABLES) $(ANDROID_HOST_OUT)/framework/core-hostdex.jar $(ART_TEST_OAT_FILES)
ART_TARGET_TEST_DEPENDENCIES := $(ART_TARGET_TEST_EXECUTABLES) $(ANDROID_PRODUCT_OUT)/system/framework/core.jar $(ART_TEST_OAT_FILES)
+ART_TARGET_TEST_DEPENDENCIES += $(TARGET_OUT_EXECUTABLES)/oat_process $(TARGET_OUT_EXECUTABLES)/oat_processd
+
+########################################################################
+# host test targets
+
# "mm test-art-host" to build and run all host tests
.PHONY: test-art-host
test-art-host: $(ART_HOST_TEST_DEPENDENCIES)
@@ -74,7 +79,10 @@
tsan-art-host: $(ART_HOST_TEST_DEPENDENCIES)
$(call run-host-tests-with,"tsan")
-# "mm test-art-device" to build and run all target tests
+########################################################################
+# target test targets
+
+# "mm test-art-target" to build and run all target tests
.PHONY: test-art-target
test-art-target: test-art-target-gtest test-art-target-oat
@@ -94,20 +102,47 @@
.PHONY: test-art-target-oat
test-art-target-oat: $(ART_TEST_OAT_TARGETS)
+########################################################################
+# oat_process test targets
+
# $(1): name
define build-art-framework-oat
$(call build-art-oat,$(1),$(TARGET_BOOT_OAT),$(TARGET_BOOT_DEX))
endef
-$(eval $(call build-art-framework-oat,am))
-
.PHONY: test-art-target-oat-process
-test-art-target-oat-process: $(TARGET_OUT_JAVA_LIBRARIES)/am.oat
+test-art-target-oat-process: test-art-target-oat-process-am # test-art-target-oat-process-Calculator
+
+$(eval $(call build-art-framework-oat,$(TARGET_OUT_JAVA_LIBRARIES)/am.jar))
+
+.PHONY: test-art-target-oat-process-am
+test-art-target-oat-process-am: $(TARGET_OUT_JAVA_LIBRARIES)/am.oat test-art-target-sync
adb remount
adb sync
- adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_process -Xbootimage:/system/framework/boot.oat -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am && touch /sdcard/test-art-target-process"
- $(hide) (adb pull /sdcard/test-art-target-process /tmp/ && echo test-art-target-process PASSED) || echo test-art-target-process FAILED
- $(hide) rm /tmp/test-art-target-process
+ adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Xbootimage:/system/framework/boot.oat -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start http://android.com && touch /sdcard/test-art-target-process-am"
+ $(hide) (adb pull /sdcard/test-art-target-process-am /tmp/ && echo test-art-target-process-am PASSED) || echo test-art-target-process-am FAILED
+ $(hide) rm /tmp/test-art-target-process-am
+
+$(eval $(call build-art-framework-oat,$(TARGET_OUT_APPS)/Calculator.apk))
+
+.PHONY: test-art-target-oat-process-Calculator
+# Note that using this instead of "adb shell am start" make sure that the /data/art-cache is up-to-date
+test-art-target-oat-process-Calculator: $(TARGET_OUT_APPS)/Calculator.oat test-art-target-sync
+ mkdir -p $(TARGET_OUT_DATA)/art-cache
+ unzip $(TARGET_OUT_APPS)/Calculator.apk classes.dex -d $(TARGET_OUT_DATA)/art-cache
+ mv $(TARGET_OUT_DATA)/art-cache/classes.dex $(TARGET_OUT_DATA)/art-cache/system@app@Calculator.apk@classes.dex.c96b4ebb # crc32 from "unzip -lv $(TARGET_OUT_APPS)/Calculator.apk"
+ adb remount
+ adb sync
+ adb shell setprop wrap.com.android.calculator2 "oat_processd"
+ adb shell stop
+ adb shell start
+ sleep 15 # sleep 30
+ adb shell sh -c "export CLASSPATH=/system/framework/am.jar && oat_processd /system/bin/app_process -Xbootimage:/system/framework/boot.oat -Ximage:/system/framework/am.oat /system/bin com.android.commands.am.Am start -a android.intent.action.MAIN -n com.android.calculator2/.Calculator && touch /sdcard/test-art-target-process-Calculator"
+ $(hide) (adb pull /sdcard/test-art-target-process-Calculator /tmp/ && echo test-art-target-process-Calculator PASSED) || echo test-art-target-process-Calculator FAILED
+ $(hide) rm /tmp/test-art-target-process-Calculator
+
+########################################################################
+# oatdump targets
.PHONY: dump-core-oat
dump-core-oat: $(TARGET_CORE_OAT) $(OATDUMP)
@@ -119,9 +154,14 @@
$(OATDUMP) $(addprefix --dex-file=,$(TARGET_BOOT_DEX)) --image=$(TARGET_BOOT_OAT) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/boot.oatdump.txt
@echo Output in /tmp/boot.oatdump.txt
+########################################################################
+# cpplint target
+
# "mm cpplint-art" to style check art source files
.PHONY: cpplint-art
cpplint-art:
$(LOCAL_PATH)/tools/cpplint.py $(LOCAL_PATH)/src/*.h $(LOCAL_PATH)/src/*.cc
+########################################################################
+
include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index 4605583..5942fcf 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -33,12 +33,12 @@
########################################################################
-# $(1): module
+# $(1): input jar or apk filename
# $(2): boot oat
# $(3): boot dex files
define build-art-oat
-# TODO: change DEX2OATD to order-only prerequisite when output is stable
-$(TARGET_OUT_JAVA_LIBRARIES)/$(1).oat: $(TARGET_OUT_JAVA_LIBRARIES)/$(1).jar $(2) $(DEX2OAT)
+# TODO: change DEX2OATD (and perhaps $(2) boot oat) to order-only prerequisite when output is stable
+$(patsubst %.apk,%.oat,$(patsubst %.jar,%.oat,$(1))): $(1) $(2) $(DEX2OAT)
@echo "target dex2oat: $$@ ($$<)"
$(hide) $(DEX2OAT) -Xms16m -Xmx16m $(addprefix --boot-dex-file=,$(3)) --boot=$(2) $(addprefix --dex-file=,$$<) --image=$$@ --strip-prefix=$(PRODUCT_OUT)
endef
@@ -48,7 +48,7 @@
# $(1): directory
define build-art-test-oat
- $(call build-art-oat,art-test-dex-$(1),$(TARGET_CORE_OAT),$(TARGET_CORE_DEX))
+ $(call build-art-oat,$(TARGET_OUT_JAVA_LIBRARIES)/art-test-dex-$(1).jar,$(TARGET_CORE_OAT),$(TARGET_CORE_DEX))
ART_TEST_OAT_FILES += $(TARGET_OUT_JAVA_LIBRARIES)/art-test-dex-$(1).oat
endef
$(foreach dir,$(TEST_DEX_DIRECTORIES), $(eval $(call build-art-test-oat,$(dir))))
diff --git a/oat_process/app_main.cpp b/oat_process/app_main.cpp
index bf827a8..92ede6d 100644
--- a/oat_process/app_main.cpp
+++ b/oat_process/app_main.cpp
@@ -148,6 +148,45 @@
argc--;
argv++;
+ // ignore /system/bin/app_process when invoked via WrapperInit
+ if (strcmp(argv[0], "/system/bin/app_process") == 0) {
+ LOGI("Removing /system/bin/app_process argument");
+ argc--;
+ argv++;
+ for (int i = 0; i < argc; i++) {
+ LOGI("argv[%d]=%s", i, argv[i]);
+ }
+ }
+
+ // TODO: remove Calculator special case
+ int oatArgc = argc + 2;
+ const char* oatArgv[oatArgc];
+ if (strcmp(argv[0], "-Xbootimage:/system/framework/boot.oat") != 0) {
+ LOGI("Adding oat arguments");
+ oatArgv[0] = "-Xbootimage:/system/framework/boot.oat";
+ oatArgv[1] = "-Ximage:/system/app/Calculator.oat";
+ setenv("CLASSPATH", "/system/app/Calculator.apk", 1);
+ memcpy(oatArgv + (oatArgc - argc), argv, argc * sizeof(*argv));
+ argv = oatArgv;
+ argc = oatArgc;
+ for (int i = 0; i < argc; i++) {
+ LOGI("argv[%d]=%s", i, argv[i]);
+ }
+ }
+
+ // TODO: remove the heap arguments when implicit garbage collection enabled
+ LOGI("Adding heap arguments");
+ int heapArgc = argc + 2;
+ const char* heapArgv[heapArgc];
+ heapArgv[0] = "-Xms64m";
+ heapArgv[1] = "-Xmx64m";
+ memcpy(heapArgv + (heapArgc - argc), argv, argc * sizeof(*argv));
+ argv = heapArgv;
+ argc = heapArgc;
+ for (int i = 0; i < argc; i++) {
+ LOGI("argv[%d]=%s", i, argv[i]);
+ }
+
// Everything up to '--' or first non '-' arg goes to the vm
int i = runtime.addVmArguments(argc, argv);
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index ec0b0ed..c334f04 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -227,13 +227,6 @@
return c->IsPrimitive();
}
-bool CheckClassAccess(const Class* access_from, const Class* klass) {
- if (klass->IsPublic()) {
- return true;
- }
- return access_from->IsInSamePackage(klass);
-}
-
// Validate method/field access.
bool CheckMemberAccess(const Class* access_from, const Class* access_to, uint32_t member_flags) {
// quick accept for public access */
@@ -293,7 +286,7 @@
Method* caller_caller = frame.GetMethod();
Class* caller_class = caller_caller->GetDeclaringClass();
- if (!CheckClassAccess(c, caller_class)) {
+ if (!caller_class->CanAccess(c)) {
Thread::Current()->ThrowNewException("Ljava/lang/IllegalAccessException;",
"Class %s is not accessible from class %s",
PrettyDescriptor(c->GetDescriptor()).c_str(),
diff --git a/src/thread.cc b/src/thread.cc
index 22495be..8005072 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -301,7 +301,7 @@
obj->MonitorEnter(thread);
DCHECK(thread->HoldsLock(obj));
// Only possible exception is NPE and is handled before entry
- DCHECK(thread->GetException() == NULL);
+ DCHECK(!thread->IsExceptionPending());
}
extern "C" void artCheckSuspendFromCode(Thread* thread) {
@@ -358,10 +358,14 @@
Method* interface_method = class_linker->ResolveMethod(method_idx, caller_method, false);
if (interface_method == NULL) {
// Could not resolve interface method. Throw error and unwind
- CHECK(thread->GetException() != NULL);
+ CHECK(thread->IsExceptionPending());
return 0;
}
Method* method = this_object->GetClass()->FindVirtualMethodForInterface(interface_method);
+ if (method == NULL) {
+ CHECK(thread->IsExceptionPending());
+ return 0;
+ }
const void* code = method->GetCode();
uint32_t method_uint = reinterpret_cast<uint32_t>(method);
@@ -1372,6 +1376,7 @@
CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\"";
int rc = env->ThrowNew(exception_class, msg.c_str());
CHECK_EQ(rc, JNI_OK);
+ env->DeleteLocalRef(exception_class);
}
void Thread::ThrowOutOfMemoryError() {