AAPT: ProGuard config for components in main dex.

Create an analogue of "aapt -G" which outputs a proguard configuration
that keeps only components which need to be in the main dex.

BUG: 27383099

Change-Id: Ic18c8c563794ff27a5598a214111d1b446a005f1
(cherry picked from commit 86229cb622)
This commit is contained in:
Rohit Agrawal
2016-04-21 16:29:58 -07:00
parent cd4f7e1203
commit 6ba873faec
5 changed files with 98 additions and 24 deletions

View File

@@ -55,7 +55,7 @@ public:
mCompressionMethod(0), mJunkPath(false), mOutputAPKFile(NULL),
mManifestPackageNameOverride(NULL), mInstrumentationPackageNameOverride(NULL),
mAutoAddOverlay(false), mGenDependencies(false), mNoVersionVectors(false),
mCrunchedOutputDir(NULL), mProguardFile(NULL),
mCrunchedOutputDir(NULL), mProguardFile(NULL), mMainDexProguardFile(NULL),
mAndroidManifestFile(NULL), mPublicOutputFile(NULL),
mRClassDir(NULL), mResourceIntermediatesDir(NULL), mManifestMinSdkVersion(NULL),
mMinSdkVersion(NULL), mTargetSdkVersion(NULL), mMaxSdkVersion(NULL),
@@ -139,6 +139,8 @@ public:
void setCrunchedOutputDir(const char* dir) { mCrunchedOutputDir = dir; }
const char* getProguardFile() const { return mProguardFile; }
void setProguardFile(const char* file) { mProguardFile = file; }
const char* getMainDexProguardFile() const { return mMainDexProguardFile; }
void setMainDexProguardFile(const char* file) { mMainDexProguardFile = file; }
const android::Vector<const char*>& getResourceSourceDirs() const { return mResourceSourceDirs; }
void addResourceSourceDir(const char* dir) { mResourceSourceDirs.insertAt(dir,0); }
const char* getAndroidManifestFile() const { return mAndroidManifestFile; }
@@ -290,6 +292,7 @@ private:
bool mNoVersionVectors;
const char* mCrunchedOutputDir;
const char* mProguardFile;
const char* mMainDexProguardFile;
const char* mAndroidManifestFile;
const char* mPublicOutputFile;
const char* mRClassDir;

View File

@@ -2573,6 +2573,12 @@ int doPackage(Bundle* bundle)
goto bail;
}
// Write out the Main Dex ProGuard file
err = writeMainDexProguardFile(bundle, assets);
if (err < 0) {
goto bail;
}
// Write the apk
if (outputAPKFile) {
// Gather all resources and add them to the APK Builder. The builder will then

View File

@@ -67,6 +67,7 @@ void usage(void)
" [--max-res-version VAL] \\\n"
" [-I base-package [-I base-package ...]] \\\n"
" [-A asset-source-dir] [-G class-list-file] [-P public-definitions-file] \\\n"
" [-D main-dex-class-list-file] \\\n"
" [-S resource-sources [-S resource-sources ...]] \\\n"
" [-F apk-file] [-J R-file-dir] \\\n"
" [--product product1,product2,...] \\\n"
@@ -120,6 +121,7 @@ void usage(void)
" localization=\"suggested\"\n"
" -A additional directory in which to find raw asset files\n"
" -G A file to output proguard options into.\n"
" -D A file to output proguard options for the main dex into.\n"
" -F specify the apk file to output\n"
" -I add an existing package to base include set\n"
" -J specify where to output R.java resource constant definitions\n"
@@ -385,6 +387,17 @@ int main(int argc, char* const argv[])
convertPath(argv[0]);
bundle.setProguardFile(argv[0]);
break;
case 'D':
argc--;
argv++;
if (!argc) {
fprintf(stderr, "ERROR: No argument supplied for '-D' option\n");
wantUsage = true;
goto bail;
}
convertPath(argv[0]);
bundle.setMainDexProguardFile(argv[0]);
break;
case 'I':
argc--;
argv++;

View File

@@ -54,6 +54,7 @@ extern android::status_t writeResourceSymbols(Bundle* bundle,
bool includePrivate, bool emitCallback);
extern android::status_t writeProguardFile(Bundle* bundle, const sp<AaptAssets>& assets);
extern android::status_t writeMainDexProguardFile(Bundle* bundle, const sp<AaptAssets>& assets);
extern bool isValidResourceType(const String8& type);

View File

@@ -2830,7 +2830,7 @@ addProguardKeepMethodRule(ProguardKeepSet* keep, const String8& memberName,
}
status_t
writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& assets, bool mainDex)
{
status_t err;
ResXMLTree tree;
@@ -2842,6 +2842,7 @@ writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& ass
sp<AaptGroup> assGroup;
sp<AaptFile> assFile;
String8 pkg;
String8 defaultProcess;
// First, look for a package file to parse. This is required to
// be able to generate the resource information.
@@ -2898,6 +2899,15 @@ writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& ass
addProguardKeepRule(keep, agent, pkg.string(),
assFile->getPrintableSource(), tree.getLineNumber());
}
if (mainDex) {
defaultProcess = AaptXml::getAttribute(tree,
"http://schemas.android.com/apk/res/android", "process", &error);
if (error != "") {
fprintf(stderr, "ERROR: %s\n", error.string());
return -1;
}
}
} else if (tag == "instrumentation") {
keepTag = true;
}
@@ -2914,7 +2924,23 @@ writeProguardForAndroidManifest(ProguardKeepSet* keep, const sp<AaptAssets>& ass
fprintf(stderr, "ERROR: %s\n", error.string());
return -1;
}
if (name.length() > 0) {
keepTag = name.length() > 0;
if (keepTag && mainDex) {
String8 componentProcess = AaptXml::getAttribute(tree,
"http://schemas.android.com/apk/res/android", "process", &error);
if (error != "") {
fprintf(stderr, "ERROR: %s\n", error.string());
return -1;
}
const String8& process =
componentProcess.length() > 0 ? componentProcess : defaultProcess;
keepTag = process.length() > 0 && process.find(":") != 0;
}
if (keepTag) {
addProguardKeepRule(keep, name, pkg.string(),
assFile->getPrintableSource(), tree.getLineNumber());
}
@@ -3097,30 +3123,12 @@ writeProguardForLayouts(ProguardKeepSet* keep, const sp<AaptAssets>& assets)
}
status_t
writeProguardFile(Bundle* bundle, const sp<AaptAssets>& assets)
writeProguardSpec(const char* filename, const ProguardKeepSet& keep, status_t err)
{
status_t err = -1;
if (!bundle->getProguardFile()) {
return NO_ERROR;
}
ProguardKeepSet keep;
err = writeProguardForAndroidManifest(&keep, assets);
if (err < 0) {
return err;
}
err = writeProguardForLayouts(&keep, assets);
if (err < 0) {
return err;
}
FILE* fp = fopen(bundle->getProguardFile(), "w+");
FILE* fp = fopen(filename, "w+");
if (fp == NULL) {
fprintf(stderr, "ERROR: Unable to open class file %s: %s\n",
bundle->getProguardFile(), strerror(errno));
filename, strerror(errno));
return UNKNOWN_ERROR;
}
@@ -3139,6 +3147,49 @@ writeProguardFile(Bundle* bundle, const sp<AaptAssets>& assets)
return err;
}
status_t
writeProguardFile(Bundle* bundle, const sp<AaptAssets>& assets)
{
status_t err = -1;
if (!bundle->getProguardFile()) {
return NO_ERROR;
}
ProguardKeepSet keep;
err = writeProguardForAndroidManifest(&keep, assets, false);
if (err < 0) {
return err;
}
err = writeProguardForLayouts(&keep, assets);
if (err < 0) {
return err;
}
return writeProguardSpec(bundle->getProguardFile(), keep, err);
}
status_t
writeMainDexProguardFile(Bundle* bundle, const sp<AaptAssets>& assets)
{
status_t err = -1;
if (!bundle->getMainDexProguardFile()) {
return NO_ERROR;
}
ProguardKeepSet keep;
err = writeProguardForAndroidManifest(&keep, assets, true);
if (err < 0) {
return err;
}
return writeProguardSpec(bundle->getMainDexProguardFile(), keep, err);
}
// Loops through the string paths and writes them to the file pointer
// Each file path is written on its own line with a terminating backslash.
status_t writePathsToFile(const sp<FilePathStore>& files, FILE* fp)