summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNarayan Kamath <narayan@google.com>2013-11-27 14:52:26 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2013-11-27 14:52:26 +0000
commit9ab926b5f7566d8e5cabc73cb69fdc214736e1bd (patch)
treee61a2e482bfb5a30bb89f4f117ad063eef7058f0
parent9660f096752d8c43e19beafd2595e46d09758b8b (diff)
parent6402794213ea82ac21dfcb24ef997ea102164f23 (diff)
downloadchromium_org-9ab926b5f7566d8e5cabc73cb69fdc214736e1bd.tar.gz
Merge "Update android generator to handle java7."
-rw-r--r--base/android/jni_generator/golden_sample_for_tests_jni.h2
-rwxr-xr-xbase/android/jni_generator/jni_generator.py104
-rwxr-xr-xbase/android/jni_generator/jni_generator_tests.py341
3 files changed, 333 insertions, 114 deletions
diff --git a/base/android/jni_generator/golden_sample_for_tests_jni.h b/base/android/jni_generator/golden_sample_for_tests_jni.h
index 2c5f6c0025..2767665935 100644
--- a/base/android/jni_generator/golden_sample_for_tests_jni.h
+++ b/base/android/jni_generator/golden_sample_for_tests_jni.h
@@ -3,7 +3,7 @@
// found in the LICENSE file.
// This file is autogenerated by
-// base/android/jni_generator/jni_generator_tests.py
+// base/android/jni_generator/jni_generator.py
// For
// org/chromium/example/jni_generator/SampleForTests
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py
index de865d527b..649182a9e9 100755
--- a/base/android/jni_generator/jni_generator.py
+++ b/base/android/jni_generator/jni_generator.py
@@ -53,7 +53,7 @@ class NativeMethod(object):
assert type(self.params) is list
assert type(self.params[0]) is Param
if (self.params and
- self.params[0].datatype == 'int' and
+ self.params[0].datatype == kwargs.get('ptr_type', 'int') and
self.params[0].name.startswith('native')):
self.type = 'method'
self.p0_type = self.params[0].name[len('native'):]
@@ -76,6 +76,7 @@ class CalledByNative(object):
self.name = kwargs['name']
self.params = kwargs['params']
self.method_id_var_name = kwargs.get('method_id_var_name', None)
+ self.signature = kwargs.get('signature')
self.is_constructor = kwargs.get('is_constructor', False)
self.env_call = GetEnvCall(self.is_constructor, self.static,
self.return_type)
@@ -141,6 +142,11 @@ class JniParams(object):
inner]
@staticmethod
+ def ParseJavaPSignature(signature_line):
+ prefix = 'Signature: '
+ return '"%s"' % signature_line[signature_line.index(prefix) + len(prefix):]
+
+ @staticmethod
def JavaToJni(param):
"""Converts a java param into a JNI signature type."""
pod_param_map = {
@@ -284,7 +290,7 @@ def ExtractFullyQualifiedJavaClassName(java_file_name, contents):
os.path.splitext(os.path.basename(java_file_name))[0])
-def ExtractNatives(contents):
+def ExtractNatives(contents, ptr_type):
"""Returns a list of dict containing information about a native method."""
contents = contents.replace('\n', '')
natives = []
@@ -301,7 +307,8 @@ def ExtractNatives(contents):
native_class_name=match.group('native_class_name'),
return_type=match.group('return_type'),
name=match.group('name').replace('native', ''),
- params=JniParams.Parse(match.group('params')))
+ params=JniParams.Parse(match.group('params')),
+ ptr_type=ptr_type)
natives += [native]
return natives
@@ -449,13 +456,16 @@ def ExtractCalledByNatives(contents):
class JNIFromJavaP(object):
"""Uses 'javap' to parse a .class file and generate the JNI header file."""
- def __init__(self, contents, namespace):
+ def __init__(self, contents, options):
self.contents = contents
- self.namespace = namespace
+ self.namespace = options.namespace
self.fully_qualified_class = re.match(
'.*?(class|interface) (?P<class_name>.*?)( |{)',
contents[1]).group('class_name')
self.fully_qualified_class = self.fully_qualified_class.replace('.', '/')
+ # Java 7's javap includes type parameters in output, like HashSet<T>. Strip
+ # away the <...> and use the raw class name that Java 6 would've given us.
+ self.fully_qualified_class = self.fully_qualified_class.split('<', 1)[0]
JniParams.SetFullyQualifiedClass(self.fully_qualified_class)
self.java_class_name = self.fully_qualified_class.split('/')[-1]
if not self.namespace:
@@ -463,7 +473,7 @@ class JNIFromJavaP(object):
re_method = re.compile('(?P<prefix>.*?)(?P<return_type>\S+?) (?P<name>\w+?)'
'\((?P<params>.*?)\)')
self.called_by_natives = []
- for content in contents[2:]:
+ for lineno, content in enumerate(contents[2:], 2):
match = re.match(re_method, content)
if not match:
continue
@@ -474,11 +484,12 @@ class JNIFromJavaP(object):
java_class_name='',
return_type=match.group('return_type').replace('.', '/'),
name=match.group('name'),
- params=JniParams.Parse(match.group('params').replace('.', '/')))]
- re_constructor = re.compile('.*? public ' +
+ params=JniParams.Parse(match.group('params').replace('.', '/')),
+ signature=JniParams.ParseJavaPSignature(contents[lineno + 1]))]
+ re_constructor = re.compile('(.*?)public ' +
self.fully_qualified_class.replace('/', '.') +
'\((?P<params>.*?)\)')
- for content in contents[2:]:
+ for lineno, content in enumerate(contents[2:], 2):
match = re.match(re_constructor, content)
if not match:
continue
@@ -490,41 +501,44 @@ class JNIFromJavaP(object):
return_type=self.fully_qualified_class,
name='Constructor',
params=JniParams.Parse(match.group('params').replace('.', '/')),
+ signature=JniParams.ParseJavaPSignature(contents[lineno + 1]),
is_constructor=True)]
self.called_by_natives = MangleCalledByNatives(self.called_by_natives)
self.inl_header_file_generator = InlHeaderFileGenerator(
- self.namespace, self.fully_qualified_class, [], self.called_by_natives)
+ self.namespace, self.fully_qualified_class, [],
+ self.called_by_natives, options)
def GetContent(self):
return self.inl_header_file_generator.GetContent()
@staticmethod
- def CreateFromClass(class_file, namespace):
+ def CreateFromClass(class_file, options):
class_name = os.path.splitext(os.path.basename(class_file))[0]
- p = subprocess.Popen(args=['javap', class_name],
+ p = subprocess.Popen(args=['javap', '-s', class_name],
cwd=os.path.dirname(class_file),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
stdout, _ = p.communicate()
- jni_from_javap = JNIFromJavaP(stdout.split('\n'), namespace)
+ jni_from_javap = JNIFromJavaP(stdout.split('\n'), options)
return jni_from_javap
class JNIFromJavaSource(object):
"""Uses the given java source file to generate the JNI header file."""
- def __init__(self, contents, fully_qualified_class):
+ def __init__(self, contents, fully_qualified_class, options):
contents = self._RemoveComments(contents)
JniParams.SetFullyQualifiedClass(fully_qualified_class)
JniParams.ExtractImportsAndInnerClasses(contents)
jni_namespace = ExtractJNINamespace(contents)
- natives = ExtractNatives(contents)
+ natives = ExtractNatives(contents, options.ptr_type)
called_by_natives = ExtractCalledByNatives(contents)
if len(natives) == 0 and len(called_by_natives) == 0:
raise SyntaxError('Unable to find any JNI methods for %s.' %
fully_qualified_class)
inl_header_file_generator = InlHeaderFileGenerator(
- jni_namespace, fully_qualified_class, natives, called_by_natives)
+ jni_namespace, fully_qualified_class, natives, called_by_natives,
+ options)
self.content = inl_header_file_generator.GetContent()
def _RemoveComments(self, contents):
@@ -549,24 +563,25 @@ class JNIFromJavaSource(object):
return self.content
@staticmethod
- def CreateFromFile(java_file_name):
+ def CreateFromFile(java_file_name, options):
contents = file(java_file_name).read()
fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name,
contents)
- return JNIFromJavaSource(contents, fully_qualified_class)
+ return JNIFromJavaSource(contents, fully_qualified_class, options)
class InlHeaderFileGenerator(object):
"""Generates an inline header file for JNI integration."""
def __init__(self, namespace, fully_qualified_class, natives,
- called_by_natives):
+ called_by_natives, options):
self.namespace = namespace
self.fully_qualified_class = fully_qualified_class
self.class_name = self.fully_qualified_class.split('/')[-1]
self.natives = natives
self.called_by_natives = called_by_natives
self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI'
+ self.script_name = options.script_name
def GetContent(self):
"""Returns the content of the JNI binding file."""
@@ -613,11 +628,8 @@ $REGISTER_NATIVES_IMPL
$CLOSE_NAMESPACE
#endif // ${HEADER_GUARD}
""")
- script_components = os.path.abspath(sys.argv[0]).split(os.path.sep)
- base_index = script_components.index('base')
- script_name = os.sep.join(script_components[base_index:])
values = {
- 'SCRIPT_NAME': script_name,
+ 'SCRIPT_NAME': self.script_name,
'FULLY_QUALIFIED_CLASS': self.fully_qualified_class,
'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(),
'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(),
@@ -928,14 +940,18 @@ jclass g_${JAVA_CLASS}_clazz = NULL;""")
if called_by_native.is_constructor:
jni_name = '<init>'
jni_return_type = 'void'
+ if called_by_native.signature:
+ signature = called_by_native.signature
+ else:
+ signature = JniParams.Signature(called_by_native.params,
+ jni_return_type,
+ True)
values = {
'JAVA_CLASS': called_by_native.java_class_name or self.class_name,
'JNI_NAME': jni_name,
'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE',
- 'JNI_SIGNATURE': JniParams.Signature(called_by_native.params,
- jni_return_type,
- True)
+ 'JNI_SIGNATURE': signature,
}
return template.substitute(values)
@@ -990,13 +1006,14 @@ def ExtractJarInputFile(jar_file, input_file, out_dir):
return extracted_file_name
-def GenerateJNIHeader(input_file, output_file, namespace, skip_if_same):
+def GenerateJNIHeader(input_file, output_file, options):
try:
if os.path.splitext(input_file)[1] == '.class':
- jni_from_javap = JNIFromJavaP.CreateFromClass(input_file, namespace)
+ jni_from_javap = JNIFromJavaP.CreateFromClass(input_file, options)
content = jni_from_javap.GetContent()
else:
- jni_from_java_source = JNIFromJavaSource.CreateFromFile(input_file)
+ jni_from_java_source = JNIFromJavaSource.CreateFromFile(
+ input_file, options)
content = jni_from_java_source.GetContent()
except ParseError, e:
print e
@@ -1004,7 +1021,7 @@ def GenerateJNIHeader(input_file, output_file, namespace, skip_if_same):
if output_file:
if not os.path.exists(os.path.dirname(os.path.abspath(output_file))):
os.makedirs(os.path.dirname(os.path.abspath(output_file)))
- if skip_if_same and os.path.exists(output_file):
+ if options.optimize_generation and os.path.exists(output_file):
with file(output_file, 'r') as f:
existing_content = f.read()
if existing_content == content:
@@ -1015,6 +1032,16 @@ def GenerateJNIHeader(input_file, output_file, namespace, skip_if_same):
print output
+def GetScriptName():
+ script_components = os.path.abspath(sys.argv[0]).split(os.path.sep)
+ base_index = 0
+ for idx, value in enumerate(script_components):
+ if value == 'base' or value == 'third_party':
+ base_index = idx
+ break
+ return os.sep.join(script_components[base_index:])
+
+
def main(argv):
usage = """usage: %prog [OPTIONS]
This script will parse the given java source code extracting the native
@@ -1044,12 +1071,24 @@ See SampleForTests.java for more details.
'not changed.')
option_parser.add_option('--jarjar',
help='Path to optional jarjar rules file.')
+ option_parser.add_option('--script_name', default=GetScriptName(),
+ help='The name of this script in the generated '
+ 'header.')
+ option_parser.add_option('--ptr_type', default='int',
+ type='choice', choices=['int', 'long'],
+ help='The type used to represent native pointers in '
+ 'Java code. For 32-bit, use int; '
+ 'for 64-bit, use long.')
options, args = option_parser.parse_args(argv)
if options.jar_file:
input_file = ExtractJarInputFile(options.jar_file, options.input_file,
options.output_dir)
- else:
+ elif options.input_file:
input_file = options.input_file
+ else:
+ option_parser.print_help()
+ print '\nError: Must specify --jar_file or --input_file.'
+ return 1
output_file = None
if options.output_dir:
root_name = os.path.splitext(os.path.basename(input_file))[0]
@@ -1057,8 +1096,7 @@ See SampleForTests.java for more details.
if options.jarjar:
with open(options.jarjar) as f:
JniParams.SetJarJarMappings(f.read())
- GenerateJNIHeader(input_file, output_file, options.namespace,
- options.optimize_generation)
+ GenerateJNIHeader(input_file, output_file, options)
if __name__ == '__main__':
diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py
index f008f394ce..cb325011ff 100755
--- a/base/android/jni_generator/jni_generator_tests.py
+++ b/base/android/jni_generator/jni_generator_tests.py
@@ -19,6 +19,18 @@ import jni_generator
from jni_generator import CalledByNative, JniParams, NativeMethod, Param
+SCRIPT_NAME = 'base/android/jni_generator/jni_generator.py'
+
+
+class TestOptions(object):
+ """The mock options object which is passed to the jni_generator.py script."""
+
+ def __init__(self):
+ self.namespace = None
+ self.script_name = SCRIPT_NAME
+ self.ptr_type = 'int'
+
+
class TestGenerator(unittest.TestCase):
def assertObjEquals(self, first, second):
dict_first = first.__dict__
@@ -84,7 +96,7 @@ class TestGenerator(unittest.TestCase):
double alpha, double beta, double gamma);
"""
jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
- natives = jni_generator.ExtractNatives(test_data)
+ natives = jni_generator.ExtractNatives(test_data, 'int')
golden_natives = [
NativeMethod(return_type='int', static=False,
name='Init',
@@ -206,14 +218,14 @@ class TestGenerator(unittest.TestCase):
]
self.assertListEquals(golden_natives, natives)
h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
- natives, [])
+ natives, [], TestOptions())
golden_content = """\
// Copyright (c) 2012 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.
// This file is autogenerated by
-// base/android/jni_generator/jni_generator_tests.py
+// base/android/jni_generator/jni_generator.py
// For
// org/chromium/TestJni
@@ -434,7 +446,7 @@ static bool RegisterNativesImpl(JNIEnv* env) {
private native int nativeInit();
}
"""
- natives = jni_generator.ExtractNatives(test_data)
+ natives = jni_generator.ExtractNatives(test_data, 'int')
golden_natives = [
NativeMethod(return_type='int', static=False,
name='Init', params=[],
@@ -443,14 +455,14 @@ static bool RegisterNativesImpl(JNIEnv* env) {
]
self.assertListEquals(golden_natives, natives)
h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
- natives, [])
+ natives, [], TestOptions())
golden_content = """\
// Copyright (c) 2012 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.
// This file is autogenerated by
-// base/android/jni_generator/jni_generator_tests.py
+// base/android/jni_generator/jni_generator.py
// For
// org/chromium/TestJni
@@ -517,7 +529,7 @@ static bool RegisterNativesImpl(JNIEnv* env) {
private native int nativeInit();
}
"""
- natives = jni_generator.ExtractNatives(test_data)
+ natives = jni_generator.ExtractNatives(test_data, 'int')
golden_natives = [
NativeMethod(return_type='int', static=False,
name='Init', params=[],
@@ -530,14 +542,14 @@ static bool RegisterNativesImpl(JNIEnv* env) {
]
self.assertListEquals(golden_natives, natives)
h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
- natives, [])
+ natives, [], TestOptions())
golden_content = """\
// Copyright (c) 2012 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.
// This file is autogenerated by
-// base/android/jni_generator/jni_generator_tests.py
+// base/android/jni_generator/jni_generator.py
// For
// org/chromium/TestJni
@@ -623,7 +635,7 @@ static bool RegisterNativesImpl(JNIEnv* env) {
}
}
"""
- natives = jni_generator.ExtractNatives(test_data)
+ natives = jni_generator.ExtractNatives(test_data, 'int')
golden_natives = [
NativeMethod(return_type='int', static=False,
name='Init', params=[],
@@ -636,14 +648,14 @@ static bool RegisterNativesImpl(JNIEnv* env) {
]
self.assertListEquals(golden_natives, natives)
h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
- natives, [])
+ natives, [], TestOptions())
golden_content = """\
// Copyright (c) 2012 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.
// This file is autogenerated by
-// base/android/jni_generator/jni_generator_tests.py
+// base/android/jni_generator/jni_generator.py
// For
// org/chromium/TestJni
@@ -1024,14 +1036,15 @@ static bool RegisterNativesImpl(JNIEnv* env) {
]
self.assertListEquals(golden_called_by_natives, called_by_natives)
h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
- [], called_by_natives)
+ [], called_by_natives,
+ TestOptions())
golden_content = """\
// Copyright (c) 2012 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.
// This file is autogenerated by
-// base/android/jni_generator/jni_generator_tests.py
+// base/android/jni_generator/jni_generator.py
// For
// org/chromium/TestJni
@@ -1566,23 +1579,137 @@ import org.chromium.base.BuildInfo;
datatype='java/lang/String'),],
'java/io/InputStream'))
+ def testFromJavaPGenerics(self):
+ contents = """
+public abstract class java.util.HashSet<T> extends java.util.AbstractSet<E>
+ implements java.util.Set<E>, java.lang.Cloneable, java.io.Serializable {
+ public void dummy();
+ Signature: ()V
+}
+"""
+ jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
+ TestOptions())
+ self.assertEquals(1, len(jni_from_javap.called_by_natives))
+ golden_content = """\
+// Copyright (c) 2012 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.
+
+// This file is autogenerated by
+// base/android/jni_generator/jni_generator.py
+// For
+// java/util/HashSet
+
+#ifndef java_util_HashSet_JNI
+#define java_util_HashSet_JNI
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+const char kHashSetClassPath[] = "java/util/HashSet";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_HashSet_clazz = NULL;
+} // namespace
+
+namespace JNI_HashSet {
+
+// Step 2: method stubs.
+
+static base::subtle::AtomicWord g_HashSet_dummy = 0;
+static void Java_HashSet_dummy(JNIEnv* env, jobject obj) __attribute__
+ ((unused));
+static void Java_HashSet_dummy(JNIEnv* env, jobject obj) {
+ /* Must call RegisterNativesImpl() */
+ DCHECK(g_HashSet_clazz);
+ jmethodID method_id =
+ base::android::MethodID::LazyGet<
+ base::android::MethodID::TYPE_INSTANCE>(
+ env, g_HashSet_clazz,
+ "dummy",
+"()V",
+ &g_HashSet_dummy);
+
+ env->CallVoidMethod(obj,
+ method_id);
+ base::android::CheckException(env);
+
+}
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+ g_HashSet_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+ base::android::GetClass(env, kHashSetClassPath).obj()));
+ return true;
+}
+} // namespace JNI_HashSet
+
+#endif // java_util_HashSet_JNI
+"""
+ self.assertTextEquals(golden_content, jni_from_javap.GetContent())
+
+ def testSnippnetJavap6_7(self):
+ content_javap6 = """
+public class java.util.HashSet {
+public boolean add(java.lang.Object);
+ Signature: (Ljava/lang/Object;)Z
+}
+"""
+
+ content_javap7 = """
+public class java.util.HashSet {
+public boolean add(E);
+ Signature: (Ljava/lang/Object;)Z
+}
+"""
+ jni_from_javap6 = jni_generator.JNIFromJavaP(content_javap6.split('\n'),
+ TestOptions())
+ jni_from_javap7 = jni_generator.JNIFromJavaP(content_javap7.split('\n'),
+ TestOptions())
+ self.assertTrue(jni_from_javap6.GetContent())
+ self.assertTrue(jni_from_javap7.GetContent())
+ # Ensure the javap7 is correctly parsed and uses the Signature field rather
+ # than the "E" parameter.
+ self.assertTextEquals(jni_from_javap6.GetContent(),
+ jni_from_javap7.GetContent())
+
def testFromJavaP(self):
contents = """
-public abstract class java.io.InputStream extends java.lang.Object
- implements java.io.Closeable{
- public java.io.InputStream();
- public int available() throws java.io.IOException;
- public void close() throws java.io.IOException;
- public void mark(int);
- public boolean markSupported();
- public abstract int read() throws java.io.IOException;
- public int read(byte[]) throws java.io.IOException;
- public int read(byte[], int, int) throws java.io.IOException;
- public synchronized void reset() throws java.io.IOException;
- public long skip(long) throws java.io.IOException;
+public abstract class java.io.InputStream extends
+ java.lang.Object implements java.io.Closeable{
+public java.io.InputStream();
+ Signature: ()V
+public int available() throws java.io.IOException;
+ Signature: ()I
+public void close() throws java.io.IOException;
+ Signature: ()V
+public void mark(int);
+ Signature: (I)V
+public boolean markSupported();
+ Signature: ()Z
+public abstract int read() throws java.io.IOException;
+ Signature: ()I
+public int read(byte[]) throws java.io.IOException;
+ Signature: ([B)I
+public int read(byte[], int, int) throws java.io.IOException;
+ Signature: ([BII)I
+public synchronized void reset() throws java.io.IOException;
+ Signature: ()V
+public long skip(long) throws java.io.IOException;
+ Signature: (J)J
}
"""
- jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'), None)
+ jni_from_javap = jni_generator.JNIFromJavaP(contents.split('\n'),
+ TestOptions())
self.assertEquals(10, len(jni_from_javap.called_by_natives))
golden_content = """\
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
@@ -1590,7 +1717,7 @@ public abstract class java.io.InputStream extends java.lang.Object
// found in the LICENSE file.
// This file is autogenerated by
-// base/android/jni_generator/jni_generator_tests.py
+// base/android/jni_generator/jni_generator.py
// For
// java/io/InputStream
@@ -1628,10 +1755,7 @@ static jint Java_InputStream_available(JNIEnv* env, jobject obj) {
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"available",
-
-"("
-")"
-"I",
+"()I",
&g_InputStream_available);
jint ret =
@@ -1652,10 +1776,7 @@ static void Java_InputStream_close(JNIEnv* env, jobject obj) {
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"close",
-
-"("
-")"
-"V",
+"()V",
&g_InputStream_close);
env->CallVoidMethod(obj,
@@ -1675,11 +1796,7 @@ static void Java_InputStream_mark(JNIEnv* env, jobject obj, jint p0) {
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"mark",
-
-"("
-"I"
-")"
-"V",
+"(I)V",
&g_InputStream_mark);
env->CallVoidMethod(obj,
@@ -1699,10 +1816,7 @@ static jboolean Java_InputStream_markSupported(JNIEnv* env, jobject obj) {
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"markSupported",
-
-"("
-")"
-"Z",
+"()Z",
&g_InputStream_markSupported);
jboolean ret =
@@ -1723,10 +1837,7 @@ static jint Java_InputStream_readI(JNIEnv* env, jobject obj) {
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"read",
-
-"("
-")"
-"I",
+"()I",
&g_InputStream_readI);
jint ret =
@@ -1747,11 +1858,7 @@ static jint Java_InputStream_readI_AB(JNIEnv* env, jobject obj, jbyteArray p0) {
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"read",
-
-"("
-"[B"
-")"
-"I",
+"([B)I",
&g_InputStream_readI_AB);
jint ret =
@@ -1777,13 +1884,7 @@ static jint Java_InputStream_readI_AB_I_I(JNIEnv* env, jobject obj, jbyteArray
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"read",
-
-"("
-"[B"
-"I"
-"I"
-")"
-"I",
+"([BII)I",
&g_InputStream_readI_AB_I_I);
jint ret =
@@ -1804,10 +1905,7 @@ static void Java_InputStream_reset(JNIEnv* env, jobject obj) {
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"reset",
-
-"("
-")"
-"V",
+"()V",
&g_InputStream_reset);
env->CallVoidMethod(obj,
@@ -1827,11 +1925,7 @@ static jlong Java_InputStream_skip(JNIEnv* env, jobject obj, jlong p0) {
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"skip",
-
-"("
-"J"
-")"
-"J",
+"(J)J",
&g_InputStream_skip);
jlong ret =
@@ -1852,10 +1946,7 @@ static ScopedJavaLocalRef<jobject> Java_InputStream_Constructor(JNIEnv* env) {
base::android::MethodID::TYPE_INSTANCE>(
env, g_InputStream_clazz,
"<init>",
-
-"("
-")"
-"V",
+"()V",
&g_InputStream_Constructor);
jobject ret =
@@ -1896,7 +1987,8 @@ static bool RegisterNativesImpl(JNIEnv* env) {
private native void nativeSyncSetupEnded(
int nativeAndroidSyncSetupFlowHandler);
"""
- jni_from_java = jni_generator.JNIFromJavaSource(test_data, 'foo/bar')
+ jni_from_java = jni_generator.JNIFromJavaSource(
+ test_data, 'foo/bar', TestOptions())
def testRaisesOnNonJNIMethod(self):
test_data = """
@@ -1907,7 +1999,7 @@ static bool RegisterNativesImpl(JNIEnv* env) {
"""
self.assertRaises(SyntaxError,
jni_generator.JNIFromJavaSource,
- test_data, 'foo/bar')
+ test_data, 'foo/bar', TestOptions())
def testJniSelfDocumentingExample(self):
script_dir = os.path.dirname(sys.argv[0])
@@ -1917,7 +2009,8 @@ static bool RegisterNativesImpl(JNIEnv* env) {
golden_content = file(os.path.join(script_dir,
'golden_sample_for_tests_jni.h')).read()
jni_from_java = jni_generator.JNIFromJavaSource(
- content, 'org/chromium/example/jni_generator/SampleForTests')
+ content, 'org/chromium/example/jni_generator/SampleForTests',
+ TestOptions())
self.assertTextEquals(golden_content, jni_from_java.GetContent())
def testNoWrappingPreprocessorLines(self):
@@ -1930,7 +2023,8 @@ static bool RegisterNativesImpl(JNIEnv* env) {
"""
jni_from_java = jni_generator.JNIFromJavaSource(
test_data, ('com/google/lookhowextremelylongiam/snarf/'
- 'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'))
+ 'icankeepthisupallday/ReallyLongClassNamesAreAllTheRage'),
+ TestOptions())
jni_lines = jni_from_java.GetContent().split('\n')
line = filter(lambda line: line.lstrip().startswith('#ifndef'),
jni_lines)[0]
@@ -1951,7 +2045,7 @@ static bool RegisterNativesImpl(JNIEnv* env) {
"""rule org.chromium.example.** com.test.@1
rule org.chromium.example2.** org.test2.@0""")
jni_from_java = jni_generator.JNIFromJavaSource(
- test_data, 'org/chromium/example/jni_generator/Example')
+ test_data, 'org/chromium/example/jni_generator/Example', TestOptions())
jni_generator.JniParams.SetJarJarMappings('')
golden_content = """\
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
@@ -1959,7 +2053,7 @@ static bool RegisterNativesImpl(JNIEnv* env) {
// found in the LICENSE file.
// This file is autogenerated by
-// base/android/jni_generator/jni_generator_tests.py
+// base/android/jni_generator/jni_generator.py
// For
// org/chromium/example/jni_generator/Example
@@ -2079,6 +2173,93 @@ class Foo {
self.assertTextEquals(
'[Ljava/nio/ByteBuffer;', JniParams.JavaToJni('java/nio/ByteBuffer[]'))
+ def testNativesLong(self):
+ test_options = TestOptions()
+ test_options.ptr_type = 'long'
+ test_data = """"
+ private native void nativeDestroy(long nativeChromeBrowserProvider);
+ """
+ jni_generator.JniParams.ExtractImportsAndInnerClasses(test_data)
+ natives = jni_generator.ExtractNatives(test_data, test_options.ptr_type)
+ golden_natives = [
+ NativeMethod(return_type='void', static=False, name='Destroy',
+ params=[Param(datatype='long',
+ name='nativeChromeBrowserProvider')],
+ java_class_name=None,
+ type='method',
+ p0_type='ChromeBrowserProvider',
+ ptr_type=test_options.ptr_type),
+ ]
+ self.assertListEquals(golden_natives, natives)
+ h = jni_generator.InlHeaderFileGenerator('', 'org/chromium/TestJni',
+ natives, [], test_options)
+ golden_content = """\
+// Copyright (c) 2012 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.
+
+// This file is autogenerated by
+// base/android/jni_generator/jni_generator.py
+// For
+// org/chromium/TestJni
+
+#ifndef org_chromium_TestJni_JNI
+#define org_chromium_TestJni_JNI
+
+#include <jni.h>
+
+#include "base/android/jni_android.h"
+#include "base/android/scoped_java_ref.h"
+#include "base/basictypes.h"
+#include "base/logging.h"
+
+using base::android::ScopedJavaLocalRef;
+
+// Step 1: forward declarations.
+namespace {
+const char kTestJniClassPath[] = "org/chromium/TestJni";
+// Leaking this jclass as we cannot use LazyInstance from some threads.
+jclass g_TestJni_clazz = NULL;
+} // namespace
+
+// Step 2: method stubs.
+static void Destroy(JNIEnv* env, jobject obj,
+ jlong nativeChromeBrowserProvider) {
+ DCHECK(nativeChromeBrowserProvider) << "Destroy";
+ ChromeBrowserProvider* native =
+ reinterpret_cast<ChromeBrowserProvider*>(nativeChromeBrowserProvider);
+ return native->Destroy(env, obj);
+}
+
+// Step 3: RegisterNatives.
+
+static bool RegisterNativesImpl(JNIEnv* env) {
+
+ g_TestJni_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
+ base::android::GetClass(env, kTestJniClassPath).obj()));
+ static const JNINativeMethod kMethodsTestJni[] = {
+ { "nativeDestroy",
+"("
+"J"
+")"
+"V", reinterpret_cast<void*>(Destroy) },
+ };
+ const int kMethodsTestJniSize = arraysize(kMethodsTestJni);
+
+ if (env->RegisterNatives(g_TestJni_clazz,
+ kMethodsTestJni,
+ kMethodsTestJniSize) < 0) {
+ LOG(ERROR) << "RegisterNatives failed in " << __FILE__;
+ return false;
+ }
+
+ return true;
+}
+
+#endif // org_chromium_TestJni_JNI
+"""
+ self.assertTextEquals(golden_content, h.GetContent())
+
if __name__ == '__main__':
unittest.main()