This commit is contained in:
REAndroid 2022-12-13 14:07:17 -05:00
parent 2e29f7a7bb
commit 9d8421b0c7
11 changed files with 129 additions and 42 deletions

View File

@ -2,7 +2,7 @@
apply plugin: 'java-library' apply plugin: 'java-library'
group 'com.reandroid.lib.arsc' group 'com.reandroid.lib.arsc'
version '1.0.5' version '1.0.6'
java { java {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8

View File

@ -114,5 +114,4 @@ public class ApkUtil {
public static final String DEF_MODULE_NAME="base"; public static final String DEF_MODULE_NAME="base";
public static final String NAME_value_type="value_type"; public static final String NAME_value_type="value_type";
public static final String NAME_data="data"; public static final String NAME_data="data";
public static final String NAME_is_array="is_array";
} }

View File

@ -4,6 +4,7 @@ import com.reandroid.lib.arsc.chunk.PackageBlock;
import com.reandroid.lib.arsc.chunk.TableBlock; import com.reandroid.lib.arsc.chunk.TableBlock;
import com.reandroid.lib.arsc.pool.SpecStringPool; import com.reandroid.lib.arsc.pool.SpecStringPool;
import com.reandroid.lib.arsc.pool.TableStringPool; import com.reandroid.lib.arsc.pool.TableStringPool;
import com.reandroid.lib.arsc.value.EntryBlock;
import com.reandroid.lib.arsc.value.ValueType; import com.reandroid.lib.arsc.value.ValueType;
import com.reandroid.lib.json.JSONArray; import com.reandroid.lib.json.JSONArray;
import com.reandroid.lib.json.JSONException; import com.reandroid.lib.json.JSONException;
@ -74,8 +75,8 @@ public class StringPoolBuilder {
return mSpecNameMap.get(pkgId); return mSpecNameMap.get(pkgId);
} }
private void scan(JSONObject jsonObject){ private void scan(JSONObject jsonObject){
if(jsonObject.has(ApkUtil.NAME_is_array)){ if(jsonObject.has(EntryBlock.NAME_entry_name)){
addSpecName(jsonObject.optString("name")); addSpecName(jsonObject.optString(EntryBlock.NAME_entry_name));
} }
if(jsonObject.has(ApkUtil.NAME_value_type)){ if(jsonObject.has(ApkUtil.NAME_value_type)){
if(ValueType.STRING.name().equals(jsonObject.getString(ApkUtil.NAME_value_type))){ if(ValueType.STRING.name().equals(jsonObject.getString(ApkUtil.NAME_value_type))){

View File

@ -49,6 +49,7 @@ public class TableBlockJsonBuilder {
for(File typeFile:typeFileList){ for(File typeFile:typeFileList){
loadType(pkg, typeFile); loadType(pkg, typeFile);
} }
pkg.sortTypes();
} }
private void loadType(PackageBlock packageBlock, File typeJsonFile) throws IOException{ private void loadType(PackageBlock packageBlock, File typeJsonFile) throws IOException{
FileInputStream inputStream=new FileInputStream(typeJsonFile); FileInputStream inputStream=new FileInputStream(typeJsonFile);

View File

@ -11,11 +11,18 @@ import com.reandroid.lib.json.JSONObject;
import java.util.*; import java.util.*;
public class SpecTypePairArray extends BlockArray<SpecTypePair> implements JSONConvert<JSONArray> { public class SpecTypePairArray extends BlockArray<SpecTypePair>
implements JSONConvert<JSONArray>, Comparator<SpecTypePair> {
public SpecTypePairArray(){ public SpecTypePairArray(){
super(); super();
} }
public void sort(){
for(SpecTypePair specTypePair:listItems()){
specTypePair.sortTypes();
}
sort(this);
}
public void removeEmptyPairs(){ public void removeEmptyPairs(){
List<SpecTypePair> allPairs=new ArrayList<>(listItems()); List<SpecTypePair> allPairs=new ArrayList<>(listItems());
boolean foundEmpty=false; boolean foundEmpty=false;
@ -219,4 +226,8 @@ public class SpecTypePairArray extends BlockArray<SpecTypePair> implements JSONC
specTypePair.fromJson(jsonObject); specTypePair.fromJson(jsonObject);
} }
} }
@Override
public int compare(SpecTypePair typePair1, SpecTypePair typePair2) {
return typePair1.compareTo(typePair2);
}
} }

View File

@ -17,13 +17,18 @@ import com.reandroid.lib.json.JSONObject;
import java.io.IOException; import java.io.IOException;
import java.util.AbstractList; import java.util.AbstractList;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Comparator;
import java.util.List; import java.util.List;
public class TypeBlockArray extends BlockArray<TypeBlock> implements JSONConvert<JSONArray> { public class TypeBlockArray extends BlockArray<TypeBlock>
implements JSONConvert<JSONArray>, Comparator<TypeBlock> {
private byte mTypeId; private byte mTypeId;
public TypeBlockArray(){ public TypeBlockArray(){
super(); super();
} }
public void sort(){
sort(this);
}
public void removeEmptyBlocks(){ public void removeEmptyBlocks(){
List<TypeBlock> allTypes=new ArrayList<>(listItems()); List<TypeBlock> allTypes=new ArrayList<>(listItems());
boolean foundEmpty=false; boolean foundEmpty=false;
@ -272,4 +277,8 @@ public class TypeBlockArray extends BlockArray<TypeBlock> implements JSONConvert
typeBlock.fromJson(jsonObject); typeBlock.fromJson(jsonObject);
} }
} }
@Override
public int compare(TypeBlock typeBlock1, TypeBlock typeBlock2) {
return typeBlock1.compareTo(typeBlock2);
}
} }

View File

@ -85,6 +85,9 @@ public class PackageBlock extends BaseChunk implements BlockLoad, JSONConvert<JS
addChild(mPackageLastBlocks); addChild(mPackageLastBlocks);
} }
public void sortTypes(){
getSpecTypePairArray().sort();
}
@Override @Override
public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { public void onBlockLoaded(BlockReader reader, Block sender) throws IOException {
if(sender==mPackageId){ if(sender==mPackageId){

View File

@ -15,7 +15,8 @@ import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class TypeBlock extends BaseTypeBlock implements JSONConvert<JSONObject> { public class TypeBlock extends BaseTypeBlock
implements JSONConvert<JSONObject>, Comparable<TypeBlock> {
private final IntegerItem mEntriesStart; private final IntegerItem mEntriesStart;
private final ResConfig mResConfig; private final ResConfig mResConfig;
private final IntegerArray mEntryOffsets; private final IntegerArray mEntryOffsets;
@ -138,6 +139,15 @@ public class TypeBlock extends BaseTypeBlock implements JSONConvert<JSONObject>
getResConfig().fromJson(json.getJSONObject("config")); getResConfig().fromJson(json.getJSONObject("config"));
} }
@Override @Override
public int compareTo(TypeBlock typeBlock) {
int id1=getTypeId();
int id2=typeBlock.getTypeId();
if(id1!=id2){
return Integer.compare(id1, id2);
}
return getResConfig().compareTo(typeBlock.getResConfig());
}
@Override
public String toString(){ public String toString(){
StringBuilder builder=new StringBuilder(); StringBuilder builder=new StringBuilder();
builder.append(getResConfig().toString()); builder.append(getResConfig().toString());

View File

@ -21,7 +21,8 @@ import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
public class SpecTypePair extends BlockContainer<Block> implements JSONConvert<JSONObject> { public class SpecTypePair extends BlockContainer<Block>
implements JSONConvert<JSONObject> , Comparable<SpecTypePair>{
private final Block[] mChildes; private final Block[] mChildes;
private final SpecBlock mSpecBlock; private final SpecBlock mSpecBlock;
private final TypeBlockArray mTypeBlockArray; private final TypeBlockArray mTypeBlockArray;
@ -37,6 +38,9 @@ public class SpecTypePair extends BlockContainer<Block> implements JSONConvert<J
public SpecTypePair(){ public SpecTypePair(){
this(new SpecBlock(), new TypeBlockArray()); this(new SpecBlock(), new TypeBlockArray());
} }
public void sortTypes(){
getTypeBlockArray().sort();
}
public void removeEmptyTypeBlocks(){ public void removeEmptyTypeBlocks(){
getTypeBlockArray().removeEmptyBlocks(); getTypeBlockArray().removeEmptyBlocks();
} }
@ -155,4 +159,23 @@ public class SpecTypePair extends BlockContainer<Block> implements JSONConvert<J
getSpecBlock().setTypeId((byte) json.getInt("id")); getSpecBlock().setTypeId((byte) json.getInt("id"));
getTypeBlockArray().fromJson(json.getJSONArray("types")); getTypeBlockArray().fromJson(json.getJSONArray("types"));
} }
@Override
public int compareTo(SpecTypePair specTypePair) {
return Integer.compare(getTypeId(), specTypePair.getTypeId());
}
@Override
public String toString(){
StringBuilder builder=new StringBuilder();
builder.append(String.format("0x%02x", getTypeId()));
builder.append(" (");
TypeString ts = getTypeString();
if(ts!=null){
builder.append(ts.get());
}else {
builder.append("null");
}
builder.append(") config count=");
builder.append(getTypeBlockArray().childesCount());
return builder.toString();
}
} }

View File

@ -227,8 +227,42 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
removeTableReferences(); removeTableReferences();
removeSpecReferences(); removeSpecReferences();
} }
private void setEntryTypeFlag(byte b){ public void setEntryTypeBag(boolean b){
mFlagEntryType.set(b); int val=mFlagEntryType.get();
if(b){
val=val|0x1;
}else {
val=val&0xFE;
}
mFlagEntryType.set((byte) val);
refreshHeaderSize();
}
public boolean isEntryTypeBag(){
return ((mFlagEntryType.get() & 0x1) != 0);
}
public void setEntryTypeShared(boolean b){
int val=mFlagEntryType.get();
if(b){
val=val|0x2;
}else {
val=val&0xFD;
}
mFlagEntryType.set((byte) val);
}
public boolean isEntryTypeShared(){
return (mFlagEntryType.get() & 0x2) !=0;
}
public void setEntryTypePublic(boolean b){
int val=mFlagEntryType.get();
if(b){
val=val|0x4;
}else {
val=val&0xFB;
}
mFlagEntryType.set((byte) val);
}
public boolean isEntryTypePublic(){
return (mFlagEntryType.get() & 0x4) !=0;
} }
private void setByteFlagsB(byte b){ private void setByteFlagsB(byte b){
mByteFlagsB.set(b); mByteFlagsB.set(b);
@ -283,19 +317,6 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
mResValue=resValue; mResValue=resValue;
} }
public void setEntryTypeBag(boolean is_complex){
if(is_complex){
if(!isEntryTypeBag()){
setEntryTypeFlag(FLAG_VALUE_BAG);
}
}else {
if(isEntryTypeBag()){
setEntryTypeFlag(FLAG_VALUE_INT);
}
}
refreshHeaderSize();
}
public ResConfig getResConfig(){ public ResConfig getResConfig(){
TypeBlock typeBlock=getTypeBlock(); TypeBlock typeBlock=getTypeBlock();
if(typeBlock!=null){ if(typeBlock!=null){
@ -488,9 +509,9 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
} }
private void refreshHeaderSize(){ private void refreshHeaderSize(){
if(isEntryTypeBag()){ if(isEntryTypeBag()){
mHeaderSize.set(HEADER_COMPLEX); mHeaderSize.set(HEADER_SIZE_BAG);
}else { }else {
mHeaderSize.set(HEADER_INT); mHeaderSize.set(HEADER_SIZE_INT);
} }
} }
private void createResValue(){ private void createResValue(){
@ -505,9 +526,6 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
} }
setResValueInternal(resValue); setResValueInternal(resValue);
} }
private boolean isEntryTypeBag(){
return ((mFlagEntryType.get() & FLAG_BAG_ENTRY) != 0);
}
@Override @Override
public void setNull(boolean is_null){ public void setNull(boolean is_null){
if(is_null){ if(is_null){
@ -635,8 +653,16 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
return null; return null;
} }
JSONObject jsonObject=new JSONObject(); JSONObject jsonObject=new JSONObject();
jsonObject.put(NAME_name, getSpecString().get()); jsonObject.put(NAME_entry_name, getSpecString().get());
jsonObject.put(NAME_is_array, isEntryTypeBag()); if(isEntryTypeBag()){
jsonObject.put(NAME_is_bag, true);
}
if(isEntryTypePublic()){
jsonObject.put(NAME_is_public, true);
}
if(isEntryTypeShared()){
jsonObject.put(NAME_is_shared, true);
}
jsonObject.put(NAME_value, getResValue().toJson()); jsonObject.put(NAME_value, getResValue().toJson());
return jsonObject; return jsonObject;
} }
@ -647,13 +673,15 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
return; return;
} }
BaseResValue baseResValue; BaseResValue baseResValue;
if(json.getBoolean(NAME_is_array)){ if(json.optBoolean(NAME_is_bag, false)){
baseResValue=new ResValueBag(); baseResValue=new ResValueBag();
}else { }else {
baseResValue=new ResValueInt(); baseResValue=new ResValueInt();
} }
setResValue(baseResValue); setResValue(baseResValue);
setName(json.getString(NAME_name)); setEntryTypeShared(json.optBoolean(NAME_is_shared, false));
setEntryTypePublic(json.optBoolean(NAME_is_public, false));
setName(json.getString(NAME_entry_name));
baseResValue.fromJson(json.getJSONObject(NAME_value)); baseResValue.fromJson(json.getJSONObject(NAME_value));
mResValue.onDataLoaded(); mResValue.onDataLoaded();
} }
@ -708,16 +736,13 @@ public class EntryBlock extends Block implements JSONConvert<JSONObject> {
return builder.toString(); return builder.toString();
} }
private final static byte FLAG_BAG_ENTRY = 0x01; private final static short HEADER_SIZE_BAG = 0x0010;
private final static short HEADER_SIZE_INT = 0x0008;
private final static byte FLAG_VALUE_BAG = 0x0001; public static final String NAME_entry_name ="entry_name";
private final static byte FLAG_VALUE_INT = 0x00; private static final String NAME_is_bag="is_bag";
private static final String NAME_is_shared="is_shared";
private final static short HEADER_COMPLEX=0x0010; private static final String NAME_is_public="is_public";
private final static short HEADER_INT=0x0008;
private static final String NAME_name="name";
private static final String NAME_is_array="is_array";
private static final String NAME_value="value"; private static final String NAME_value="value";
} }

View File

@ -12,7 +12,8 @@ import com.reandroid.lib.json.JSONObject;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays; import java.util.Arrays;
public class ResConfig extends FixedBlockContainer implements BlockLoad, JSONConvert<JSONObject> { public class ResConfig extends FixedBlockContainer
implements BlockLoad, JSONConvert<JSONObject>, Comparable<ResConfig> {
private final IntegerItem configSize; private final IntegerItem configSize;
private final ByteArray mValuesContainer; private final ByteArray mValuesContainer;
@ -781,6 +782,10 @@ public class ResConfig extends FixedBlockContainer implements BlockLoad, JSONCon
} }
return "["+q+"]"; return "["+q+"]";
} }
@Override
public int compareTo(ResConfig resConfig) {
return getQualifiers().compareTo(resConfig.getQualifiers());
}
private static char[] unpackLanguageOrRegion(byte b0, byte b1, char base){ private static char[] unpackLanguageOrRegion(byte b0, byte b1, char base){