Home | History | Annotate | Download | only in back
      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