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.ResXmlDocument;
import com.reandroid.arsc.container.SpecTypePair;
import com.reandroid.arsc.decoder.Decoder;
import com.reandroid.arsc.group.StringGroup;
import com.reandroid.arsc.item.TableString;
import com.reandroid.arsc.pool.TableStringPool;
import com.reandroid.arsc.util.FrameworkTable;
import com.reandroid.arsc.value.Entry;
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.XMLElement;
import com.reandroid.xml.XMLException;
@ -47,17 +46,25 @@ public class ApkModule implements ApkFile {
private final String moduleName;
private final APKArchive apkArchive;
private boolean loadDefaultFramework = true;
private boolean mDisableLoadFramework = false;
private TableBlock mTableBlock;
private AndroidManifestBlock mManifestBlock;
private final UncompressedFiles mUncompressedFiles;
private APKLogger apkLogger;
private TableEntryStore mEntryStore;
private Decoder mDecoder;
private ApkType mApkType;
public ApkModule(String moduleName, APKArchive apkArchive){
this.moduleName=moduleName;
this.apkArchive=apkArchive;
this.mUncompressedFiles=new UncompressedFiles();
this.mUncompressedFiles.addPath(apkArchive);
}
public String getSplit(){
if(!hasAndroidManifestBlock()){
return null;
}
return getAndroidManifestBlock().getSplit();
}
public FrameworkApk initializeAndroidFramework() throws IOException {
if(!hasTableBlock()){
return null;
@ -485,11 +492,15 @@ public class ApkModule implements ApkFile {
archive.add(blockInputSource);
manifestBlock.setApkFile(this);
mManifestBlock = manifestBlock;
onManifestBlockLoaded(manifestBlock);
} catch (IOException exception) {
throw new IllegalArgumentException(exception);
}
return mManifestBlock;
}
private void onManifestBlockLoaded(AndroidManifestBlock manifestBlock){
initializeApkType(manifestBlock);
}
public TableBlock getTableBlock(boolean initFramework) {
if(mTableBlock==null){
if(!hasTableBlock()){
@ -509,7 +520,7 @@ public class ApkModule implements ApkFile {
}
@Override
public TableBlock getTableBlock() {
return getTableBlock(true);
return getTableBlock(!mDisableLoadFramework);
}
@Override
public ResXmlDocument loadResXmlDocument(String path) throws IOException{
@ -522,6 +533,38 @@ public class ApkModule implements ApkFile {
resXmlDocument.readBytes(inputSource.openStream());
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
// 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) {
this.loadDefaultFramework = loadDefaultFramework;
this.mDisableLoadFramework = !loadDefaultFramework;
}
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.xml.AndroidManifestBlock;
import com.reandroid.arsc.chunk.xml.ResXmlDocument;
import com.reandroid.arsc.decoder.Decoder;
import java.io.IOException;
@ -25,4 +26,13 @@ public interface ApkFile {
AndroidManifestBlock getAndroidManifestBlock();
TableBlock getTableBlock();
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(){
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){
if(tableBlock==null||tableBlock==this){
return;

View File

@ -15,6 +15,7 @@
*/
package com.reandroid.arsc.chunk.xml;
import com.reandroid.arsc.ApkFile;
import com.reandroid.arsc.value.ValueType;
import java.io.File;
@ -30,6 +31,33 @@ public class AndroidManifestBlock extends ResXmlDocument {
super();
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(){
ResXmlElement manifest = getManifestElement();
if(manifest == null){

View File

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