From 0f1185e6b6f0432c4529c1ffa6a66553361180a3 Mon Sep 17 00:00:00 2001 From: REAndroid Date: Mon, 26 Dec 2022 10:37:09 -0500 Subject: [PATCH] Code cleanup, documentation and minor bug fix --- .../lib/arsc/array/EntryBlockArray.java | 18 ++- .../lib/arsc/array/SpecTypePairArray.java | 21 +++ .../lib/arsc/array/TypeBlockArray.java | 15 ++ .../com/reandroid/lib/arsc/base/Block.java | 3 +- .../lib/arsc/chunk/PackageBlock.java | 8 ++ .../reandroid/lib/arsc/chunk/TypeBlock.java | 8 ++ .../arsc/chunk/xml/AndroidManifestBlock.java | 128 +++++++++--------- .../lib/arsc/chunk/xml/ResXmlAttribute.java | 32 +---- .../lib/arsc/container/SpecTypePair.java | 17 ++- .../reandroid/lib/arsc/item/BlockItem.java | 3 +- .../reandroid/lib/arsc/item/ByteArray.java | 4 - .../com/reandroid/lib/arsc/item/ByteItem.java | 3 - .../reandroid/lib/arsc/item/IntegerArray.java | 8 +- .../reandroid/lib/arsc/item/IntegerItem.java | 6 +- .../reandroid/lib/arsc/item/ShortItem.java | 3 +- .../reandroid/lib/arsc/item/StringItem.java | 5 +- .../reandroid/lib/arsc/item/StyleItem.java | 3 - .../reandroid/lib/arsc/item/TypeString.java | 20 ++- .../lib/arsc/pool/BaseStringPool.java | 5 +- .../lib/arsc/pool/TypeStringPool.java | 45 +++++- .../lib/arsc/util/FrameworkTable.java | 83 ++++++++++++ .../lib/arsc/value/BaseResValue.java | 4 - 22 files changed, 306 insertions(+), 136 deletions(-) diff --git a/src/main/java/com/reandroid/lib/arsc/array/EntryBlockArray.java b/src/main/java/com/reandroid/lib/arsc/array/EntryBlockArray.java index 422ce97..bd013be 100755 --- a/src/main/java/com/reandroid/lib/arsc/array/EntryBlockArray.java +++ b/src/main/java/com/reandroid/lib/arsc/array/EntryBlockArray.java @@ -15,7 +15,6 @@ */ package com.reandroid.lib.arsc.array; -import com.reandroid.lib.arsc.chunk.TypeBlock; import com.reandroid.lib.arsc.item.IntegerArray; import com.reandroid.lib.arsc.item.IntegerItem; import com.reandroid.lib.arsc.value.BaseResValue; @@ -56,12 +55,27 @@ public class EntryBlockArray extends OffsetBlockArray implements JSO public EntryBlock newInstance() { return new EntryBlock(); } - @Override public EntryBlock[] newInstance(int len) { return new EntryBlock[len]; } + /** + * It is allowed to have duplicate entry name therefore it is not recommend to use this. + * Lets depreciate to warn developer + */ + @Deprecated + public EntryBlock searchByEntryName(String entryName){ + if(entryName==null){ + return null; + } + for(EntryBlock entryBlock:listItems()){ + if(entryName.equals(entryBlock.getName())){ + return entryBlock; + } + } + return null; + } @Override public JSONArray toJson() { JSONArray jsonArray=new JSONArray(); diff --git a/src/main/java/com/reandroid/lib/arsc/array/SpecTypePairArray.java b/src/main/java/com/reandroid/lib/arsc/array/SpecTypePairArray.java index 8f84454..3d1a7b8 100755 --- a/src/main/java/com/reandroid/lib/arsc/array/SpecTypePairArray.java +++ b/src/main/java/com/reandroid/lib/arsc/array/SpecTypePairArray.java @@ -254,6 +254,27 @@ public class SpecTypePairArray extends BlockArray exist.merge(typePair); } } + /** + * It is allowed to have duplicate type name therefore it is not recommend to use this. + * Lets depreciate to warn developer + */ + @Deprecated + public SpecTypePair searchByTypeName(String typeName){ + if(typeName==null){ + return null; + } + SpecTypePair[] childes=getChildes(); + if(childes==null){ + return null; + } + for(int i=0;i block.merge(typeBlock); } } + /** + * It is allowed to have duplicate entry name therefore it is not recommend to use this. + * Lets depreciate to warn developer + */ + @Deprecated + public EntryBlock searchByEntryName(String entryName){ + if(entryName==null){ + return null; + } + TypeBlock[] childes = getChildes(); + if(childes==null || childes.length==0){ + return null; + } + return childes[0].searchByEntryName(entryName); + } @Override public int compare(TypeBlock typeBlock1, TypeBlock typeBlock2) { return typeBlock1.compareTo(typeBlock2); diff --git a/src/main/java/com/reandroid/lib/arsc/base/Block.java b/src/main/java/com/reandroid/lib/arsc/base/Block.java index 95372a1..d020273 100755 --- a/src/main/java/com/reandroid/lib/arsc/base/Block.java +++ b/src/main/java/com/reandroid/lib/arsc/base/Block.java @@ -47,8 +47,7 @@ public abstract class Block { blockLoad.onBlockLoaded(reader, this); } } - public void onReadBytes(BlockReader reader) throws IOException{ - + protected void onReadBytes(BlockReader reader) throws IOException{ } public final int writeBytes(OutputStream stream) throws IOException{ if(isNull()){ diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java index 011e01d..b340d1a 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/PackageBlock.java @@ -323,6 +323,14 @@ public class PackageBlock extends BaseChunk getLibraryBlock().merge(packageBlock.getLibraryBlock()); getSpecTypePairArray().merge(packageBlock.getSpecTypePairArray()); } + /** + * It is allowed to have duplicate type name therefore it is not recommend to use this. + * Lets depreciate to warn developer + */ + @Deprecated + public SpecTypePair searchByTypeName(String typeName){ + return getSpecTypePairArray().searchByTypeName(typeName); + } @Override public int compareTo(PackageBlock pkg) { return Integer.compare(getId(), pkg.getId()); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java index 8997f42..deae562 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java @@ -190,6 +190,14 @@ public class TypeBlock extends BaseTypeBlock } return getResConfig().compareTo(typeBlock.getResConfig()); } + /** + * It is allowed to have duplicate entry name therefore it is not recommend to use this. + * Lets depreciate to warn developer + */ + @Deprecated + public EntryBlock searchByEntryName(String entryName){ + return getEntryBlockArray().searchByEntryName(entryName); + } @Override public String toString(){ StringBuilder builder=new StringBuilder(); diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/AndroidManifestBlock.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/AndroidManifestBlock.java index 07709e7..ae781c7 100644 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/AndroidManifestBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/AndroidManifestBlock.java @@ -15,8 +15,6 @@ */ package com.reandroid.lib.arsc.chunk.xml; -import com.reandroid.lib.arsc.item.ResXmlString; -import com.reandroid.lib.arsc.pool.ResXmlStringPool; import com.reandroid.lib.arsc.value.ValueType; import java.io.File; @@ -76,10 +74,10 @@ public class AndroidManifestBlock extends ResXmlBlock{ List permissionList = manifestElement.listElements(TAG_uses_permission); for(ResXmlElement permission:permissionList){ ResXmlAttribute nameAttr = permission.searchAttributeByResourceId(ID_name); - if(nameAttr==null){ + if(nameAttr==null||nameAttr.getValueType()!=ValueType.STRING){ continue; } - String val=nameAttr.getValueString(); + String val=nameAttr.getValueAsString(); if(val!=null){ results.add(val); } @@ -94,10 +92,10 @@ public class AndroidManifestBlock extends ResXmlBlock{ List permissionList = manifestElement.listElements(TAG_uses_permission); for(ResXmlElement permission:permissionList){ ResXmlAttribute nameAttr = permission.searchAttributeByResourceId(ID_name); - if(nameAttr==null){ + if(nameAttr==null || nameAttr.getValueType()!=ValueType.STRING){ continue; } - String val=nameAttr.getValueString(); + String val=nameAttr.getValueAsString(); if(val==null){ continue; } @@ -112,87 +110,93 @@ public class AndroidManifestBlock extends ResXmlBlock{ if(manifestElement==null){ return null; } - ResXmlElement exist=getUsesPermission(permissionName); + ResXmlElement exist = getUsesPermission(permissionName); if(exist!=null){ return exist; } - ResXmlElement result=manifestElement.createChildElement(TAG_uses_permission); + ResXmlElement result = manifestElement.createChildElement(TAG_uses_permission); ResXmlAttribute attr = result.createAndroidAttribute(NAME_name, ID_name); attr.setValueAsString(permissionName); return result; } public String getPackageName(){ - return getManifestAttributeString(NAME_PACKAGE); + ResXmlElement manifest=getManifestElement(); + if(manifest==null){ + return null; + } + ResXmlAttribute attribute = manifest.searchAttributeByName(NAME_PACKAGE); + if(attribute==null || attribute.getValueType()!=ValueType.STRING){ + return null; + } + return attribute.getValueAsString(); } public boolean setPackageName(String packageName){ - return setManifestAttributeString(NAME_PACKAGE, packageName); + ResXmlElement manifestElement=getManifestElement(); + if(manifestElement==null){ + return false; + } + ResXmlAttribute attribute= manifestElement.searchAttributeByName(NAME_PACKAGE); + if(attribute==null){ + return false; + } + attribute.setValueAsString(packageName); + return true; } public Integer getCompileSdkVersion(){ - return getManifestAttributeInt(NAME_compileSdkVersion); + return getManifestAttributeInt(ID_compileSdkVersion); } public boolean setCompileSdkVersion(int val){ return setManifestAttributeInt(ID_compileSdkVersion, val); } public String getCompileSdkVersionCodename(){ - return getManifestAttributeString(NAME_compileSdkVersionCodename); + return getManifestAttributeString(ID_compileSdkVersionCodename); } public boolean setCompileSdkVersionCodename(String val){ - return setManifestAttributeString(ID_compileSdkVersionCodename, val); + ResXmlElement manifest=getManifestElement(); + if(manifest==null){ + return false; + } + ResXmlAttribute attribute = manifest.searchAttributeByResourceId(ID_compileSdkVersionCodename); + if(attribute==null){ + return false; + } + attribute.setValueAsString(val); + return true; } public Integer getVersionCode(){ - return getManifestAttributeInt(NAME_versionCode); + return getManifestAttributeInt(ID_versionCode); } public boolean setVersionCode(int val){ - return setManifestAttributeInt(NAME_versionCode, val); + return setManifestAttributeInt(ID_versionCode, val); } public String getVersionName(){ - return getManifestAttributeString(NAME_versionName); + return getManifestAttributeString(ID_versionName); } public boolean setVersionName(String packageName){ - return setManifestAttributeString(NAME_versionName, packageName); + return setManifestAttributeString(ID_versionName, packageName); } - private String getManifestAttributeString(String name){ - ResXmlElement manifestElement=getManifestElement(); - if(manifestElement==null){ + private String getManifestAttributeString(int resourceId){ + ResXmlElement manifest=getManifestElement(); + if(manifest==null){ return null; } - ResXmlAttribute attribute= manifestElement.searchAttributeByName(name); - if(attribute==null){ + ResXmlAttribute attribute = manifest.searchAttributeByResourceId(resourceId); + if(attribute==null || attribute.getValueType()!=ValueType.STRING){ return null; } - int raw=attribute.getRawValue(); - ResXmlStringPool pool = getStringPool(); - ResXmlString resXmlString = pool.get(raw); - if(resXmlString==null){ - return null; - } - return resXmlString.getHtml(); + return attribute.getValueAsString(); } - private boolean setManifestAttributeString(int resId, String value){ + private boolean setManifestAttributeString(int resourceId, String value){ ResXmlElement manifestElement=getManifestElement(); if(manifestElement==null){ return false; } - ResXmlAttribute attribute= manifestElement.searchAttributeByResourceId(resId); + ResXmlAttribute attribute = manifestElement.searchAttributeByResourceId(resourceId); if(attribute==null){ return false; } - attribute.setValueType(ValueType.STRING); - ResXmlString resXmlString=attribute.setValueString(value); - return resXmlString!=null; - } - private boolean setManifestAttributeString(String name, String value){ - ResXmlElement manifestElement=getManifestElement(); - if(manifestElement==null){ - return false; - } - ResXmlAttribute attribute= manifestElement.searchAttributeByName(name); - if(attribute==null){ - return false; - } - attribute.setValueType(ValueType.STRING); - ResXmlString resXmlString=attribute.setValueString(value); - return resXmlString!=null; + attribute.setValueAsString(value); + return true; } private boolean setManifestAttributeInt(int resId, int value){ ResXmlElement manifestElement=getManifestElement(); @@ -203,32 +207,16 @@ public class AndroidManifestBlock extends ResXmlBlock{ if(attribute==null){ return false; } - attribute.setValueType(ValueType.INT_DEC); - attribute.setValueString(String.valueOf(value)); - attribute.setRawValue(value); + attribute.setValueAsIntegerDec(value); return true; } - private boolean setManifestAttributeInt(String name, int value){ - ResXmlElement manifestElement=getManifestElement(); - if(manifestElement==null){ - return false; - } - ResXmlAttribute attribute= manifestElement.searchAttributeByName(name); - if(attribute==null){ - return false; - } - attribute.setValueType(ValueType.INT_DEC); - attribute.setValueString(String.valueOf(value)); - attribute.setRawValue(value); - return true; - } - private Integer getManifestAttributeInt(String name){ + private Integer getManifestAttributeInt(int resourceId){ ResXmlElement manifestElement=getManifestElement(); if(manifestElement==null){ return null; } - ResXmlAttribute attribute= manifestElement.searchAttributeByName(name); - if(attribute==null){ + ResXmlAttribute attribute= manifestElement.searchAttributeByResourceId(resourceId); + if(attribute==null || attribute.getValueType()!=ValueType.INT_DEC){ return null; } return attribute.getRawValue(); @@ -324,6 +312,8 @@ public class AndroidManifestBlock extends ResXmlBlock{ public static final String NAME_name = "name"; public static final String NAME_extractNativeLibs = "extractNativeLibs"; public static final String NAME_isSplitRequired = "isSplitRequired"; + public static final String NAME_value = "value"; + public static final String NAME_resource = "resource"; public static final int ID_name = 0x01010003; public static final int ID_compileSdkVersion = 0x01010572; @@ -334,6 +324,10 @@ public class AndroidManifestBlock extends ResXmlBlock{ public static final int ID_screenOrientation = 0x0101001e; public static final int ID_extractNativeLibs = 0x010104ea; public static final int ID_isSplitRequired = 0x01010591; + public static final int ID_value = 0x01010024; + public static final int ID_resource = 0x01010025; + public static final int ID_versionCode = 0x0101021b; + public static final int ID_versionName = 0x0101021c; public static final String VALUE_android_intent_action_MAIN = "android.intent.action.MAIN"; diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java index faae2fa..8357e58 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/xml/ResXmlAttribute.java @@ -178,22 +178,10 @@ import java.util.Set; } return xmlElement.getStartNamespaceByUriRef(getNamespaceReference()); } + @Deprecated public String getValueString(){ return getString(getValueStringReference()); } - ResXmlString setValueString(String str){ - ResXmlString resXmlString=getOrCreateResXmlString(str); - if(resXmlString==null){ - return null; - } - int ref=resXmlString.getIndex(); - setValueStringReference(ref); - if(getValueType()==ValueType.STRING){ - setRawValue(ref); - setValueStringReference(ref); - } - return resXmlString; - } public int getNameResourceID(){ return getResourceId(getNameReference()); } @@ -313,8 +301,8 @@ import java.util.Set; setRawValue(ref); setValueStringReference(-1); } - public void setValueAsInteger(int val){ - setValueType(ValueType.FIRST_INT); + public void setValueAsIntegerDec(int val){ + setValueType(ValueType.INT_DEC); setRawValue(val); setValueStringReference(-1); } @@ -362,18 +350,6 @@ import java.util.Set; setRawValue(val); setValueStringReference(-1); } - private String getCompareName(){ - int id=getNameResourceID(); - StringBuilder builder=new StringBuilder(); - if(id!=0){ - builder.append("0 "); - builder.append(String.format("%08x", id)); - }else { - builder.append("1 "); - builder.append(getName()); - } - return builder.toString(); - } @Override public int compareTo(ResXmlAttribute other) { int id1=getNameResourceID(); @@ -473,7 +449,7 @@ import java.util.Set; } static final String NAME_id = "id"; public static final String NAME_value_type = "value_type"; - static final String NAME_name = "name"; + public static final String NAME_name = "name"; public static final String NAME_namespace_uri = "namespace_uri"; public static final String NAME_data= "data"; } diff --git a/src/main/java/com/reandroid/lib/arsc/container/SpecTypePair.java b/src/main/java/com/reandroid/lib/arsc/container/SpecTypePair.java index 8058ec1..ab6c6a8 100755 --- a/src/main/java/com/reandroid/lib/arsc/container/SpecTypePair.java +++ b/src/main/java/com/reandroid/lib/arsc/container/SpecTypePair.java @@ -88,6 +88,21 @@ public class SpecTypePair extends BlockContainer mSpecBlock.setTypeId(id); mTypeBlockArray.setTypeId(id); } + public String getTypeName(){ + TypeString typeString = getTypeString(); + if(typeString!=null){ + return typeString.get(); + } + return null; + } + /** + * It is allowed to have duplicate entry name therefore it is not recommend to use this. + * Lets depreciate to warn developer + */ + @Deprecated + public EntryBlock searchByEntryName(String entryName){ + return getTypeBlockArray().searchByEntryName(entryName); + } public SpecBlock getSpecBlock(){ return mSpecBlock; } @@ -118,7 +133,7 @@ public class SpecTypePair extends BlockContainer return results; } public Collection listTypeBlocks(){ - return mTypeBlockArray.listItems(); + return getTypeBlockArray().listItems(); } @Override diff --git a/src/main/java/com/reandroid/lib/arsc/item/BlockItem.java b/src/main/java/com/reandroid/lib/arsc/item/BlockItem.java index 06e6836..297e855 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/BlockItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/BlockItem.java @@ -29,7 +29,8 @@ public abstract class BlockItem extends Block { super(); mBytes=new byte[bytesLength]; } - public abstract void onBytesChanged(); + protected void onBytesChanged(){ + } protected byte[] getBytesInternal() { return mBytes; } diff --git a/src/main/java/com/reandroid/lib/arsc/item/ByteArray.java b/src/main/java/com/reandroid/lib/arsc/item/ByteArray.java index dc6ec9f..3fcc1fa 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/ByteArray.java +++ b/src/main/java/com/reandroid/lib/arsc/item/ByteArray.java @@ -149,10 +149,6 @@ public class ByteArray extends BlockItem { } }; } - - @Override - public void onBytesChanged() { - } @Override public String toString(){ return "size="+size(); diff --git a/src/main/java/com/reandroid/lib/arsc/item/ByteItem.java b/src/main/java/com/reandroid/lib/arsc/item/ByteItem.java index c78f08d..73ed2bf 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/ByteItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/ByteItem.java @@ -44,9 +44,6 @@ public class ByteItem extends BlockItem { return getBytesInternal()[0]; } @Override - public void onBytesChanged() { - } - @Override public String toString(){ return String.valueOf(get()); } diff --git a/src/main/java/com/reandroid/lib/arsc/item/IntegerArray.java b/src/main/java/com/reandroid/lib/arsc/item/IntegerArray.java index d25bb08..6545e8f 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/IntegerArray.java +++ b/src/main/java/com/reandroid/lib/arsc/item/IntegerArray.java @@ -49,18 +49,16 @@ public class IntegerArray extends BlockItem { } } public final List toList(){ - List results=new AbstractList() { + return new AbstractList() { @Override public Integer get(int i) { return IntegerArray.this.get(i); } - @Override public int size() { return IntegerArray.this.size(); } }; - return results; } public final int[] toArray(){ int s=size(); @@ -112,8 +110,4 @@ public class IntegerArray extends BlockItem { bts[i+1]= (byte) (value >>> 8 & 0xff); bts[i]= (byte) (value & 0xff); } - @Override - public void onBytesChanged() { - - } } diff --git a/src/main/java/com/reandroid/lib/arsc/item/IntegerItem.java b/src/main/java/com/reandroid/lib/arsc/item/IntegerItem.java index 94ac430..86d87aa 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/IntegerItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/IntegerItem.java @@ -41,11 +41,9 @@ public class IntegerItem extends BlockItem implements ReferenceItem{ public int get(){ return mCache; } - - - @Override - public void onBytesChanged() { + protected void onBytesChanged() { + // To save cpu usage, better to calculate once only when bytes changed mCache=readIntBytes(); } private int readIntBytes(){ diff --git a/src/main/java/com/reandroid/lib/arsc/item/ShortItem.java b/src/main/java/com/reandroid/lib/arsc/item/ShortItem.java index f8cdd2f..faf83aa 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/ShortItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/ShortItem.java @@ -38,7 +38,8 @@ public class ShortItem extends BlockItem { return mCache; } @Override - public void onBytesChanged() { + protected void onBytesChanged() { + // To save cpu usage, better to calculate once only when bytes changed mCache=readShortBytes(); } private short readShortBytes(){ diff --git a/src/main/java/com/reandroid/lib/arsc/item/StringItem.java b/src/main/java/com/reandroid/lib/arsc/item/StringItem.java index 5f20025..1fa3176 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/StringItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/StringItem.java @@ -118,12 +118,11 @@ public class StringItem extends BlockItem implements JSONConvert { mUtf8=utf8; onBytesChanged(); } - @Override - public void onBytesChanged() { + protected void onBytesChanged() { + // To save cpu/memory usage, better to decode once only when bytes changed mCache=decodeString(); } - @Override public void onReadBytes(BlockReader reader) throws IOException { if(reader.available()<4){ diff --git a/src/main/java/com/reandroid/lib/arsc/item/StyleItem.java b/src/main/java/com/reandroid/lib/arsc/item/StyleItem.java index 8e2a00f..b3dbd50 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/StyleItem.java +++ b/src/main/java/com/reandroid/lib/arsc/item/StyleItem.java @@ -254,9 +254,6 @@ public class StyleItem extends IntegerArray implements JSONConvert { return true; } @Override - public void onBytesChanged() { - } - @Override public void setNull(boolean is_null){ if(!is_null){ return; diff --git a/src/main/java/com/reandroid/lib/arsc/item/TypeString.java b/src/main/java/com/reandroid/lib/arsc/item/TypeString.java index 750a248..81f261a 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/TypeString.java +++ b/src/main/java/com/reandroid/lib/arsc/item/TypeString.java @@ -16,11 +16,19 @@ package com.reandroid.lib.arsc.item; -public class TypeString extends StringItem { + import com.reandroid.lib.arsc.base.Block; + import com.reandroid.lib.arsc.pool.TypeStringPool; + + public class TypeString extends StringItem { public TypeString(boolean utf8) { super(utf8); } public byte getId(){ + TypeStringPool stringPool=getTypeStringPool(); + if(stringPool!=null){ + return stringPool.idOf(this); + } + // Should not reach here , this means it not added to string pool return (byte) (getIndex()+1); } @Override @@ -28,4 +36,14 @@ public class TypeString extends StringItem { // Type don't have style unless to obfuscate/confuse other decompilers return null; } + private TypeStringPool getTypeStringPool(){ + Block parent=this; + while (parent!=null){ + if(parent instanceof TypeStringPool){ + return (TypeStringPool) parent; + } + parent=parent.getParent(); + } + return null; + } } diff --git a/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java b/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java index 1e32447..03084d9 100755 --- a/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java +++ b/src/main/java/com/reandroid/lib/arsc/pool/BaseStringPool.java @@ -144,6 +144,9 @@ public abstract class BaseStringPool extends BaseChunk imp public List listUnusedStrings(){ return getStringsArray().listUnusedStrings(); } + public Collection listStrings(){ + return getStringsArray().listItems(); + } public StyleArray getStyleArray(){ return mArrayStyles; } @@ -195,7 +198,7 @@ public abstract class BaseStringPool extends BaseChunk imp public final StringGroup get(String str){ return mUniqueMap.get(str); } - public final T getOrCreate(String str){ + public T getOrCreate(String str){ StringGroup group=getOrCreateGroup(str); T[] items=group.getItems(); if(items.length==0){ diff --git a/src/main/java/com/reandroid/lib/arsc/pool/TypeStringPool.java b/src/main/java/com/reandroid/lib/arsc/pool/TypeStringPool.java index 00d5311..cd97a9c 100755 --- a/src/main/java/com/reandroid/lib/arsc/pool/TypeStringPool.java +++ b/src/main/java/com/reandroid/lib/arsc/pool/TypeStringPool.java @@ -17,20 +17,44 @@ package com.reandroid.lib.arsc.pool; import com.reandroid.lib.arsc.array.StringArray; import com.reandroid.lib.arsc.array.TypeStringArray; -import com.reandroid.lib.arsc.header.HeaderBlock; -import com.reandroid.lib.arsc.io.BlockReader; +import com.reandroid.lib.arsc.chunk.TypeBlock; +import com.reandroid.lib.arsc.group.StringGroup; import com.reandroid.lib.arsc.item.IntegerArray; import com.reandroid.lib.arsc.item.IntegerItem; import com.reandroid.lib.arsc.item.TypeString; -import java.io.IOException; - public class TypeStringPool extends BaseStringPool { private final IntegerItem mTypeIdOffset; public TypeStringPool(boolean is_utf8, IntegerItem typeIdOffset) { super(is_utf8); this.mTypeIdOffset = typeIdOffset; } + public byte idOf(String typeName){ + return idOf(getByName(typeName)); + } + /** + * Resolves id of {@link TypeBlock} + * Not recommend to use unless unless you are sure of proper pool + **/ + public byte idOf(TypeString typeString){ + if(typeString==null){ + return 0; + } + return (byte) (typeString.getIndex()+mTypeIdOffset.get()+1); + } + /** + * Searches string entry {@link TypeBlock} + * {@param name} is name of {@link TypeBlock} + * This might not working if duplicate type names are present + **/ + public TypeString getByName(String name){ + for(TypeString typeString:listStrings()){ + if(name.equals(typeString.get())){ + return typeString; + } + } + return null; + } public TypeString getById(int id){ int index=id-mTypeIdOffset.get()-1; return super.get(index); @@ -42,6 +66,19 @@ public class TypeStringPool extends BaseStringPool { typeString.set(typeName); return typeString; } + /** + * Use getOrCreate(typeId, typeName)} + **/ + @Deprecated + @Override + public final TypeString getOrCreate(String str){ + StringGroup group = get(str); + if(group==null||group.size()==0){ + throw new IllegalArgumentException("Can not create TypeString (" + str + +") without type id. use getOrCreate(typeId, typeName)"); + } + return group.get(0); + } @Override StringArray newInstance(IntegerArray offsets, IntegerItem itemCount, IntegerItem itemStart, boolean is_utf8) { return new TypeStringArray(offsets, itemCount, itemStart, is_utf8); diff --git a/src/main/java/com/reandroid/lib/arsc/util/FrameworkTable.java b/src/main/java/com/reandroid/lib/arsc/util/FrameworkTable.java index b353581..cc8566b 100755 --- a/src/main/java/com/reandroid/lib/arsc/util/FrameworkTable.java +++ b/src/main/java/com/reandroid/lib/arsc/util/FrameworkTable.java @@ -39,9 +39,92 @@ public class FrameworkTable extends TableBlock { private String mFrameworkTitle; private String mFrameworkName; private String mFrameworkVersion; + private Map> mNameGroupMap; + private final Object mMapLock=new Object(); public FrameworkTable(){ super(); } + + public int resolveResourceId(String typeName, String entryName){ + EntryBlock entryBlock=searchEntryBlock(typeName, entryName); + if(entryBlock!=null){ + return entryBlock.getResourceId(); + } + return 0; + } + /** + * Loads all resource name map to memory for faster use + * Call this if you plan to search entries frequently + */ + public void loadResourceNameMap(){ + synchronized (mMapLock){ + if(mNameGroupMap !=null){ + return; + } + Map> typeMap=new HashMap<>(); + for(PackageBlock packageBlock:listPackages()){ + for(EntryGroup group:packageBlock.listEntryGroup()){ + String type=group.getTypeName(); + Map groupMap=typeMap.get(type); + if(groupMap==null){ + groupMap=new HashMap<>(); + typeMap.put(type, groupMap); + } + groupMap.put(group.getSpecName(), group); + } + } + mNameGroupMap = typeMap; + } + } + /** + * Clears resource name map from memory + */ + public void clearResourceNameMap(){ + synchronized (mMapLock){ + if(mNameGroupMap!=null){ + mNameGroupMap.clear(); + mNameGroupMap =null; + } + } + } + private boolean hasResourceGroupMap(){ + synchronized (mMapLock){ + return mNameGroupMap!=null; + } + } + private EntryBlock searchEntryBlockFromMap(String typeName, String entryName){ + synchronized (mMapLock){ + if(mNameGroupMap ==null){ + return null; + } + Map groupMap = mNameGroupMap.get(typeName); + if(groupMap!=null){ + EntryGroup group=groupMap.get(entryName); + if(group!=null){ + return group.pickOne(); + } + } + return null; + } + } + public EntryBlock searchEntryBlock(String typeName, String entryName){ + if(hasResourceGroupMap()){ + return searchEntryBlockFromMap(typeName, entryName); + } + return searchEntryBlockFromTable(typeName, entryName); + } + /** + * Since this is framework, we are sure of proper names. + */ + public EntryBlock searchEntryBlockFromTable(String typeName, String entryName){ + for(PackageBlock packageBlock:listPackages()){ + SpecTypePair specTypePair = packageBlock.searchByTypeName(typeName); + if(specTypePair!=null){ + return specTypePair.searchByEntryName(entryName); + } + } + return null; + } public String getFrameworkTitle(){ if(mFrameworkTitle==null){ mFrameworkTitle=loadProperty(PROP_TITLE); diff --git a/src/main/java/com/reandroid/lib/arsc/value/BaseResValue.java b/src/main/java/com/reandroid/lib/arsc/value/BaseResValue.java index 31d7644..33200f6 100755 --- a/src/main/java/com/reandroid/lib/arsc/value/BaseResValue.java +++ b/src/main/java/com/reandroid/lib/arsc/value/BaseResValue.java @@ -66,10 +66,6 @@ public abstract class BaseResValue extends BlockItem implements JSONConvert