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());