diff --git a/src/main/java/com/reandroid/lib/arsc/base/BlockContainer.java b/src/main/java/com/reandroid/lib/arsc/base/BlockContainer.java index 70a2dac..667b5c6 100755 --- a/src/main/java/com/reandroid/lib/arsc/base/BlockContainer.java +++ b/src/main/java/com/reandroid/lib/arsc/base/BlockContainer.java @@ -1,6 +1,7 @@ package com.reandroid.lib.arsc.base; import com.reandroid.lib.arsc.container.BlockList; +import com.reandroid.lib.arsc.container.FixedBlockContainer; import com.reandroid.lib.arsc.io.BlockReader; import java.io.IOException; @@ -43,8 +44,7 @@ public abstract class BlockContainer extends Block{ if(item instanceof BlockContainer){ BlockContainer container=(BlockContainer)item; container.refresh(); - } - if(item instanceof BlockList){ + }else if(item instanceof BlockList){ BlockList blockList=(BlockList)item; blockList.refresh(); } 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 d75cebd..fbaeaeb 100755 --- a/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/chunk/TypeBlock.java @@ -108,6 +108,11 @@ public class TypeBlock extends BaseTypeBlock { getEntryBlockArray().refreshCountAndStart(); } @Override + protected void onPreRefreshRefresh(){ + mResConfig.refresh(); + super.onPreRefreshRefresh(); + } + @Override public String toString(){ StringBuilder builder=new StringBuilder(); builder.append(getResConfig().toString()); diff --git a/src/main/java/com/reandroid/lib/arsc/container/BlockList.java b/src/main/java/com/reandroid/lib/arsc/container/BlockList.java index 30a5bba..2194304 100755 --- a/src/main/java/com/reandroid/lib/arsc/container/BlockList.java +++ b/src/main/java/com/reandroid/lib/arsc/container/BlockList.java @@ -47,8 +47,7 @@ public class BlockList extends Block { if(item instanceof BlockContainer){ BlockContainer container=(BlockContainer)item; container.refresh(); - } - if(item instanceof BlockList){ + }else if(item instanceof BlockList){ BlockList blockList=(BlockList)item; blockList.refresh(); } 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 09919b8..894f10c 100755 --- a/src/main/java/com/reandroid/lib/arsc/item/ByteArray.java +++ b/src/main/java/com/reandroid/lib/arsc/item/ByteArray.java @@ -21,50 +21,11 @@ public class ByteArray extends BlockItem { int len=values.length; setBytesLength(old+len, false); byte[] bts = getBytesInternal(); - for(int i=0;i>> 24 & 0xff); - bts[2]= (byte) (val >>> 16 & 0xff); - bts[1]= (byte) (val >>> 8 & 0xff); - bts[0]= (byte) (val & 0xff); - } - public final void setShort(short val){ - byte[] bts = getBytesInternal(); - bts[1]= (byte) (val >>> 8 & 0xff); - bts[0]= (byte) (val & 0xff); - } - public final short getShort(){ - byte[] bts = getBytesInternal(); - return (short) (bts[0] & 0xff | (bts[1] & 0xff) << 8); - } - public final int getInt(){ - byte[] bts = getBytesInternal(); - return bts[0] & 0xff | - (bts[1] & 0xff) << 8 | - (bts[2] & 0xff) << 16 | - (bts[3] & 0xff) << 24; - } - public final List toList(){ - List results=new AbstractList() { - @Override - public Byte get(int i) { - return ByteArray.this.get(i); - } - - @Override - public int size() { - return ByteArray.this.size(); - } - }; - return results; - } public final byte[] toArray(){ return getBytes(); } @@ -88,28 +49,94 @@ public class ByteArray extends BlockItem { } setBytesLength(s); } + public final int size(){ + return getBytesLength(); + } public Byte get(int index){ if(index<0 || index>=size()){ return null; } return getBytesInternal()[index]; } - public final int size(){ - return getBytesLength(); - } - final void add(byte value){ - int len=getBytesLength(); - len=len + 1; - setBytesLength(len, false); - put(len, value); - } public final void put(int index, byte value){ byte[] bts = getBytesInternal(); bts[index]=value; } + public final void putShort(int offset, short val){ + byte[] bts = getBytesInternal(); + bts[offset+1]= (byte) (val >>> 8 & 0xff); + bts[offset]= (byte) (val & 0xff); + } + public final short getShort(int offset){ + byte[] bts = getBytesInternal(); + return (short) (bts[offset] & 0xff | (bts[offset+1] & 0xff) << 8); + } + public final void putInteger(int offset, int val){ + byte[] bts = getBytesInternal(); + bts[offset+3]= (byte) (val >>> 24 & 0xff); + bts[offset+2]= (byte) (val >>> 16 & 0xff); + bts[offset+1]= (byte) (val >>> 8 & 0xff); + bts[offset]= (byte) (val & 0xff); + } + public final int getInteger(int offset){ + byte[] bts = getBytesInternal(); + return bts[offset] & 0xff | + (bts[offset+1] & 0xff) << 8 | + (bts[offset+2] & 0xff) << 16 | + (bts[offset+3] & 0xff) << 24; + } + public final void putByteArray(int offset, byte[] val){ + byte[] bts = getBytesInternal(); + System.arraycopy(val, 0, bts, offset, val.length); + } + public final byte[] getByteArray(int offset, int length){ + byte[] bts = getBytesInternal(); + byte[] result = new byte[length]; + if (result.length >= 0) { + System.arraycopy(bts, offset, result, 0, result.length); + } + return result; + } + + public final List toByteList(){ + return new AbstractList() { + @Override + public Byte get(int i) { + return ByteArray.this.get(i); + } + @Override + public int size() { + return ByteArray.this.size(); + } + }; + } + public final List toShortList(){ + return new AbstractList() { + @Override + public Short get(int i) { + return ByteArray.this.getShort(i); + } + @Override + public int size() { + return ByteArray.this.size()/2; + } + }; + } + public final List toIntegerList(){ + return new AbstractList() { + @Override + public Integer get(int i) { + return ByteArray.this.getInteger(i); + } + @Override + public int size() { + return ByteArray.this.size()/4; + } + }; + } + @Override public void onBytesChanged() { - } @Override public String toString(){ diff --git a/src/main/java/com/reandroid/lib/arsc/value/ResConfig.java b/src/main/java/com/reandroid/lib/arsc/value/ResConfig.java index 11a8d68..2276a14 100755 --- a/src/main/java/com/reandroid/lib/arsc/value/ResConfig.java +++ b/src/main/java/com/reandroid/lib/arsc/value/ResConfig.java @@ -1,220 +1,91 @@ package com.reandroid.lib.arsc.value; import com.reandroid.lib.arsc.base.Block; -import com.reandroid.lib.arsc.base.BlockArray; +import com.reandroid.lib.arsc.container.FixedBlockContainer; import com.reandroid.lib.arsc.io.BlockLoad; import com.reandroid.lib.arsc.io.BlockReader; import com.reandroid.lib.arsc.item.ByteArray; -import com.reandroid.lib.arsc.item.ByteItem; import com.reandroid.lib.arsc.item.IntegerItem; -import com.reandroid.lib.arsc.item.ShortItem; import java.io.IOException; -public class ResConfig extends BlockArray implements BlockLoad { +public class ResConfig extends FixedBlockContainer implements BlockLoad { + private final IntegerItem configSize; - private final ShortItem mcc; - private final ShortItem mnc; - private final ByteItem languageIn0; - private final ByteItem languageIn1; - private final ByteItem countryIn0; - private final ByteItem countryIn1; - private final ByteItem orientation; - private final ByteItem touchscreen; - private final ShortItem density; - private final ByteItem keyboard; - private final ByteItem navigation; - private final ByteItem inputFlags; - private final ByteItem inputPad0; - private final ShortItem screenWidth; - private final ShortItem screenHeight; - private final ShortItem sdkVersion; - private final ShortItem minorVersion; - private final ByteArray screenLayout; - private final ByteArray uiMode; - private final ByteArray smallestScreenWidthDp; - private final ByteArray screenWidthDp; - private final ByteArray screenHeightDp; - private final ByteArray localeScript; - private final ByteArray localeVariant; - private final ByteArray screenLayout2; - private final ByteArray colorMode; - private final ByteArray reservedPadding; - private final ByteArray skipSizeGreater56; - private final ByteArray exceedingSize; - private final ByteArray remainingSize; - private int mCurrentSize; - private boolean mIsUpdatingSize; + private final ByteArray mValuesContainer; private String mQualifiers; - public ResConfig(){ - super(); - - this.configSize = new IntegerItem(64);//4 - this.mcc = new ShortItem();//6 - this.mnc = new ShortItem();//8 - this.languageIn0 = new ByteItem();//9 - this.languageIn1 = new ByteItem();//10 - this.countryIn0 = new ByteItem();//11 - this.countryIn1 = new ByteItem();//12 - this.orientation = new ByteItem();//13 - this.touchscreen = new ByteItem();//14 - this.density = new ShortItem();//16 - this.keyboard = new ByteItem();//17 - this.navigation = new ByteItem();//18 - this.inputFlags = new ByteItem();//19 - this.inputPad0 = new ByteItem();//20 - this.screenWidth = new ShortItem();//22 - this.screenHeight = new ShortItem();//24 - this.sdkVersion = new ShortItem();//26 - this.minorVersion = new ShortItem();//28 - //28 - this.screenLayout = new ByteArray();//29 - this.uiMode = new ByteArray();//30 - this.smallestScreenWidthDp = new ByteArray();//32 - this.screenWidthDp = new ByteArray();//34 - this.screenHeightDp = new ByteArray();//36 - // size sum=44; - this.localeScript = new ByteArray(4); - this.localeVariant = new ByteArray(8); - this.screenLayout2 = new ByteArray(); - this.colorMode = new ByteArray(); - this.reservedPadding = new ByteArray(); - this.skipSizeGreater56 = new ByteArray(4); - this.exceedingSize = new ByteArray(8); - this.remainingSize = new ByteArray(); - - configSize.setBlockLoad(this); - initChildes(); - mCurrentSize=64; - setConfigSize(mCurrentSize); + super(2); + this.configSize = new IntegerItem(SIZE_64); + this.mValuesContainer = new ByteArray(SIZE_64); + addChild(0, configSize); + addChild(1, mValuesContainer); + this.configSize.setBlockLoad(this); + this.mValuesContainer.setBlockLoad(this); } - @Override - protected void onRefreshed() { - + public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { + if(sender==configSize){ + setConfigSize(configSize.get()); + }else if(sender==mValuesContainer){ + valuesChanged(); + } } - @Override - public Block newInstance() { - return null; + protected void onPreRefreshRefresh(){ + int count=countBytes(); + configSize.set(count); } - @Override - public Block[] newInstance(int len) { - return new Block[len]; + protected void onRefreshed() { + valuesChanged(); } - public void parseQualifiers(String name){ ResConfigHelper.parseQualifiers(this, name); mQualifiers=null; } - - - private void initChildes(){ - add(configSize); - add(mcc); - add(mnc); - add(languageIn0); - add(languageIn1); - add(countryIn0); - add(countryIn1); - add(orientation); - add(touchscreen); - add(density); - add(keyboard); - add(navigation); - add(inputFlags); - add(inputPad0); - add(screenWidth); - add(screenHeight); - add(sdkVersion); - add(minorVersion); - add(screenLayout); - add(uiMode); - add(smallestScreenWidthDp); - add(screenWidthDp); - add(screenHeightDp); - add(localeScript); - add(localeVariant); - add(screenLayout2); - add(colorMode); - add(reservedPadding); - add(skipSizeGreater56); - add(exceedingSize); - add(remainingSize); - } - private void resetToDefault(){ - configSize.set(0); - mcc.set((short) 0); - mnc.set((short) 0); - languageIn0.set((byte)0); - languageIn1.set((byte)0); - countryIn0.set((byte)0); - countryIn1.set((byte)0); - orientation.set((byte)0); - touchscreen.set((byte)0); - density.set((short) 0); - keyboard.set((byte)0); - navigation.set((byte)0); - inputFlags.set((byte)0); - inputPad0.set((byte)0); - screenWidth.set((short) 0); - screenHeight.set((short) 0); - sdkVersion.set((short) 0); - minorVersion.set((short) 0); - screenLayout.setSize(0); - uiMode.setSize((byte)0); - smallestScreenWidthDp.setSize((byte)0); - screenWidthDp.setSize((byte)0); - screenHeightDp.setSize((byte)0); - localeScript.clear(); - localeVariant.clear(); - screenLayout2.setSize(0); - colorMode.setSize(0); - reservedPadding.setSize( 0); - skipSizeGreater56.clear(); - exceedingSize.clear(); - remainingSize.clear(); - mCurrentSize=0; - setConfigSize(DEFAULT_CONFIG_SIZE); - } - public void setConfigSize(int i){ - this.configSize.set(i); - updateConfigSize(i); + public void setConfigSize(int size){ + if(size != SIZE_28 + && size != SIZE_32 + && size != SIZE_36 + && size != SIZE_48 + && size != SIZE_56 + && size != SIZE_64){ + throw new IllegalArgumentException("Invalid config size = " + size); + } + this.configSize.set(size); + size=size-4; + mValuesContainer.setSize(size); + valuesChanged(); } public int getConfigSize(){ return this.configSize.get(); } public void setMcc(short sh){ - this.mcc.set(sh); + mValuesContainer.putShort(OFFSET_mcc, sh); } public short getMcc(){ - return this.mcc.get(); + return mValuesContainer.getShort(OFFSET_mcc); } public void setMnc(short sh){ - this.mnc.set(sh); + mValuesContainer.putShort(OFFSET_mnc, sh); } public short getMnc(){ - return this.mnc.get(); + return mValuesContainer.getShort(OFFSET_mnc); } public void setLanguageIn0(byte b){ - byte old=languageIn0.get(); - this.languageIn0.set(b); - valuesChanged(b, old); + mValuesContainer.put(OFFSET_languageIn0, b); } public byte getLanguageIn0(){ - return this.languageIn0.get(); + return mValuesContainer.get(OFFSET_languageIn0); } public void setLanguageIn1(byte b){ - byte old=languageIn1.get(); - this.languageIn1.set(b); - valuesChanged(b, old); + mValuesContainer.put(OFFSET_languageIn1, b); } public byte getLanguageIn1(){ - return this.languageIn1.get(); + return mValuesContainer.get(OFFSET_languageIn1); } public char[] getLanguage(){ byte b0=getLanguageIn0(); @@ -232,20 +103,16 @@ public class ResConfig extends BlockArray implements BlockLoad { setLanguageIn1(bts[1]); } public void setCountryIn0(byte b){ - byte old=countryIn0.get(); - this.countryIn0.set(b); - valuesChanged(b, old); + mValuesContainer.put(OFFSET_countryIn0, b); } public byte getCountryIn0(){ - return this.countryIn0.get(); + return mValuesContainer.get(OFFSET_countryIn0); } public void setCountryIn1(byte b){ - byte old=countryIn1.get(); - this.countryIn1.set(b); - valuesChanged(b, old); + mValuesContainer.put(OFFSET_countryIn1, b); } public byte getCountryIn1(){ - return this.countryIn1.get(); + return mValuesContainer.get(OFFSET_countryIn1); } public char[] getRegion(){ byte b0=getCountryIn0(); @@ -263,203 +130,221 @@ public class ResConfig extends BlockArray implements BlockLoad { setCountryIn1(bts[1]); } public void setOrientation(byte b){ - byte old=orientation.get(); - this.orientation.set(b); - valuesChanged(b, old); + mValuesContainer.put(OFFSET_orientation, b); } public byte getOrientation(){ - return this.orientation.get(); + return mValuesContainer.get(OFFSET_orientation); } public void setTouchscreen(byte b){ - byte old=touchscreen.get(); - this.touchscreen.set(b); - valuesChanged(b, old); + mValuesContainer.put(OFFSET_touchscreen, b); } public byte getTouchscreen(){ - return this.touchscreen.get(); + return mValuesContainer.get(OFFSET_touchscreen); } public void setDensity(short sh){ - short old=density.get(); - this.density.set(sh); - valuesChanged(sh, old); + mValuesContainer.putShort(OFFSET_density, sh); } public short getDensity(){ - return this.density.get(); + return mValuesContainer.getShort(OFFSET_density); } public void setKeyboard(byte b){ - this.keyboard.set(b); + mValuesContainer.put(OFFSET_keyboard, b); } public byte getKeyboard(){ - return this.keyboard.get(); + return mValuesContainer.get(OFFSET_keyboard); } public void setNavigation(byte b){ - this.navigation.set(b); + mValuesContainer.put(OFFSET_navigation, b); } public byte getNavigation(){ - return this.navigation.get(); + return mValuesContainer.get(OFFSET_navigation); } public void setInputFlags(byte b){ - this.inputFlags.set(b); + mValuesContainer.put(OFFSET_inputFlags, b); } public byte getInputFlags(){ - return this.inputFlags.get(); + return mValuesContainer.get(OFFSET_inputFlags); } public void setInputPad0(byte b){ - this.inputPad0.set(b); + mValuesContainer.put(OFFSET_inputPad0, b); } - public byte getInputPad0(){ - return this.inputPad0.get(); + public byte setInputPad0(){ + return mValuesContainer.get(OFFSET_inputPad0); + } + public void setScreenWidth(short sh){ + mValuesContainer.putShort(OFFSET_screenWidth, sh); + } + public short getScreenWidth(){ + return mValuesContainer.getShort(OFFSET_screenWidth); + } + public void setScreenHeight(short sh){ + mValuesContainer.putShort(OFFSET_screenHeight, sh); + } + public short getScreenHeight(){ + return mValuesContainer.getShort(OFFSET_screenHeight); } public void setScreenSize(short w, short h){ this.setScreenWidth(w); this.setScreenHeight(h); } - public void setScreenWidth(short sh){ - short old=screenWidth.get(); - this.screenWidth.set(sh); - valuesChanged(sh, old); - } - public short getScreenWidth(){ - return this.screenWidth.get(); - } - public void setScreenHeight(short sh){ - short old=screenHeight.get(); - this.screenHeight.set(sh); - valuesChanged(sh, old); - } - public short getScreenHeight(){ - return this.screenHeight.get(); - } public void setSdkVersion(short sh){ - short old=sdkVersion.get(); - this.sdkVersion.set(sh); - valuesChanged(sh, old); + mValuesContainer.putShort(OFFSET_sdkVersion, sh); } public short getSdkVersion(){ - return this.sdkVersion.get(); + return mValuesContainer.getShort(OFFSET_sdkVersion); } public void setMinorVersion(short sh){ - this.minorVersion.set(sh); + mValuesContainer.putShort(OFFSET_minorVersion, sh); } public short getMinorVersion(){ - return this.minorVersion.get(); + return mValuesContainer.getShort(OFFSET_minorVersion); } public void setScreenLayout(byte b){ - if(screenLayout.size()==0){ - return; + if(getConfigSize() implements BlockLoad { public String getLocale(){ return ResConfigHelper.decodeLocale(this); } + public boolean isDefault(){ + return getQualifiers().length()==0; + } @Override public boolean equals(Object o){ if(o instanceof ResConfig){ @@ -563,9 +384,6 @@ public class ResConfig extends BlockArray implements BlockLoad { } return false; } - public boolean isDefault(){ - return getQualifiers().length()==0; - } @Override public String toString(){ String q=getQualifiers(); @@ -675,11 +493,64 @@ public class ResConfig extends BlockArray implements BlockLoad { } return true; } + private static byte[] ensureArrayLength(byte[] bts, int length){ + if(bts == null || length == 0){ + return new byte[length]; + } + if(bts.length==length){ + return bts; + } + byte[] result = new byte[length]; + int max=result.length; + if(bts.length