Assorted fixes for running frameworks apps

- Adding Heap::target_utililization_
- Convert ClassNotFoundError to ClassNotFoundException in Class.forName
- Finish String::GetHashCode
- Changed Runtime.gc to unimplemented
- Disable preload simulation in oat_process
- Empty native placeholder for org.apache.harmony.dalvik.ddmc.DdmServer
- Bonus: Fix problem with reflective invocation of constructors and private methods

Change-Id: If11b273e2f82e8e0fa7161a756098514e1156a19
diff --git a/Android.mk b/Android.mk
index ba7cf62..6c2fd7e 100644
--- a/Android.mk
+++ b/Android.mk
@@ -51,6 +51,7 @@
 # "mm test-art" to build and run all tests on host and device
 .PHONY: test-art
 test-art: test-art-host test-art-target
+	@echo test-art PASSED
 
 define run-host-tests-with
   $(foreach file,$(sort $(ART_HOST_TEST_EXECUTABLES)),$(1) $(file) &&) true
@@ -68,16 +69,19 @@
 .PHONY: test-art-host
 test-art-host: $(ART_HOST_TEST_DEPENDENCIES)
 	$(call run-host-tests-with,)
+	@echo test-art-host PASSED
 
 # "mm valgrind-art-host" to build and run all host tests under valgrind.
 .PHONY: valgrind-art-host
 valgrind-art-host: $(ART_HOST_TEST_DEPENDENCIES)
 	$(call run-host-tests-with,"valgrind")
+	@echo valgrind-art-host PASSED
 
 # "mm tsan-art-host" to build and run all host tests under tsan.
 .PHONY: tsan-art-host
 tsan-art-host: $(ART_HOST_TEST_DEPENDENCIES)
 	$(call run-host-tests-with,"tsan")
+	@echo tsan-art-host PASSED
 
 ########################################################################
 # target test targets
@@ -85,6 +89,7 @@
 # "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
+	@echo test-art-target PASSED
 
 .PHONY: test-art-target-sync
 test-art-target-sync: $(ART_TARGET_TEST_DEPENDENCIES)
@@ -101,6 +106,7 @@
 
 .PHONY: test-art-target-oat
 test-art-target-oat: $(ART_TEST_OAT_TARGETS)
+	@echo test-art-target-oat PASSED
 
 ########################################################################
 # oat_process test targets
@@ -130,13 +136,18 @@
 test-art-target-oat-process-Calculator: $(TARGET_OUT_APPS)/Calculator.oat $(TARGET_OUT_JAVA_LIBRARIES)/am.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"
+	mv $(TARGET_OUT_DATA)/art-cache/classes.dex $(TARGET_OUT_DATA)/art-cache/system@app@Calculator.apk@classes.dex.`unzip -lv $(TARGET_OUT_APPS)/Calculator.apk classes.dex | grep classes.dex | sed -E 's/.* ([0-9a-f]+)  classes.dex/\1/'` # note this is extracting the crc32 that is needed as the file extension
 	adb remount
 	adb sync
-	adb shell setprop wrap.com.android.calculator2 "oat_processd"
-	adb shell stop
-	adb shell start
-	sleep 15 # sleep 30
+	if [ "`adb shell getprop wrap.com.android.calculator2 | tr -d '\r'`" = "oat_processd" ]; then \
+	  echo wrap.com.android.calculator2 already set; \
+	else \
+	  echo Setting wrap.com.android.calculator2 and restarting runtime; \
+	  adb shell setprop wrap.com.android.calculator2 "oat_processd"; \
+	  adb shell stop; \
+	  adb shell start; \
+	  sleep 30; \
+	fi
 	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
@@ -144,6 +155,9 @@
 ########################################################################
 # oatdump targets
 
+.PHONY: dump-oat
+dump-oat: dump-core-oat dump-boot-oat
+
 .PHONY: dump-core-oat
 dump-core-oat: $(TARGET_CORE_OAT) $(OATDUMP)
 	$(OATDUMP) $(addprefix --dex-file=,$(TARGET_CORE_DEX)) --image=$(TARGET_CORE_OAT) --strip-prefix=$(PRODUCT_OUT) --output=/tmp/core.oatdump.txt
diff --git a/build/Android.common.mk b/build/Android.common.mk
index f0e80b1..5903eae 100644
--- a/build/Android.common.mk
+++ b/build/Android.common.mk
@@ -132,6 +132,7 @@
 	src/object.cc \
 	src/object_bitmap.cc \
 	src/offsets.cc \
+	src/org_apache_harmony_dalvik_ddmc_DdmServer.cc \
 	src/os_linux.cc \
 	src/reference_table.cc \
 	src/reflection.cc \
diff --git a/oat_process/app_main.cpp b/oat_process/app_main.cpp
index 92ede6d..ca80fc2 100644
--- a/oat_process/app_main.cpp
+++ b/oat_process/app_main.cpp
@@ -128,7 +128,7 @@
     strlcpy(const_cast<char *>(argv0), newArgv0, strlen(argv0));
 }
 
-int main(int argc, const char* const argv[])
+int main(int argc, const char* argv[])
 {
     // These are global variables in ProcessState.cpp
     mArgC = argc;
@@ -187,6 +187,18 @@
         LOGI("argv[%d]=%s", i, argv[i]);
     }
 
+    // TODO: change the system default to not perform preloading
+    LOGI("Disabling preloading");
+    for (int i = 0; i < argc; i++) {
+        if (strcmp(argv[i], "preload") == 0) {
+            argv[i] = "nopreload";
+            break;
+        }
+    }
+    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/heap.cc b/src/heap.cc
index 8311944..5e96a79 100644
--- a/src/heap.cc
+++ b/src/heap.cc
@@ -38,6 +38,8 @@
 MemberOffset Heap::reference_pendingNext_offset_ = MemberOffset(0);
 MemberOffset Heap::finalizer_reference_zombie_offset_ = MemberOffset(0);
 
+float Heap::target_utilization_ = 0.5;
+
 Mutex* Heap::lock_ = NULL;
 
 bool Heap::verify_objects_ = false;
diff --git a/src/heap.h b/src/heap.h
index ea05a73..b669a86 100644
--- a/src/heap.h
+++ b/src/heap.h
@@ -87,12 +87,11 @@
   }
   // Implements dalvik.system.VMRuntime.getTargetHeapUtilization.
   static float GetTargetHeapUtilization() {
-    UNIMPLEMENTED(WARNING);
-    return 0.0f;
+    return target_utilization_;
   }
   // Implements dalvik.system.VMRuntime.setTargetHeapUtilization.
   static void SetTargetHeapUtilization(float target) {
-    UNIMPLEMENTED(WARNING);
+    target_utilization_ = target;
   }
 
   // Blocks the caller until the garbage collector becomes idle.
@@ -240,6 +239,9 @@
   // offset of java.lang.ref.FinalizerReference.zombie
   static MemberOffset finalizer_reference_zombie_offset_;
 
+  // Target ideal heap utilization ratio
+  static float target_utilization_;
+
   static bool verify_objects_;
 
   DISALLOW_IMPLICIT_CONSTRUCTORS(Heap);
diff --git a/src/indirect_reference_table.cc b/src/indirect_reference_table.cc
index ed27bf4..f1e903c 100644
--- a/src/indirect_reference_table.cc
+++ b/src/indirect_reference_table.cc
@@ -85,7 +85,7 @@
 
   DCHECK(obj != NULL);
   // TODO: stronger sanity check on the object (such as in heap)
-  DCHECK(IsAligned(reinterpret_cast<intptr_t>(obj), 8));
+  DCHECK(IsAligned(reinterpret_cast<intptr_t>(obj), 8)) << reinterpret_cast<const void*>(obj);
   DCHECK(table_ != NULL);
   DCHECK_LE(alloc_entries_, max_entries_);
   DCHECK_GE(segment_state_.parts.numHoles, prevState.parts.numHoles);
diff --git a/src/java_lang_Class.cc b/src/java_lang_Class.cc
index d93d3e6..4fe3191 100644
--- a/src/java_lang_Class.cc
+++ b/src/java_lang_Class.cc
@@ -48,6 +48,15 @@
   ClassLoader* class_loader = down_cast<ClassLoader*>(loader);
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
   Class* c = class_linker->FindClass(descriptor.c_str(), class_loader);
+  if (c == NULL) {
+    // Convert NoClassDefFoundError to ClassNotFoundException
+    // TODO: chain exceptions?
+    DCHECK(env->ExceptionCheck());
+    env->ExceptionClear();
+    Thread::Current()->ThrowNewException("Ljava/lang/ClassNotFoundException;",
+                                         "%s", name.c_str());
+    return NULL;
+  }
   if (initialize) {
     class_linker->EnsureInitialized(c, true);
   }
diff --git a/src/java_lang_Runtime.cc b/src/java_lang_Runtime.cc
index a2bd399..a3f4f49 100644
--- a/src/java_lang_Runtime.cc
+++ b/src/java_lang_Runtime.cc
@@ -30,6 +30,8 @@
 namespace {
 
 void Runtime_gc(JNIEnv*, jclass) {
+  UNIMPLEMENTED(WARNING);
+  return;
   Heap::CollectGarbage();
 }
 
diff --git a/src/object.cc b/src/object.cc
index e37b683..8bdc295 100644
--- a/src/object.cc
+++ b/src/object.cc
@@ -1273,11 +1273,14 @@
   return Runtime::Current()->GetInternTable()->InternWeak(this);
 }
 
-int32_t String::GetHashCode() const {
-  int32_t result = GetField32(
-      OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false);
-  DCHECK(result != 0 ||
-         ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0);
+int32_t String::GetHashCode() {
+  int32_t result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false);
+  if (result == 0) {
+    ComputeHashCode();
+  }
+  result = GetField32(OFFSET_OF_OBJECT_MEMBER(String, hash_code_), false);
+  DCHECK(result != 0 || ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()) == 0)
+          << ToModifiedUtf8() << " " << result;
   return result;
 }
 
diff --git a/src/object.h b/src/object.h
index 2ceafbd..1a137bd 100644
--- a/src/object.h
+++ b/src/object.h
@@ -1711,6 +1711,9 @@
                               const StringPiece& descriptor);
 
   Method* FindVirtualMethodForVirtualOrInterface(Method* method) {
+    if (method->IsDirect()) {
+      return method;
+    }
     if (method->GetDeclaringClass()->IsInterface()) {
       return FindVirtualMethodForInterface(method);
     }
@@ -2393,7 +2396,7 @@
 
   int32_t GetLength() const;
 
-  int32_t GetHashCode() const;
+  int32_t GetHashCode();
 
   void ComputeHashCode() {
     SetHashCode(ComputeUtf16Hash(GetCharArray(), GetOffset(), GetLength()));
diff --git a/src/org_apache_harmony_dalvik_ddmc_DdmServer.cc b/src/org_apache_harmony_dalvik_ddmc_DdmServer.cc
new file mode 100644
index 0000000..3392689
--- /dev/null
+++ b/src/org_apache_harmony_dalvik_ddmc_DdmServer.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include "logging.h"
+
+#include "JniConstants.h"  // Last to avoid problems with LOG redefinition.
+#include "ScopedPrimitiveArray.h"  // Last to avoid problems with LOG redefinition.
+
+namespace art {
+
+namespace {
+
+static void DdmServer_nativeSendChunk(JNIEnv* env, jclass, jint type,
+                                      jbyteArray javaData, jint offset, jint length)
+{
+  ScopedByteArrayRO data(env, javaData);
+  DCHECK_LE(offset + length, static_cast<int32_t>(data.size()));
+  UNIMPLEMENTED(WARNING) << "dvmDbgDdmSendChunk(type, length, data->get() + offset);";
+}
+
+static JNINativeMethod gMethods[] = {
+  NATIVE_METHOD(DdmServer, nativeSendChunk, "(I[BII)V"),
+};
+
+}  // namespace
+
+void register_org_apache_harmony_dalvik_ddmc_DdmServer(JNIEnv* env) {
+    jniRegisterNativeMethods(env, "org/apache/harmony/dalvik/ddmc/DdmServer", gMethods, NELEM(gMethods));
+}
+
+}  // namespace art
diff --git a/src/runtime.cc b/src/runtime.cc
index acb42e9..ca1d4f8 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -471,7 +471,7 @@
   REGISTER(register_java_lang_reflect_Method);
   //REGISTER(register_java_lang_reflect_Proxy);
   REGISTER(register_java_util_concurrent_atomic_AtomicLong);
-  //REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer);
+  REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmServer);
   //REGISTER(register_org_apache_harmony_dalvik_ddmc_DdmVmInternal);
   REGISTER(register_sun_misc_Unsafe);
 #undef REGISTER