/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "debugger.h"
#include "logging.h"
#include "stack.h"
#include "thread_list.h"

#include "JniConstants.h"  // Last to avoid problems with LOG redefinition.
#include "ScopedPrimitiveArray.h"  // Last to avoid problems with LOG redefinition.

namespace art {

namespace {

static void DdmVmInternal_enableRecentAllocations(JNIEnv* env, jclass, jboolean enable) {
  UNIMPLEMENTED(WARNING);
  if (enable) {
    //dvmEnableAllocTracker();
  } else {
    //dvmDisableAllocTracker();
  }
}

static jbyteArray DdmVmInternal_getRecentAllocations(JNIEnv* env, jclass) {
  UNIMPLEMENTED(WARNING);
  return NULL;
  //ArrayObject* data = dvmDdmGetRecentAllocations();
  //dvmReleaseTrackedAlloc(data, NULL);
  //return reinterpret_cast<jbyteArray>(addLocalReference(env, data));
}

static jboolean DdmVmInternal_getRecentAllocationStatus(JNIEnv* env, jclass) {
  UNIMPLEMENTED(WARNING);
  return JNI_FALSE;
  //return (gDvm.allocRecords != NULL);
}

static Thread* FindThreadByThinLockId(uint32_t thin_lock_id) {
  struct ThreadFinder {
    ThreadFinder(uint32_t thin_lock_id) : thin_lock_id(thin_lock_id), thread(NULL) {
    }

    static void Callback(Thread* t, void* context) {
      ThreadFinder* finder = reinterpret_cast<ThreadFinder*>(context);
      if (t->GetThinLockId() == finder->thin_lock_id) {
        finder->thread = t;
      }
    }

    uint32_t thin_lock_id;
    Thread* thread;
  };
  ThreadFinder finder(thin_lock_id);
  Runtime::Current()->GetThreadList()->ForEach(ThreadFinder::Callback, &finder);
  return finder.thread;
}

/*
 * Get a stack trace as an array of StackTraceElement objects.  Returns
 * NULL on failure, e.g. if the threadId couldn't be found.
 */
static jobjectArray DdmVmInternal_getStackTraceById(JNIEnv* env, jclass, jint thin_lock_id) {
  ScopedThreadListLock thread_list_lock;
  Thread* thread = FindThreadByThinLockId(static_cast<uint32_t>(thin_lock_id));
  if (thread == NULL) {
    return NULL;
  }
  jobject stack = GetThreadStack(env, thread);
  return (stack != NULL) ? Thread::InternalStackTraceToStackTraceElementArray(env, stack) : NULL;
}

static void ThreadCountCallback(Thread*, void* context) {
  uint16_t& count = *reinterpret_cast<uint16_t*>(context);
  ++count;
}

static const int kThstBytesPerEntry = 18;
static const int kThstHeaderLen = 4;

static void ThreadStatsGetterCallback(Thread* t, void* context) {
  uint8_t** ptr = reinterpret_cast<uint8_t**>(context);
  uint8_t* buf = *ptr;

  /*
   * Generate the contents of a THST chunk.  The data encompasses all known
   * threads.
   *
   * Response has:
   *  (1b) header len
   *  (1b) bytes per entry
   *  (2b) thread count
   * Then, for each thread:
   *  (4b) threadId
   *  (1b) thread status
   *  (4b) tid
   *  (4b) utime
   *  (4b) stime
   *  (1b) is daemon?
   *
   * The length fields exist in anticipation of adding additional fields
   * without wanting to break ddms or bump the full protocol version.  I don't
   * think it warrants full versioning.  They might be extraneous and could
   * be removed from a future version.
   */
  int utime, stime, task_cpu;
  GetTaskStats(t->GetTid(), utime, stime, task_cpu);

  JDWP::Set4BE(buf+0, t->GetThinLockId());
  JDWP::Set1(buf+4, t->GetState());
  JDWP::Set4BE(buf+5, t->GetTid());
  JDWP::Set4BE(buf+9, utime);
  JDWP::Set4BE(buf+13, stime);
  JDWP::Set1(buf+17, t->IsDaemon());

  *ptr += kThstBytesPerEntry;
}

static jbyteArray DdmVmInternal_getThreadStats(JNIEnv* env, jclass) {
  std::vector<uint8_t> bytes;
  {
    ScopedThreadListLock thread_list_lock;
    ThreadList* thread_list = Runtime::Current()->GetThreadList();

    uint16_t thread_count;
    thread_list->ForEach(ThreadCountCallback, &thread_count);

    bytes.resize(kThstHeaderLen + thread_count * kThstBytesPerEntry);

    JDWP::Set1(&bytes[0], kThstHeaderLen);
    JDWP::Set1(&bytes[1], kThstBytesPerEntry);
    JDWP::Set2BE(&bytes[2], thread_count);

    uint8_t* ptr = &bytes[kThstHeaderLen];
    thread_list->ForEach(ThreadStatsGetterCallback, &ptr);
  }

  jbyteArray result = env->NewByteArray(bytes.size());
  env->SetByteArrayRegion(result, 0, bytes.size(), reinterpret_cast<const jbyte*>(&bytes[0]));
  return result;
}

static jint DdmVmInternal_heapInfoNotify(JNIEnv* env, jclass, jint when) {
  return Dbg::DdmHandleHpifChunk(static_cast<Dbg::HpifWhen>(when));
}

static jboolean DdmVmInternal_heapSegmentNotify(JNIEnv* env, jclass, jint when, jint what, jboolean native) {
  return Dbg::DdmHandleHpsgNhsgChunk(static_cast<Dbg::HpsgWhen>(when), static_cast<Dbg::HpsgWhat>(what), native);
}

static void DdmVmInternal_threadNotify(JNIEnv* env, jclass, jboolean enable) {
  Dbg::DdmSetThreadNotification(enable);
}

static JNINativeMethod gMethods[] = {
  NATIVE_METHOD(DdmVmInternal, enableRecentAllocations, "(Z)V"),
  NATIVE_METHOD(DdmVmInternal, getRecentAllocations, "()[B"),
  NATIVE_METHOD(DdmVmInternal, getRecentAllocationStatus, "()Z"),
  NATIVE_METHOD(DdmVmInternal, getStackTraceById, "(I)[Ljava/lang/StackTraceElement;"),
  NATIVE_METHOD(DdmVmInternal, getThreadStats, "()[B"),
  NATIVE_METHOD(DdmVmInternal, heapInfoNotify, "(I)Z"),
  NATIVE_METHOD(DdmVmInternal, heapSegmentNotify, "(IIZ)Z"),
  NATIVE_METHOD(DdmVmInternal, threadNotify, "(Z)V"),
};

}  // namespace

void register_org_apache_harmony_dalvik_ddmc_DdmVmInternal(JNIEnv* env) {
  jniRegisterNativeMethods(env, "org/apache/harmony/dalvik/ddmc/DdmVmInternal", gMethods, NELEM(gMethods));
}

}  // namespace art
