define apk type

This commit is contained in:
REAndroid 2023-03-28 09:35:06 -04:00
parent aac57842ed
commit 3919457f4b
5 changed files with 120 additions and 8 deletions

View File

@ -24,14 +24,13 @@ import com.reandroid.arsc.chunk.TableBlock;
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock; import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
import com.reandroid.arsc.chunk.xml.ResXmlDocument; import com.reandroid.arsc.chunk.xml.ResXmlDocument;
import com.reandroid.arsc.container.SpecTypePair; import com.reandroid.arsc.container.SpecTypePair;
import com.reandroid.arsc.decoder.Decoder;
import com.reandroid.arsc.group.StringGroup; import com.reandroid.arsc.group.StringGroup;
import com.reandroid.arsc.item.TableString; import com.reandroid.arsc.item.TableString;
import com.reandroid.arsc.pool.TableStringPool; import com.reandroid.arsc.pool.TableStringPool;
import com.reandroid.arsc.util.FrameworkTable; import com.reandroid.arsc.util.FrameworkTable;
import com.reandroid.arsc.value.Entry; import com.reandroid.arsc.value.Entry;
import com.reandroid.arsc.value.ResConfig; import com.reandroid.arsc.value.ResConfig;
import com.reandroid.common.Frameworks;
import com.reandroid.common.TableEntryStore;
import com.reandroid.xml.XMLDocument; import com.reandroid.xml.XMLDocument;
import com.reandroid.xml.XMLElement; import com.reandroid.xml.XMLElement;
import com.reandroid.xml.XMLException; import com.reandroid.xml.XMLException;
@ -47,17 +46,25 @@ public class ApkModule implements ApkFile {
private final String moduleName; private final String moduleName;
private final APKArchive apkArchive; private final APKArchive apkArchive;
private boolean loadDefaultFramework = true; private boolean loadDefaultFramework = true;
private boolean mDisableLoadFramework = false;
private TableBlock mTableBlock; private TableBlock mTableBlock;
private AndroidManifestBlock mManifestBlock; private AndroidManifestBlock mManifestBlock;
private final UncompressedFiles mUncompressedFiles; private final UncompressedFiles mUncompressedFiles;
private APKLogger apkLogger; private APKLogger apkLogger;
private TableEntryStore mEntryStore; private Decoder mDecoder;
private ApkType mApkType;
public ApkModule(String moduleName, APKArchive apkArchive){ public ApkModule(String moduleName, APKArchive apkArchive){
this.moduleName=moduleName; this.moduleName=moduleName;
this.apkArchive=apkArchive; this.apkArchive=apkArchive;
this.mUncompressedFiles=new UncompressedFiles(); this.mUncompressedFiles=new UncompressedFiles();
this.mUncompressedFiles.addPath(apkArchive); this.mUncompressedFiles.addPath(apkArchive);
} }
public String getSplit(){
if(!hasAndroidManifestBlock()){
return null;
}
return getAndroidManifestBlock().getSplit();
}
public FrameworkApk initializeAndroidFramework() throws IOException { public FrameworkApk initializeAndroidFramework() throws IOException {
if(!hasTableBlock()){ if(!hasTableBlock()){
return null; return null;
@ -485,11 +492,15 @@ public class ApkModule implements ApkFile {
archive.add(blockInputSource); archive.add(blockInputSource);
manifestBlock.setApkFile(this); manifestBlock.setApkFile(this);
mManifestBlock = manifestBlock; mManifestBlock = manifestBlock;
onManifestBlockLoaded(manifestBlock);
} catch (IOException exception) { } catch (IOException exception) {
throw new IllegalArgumentException(exception); throw new IllegalArgumentException(exception);
} }
return mManifestBlock; return mManifestBlock;
} }
private void onManifestBlockLoaded(AndroidManifestBlock manifestBlock){
initializeApkType(manifestBlock);
}
public TableBlock getTableBlock(boolean initFramework) { public TableBlock getTableBlock(boolean initFramework) {
if(mTableBlock==null){ if(mTableBlock==null){
if(!hasTableBlock()){ if(!hasTableBlock()){
@ -509,7 +520,7 @@ public class ApkModule implements ApkFile {
} }
@Override @Override
public TableBlock getTableBlock() { public TableBlock getTableBlock() {
return getTableBlock(true); return getTableBlock(!mDisableLoadFramework);
} }
@Override @Override
public ResXmlDocument loadResXmlDocument(String path) throws IOException{ public ResXmlDocument loadResXmlDocument(String path) throws IOException{
@ -522,6 +533,38 @@ public class ApkModule implements ApkFile {
resXmlDocument.readBytes(inputSource.openStream()); resXmlDocument.readBytes(inputSource.openStream());
return resXmlDocument; return resXmlDocument;
} }
@Override
public Decoder getDecoder(){
return mDecoder;
}
@Override
public void setDecoder(Decoder decoder){
this.mDecoder = decoder;
}
public ApkType getApkType(){
if(mApkType!=null){
return mApkType;
}
return initializeApkType(mManifestBlock);
}
public void setApkType(ApkType apkType){
this.mApkType = apkType;
}
private ApkType initializeApkType(AndroidManifestBlock manifestBlock){
if(mApkType!=null){
return mApkType;
}
ApkType apkType = null;
if(manifestBlock!=null){
apkType = manifestBlock.guessApkType();
}
if(apkType != null){
mApkType = apkType;
}else {
apkType = ApkType.UNKNOWN;
}
return apkType;
}
// If we need TableStringPool only, this loads pool without // If we need TableStringPool only, this loads pool without
// loading packages and other chunk blocks for faster and less memory usage // loading packages and other chunk blocks for faster and less memory usage
@ -574,6 +617,7 @@ public class ApkModule implements ApkFile {
} }
public void setLoadDefaultFramework(boolean loadDefaultFramework) { public void setLoadDefaultFramework(boolean loadDefaultFramework) {
this.loadDefaultFramework = loadDefaultFramework; this.loadDefaultFramework = loadDefaultFramework;
this.mDisableLoadFramework = !loadDefaultFramework;
} }
public void merge(ApkModule module) throws IOException { public void merge(ApkModule module) throws IOException {

View File

@ -18,6 +18,7 @@ package com.reandroid.arsc;
import com.reandroid.arsc.chunk.TableBlock; import com.reandroid.arsc.chunk.TableBlock;
import com.reandroid.arsc.chunk.xml.AndroidManifestBlock; import com.reandroid.arsc.chunk.xml.AndroidManifestBlock;
import com.reandroid.arsc.chunk.xml.ResXmlDocument; import com.reandroid.arsc.chunk.xml.ResXmlDocument;
import com.reandroid.arsc.decoder.Decoder;
import java.io.IOException; import java.io.IOException;
@ -25,4 +26,13 @@ public interface ApkFile {
AndroidManifestBlock getAndroidManifestBlock(); AndroidManifestBlock getAndroidManifestBlock();
TableBlock getTableBlock(); TableBlock getTableBlock();
ResXmlDocument loadResXmlDocument(String path) throws IOException; ResXmlDocument loadResXmlDocument(String path) throws IOException;
Decoder getDecoder();
void setDecoder(Decoder decoder);
enum ApkType {
BASE,
SPLIT,
CORE,
UNKNOWN
}
} }

View File

@ -227,6 +227,17 @@ import java.util.*;
public List<TableBlock> getFrameWorks(){ public List<TableBlock> getFrameWorks(){
return mFrameWorks; return mFrameWorks;
} }
public boolean isAndroid(){
PackageBlock packageBlock = pickOne();
if(packageBlock == null){
return false;
}
return "android".equals(packageBlock.getName())
&& packageBlock.getId() == 0x01;
}
public boolean hasFramework(){
return getFrameWorks().size() != 0;
}
public void addFramework(TableBlock tableBlock){ public void addFramework(TableBlock tableBlock){
if(tableBlock==null||tableBlock==this){ if(tableBlock==null||tableBlock==this){
return; return;

View File

@ -15,6 +15,7 @@
*/ */
package com.reandroid.arsc.chunk.xml; package com.reandroid.arsc.chunk.xml;
import com.reandroid.arsc.ApkFile;
import com.reandroid.arsc.value.ValueType; import com.reandroid.arsc.value.ValueType;
import java.io.File; import java.io.File;
@ -30,6 +31,33 @@ public class AndroidManifestBlock extends ResXmlDocument {
super(); super();
super.getStringPool().setUtf8(false); super.getStringPool().setUtf8(false);
} }
public ApkFile.ApkType guessApkType(){
if(isSplit()){
return ApkFile.ApkType.SPLIT;
}
Boolean core = isCoreApp();
if(core!=null && core){
return ApkFile.ApkType.CORE;
}
if(getMainActivity()!=null){
return ApkFile.ApkType.BASE;
}
return null;
}
public Boolean isCoreApp(){
ResXmlElement manifest = getManifestElement();
if(manifest == null){
return null;
}
ResXmlAttribute attribute = manifest.searchAttributeByName(NAME_coreApp);
if(attribute == null){
return null;
}
if(attribute.getValueType() != ValueType.INT_BOOLEAN){
return null;
}
return attribute.getValueAsBoolean();
}
public boolean isSplit(){ public boolean isSplit(){
ResXmlElement manifest = getManifestElement(); ResXmlElement manifest = getManifestElement();
if(manifest == null){ if(manifest == null){

View File

@ -35,6 +35,7 @@ import java.io.IOException;
public class Decoder { public class Decoder {
private final EntryStore entryStore; private final EntryStore entryStore;
private int currentPackageId; private int currentPackageId;
private ApkFile mApkFile;
public Decoder(EntryStore entryStore, int currentPackageId){ public Decoder(EntryStore entryStore, int currentPackageId){
this.entryStore = entryStore; this.entryStore = entryStore;
this.currentPackageId = currentPackageId; this.currentPackageId = currentPackageId;
@ -83,6 +84,15 @@ public class Decoder {
public void setCurrentPackageId(int currentPackageId) { public void setCurrentPackageId(int currentPackageId) {
this.currentPackageId = currentPackageId; this.currentPackageId = currentPackageId;
} }
public ApkFile getApkFile(){
return mApkFile;
}
public void setApkFile(ApkFile apkFile) {
this.mApkFile = apkFile;
}
public boolean isNullDecoder(){
return false;
}
public static Decoder create(ResXmlDocument resXmlDocument){ public static Decoder create(ResXmlDocument resXmlDocument){
MainChunk mainChunk = resXmlDocument.getMainChunk(); MainChunk mainChunk = resXmlDocument.getMainChunk();
@ -107,7 +117,7 @@ public class Decoder {
return create(tableBlock); return create(tableBlock);
} }
public static Decoder create(TableBlock tableBlock){ public static Decoder create(TableBlock tableBlock){
if(tableBlock.getFrameWorks().size()==0){ if(!tableBlock.hasFramework() && !tableBlock.isAndroid()){
tableBlock.addFramework(getFramework()); tableBlock.addFramework(getFramework());
} }
int currentPackageId; int currentPackageId;
@ -121,7 +131,7 @@ public class Decoder {
return create(tableBlock, currentPackageId); return create(tableBlock, currentPackageId);
} }
public static Decoder create(TableBlock tableBlock, int currentPackageId){ public static Decoder create(TableBlock tableBlock, int currentPackageId){
if(tableBlock.getFrameWorks().size()==0){ if(!tableBlock.hasFramework() && !tableBlock.isAndroid()){
TableBlock framework = getFramework(); TableBlock framework = getFramework();
if(framework!=null){ if(framework!=null){
PackageBlock packageBlock = framework.pickOne(); PackageBlock packageBlock = framework.pickOne();
@ -151,10 +161,19 @@ public class Decoder {
return NULL_ENTRY_STORE_DECODER; return NULL_ENTRY_STORE_DECODER;
} }
synchronized (Decoder.class){ synchronized (Decoder.class){
Decoder decoder = new Decoder(getFramework(), 0x7f); NullEntryDecoder decoder = new NullEntryDecoder(getFramework(), 0x7f);
NULL_ENTRY_STORE_DECODER = decoder; NULL_ENTRY_STORE_DECODER = decoder;
return decoder; return decoder;
} }
} }
private static Decoder NULL_ENTRY_STORE_DECODER; static class NullEntryDecoder extends Decoder{
public NullEntryDecoder(EntryStore entryStore, int currentPackageId) {
super(entryStore, currentPackageId);
}
@Override
public boolean isNullDecoder(){
return true;
}
}
private static NullEntryDecoder NULL_ENTRY_STORE_DECODER;
} }