keeper icon indicating copy to clipboard operation
keeper copied to clipboard

Shrinked resources support

Open dsvoronin opened this issue 5 years ago • 3 comments

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

dsvoronin avatar Feb 04 '20 16:02 dsvoronin

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

ZacSweers avatar Feb 04 '20 23:02 ZacSweers

Specific things that would be needed:

  • Read R.txt from build/intermediates/R.txt (unsure what task produces this) to get a list of all the resources.
    • Unclear if this will still be totally correct after namespaced resources
  • All code references to resources (likely requires bytecode analysis with ASM)
  • All resource references to other resources (Not sure where to get there)
  • Generate keep.xml file, wire this into whatever resource shrinking task runs

ZacSweers avatar Feb 04 '20 23:02 ZacSweers

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.

ZacSweers avatar Jun 06 '20 02:06 ZacSweers