AppLovin: Server-side kill switch — automatic installations occur only if a token is provided

This post is part of AppLovin Nonconsensual Installs. See important disclosures.

It is by no means assured that AppLovin will perform an automatic installation of an app featured in a given ad. For one, the Apphub/Array package must be present and functional, and must have an install partner. Without these, there can be no automatic installation. Some phones (including Google Pixels) never have install helpers. High-end phones and unlocked phones are less likely to have install helpers.

Furthermore, the SDK startDirectInstallOrDownloadProcess() code indicates that direct downloads occur only if AppLovin servers send a “download token” to the app/SDK to authorize a direct download. See startDirectInstallOrDownloadProcess():

public void startDirectInstallOrDownloadProcess(ArrayDirectDownloadAd arrayDirectDownloadAd, Bundle bundle, DirectDownloadListener directDownloadListener) {
    if (this.appHubService == null) {
        if (C1886x.m8960Fn()) {
            this.logger.m8974i(TAG, "Cannot begin Direct Install / Download process - service disconnected");
        }
        directDownloadListener.onFailure();
        return;
    }
    if (!arrayDirectDownloadAd.isDirectDownloadEnabled()) {
        if (C1886x.m8960Fn()) {
            this.logger.m8974i(TAG, "Cannot begin Direct Install / Download process - missing token");
        }
        directDownloadListener.onFailure();
        return;
    }
    try {
    ...

The underlying isDirectDownloadEnabled():

public boolean isDirectDownloadEnabled() {
    return StringUtils.isValidString(getDirectDownloadToken());
}

The token is retrieved from within the ad object (i.e. delivered at runtime along with ad creative):

public String getDirectDownloadToken() {
    return getStringFromAdObject("ah_dd_token", null);
}

protected String getStringFromAdObject(String str, String str2) {
    String string;
    synchronized (this.adObjectLock) {
        string = JsonUtils.getString(this.adObject, str, str2);
    }
    return string;
}

It turns out “isValid” just means nonempty:

public static boolean isValidString(String str) {
    return !TextUtils.isEmpty(str);
}

This is an unusual approach to token-based installations – neither a cryptographic verification nor a check for user consent. Instead, AppLovin can proceed with an automatic installation, or not, based merely on a string in the ad object being nonempty. The apparent benefit to AppLovin is that it can condition a direct download on any information known to the server as it sends the ad object. For example, AppLovin can limit direct downloads by IP address and geography, such as never targeting countries or regions deemed high-risk. (AppLovin can geofence jurisdictions where consumer protection authorities take a particularly dim view of nonconsensual installations. AppLovin can geofence the headquarters of companies that it doesn’t want to see nonconsensual installations.) AppLovin can equally avoid users with certain profiles, such as users who have seen less than x ads (who might be security researchers rather than serious gamers). Finally, this architecture allows AppLovin to end all direct downloads on a moment’s notice — as it might anticipate needing to do if facing public criticism.