Wire up enough of the pieces that we can connect ddms or jdb.

(And die with an UNIMPLEMENTED as soon as they connect, of course.)

Change-Id: I9abb25d581384361c215b3cd96b8278c751e79ea
diff --git a/src/debugger.cc b/src/debugger.cc
index 1580c76..ef44816 100644
--- a/src/debugger.cc
+++ b/src/debugger.cc
@@ -144,13 +144,36 @@
   return true;
 }
 
-bool Dbg::DebuggerStartup() {
-  UNIMPLEMENTED(FATAL);
-  return false;
+void Dbg::StartJdwp() {
+  // Init JDWP if the debugger is enabled. This may connect out to a
+  // debugger, passively listen for a debugger, or block waiting for a
+  // debugger.
+  if (gJdwpAllowed && gJdwpConfigured) {
+    JDWP::JdwpStartupParams params;
+    params.host = gJdwpHost;
+    params.transport = gJdwpTransport;
+    params.server = gJdwpServer;
+    params.suspend = gJdwpSuspend;
+    params.port = gJdwpPort;
+
+    gJdwpState = JDWP::JdwpStartup(&params);
+    if (gJdwpState == NULL) {
+      LOG(WARNING) << "debugger thread failed to initialize";
+    }
+  }
+
+  // If a debugger has already attached, send the "welcome" message.
+  // This may cause us to suspend all threads.
+  if (JDWP::JdwpIsActive(gJdwpState)) {
+    //ScopedThreadStateChange(Thread::Current(), Thread::kRunnable);
+    if (!JDWP::PostVMStart(gJdwpState, gJdwpSuspend)) {
+      LOG(WARNING) << "failed to post 'start' message to debugger";
+    }
+  }
 }
 
-void Dbg::DebuggerShutdown() {
-  UNIMPLEMENTED(FATAL);
+void Dbg::StopJdwp() {
+  JDWP::JdwpShutdown(gJdwpState);
 }
 
 void Dbg::SetJdwpAllowed(bool allowed) {
@@ -190,13 +213,11 @@
 }
 
 int Dbg::ThreadRunning() {
-  UNIMPLEMENTED(FATAL);
-  return 0;
+  return static_cast<int>(Thread::Current()->SetState(Thread::kRunnable));
 }
 
 int Dbg::ThreadWaiting() {
-  UNIMPLEMENTED(FATAL);
-  return 0;
+  return static_cast<int>(Thread::Current()->SetState(Thread::kVmWait));
 }
 
 int Dbg::ThreadContinuing(int status) {
diff --git a/src/debugger.h b/src/debugger.h
index 2c2ade7..fa870b1 100644
--- a/src/debugger.h
+++ b/src/debugger.h
@@ -65,11 +65,11 @@
 class Dbg {
 public:
   static bool ParseJdwpOptions(const std::string& options);
-  static bool DebuggerStartup();
-  static void DebuggerShutdown();
-
   static void SetJdwpAllowed(bool allowed);
 
+  static void StartJdwp();
+  static void StopJdwp();
+
   // Return the DebugInvokeReq for the current thread.
   static DebugInvokeReq* GetInvokeReq();
 
diff --git a/src/jdwp/jdwp.h b/src/jdwp/jdwp.h
index 1c205bc..8455ba5 100644
--- a/src/jdwp/jdwp.h
+++ b/src/jdwp/jdwp.h
@@ -93,9 +93,8 @@
   JdwpTransportType transport;
   bool server;
   bool suspend;
-  char host[64];
+  std::string host;
   short port;
-  /* more will be here someday */
 };
 
 /*
diff --git a/src/jdwp/jdwp_main.cc b/src/jdwp/jdwp_main.cc
index f2ff937..c9dac64f 100644
--- a/src/jdwp/jdwp_main.cc
+++ b/src/jdwp/jdwp_main.cc
@@ -311,7 +311,7 @@
   android_atomic_release_store(true, &state->debug_thread_started_);
 
   state->thread_start_lock_.Lock();
-  state->thread_start_cond_.Wait(state->thread_start_lock_);
+  state->thread_start_cond_.Broadcast();
   state->thread_start_lock_.Unlock();
 
   /* set the thread state to VMWAIT so GCs don't wait for us */
diff --git a/src/jdwp/jdwp_socket.cc b/src/jdwp/jdwp_socket.cc
index b4062d0..55bc1b4 100644
--- a/src/jdwp/jdwp_socket.cc
+++ b/src/jdwp/jdwp_socket.cc
@@ -407,14 +407,14 @@
   struct hostent he;
   char auxBuf[128];
   int error;
-  int cc = gethostbyname_r(state->params.host, &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
+  int cc = gethostbyname_r(state->params.host.c_str(), &he, auxBuf, sizeof(auxBuf), &pEntry, &error);
   if (cc != 0) {
     LOG(WARNING) << "gethostbyname_r('" << state->params.host << "') failed: " << hstrerror(error);
     return false;
   }
 #else
   h_errno = 0;
-  pEntry = gethostbyname(state->params.host);
+  pEntry = gethostbyname(state->params.host.c_str());
   if (pEntry == NULL) {
     PLOG(WARNING) << "gethostbyname('" << state->params.host << "') failed";
     return false;
diff --git a/src/oat_file.cc b/src/oat_file.cc
index 30b19a8..1a99820 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -11,7 +11,6 @@
 namespace art {
 
 std::string OatFile::DexFilenameToOatFilename(const std::string& location) {
-  LOG(INFO) << "dexfilenametooatfilename " << location;
   CHECK(IsValidDexFilename(location) || IsValidZipFilename(location));
   std::string oat_location = location.substr(0, location.size()-3);
   oat_location += "oat";
diff --git a/src/runtime.cc b/src/runtime.cc
index a144c44..5f2eddd 100644
--- a/src/runtime.cc
+++ b/src/runtime.cc
@@ -56,6 +56,8 @@
 }
 
 Runtime::~Runtime() {
+  Dbg::StopJdwp();
+
   // Make sure our internal threads are dead before we start tearing down things they're using.
   delete signal_catcher_;
   // TODO: GC thread.
@@ -402,7 +404,9 @@
   // come after ClassLinker::RunRootClinits.
   started_ = true;
 
-  StartSignalCatcher();
+  if (!is_zygote_) {
+    DidForkFromZygote();
+  }
 
   StartDaemonThreads();
 
@@ -416,9 +420,13 @@
 }
 
 void Runtime::DidForkFromZygote() {
-  CHECK(is_zygote_);
   is_zygote_ = false;
+
   StartSignalCatcher();
+
+  // Start the JDWP thread. If the command-line debugger flags specified "suspend=y",
+  // this will pause the runtime, so we probably want this to come last.
+  Dbg::StartJdwp();
 }
 
 void Runtime::StartSignalCatcher() {
diff --git a/src/runtime.h b/src/runtime.h
index 44dfacf..d29bd3a 100644
--- a/src/runtime.h
+++ b/src/runtime.h
@@ -221,8 +221,9 @@
   bool Init(const Options& options, bool ignore_unrecognized);
   void InitNativeMethods();
   void RegisterRuntimeNativeMethods(JNIEnv*);
-  void StartSignalCatcher();
+
   void StartDaemonThreads();
+  void StartSignalCatcher();
 
   bool verbose_startup_;
   bool is_zygote_;
diff --git a/test/etc/push-and-run-test-jar b/test/etc/push-and-run-test-jar
index ae1474a..53d7a76 100755
--- a/test/etc/push-and-run-test-jar
+++ b/test/etc/push-and-run-test-jar
@@ -98,7 +98,15 @@
 fi
 
 if [ "$DEBUG" = "y" ]; then
+  # This is for ddms:
   DEX_DEBUG="-agentlib:jdwp=transport=dt_android_adb,server=y,suspend=y"
+  # Connect by running 'ddms'.
+
+  # This is for jdb:
+  #DEX_DEBUG="-agentlib:jdwp=transport=dt_socket,address=12345,server=y,suspend=y"
+  # Connect thus:
+  #   adb forward tcp:12345 tcp:12345
+  #   jdb -attach localhost:12345
 fi
 
 if [ "$ZYGOTE" = "y" ]; then