rework manifest renaming

Issue #526, correctly handles apks where a renamed package is required, by comparing the package name present
in AndroidManifest.xml and resources.arsc. If different, we take the package name present
in resources.arsc (original) and replace it in the <manifest> tag of AndroidManifest.xml. The previous value in
AndroidManifest.xml (renamed) becomes the value to be passed to aapt on rebuild via --rename-manifest-package

Both these values along with the package id of the original are stored in apktool.yml, for use during the
rebuild
This commit is contained in:
Connor Tumbleson 2014-01-07 10:59:37 -06:00
parent 559a3024cc
commit e254cec648
6 changed files with 70 additions and 40 deletions

View File

@ -272,6 +272,7 @@ public class Androlib {
: Boolean.valueOf(meta.get("compressionType").toString())); : Boolean.valueOf(meta.get("compressionType").toString()));
mAndRes.setSdkInfo((Map<String, String>) meta.get("sdkInfo")); mAndRes.setSdkInfo((Map<String, String>) meta.get("sdkInfo"));
mAndRes.setPackageId((Map<String, String>) meta.get("packageInfo")); mAndRes.setPackageId((Map<String, String>) meta.get("packageInfo"));
mAndRes.setPackageInfo((Map<String, String>) meta.get("packageInfo"));
mAndRes.setVersionInfo((Map<String, String>) meta.get("versionInfo")); mAndRes.setVersionInfo((Map<String, String>) meta.get("versionInfo"));
if (outFile == null) { if (outFile == null) {

View File

@ -317,10 +317,15 @@ public class ApkDecoder {
private void putPackageInfo(Map<String, Object> meta) private void putPackageInfo(Map<String, Object> meta)
throws AndrolibException { throws AndrolibException {
Map<String, String> info = getResTable().getPackageInfo(); String renamed = getResTable().getPackageRenamed();
if (info.size() > 0) { String original = getResTable().getPackageOriginal();
meta.put("packageInfo", info); int id = getResTable().getPackageId();
}
HashMap<String, String> packages = new HashMap<String, String>();
packages.put("renamed", renamed);
packages.put("original", original);
packages.put("original_id", String.valueOf(id));
meta.put("packageInfo", packages);
} }
private void putVersionInfo(Map<String, Object> meta) private void putVersionInfo(Map<String, Object> meta)

View File

@ -176,13 +176,17 @@ final public class AndrolibResources {
public void adjust_package_manifest(ResTable resTable, String filePath) public void adjust_package_manifest(ResTable resTable, String filePath)
throws AndrolibException { throws AndrolibException {
// check if packages different, and that package is not equal to "android" // compare resources.arsc package name to the one present in AndroidManifest
Map<String, String> packageInfo = resTable.getPackageInfo(); ResPackage resPackage = resTable.getHighestSpecPackage();
String currentPackage = packageInfo.get("cur_package"); mPackageOriginal = resPackage.getName();
String originalPackage = packageInfo.get("orig_package"); mPackageRenamed = resTable.getPackageRenamed();
if (currentPackage.equalsIgnoreCase(originalPackage) || "android".equalsIgnoreCase(currentPackage)
|| "com.htc".equalsIgnoreCase(currentPackage)) { resTable.setPackageId(resPackage.getId());
resTable.setPackageOriginal(mPackageOriginal);
if (mPackageOriginal.equalsIgnoreCase(mPackageRenamed) || "android".equalsIgnoreCase(mPackageRenamed)
|| "com.htc".equalsIgnoreCase(mPackageRenamed)) {
LOGGER.info("Regular manifest package..."); LOGGER.info("Regular manifest package...");
} else { } else {
try { try {
@ -196,9 +200,7 @@ final public class AndrolibResources {
// update package attribute // update package attribute
NamedNodeMap attr = manifest.getAttributes(); NamedNodeMap attr = manifest.getAttributes();
Node nodeAttr = attr.getNamedItem("package"); Node nodeAttr = attr.getNamedItem("package");
mPackageRenamed = nodeAttr.getNodeValue(); nodeAttr.setNodeValue(mPackageOriginal);
nodeAttr.setNodeValue(currentPackage);
saveDocument(filePath, doc); saveDocument(filePath, doc);
} catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) { } catch (SAXException | ParserConfigurationException | IOException | TransformerException ignored) {
@ -284,6 +286,7 @@ final public class AndrolibResources {
// it will be passed as a parameter to aapt like "--min-sdk-version" via apktool.yml // it will be passed as a parameter to aapt like "--min-sdk-version" via apktool.yml
adjust_package_manifest(resTable, outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml"); adjust_package_manifest(resTable, outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml");
remove_manifest_versions(outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml"); remove_manifest_versions(outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml");
mPackageId = String.valueOf(resTable.getPackageId());
} }
if (inApk.containsDir("res")) { if (inApk.containsDir("res")) {
in = inApk.getDir("res"); in = inApk.getDir("res");
@ -332,13 +335,14 @@ final public class AndrolibResources {
public void setPackageInfo(Map<String, String> map) { public void setPackageInfo(Map<String, String> map) {
if (map != null) { if (map != null) {
mPackageRenamed = map.get("package"); mPackageRenamed = map.get("renamed");
mPackageOriginal = map.get("original");
} }
} }
public void setPackageId(Map<String, String> map) { public void setPackageId(Map<String, String> map) {
if (map != null) { if (map != null) {
mPackageId = map.get("cur_package_id"); mPackageId = map.get("original_id");
} }
} }
@ -359,8 +363,7 @@ final public class AndrolibResources {
customAapt = true; customAapt = true;
if (flags.get("verbose")) { if (flags.get("verbose")) {
LOGGER.info(aaptFile.getPath() LOGGER.info(aaptFile.getPath() + " being used as aapt location.");
+ " being used as aapt location.");
} }
} else { } else {
LOGGER.warning("aapt location could not be found. Defaulting back to default"); LOGGER.warning("aapt location could not be found. Defaulting back to default");
@ -838,7 +841,6 @@ final public class AndrolibResources {
private final static Logger LOGGER = Logger private final static Logger LOGGER = Logger
.getLogger(AndrolibResources.class.getName()); .getLogger(AndrolibResources.class.getName());
private String mPackageId = null;
private String mMinSdkVersion = null; private String mMinSdkVersion = null;
private String mMaxSdkVersion = null; private String mMaxSdkVersion = null;
private String mTargetSdkVersion = null; private String mTargetSdkVersion = null;
@ -846,6 +848,9 @@ final public class AndrolibResources {
private String mVersionName = null; private String mVersionName = null;
private String mPackageRenamed = null; private String mPackageRenamed = null;
private String mPackageOriginal = null;
private String mPackageId = null;
private File mAaptBinary = null; private File mAaptBinary = null;
} }

View File

@ -34,10 +34,12 @@ public class ResTable {
private final Set<ResPackage> mFramePackages = new LinkedHashSet<ResPackage>(); private final Set<ResPackage> mFramePackages = new LinkedHashSet<ResPackage>();
private String mFrameTag; private String mFrameTag;
private String mPackageRenamed;
private String mPackageOriginal;
private int mPackageId;
private boolean mAnalysisMode = false; private boolean mAnalysisMode = false;
private Map<String, String> mSdkInfo = new LinkedHashMap<String, String>(); private Map<String, String> mSdkInfo = new LinkedHashMap<String, String>();
private Map<String, String> mPackageInfo = new LinkedHashMap<String, String>();
private Map<String, String> mVersionInfo = new LinkedHashMap<String, String>(); private Map<String, String> mVersionInfo = new LinkedHashMap<String, String>();
private Map<String, String> mUnknownFiles = new LinkedHashMap<String, String>(); private Map<String, String> mUnknownFiles = new LinkedHashMap<String, String>();
@ -76,6 +78,18 @@ public class ResTable {
throw new UndefinedResObject(String.format("package: id=%d", id)); throw new UndefinedResObject(String.format("package: id=%d", id));
} }
public ResPackage getHighestSpecPackage() throws AndrolibException {
int id = 0;
int value = 0;
for(ResPackage resPackage : mPackagesById.values()) {
if(resPackage.getResSpecCount() > value && !resPackage.getName().equalsIgnoreCase("android")) {
value = resPackage.getResSpecCount();
id = resPackage.getId();
}
}
return getPackage(id);
}
public ResPackage getPackage(String name) throws AndrolibException { public ResPackage getPackage(String name) throws AndrolibException {
ResPackage pkg = mPackagesByName.get(name); ResPackage pkg = mPackagesByName.get(name);
if (pkg == null) { if (pkg == null) {
@ -126,6 +140,18 @@ public class ResTable {
public void setAnalysisMode(boolean mode) { public void setAnalysisMode(boolean mode) {
mAnalysisMode = mode; mAnalysisMode = mode;
} }
public void setPackageRenamed(String pkg) {
mPackageRenamed = pkg;
}
public void setPackageOriginal(String pkg) {
mPackageOriginal = pkg;
}
public void setPackageId(int id) {
mPackageId = id;
}
public void clearSdkInfo() { public void clearSdkInfo() {
mSdkInfo.clear(); mSdkInfo.clear();
@ -139,18 +165,10 @@ public class ResTable {
mVersionInfo.put(key, value); mVersionInfo.put(key, value);
} }
public void addPackageInfo(String key, String value) {
mPackageInfo.put(key, value);
}
public void addUnknownFileInfo(String file, String value) { public void addUnknownFileInfo(String file, String value) {
mUnknownFiles.put(file,value); mUnknownFiles.put(file,value);
} }
public Map<String, String> getPackageInfo() {
return mPackageInfo;
}
public Map<String, String> getVersionInfo() { public Map<String, String> getVersionInfo() {
return mVersionInfo; return mVersionInfo;
} }
@ -167,7 +185,15 @@ public class ResTable {
return mUnknownFiles; return mUnknownFiles;
} }
public boolean isPackageInfoValueSet(String key) { public String getPackageRenamed() {
return (mPackageInfo.containsKey(key)); return mPackageRenamed;
} }
public String getPackageOriginal() {
return mPackageOriginal;
}
public int getPackageId() {
return mPackageId;
}
} }

View File

@ -80,12 +80,6 @@ public class ARSCDecoder {
for (int i = 0; i < packageCount; i++) { for (int i = 0; i < packageCount; i++) {
packages[i] = readPackage(); packages[i] = readPackage();
} }
// store package
if (this.mResTable.isPackageInfoValueSet("cur_package") != true) {
this.mResTable.addPackageInfo("cur_package", packages[0].getName());
this.mResTable.addPackageInfo("cur_package_id", String.valueOf(packages[0].getId()));
}
return packages; return packages;
} }

View File

@ -89,16 +89,15 @@ public class XmlPullStreamDecoder implements ResStreamDecoder {
private boolean parseManifest(XmlPullParser pp) private boolean parseManifest(XmlPullParser pp)
throws AndrolibException { throws AndrolibException {
ResTable restable = resTable;
// read <manifest> for package: // read <manifest> for package:
for (int i = 0; i < pp.getAttributeCount(); i++) { for (int i = 0; i < pp.getAttributeCount(); i++) {
if (pp.getAttributeName(i).equalsIgnoreCase(("package"))) { if (pp.getAttributeName(i).equalsIgnoreCase(("package"))) {
restable.addPackageInfo("orig_package",pp.getAttributeValue(i)); resTable.setPackageRenamed(pp.getAttributeValue(i));
} else if (pp.getAttributeName(i).equalsIgnoreCase("versionCode")) { } else if (pp.getAttributeName(i).equalsIgnoreCase("versionCode")) {
restable.addVersionInfo("versionCode", pp.getAttributeValue(i).toString()); resTable.addVersionInfo("versionCode", pp.getAttributeValue(i));
} else if (pp.getAttributeName(i).equalsIgnoreCase("versionName")) { } else if (pp.getAttributeName(i).equalsIgnoreCase("versionName")) {
restable.addVersionInfo("versionName", pp.getAttributeValue(i).toString()); resTable.addVersionInfo("versionName", pp.getAttributeValue(i));
} }
} }
return true; return true;