1 /* 2 * Copyright (c) 1999, 2005, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #include <stdatomic.h> 27 28 #include "util.h" 29 #include "DDMImpl.h" 30 #include "inStream.h" 31 #include "outStream.h" 32 33 static _Atomic(jboolean) ddmIsActive = ATOMIC_VAR_INIT(JNI_FALSE); 34 35 static void 36 SendDdmBroadcast(JNIEnv* env, jboolean connected) 37 { 38 WITH_LOCAL_REFS(env, 2) { 39 jclass ddm_class = JNI_FUNC_PTR(env,FindClass)(env, "org/apache/harmony/dalvik/ddmc/DdmServer"); 40 if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) { 41 JNI_FUNC_PTR(env,ExceptionClear)(env); 42 goto end; 43 } 44 jmethodID broadcast = JNI_FUNC_PTR(env,GetStaticMethodID)(env, ddm_class, "broadcast", "(I)V"); 45 if (broadcast == NULL) { 46 ERROR_MESSAGE(("JDWP Cannot find DdmServer.broadcast(I)V method!")); 47 JNI_FUNC_PTR(env,ExceptionDescribe)(env); 48 JNI_FUNC_PTR(env,ExceptionClear)(env); 49 goto end; 50 } 51 jint event = 52 connected == JNI_TRUE ? 1 /* DdmServer.CONNECTED */ : 2 /*DdmServer.DISCONNECTED */; 53 JNI_FUNC_PTR(env,CallStaticVoidMethod)(env, ddm_class, broadcast, event); 54 if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) { 55 LOG_ERROR(("DdmServer.broadcast %d failed", event)); 56 JNI_FUNC_PTR(env,ExceptionDescribe)(env); 57 JNI_FUNC_PTR(env,ExceptionClear)(env); 58 } 59 if (!connected) { 60 // If we are disconnecting we also need to call DdmVmInternal.threadNotify(false) 61 jclass ddm_vm_internal = 62 JNI_FUNC_PTR(env,FindClass)(env, "org/apache/harmony/dalvik/ddmc/DdmVmInternal"); 63 jmethodID thread_notify = 64 JNI_FUNC_PTR(env,GetStaticMethodID)(env, ddm_vm_internal, "threadNotify", "(Z)V"); 65 if (thread_notify == NULL) { 66 ERROR_MESSAGE(("JDWP Cannot find DdmVmInternal.threadNotify(Z)V method!")); 67 JNI_FUNC_PTR(env,ExceptionDescribe)(env); 68 JNI_FUNC_PTR(env,ExceptionClear)(env); 69 goto end; 70 } 71 JNI_FUNC_PTR(env,CallStaticVoidMethod)(env, ddm_vm_internal, thread_notify, JNI_FALSE); 72 if (JNI_FUNC_PTR(env,ExceptionCheck)(env)) { 73 LOG_ERROR(("DdmVmInternal.threadNotify(false) failed")); 74 JNI_FUNC_PTR(env,ExceptionDescribe)(env); 75 JNI_FUNC_PTR(env,ExceptionClear)(env); 76 } 77 } 78 end: ; 79 } END_WITH_LOCAL_REFS(env); 80 } 81 82 static jboolean 83 chunk(PacketInputStream *in, PacketOutputStream *out) 84 { 85 int i; 86 jint type_in; 87 jint type_out; 88 jint len_in; 89 jint len_out; 90 jbyte* data_in; 91 jbyte* data_out; 92 jvmtiError error; 93 94 type_in = inStream_readInt(in); 95 len_in = inStream_readInt(in); 96 data_in = inStream_readBytes(in, len_in, (jbyte*)jvmtiAllocate(len_in)); 97 98 if (inStream_error(in)) { 99 return JNI_TRUE; 100 } 101 102 if (gdata->ddm_process_chunk == NULL) { 103 jvmtiDeallocate(data_in); 104 outStream_setError(out, JDWP_ERROR(NOT_IMPLEMENTED)); 105 return JNI_TRUE; 106 } 107 108 jboolean ddm_newly_active = !atomic_exchange(&ddmIsActive, JNI_TRUE); 109 if (ddm_newly_active) { 110 SendDdmBroadcast(getEnv(), /* connected */JNI_TRUE); 111 } 112 113 LOG_JVMTI(("com.android.art.internal.ddm.process_chunk()")); 114 error = gdata->ddm_process_chunk(gdata->jvmti, 115 type_in, 116 len_in, 117 data_in, 118 &type_out, 119 &len_out, 120 &data_out); 121 122 jvmtiDeallocate(data_in); 123 124 if (error != JVMTI_ERROR_NONE) { 125 // For backwards-compatibility we do not actually return any error or any data at all 126 // here. 127 LOG_MISC(("Suppressing error from com.android.art.internal.ddm.process_chunk for backwards " 128 "compatibility. Error was %s (%d)", jvmtiErrorText(error), error)); 129 return JNI_TRUE; 130 } 131 132 outStream_writeInt(out, type_out); 133 outStream_writeByteArray(out, len_out, data_out); 134 jvmtiDeallocate(data_out); 135 136 return JNI_TRUE; 137 } 138 139 void DDM_initialize(void) 140 { 141 atomic_exchange(&ddmIsActive, gdata->ddmInitiallyActive); 142 } 143 144 void DDM_onDisconnect(void) 145 { 146 jboolean was_active = atomic_exchange(&ddmIsActive, JNI_FALSE); 147 if (was_active) { 148 JNIEnv* env = getEnv(); 149 SendDdmBroadcast(getEnv(), /*connected*/ JNI_FALSE); 150 } 151 } 152 153 void *DDM_Cmds[] = { (void *)1 154 ,(void *)chunk 155 }; 156