/*
 * Copyright (C) 2014 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 "native_bridge_art_interface.h"

#include <signal.h>

#include "nativebridge/native_bridge.h"

#include "art_method-inl.h"
#include "base/enums.h"
#include "base/logging.h"  // For VLOG.
#include "base/macros.h"
#include "dex/dex_file-inl.h"
#include "jni_internal.h"
#include "mirror/class-inl.h"
#include "scoped_thread_state_change-inl.h"
#include "sigchain.h"

namespace art {

static const char* GetMethodShorty(JNIEnv* env, jmethodID mid) {
  ScopedObjectAccess soa(env);
  ArtMethod* m = jni::DecodeArtMethod(mid);
  return m->GetShorty();
}

static uint32_t GetNativeMethodCount(JNIEnv* env, jclass clazz) {
  if (clazz == nullptr) {
    return 0;
  }

  ScopedObjectAccess soa(env);
  ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(clazz);

  uint32_t native_method_count = 0;
  for (auto& m : c->GetMethods(kRuntimePointerSize)) {
    native_method_count += m.IsNative() ? 1u : 0u;
  }
  return native_method_count;
}

static uint32_t GetNativeMethods(JNIEnv* env, jclass clazz, JNINativeMethod* methods,
                                 uint32_t method_count) {
  if ((clazz == nullptr) || (methods == nullptr)) {
    return 0;
  }
  ScopedObjectAccess soa(env);
  ObjPtr<mirror::Class> c = soa.Decode<mirror::Class>(clazz);

  uint32_t count = 0;
  for (auto& m : c->GetMethods(kRuntimePointerSize)) {
    if (m.IsNative()) {
      if (count < method_count) {
        methods[count].name = m.GetName();
        methods[count].signature = m.GetShorty();
        methods[count].fnPtr = m.GetEntryPointFromJni();
        count++;
      } else {
        LOG(WARNING) << "Output native method array too small. Skipping "
                     << m.PrettyMethod();
      }
    }
  }
  return count;
}

// Native bridge library runtime callbacks. They represent the runtime interface to native bridge.
//
// The interface is expected to expose the following methods:
// getMethodShorty(): in the case of native method calling JNI native function CallXXXXMethodY(),
//   native bridge calls back to VM for the shorty of the method so that it can prepare based on
//   host calling convention.
// getNativeMethodCount() and getNativeMethods(): in case of JNI function UnregisterNatives(),
//   native bridge can call back to get all native methods of specified class so that all
//   corresponding trampolines can be destroyed.
static android::NativeBridgeRuntimeCallbacks native_bridge_art_callbacks_ {
  GetMethodShorty, GetNativeMethodCount, GetNativeMethods
};

bool LoadNativeBridge(const std::string& native_bridge_library_filename) {
  VLOG(startup) << "Runtime::Setup native bridge library: "
      << (native_bridge_library_filename.empty() ? "(empty)" : native_bridge_library_filename);
  return android::LoadNativeBridge(native_bridge_library_filename.c_str(),
                                   &native_bridge_art_callbacks_);
}

void PreInitializeNativeBridge(const std::string& dir) {
  VLOG(startup) << "Runtime::Pre-initialize native bridge";
#ifndef __APPLE__  // Mac OS does not support CLONE_NEWNS.
  if (unshare(CLONE_NEWNS) == -1) {
    LOG(WARNING) << "Could not create mount namespace.";
  }
  android::PreInitializeNativeBridge(dir.c_str(), GetInstructionSetString(kRuntimeISA));
#else
  UNUSED(dir);
#endif
}

void InitializeNativeBridge(JNIEnv* env, const char* instruction_set) {
  if (android::InitializeNativeBridge(env, instruction_set)) {
    if (android::NativeBridgeGetVersion() >= 2U) {
#ifdef _NSIG  // Undefined on Apple, but we don't support running on Mac, anyways.
      // Managed signal handling support added in version 2.
      for (int signal = 0; signal < _NSIG; ++signal) {
        android::NativeBridgeSignalHandlerFn fn = android::NativeBridgeGetSignalHandler(signal);
        if (fn != nullptr) {
          sigset_t mask;
          sigfillset(&mask);
          SigchainAction sa = {
            .sc_sigaction = fn,
            .sc_mask = mask,
            // The native bridge signal might not return back to sigchain's handler.
            .sc_flags = SIGCHAIN_ALLOW_NORETURN,
          };
          AddSpecialSignalHandlerFn(signal, &sa);
        }
      }
#endif
    }
  }
}

void UnloadNativeBridge() {
  android::UnloadNativeBridge();
}

}  // namespace art
