mirror of
https://github.com/revanced/ARSCLib.git
synced 2025-05-01 06:34:26 +02:00
add: Overlayable & OverlayablePolicy chunk
This commit is contained in:
parent
bb1fe20f93
commit
06136b11e9
84
src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java
Normal file
84
src/main/java/com/reandroid/lib/arsc/chunk/Overlayable.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
@ -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<Integer> 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<values.length;i++){
|
||||
PolicyFlag flags = values[i];
|
||||
if((flags.getFlagValue() & flagValue)==flags.getFlagValue()){
|
||||
tmp[i]=flags;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if(count==0){
|
||||
return null;
|
||||
}
|
||||
if(count==tmp.length){
|
||||
return tmp;
|
||||
}
|
||||
PolicyFlag[] results=new PolicyFlag[count];
|
||||
int j=0;
|
||||
for(int i=0;i<tmp.length;i++){
|
||||
if(tmp[i]!=null){
|
||||
results[j]=tmp[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
public static int sum(PolicyFlag[] flagsList){
|
||||
if(flagsList==null||flagsList.length==0){
|
||||
return 0;
|
||||
}
|
||||
int results = 0;
|
||||
for(PolicyFlag flags:flagsList){
|
||||
if(flags!=null){
|
||||
results |=flags.getFlagValue();
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
public static boolean contains(PolicyFlag[] flagsList, PolicyFlag policyFlag){
|
||||
if(flagsList==null||flagsList.length==0){
|
||||
return policyFlag ==null;
|
||||
}
|
||||
if(policyFlag ==null){
|
||||
return false;
|
||||
}
|
||||
for(PolicyFlag flags:flagsList){
|
||||
if(policyFlag.equals(flags)){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
public static String toString(PolicyFlag[] flagsList){
|
||||
if(flagsList==null || flagsList.length==0){
|
||||
return "NONE";
|
||||
}
|
||||
StringBuilder builder=new StringBuilder();
|
||||
boolean appendOnce=false;
|
||||
for(PolicyFlag flags:flagsList){
|
||||
if(flags==null){
|
||||
continue;
|
||||
}
|
||||
if(appendOnce){
|
||||
builder.append('|');
|
||||
}
|
||||
builder.append(flags.name());
|
||||
appendOnce=true;
|
||||
}
|
||||
if(appendOnce){
|
||||
return builder.toString();
|
||||
}
|
||||
return "NONE";
|
||||
}
|
||||
public static PolicyFlag[] valuesOf(String flagsString){
|
||||
if(flagsString==null){
|
||||
return null;
|
||||
}
|
||||
flagsString=flagsString.trim().toUpperCase();
|
||||
String[] namesList=flagsString.split("\\s*\\|\\s*");
|
||||
PolicyFlag[] tmp = new PolicyFlag[namesList.length];
|
||||
int count=0;
|
||||
for(int i=0;i< namesList.length; i++){
|
||||
PolicyFlag flags=nameOf(namesList[i]);
|
||||
if(flags!=null){
|
||||
tmp[i]=flags;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if(count==0){
|
||||
return null;
|
||||
}
|
||||
if(count == tmp.length){
|
||||
return tmp;
|
||||
}
|
||||
PolicyFlag[] results=new PolicyFlag[count];
|
||||
int j=0;
|
||||
for(int i=0;i<tmp.length;i++){
|
||||
if(tmp[i]!=null){
|
||||
results[j]=tmp[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
public static PolicyFlag nameOf(String name){
|
||||
if(name==null){
|
||||
return null;
|
||||
}
|
||||
name=name.trim().toUpperCase();
|
||||
for(PolicyFlag flags:values()){
|
||||
if(name.equals(flags.name())){
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
@ -18,6 +18,7 @@ package com.reandroid.lib.arsc.chunk;
|
||||
import com.reandroid.lib.arsc.array.LibraryInfoArray;
|
||||
import com.reandroid.lib.arsc.array.SpecTypePairArray;
|
||||
import com.reandroid.lib.arsc.base.Block;
|
||||
import com.reandroid.lib.arsc.container.BlockList;
|
||||
import com.reandroid.lib.arsc.container.PackageLastBlocks;
|
||||
import com.reandroid.lib.arsc.container.SingleBlockContainer;
|
||||
import com.reandroid.lib.arsc.container.SpecTypePair;
|
||||
@ -57,6 +58,8 @@ package com.reandroid.lib.arsc.chunk;
|
||||
private final SpecTypePairArray mSpecTypePairArray;
|
||||
private final LibraryBlock mLibraryBlock;
|
||||
private final StagedAlias mStagedAlias;
|
||||
private final BlockList<Overlayable> mOverlayableList;
|
||||
private final BlockList<OverlayablePolicy> 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<Overlayable> getOverlayableList(){
|
||||
return mOverlayableList;
|
||||
}
|
||||
public BlockList<OverlayablePolicy> getOverlayablePolicyList(){
|
||||
return mOverlayablePolicyList;
|
||||
}
|
||||
public void sortTypes(){
|
||||
getSpecTypePairArray().sort();
|
||||
}
|
||||
|
@ -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<Overlayable> mOverlayableList;
|
||||
private final BlockList<OverlayablePolicy> mOverlayablePolicyList;
|
||||
public PackageLastBlocks(SpecTypePairArray specTypePairArray,
|
||||
LibraryBlock libraryBlock,
|
||||
StagedAlias stagedAlias){
|
||||
super(3);
|
||||
StagedAlias stagedAlias,
|
||||
BlockList<Overlayable> overlayableList,
|
||||
BlockList<OverlayablePolicy> 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());
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user