Watch your Manifest

Lin Wang | Android Performance Engineer

Black magnifying glass with “</” inside of the glass portion and “manifest >” to the right of the magnifying glass

Designed by AJ Oxendine | Software Engineer

It’s a well-known fact for Android developers that an app’s manifest (AndroidManifest.xml) holds crucial application declarations. It is rarely monitored after being set up because we assume it hardly ever changes. At Pinterest, however, we have been actively monitoring the manifest after realizing it does change every so often.

While building an app, Gradle downloads all the dependent libraries to compile and link them with the app. These dependent libraries each have their own mini manifest. During the build process, Android Gradle Plugin (AGP) merges them with the app’s main manifest to form the final manifest. Because of this merging process, the final manifest often looks quite different from the original one and contains additional declarations. In most cases, these extra declarations are necessary for dependent libraries to function. However, sometimes they can have unintended behaviors.

It first caught our attention during a cold start regression investigation. We found a 3rd party Software Development Kit (SDK) declaring a special ContentProvider in its manifest to warm up itself as early as possible. This is because content providers get initialized very early during the application startup, even before the Application’s onCreate() method is invoked. However, we want to control every 3rd party libraries’ initialization and only initialize them when it is necessary. Therefore, we added the following declaration:

<provider android:name=”com.company.SdkEarlyInitializer” … other android properties … tools:node=”remove”/>

Adding this declaration to the manifest will cause the SdkEarlyInitializer to be removed from the final merged manifest. This change resulted in a cold start improvement of 130ms.

From then on, we created the following process to regularly monitor the merged manifest changes before landing a commit, starting with taking a snapshot of the current merged manifest and keeping it in the codebase:

  1. As part of the PR build, we compare the merged manifest against the snapshot.
  2. If a difference is detected, we fail the build.
  3. The PR developer must then adjust the snapshot manifest if the changes are necessary, or add the proper “remove” tags to keep the new components out of the final manifest.

A small group of blocking reviewers will review every manifest change.

Useful Cases

  • Discovered the WorkManagerInitializer (ContentProvider), which was added by the work manager library. We firstly removed it and notified Google, who eventually added support for initializing the work manager with a custom configuration.

  • Found a new intent was added by upgrading of the exoplayer library to 2.15.0. We then contributed to the ongoing issue discussion with Google to finally have this unnecessary intent removed.

  • Detected the AD_ID permission was added by a library.

  • The regular cshell diff is sufficient to compare manifests

  • AGP does sometimes reorder the items in manifest without changing the content, in which case the snapshot needs to be adjusted

  • Ignoring white spaces and newlines is necessary

  • Frequently changed items in the manifest need to be explicitly ignored (e.g. UUIDs, version codes)

With this approach, we will be alerted when any new component gets added to our app and feel more confident whenever we add new dependencies.

Acknowledgements

Android Performance Team: Arun K, Ernesto Duhart, Lin Wang, Sheng Liu, Tom Harman

Special Thanks: Sha Sha Chu (She Her)

To learn more about engineering at Pinterest, check out the rest of our Engineering Blog and visit our Pinterest Labs site. To explore life at Pinterest, visit our Careers page.

Home - Wiki
Copyright © 2011-2024 iteam. Current version is 2.137.1. UTC+08:00, 2024-11-05 17:18
浙ICP备14020137号-1 $Map of visitor$