提交 a9c22e9d 编写于 作者: J Jason Simmons

Initial work toward exposing the Java native interface APIs in Dart

上级 2848bcc2
......@@ -37,6 +37,10 @@ source_set("bindings") {
"//sky/engine/wtf",
]
if (is_android) {
deps += [ "//sky/engine/bindings/jni" ]
}
# On iOS (device), precompiled snapshots contain the instruction buffer.
# Generation of the same requires all application specific script code to be
# specified up front. In such cases, there can be no updater or generic
......@@ -144,6 +148,7 @@ source_set("snapshot_cc") {
copy("generate_dart_ui") {
sources = [
"dart_ui.dart",
"jni/jni.dart",
]
sources += core_dart_files
......
......@@ -25,6 +25,10 @@
#include "sky/engine/tonic/dart_converter.h"
#include "sky/engine/tonic/dart_error.h"
#ifdef OS_ANDROID
#include "sky/engine/bindings/jni/dart_jni.h"
#endif
namespace blink {
namespace {
......@@ -63,6 +67,11 @@ void DartUI::InitForGlobal() {
Scene::RegisterNatives(g_natives);
SceneBuilder::RegisterNatives(g_natives);
Window::RegisterNatives(g_natives);
#ifdef OS_ANDROID
// TODO(jsimmons): move this into a dart:jni library
DartJni::RegisterNatives(g_natives);
#endif
}
}
......
......@@ -24,6 +24,7 @@ part 'TransferMode.dart';
part 'compositing.dart';
part 'hash_codes.dart';
part 'hooks.dart';
part 'jni.dart';
part 'lerp.dart';
part 'natives.dart';
part 'painting.dart';
......
# Copyright 2016 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
source_set("jni") {
sources = [
"dart_jni.cc",
"dart_jni.h",
]
deps = [
"//base",
"//dart/runtime:libdart",
"//sky/engine/tonic",
"//sky/engine/wtf",
]
}
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "sky/engine/bindings/jni/dart_jni.h"
#include "base/logging.h"
#include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "sky/engine/tonic/dart_args.h"
#include "sky/engine/tonic/dart_binding_macros.h"
namespace blink {
using base::android::ScopedJavaLocalRef;
using base::android::ScopedJavaGlobalRef;
namespace {
// Check if a JNI API has thrown an exception. If so, rethrow it as a
// Dart exception.
void CheckJniException(JNIEnv* env) {
if (env->ExceptionCheck() == JNI_FALSE)
return;
jthrowable java_throwable = env->ExceptionOccurred();
env->ExceptionClear();
std::string info = base::android::GetJavaExceptionInfo(
env, java_throwable);
Dart_ThrowException(StdStringToDart(info));
}
} // anonymous namespace
DART_NATIVE_CALLBACK_STATIC(JniClass, fromName);
#define FOR_EACH_BINDING(V) \
V(JniClass, getFieldId) \
V(JniClass, getStaticFieldId) \
V(JniClass, getStaticIntField) \
V(JniClass, getStaticObjectField) \
V(JniObject, getIntField)
FOR_EACH_BINDING(DART_NATIVE_CALLBACK)
void DartJni::RegisterNatives(DartLibraryNatives* natives) {
natives->Register({
DART_REGISTER_NATIVE_STATIC(JniClass, fromName)
FOR_EACH_BINDING(DART_REGISTER_NATIVE)
});
}
ScopedJavaGlobalRef<jobject> DartJni::class_loader_;
jmethodID DartJni::load_class_method_id_;
bool DartJni::InitJni() {
JNIEnv* env = base::android::AttachCurrentThread();
class_loader_.Reset(base::android::GetClassLoader(env));
ScopedJavaLocalRef<jclass> class_loader_clazz(
env, env->FindClass("java/lang/ClassLoader"));
CHECK(!base::android::ClearException(env));
load_class_method_id_ = env->GetMethodID(
class_loader_clazz.obj(),
"loadClass",
"(Ljava/lang/String;)Ljava/lang/Class;");
CHECK(!base::android::ClearException(env));
return true;
}
ScopedJavaLocalRef<jclass> DartJni::GetClass(JNIEnv* env, const char* name) {
jobject clazz = env->CallObjectMethod(
class_loader_.obj(),
load_class_method_id_,
base::android::ConvertUTF8ToJavaString(env, name).obj());
return ScopedJavaLocalRef<jclass>(env, static_cast<jclass>(clazz));
}
IMPLEMENT_WRAPPERTYPEINFO(JniClass);
JniClass::JniClass(JNIEnv* env, jclass clazz)
: clazz_(env, clazz) {
}
JniClass::~JniClass() {
}
PassRefPtr<JniClass> JniClass::fromName(const char* name) {
JNIEnv* env = base::android::AttachCurrentThread();
ScopedJavaLocalRef<jclass> clazz = DartJni::GetClass(env, name);
CheckJniException(env);
return adoptRef(new JniClass(env, clazz.obj()));
}
intptr_t JniClass::getFieldId(const char* name, const char* sig) {
JNIEnv* env = base::android::AttachCurrentThread();
jfieldID id = env->GetFieldID(clazz_.obj(), name, sig);
CheckJniException(env);
return reinterpret_cast<intptr_t>(id);
}
intptr_t JniClass::getStaticFieldId(const char* name, const char* sig) {
JNIEnv* env = base::android::AttachCurrentThread();
jfieldID id = env->GetStaticFieldID(clazz_.obj(), name, sig);
CheckJniException(env);
return reinterpret_cast<intptr_t>(id);
}
jint JniClass::getStaticIntField(jfieldID fieldId) {
JNIEnv* env = base::android::AttachCurrentThread();
return env->GetStaticIntField(clazz_.obj(), fieldId);
}
PassRefPtr<JniObject> JniClass::getStaticObjectField(jfieldID fieldId) {
JNIEnv* env = base::android::AttachCurrentThread();
jobject obj = env->GetStaticObjectField(clazz_.obj(), fieldId);
return JniObject::create(env, obj);
}
IMPLEMENT_WRAPPERTYPEINFO(JniObject);
JniObject::JniObject(JNIEnv* env, jobject object)
: object_(env, object) {
}
JniObject::~JniObject() {
}
PassRefPtr<JniObject> JniObject::create(JNIEnv* env, jobject object) {
return adoptRef(new JniObject(env, object));
}
jint JniObject::getIntField(jfieldID fieldId) {
JNIEnv* env = base::android::AttachCurrentThread();
return env->GetIntField(object_.obj(), fieldId);
}
} // namespace blink
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SKY_ENGINE_BINDINGS_OBJC_DART_JNI_H_
#define SKY_ENGINE_BINDINGS_OBJC_DART_JNI_H_
#include "base/android/jni_android.h"
#include "base/android/jni_utils.h"
#include "sky/engine/tonic/dart_library_natives.h"
#include "sky/engine/tonic/dart_wrappable.h"
#include "sky/engine/wtf/PassRefPtr.h"
#include "sky/engine/wtf/RefCounted.h"
namespace blink {
class DartJni {
public:
static void RegisterNatives(DartLibraryNatives* natives);
static bool InitJni();
static base::android::ScopedJavaLocalRef<jclass> GetClass(
JNIEnv* env, const char* name);
private:
static base::android::ScopedJavaGlobalRef<jobject> class_loader_;
static jmethodID load_class_method_id_;
};
class JniObject;
// Wrapper that exposes a JNI jclass to Dart
class JniClass : public RefCounted<JniClass>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
~JniClass() override;
static PassRefPtr<JniClass> fromName(const char* className);
intptr_t getFieldId(const char* name, const char* sig);
intptr_t getStaticFieldId(const char* name, const char* sig);
jint getStaticIntField(jfieldID fieldId);
PassRefPtr<JniObject> getStaticObjectField(jfieldID fieldId);
private:
JniClass(JNIEnv* env, jclass clazz);
base::android::ScopedJavaGlobalRef<jclass> clazz_;
};
// Wrapper that exposes a JNI jobject to Dart
class JniObject : public RefCounted<JniObject>, public DartWrappable {
DEFINE_WRAPPERTYPEINFO();
public:
~JniObject() override;
static PassRefPtr<JniObject> create(JNIEnv* env, jobject object);
jint getIntField(jfieldID fieldId);
private:
JniObject(JNIEnv* env, jobject object);
base::android::ScopedJavaGlobalRef<jobject> object_;
};
template <>
struct DartConverter<jfieldID> {
static jfieldID FromArguments(Dart_NativeArguments args,
int index,
Dart_Handle& exception) {
int64_t result = 0;
Dart_GetNativeIntegerArgument(args, index, &result);
return reinterpret_cast<jfieldID>(result);
}
};
} // namespace blink
#endif // SKY_ENGINE_BINDINGS_OBJC_DART_JNI_H_
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of dart_ui;
/// Wrapper for a Java class accessed via JNI.
class JniClass extends NativeFieldWrapperClass2 {
static JniClass fromName(String name) native 'JniClass_fromName';
int getFieldId(String name, String sig) native 'JniClass_getFieldId';
int getStaticFieldId(String name, String sig) native 'JniClass_getStaticFieldId';
int getStaticIntField(int fieldId) native 'JniClass_getStaticIntField';
JniObject getStaticObjectField(int fieldId) native 'JniClass_getStaticObjectField';
}
/// Wrapper for a Java object accessed via JNI.
class JniObject extends NativeFieldWrapperClass2 {
int getIntField(String name, String sig) native 'JniObject_getIntField';
}
......@@ -136,6 +136,7 @@ if (is_android) {
"//mojo/android:libsystem_java",
"//mojo/edk/base_edk",
"//mojo/edk/system",
"//sky/engine/bindings/jni",
"//ui/gl",
":common",
":gpu_direct",
......
......@@ -11,6 +11,7 @@
#include "base/logging.h"
#include "mojo/android/system/base_run_loop.h"
#include "mojo/android/system/core_impl.h"
#include "sky/engine/bindings/jni/dart_jni.h"
#include "sky/shell/platform/android/platform_view_android.h"
#include "sky/shell/platform/android/sky_main.h"
#include "sky/shell/platform/android/tracing_controller.h"
......@@ -35,15 +36,22 @@ bool RegisterJNI(JNIEnv* env) {
arraysize(kSkyRegisteredMethods));
}
bool InitJNI() {
return blink::DartJni::InitJni();
}
} // namespace
// This is called by the VM when the shared library is first loaded.
JNI_EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
std::vector<base::android::RegisterCallback> register_callbacks;
register_callbacks.push_back(base::Bind(&RegisterJNI));
std::vector<base::android::InitCallback> init_callbacks;
init_callbacks.push_back(base::Bind(&InitJNI));
if (!base::android::OnJNIOnLoadRegisterJNI(vm, register_callbacks) ||
!base::android::OnJNIOnLoadInit(
std::vector<base::android::InitCallback>())) {
!base::android::OnJNIOnLoadInit(init_callbacks)) {
return -1;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册