Commit e49d9019 authored by Aiden Benner's avatar Aiden Benner Committed by Commit Bot

Add Java side of JNI annotation processor for static methods

First iteration of the JNI annotation processor for static methods.

Adds a new annotation @JNIStaticNatives that when used
on an inner interface, will trigger the annotation processor
to generate native declarations and a wrapper class.

I provided a sample usage in
example/jni_generator/SampleForAnnotationProcessor.java

Change-Id: If888b6fd41eafccb54af32aebde3a850bab55849
Reviewed-on: https://chromium-review.googlesource.com/c/1239348
Commit-Queue: Aiden Benner <abenner@google.com>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Reviewed-by: default avatarEric Stevenson <estevenson@chromium.org>
Reviewed-by: default avatarPeter Wen <wnwen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#597359}
parent 4d670b60
...@@ -2872,6 +2872,13 @@ if (is_android) { ...@@ -2872,6 +2872,13 @@ if (is_android) {
classes = [ "java/lang/Runtime.class" ] classes = [ "java/lang/Runtime.class" ]
} }
java_library("jni_processor_annotations_java") {
supports_android = true
java_files = [
"android/java/src/org/chromium/base/annotations/JniStaticNatives.java",
]
}
android_library("base_java") { android_library("base_java") {
srcjar_deps = [ srcjar_deps = [
":base_android_java_enums_srcjar", ":base_android_java_enums_srcjar",
......
// Copyright 2018 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.
package org.chromium.base.annotations;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface JniStaticNatives {}
...@@ -21,6 +21,14 @@ android_library("jni_sample_java") { ...@@ -21,6 +21,14 @@ android_library("jni_sample_java") {
] ]
} }
android_library("jni_annotation_sample_java") {
java_files = [ "java/src/org/chromium/example/jni_generator/SampleForAnnotationProcessor.java" ]
deps = [
"//base:jni_processor_annotations_java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
source_set("jni_sample_native_side") { source_set("jni_sample_native_side") {
deps = [ deps = [
":jni_sample_header", ":jni_sample_header",
...@@ -63,6 +71,22 @@ generate_jni_registration("sample_jni_registration") { ...@@ -63,6 +71,22 @@ generate_jni_registration("sample_jni_registration") {
# Serves to test that generated bindings compile properly. # Serves to test that generated bindings compile properly.
group("jni_generator_tests") { group("jni_generator_tests") {
deps = [ deps = [
":jni_annotation_sample_java",
":sample_jni_apk", ":sample_jni_apk",
] ]
} }
java_annotation_processor("jni_processor") {
java_files = [ "java/src/org/chromium/jni_generator/JniProcessor.java" ]
main_class = "org.chromium.jni_generator.JniProcessor"
annotation_processor_deps = [ "//third_party/auto:auto_service_processor" ]
deps = [
"//base:jni_processor_annotations_java",
"//third_party/android_deps:com_squareup_javapoet_java",
"//third_party/auto:auto_service_java",
"//third_party/guava:guava_java",
]
}
// Copyright 2018 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.
package org.chromium.example.jni_generator;
import org.chromium.base.annotations.JniStaticNatives;
/**
* Sample class that uses the JNI annotation processor for static methods.
* See generated files at bottom.
*/
class SampleForAnnotationProcessor {
/**
* Static methods declared here, each of these refer to a native method
* which will have its declaration generated by our annotation processor.
* There will also be a class generated to wrap these native methods
* with the name SampleForAnnotationProcessorJni which will implement
* Natives.
*/
@JniStaticNatives
interface Natives {
void foo(String a, int b, char c, int[] d);
SampleForAnnotationProcessor bar(SampleForAnnotationProcessor sample);
String revString(String stringToReverse);
String[] sendToNative(String[] strs);
SampleForAnnotationProcessor[] sendSamplesToNative(SampleForAnnotationProcessor[] strs);
boolean hasPhalange();
}
void test() {
int[] x = new int[] {1, 2, 3, 4, 5};
String[] strs = new String[] {"the", "quick", "brown", "fox"};
strs = SampleForAnnotationProcessorJni.get().sendToNative(strs);
SampleForAnnotationProcessor[] samples =
new SampleForAnnotationProcessor[] {this, this, this};
samples = SampleForAnnotationProcessorJni.get().sendSamplesToNative(samples);
// Instance of Natives accessed through (classname + "Jni").get().
SampleForAnnotationProcessorJni.get().foo("Test", 5, 'c', x);
SampleForAnnotationProcessor sample = SampleForAnnotationProcessorJni.get().bar(this);
boolean hasPhalange = SampleForAnnotationProcessorJni.get().hasPhalange();
String s = SampleForAnnotationProcessorJni.get().revString("abcd");
}
}
...@@ -59,7 +59,8 @@ _DEFAULT_TARGETS = [ ...@@ -59,7 +59,8 @@ _DEFAULT_TARGETS = [
'//chrome/android:chrome_sync_shell_test_apk', '//chrome/android:chrome_sync_shell_test_apk',
'//content/public/android:content_junit_tests', '//content/public/android:content_junit_tests',
'//content/shell/android:content_shell_apk', '//content/shell/android:content_shell_apk',
# Needed even with --all since it's a library. # Below must be included even with --all since they are libraries.
'//base/android/jni_generator:jni_processor',
'//tools/android/errorprone_plugin:errorprone_plugin_java', '//tools/android/errorprone_plugin:errorprone_plugin_java',
] ]
...@@ -952,10 +953,10 @@ def main(): ...@@ -952,10 +953,10 @@ def main():
data = _GenerateGradleFile( data = _GenerateGradleFile(
entry, generator, build_vars, source_properties, jinja_processor) entry, generator, build_vars, source_properties, jinja_processor)
if data and not args.all: if data and not args.all:
project_entries.append((entry.ProjectName(), entry.GradleSubdir())) project_entries.append((entry.ProjectName(), entry.GradleSubdir()))
_WriteFile( _WriteFile(
os.path.join(generator.EntryOutputDir(entry), _GRADLE_BUILD_FILE), os.path.join(generator.EntryOutputDir(entry), _GRADLE_BUILD_FILE),
data) data)
if args.all: if args.all:
project_entries.append((_MODULE_ALL, _MODULE_ALL)) project_entries.append((_MODULE_ALL, _MODULE_ALL))
_GenerateModuleAll( _GenerateModuleAll(
......
...@@ -24,6 +24,10 @@ java_prebuilt("guava_java") { ...@@ -24,6 +24,10 @@ java_prebuilt("guava_java") {
visibility = [ visibility = [
"//third_party/auto:*", "//third_party/auto:*",
"//third_party/robolectric:*", "//third_party/robolectric:*",
# jni_processor is a build tool even though it's in base.
"//base/android/jni_generator:jni_processor",
"//base/android/jni_generator:jni_processor__compile_java",
] ]
jar_path = "lib/guava.jar" jar_path = "lib/guava.jar"
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment