Commit a48308c6 authored by Andrew Grieve's avatar Andrew Grieve Committed by Commit Bot

Android: Simplify GEN_JNI.java generation (no behavior change)

Rather than generating a different ${Foo}Jni class for every
target when use_hashed_jni_names=true, also have classes use
org.chromium.base.natives.GEN_JNI.

Then, at the final step, have GEN_JNI forward calls to J.N.$HASH.

Makes a bit more work for R8 (it needs to inline all the GEN_JNI
methods), but move the "hashed functions" logic to live in
one spot at the end of the pipeline.

A byproduct of this is that toggling use_hashed_jni_names no
long requires all libraries to be recompiled (attached bug)

Bug: 1073921
Change-Id: I8df7c751b51d60e878f270c06e2e979dd9dbc821
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2162109Reviewed-by: default avatarMichael Thiessen <mthiesse@chromium.org>
Commit-Queue: Andrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#762036}
parent 1651709a
......@@ -82,12 +82,6 @@ group("jni_generator_tests") {
]
}
java_cpp_template("processor_args_java") {
package_path = "org/chromium/jni_generator"
sources = [ "ProcessorArgs.template" ]
defines = [ "HASH_JNI_NAMES_VALUE=$use_hashed_jni_names" ]
}
java_annotation_processor("jni_processor") {
sources = [
"java/src/org/chromium/jni_generator/JniProcessor.java",
......@@ -110,6 +104,4 @@ java_annotation_processor("jni_processor") {
"//third_party/android_deps:com_squareup_javapoet_java",
"//third_party/android_deps:javax_annotation_jsr250_api_java",
]
srcjar_deps = [ ":processor_args_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.jni_generator;
class ProcessorArgs {
public static final boolean HASH_JNI_NAMES = HASH_JNI_NAMES_VALUE;
}
// 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.natives;
// This file is autogenerated by
// base/android/jni_generator/jni_registration_generator.py
// Please do not change its content.
public class GEN_JNI {
public static final boolean TESTING_ENABLED = false;
public static final boolean REQUIRE_MOCK = false;
public static void org_chromium_example_jni_1generator_SampleForAnnotationProcessor_foo() {
J.N.MygCV2jQ();
}
public static Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_bar(Object sample) {
return J.N.MHuqnmXT(sample);
}
public static String org_chromium_example_jni_1generator_SampleForAnnotationProcessor_revString(String stringToReverse) {
return J.N.MM5Xkwyy(stringToReverse);
}
public static String[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_sendToNative(String[] strs) {
return J.N.MAC2QhR9(strs);
}
public static Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_sendSamplesToNative(Object[] strs) {
return J.N.MGhRh4Nd(strs);
}
public static boolean org_chromium_example_jni_1generator_SampleForAnnotationProcessor_hasPhalange() {
return J.N.MW0aEs4h();
}
public static int[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_testAllPrimitives(int zint, int[] ints, long zlong, long[] longs, short zshort, short[] shorts, char zchar, char[] chars, byte zbyte, byte[] bytes, double zdouble, double[] doubles, float zfloat, float[] floats, boolean zbool, boolean[] bools) {
return J.N.MlVFI4RX(zint, ints, zlong, longs, zshort, shorts, zchar, chars, zbyte, bytes, zdouble, doubles, zfloat, floats, zbool, bools);
}
public static void org_chromium_example_jni_1generator_SampleForAnnotationProcessor_testSpecialTypes(Class clazz, Class[] classes, Throwable throwable, Throwable[] throwables, String string, String[] strings, Object tStruct, Object[] structs, Object obj, Object[] objects) {
J.N.MqOnlud7(clazz, classes, throwable, throwables, string, strings, tStruct, structs, obj, objects);
}
public static Throwable org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnThrowable() {
return J.N.MuZc76Vt();
}
public static Throwable[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnThrowables() {
return J.N.MAD53J7V();
}
public static Class org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnClass() {
return J.N.M$ZgOi4g();
}
public static Class[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnClasses() {
return J.N.M$hL1577();
}
public static String org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnString() {
return J.N.M0k1OjBK();
}
public static String[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnStrings() {
return J.N.Mssfs54E();
}
public static Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnStruct() {
return J.N.MSzcel_H();
}
public static Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnStructs() {
return J.N.MIBrQLK4();
}
public static Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObject() {
return J.N.M$hPywjv();
}
public static Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObjects() {
return J.N.MPpCU1l5();
}
}
......@@ -2,50 +2,48 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.base.natives;
package J;
// This file is autogenerated by
// base/android/jni_generator/jni_registration_generator.py
// Please do not change its content.
public class GEN_JNI {
public static final boolean TESTING_ENABLED = false;
public static final boolean REQUIRE_MOCK = false;
public class N {
public static native void org_chromium_example_jni_1generator_SampleForAnnotationProcessor_foo();
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_bar(Object sample);
public static native void MygCV2jQ();
public static native String org_chromium_example_jni_1generator_SampleForAnnotationProcessor_revString(String stringToReverse);
public static native Object MHuqnmXT(Object sample);
public static native String[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_sendToNative(String[] strs);
public static native String MM5Xkwyy(String stringToReverse);
public static native Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_sendSamplesToNative(Object[] strs);
public static native String[] MAC2QhR9(String[] strs);
public static native boolean org_chromium_example_jni_1generator_SampleForAnnotationProcessor_hasPhalange();
public static native Object[] MGhRh4Nd(Object[] strs);
public static native int[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_testAllPrimitives(int zint, int[] ints, long zlong, long[] longs, short zshort, short[] shorts, char zchar, char[] chars, byte zbyte, byte[] bytes, double zdouble, double[] doubles, float zfloat, float[] floats, boolean zbool, boolean[] bools);
public static native boolean MW0aEs4h();
public static native void org_chromium_example_jni_1generator_SampleForAnnotationProcessor_testSpecialTypes(Class clazz, Class[] classes, Throwable throwable, Throwable[] throwables, String string, String[] strings, Object tStruct, Object[] structs, Object obj, Object[] objects);
public static native int[] MlVFI4RX(int zint, int[] ints, long zlong, long[] longs, short zshort, short[] shorts, char zchar, char[] chars, byte zbyte, byte[] bytes, double zdouble, double[] doubles, float zfloat, float[] floats, boolean zbool, boolean[] bools);
public static native Throwable org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnThrowable();
public static native void MqOnlud7(Class clazz, Class[] classes, Throwable throwable, Throwable[] throwables, String string, String[] strings, Object tStruct, Object[] structs, Object obj, Object[] objects);
public static native Throwable[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnThrowables();
public static native Throwable MuZc76Vt();
public static native Class org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnClass();
public static native Throwable[] MAD53J7V();
public static native Class[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnClasses();
public static native Class M$ZgOi4g();
public static native String org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnString();
public static native Class[] M$hL1577();
public static native String[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnStrings();
public static native String M0k1OjBK();
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnStruct();
public static native String[] Mssfs54E();
public static native Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnStructs();
public static native Object MSzcel_H();
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObject();
public static native Object[] MIBrQLK4();
public static native Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObjects();
public static native Object M$hPywjv();
public static native Object[] MPpCU1l5();
}
......@@ -12,6 +12,7 @@ public class GEN_JNI {
public static final boolean TESTING_ENABLED = false;
public static final boolean REQUIRE_MOCK = false;
public static native void org_chromium_example_jni_1generator_SampleForAnnotationProcessor_foo();
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_bar(Object sample);
......@@ -47,5 +48,4 @@ public class GEN_JNI {
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObject();
public static native Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObjects();
}
......@@ -12,6 +12,7 @@ public class GEN_JNI {
public static final boolean TESTING_ENABLED = true;
public static final boolean REQUIRE_MOCK = false;
public static native void org_chromium_example_jni_1generator_SampleForAnnotationProcessor_foo();
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_bar(Object sample);
......@@ -47,5 +48,4 @@ public class GEN_JNI {
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObject();
public static native Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObjects();
}
......@@ -12,6 +12,7 @@ public class GEN_JNI {
public static final boolean TESTING_ENABLED = true;
public static final boolean REQUIRE_MOCK = true;
public static native void org_chromium_example_jni_1generator_SampleForAnnotationProcessor_foo();
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_bar(Object sample);
......@@ -47,5 +48,4 @@ public class GEN_JNI {
public static native Object org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObject();
public static native Object[] org_chromium_example_jni_1generator_SampleForAnnotationProcessor_returnObjects();
}
......@@ -12,10 +12,10 @@ public class GEN_JNI {
public static final boolean TESTING_ENABLED = false;
public static final boolean REQUIRE_MOCK = false;
public static native void org_chromium_example_SampleProxyJni_foo(long nativePtr);
public static native int org_chromium_example_SampleProxyJni_bar(int x, int y);
public static native String org_chromium_example_SampleProxyJni_foobar(String x, String y);
}
......@@ -5,7 +5,6 @@
package org.chromium.jni_generator;
import com.google.auto.service.AutoService;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
......@@ -26,10 +25,7 @@ import org.chromium.base.annotations.CheckDiscard;
import org.chromium.base.annotations.MainDex;
import org.chromium.base.annotations.NativeMethods;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.Map;
import java.util.Set;
......@@ -68,16 +64,14 @@ public class JniProcessor extends AbstractProcessor {
private static final Class<NativeMethods> JNI_STATIC_NATIVES_CLASS = NativeMethods.class;
private static final Class<MainDex> MAIN_DEX_CLASS = MainDex.class;
private static final Class<CheckDiscard> CHECK_DISCARD_CLASS = CheckDiscard.class;
private static final Class<NativeLibraryLoadedStatus> JNI_STATUS_CLASS =
NativeLibraryLoadedStatus.class;
private static final String CHECK_DISCARD_CRBUG = "crbug.com/993421";
private static final String NATIVE_WRAPPER_CLASS_POSTFIX = "Jni";
// The native class name and package name used in debug.
private String mNativeClassStr = "GEN_JNI";
private String mNativeClassPackage = "org.chromium.base.natives";
private ClassName mNativeClassName;
private static final ClassName GEN_JNI_CLASS_NAME =
ClassName.get("org.chromium.base.natives", "GEN_JNI");
private static final ClassName JNI_STATUS_CLASS_NAME =
ClassName.get(NativeLibraryLoadedStatus.class);
static final String NATIVE_TEST_FIELD_NAME = "TESTING_ENABLED";
static final String NATIVE_REQUIRE_MOCK_FIELD_NAME = "REQUIRE_MOCK";
......@@ -85,14 +79,6 @@ public class JniProcessor extends AbstractProcessor {
// Builder for NativeClass which will hold all our native method declarations.
private TypeSpec.Builder mNativesBuilder;
// Hash function for native method names.
private static MessageDigest sNativeMethodHashFunction;
// Limits the number characters of the Base64 encoded hash
// of the method descriptor used as name of the generated
// native method in GEN_JNI (prefixed with "M")
private static final int MAX_CHARS_FOR_HASHED_NATIVE_METHODS = 8;
// Types that are non-primitives and should not be
// casted to objects in native method declarations.
static final ImmutableSet JNI_OBJECT_TYPE_EXCEPTIONS =
......@@ -113,14 +99,6 @@ public class JniProcessor extends AbstractProcessor {
}
public JniProcessor() {
// If non-debug we use shorter names to save space.
if (ProcessorArgs.HASH_JNI_NAMES) {
// J.N
mNativeClassPackage = "J";
mNativeClassStr = "N";
}
mNativeClassName = ClassName.get(mNativeClassPackage, mNativeClassStr);
FieldSpec.Builder testingFlagBuilder =
FieldSpec.builder(TypeName.BOOLEAN, NATIVE_TEST_FIELD_NAME)
.addModifiers(Modifier.STATIC, Modifier.PUBLIC);
......@@ -129,19 +107,12 @@ public class JniProcessor extends AbstractProcessor {
.addModifiers(Modifier.STATIC, Modifier.PUBLIC);
// State of mNativesBuilder needs to be preserved between processing rounds.
mNativesBuilder = TypeSpec.classBuilder(mNativeClassName)
mNativesBuilder = TypeSpec.classBuilder(GEN_JNI_CLASS_NAME)
.addAnnotation(createAnnotationWithValue(
Generated.class, JniProcessor.class.getCanonicalName()))
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
.addField(testingFlagBuilder.build())
.addField(throwFlagBuilder.build());
try {
sNativeMethodHashFunction = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
// MD5 support is required for all Java platforms so this should never happen.
printError(e.getMessage());
}
}
/**
......@@ -223,7 +194,8 @@ public class JniProcessor extends AbstractProcessor {
// provided elsewhere.
if (!processingEnv.getOptions().containsKey(SKIP_GEN_JNI_ARG)) {
JavaFile nativeClassFile =
JavaFile.builder(mNativeClassPackage, mNativesBuilder.build()).build();
JavaFile.builder(GEN_JNI_CLASS_NAME.packageName(), mNativesBuilder.build())
.build();
nativeClassFile.writeTo(processingEnv.getFiler());
}
......@@ -253,24 +225,9 @@ public class JniProcessor extends AbstractProcessor {
String getNativeMethodName(String packageName, String className, String oldMethodName) {
// e.g. org.chromium.base.Foo_Class.bar
// => org_chromium_base_Foo_1Class_bar()
String descriptor = String.format("%s.%s.%s", packageName, className, oldMethodName)
return String.format("%s.%s.%s", packageName, className, oldMethodName)
.replaceAll("_", "_1")
.replaceAll("\\.", "_");
if (ProcessorArgs.HASH_JNI_NAMES) {
// Must start with a character.
byte[] hash = sNativeMethodHashFunction.digest(descriptor.getBytes(Charsets.UTF_8));
String methodName = "M"
+ Base64.getEncoder()
.encodeToString(hash)
.replace("/", "_")
.replace("+", "$")
.replace("=", "");
return methodName.substring(
0, Math.min(MAX_CHARS_FOR_HASHED_NATIVE_METHODS, methodName.length()));
}
return descriptor;
}
/**
......@@ -411,18 +368,17 @@ public class JniProcessor extends AbstractProcessor {
MethodSpec.methodBuilder("get")
.addModifiers(Modifier.PUBLIC, Modifier.STATIC)
.returns(nativeInterfaceType)
.beginControlFlow("if ($T.$N)", mNativeClassName, NATIVE_TEST_FIELD_NAME)
.beginControlFlow("if ($T.$N)", GEN_JNI_CLASS_NAME, NATIVE_TEST_FIELD_NAME)
.beginControlFlow("if ($N != null)", testTarget)
.addStatement("return $N", testTarget)
.endControlFlow()
.beginControlFlow(
"if ($T.$N)", mNativeClassName, NATIVE_REQUIRE_MOCK_FIELD_NAME)
"if ($T.$N)", GEN_JNI_CLASS_NAME, NATIVE_REQUIRE_MOCK_FIELD_NAME)
.addStatement("throw new UnsupportedOperationException($S)",
noMockExceptionString)
.endControlFlow()
.endControlFlow()
.addStatement("$T.$N($L)", ClassName.get(JNI_STATUS_CLASS), "checkLoaded",
isMainDex)
.addStatement("$T.$N($L)", JNI_STATUS_CLASS_NAME, "checkLoaded", isMainDex)
.addStatement("return new $N()", name)
.build();
......@@ -445,7 +401,7 @@ public class JniProcessor extends AbstractProcessor {
.addModifiers(Modifier.PUBLIC)
.addAnnotation(Override.class)
.addParameter(nativeInterfaceType, "instance")
.beginControlFlow("if (!$T.$N)", mNativeClassName, NATIVE_TEST_FIELD_NAME)
.beginControlFlow("if (!$T.$N)", GEN_JNI_CLASS_NAME, NATIVE_TEST_FIELD_NAME)
.addStatement(
"throw new RuntimeException($S)", mocksNotEnabledExceptionString)
.endControlFlow()
......@@ -495,7 +451,7 @@ public class JniProcessor extends AbstractProcessor {
}
// Make call to native function.
builder.addCode("$T.$N(", mNativeClassName, staticNativeMethod);
builder.addCode("$T.$N(", GEN_JNI_CLASS_NAME, staticNativeMethod);
// Add params to native call.
ArrayList<String> paramNames = new ArrayList<>();
......@@ -529,10 +485,8 @@ public class JniProcessor extends AbstractProcessor {
/**
* Since some types may decay to objects in the native method
* this method returns a javadoc string that contains the
* type information from the old method. The fully qualified
* descriptor of the method is also included since the name
* may be hashed.
*/
* type information from the old method.
**/
String createNativeMethodJavadocString(ClassName outerType, ExecutableElement oldMethod) {
ArrayList<String> docLines = new ArrayList<>();
......
......@@ -138,6 +138,8 @@ class NativeMethod(object):
self.name = self.name[0].upper() + self.name[1:]
self.proxy_name = kwargs.get('proxy_name', self.name)
# Non-hashed proxy name if applicable.
self.proxy_name_orig = None
if self.params:
assert type(self.params) is list
......@@ -469,10 +471,6 @@ class JniParams(object):
index = signature_line.index(prefix)
return '"%s"' % signature_line[index + len(prefix):]
@staticmethod
def MakeProxyParamSignature(params):
return ', '.join('%s %s' % (p.datatype, p.name) for p in params)
@staticmethod
def Parse(params, use_proxy_types=False):
"""Parses the params into a list of Param objects."""
......@@ -969,22 +967,15 @@ class JNIFromJavaP(object):
# declaration in another class (org.chromium.base.natives.GEN_JNI)
# but generates wrapper code so it can be called through the declaring class.
class ProxyHelpers(object):
NATIVE_PROXY_CLASS_NAME = 'GEN_JNI'
NATIVE_PROXY_PACKAGE_NAME = 'org/chromium/base/natives'
MAX_CHARS_FOR_HASHED_NATIVE_METHODS = 8
@staticmethod
def GetClass(use_hash):
if use_hash:
return 'N'
return ProxyHelpers.NATIVE_PROXY_CLASS_NAME
return 'N' if use_hash else 'GEN_JNI'
@staticmethod
def GetPackage(use_hash):
if use_hash:
return 'J'
return ProxyHelpers.NATIVE_PROXY_PACKAGE_NAME
return 'J' if use_hash else 'org/chromium/base/natives'
@staticmethod
def GetQualifiedClass(use_hash):
......@@ -1009,9 +1000,8 @@ class ProxyHelpers(object):
def CreateProxyMethodName(fully_qualified_class, old_name, use_hash=False):
"""Returns the literal method name for the corresponding proxy method"""
if use_hash:
hashed_name = ProxyHelpers.CreateHashedMethodName(fully_qualified_class,
return ProxyHelpers.CreateHashedMethodName(fully_qualified_class,
old_name)
return hashed_name
# The annotation processor currently uses a method name
# org_chromium_example_foo_method_1name escaping _ to _1
......@@ -1045,6 +1035,9 @@ class ProxyHelpers(object):
is_proxy=True,
proxy_name=unescaped_proxy_name,
ptr_type=ptr_type)
if use_hash:
native.proxy_name_orig = ProxyHelpers.CreateProxyMethodName(
fully_qualified_class, name, False)
methods.append(native)
return methods
......@@ -1753,8 +1746,7 @@ See SampleForTests.java for more details.
'--use_proxy_hash',
action='store_true',
help='Hashes the native declaration of methods used '
'in @JniNatives interface. And uses a shorter name and package'
' than GEN_JNI.')
'in @JniNatives interface.')
parser.add_argument(
'--feature_list_file',
default='',
......
......@@ -1792,14 +1792,18 @@ class ProxyTestGenerator(BaseTest):
golden_file='HashedSampleForAnnotationProcessor_jni.golden')
reg_dict = jni_registration_generator._DictForPath(
self._JoinScriptDir(path))
self._JoinScriptDir(path), use_proxy_hash=True)
reg_dict = self._MergeRegistrationForTests([reg_dict])
proxy_opts = jni_registration_generator.ProxyOptions()
proxy_opts = jni_registration_generator.ProxyOptions(use_hash=True)
self.AssertGoldenTextEquals(
jni_registration_generator.CreateProxyJavaFromDict(
reg_dict, proxy_opts),
golden_file='HashedSampleForAnnotationProcessorGenJni.golden')
self.AssertGoldenTextEquals(
jni_registration_generator.CreateProxyJavaFromDict(
reg_dict, proxy_opts, forwarding=True),
golden_file='HashedSampleForAnnotationProcessorGenJni.2.golden')
def testProxyJniExample(self):
generated_text = self._CreateJniHeaderFromFile(
......
......@@ -27,6 +27,7 @@ MERGEABLE_KEYS = [
'JNI_NATIVE_METHOD',
'JNI_NATIVE_METHOD_ARRAY',
'PROXY_NATIVE_SIGNATURES',
'FORWARDING_PROXY_METHODS',
'PROXY_NATIVE_METHOD_ARRAY',
'PROXY_NATIVE_METHOD_ARRAY_MAIN_DEX',
'REGISTER_MAIN_DEX_NATIVES',
......@@ -83,10 +84,23 @@ def _Generate(java_file_paths,
with build_utils.AtomicOutput(srcjar_path) as f:
with zipfile.ZipFile(f, 'w') as srcjar:
if proxy_opts.use_hash:
# J/N.java
build_utils.AddToZipHermetic(
srcjar,
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(
proxy_opts.use_hash),
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(True),
data=CreateProxyJavaFromDict(combined_dict, proxy_opts))
# org/chromium/base/natives/GEN_JNI.java
build_utils.AddToZipHermetic(
srcjar,
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(False),
data=CreateProxyJavaFromDict(
combined_dict, proxy_opts, forwarding=True))
else:
# org/chromium/base/natives/GEN_JNI.java
build_utils.AddToZipHermetic(
srcjar,
'%s.java' % jni_generator.ProxyHelpers.GetQualifiedClass(False),
data=CreateProxyJavaFromDict(combined_dict, proxy_opts))
......@@ -188,7 +202,7 @@ JNI_REGISTRATION_EXPORT bool ${REGISTRATION_NAME}(JNIEnv* env) {
registration_dict['REGISTER_MAIN_DEX_PROXY_NATIVES'] = main_dex_call
def CreateProxyJavaFromDict(registration_dict, proxy_opts):
def CreateProxyJavaFromDict(registration_dict, proxy_opts, forwarding=False):
template = string.Template("""\
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
......@@ -201,25 +215,36 @@ package ${PACKAGE};
// Please do not change its content.
public class ${CLASS_NAME} {
${FIELDS}
${METHODS}
}
""")
is_natives_class = not forwarding and proxy_opts.use_hash
class_name = jni_generator.ProxyHelpers.GetClass(is_natives_class)
package = jni_generator.ProxyHelpers.GetPackage(is_natives_class)
if forwarding or not proxy_opts.use_hash:
fields = string.Template("""\
public static final boolean TESTING_ENABLED = ${TESTING_ENABLED};
public static final boolean REQUIRE_MOCK = ${REQUIRE_MOCK};
${SIGNATURES}
""").substitute({
'TESTING_ENABLED': str(proxy_opts.enable_mocks).lower(),
'REQUIRE_MOCK': str(proxy_opts.require_mocks).lower(),
})
else:
fields = ''
}
""")
if forwarding:
methods = registration_dict['FORWARDING_PROXY_METHODS']
else:
methods = registration_dict['PROXY_NATIVE_SIGNATURES']
return template.substitute({
'TESTING_ENABLED':
str(proxy_opts.enable_mocks).lower(),
'REQUIRE_MOCK':
str(proxy_opts.require_mocks).lower(),
'CLASS_NAME':
jni_generator.ProxyHelpers.GetClass(proxy_opts.use_hash),
'PACKAGE':
jni_generator.ProxyHelpers.GetPackage(proxy_opts.use_hash).replace(
'/', '.'),
'SIGNATURES':
registration_dict['PROXY_NATIVE_SIGNATURES']
'CLASS_NAME': class_name,
'FIELDS': fields,
'PACKAGE': package.replace('/', '.'),
'METHODS': methods
})
......@@ -310,10 +335,16 @@ class HeaderGenerator(object):
self._AddClassPathDeclarations()
self._AddForwardDeclaration()
self._AddJNINativeMethodsArrays()
self._AddProxySignatures()
self._AddProxyNativeMethodKStrings()
self._AddRegisterNativesCalls()
self._AddRegisterNativesFunctions()
self.registration_dict['PROXY_NATIVE_SIGNATURES'] = ('\n'.join(
_MakeProxySignature(n) for n in self.proxy_natives))
if self.use_proxy_hash:
self.registration_dict['FORWARDING_PROXY_METHODS'] = ('\n'.join(
_MakeForwardingProxy(n) for n in self.proxy_natives))
return self.registration_dict
def _SetDictValue(self, key, value):
......@@ -412,10 +443,6 @@ ${KMETHODS}
}
return template.substitute(values)
def _AddProxySignatures(self):
self.registration_dict['PROXY_NATIVE_SIGNATURES'] = ('\n'.join(
_MakeProxySignature(n) for n in self.proxy_natives))
def _AddProxyNativeMethodKStrings(self):
"""Returns KMethodString for wrapped native methods in all_classes """
......@@ -508,17 +535,45 @@ ${NATIVES}\
return ''
def _MakeProxySignature(proxy_native):
signature_template = string.Template("""
public static native ${RETURN_TYPE} ${NAME}(${PARAMS});""")
def _MakeForwardingProxy(proxy_native):
template = string.Template("""
public static ${RETURN_TYPE} ${ORIG_NAME}(${PARAMS_WITH_TYPES}) {
${MAYBE_RETURN}${PROXY_CLASS}.${NAME}($PARAM_NAMES);
}""")
return signature_template.substitute({
params_with_types = ', '.join(
'%s %s' % (p.datatype, p.name) for p in proxy_native.params)
param_names = ', '.join(p.name for p in proxy_native.params)
proxy_class = jni_generator.ProxyHelpers.GetQualifiedClass(True)
return template.substitute({
'RETURN_TYPE':
proxy_native.return_type,
'ORIG_NAME':
proxy_native.proxy_name_orig,
'PARAMS_WITH_TYPES':
params_with_types,
'MAYBE_RETURN':
'' if proxy_native.return_type == 'void' else 'return ',
'PROXY_CLASS':
proxy_class.replace('/', '.'),
'NAME':
proxy_native.proxy_name,
'PARAMS':
jni_generator.JniParams.MakeProxyParamSignature(proxy_native.params)
'PARAM_NAMES':
param_names,
})
def _MakeProxySignature(proxy_native):
signature_template = string.Template("""
public static native ${RETURN_TYPE} ${NAME}(${PARAMS_WITH_TYPES});""")
params_with_types = ', '.join(
'%s %s' % (p.datatype, p.name) for p in proxy_native.params)
return signature_template.substitute({
'RETURN_TYPE': proxy_native.return_type,
'NAME': proxy_native.proxy_name,
'PARAMS_WITH_TYPES': params_with_types,
})
......@@ -547,7 +602,7 @@ def main(argv):
arg_parser.add_argument(
'--srcjar-path',
required=True,
help='Path to output srcjar for GEN_JNI.java (Or J/N.java if proxy'
help='Path to output srcjar for GEN_JNI.java (and J/N.java if proxy'
' hash is enabled).')
arg_parser.add_argument(
'--sources-exclusions',
......
......@@ -1857,12 +1857,8 @@ if (enable_java_templates) {
"*/R\$*.class",
"*/Manifest.class",
"*/Manifest\$*.class",
"*/GEN_JNI.class",
]
if (use_hashed_jni_names) {
jar_excluded_patterns += [ "J/N.class" ]
} else {
jar_excluded_patterns += [ "*/GEN_JNI.class" ]
}
}
}
......@@ -1916,7 +1912,7 @@ if (enable_java_templates) {
defines = []
# Set these even when !use_final_fields so that they have correct default
# values withnin junit_binary().
# values within junit_binary(), which ignores jar_excluded_patterns.
if (is_java_debug || dcheck_always_on) {
defines += [ "_DCHECK_IS_ON" ]
}
......
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