Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: base/android/jni_generator/jni_generator.py

Issue 1959583003: jni_generator: remove obsolete/unused features. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Undo whitespace change to reduce diff to golden files Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | base/android/jni_generator/jni_generator_tests.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Extracts native methods from a Java file and generates the JNI bindings. 6 """Extracts native methods from a Java file and generates the JNI bindings.
7 If you change this, please run and update the tests.""" 7 If you change this, please run and update the tests."""
8 8
9 import collections 9 import collections
10 import errno 10 import errno
(...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after
170 'void': '' 170 'void': ''
171 } 171 }
172 return java_pod_type_map.get(java_type, 'NULL') 172 return java_pod_type_map.get(java_type, 'NULL')
173 173
174 174
175 class JniParams(object): 175 class JniParams(object):
176 _imports = [] 176 _imports = []
177 _fully_qualified_class = '' 177 _fully_qualified_class = ''
178 _package = '' 178 _package = ''
179 _inner_classes = [] 179 _inner_classes = []
180 _remappings = []
181 _implicit_imports = [] 180 _implicit_imports = []
182 181
183 @staticmethod 182 @staticmethod
184 def SetFullyQualifiedClass(fully_qualified_class): 183 def SetFullyQualifiedClass(fully_qualified_class):
185 JniParams._fully_qualified_class = 'L' + fully_qualified_class 184 JniParams._fully_qualified_class = 'L' + fully_qualified_class
186 JniParams._package = '/'.join(fully_qualified_class.split('/')[:-1]) 185 JniParams._package = '/'.join(fully_qualified_class.split('/')[:-1])
187 186
188 @staticmethod 187 @staticmethod
189 def AddAdditionalImport(class_name): 188 def AddAdditionalImport(class_name):
190 assert class_name.endswith('.class') 189 assert class_name.endswith('.class')
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 while param[-2:] == '[]': 260 while param[-2:] == '[]':
262 prefix += '[' 261 prefix += '['
263 param = param[:-2] 262 param = param[:-2]
264 # Generic? 263 # Generic?
265 if '<' in param: 264 if '<' in param:
266 param = param[:param.index('<')] 265 param = param[:param.index('<')]
267 if param in pod_param_map: 266 if param in pod_param_map:
268 return prefix + pod_param_map[param] 267 return prefix + pod_param_map[param]
269 if '/' in param: 268 if '/' in param:
270 # Coming from javap, use the fully qualified param directly. 269 # Coming from javap, use the fully qualified param directly.
271 return prefix + 'L' + JniParams.RemapClassName(param) + ';' 270 return prefix + 'L' + param + ';'
272 271
273 for qualified_name in (object_param_list + 272 for qualified_name in (object_param_list +
274 [JniParams._fully_qualified_class] + 273 [JniParams._fully_qualified_class] +
275 JniParams._inner_classes): 274 JniParams._inner_classes):
276 if (qualified_name.endswith('/' + param) or 275 if (qualified_name.endswith('/' + param) or
277 qualified_name.endswith('$' + param.replace('.', '$')) or 276 qualified_name.endswith('$' + param.replace('.', '$')) or
278 qualified_name == 'L' + param): 277 qualified_name == 'L' + param):
279 return prefix + JniParams.RemapClassName(qualified_name) + ';' 278 return prefix + qualified_name + ';'
280 279
281 # Is it from an import? (e.g. referecing Class from import pkg.Class; 280 # Is it from an import? (e.g. referecing Class from import pkg.Class;
282 # note that referencing an inner class Inner from import pkg.Class.Inner 281 # note that referencing an inner class Inner from import pkg.Class.Inner
283 # is not supported). 282 # is not supported).
284 for qualified_name in JniParams._imports: 283 for qualified_name in JniParams._imports:
285 if qualified_name.endswith('/' + param): 284 if qualified_name.endswith('/' + param):
286 # Ensure it's not an inner class. 285 # Ensure it's not an inner class.
287 components = qualified_name.split('/') 286 components = qualified_name.split('/')
288 if len(components) > 2 and components[-2][0].isupper(): 287 if len(components) > 2 and components[-2][0].isupper():
289 raise SyntaxError('Inner class (%s) can not be imported ' 288 raise SyntaxError('Inner class (%s) can not be imported '
290 'and used by JNI (%s). Please import the outer ' 289 'and used by JNI (%s). Please import the outer '
291 'class and use Outer.Inner instead.' % 290 'class and use Outer.Inner instead.' %
292 (qualified_name, param)) 291 (qualified_name, param))
293 return prefix + JniParams.RemapClassName(qualified_name) + ';' 292 return prefix + qualified_name + ';'
294 293
295 # Is it an inner class from an outer class import? (e.g. referencing 294 # Is it an inner class from an outer class import? (e.g. referencing
296 # Class.Inner from import pkg.Class). 295 # Class.Inner from import pkg.Class).
297 if '.' in param: 296 if '.' in param:
298 components = param.split('.') 297 components = param.split('.')
299 outer = '/'.join(components[:-1]) 298 outer = '/'.join(components[:-1])
300 inner = components[-1] 299 inner = components[-1]
301 for qualified_name in JniParams._imports: 300 for qualified_name in JniParams._imports:
302 if qualified_name.endswith('/' + outer): 301 if qualified_name.endswith('/' + outer):
303 return (prefix + JniParams.RemapClassName(qualified_name) + 302 return (prefix + qualified_name + '$' + inner + ';')
304 '$' + inner + ';')
305 raise SyntaxError('Inner class (%s) can not be ' 303 raise SyntaxError('Inner class (%s) can not be '
306 'used directly by JNI. Please import the outer ' 304 'used directly by JNI. Please import the outer '
307 'class, probably:\n' 305 'class, probably:\n'
308 'import %s.%s;' % 306 'import %s.%s;' %
309 (param, JniParams._package.replace('/', '.'), 307 (param, JniParams._package.replace('/', '.'),
310 outer.replace('/', '.'))) 308 outer.replace('/', '.')))
311 309
312 JniParams._CheckImplicitImports(param) 310 JniParams._CheckImplicitImports(param)
313 311
314 # Type not found, falling back to same package as this class. 312 # Type not found, falling back to same package as this class.
315 return (prefix + 'L' + 313 return (prefix + 'L' + JniParams._package + '/' + param + ';')
316 JniParams.RemapClassName(JniParams._package + '/' + param) + ';')
317 314
318 @staticmethod 315 @staticmethod
319 def _CheckImplicitImports(param): 316 def _CheckImplicitImports(param):
320 # Ensure implicit imports, such as java.lang.*, are not being treated 317 # Ensure implicit imports, such as java.lang.*, are not being treated
321 # as being in the same package. 318 # as being in the same package.
322 if not JniParams._implicit_imports: 319 if not JniParams._implicit_imports:
323 # This file was generated from android.jar and lists 320 # This file was generated from android.jar and lists
324 # all classes that are implicitly imported. 321 # all classes that are implicitly imported.
325 with file(os.path.join(os.path.dirname(sys.argv[0]), 322 with file(os.path.join(os.path.dirname(sys.argv[0]),
326 'android_jar.classes'), 'r') as f: 323 'android_jar.classes'), 'r') as f:
(...skipping 30 matching lines...) Expand all
357 items = p.split(' ') 354 items = p.split(' ')
358 if 'final' in items: 355 if 'final' in items:
359 items.remove('final') 356 items.remove('final')
360 param = Param( 357 param = Param(
361 datatype=items[0], 358 datatype=items[0],
362 name=(items[1] if len(items) > 1 else 'p%s' % len(ret)), 359 name=(items[1] if len(items) > 1 else 'p%s' % len(ret)),
363 ) 360 )
364 ret += [param] 361 ret += [param]
365 return ret 362 return ret
366 363
367 @staticmethod
368 def RemapClassName(class_name):
369 """Remaps class names using the jarjar mapping table."""
370 for old, new in JniParams._remappings:
371 if old.endswith('**') and old[:-2] in class_name:
372 return class_name.replace(old[:-2], new, 1)
373 if '*' not in old and class_name.endswith(old):
374 return class_name.replace(old, new, 1)
375
376 return class_name
377
378 @staticmethod
379 def SetJarJarMappings(mappings):
380 """Parse jarjar mappings from a string."""
381 JniParams._remappings = []
382 for line in mappings.splitlines():
383 rule = line.split()
384 if rule[0] != 'rule':
385 continue
386 _, src, dest = rule
387 src = src.replace('.', '/')
388 dest = dest.replace('.', '/')
389 if src.endswith('**'):
390 src_real_name = src[:-2]
391 else:
392 assert not '*' in src
393 src_real_name = src
394
395 if dest.endswith('@0'):
396 JniParams._remappings.append((src, dest[:-2] + src_real_name))
397 elif dest.endswith('@1'):
398 assert '**' in src
399 JniParams._remappings.append((src, dest[:-2]))
400 else:
401 assert not '@' in dest
402 JniParams._remappings.append((src, dest))
403
404 364
405 def ExtractJNINamespace(contents): 365 def ExtractJNINamespace(contents):
406 re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') 366 re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)')
407 m = re.findall(re_jni_namespace, contents) 367 m = re.findall(re_jni_namespace, contents)
408 if not m: 368 if not m:
409 return '' 369 return ''
410 return m[0] 370 return m[0]
411 371
412 372
413 def ExtractFullyQualifiedJavaClassName(java_file_name, contents): 373 def ExtractFullyQualifiedJavaClassName(java_file_name, contents):
(...skipping 322 matching lines...) Expand 10 before | Expand all | Expand 10 after
736 def __init__(self, namespace, fully_qualified_class, natives, 696 def __init__(self, namespace, fully_qualified_class, natives,
737 called_by_natives, constant_fields, options): 697 called_by_natives, constant_fields, options):
738 self.namespace = namespace 698 self.namespace = namespace
739 self.fully_qualified_class = fully_qualified_class 699 self.fully_qualified_class = fully_qualified_class
740 self.class_name = self.fully_qualified_class.split('/')[-1] 700 self.class_name = self.fully_qualified_class.split('/')[-1]
741 self.natives = natives 701 self.natives = natives
742 self.called_by_natives = called_by_natives 702 self.called_by_natives = called_by_natives
743 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' 703 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI'
744 self.constant_fields = constant_fields 704 self.constant_fields = constant_fields
745 self.options = options 705 self.options = options
746 self.init_native = self.ExtractInitNative(options)
747 706
748 def ExtractInitNative(self, options):
749 for native in self.natives:
750 if options.jni_init_native_name == 'native' + native.name:
751 self.natives.remove(native)
752 return native
753 return None
754 707
755 def GetContent(self): 708 def GetContent(self):
756 """Returns the content of the JNI binding file.""" 709 """Returns the content of the JNI binding file."""
757 template = Template("""\ 710 template = Template("""\
758 // Copyright 2014 The Chromium Authors. All rights reserved. 711 // Copyright 2014 The Chromium Authors. All rights reserved.
759 // Use of this source code is governed by a BSD-style license that can be 712 // Use of this source code is governed by a BSD-style license that can be
760 // found in the LICENSE file. 713 // found in the LICENSE file.
761 714
762 715
763 // This file is autogenerated by 716 // This file is autogenerated by
764 // ${SCRIPT_NAME} 717 // ${SCRIPT_NAME}
765 // For 718 // For
766 // ${FULLY_QUALIFIED_CLASS} 719 // ${FULLY_QUALIFIED_CLASS}
767 720
768 #ifndef ${HEADER_GUARD} 721 #ifndef ${HEADER_GUARD}
769 #define ${HEADER_GUARD} 722 #define ${HEADER_GUARD}
770 723
771 #include <jni.h> 724 #include <jni.h>
772 725
773 ${INCLUDES} 726 ${INCLUDES}
774 727
775 #include "base/android/jni_int_wrapper.h" 728 #include "base/android/jni_int_wrapper.h"
776 729
777 // Step 1: forward declarations. 730 // Step 1: forward declarations.
778 namespace { 731 namespace {
779 $CLASS_PATH_DEFINITIONS 732 $CLASS_PATH_DEFINITIONS
780 $METHOD_ID_DEFINITIONS 733
781 } // namespace 734 } // namespace
782 735
783 $OPEN_NAMESPACE 736 $OPEN_NAMESPACE
784 737
785 $CONSTANT_FIELDS 738 $CONSTANT_FIELDS
786 739
787 // Step 2: method stubs. 740 // Step 2: method stubs.
788 $METHOD_STUBS 741 $METHOD_STUBS
789 742
790 // Step 3: RegisterNatives. 743 // Step 3: RegisterNatives.
791 $JNI_NATIVE_METHODS 744 $JNI_NATIVE_METHODS
792 $REGISTER_NATIVES 745 $REGISTER_NATIVES
793 $CLOSE_NAMESPACE 746 $CLOSE_NAMESPACE
794 $JNI_REGISTER_NATIVES 747
795 #endif // ${HEADER_GUARD} 748 #endif // ${HEADER_GUARD}
796 """) 749 """)
797 values = { 750 values = {
798 'SCRIPT_NAME': self.options.script_name, 751 'SCRIPT_NAME': self.options.script_name,
799 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, 752 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class,
800 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), 753 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(),
801 'METHOD_ID_DEFINITIONS': self.GetMethodIDDefinitionsString(),
802 'CONSTANT_FIELDS': self.GetConstantFieldsString(), 754 'CONSTANT_FIELDS': self.GetConstantFieldsString(),
803 'METHOD_STUBS': self.GetMethodStubsString(), 755 'METHOD_STUBS': self.GetMethodStubsString(),
804 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), 756 'OPEN_NAMESPACE': self.GetOpenNamespaceString(),
805 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(), 757 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(),
806 'REGISTER_NATIVES': self.GetRegisterNativesString(), 758 'REGISTER_NATIVES': self.GetRegisterNativesString(),
807 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), 759 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(),
808 'HEADER_GUARD': self.header_guard, 760 'HEADER_GUARD': self.header_guard,
809 'INCLUDES': self.GetIncludesString(), 761 'INCLUDES': self.GetIncludesString(),
810 'JNI_REGISTER_NATIVES': self.GetJNIRegisterNativesString()
811 } 762 }
812 return WrapOutput(template.substitute(values)) 763 return WrapOutput(template.substitute(values))
813 764
814 def GetClassPathDefinitionsString(self): 765 def GetClassPathDefinitionsString(self):
815 ret = [] 766 ret = []
816 ret += [self.GetClassPathDefinitions()] 767 ret += [self.GetClassPathDefinitions()]
817 return '\n'.join(ret) 768 return '\n'.join(ret)
818 769
819 def GetMethodIDDefinitionsString(self):
820 """Returns the definition of method ids for the called by native methods."""
821 if not self.options.eager_called_by_natives:
822 return ''
823 template = Template("""\
824 jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = NULL;""")
825 ret = []
826 for called_by_native in self.called_by_natives:
827 values = {
828 'JAVA_CLASS': called_by_native.java_class_name or self.class_name,
829 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
830 }
831 ret += [template.substitute(values)]
832 return '\n'.join(ret)
833
834 def GetConstantFieldsString(self): 770 def GetConstantFieldsString(self):
835 if not self.constant_fields: 771 if not self.constant_fields:
836 return '' 772 return ''
837 ret = ['enum Java_%s_constant_fields {' % self.class_name] 773 ret = ['enum Java_%s_constant_fields {' % self.class_name]
838 for c in self.constant_fields: 774 for c in self.constant_fields:
839 ret += [' %s = %s,' % (c.name, c.value)] 775 ret += [' %s = %s,' % (c.name, c.value)]
840 ret += ['};'] 776 ret += ['};']
841 return '\n'.join(ret) 777 return '\n'.join(ret)
842 778
843 def GetMethodStubsString(self): 779 def GetMethodStubsString(self):
844 """Returns the code corresponding to method stubs.""" 780 """Returns the code corresponding to method stubs."""
845 ret = [] 781 ret = []
846 for native in self.natives: 782 for native in self.natives:
847 ret += [self.GetNativeStub(native)] 783 ret += [self.GetNativeStub(native)]
848 if self.options.eager_called_by_natives: 784 ret += self.GetLazyCalledByNativeMethodStubs()
849 ret += self.GetEagerCalledByNativeMethodStubs()
850 else:
851 ret += self.GetLazyCalledByNativeMethodStubs()
852 return '\n'.join(ret) 785 return '\n'.join(ret)
853 786
854 def GetLazyCalledByNativeMethodStubs(self): 787 def GetLazyCalledByNativeMethodStubs(self):
855 return [self.GetLazyCalledByNativeMethodStub(called_by_native) 788 return [self.GetLazyCalledByNativeMethodStub(called_by_native)
856 for called_by_native in self.called_by_natives] 789 for called_by_native in self.called_by_natives]
857 790
858 def GetEagerCalledByNativeMethodStubs(self):
859 ret = []
860 if self.called_by_natives:
861 ret += ['namespace {']
862 for called_by_native in self.called_by_natives:
863 ret += [self.GetEagerCalledByNativeMethodStub(called_by_native)]
864 ret += ['} // namespace']
865 return ret
866
867 def GetIncludesString(self): 791 def GetIncludesString(self):
868 if not self.options.includes: 792 if not self.options.includes:
869 return '' 793 return ''
870 includes = self.options.includes.split(',') 794 includes = self.options.includes.split(',')
871 return '\n'.join('#include "%s"' % x for x in includes) 795 return '\n'.join('#include "%s"' % x for x in includes)
872 796
873 def GetKMethodsString(self, clazz): 797 def GetKMethodsString(self, clazz):
874 ret = [] 798 ret = []
875 for native in self.natives: 799 for native in self.natives:
876 if (native.java_class_name == clazz or 800 if (native.java_class_name == clazz or
(...skipping 19 matching lines...) Expand all
896 """Returns the implementation of the array of native methods.""" 820 """Returns the implementation of the array of native methods."""
897 if self.options.native_exports and not self.options.native_exports_optional: 821 if self.options.native_exports and not self.options.native_exports_optional:
898 return '' 822 return ''
899 template = Template("""\ 823 template = Template("""\
900 static const JNINativeMethod kMethods${JAVA_CLASS}[] = { 824 static const JNINativeMethod kMethods${JAVA_CLASS}[] = {
901 ${KMETHODS} 825 ${KMETHODS}
902 }; 826 };
903 """) 827 """)
904 return self.SubstituteNativeMethods(template) 828 return self.SubstituteNativeMethods(template)
905 829
906 def GetRegisterCalledByNativesImplString(self):
907 """Returns the code for registering the called by native methods."""
908 if not self.options.eager_called_by_natives:
909 return ''
910 template = Template("""\
911 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = ${GET_METHOD_ID_IMPL}
912 if (g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} == NULL) {
913 return false;
914 }
915 """)
916 ret = []
917 for called_by_native in self.called_by_natives:
918 values = {
919 'JAVA_CLASS': called_by_native.java_class_name or self.class_name,
920 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
921 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native),
922 }
923 ret += [template.substitute(values)]
924 return '\n'.join(ret)
925
926 def GetRegisterNativesString(self): 830 def GetRegisterNativesString(self):
927 """Returns the code for RegisterNatives.""" 831 """Returns the code for RegisterNatives."""
928 template = Template("""\ 832 template = Template("""\
929 ${REGISTER_NATIVES_SIGNATURE} { 833 ${REGISTER_NATIVES_SIGNATURE} {
930 ${EARLY_EXIT} 834 ${EARLY_EXIT}
931 ${CLASSES} 835 ${CLASSES}
932 ${NATIVES} 836 ${NATIVES}
933 ${CALLED_BY_NATIVES}
934 return true; 837 return true;
935 } 838 }
936 """) 839 """)
937 signature = 'static bool RegisterNativesImpl(JNIEnv* env' 840 signature = 'static bool RegisterNativesImpl(JNIEnv* env)'
938 if self.init_native:
939 signature += ', jclass clazz)'
940 else:
941 signature += ')'
942
943 early_exit = '' 841 early_exit = ''
944 if self.options.native_exports_optional: 842 if self.options.native_exports_optional:
945 early_exit = """\ 843 early_exit = """\
946 if (base::android::IsManualJniRegistrationDisabled()) return true; 844 if (base::android::IsManualJniRegistrationDisabled()) return true;
947 """ 845 """
948 846
949 natives = self.GetRegisterNativesImplString() 847 natives = self.GetRegisterNativesImplString()
950 called_by_natives = self.GetRegisterCalledByNativesImplString()
951 values = {'REGISTER_NATIVES_SIGNATURE': signature, 848 values = {'REGISTER_NATIVES_SIGNATURE': signature,
952 'EARLY_EXIT': early_exit, 849 'EARLY_EXIT': early_exit,
953 'CLASSES': self.GetFindClasses(), 850 'CLASSES': self.GetFindClasses(),
954 'NATIVES': natives, 851 'NATIVES': natives,
955 'CALLED_BY_NATIVES': called_by_natives,
956 } 852 }
957 return template.substitute(values) 853 return template.substitute(values)
958 854
959 def GetRegisterNativesImplString(self): 855 def GetRegisterNativesImplString(self):
960 """Returns the shared implementation for RegisterNatives.""" 856 """Returns the shared implementation for RegisterNatives."""
961 if self.options.native_exports and not self.options.native_exports_optional: 857 if self.options.native_exports and not self.options.native_exports_optional:
962 return '' 858 return ''
963 859
964 template = Template("""\ 860 template = Template("""\
965 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); 861 const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS});
966 862
967 if (env->RegisterNatives(${JAVA_CLASS}_clazz(env), 863 if (env->RegisterNatives(${JAVA_CLASS}_clazz(env),
968 kMethods${JAVA_CLASS}, 864 kMethods${JAVA_CLASS},
969 kMethods${JAVA_CLASS}Size) < 0) { 865 kMethods${JAVA_CLASS}Size) < 0) {
970 jni_generator::HandleRegistrationError( 866 jni_generator::HandleRegistrationError(
971 env, ${JAVA_CLASS}_clazz(env), __FILE__); 867 env, ${JAVA_CLASS}_clazz(env), __FILE__);
972 return false; 868 return false;
973 } 869 }
974 """) 870 """)
975 return self.SubstituteNativeMethods(template) 871 return self.SubstituteNativeMethods(template)
976 872
977 def GetJNIRegisterNativesString(self):
978 """Returns the implementation for the JNI registration of native methods."""
979 if not self.init_native:
980 return ''
981
982 template = Template("""\
983 extern "C" JNIEXPORT bool JNICALL
984 Java_${FULLY_QUALIFIED_CLASS}_${INIT_NATIVE_NAME}(JNIEnv* env, jclass clazz) {
985 return ${NAMESPACE}RegisterNativesImpl(env, clazz);
986 }
987 """)
988
989 if self.options.native_exports:
990 java_name = JniParams.RemapClassName(self.fully_qualified_class)
991 java_name = java_name.replace('_', '_1').replace('/', '_')
992 else:
993 java_name = self.fully_qualified_class.replace('/', '_')
994
995 namespace = ''
996 if self.namespace:
997 namespace = self.namespace + '::'
998 values = {'FULLY_QUALIFIED_CLASS': java_name,
999 'INIT_NATIVE_NAME': 'native' + self.init_native.name,
1000 'NAMESPACE': namespace,
1001 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString()
1002 }
1003 return template.substitute(values)
1004
1005 def GetOpenNamespaceString(self): 873 def GetOpenNamespaceString(self):
1006 if self.namespace: 874 if self.namespace:
1007 all_namespaces = ['namespace %s {' % ns 875 all_namespaces = ['namespace %s {' % ns
1008 for ns in self.namespace.split('::')] 876 for ns in self.namespace.split('::')]
1009 return '\n'.join(all_namespaces) 877 return '\n'.join(all_namespaces)
1010 return '' 878 return ''
1011 879
1012 def GetCloseNamespaceString(self): 880 def GetCloseNamespaceString(self):
1013 if self.namespace: 881 if self.namespace:
1014 all_namespaces = ['} // namespace %s' % ns 882 all_namespaces = ['} // namespace %s' % ns
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 """Return the name of the stub function for this native method. 938 """Return the name of the stub function for this native method.
1071 939
1072 Args: 940 Args:
1073 native: the native dictionary describing the method. 941 native: the native dictionary describing the method.
1074 942
1075 Returns: 943 Returns:
1076 A string with the stub function name (used by the JVM). 944 A string with the stub function name (used by the JVM).
1077 """ 945 """
1078 template = Template("Java_${JAVA_NAME}_native${NAME}") 946 template = Template("Java_${JAVA_NAME}_native${NAME}")
1079 947
1080 java_name = JniParams.RemapClassName(self.fully_qualified_class) 948 java_name = self.fully_qualified_class.replace('_', '_1').replace('/', '_')
1081 java_name = java_name.replace('_', '_1').replace('/', '_')
1082 if native.java_class_name: 949 if native.java_class_name:
1083 java_name += '_00024' + native.java_class_name 950 java_name += '_00024' + native.java_class_name
1084 951
1085 values = {'NAME': native.name, 952 values = {'NAME': native.name,
1086 'JAVA_NAME': java_name} 953 'JAVA_NAME': java_name}
1087 return template.substitute(values) 954 return template.substitute(values)
1088 955
1089 def GetJavaParamRefForCall(self, c_type, name): 956 def GetJavaParamRefForCall(self, c_type, name):
1090 return Template('JavaParamRef<${TYPE}>(env, ${NAME})').substitute({ 957 return Template('JavaParamRef<${TYPE}>(env, ${NAME})').substitute({
1091 'TYPE': c_type, 958 'TYPE': c_type,
1092 'NAME': name, 959 'NAME': name,
1093 }) 960 })
1094 961
1095 def GetJNIFirstParamForCall(self, native): 962 def GetJNIFirstParamForCall(self, native):
1096 c_type = self.GetJNIFirstParamType(native) 963 c_type = self.GetJNIFirstParamType(native)
1097 return [self.GetJavaParamRefForCall(c_type, 'jcaller')] 964 return [self.GetJavaParamRefForCall(c_type, 'jcaller')]
1098 965
1099 def GetNativeStub(self, native): 966 def GetNativeStub(self, native):
1100 is_method = native.type == 'method' 967 is_method = native.type == 'method'
1101 968
1102 if is_method: 969 if is_method:
1103 params = native.params[1:] 970 params = native.params[1:]
1104 else: 971 else:
1105 params = native.params 972 params = native.params
1106 params_in_call = [] 973 params_in_call = ['env'] + self.GetJNIFirstParamForCall(native)
1107 if not self.options.pure_native_methods:
1108 params_in_call = ['env'] + self.GetJNIFirstParamForCall(native)
1109 for p in params: 974 for p in params:
1110 c_type = JavaDataTypeToC(p.datatype) 975 c_type = JavaDataTypeToC(p.datatype)
1111 if re.match(RE_SCOPED_JNI_TYPES, c_type): 976 if re.match(RE_SCOPED_JNI_TYPES, c_type):
1112 params_in_call.append(self.GetJavaParamRefForCall(c_type, p.name)) 977 params_in_call.append(self.GetJavaParamRefForCall(c_type, p.name))
1113 else: 978 else:
1114 params_in_call.append(p.name) 979 params_in_call.append(p.name)
1115 params_in_call = ', '.join(params_in_call) 980 params_in_call = ', '.join(params_in_call)
1116 981
1117 if self.options.native_exports: 982 if self.options.native_exports:
1118 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n' 983 stub_visibility = 'extern "C" __attribute__((visibility("default")))\n'
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1220 'PRE_CALL': pre_call, 1085 'PRE_CALL': pre_call,
1221 'POST_CALL': post_call, 1086 'POST_CALL': post_call,
1222 'ENV_CALL': called_by_native.env_call, 1087 'ENV_CALL': called_by_native.env_call,
1223 'FIRST_PARAM_IN_CALL': first_param_in_call, 1088 'FIRST_PARAM_IN_CALL': first_param_in_call,
1224 'PARAMS_IN_CALL': params_in_call, 1089 'PARAMS_IN_CALL': params_in_call,
1225 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 1090 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
1226 'CHECK_EXCEPTION': check_exception, 1091 'CHECK_EXCEPTION': check_exception,
1227 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native) 1092 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native)
1228 } 1093 }
1229 1094
1230 def GetEagerCalledByNativeMethodStub(self, called_by_native):
1231 """Returns the implementation of the called by native method."""
1232 template = Template("""
1233 static ${RETURN_TYPE} ${METHOD_ID_VAR_NAME}(\
1234 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION}) {
1235 ${RETURN_DECLARATION}${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL},
1236 g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}${PARAMS_IN_CALL})${POST_CALL};
1237 ${RETURN_CLAUSE}
1238 }""")
1239 values = self.GetCalledByNativeValues(called_by_native)
1240 return template.substitute(values)
1241 1095
1242 def GetLazyCalledByNativeMethodStub(self, called_by_native): 1096 def GetLazyCalledByNativeMethodStub(self, called_by_native):
1243 """Returns a string.""" 1097 """Returns a string."""
1244 function_signature_template = Template("""\ 1098 function_signature_template = Template("""\
1245 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ 1099 static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\
1246 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") 1100 JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""")
1247 function_header_template = Template("""\ 1101 function_header_template = Template("""\
1248 ${FUNCTION_SIGNATURE} {""") 1102 ${FUNCTION_SIGNATURE} {""")
1249 function_header_with_unused_template = Template("""\ 1103 function_header_with_unused_template = Template("""\
1250 ${FUNCTION_SIGNATURE} __attribute__ ((unused)); 1104 ${FUNCTION_SIGNATURE} __attribute__ ((unused));
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
1303 called_by_native_classes = self.GetUniqueClasses(self.called_by_natives) 1157 called_by_native_classes = self.GetUniqueClasses(self.called_by_natives)
1304 if self.options.native_exports: 1158 if self.options.native_exports:
1305 all_classes = called_by_native_classes 1159 all_classes = called_by_native_classes
1306 else: 1160 else:
1307 all_classes = native_classes 1161 all_classes = native_classes
1308 all_classes.update(called_by_native_classes) 1162 all_classes.update(called_by_native_classes)
1309 1163
1310 for clazz in all_classes: 1164 for clazz in all_classes:
1311 values = { 1165 values = {
1312 'JAVA_CLASS': clazz, 1166 'JAVA_CLASS': clazz,
1313 'JNI_CLASS_PATH': JniParams.RemapClassName(all_classes[clazz]), 1167 'JNI_CLASS_PATH': all_classes[clazz],
1314 } 1168 }
1315 ret += [template.substitute(values)] 1169 ret += [template.substitute(values)]
1316 ret += '' 1170 ret += ''
1317 1171
1318 class_getter_methods = [] 1172 class_getter_methods = []
1319 if self.options.native_exports: 1173 if self.options.native_exports:
1320 template = Template("""\ 1174 template = Template("""\
1321 // Leaking this jclass as we cannot use LazyInstance from some threads. 1175 // Leaking this jclass as we cannot use LazyInstance from some threads.
1322 base::subtle::AtomicWord g_${JAVA_CLASS}_clazz __attribute__((unused)) = 0; 1176 base::subtle::AtomicWord g_${JAVA_CLASS}_clazz __attribute__((unused)) = 0;
1323 #define ${JAVA_CLASS}_clazz(env) \ 1177 #define ${JAVA_CLASS}_clazz(env) \
1324 base::android::LazyGetClass(env, k${JAVA_CLASS}ClassPath, \ 1178 base::android::LazyGetClass(env, k${JAVA_CLASS}ClassPath, \
1325 &g_${JAVA_CLASS}_clazz)""") 1179 &g_${JAVA_CLASS}_clazz)""")
1326 else: 1180 else:
1327 template = Template("""\ 1181 template = Template("""\
1328 // Leaking this jclass as we cannot use LazyInstance from some threads. 1182 // Leaking this jclass as we cannot use LazyInstance from some threads.
1329 jclass g_${JAVA_CLASS}_clazz = NULL; 1183 jclass g_${JAVA_CLASS}_clazz = NULL;
1330 #define ${JAVA_CLASS}_clazz(env) g_${JAVA_CLASS}_clazz""") 1184 #define ${JAVA_CLASS}_clazz(env) g_${JAVA_CLASS}_clazz""")
1331 1185
1332 for clazz in called_by_native_classes: 1186 for clazz in called_by_native_classes:
1333 values = { 1187 values = {
1334 'JAVA_CLASS': clazz, 1188 'JAVA_CLASS': clazz,
1335 } 1189 }
1336 ret += [template.substitute(values)] 1190 ret += [template.substitute(values)]
1337 1191
1338 return '\n'.join(ret) 1192 return '\n'.join(ret)
1339 1193
1340 def GetFindClasses(self): 1194 def GetFindClasses(self):
1341 """Returns the imlementation of FindClass for all known classes.""" 1195 """Returns the imlementation of FindClass for all known classes."""
1342 if self.init_native: 1196 if self.options.native_exports:
1343 if self.options.native_exports: 1197 return '\n'
1344 template = Template("""\ 1198 template = Template("""\
1345 base::subtle::Release_Store(&g_${JAVA_CLASS}_clazz,
1346 static_cast<base::subtle::AtomicWord>(env->NewWeakGlobalRef(clazz));""")
1347 else:
1348 template = Template("""\
1349 g_${JAVA_CLASS}_clazz = static_cast<jclass>(env->NewWeakGlobalRef(clazz));""")
1350 else:
1351 if self.options.native_exports:
1352 return '\n'
1353 template = Template("""\
1354 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( 1199 g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef(
1355 base::android::GetClass(env, k${JAVA_CLASS}ClassPath).obj()));""") 1200 base::android::GetClass(env, k${JAVA_CLASS}ClassPath).obj()));""")
1356 ret = [] 1201 ret = []
1357 for clazz in self.GetUniqueClasses(self.called_by_natives): 1202 for clazz in self.GetUniqueClasses(self.called_by_natives):
1358 values = {'JAVA_CLASS': clazz} 1203 values = {'JAVA_CLASS': clazz}
1359 ret += [template.substitute(values)] 1204 ret += [template.substitute(values)]
1360 return '\n'.join(ret) 1205 return '\n'.join(ret)
1361 1206
1362 def GetMethodIDImpl(self, called_by_native): 1207 def GetMethodIDImpl(self, called_by_native):
1363 """Returns the implementation of GetMethodID.""" 1208 """Returns the implementation of GetMethodID."""
1364 if self.options.eager_called_by_natives: 1209 template = Template("""\
1365 template = Template("""\
1366 env->Get${STATIC_METHOD_PART}MethodID(
1367 ${JAVA_CLASS}_clazz(env),
1368 "${JNI_NAME}", ${JNI_SIGNATURE});""")
1369 else:
1370 template = Template("""\
1371 base::android::MethodID::LazyGet< 1210 base::android::MethodID::LazyGet<
1372 base::android::MethodID::TYPE_${STATIC}>( 1211 base::android::MethodID::TYPE_${STATIC}>(
1373 env, ${JAVA_CLASS}_clazz(env), 1212 env, ${JAVA_CLASS}_clazz(env),
1374 "${JNI_NAME}", 1213 "${JNI_NAME}",
1375 ${JNI_SIGNATURE}, 1214 ${JNI_SIGNATURE},
1376 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); 1215 &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME});
1377 """) 1216 """)
1378 jni_name = called_by_native.name 1217 jni_name = called_by_native.name
1379 jni_return_type = called_by_native.return_type 1218 jni_return_type = called_by_native.return_type
1380 if called_by_native.is_constructor: 1219 if called_by_native.is_constructor:
1381 jni_name = '<init>' 1220 jni_name = '<init>'
1382 jni_return_type = 'void' 1221 jni_return_type = 'void'
1383 if called_by_native.signature: 1222 if called_by_native.signature:
1384 signature = called_by_native.signature 1223 signature = called_by_native.signature
1385 else: 1224 else:
1386 signature = JniParams.Signature(called_by_native.params, 1225 signature = JniParams.Signature(called_by_native.params,
1387 jni_return_type, 1226 jni_return_type,
1388 True) 1227 True)
1389 values = { 1228 values = {
1390 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, 1229 'JAVA_CLASS': called_by_native.java_class_name or self.class_name,
1391 'JNI_NAME': jni_name, 1230 'JNI_NAME': jni_name,
1392 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 1231 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name,
1393 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', 1232 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE',
1394 'STATIC_METHOD_PART': 'Static' if called_by_native.static else '',
1395 'JNI_SIGNATURE': signature, 1233 'JNI_SIGNATURE': signature,
1396 } 1234 }
1397 return template.substitute(values) 1235 return template.substitute(values)
1398 1236
1399 1237
1400 def WrapOutput(output): 1238 def WrapOutput(output):
1401 ret = [] 1239 ret = []
1402 for line in output.splitlines(): 1240 for line in output.splitlines():
1403 # Do not wrap lines under 80 characters or preprocessor directives. 1241 # Do not wrap lines under 80 characters or preprocessor directives.
1404 if len(line) < 80 or line.lstrip()[:1] == '#': 1242 if len(line) < 80 or line.lstrip()[:1] == '#':
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1506 help='Single input file name. The output file name ' 1344 help='Single input file name. The output file name '
1507 'will be derived from it. Must be used with ' 1345 'will be derived from it. Must be used with '
1508 '--output_dir.') 1346 '--output_dir.')
1509 option_parser.add_option('--output_dir', 1347 option_parser.add_option('--output_dir',
1510 help='The output directory. Must be used with ' 1348 help='The output directory. Must be used with '
1511 '--input') 1349 '--input')
1512 option_parser.add_option('--optimize_generation', type="int", 1350 option_parser.add_option('--optimize_generation', type="int",
1513 default=0, help='Whether we should optimize JNI ' 1351 default=0, help='Whether we should optimize JNI '
1514 'generation by not regenerating files if they have ' 1352 'generation by not regenerating files if they have '
1515 'not changed.') 1353 'not changed.')
1516 option_parser.add_option('--jarjar',
1517 help='Path to optional jarjar rules file.')
1518 option_parser.add_option('--script_name', default=GetScriptName(), 1354 option_parser.add_option('--script_name', default=GetScriptName(),
1519 help='The name of this script in the generated ' 1355 help='The name of this script in the generated '
1520 'header.') 1356 'header.')
1521 option_parser.add_option('--includes', 1357 option_parser.add_option('--includes',
1522 help='The comma-separated list of header files to ' 1358 help='The comma-separated list of header files to '
1523 'include in the generated header.') 1359 'include in the generated header.')
1524 option_parser.add_option('--pure_native_methods',
1525 action='store_true', dest='pure_native_methods',
1526 help='When true, the native methods will be called '
1527 'without any JNI-specific arguments.')
1528 option_parser.add_option('--ptr_type', default='int', 1360 option_parser.add_option('--ptr_type', default='int',
1529 type='choice', choices=['int', 'long'], 1361 type='choice', choices=['int', 'long'],
1530 help='The type used to represent native pointers in ' 1362 help='The type used to represent native pointers in '
1531 'Java code. For 32-bit, use int; ' 1363 'Java code. For 32-bit, use int; '
1532 'for 64-bit, use long.') 1364 'for 64-bit, use long.')
1533 option_parser.add_option('--jni_init_native_name', default='',
1534 help='The name of the JNI registration method that '
1535 'is used to initialize all native methods. If a '
1536 'method with this name is not present in the Java '
1537 'source file, setting this option is a no-op. When '
1538 'a method with this name is found however, the '
1539 'naming convention Java_<packageName>_<className> '
1540 'will limit the initialization to only the '
1541 'top-level class.')
1542 option_parser.add_option('--eager_called_by_natives',
1543 action='store_true', dest='eager_called_by_natives',
1544 help='When true, the called-by-native methods will '
1545 'be initialized in a non-atomic way.')
1546 option_parser.add_option('--cpp', default='cpp', 1365 option_parser.add_option('--cpp', default='cpp',
1547 help='The path to cpp command.') 1366 help='The path to cpp command.')
1548 option_parser.add_option('--javap', default='javap', 1367 option_parser.add_option('--javap', default='javap',
1549 help='The path to javap command.') 1368 help='The path to javap command.')
1550 option_parser.add_option('--native_exports', action='store_true', 1369 option_parser.add_option('--native_exports', action='store_true',
1551 help='Native method registration through .so ' 1370 help='Native method registration through .so '
1552 'exports.') 1371 'exports.')
1553 option_parser.add_option('--native_exports_optional', action='store_true', 1372 option_parser.add_option('--native_exports_optional', action='store_true',
1554 help='Support both explicit and native method' 1373 help='Support both explicit and native method'
1555 'registration.') 1374 'registration.')
1556 options, args = option_parser.parse_args(argv) 1375 options, args = option_parser.parse_args(argv)
1557 if options.native_exports_optional: 1376 if options.native_exports_optional:
1558 options.native_exports = True 1377 options.native_exports = True
1559 if options.jar_file: 1378 if options.jar_file:
1560 input_file = ExtractJarInputFile(options.jar_file, options.input_file, 1379 input_file = ExtractJarInputFile(options.jar_file, options.input_file,
1561 options.output_dir) 1380 options.output_dir)
1562 elif options.input_file: 1381 elif options.input_file:
1563 input_file = options.input_file 1382 input_file = options.input_file
1564 else: 1383 else:
1565 option_parser.print_help() 1384 option_parser.print_help()
1566 print '\nError: Must specify --jar_file or --input_file.' 1385 print '\nError: Must specify --jar_file or --input_file.'
1567 return 1 1386 return 1
1568 output_file = None 1387 output_file = None
1569 if options.output_dir: 1388 if options.output_dir:
1570 root_name = os.path.splitext(os.path.basename(input_file))[0] 1389 root_name = os.path.splitext(os.path.basename(input_file))[0]
1571 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' 1390 output_file = os.path.join(options.output_dir, root_name) + '_jni.h'
1572 if options.jarjar:
1573 with open(options.jarjar) as f:
1574 JniParams.SetJarJarMappings(f.read())
1575 GenerateJNIHeader(input_file, output_file, options) 1391 GenerateJNIHeader(input_file, output_file, options)
1576 1392
1577 if options.depfile: 1393 if options.depfile:
1578 build_utils.WriteDepfile( 1394 build_utils.WriteDepfile(
1579 options.depfile, 1395 options.depfile,
1580 build_utils.GetPythonDependencies()) 1396 build_utils.GetPythonDependencies())
1581 1397
1582 1398
1583 if __name__ == '__main__': 1399 if __name__ == '__main__':
1584 sys.exit(main(sys.argv)) 1400 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « no previous file | base/android/jni_generator/jni_generator_tests.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698