From cd819c1d0d1beffa5a587843f958db41bd4855c7 Mon Sep 17 00:00:00 2001 From: REAndroid Date: Wed, 8 Mar 2023 14:46:41 -0500 Subject: [PATCH] make accessible SpecFlag --- .../com/reandroid/arsc/chunk/SpecBlock.java | 48 ++++++++++++- .../com/reandroid/arsc/chunk/TypeBlock.java | 1 - .../arsc/chunk/xml/ResXmlElement.java | 5 +- .../reandroid/arsc/chunk/xml/ResXmlIDMap.java | 1 - .../com/reandroid/arsc/header/TypeHeader.java | 3 +- .../com/reandroid/arsc/item/IndirectItem.java | 48 +++++++++++++ .../com/reandroid/arsc/item/SpecFlag.java | 68 +++++++++++++++++++ .../reandroid/arsc/item/SpecFlagsArray.java | 22 ++++++ .../java/com/reandroid/arsc/value/Entry.java | 26 ++++++- 9 files changed, 215 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/reandroid/arsc/item/IndirectItem.java create mode 100644 src/main/java/com/reandroid/arsc/item/SpecFlag.java diff --git a/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java b/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java index 81227ed..5b86f52 100755 --- a/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/SpecBlock.java @@ -16,7 +16,6 @@ package com.reandroid.arsc.chunk; import com.reandroid.arsc.array.TypeBlockArray; - import com.reandroid.arsc.base.Block; import com.reandroid.arsc.container.SpecTypePair; import com.reandroid.arsc.header.SpecHeader; import com.reandroid.arsc.item.*; @@ -33,6 +32,9 @@ this.specFlagsArray = new SpecFlagsArray(header.getEntryCount()); addChild(specFlagsArray); } + public SpecFlag getSpecFlag(int id){ + return getSpecFlagsArray().getFlag(id); + } public SpecFlagsArray getSpecFlagsArray(){ return specFlagsArray; } @@ -106,6 +108,50 @@ getSpecFlagsArray().fromJson(json.optJSONArray(NAME_spec_flags)); } + public enum Flag{ + SPEC_PUBLIC((byte) 0x40), + SPEC_STAGED_API((byte) 0x20); + + private final byte flag; + Flag(byte flag) { + this.flag = flag; + } + public byte getFlag() { + return flag; + } + public static boolean isPublic(byte flag){ + return (SPEC_PUBLIC.flag & flag) == SPEC_PUBLIC.flag; + } + public static boolean isStagedApi(byte flag){ + return (SPEC_STAGED_API.flag & flag) == SPEC_STAGED_API.flag; + } + public static String toString(byte flagValue){ + StringBuilder builder = new StringBuilder(); + boolean appendOnce = false; + int sum = 0; + int flagValueInt = flagValue & 0xff; + for(Flag flag:values()){ + int flagInt = flag.flag & 0xff; + if((flagInt & flagValueInt) != flagInt){ + continue; + } + if(appendOnce){ + builder.append('|'); + } + builder.append(flag); + appendOnce = true; + sum = sum | flagInt; + } + if(sum != flagValueInt){ + if(appendOnce){ + builder.append('|'); + } + builder.append(String.format("0x%02x", flagValueInt)); + } + return builder.toString(); + } + } + public static final String NAME_spec = "spec"; public static final String NAME_spec_flags = "spec_flags"; public static final String NAME_flag = "flag"; diff --git a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java index baed726..261d14a 100755 --- a/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java +++ b/src/main/java/com/reandroid/arsc/chunk/TypeBlock.java @@ -25,7 +25,6 @@ import com.reandroid.arsc.item.*; import com.reandroid.arsc.pool.TypeStringPool; import com.reandroid.arsc.value.Entry; import com.reandroid.arsc.value.ResConfig; -import com.reandroid.arsc.value.ValueType; import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONObject; diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlElement.java b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlElement.java index 697cf57..e0da7e3 100755 --- a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlElement.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlElement.java @@ -303,12 +303,15 @@ return null; } public ResXmlIDMap getResXmlIDMap(){ - ResXmlDocument resXmlDocument = getParentInstance(ResXmlDocument.class); + ResXmlDocument resXmlDocument = getParentDocument(); if(resXmlDocument!=null){ return resXmlDocument.getResXmlIDMap(); } return null; } + public ResXmlDocument getParentDocument(){ + return getParentInstance(ResXmlDocument.class); + } public int getDepth(){ return mDepth; diff --git a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlIDMap.java b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlIDMap.java index a28670f..cfdb64b 100755 --- a/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlIDMap.java +++ b/src/main/java/com/reandroid/arsc/chunk/xml/ResXmlIDMap.java @@ -15,7 +15,6 @@ */ package com.reandroid.arsc.chunk.xml; - import com.reandroid.arsc.base.Block; import com.reandroid.arsc.chunk.ChunkType; import com.reandroid.arsc.array.ResXmlIDArray; import com.reandroid.arsc.chunk.Chunk; diff --git a/src/main/java/com/reandroid/arsc/header/TypeHeader.java b/src/main/java/com/reandroid/arsc/header/TypeHeader.java index f9fe51d..1c73584 100644 --- a/src/main/java/com/reandroid/arsc/header/TypeHeader.java +++ b/src/main/java/com/reandroid/arsc/header/TypeHeader.java @@ -70,7 +70,6 @@ public class TypeHeader extends HeaderBlock{ +", flags=" + getFlags().toHex() +", count=" + getCount() +", entriesStart=" + getEntriesStart() - +", config=" + getConfig() - +", flags=" + getFlags().toHex() + '}'; + +", config=" + getConfig() + '}'; } } diff --git a/src/main/java/com/reandroid/arsc/item/IndirectItem.java b/src/main/java/com/reandroid/arsc/item/IndirectItem.java new file mode 100644 index 0000000..47e6133 --- /dev/null +++ b/src/main/java/com/reandroid/arsc/item/IndirectItem.java @@ -0,0 +1,48 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.arsc.item; + +import java.util.Objects; + +public class IndirectItem { + private final T blockItem; + private final int offset; + public IndirectItem(T blockItem, int offset){ + this.blockItem = blockItem; + this.offset = offset; + } + public T getBlockItem() { + return blockItem; + } + public int getOffset() { + return offset; + } + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + IndirectItem other = (IndirectItem) obj; + return this.getOffset() == other.getOffset() && this.getBlockItem() == other.getBlockItem(); + } + @Override + public int hashCode(){ + return Objects.hash(this.getOffset(), this.getBlockItem()); + } +} diff --git a/src/main/java/com/reandroid/arsc/item/SpecFlag.java b/src/main/java/com/reandroid/arsc/item/SpecFlag.java new file mode 100644 index 0000000..8c3cbd8 --- /dev/null +++ b/src/main/java/com/reandroid/arsc/item/SpecFlag.java @@ -0,0 +1,68 @@ + /* + * Copyright (C) 2022 github.com/REAndroid + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.reandroid.arsc.item; + +import com.reandroid.arsc.chunk.SpecBlock; + +public class SpecFlag extends IndirectItem { + public SpecFlag(SpecFlagsArray specFlagsArray, int offset) { + super(specFlagsArray, offset); + } + public byte getFlagByte(){ + return getBlockItem().getBytesInternal()[getOffset() + OFFSET_FLAG]; + } + public void setFlagByte(byte flag){ + getBlockItem().getBytesInternal()[getOffset() + OFFSET_FLAG] = flag; + } + public void addFlagByte(byte flag){ + flag = (byte) ((getFlagByte() & 0xff) | (flag & 0xff)); + setFlagByte(flag); + } + public void addFlag(SpecBlock.Flag flag){ + addFlagByte(flag.getFlag()); + } + public void setPublic(){ + addFlag(SpecBlock.Flag.SPEC_PUBLIC); + } + public boolean isPublic(){ + return SpecBlock.Flag.isPublic(getFlagByte()); + } + public int getInteger(){ + return BlockItem.getInteger(this.getBlockItem().getBytesInternal(), this.getOffset()); + } + public void setInteger(int value){ + if(value == getInteger()){ + return; + } + BlockItem.putInteger(this.getBlockItem().getBytesInternal(), this.getOffset(), value); + this.getBlockItem().onBytesChanged(); + } + @Override + public String toString(){ + byte flag = getFlagByte(); + if(flag != 0){ + return SpecBlock.Flag.toString(getFlagByte()); + } + int val = getInteger(); + if(val != 0){ + return String.format("0x%08x", val); + } + return ""; + } + + private static final int OFFSET_FLAG = 3; + +} diff --git a/src/main/java/com/reandroid/arsc/item/SpecFlagsArray.java b/src/main/java/com/reandroid/arsc/item/SpecFlagsArray.java index 4702958..71ff5ce 100644 --- a/src/main/java/com/reandroid/arsc/item/SpecFlagsArray.java +++ b/src/main/java/com/reandroid/arsc/item/SpecFlagsArray.java @@ -25,15 +25,37 @@ import com.reandroid.json.JSONConvert; import com.reandroid.json.JSONObject; import java.io.IOException; +import java.util.AbstractList; public class SpecFlagsArray extends IntegerArray implements BlockLoad, JSONConvert { private final IntegerItem entryCount; + private AbstractList specFlagList; public SpecFlagsArray(IntegerItem entryCount) { super(); this.entryCount = entryCount; this.entryCount.setBlockLoad(this); setBlockLoad(this); } + public AbstractList listSpecFlags(){ + if(specFlagList==null){ + specFlagList = new AbstractList() { + @Override + public SpecFlag get(int i) { + return SpecFlagsArray.this.getFlag(i); + } + @Override + public int size() { + return SpecFlagsArray.this.size(); + } + }; + } + return specFlagList; + } + public SpecFlag getFlag(int id){ + int offset = id & 0xffff; + offset = offset * 4; + return new SpecFlag(this, offset); + } public void set(int entryId, int value){ setFlag(entryId, value); refresh(); diff --git a/src/main/java/com/reandroid/arsc/value/Entry.java b/src/main/java/com/reandroid/arsc/value/Entry.java index 6be251a..443b7c2 100755 --- a/src/main/java/com/reandroid/arsc/value/Entry.java +++ b/src/main/java/com/reandroid/arsc/value/Entry.java @@ -18,8 +18,10 @@ import com.reandroid.arsc.base.Block; import com.reandroid.arsc.base.BlockCounter; import com.reandroid.arsc.chunk.PackageBlock; + import com.reandroid.arsc.chunk.SpecBlock; import com.reandroid.arsc.chunk.TableBlock; import com.reandroid.arsc.chunk.TypeBlock; + import com.reandroid.arsc.container.SpecTypePair; import com.reandroid.arsc.group.EntryGroup; import com.reandroid.arsc.io.BlockReader; import com.reandroid.arsc.item.*; @@ -37,6 +39,13 @@ super(); } + public SpecFlag getSpecFlag(){ + SpecBlock specBlock = getSpecBlock(); + if(specBlock == null){ + return null; + } + return specBlock.getSpecFlag(getId()); + } public void ensureComplex(boolean isComplex){ ensureTableEntry(isComplex); } @@ -161,7 +170,17 @@ } return null; } - + public SpecBlock getSpecBlock(){ + TypeBlock typeBlock = getTypeBlock(); + if(typeBlock == null){ + return null; + } + SpecTypePair specTypePair = typeBlock.getParentSpecTypePair(); + if(specTypePair==null){ + return null; + } + return specTypePair.getSpecBlock(); + } public TypeBlock getTypeBlock(){ return getParent(TypeBlock.class); } @@ -394,6 +413,11 @@ builder.append(resConfig); builder.append(' '); } + SpecFlag specFlag = getSpecFlag(); + if(specFlag!=null){ + builder.append(specFlag); + builder.append(' '); + } if(isNull()){ builder.append("NULL"); return builder.toString();