Make DDM.Chunk call DdmServer.broadcast appropriately am: 6b816bb4b1
am: 790f71af96

Change-Id: Id0fb3fa076265d47f3f8f8aac512aaacf3dda554
diff --git a/src/share/back/DDMImpl.c b/src/share/back/DDMImpl.c
index 80fe669..262f778 100644
--- a/src/share/back/DDMImpl.c
+++ b/src/share/back/DDMImpl.c
@@ -23,11 +23,62 @@
  * questions.
  */
 
+#include <stdatomic.h>
+
 #include "util.h"
 #include "DDMImpl.h"
 #include "inStream.h"
 #include "outStream.h"
 
+static _Atomic(jboolean) ddmIsActive = ATOMIC_VAR_INIT(JNI_FALSE);
+
+static void
+SendDdmBroadcast(JNIEnv* env, jboolean connected)
+{
+  WITH_LOCAL_REFS(env, 2) {
+    jclass ddm_class = JNI_FUNC_PTR(env,FindClass)(env, "org/apache/harmony/dalvik/ddmc/DdmServer");
+    if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) {
+      JNI_FUNC_PTR(env,ExceptionClear)(env);
+      goto end;
+    }
+    jmethodID broadcast = JNI_FUNC_PTR(env,GetStaticMethodID)(env, ddm_class, "broadcast", "(I)V");
+    if (broadcast == NULL) {
+      ERROR_MESSAGE(("JDWP Cannot find DdmServer.broadcast(I)V method!"));
+      JNI_FUNC_PTR(env,ExceptionDescribe)(env);
+      JNI_FUNC_PTR(env,ExceptionClear)(env);
+      goto end;
+    }
+    jint event =
+        connected == JNI_TRUE ? 1 /* DdmServer.CONNECTED */ : 2 /*DdmServer.DISCONNECTED */;
+    JNI_FUNC_PTR(env,CallStaticVoidMethod)(env, ddm_class, broadcast, event);
+    if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) {
+      LOG_ERROR(("DdmServer.broadcast %d failed", event));
+      JNI_FUNC_PTR(env,ExceptionDescribe)(env);
+      JNI_FUNC_PTR(env,ExceptionClear)(env);
+    }
+    if (!connected) {
+      // If we are disconnecting we also need to call DdmVmInternal.threadNotify(false)
+      jclass ddm_vm_internal =
+          JNI_FUNC_PTR(env,FindClass)(env, "org/apache/harmony/dalvik/ddmc/DdmVmInternal");
+      jmethodID thread_notify =
+          JNI_FUNC_PTR(env,GetStaticMethodID)(env, ddm_vm_internal, "threadNotify", "(Z)V");
+      if (thread_notify == NULL) {
+        ERROR_MESSAGE(("JDWP Cannot find DdmVmInternal.threadNotify(Z)V method!"));
+        JNI_FUNC_PTR(env,ExceptionDescribe)(env);
+        JNI_FUNC_PTR(env,ExceptionClear)(env);
+        goto end;
+      }
+      JNI_FUNC_PTR(env,CallStaticVoidMethod)(env, ddm_vm_internal, thread_notify, JNI_FALSE);
+      if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) {
+        LOG_ERROR(("DdmVmInternal.threadNotify(false) failed"));
+        JNI_FUNC_PTR(env,ExceptionDescribe)(env);
+        JNI_FUNC_PTR(env,ExceptionClear)(env);
+      }
+    }
+end: ;
+  } END_WITH_LOCAL_REFS(env);
+}
+
 static jboolean
 chunk(PacketInputStream *in, PacketOutputStream *out)
 {
@@ -54,6 +105,11 @@
         return JNI_TRUE;
     }
 
+    jboolean ddm_newly_active = !atomic_exchange(&ddmIsActive, JNI_TRUE);
+    if (ddm_newly_active) {
+      SendDdmBroadcast(getEnv(), /* connected */JNI_TRUE);
+    }
+
     LOG_JVMTI(("com.android.art.internal.ddm.process_chunk()"));
     error = gdata->ddm_process_chunk(gdata->jvmti,
                                      type_in,
@@ -80,6 +136,15 @@
     return JNI_TRUE;
 }
 
+void DDM_onDisconnect(void)
+{
+  jboolean was_active = atomic_exchange(&ddmIsActive, JNI_FALSE);
+  if (was_active) {
+    JNIEnv* env = getEnv();
+    SendDdmBroadcast(getEnv(), /*connected*/ JNI_FALSE);
+  }
+}
+
 void *DDM_Cmds[] = { (void *)1
     ,(void *)chunk
 };
diff --git a/src/share/back/DDMImpl.h b/src/share/back/DDMImpl.h
index 4d92ef4..b723c39 100644
--- a/src/share/back/DDMImpl.h
+++ b/src/share/back/DDMImpl.h
@@ -22,5 +22,7 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
+
 extern void *DDM_Cmds[];
 
+void DDM_onDisconnect(void);
diff --git a/src/share/back/debugLoop.c b/src/share/back/debugLoop.c
index 765f836..57055c5 100644
--- a/src/share/back/debugLoop.c
+++ b/src/share/back/debugLoop.c
@@ -35,6 +35,9 @@
 #include "outStream.h"
 #include "threadControl.h"
 
+// ANDROID-CHANGED: Needed for DDM_onDisconnect
+#include "DDMImpl.h"
+
 
 static void JNICALL reader(jvmtiEnv* jvmti_env, JNIEnv* jni_env, void* arg);
 static void enqueue(jdwpPacket *p);
@@ -219,6 +222,9 @@
     transport_close();
     debugMonitorDestroy(cmdQueueLock);
 
+    // ANDROID-CHANGED: DDM needs to call some functions when we disconnect.
+    DDM_onDisconnect();
+
     /* Reset for a new connection to this VM if it's still alive */
     if ( ! gdata->vmDead ) {
         debugInit_reset(getEnv());