mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge pull request #2224 from jason-simmons/jni_binding
Initial work toward exposing the Java native interface APIs in Dart
This commit is contained in:
commit
e75a0cb4aa
@ -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';
|
||||
|
||||
17
sky/engine/bindings/jni/BUILD.gn
Normal file
17
sky/engine/bindings/jni/BUILD.gn
Normal file
@ -0,0 +1,17 @@
|
||||
# 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",
|
||||
]
|
||||
}
|
||||
145
sky/engine/bindings/jni/dart_jni.cc
Normal file
145
sky/engine/bindings/jni/dart_jni.cc
Normal file
@ -0,0 +1,145 @@
|
||||
// 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
|
||||
83
sky/engine/bindings/jni/dart_jni.h
Normal file
83
sky/engine/bindings/jni/dart_jni.h
Normal file
@ -0,0 +1,83 @@
|
||||
// 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_
|
||||
21
sky/engine/bindings/jni/jni.dart
Normal file
21
sky/engine/bindings/jni/jni.dart
Normal file
@ -0,0 +1,21 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user