When Google launched the Pixel 5 back in October, we were excited to get our hands on its new apps. (The phone itself is pretty cool, too.) With the Pixel 5's launch came new versions of the Google Camera and Google Recorder apps that we shared with the community. However, when many users of older Pixel devices tried to sideload the updates, they were met with an error (shown above). Bizarrely, not everyone had issues with installing the updates. Some were able to install them just fine, while others had to factory reset just so they could install the new versions. Because of the seemingly random nature of this issue, many chalked it up to a bug. We're pretty confident now that this issue doesn't stem from a bug but rather Google's use of a new API in Android 11 to block sideloading updates.

If you try to sideload Google Camera 8.0 or later or Google Recorder 2.0 or later on a Pixel device running Android 11, you'll see an error message that says the verification could not succeed. Even if you try to sideload the APK using a shell command, you won't get a more specific reason for the installation failure. The installation return code that you'll be given is "INSTALL_FAILED_VERIFICATION_FAILURE", which unfortunately doesn't tell you why the verification doesn't succeed. By examining the logcat, we can learn exactly why the verification fails:

        AppIntegrityManagerServiceImpl: Integrity check of com.google.android.GoogleCamera result: DENY due to [Rule: (PACKAGE_NAME EQ com.google.android.GoogleCamera) AND (VERSION_CODE GTE 32045130) AND (APP_CERTIFICATE EQ F0FD6C5B410F25CB25C3B53346C8972FAE30F8EE7411DF910480AD6B2D60DB83) AND NOT (INSTALLER_NAME EQ com.android.vending), DENY]
    

According to this message, an integrity check of the Google Camera installation failed because the "INSTALLER_NAME" did not match "com.android.vending", the package name for the Google Play Store. (I was attempting to install Google Camera 8.0 using the APKMirror Installer app, for what it's worth.) This message was added to the system log by "AppIntegrityManagerServiceImpl", which is part of Android's new "App Integrity" feature. According to the code in AOSP, App Integrity is designed to provide an additional layer of checks on top of the package manager's existing APK signature verification. The App Integrity API seems to use a set of Rules to decide whether or not to allow or deny the install. Rules are provided by a system app — which we believe to be Google Play Services — and are stored in a file.

In addition, App Integrity also calls another class called SourceStampVerifier if a "source stamp" is embedded in the Manifest's metadata. For example, here's what we believe is the "source stamp" from the Google Camera app's Manifest:

        <meta-data android:name="com.android.stamp.source" android:value="https://play.google.com/store"/>
    

From what we can tell, the source stamp is used to verify the signature of the package installer. So, for example, you can't trick AppIntegrity into allowing the installation even if you spoofed the Play Store as the installer.

Beyond this, we were unable to find out exactly how Google is using AppIntegrity and related APIs to block sideloading updates to the Google Camera and Google Recorder apps. A quick examination of Google Play Services APK reveals that it is using these APIs, but the code is too obfuscated to really make sense of everything. We even found the directory where the integrity rules are stored — /data/system/integrity_rules — but it was of little use because it only contains serialized data. We also haven't found a way to disable integrity verification (it doesn't seem to be as easy as just changing a setting), though we believe the reason that factory resetting works for some is that Google Play Services doesn't get a chance to initialize its ruleset to block installation. The logcat message and the introduction of these new APIs in Android 11 strongly suggest that this is all by design and not a bug, though.

Google has not publicly commented on its use of these APIs (nor do we expect them to), and they did not respond when reached for comment. We have a few theories why they're blocking sideloaded updates, though. First, they could be protecting people from installing the wrong version of the app for their device. Google delivers specific versions of its apps to specific Pixel devices. For example, several versions of the Device Personalization Services app can be found online. Even though they're all installable on Pixel devices, it was possible at one point to lose the Live Captions feature on the Pixel 4 by downloading a version built for an older Pixel device. Another reason could be to "improve traceability of apps with respect to unauthorized distribution", as explained by Google in the SourceStampVerifier class.

So far, only a few of Google's apps using the app bundle format (like Google Camera and Google Recorder) are blocking non-Play Store installs, but we don't know if the company will extend this behavior to its other apps once they all switch to the AAB format. We also considered if the switch to app bundles necessitated implementing App Integrity, but we found that Google already has a solution to handle when users try to install an app that doesn't have all its required splits. Whatever the case may be, we don't think Google intends to block all sideloading of its apps, though these tools certainly allow them to do so.

Thanks to developers vvb2060, aviraxp, and Quinny899 for their assistance in this article, and thanks to PNF Software for providing us a license to use JEB Decompiler, a professional-grade reverse engineering tool for Android applications.