diff --git a/dex-reader-api/src/main/java/com/googlecode/d2j/DexConstants.java b/dex-reader-api/src/main/java/com/googlecode/d2j/DexConstants.java index decf099ff..b71df6b2a 100644 --- a/dex-reader-api/src/main/java/com/googlecode/d2j/DexConstants.java +++ b/dex-reader-api/src/main/java/com/googlecode/d2j/DexConstants.java @@ -44,6 +44,10 @@ public interface DexConstants { int ACC_CONSTRUCTOR = 0x10000;// constructor method (class or instance initializer) int ACC_DECLARED_SYNCHRONIZED = 0x20000; + int ACC_VISIBILITY_FLAGS = ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED; + int ACC_DEX_HIDDEN_BIT = 0x00000020; // field, method (not native) + int ACC_DEX_HIDDEN_BIT_NATIVE = 0x00000200; // method (native) + String ANNOTATION_DEFAULT_TYPE = "Ldalvik/annotation/AnnotationDefault;"; String ANNOTATION_SIGNATURE_TYPE = "Ldalvik/annotation/Signature;"; String ANNOTATION_THROWS_TYPE = "Ldalvik/annotation/Throws;"; diff --git a/dex-translator/src/main/java/com/googlecode/d2j/dex/Dex2Asm.java b/dex-translator/src/main/java/com/googlecode/d2j/dex/Dex2Asm.java index 2bce6eae8..95d921158 100644 --- a/dex-translator/src/main/java/com/googlecode/d2j/dex/Dex2Asm.java +++ b/dex-translator/src/main/java/com/googlecode/d2j/dex/Dex2Asm.java @@ -58,6 +58,20 @@ import java.util.Stack; public class Dex2Asm { + private static boolean isPowerOfTwo(int i) { + return (i & (i - 1)) == 0; + } + + private static int removeHiddenAccess(int accessFlags) { + // Refer to art/libdexfile/dex/hidden_api_access_flags.h + if (!isPowerOfTwo(accessFlags & DexConstants.ACC_VISIBILITY_FLAGS)) { + accessFlags ^= DexConstants.ACC_VISIBILITY_FLAGS; + } + accessFlags &= ~((accessFlags & DexConstants.ACC_NATIVE) != 0 ? + DexConstants.ACC_DEX_HIDDEN_BIT_NATIVE : DexConstants.ACC_DEX_HIDDEN_BIT); + return accessFlags; + } + public static class ClzCtx { public String classDescriptor; public String hexDecodeMethodNamePrefix; @@ -319,7 +333,9 @@ private static MethodVisitor collectBasicMethodInfo(DexMethodNode methodNode, Cl + " by changing its signature to null"); signature = null; } - int access = methodNode.access; + + // HiddenApiAccessFlags is valid for .dex but not for .class + int access = removeHiddenAccess(methodNode.access); // clear ACC_DECLARED_SYNCHRONIZED and ACC_CONSTRUCTOR from method flags final int cleanFlag = ~((DexConstants.ACC_DECLARED_SYNCHRONIZED | DexConstants.ACC_CONSTRUCTOR)); access &= cleanFlag; @@ -615,10 +631,11 @@ public void convertField(DexClassNode classNode, DexFieldNode fieldNode, ClassVi signature = null; } - + // HiddenApiAccessFlags is valid for .dex but not for .class + int access = removeHiddenAccess(fieldNode.access); final int fieldCleanFlag = ~((DexConstants.ACC_DECLARED_SYNCHRONIZED | Opcodes.ACC_SYNTHETIC)); - FieldVisitor fv = cv.visitField(fieldNode.access & fieldCleanFlag, fieldNode.field.getName(), - fieldNode.field.getType(), signature, value); + FieldVisitor fv = cv.visitField(access & fieldCleanFlag, fieldNode.field.getName(), + fieldNode.field.getType(), signature, value); if (fv == null) { return;