implement new AndroidFrameworks

This commit is contained in:
REAndroid 2023-03-13 14:33:10 -04:00
parent 26b7ead67f
commit d3ef84c59f
8 changed files with 111 additions and 55 deletions

View File

@ -38,7 +38,6 @@ javadoc {
jar { jar {
exclude('com/reandroid/test/**') exclude('com/reandroid/test/**')
exclude('com/reandroid/facebook/**')
} }
task fatJar(type: Jar) { task fatJar(type: Jar) {

View File

@ -33,6 +33,7 @@ import com.reandroid.arsc.value.ResConfig;
import com.reandroid.common.Frameworks; import com.reandroid.common.Frameworks;
import com.reandroid.common.TableEntryStore; import com.reandroid.common.TableEntryStore;
import com.reandroid.xml.XMLDocument; import com.reandroid.xml.XMLDocument;
import com.reandroid.xml.XMLElement;
import com.reandroid.xml.XMLException; import com.reandroid.xml.XMLException;
import java.io.File; import java.io.File;
@ -57,27 +58,31 @@ public class ApkModule implements ApkFile {
this.mUncompressedFiles=new UncompressedFiles(); this.mUncompressedFiles=new UncompressedFiles();
this.mUncompressedFiles.addPath(apkArchive); this.mUncompressedFiles.addPath(apkArchive);
} }
public void initializeAndroidFramework() throws IOException { public FrameworkApk initializeAndroidFramework() throws IOException {
if(!hasTableBlock()){ if(!hasTableBlock()){
return; return null;
} }
initializeAndroidFramework(getTableBlock()); Integer version = getAndroidFrameworkVersion();
return initializeAndroidFramework(getTableBlock(false), version);
} }
private void initializeAndroidFramework(TableBlock tableBlock) throws IOException { private FrameworkApk initializeAndroidFramework(TableBlock tableBlock, Integer version) throws IOException {
if(tableBlock == null || isAndroid(tableBlock)){ if(tableBlock == null || isAndroid(tableBlock)){
return; return null;
} }
List<TableBlock> frameWorkList = tableBlock.getFrameWorks(); List<TableBlock> frameWorkList = tableBlock.getFrameWorks();
for(TableBlock frameWork:frameWorkList){ for(TableBlock frameWork:frameWorkList){
if(isAndroid(frameWork)){ if(isAndroid(frameWork)){
return; ApkFile apkFile = frameWork.getApkFile();
if(apkFile instanceof FrameworkApk){
return (FrameworkApk) apkFile;
}
return null;
} }
} }
logMessage("Initializing android framework ..."); logMessage("Initializing android framework ...");
Integer version = getAndroidFrameworkVersion();
FrameworkApk frameworkApk; FrameworkApk frameworkApk;
if(version==null){ if(version==null){
logMessage("Can not read framework version from manifest, loading latest"); logMessage("Can not read framework version, loading latest");
frameworkApk = AndroidFrameworks.getLatest(); frameworkApk = AndroidFrameworks.getLatest();
}else { }else {
logMessage("Loading android framework for version: " + version); logMessage("Loading android framework for version: " + version);
@ -86,6 +91,7 @@ public class ApkModule implements ApkFile {
FrameworkTable frameworkTable = frameworkApk.getTableBlock(); FrameworkTable frameworkTable = frameworkApk.getTableBlock();
tableBlock.addFramework(frameworkTable); tableBlock.addFramework(frameworkTable);
logMessage("Initialized framework: "+frameworkApk.getName()); logMessage("Initialized framework: "+frameworkApk.getName());
return frameworkApk;
} }
private boolean isAndroid(TableBlock tableBlock){ private boolean isAndroid(TableBlock tableBlock){
if(tableBlock instanceof FrameworkTable){ if(tableBlock instanceof FrameworkTable){
@ -94,6 +100,60 @@ public class ApkModule implements ApkFile {
} }
return false; return false;
} }
public FrameworkApk initializeAndroidFramework(XMLDocument xmlDocument) throws IOException {
TableBlock tableBlock = getTableBlock(false);
if(isAndroidCoreApp(xmlDocument)){
logMessage("Looks framework itself, skip loading frameworks");
return null;
}
Integer version = readCompileVersionCode(xmlDocument);
return initializeAndroidFramework(tableBlock, version);
}
private boolean isAndroidCoreApp(XMLDocument manifestDocument){
XMLElement root = manifestDocument.getDocumentElement();
if(root == null){
return false;
}
if(!"android".equals(root.getAttributeValue("package"))){
return false;
}
String coreApp = root.getAttributeValue("coreApp");
return "true".equals(coreApp);
}
private Integer readCompileVersionCode(XMLDocument manifestDocument) {
XMLElement root = manifestDocument.getDocumentElement();
String versionString = readVersionCodeString(root);
if(versionString==null){
return null;
}
try{
return Integer.parseInt(versionString);
}catch (NumberFormatException exception){
logMessage("NumberFormatException on manifest version reading: '"
+versionString+"': "+exception.getMessage());
return null;
}
}
private String readVersionCodeString(XMLElement manifestRoot){
String versionString = manifestRoot.getAttributeValue("android:compileSdkVersion");
if(versionString!=null){
return versionString;
}
versionString = manifestRoot.getAttributeValue("platformBuildVersionCode");
if(versionString!=null){
return versionString;
}
for(XMLElement element:manifestRoot.listChildElements()){
if(AndroidManifestBlock.TAG_uses_sdk.equals(element.getTagName())){
versionString = element.getAttributeValue("android:targetSdkVersion");
if(versionString!=null){
return versionString;
}
}
}
return null;
}
public Integer getAndroidFrameworkVersion(){ public Integer getAndroidFrameworkVersion(){
if(!hasAndroidManifestBlock()){ if(!hasAndroidManifestBlock()){
return null; return null;
@ -148,16 +208,7 @@ public class ApkModule implements ApkFile {
ResXmlDocument resXmlDocument = loadResXmlDocument(path); ResXmlDocument resXmlDocument = loadResXmlDocument(path);
AndroidManifestBlock manifestBlock = getAndroidManifestBlock(); AndroidManifestBlock manifestBlock = getAndroidManifestBlock();
int pkgId = manifestBlock.guessCurrentPackageId(); int pkgId = manifestBlock.guessCurrentPackageId();
return resXmlDocument.decodeToXml(getTableEntryStore(), pkgId); return resXmlDocument.decodeToXml(getTableBlock(), pkgId);
}
private TableEntryStore getTableEntryStore() throws IOException {
if(mEntryStore!=null){
return mEntryStore;
}
mEntryStore = new TableEntryStore();
mEntryStore.add(getTableBlock());
mEntryStore.add(Frameworks.getAndroid());
return mEntryStore;
} }
public List<DexFileInputSource> listDexFiles(){ public List<DexFileInputSource> listDexFiles(){
List<DexFileInputSource> results=new ArrayList<>(); List<DexFileInputSource> results=new ArrayList<>();
@ -436,16 +487,16 @@ public class ApkModule implements ApkFile {
} }
return mManifestBlock; return mManifestBlock;
} }
@Override public TableBlock getTableBlock(boolean initFramework) {
public TableBlock getTableBlock() {
if(mTableBlock==null){ if(mTableBlock==null){
if(!hasTableBlock()){ if(!hasTableBlock()){
return null; return null;
} }
try { try {
mTableBlock = loadTableBlock(); mTableBlock = loadTableBlock();
if(loadDefaultFramework){ if(initFramework && loadDefaultFramework){
initializeAndroidFramework(mTableBlock); Integer version = getAndroidFrameworkVersion();
initializeAndroidFramework(mTableBlock, version);
} }
} catch (IOException exception) { } catch (IOException exception) {
throw new IllegalArgumentException(exception); throw new IllegalArgumentException(exception);
@ -454,6 +505,10 @@ public class ApkModule implements ApkFile {
return mTableBlock; return mTableBlock;
} }
@Override @Override
public TableBlock getTableBlock() {
return getTableBlock(true);
}
@Override
public ResXmlDocument loadResXmlDocument(String path) throws IOException{ public ResXmlDocument loadResXmlDocument(String path) throws IOException{
InputSource inputSource = getApkArchive().getInputSource(path); InputSource inputSource = getApkArchive().getInputSource(path);
if(inputSource==null){ if(inputSource==null){

View File

@ -27,8 +27,6 @@ import com.reandroid.arsc.container.SpecTypePair;
import com.reandroid.arsc.decoder.ValueDecoder; import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.*; import com.reandroid.arsc.value.*;
import com.reandroid.common.EntryStore; import com.reandroid.common.EntryStore;
import com.reandroid.common.Frameworks;
import com.reandroid.common.TableEntryStore;
import com.reandroid.json.JSONObject; import com.reandroid.json.JSONObject;
import com.reandroid.xml.XMLAttribute; import com.reandroid.xml.XMLAttribute;
import com.reandroid.xml.XMLDocument; import com.reandroid.xml.XMLDocument;
@ -55,27 +53,25 @@ import java.util.*;
this.decodedEntries.clear(); this.decodedEntries.clear();
logMessage("Decoding ..."); logMessage("Decoding ...");
decodeUncompressedFiles(outDir); decodeUncompressedFiles(outDir);
TableEntryStore entryStore=new TableEntryStore(); apkModule.initializeAndroidFramework();
entryStore.add(Frameworks.getAndroid());
TableBlock tableBlock=apkModule.getTableBlock(); TableBlock tableBlock=apkModule.getTableBlock();
entryStore.add(tableBlock);
decodePackageInfo(outDir, tableBlock); decodePackageInfo(outDir, tableBlock);
xmlBagDecoder=new XMLBagDecoder(entryStore); xmlBagDecoder=new XMLBagDecoder(tableBlock);
decodePublicXml(tableBlock, outDir); decodePublicXml(tableBlock, outDir);
decodeAndroidManifest(entryStore, outDir); decodeAndroidManifest(tableBlock, outDir);
addDecodedPath(TableBlock.FILE_NAME); addDecodedPath(TableBlock.FILE_NAME);
logMessage("Decoding resource files ..."); logMessage("Decoding resource files ...");
List<ResFile> resFileList=apkModule.listResFiles(); List<ResFile> resFileList=apkModule.listResFiles();
for(ResFile resFile:resFileList){ for(ResFile resFile:resFileList){
decodeResFile(entryStore, outDir, resFile); decodeResFile(tableBlock, outDir, resFile);
} }
decodeValues(entryStore, outDir, tableBlock); decodeValues(tableBlock, outDir, tableBlock);
extractRootFiles(outDir); extractRootFiles(outDir);
} }

View File

@ -16,6 +16,7 @@
package com.reandroid.apk.xmlencoder; package com.reandroid.apk.xmlencoder;
import com.reandroid.apk.APKLogger; import com.reandroid.apk.APKLogger;
import com.reandroid.apk.FrameworkApk;
import com.reandroid.apk.ResourceIds; import com.reandroid.apk.ResourceIds;
import com.reandroid.arsc.chunk.PackageBlock; import com.reandroid.arsc.chunk.PackageBlock;
import com.reandroid.arsc.chunk.TableBlock; import com.reandroid.arsc.chunk.TableBlock;
@ -282,6 +283,12 @@
this.currentPackage = currentPackage; this.currentPackage = currentPackage;
return this; return this;
} }
public EncodeMaterials addFramework(FrameworkApk frameworkApk) {
if(frameworkApk!=null){
addFramework(frameworkApk.getTableBlock());
}
return this;
}
public EncodeMaterials addFramework(FrameworkTable frameworkTable) { public EncodeMaterials addFramework(FrameworkTable frameworkTable) {
frameworkTable.loadResourceNameMap(); frameworkTable.loadResourceNameMap();
this.frameworkTables.add(frameworkTable); this.frameworkTables.add(frameworkTable);
@ -333,10 +340,16 @@
ResourceIds resourceIds = new ResourceIds(); ResourceIds resourceIds = new ResourceIds();
resourceIds.loadPackageBlock(packageBlock); resourceIds.loadPackageBlock(packageBlock);
ResourceIds.Table.Package packageId = resourceIds.getTable().listPackages().get(0); ResourceIds.Table.Package packageId = resourceIds.getTable().listPackages().get(0);
return new EncodeMaterials() EncodeMaterials encodeMaterials = new EncodeMaterials()
.addPackageIds(packageId) .addPackageIds(packageId)
.setCurrentPackage(packageBlock) .setCurrentPackage(packageBlock);
.addFramework(Frameworks.getAndroid()); TableBlock tableBlock = packageBlock.getTableBlock();
for(TableBlock frameworkTable:tableBlock.getFrameWorks()){
if(frameworkTable instanceof FrameworkTable){
encodeMaterials.addFramework((FrameworkTable) frameworkTable);
}
}
return encodeMaterials;
} }
} }

View File

@ -20,7 +20,6 @@
import com.reandroid.arsc.chunk.PackageBlock; import com.reandroid.arsc.chunk.PackageBlock;
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.common.Frameworks;
import com.reandroid.xml.XMLDocument; import com.reandroid.xml.XMLDocument;
import com.reandroid.xml.XMLException; import com.reandroid.xml.XMLException;
import com.reandroid.xml.source.XMLFileSource; import com.reandroid.xml.source.XMLFileSource;
@ -162,12 +161,18 @@
List<File> pubXmlFileList, EncodeMaterials encodeMaterials) List<File> pubXmlFileList, EncodeMaterials encodeMaterials)
throws IOException, XMLException { throws IOException, XMLException {
encodeMaterials.setAPKLogger(apkLogger);
Map<File, ResourceIds.Table.Package> results = new HashMap<>(); Map<File, ResourceIds.Table.Package> results = new HashMap<>();
String packageName=null; String packageName=null;
for(File pubXmlFile:pubXmlFileList){ for(File pubXmlFile:pubXmlFileList){
if(packageName==null){ if(packageName==null){
packageName=readManifestPackageName(toAndroidManifest(pubXmlFile)); File manifestFile = toAndroidManifest(pubXmlFile);
packageName=readManifestPackageName(manifestFile);
FrameworkApk frameworkApk = getApkModule()
.initializeAndroidFramework(XMLDocument.load(manifestFile));
encodeMaterials.addFramework(frameworkApk);
} }
ResourceIds resourceIds=new ResourceIds(); ResourceIds resourceIds=new ResourceIds();
resourceIds.fromXml(pubXmlFile); resourceIds.fromXml(pubXmlFile);
@ -184,8 +189,7 @@
results.put(pubXmlFile, pkg); results.put(pubXmlFile, pkg);
} }
encodeMaterials.addFramework(Frameworks.getAndroid()) encodeMaterials.setAPKLogger(apkLogger);
.setAPKLogger(apkLogger);
return results; return results;
} }
private String readManifestPackageName(File manifestFile) throws XMLException { private String readManifestPackageName(File manifestFile) throws XMLException {

View File

@ -15,6 +15,7 @@
*/ */
package com.reandroid.apk.xmlencoder; package com.reandroid.apk.xmlencoder;
import com.reandroid.arsc.decoder.ValueDecoder;
import com.reandroid.arsc.value.ValueHeader; import com.reandroid.arsc.value.ValueHeader;
import com.reandroid.arsc.value.Entry; import com.reandroid.arsc.value.Entry;
@ -25,7 +26,7 @@ import com.reandroid.arsc.value.Entry;
@Override @Override
void encodeStringValue(Entry entry, String value){ void encodeStringValue(Entry entry, String value){
throw new EncodeException("Unexpected value for id: "+value); entry.setValueAsString(ValueDecoder.unEscapeSpecialCharacter(value));
} }
@Override @Override
void encodeNullValue(Entry entry){ void encodeNullValue(Entry entry){

View File

@ -281,9 +281,7 @@ import java.util.*;
@Deprecated @Deprecated
public static TableBlock loadWithAndroidFramework(InputStream inputStream) throws IOException{ public static TableBlock loadWithAndroidFramework(InputStream inputStream) throws IOException{
TableBlock tableBlock=load(inputStream); return load(inputStream);
tableBlock.addFramework(Frameworks.getAndroid());
return tableBlock;
} }
public static TableBlock load(File file) throws IOException{ public static TableBlock load(File file) throws IOException{
return load(new FileInputStream(file)); return load(new FileInputStream(file));

View File

@ -26,6 +26,7 @@ import java.io.InputStream;
public class Frameworks { public class Frameworks {
private static FrameworkTable android_table; private static FrameworkTable android_table;
private static boolean load_once; private static boolean load_once;
@Deprecated
public static FrameworkTable getAndroid(){ public static FrameworkTable getAndroid(){
if(android_table!=null || load_once){ if(android_table!=null || load_once){
return android_table; return android_table;
@ -33,21 +34,10 @@ public class Frameworks {
load_once=true; load_once=true;
FrameworkTable frameworkTable=null; FrameworkTable frameworkTable=null;
try { try {
frameworkTable = loadFramework(ANDROID_FRAMEWORK_33); frameworkTable = AndroidFrameworks.getLatest().getTableBlock();
} catch (IOException e) { } catch (IOException e) {
} }
android_table=frameworkTable; android_table=frameworkTable;
return android_table; return android_table;
} }
private static FrameworkTable loadFramework(String name) throws IOException {
InputStream inputStream= Frameworks.class.getResourceAsStream(name);
if(inputStream==null){
return null;
}
FrameworkTable frameworkTable=new FrameworkTable();
frameworkTable.readBytes(inputStream);
return frameworkTable;
}
private static final String ANDROID_FRAMEWORK_33 = "/fwk/android_resources_33.arsc";
} }