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()));
mAndRes.setSdkInfo((Map<String, String>) meta.get("sdkInfo"));
mAndRes.setPackageId((Map<String, String>) meta.get("packageInfo"));
mAndRes.setPackageInfo((Map<String, String>) meta.get("packageInfo"));
mAndRes.setVersionInfo((Map<String, String>) meta.get("versionInfo"));
if (outFile == null) {

View File

@ -317,10 +317,15 @@ public class ApkDecoder {
private void putPackageInfo(Map<String, Object> meta)
throws AndrolibException {
Map<String, String> info = getResTable().getPackageInfo();
if (info.size() > 0) {
meta.put("packageInfo", info);
}
String renamed = getResTable().getPackageRenamed();
String original = getResTable().getPackageOriginal();
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)

View File

@ -176,13 +176,17 @@ final public class AndrolibResources {
public void adjust_package_manifest(ResTable resTable, String filePath)
throws AndrolibException {
// check if packages different, and that package is not equal to "android"
Map<String, String> packageInfo = resTable.getPackageInfo();
String currentPackage = packageInfo.get("cur_package");
String originalPackage = packageInfo.get("orig_package");
// compare resources.arsc package name to the one present in AndroidManifest
ResPackage resPackage = resTable.getHighestSpecPackage();
mPackageOriginal = resPackage.getName();
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...");
} else {
try {
@ -196,9 +200,7 @@ final public class AndrolibResources {
// update package attribute
NamedNodeMap attr = manifest.getAttributes();
Node nodeAttr = attr.getNamedItem("package");
mPackageRenamed = nodeAttr.getNodeValue();
nodeAttr.setNodeValue(currentPackage);
nodeAttr.setNodeValue(mPackageOriginal);
saveDocument(filePath, doc);
} 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
adjust_package_manifest(resTable, outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml");
remove_manifest_versions(outDir.getAbsolutePath() + File.separator + "AndroidManifest.xml");
mPackageId = String.valueOf(resTable.getPackageId());
}
if (inApk.containsDir("res")) {
in = inApk.getDir("res");
@ -332,13 +335,14 @@ final public class AndrolibResources {
public void setPackageInfo(Map<String, String> map) {
if (map != null) {
mPackageRenamed = map.get("package");
mPackageRenamed = map.get("renamed");
mPackageOriginal = map.get("original");
}
}
public void setPackageId(Map<String, String> map) {
if (map != null) {
mPackageId = map.get("cur_package_id");
mPackageId = map.get("original_id");
}
}
@ -359,8 +363,7 @@ final public class AndrolibResources {
customAapt = true;
if (flags.get("verbose")) {
LOGGER.info(aaptFile.getPath()
+ " being used as aapt location.");
LOGGER.info(aaptFile.getPath() + " being used as aapt location.");
}
} else {
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
.getLogger(AndrolibResources.class.getName());
private String mPackageId = null;
private String mMinSdkVersion = null;
private String mMaxSdkVersion = null;
private String mTargetSdkVersion = null;
@ -846,6 +848,9 @@ final public class AndrolibResources {
private String mVersionName = null;
private String mPackageRenamed = null;
private String mPackageOriginal = null;
private String mPackageId = null;
private File mAaptBinary = null;
}

View File

@ -34,10 +34,12 @@ public class ResTable {
private final Set<ResPackage> mFramePackages = new LinkedHashSet<ResPackage>();
private String mFrameTag;
private String mPackageRenamed;
private String mPackageOriginal;
private int mPackageId;
private boolean mAnalysisMode = false;
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> mUnknownFiles = new LinkedHashMap<String, String>();
@ -76,6 +78,18 @@ public class ResTable {
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 {
ResPackage pkg = mPackagesByName.get(name);
if (pkg == null) {
@ -126,6 +140,18 @@ public class ResTable {
public void setAnalysisMode(boolean 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() {
mSdkInfo.clear();
@ -139,18 +165,10 @@ public class ResTable {
mVersionInfo.put(key, value);
}
public void addPackageInfo(String key, String value) {
mPackageInfo.put(key, value);
}
public void addUnknownFileInfo(String file, String value) {
mUnknownFiles.put(file,value);
}
public Map<String, String> getPackageInfo() {
return mPackageInfo;
}
public Map<String, String> getVersionInfo() {
return mVersionInfo;
}
@ -167,7 +185,15 @@ public class ResTable {
return mUnknownFiles;
}
public boolean isPackageInfoValueSet(String key) {
return (mPackageInfo.containsKey(key));
}
public String getPackageRenamed() {
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++) {
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;
}

View File

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