| Index: base/android/jni_generator/jni_generator.py
 | 
| diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py
 | 
| index 35a75101088c076c421a274dd9637830968eb2b3..5018cf53531bb205d79e7c5fc91d232abe90312a 100755
 | 
| --- a/base/android/jni_generator/jni_generator.py
 | 
| +++ b/base/android/jni_generator/jni_generator.py
 | 
| @@ -793,6 +793,8 @@ jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = NULL;""")
 | 
|      for native in self.natives:
 | 
|        if native.type != 'method':
 | 
|          ret += [self.GetForwardDeclaration(native)]
 | 
| +    if self.options.native_exports and ret:
 | 
| +      return '\nextern "C" {\n' + "\n".join(ret) + '\n};  // extern "C"'
 | 
|      return '\n'.join(ret)
 | 
|  
 | 
|    def GetConstantFieldsString(self):
 | 
| @@ -814,6 +816,9 @@ jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = NULL;""")
 | 
|        ret += self.GetEagerCalledByNativeMethodStubs()
 | 
|      else:
 | 
|        ret += self.GetLazyCalledByNativeMethodStubs()
 | 
| +
 | 
| +    if self.options.native_exports and ret:
 | 
| +      return '\nextern "C" {\n' + "\n".join(ret) + '\n};  // extern "C"'
 | 
|      return '\n'.join(ret)
 | 
|  
 | 
|    def GetLazyCalledByNativeMethodStubs(self):
 | 
| @@ -859,6 +864,8 @@ jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = NULL;""")
 | 
|  
 | 
|    def GetJNINativeMethodsString(self):
 | 
|      """Returns the implementation of the array of native methods."""
 | 
| +    if self.options.native_exports:
 | 
| +      return ''
 | 
|      template = Template("""\
 | 
|  static const JNINativeMethod kMethods${JAVA_CLASS}[] = {
 | 
|  ${KMETHODS}
 | 
| @@ -913,6 +920,9 @@ ${CALLED_BY_NATIVES}
 | 
|  
 | 
|    def GetRegisterNativesImplString(self):
 | 
|      """Returns the shared implementation for RegisterNatives."""
 | 
| +    if self.options.native_exports:
 | 
| +      return ''
 | 
| +
 | 
|      template = Template("""\
 | 
|    const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS});
 | 
|  
 | 
| @@ -937,11 +947,17 @@ Java_${FULLY_QUALIFIED_CLASS}_${INIT_NATIVE_NAME}(JNIEnv* env, jclass clazz) {
 | 
|    return ${NAMESPACE}RegisterNativesImpl(env, clazz);
 | 
|  }
 | 
|  """)
 | 
| -    fully_qualified_class = self.fully_qualified_class.replace('/', '_')
 | 
| +
 | 
| +    if self.options.native_exports:
 | 
| +      java_name = JniParams.RemapClassName(self.fully_qualified_class)
 | 
| +      java_name = java_name.replace('_', '_1').replace('/', '_')
 | 
| +    else:
 | 
| +      java_name = self.fully_qualified_class.replace('/', '_')
 | 
| +
 | 
|      namespace = ''
 | 
|      if self.namespace:
 | 
|        namespace = self.namespace + '::'
 | 
| -    values = {'FULLY_QUALIFIED_CLASS': fully_qualified_class,
 | 
| +    values = {'FULLY_QUALIFIED_CLASS': java_name,
 | 
|                'INIT_NATIVE_NAME': 'native' + self.init_native.name,
 | 
|                'NAMESPACE': namespace,
 | 
|                'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString()
 | 
| @@ -995,23 +1011,52 @@ Java_${FULLY_QUALIFIED_CLASS}_${INIT_NATIVE_NAME}(JNIEnv* env, jclass clazz) {
 | 
|          for param in called_by_native.params])
 | 
|  
 | 
|    def GetForwardDeclaration(self, native):
 | 
| -    template = Template("""
 | 
| +    template_str = """
 | 
|  static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS});
 | 
| -""")
 | 
| +"""
 | 
| +    if self.options.native_exports:
 | 
| +      template_str += """
 | 
| +__attribute__((visibility("default")))
 | 
| +${RETURN} Java_${JAVA_NAME}_native${NAME}(JNIEnv* env, ${PARAMS}) {
 | 
| +  return ${NAME}(${PARAMS_IN_CALL});
 | 
| +}
 | 
| +"""
 | 
| +    template = Template(template_str)
 | 
| +    params_in_call = []
 | 
| +    if not self.options.pure_native_methods:
 | 
| +      params_in_call = ['env', 'jcaller']
 | 
| +    params_in_call = ', '.join(params_in_call + [p.name for p in native.params])
 | 
| +
 | 
| +    java_name = JniParams.RemapClassName(self.fully_qualified_class)
 | 
| +    java_name = java_name.replace('_', '_1').replace('/', '_')
 | 
| +    if native.java_class_name:
 | 
| +      java_name += '_00024' + native.java_class_name
 | 
| +
 | 
|      values = {'RETURN': JavaDataTypeToC(native.return_type),
 | 
|                'NAME': native.name,
 | 
| -              'PARAMS': self.GetParamsInDeclaration(native)}
 | 
| +              'JAVA_NAME': java_name,
 | 
| +              'PARAMS': self.GetParamsInDeclaration(native),
 | 
| +              'PARAMS_IN_CALL': params_in_call}
 | 
|      return template.substitute(values)
 | 
|  
 | 
|    def GetNativeMethodStubString(self, native):
 | 
|      """Returns stubs for native methods."""
 | 
| -    template = Template("""\
 | 
| -static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) {
 | 
| +    if self.options.native_exports:
 | 
| +      template_str = """\
 | 
| +__attribute__((visibility("default")))
 | 
| +${RETURN} Java_${JAVA_NAME}_native${NAME}(JNIEnv* env,
 | 
| +    ${PARAMS_IN_DECLARATION}) {"""
 | 
| +    else:
 | 
| +      template_str = """\
 | 
| +static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) {"""
 | 
| +    template_str += """
 | 
|    ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME});
 | 
|    CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN});
 | 
|    return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL};
 | 
|  }
 | 
| -""")
 | 
| +"""
 | 
| +
 | 
| +    template = Template(template_str)
 | 
|      params = []
 | 
|      if not self.options.pure_native_methods:
 | 
|        params = ['env', 'jcaller']
 | 
| @@ -1024,9 +1069,19 @@ static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) {
 | 
|      post_call = ''
 | 
|      if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type):
 | 
|        post_call = '.Release()'
 | 
| +
 | 
| +    if self.options.native_exports:
 | 
| +      java_name = JniParams.RemapClassName(self.fully_qualified_class)
 | 
| +      java_name = java_name.replace('_', '_1').replace('/', '_')
 | 
| +      if native.java_class_name:
 | 
| +        java_name += '_00024' + native.java_class_name
 | 
| +    else:
 | 
| +      java_name = ''
 | 
| +
 | 
|      values = {
 | 
|          'RETURN': return_type,
 | 
|          'OPTIONAL_ERROR_RETURN': optional_error_return,
 | 
| +        'JAVA_NAME': java_name,
 | 
|          'NAME': native.name,
 | 
|          'PARAMS_IN_DECLARATION': self.GetParamsInDeclaration(native),
 | 
|          'PARAM0_NAME': native.params[0].name,
 | 
| @@ -1174,8 +1229,12 @@ ${FUNCTION_HEADER}
 | 
|  const char k${JAVA_CLASS}ClassPath[] = "${JNI_CLASS_PATH}";""")
 | 
|      native_classes = self.GetUniqueClasses(self.natives)
 | 
|      called_by_native_classes = self.GetUniqueClasses(self.called_by_natives)
 | 
| -    all_classes = native_classes
 | 
| -    all_classes.update(called_by_native_classes)
 | 
| +    if self.options.native_exports:
 | 
| +      all_classes = called_by_native_classes
 | 
| +    else:
 | 
| +      all_classes = native_classes
 | 
| +      all_classes.update(called_by_native_classes)
 | 
| +
 | 
|      for clazz in all_classes:
 | 
|        values = {
 | 
|            'JAVA_CLASS': clazz,
 | 
| @@ -1394,6 +1453,9 @@ See SampleForTests.java for more details.
 | 
|                             help='The path to cpp command.')
 | 
|    option_parser.add_option('--javap', default='javap',
 | 
|                             help='The path to javap command.')
 | 
| +  option_parser.add_option('--native_exports', action='store_true',
 | 
| +                           help='Native method registration through .so '
 | 
| +                           'exports.')
 | 
|    options, args = option_parser.parse_args(argv)
 | 
|    if options.jar_file:
 | 
|      input_file = ExtractJarInputFile(options.jar_file, options.input_file,
 | 
| 
 |