From 06136b11e9c69db5bfb497c6808517a2d6795f35 Mon Sep 17 00:00:00 2001 From: REAndroid Date: Thu, 29 Dec 2022 08:56:44 -0500 Subject: [PATCH] add: Overlayable & OverlayablePolicy chunk --- .../reandroid/lib/arsc/chunk/Overlayable.java | 84 ++++++ .../lib/arsc/chunk/OverlayablePolicy.java | 242 ++++++++++++++++++ .../lib/arsc/chunk/PackageBlock.java | 18 +- .../lib/arsc/container/PackageLastBlocks.java | 30 ++- .../lib/arsc/header/HeaderBlock.java | 4 +- 5 files changed, 370 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java create mode 100644 src/main/java/com/reandroid/lib/arsc/chunk/OverlayablePolicy.java diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java b/src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java new file mode 100644 index 0000000..e311b20 --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java @@ -0,0 +1,84 @@ + /* + * 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.lib.arsc.chunk; + + import com.reandroid.lib.arsc.base.Block; + import com.reandroid.lib.arsc.header.HeaderBlock; + 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.FixedLengthString; + + import java.io.IOException; + + /** + * Replica of struct "ResTable_overlayable_header" as on AOSP androidfw/ResourceTypes.h + * We didn't test this class with resource table, if someone found a resource/apk please + * create issue on https://github.com/REAndroid/ARSCLib + * */ + public class Overlayable extends BaseChunk implements BlockLoad { + private final FixedLengthString name; + private final FixedLengthString actor; + /** + * @link body + * As on AOSP there is only a description of header struct but no mention about + * chunk-content/body, thus we will use empty body byte array to avoid parse error + * */ + private final ByteArray body; + public Overlayable() { + super(ChunkType.OVERLAYABLE, 1); + this.name = new FixedLengthString(512); + this.actor = new FixedLengthString(512); + this.body = new ByteArray(); + addToHeader(this.name); + addToHeader(this.actor); + addChild(this.body); + this.actor.setBlockLoad(this); + } + public ByteArray getBody() { + return body; + } + public String getName(){ + return this.name.get(); + } + public void setName(String str){ + this.name.set(str); + } + public String getActor(){ + return this.actor.get(); + } + public void setActor(String str){ + this.actor.set(str); + } + @Override + public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { + if(sender==this.actor){ + HeaderBlock header = getHeaderBlock(); + int bodySize=header.getChunkSize()-header.getHeaderSize(); + this.body.setSize(bodySize); + } + } + @Override + protected void onChunkRefreshed() { + } + @Override + public String toString(){ + return getClass().getSimpleName()+ + ": name='"+getName() + +"', actor='"+getActor() + +"', body-size="+getBody().size(); + } + } diff --git a/src/main/java/com/reandroid/lib/arsc/chunk/OverlayablePolicy.java b/src/main/java/com/reandroid/lib/arsc/chunk/OverlayablePolicy.java new file mode 100644 index 0000000..8bed73d --- /dev/null +++ b/src/main/java/com/reandroid/lib/arsc/chunk/OverlayablePolicy.java @@ -0,0 +1,242 @@ + /* + * 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.lib.arsc.chunk; + + import com.reandroid.lib.arsc.base.Block; + import com.reandroid.lib.arsc.io.BlockLoad; + import com.reandroid.lib.arsc.io.BlockReader; + import com.reandroid.lib.arsc.item.IntegerArray; + import com.reandroid.lib.arsc.item.IntegerItem; + + import java.io.IOException; + import java.util.Collection; + + /** + * Replica of struct "ResTable_overlayable_policy_header" as on AOSP androidfw/ResourceTypes.h + * We didn't test this class with resource table, if someone found a resource/apk please + * create issue on https://github.com/REAndroid/ARSCLib + * */ + public class OverlayablePolicy extends BaseChunk implements BlockLoad { + private final IntegerItem flags; + private final IntegerItem entryCount; + private final IntegerArray tableRefArray; + public OverlayablePolicy(){ + super(ChunkType.OVERLAYABLE_POLICY, 1); + this.flags = new IntegerItem(); + this.entryCount = new IntegerItem(); + this.tableRefArray = new IntegerArray(); + + addToHeader(this.flags); + addToHeader(this.entryCount); + + addChild(this.tableRefArray); + + this.entryCount.setBlockLoad(this); + } + @Override + public boolean isNull() { + return getTableReferenceCount()==0; + } + public int getTableReferenceCount(){ + return getTableRefArray().size(); + } + + public Collection listTableReferences(){ + return getTableRefArray().toList(); + } + public IntegerArray getTableRefArray() { + return tableRefArray; + } + public int getFlags() { + return flags.get(); + } + public void setFlags(int flags){ + this.flags.set(flags); + } + public void setFlags(PolicyFlag[] policyFlags){ + setFlags(PolicyFlag.sum(policyFlags)); + } + public void addFlag(PolicyFlag policyFlag){ + int i = policyFlag==null? 0 : policyFlag.getFlagValue(); + setFlags(getFlags() | i); + } + public PolicyFlag[] getPolicyFlags(){ + return PolicyFlag.valuesOf(getFlags()); + } + @Override + protected void onChunkRefreshed() { + this.entryCount.set(getTableRefArray().size()); + } + @Override + public void onBlockLoaded(BlockReader reader, Block sender) throws IOException { + if(sender==this.entryCount){ + this.tableRefArray.setSize(entryCount.get()); + } + } + @Override + public String toString(){ + return getClass().getSimpleName()+ + ": flags="+ PolicyFlag.toString(getPolicyFlags()) + +"', count="+getTableReferenceCount(); + } + + public enum PolicyFlag { + + PUBLIC(0x00000001), + SYSTEM_PARTITION(0x00000002), + VENDOR_PARTITION(0x00000004), + PRODUCT_PARTITION(0x00000008), + SIGNATURE(0x00000010), + ODM_PARTITION(0x00000020), + OEM_PARTITION(0x00000040), + ACTOR_SIGNATURE(0x00000080), + CONFIG_SIGNATURE(0x00000100); + + private final int flag; + PolicyFlag(int flag) { + this.flag=flag; + } + public int getFlagValue(){ + return this.flag; + } + + public boolean contains(int flagsValue){ + return (this.flag & flagsValue)==this.flag; + } + + public static PolicyFlag[] valuesOf(int flagValue){ + if(flagValue==0){ + return null; + } + PolicyFlag[] values = values(); + PolicyFlag[] tmp = new PolicyFlag[values.length]; + int count=0; + for(int i=0;i mOverlayableList; + private final BlockList mOverlayablePolicyList; private final PackageLastBlocks mPackageLastBlocks; @@ -83,10 +86,14 @@ package com.reandroid.lib.arsc.chunk; this.mSpecTypePairArray=new SpecTypePairArray(); this.mLibraryBlock=new LibraryBlock(); this.mStagedAlias=new StagedAlias(); + this.mOverlayableList=new BlockList<>(); + this.mOverlayablePolicyList=new BlockList<>(); this.mPackageLastBlocks = new PackageLastBlocks( mSpecTypePairArray, mLibraryBlock, - mStagedAlias); + mStagedAlias, + mOverlayableList, + mOverlayablePolicyList); this.mEntriesGroup=new HashMap<>(); @@ -106,6 +113,15 @@ package com.reandroid.lib.arsc.chunk; addChild(mPackageLastBlocks); } + public StagedAlias getStagedAlias(){ + return mStagedAlias; + } + public BlockList getOverlayableList(){ + return mOverlayableList; + } + public BlockList getOverlayablePolicyList(){ + return mOverlayablePolicyList; + } public void sortTypes(){ getSpecTypePairArray().sort(); } diff --git a/src/main/java/com/reandroid/lib/arsc/container/PackageLastBlocks.java b/src/main/java/com/reandroid/lib/arsc/container/PackageLastBlocks.java index a36314a..9fa1611 100755 --- a/src/main/java/com/reandroid/lib/arsc/container/PackageLastBlocks.java +++ b/src/main/java/com/reandroid/lib/arsc/container/PackageLastBlocks.java @@ -15,10 +15,8 @@ */ package com.reandroid.lib.arsc.container; -import com.reandroid.lib.arsc.chunk.ChunkType; +import com.reandroid.lib.arsc.chunk.*; import com.reandroid.lib.arsc.array.SpecTypePairArray; -import com.reandroid.lib.arsc.chunk.LibraryBlock; -import com.reandroid.lib.arsc.chunk.StagedAlias; import com.reandroid.lib.arsc.header.HeaderBlock; import com.reandroid.lib.arsc.io.BlockReader; @@ -29,16 +27,24 @@ public class PackageLastBlocks extends FixedBlockContainer { private final SpecTypePairArray mSpecTypePairArray; private final LibraryBlock mLibraryBlock; private final StagedAlias mStagedAlias; + private final BlockList mOverlayableList; + private final BlockList mOverlayablePolicyList; public PackageLastBlocks(SpecTypePairArray specTypePairArray, LibraryBlock libraryBlock, - StagedAlias stagedAlias){ - super(3); + StagedAlias stagedAlias, + BlockList overlayableList, + BlockList overlayablePolicyList){ + super(5); this.mSpecTypePairArray=specTypePairArray; this.mLibraryBlock=libraryBlock; this.mStagedAlias=stagedAlias; + this.mOverlayableList=overlayableList; + this.mOverlayablePolicyList=overlayablePolicyList; addChild(0, mSpecTypePairArray); addChild(1, mLibraryBlock); addChild(2, mStagedAlias); + addChild(3, mOverlayableList); + addChild(4, mOverlayablePolicyList); } @Override @@ -59,6 +65,10 @@ public class PackageLastBlocks extends FixedBlockContainer { readSpecBlock(reader); }else if(chunkType==ChunkType.LIBRARY){ readLibraryBlock(reader); + }else if(chunkType==ChunkType.OVERLAYABLE){ + readOverlayable(reader); + }else if(chunkType==ChunkType.OVERLAYABLE_POLICY){ + readOverlayablePolicy(reader); }else if(chunkType==ChunkType.STAGED_ALIAS){ readStagedAlias(reader); }else { @@ -80,6 +90,16 @@ public class PackageLastBlocks extends FixedBlockContainer { stagedAlias.readBytes(reader); mStagedAlias.addStagedAliasEntries(stagedAlias); } + private void readOverlayable(BlockReader reader) throws IOException{ + Overlayable overlayable = new Overlayable(); + overlayable.readBytes(reader); + mOverlayableList.add(overlayable); + } + private void readOverlayablePolicy(BlockReader reader) throws IOException{ + OverlayablePolicy overlayablePolicy = new OverlayablePolicy(); + overlayablePolicy.readBytes(reader); + mOverlayablePolicyList.add(overlayablePolicy); + } private void readUnexpectedBlock(BlockReader reader, HeaderBlock headerBlock) throws IOException{ throw new IOException(reader.getActualPosition()+", Unexpected block: "+headerBlock.toString()); } diff --git a/src/main/java/com/reandroid/lib/arsc/header/HeaderBlock.java b/src/main/java/com/reandroid/lib/arsc/header/HeaderBlock.java index d7c4ef2..00b31a4 100755 --- a/src/main/java/com/reandroid/lib/arsc/header/HeaderBlock.java +++ b/src/main/java/com/reandroid/lib/arsc/header/HeaderBlock.java @@ -53,8 +53,8 @@ public class HeaderBlock extends ExpandableBlockContainer { mType.set(type); } - public short getHeaderSize(){ - return mHeaderSize.get(); + public int getHeaderSize(){ + return (0xffff & mHeaderSize.get()); } public void setHeaderSize(short headerSize){ mHeaderSize.set(headerSize);