Commit 153b61d5 authored by Eric Stevenson's avatar Eric Stevenson Committed by Commit Bot

Android: Add bytecode rewriting for Resources.getIdentifier().

The default implementation simply calls the original method.

Bug: 793816
Change-Id: I2ac147d5318d6a04db2d9cec46659d574383b005
Reviewed-on: https://chromium-review.googlesource.com/824722
Commit-Queue: Eric Stevenson <estevenson@chromium.org>
Reviewed-by: default avataragrieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#524092}
parent 5ee9572e
...@@ -51,6 +51,14 @@ public abstract class BuildHooksAndroid { ...@@ -51,6 +51,14 @@ public abstract class BuildHooksAndroid {
protected abstract Context createConfigurationContextImpl(Context context); protected abstract Context createConfigurationContextImpl(Context context);
public static int getIdentifier(
Resources resources, String name, String defType, String defPackage) {
return sInstance.getIdentifierImpl(resources, name, defType, defPackage);
}
protected abstract int getIdentifierImpl(
Resources resources, String name, String defType, String defPackage);
public static boolean isEnabled() { public static boolean isEnabled() {
return sInstance.isEnabledImpl(); return sInstance.isEnabledImpl();
} }
......
...@@ -35,6 +35,12 @@ public class BuildHooksAndroidImpl extends BuildHooksAndroid { ...@@ -35,6 +35,12 @@ public class BuildHooksAndroidImpl extends BuildHooksAndroid {
return null; return null;
} }
@Override
protected int getIdentifierImpl(
Resources resources, String name, String defType, String defPackage) {
return resources.getIdentifier(name, defType, defPackage);
}
@Override @Override
protected boolean isEnabledImpl() { protected boolean isEnabledImpl() {
return false; return false;
......
...@@ -55,11 +55,11 @@ class AssertionEnablerClassAdapter extends ClassVisitor { ...@@ -55,11 +55,11 @@ class AssertionEnablerClassAdapter extends ClassVisitor {
@Override @Override
public MethodVisitor visitMethod(final int access, final String name, String desc, public MethodVisitor visitMethod(final int access, final String name, String desc,
String signature, String[] exceptions) { String signature, String[] exceptions) {
return new RewriteAssertMethodVisitorWriter( return new RewriteAssertMethodVisitor(
Opcodes.ASM5, super.visitMethod(access, name, desc, signature, exceptions)); Opcodes.ASM5, super.visitMethod(access, name, desc, signature, exceptions));
} }
static class RewriteAssertMethodVisitorWriter extends MethodVisitor { static class RewriteAssertMethodVisitor extends MethodVisitor {
static final String ASSERTION_DISABLED_NAME = "$assertionsDisabled"; static final String ASSERTION_DISABLED_NAME = "$assertionsDisabled";
static final String INSERT_INSTRUCTION_NAME = "assertFailureHandler"; static final String INSERT_INSTRUCTION_NAME = "assertFailureHandler";
static final String INSERT_INSTRUCTION_DESC = static final String INSERT_INSTRUCTION_DESC =
...@@ -69,7 +69,7 @@ class AssertionEnablerClassAdapter extends ClassVisitor { ...@@ -69,7 +69,7 @@ class AssertionEnablerClassAdapter extends ClassVisitor {
boolean mStartLoadingAssert; boolean mStartLoadingAssert;
Label mGotoLabel; Label mGotoLabel;
public RewriteAssertMethodVisitorWriter(int api, MethodVisitor mv) { public RewriteAssertMethodVisitor(int api, MethodVisitor mv) {
super(api, mv); super(api, mv);
} }
......
...@@ -16,6 +16,7 @@ import static org.objectweb.asm.Opcodes.IF_ICMPGE; ...@@ -16,6 +16,7 @@ import static org.objectweb.asm.Opcodes.IF_ICMPGE;
import static org.objectweb.asm.Opcodes.ILOAD; import static org.objectweb.asm.Opcodes.ILOAD;
import static org.objectweb.asm.Opcodes.INVOKESPECIAL; import static org.objectweb.asm.Opcodes.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKESTATIC; import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.RETURN; import static org.objectweb.asm.Opcodes.RETURN;
import static org.chromium.bytecode.TypeUtils.ASSET_MANAGER; import static org.chromium.bytecode.TypeUtils.ASSET_MANAGER;
...@@ -28,6 +29,7 @@ import static org.chromium.bytecode.TypeUtils.CONTEXT_WRAPPER; ...@@ -28,6 +29,7 @@ import static org.chromium.bytecode.TypeUtils.CONTEXT_WRAPPER;
import static org.chromium.bytecode.TypeUtils.DISPLAY_LEAK_ACTIVITY; import static org.chromium.bytecode.TypeUtils.DISPLAY_LEAK_ACTIVITY;
import static org.chromium.bytecode.TypeUtils.INT; import static org.chromium.bytecode.TypeUtils.INT;
import static org.chromium.bytecode.TypeUtils.RESOURCES; import static org.chromium.bytecode.TypeUtils.RESOURCES;
import static org.chromium.bytecode.TypeUtils.STRING;
import static org.chromium.bytecode.TypeUtils.THEME; import static org.chromium.bytecode.TypeUtils.THEME;
import static org.chromium.bytecode.TypeUtils.VOID; import static org.chromium.bytecode.TypeUtils.VOID;
...@@ -59,6 +61,9 @@ import java.util.List; ...@@ -59,6 +61,9 @@ import java.util.List;
class CustomResourcesClassAdapter extends ClassVisitor { class CustomResourcesClassAdapter extends ClassVisitor {
private static final String IS_ENABLED_METHOD = "isEnabled"; private static final String IS_ENABLED_METHOD = "isEnabled";
private static final String IS_ENABLED_DESCRIPTOR = TypeUtils.getMethodDescriptor(BOOLEAN); private static final String IS_ENABLED_DESCRIPTOR = TypeUtils.getMethodDescriptor(BOOLEAN);
// Cached since this is used so often.
private static final String GET_IDENTIFIER_DESCRIPTOR =
TypeUtils.getMethodDescriptor(INT, STRING, STRING, STRING);
// Existing methods are more difficult to handle, and not currently needed. // Existing methods are more difficult to handle, and not currently needed.
private static final List<String> PROHIBITED_METHODS = Arrays.asList( private static final List<String> PROHIBITED_METHODS = Arrays.asList(
...@@ -102,7 +107,8 @@ class CustomResourcesClassAdapter extends ClassVisitor { ...@@ -102,7 +107,8 @@ class CustomResourcesClassAdapter extends ClassVisitor {
+ "#" + methodSignature); + "#" + methodSignature);
} }
} }
return super.visitMethod(access, name, desc, signature, exceptions); return new RewriteGetIdentifierMethodVisitor(
super.visitMethod(access, name, desc, signature, exceptions));
} }
@Override @Override
...@@ -159,6 +165,31 @@ class CustomResourcesClassAdapter extends ClassVisitor { ...@@ -159,6 +165,31 @@ class CustomResourcesClassAdapter extends ClassVisitor {
} }
} }
/**
* Remaps Resources.getIdentifier() method calls to use BuildHooksAndroid.
*
* resourceObj.getIdentifier(String, String, String) becomes:
* BuildHooksAndroid.getIdentifier(resourceObj, String, String, String);
*/
private static final class RewriteGetIdentifierMethodVisitor extends MethodVisitor {
RewriteGetIdentifierMethodVisitor(MethodVisitor mv) {
super(ASM5, mv);
}
@Override
public void visitMethodInsn(
int opcode, String owner, String name, String desc, boolean itf) {
String methodName = "getIdentifier";
if (opcode == INVOKEVIRTUAL && owner.equals(RESOURCES) && name.equals(methodName)
&& desc.equals(GET_IDENTIFIER_DESCRIPTOR)) {
super.visitMethodInsn(INVOKESTATIC, BUILD_HOOKS_ANDROID, methodName,
TypeUtils.getMethodDescriptor(INT, RESOURCES, STRING, STRING, STRING), itf);
} else {
super.visitMethodInsn(opcode, owner, name, desc, itf);
}
}
}
/** /**
* Generates: * Generates:
* *
......
...@@ -31,12 +31,13 @@ class TypeUtils { ...@@ -31,12 +31,13 @@ class TypeUtils {
static final String DISPLAY_LEAK_ACTIVITY = static final String DISPLAY_LEAK_ACTIVITY =
"com/squareup/leakcanary/internal/DisplayLeakActivity"; "com/squareup/leakcanary/internal/DisplayLeakActivity";
static final String RESOURCES = "android/content/res/Resources"; static final String RESOURCES = "android/content/res/Resources";
static final String STRING = "java/lang/String";
static final String THEME = "android/content/res/Resources$Theme"; static final String THEME = "android/content/res/Resources$Theme";
static final String BOOLEAN = "Z"; static final String BOOLEAN = "Z";
static final String INT = "I"; static final String INT = "I";
static final String VOID = "V"; static final String VOID = "V";
private static final Map<String, Type> PRIMITIVE_DESCRIPTORS; private static final Map<String, Type> PRIMITIVE_DESCRIPTORS;
static { static {
PRIMITIVE_DESCRIPTORS = new HashMap<>(); PRIMITIVE_DESCRIPTORS = new HashMap<>();
PRIMITIVE_DESCRIPTORS.put(Type.BOOLEAN_TYPE.toString(), Type.BOOLEAN_TYPE); PRIMITIVE_DESCRIPTORS.put(Type.BOOLEAN_TYPE.toString(), Type.BOOLEAN_TYPE);
......
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