Implement DexFile_getClassNameList

Change-Id: I9b48628e338a5346bc3ac21f3469e4e3d224a956
diff --git a/Android.mk b/Android.mk
index b909c98..06b7ebe 100644
--- a/Android.mk
+++ b/Android.mk
@@ -215,7 +215,7 @@
 # oatdump targets
 
 .PHONY: dump-oat
-dump-oat: dump-oat-core dump-oat-boot # dump-oat-Calculator # TODO: restore when oatdump can dump an oat without an image
+dump-oat: dump-oat-core dump-oat-boot dump-oat-Calculator
 
 .PHONY: dump-oat-core
 dump-oat-core: $(TARGET_CORE_OAT) $(OATDUMP)
@@ -228,8 +228,8 @@
 	@echo Output in /tmp/boot.oatdump.txt
 
 .PHONY: dump-oat-Calculator
-dump-oat-Calculator: $(TARGET_OUT_APPS)/Calculator.oat $(TARGET_BOOT_OAT) $(OATDUMP)
-	$(OATDUMP) --image=$(patsubst %.oat,%.art,$<) --boot-image=$(TARGET_BOOT_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/Calculator.oatdump.txt
+dump-oat-Calculator: $(call art-cache-oat,system/app/Calculator.oat) $(TARGET_BOOT_OAT) $(OATDUMP)
+	$(OATDUMP) --oat=$< --boot-image=$(TARGET_BOOT_IMG) --host-prefix=$(PRODUCT_OUT) --output=/tmp/Calculator.oatdump.txt
 	@echo Output in /tmp/Calculator.oatdump.txt
 
 
diff --git a/build/Android.oat.mk b/build/Android.oat.mk
index b8047aa..505d7bc 100644
--- a/build/Android.oat.mk
+++ b/build/Android.oat.mk
@@ -19,6 +19,10 @@
 # TODO: for now, override with debug version for better error reporting
 DEX2OAT := $(DEX2OATD)
 
+# TODO: change DEX2OAT_DEPENDENCY to order-only prerequisite when output is stable
+DEX2OAT_DEPENDENCY := $(DEX2OAT)    # when dex2oat changes, rebuild all oat files
+DEX2OAT_DEPENDENCY := | $(DEX2OAT)  # only build dex2oat if needed to build oat files
+
 OATDUMP := $(HOST_OUT_EXECUTABLES)/oatdump$(HOST_EXECUTABLE_SUFFIX)
 OATDUMPD := $(HOST_OUT_EXECUTABLES)/oatdumpd$(HOST_EXECUTABLE_SUFFIX)
 # TODO: for now, override with debug version for better error reporting
@@ -42,14 +46,12 @@
 HOST_CORE_IMG := $(HOST_OUT_JAVA_LIBRARIES)/core.art
 TARGET_CORE_IMG := $(ART_TEST_OUT)/core.art
 
-# TODO: change DEX2OATD to order-only prerequisite when output is stable
-$(HOST_CORE_OAT): $(HOST_CORE_DEX) $(DEX2OAT)
+$(HOST_CORE_OAT): $(HOST_CORE_DEX) $(DEX2OAT_DEPENDENCY)
 	@echo "host dex2oat: $@ ($<)"
 	@mkdir -p $(dir $@)
 	$(hide) $(DEX2OAT) -Xms16m -Xmx16m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(HOST_CORE_IMG) --base=$(IMG_HOST_BASE_ADDRESS)
 
-# TODO: change DEX2OATD to order-only prerequisite when output is stable
-$(TARGET_CORE_OAT): $(TARGET_CORE_DEX) $(DEX2OAT)
+$(TARGET_CORE_OAT): $(TARGET_CORE_DEX) $(DEX2OAT_DEPENDENCY)
 	@echo "target dex2oat: $@ ($<)"
 	@mkdir -p $(dir $@)
 	$(hide) $(DEX2OAT) -Xms32m -Xmx32m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_CORE_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
@@ -61,7 +63,6 @@
 TARGET_BOOT_OAT := $(ART_CACHE_OUT)/boot.oat
 TARGET_BOOT_IMG := $(ART_CACHE_OUT)/boot.art
 
-# TODO: change DEX2OATD to order-only prerequisite when output is stable
-$(TARGET_BOOT_OAT): $(TARGET_BOOT_DEX) $(DEX2OAT)
+$(TARGET_BOOT_OAT): $(TARGET_BOOT_DEX) $(DEX2OAT_DEPENDENCY)
 	@echo "target dex2oat: $@ ($<)"
 	$(hide) $(DEX2OAT) -Xms256m -Xmx256m $(addprefix --dex-file=,$(filter-out $(DEX2OAT),$^)) --oat=$@ --image=$(TARGET_BOOT_IMG) --base=$(IMG_TARGET_BASE_ADDRESS) --host-prefix=$(PRODUCT_OUT)
diff --git a/build/Android.oattest.mk b/build/Android.oattest.mk
index 27a4646..801cc42 100644
--- a/build/Android.oattest.mk
+++ b/build/Android.oattest.mk
@@ -38,8 +38,7 @@
 # $(2): output oat filename
 # $(3): boot image
 define build-art-oat
-# TODO: change DEX2OATD (and perhaps $(2) boot oat) to order-only prerequisite when output is stable
-$(2): $(1) $(3) $(DEX2OAT)
+$(2): $(1) $(3) $(DEX2OAT_DEPENDENCY)
 	@echo "target dex2oat: $$@ ($$<)"
 	$(hide) $(DEX2OAT) -Xms16m -Xmx16m --boot-image=$(3) $(addprefix --dex-file=,$$<) --oat=$$@ --host-prefix=$(PRODUCT_OUT)
 endef
diff --git a/src/dalvik_system_DexFile.cc b/src/dalvik_system_DexFile.cc
index 67ff27f..cad1acd 100644
--- a/src/dalvik_system_DexFile.cc
+++ b/src/dalvik_system_DexFile.cc
@@ -19,6 +19,7 @@
 #include "dex_file.h"
 #include "logging.h"
 #include "runtime.h"
+#include "toStringArray.h"
 #include "ScopedUtfChars.h"
 
 #include "JniConstants.h" // Last to avoid problems with LOG redefinition.
@@ -144,13 +145,23 @@
   if (dex_file == NULL) {
     return NULL;
   }
-  UNIMPLEMENTED(ERROR);
-  return NULL;
+
+  std::vector<std::string> class_names;
+  for (size_t i = 0; i < dex_file->NumClassDefs(); ++i) {
+    const DexFile::ClassDef& class_def = dex_file->GetClassDef(i);
+    const char* descriptor = dex_file->GetClassDescriptor(class_def);
+    class_names.push_back(DescriptorToDot(descriptor));
+  }
+  return toStringArray(env, class_names);
 }
 
 jboolean DexFile_isDexOptNeeded(JNIEnv* env, jclass, jstring javaFilename) {
-  // TODO: run dex2oat?
-  UNIMPLEMENTED(WARNING);
+  ScopedUtfChars filename(env, javaFilename);
+  if (filename.c_str() == NULL) {
+    return JNI_FALSE;
+  }
+  // TODO: return true if we need to extract dex or run dex2oat
+  UNIMPLEMENTED(WARNING) << filename.c_str();
   return JNI_FALSE;
 }
 
diff --git a/src/runtime_support.cc b/src/runtime_support.cc
index 8608eff..ba3e1b4 100644
--- a/src/runtime_support.cc
+++ b/src/runtime_support.cc
@@ -182,7 +182,7 @@
   const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
 
   const DexFile::FieldId& id = dex_file.GetFieldId(ref);
-  std::string class_name(PrettyDescriptor(dex_file.dexStringByTypeIdx(id.class_idx_)));
+  std::string class_name(PrettyDescriptor(dex_file.GetFieldClassDescriptor(id)));
   const char* field_name = dex_file.dexStringById(id.name_idx_);
   if (!access) {
     return class_name + "." + field_name;
@@ -204,7 +204,7 @@
   const DexFile& dex_file = class_linker->FindDexFile(method->GetDeclaringClass()->GetDexCache());
 
   const DexFile::MethodId& id = dex_file.GetMethodId(ref);
-  std::string class_name(PrettyDescriptor(dex_file.dexStringByTypeIdx(id.class_idx_)));
+  std::string class_name(PrettyDescriptor(dex_file.GetMethodClassDescriptor(id)));
   const char* method_name = dex_file.dexStringById(id.name_idx_);
   if (!access) {
     return class_name + "." + method_name;