slackhq / keeper

A Gradle plugin that infers Proguard/R8 keep rules for androidTest sources.
https://slackhq.github.io/keeper
Apache License 2.0
258 stars 28 forks source link

Shrinked resources support #22

Open dsvoronin opened 4 years ago

dsvoronin commented 4 years ago

I faced an issue, that is not an keeper fault, but thought it might be a good improvement.

With shrinkResources = true if test code dynamically reference some resources from target app, but app itself not - it ends up shrinked (just like code without keeper).

More context in our repo PR: https://github.com/avito-tech/avito-android/pull/148/files#diff-9d9fe566f80ff63b20a99099ded9080f

Could it be somehow analysed beforehand? Because adding pre-generated keep.xml is not a big deal

ZacSweers commented 4 years ago

That could be possible, but not a high priority for now as it would likely be an independent implementation. PRs welcome!

ZacSweers commented 4 years ago

Specific things that would be needed:

ZacSweers commented 4 years ago

Looking into this a bit

ButterKnife has an example of reading the R.txt file: https://github.com/JakeWharton/butterknife/blob/master/butterknife-gradle-plugin/src/main/java/butterknife/plugin/ButterKnifePlugin.kt#L56-L89

Resource shrinking is handled by ShrinkResourcesTask. Since resource merging has already happened, we likely need to rewire the dependencies such that

processResourcesProvider -> InferKeepXmlTask -> ShrinkResourcesTask

There is also a ShrinkBundleResourcesTask that I think we have to duplicate.

There is a ResourceUsageAnalyzer in AOSP that we could borrow some code from as it does the bytecode analysis (UsageVisitor) to read resource usages.

There's a processKeepAttributes in ResourceUsageModel that adds keep.xml keeps. This in turn is populated at ResourceUsageModel-time. What I'm hoping this means is that as long as we generate a keep resource before prior to the ShrinkResourcesTask's run, it should Just Work.

I'm hoping we can reuse their resource finding analyzer without needing to copy anything over. If that's the case, this could hopefully be as easy as running the usage analyzer on androidTest sources/resources/manifest, then generate a keep file based on all the usages that are in the original app's processed resources.

The final piece to this puzzle is the hardest though. Merged resources are stored in binary formats ("compiled XML"). We can create a keep file, compile it, and write it out + copies of all the existing ones. But this is a murky area of the the sdk and I don't really know what I'm doing :/. If someone wants to contribute this, we'd be super open to a PR. Right now though, this is far more complex than what the library currently does.