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 {
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() {
return sInstance.isEnabledImpl();
}
......
......@@ -35,6 +35,12 @@ public class BuildHooksAndroidImpl extends BuildHooksAndroid {
return null;
}
@Override
protected int getIdentifierImpl(
Resources resources, String name, String defType, String defPackage) {
return resources.getIdentifier(name, defType, defPackage);
}
@Override
protected boolean isEnabledImpl() {
return false;
......
......@@ -55,11 +55,11 @@ class AssertionEnablerClassAdapter extends ClassVisitor {
@Override
public MethodVisitor visitMethod(final int access, final String name, String desc,
String signature, String[] exceptions) {
return new RewriteAssertMethodVisitorWriter(
return new RewriteAssertMethodVisitor(
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 INSERT_INSTRUCTION_NAME = "assertFailureHandler";
static final String INSERT_INSTRUCTION_DESC =
......@@ -69,7 +69,7 @@ class AssertionEnablerClassAdapter extends ClassVisitor {
boolean mStartLoadingAssert;
Label mGotoLabel;
public RewriteAssertMethodVisitorWriter(int api, MethodVisitor mv) {
public RewriteAssertMethodVisitor(int api, MethodVisitor mv) {
super(api, mv);
}
......
......@@ -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.INVOKESPECIAL;
import static org.objectweb.asm.Opcodes.INVOKESTATIC;
import static org.objectweb.asm.Opcodes.INVOKEVIRTUAL;
import static org.objectweb.asm.Opcodes.RETURN;
import static org.chromium.bytecode.TypeUtils.ASSET_MANAGER;
......@@ -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.INT;
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.VOID;
......@@ -59,6 +61,9 @@ import java.util.List;
class CustomResourcesClassAdapter extends ClassVisitor {
private static final String IS_ENABLED_METHOD = "isEnabled";
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.
private static final List<String> PROHIBITED_METHODS = Arrays.asList(
......@@ -102,7 +107,8 @@ class CustomResourcesClassAdapter extends ClassVisitor {
+ "#" + methodSignature);
}
}
return super.visitMethod(access, name, desc, signature, exceptions);
return new RewriteGetIdentifierMethodVisitor(
super.visitMethod(access, name, desc, signature, exceptions));
}
@Override
......@@ -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:
*
......
......@@ -31,12 +31,13 @@ class TypeUtils {
static final String DISPLAY_LEAK_ACTIVITY =
"com/squareup/leakcanary/internal/DisplayLeakActivity";
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 BOOLEAN = "Z";
static final String INT = "I";
static final String VOID = "V";
private static final Map<String, Type> PRIMITIVE_DESCRIPTORS;
static {
PRIMITIVE_DESCRIPTORS = new HashMap<>();
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