Skip to content

Commit

Permalink
ui: distinguish play store installs at runtime for reproducible builds
Browse files Browse the repository at this point in the history
This change lets us use the same build for F-Droid, Play Store, self
builds, and elsewhere, which makes everything more easily publicly
verifiable, since the build system is reproducible. That means that all
APKs will have the same code and be completely interchangeable, no
matter where they come from.

It does this by removing the build-time branch for special Play Store
builds, and replacing it with a simple runtime check using the
PackageManager APIs that return the name of the installer. If the app is
installed by "com.android.vending", then it's a Play Store install.

It's possible to test this with:

    $ pm install -i com.android.vending path/to/package.apk

And it appears to work well.

However, it's still unclear whether the Play Store reviewers install the
app using utilities that set com.android.vending like this. If not, that
might be a problem. However, it looks like various banking apps also use
the installer package name check in the same way, and refuse to start if
it's not right. That suggests that it would be impossible for Play Store
reviewers to even review those banking apps if they did not set
com.android.vending properly.

Out of an abundance of caution, though, and in order to avoid a Play
Store suspension that's harder to appeal, I sent a support request
today (which just managed to fit exactly in the 1000 character limit):

    Hi,

    My app pays special attention to Google Play Store guidelines. For that
    reason, there is some code in the app that looks like this:

        if (BuildConfig.IS_GOOGLE_PLAY)
            ...
        else
            ...

    This means that I compile two versions of my app, one for Google Play,
    and another for other app stores. This has worked well for many years
    and it satisfies Google's policy requirements.

    However, compiling two versions of my app is a bit of a pain. Instead, I
    would like to do this check at runtime, with code like this:

        if (pm.getInstallSourceInfo(package).installingPackageName == "com.android.vending")
            ...
        else
            ...

    I have tested that this code works well, and I've installed my app with:

        $ pm install -i com.android.vending ui-release.apk

    This works and successfully satisfies the policy requirements.

    My question is how this works during the review process. Are reviewed
    apps installed with the necessary -i com.android.vending switch to make
    this work?

    Thanks.

They responded fairly quickly:

    Hi Jason,

    Thanks for contacting the Google Play team.

    Unfortunately I'm not able to comment on your planned implementation. If
    you think your app is in compliance, please submit your app for review.
    You may want to review the Developer Program Policies for additional
    policy guidance.

    We recommend reviewing the details listed in this blog post and update
    your app accordingly to comply with the changes.

    Thanks for your understanding and continued support.

    Regards,
    Mia
    Google Play Developer Support

So I'll interpret that as a, "if you think it's okay, submit it and see,
and then we'll let you know." So here we go. Hopefully if it is
rejected, the update will only be blocked, and I'll just revert this
commit and resubmit.

Signed-off-by: Jason A. Donenfeld <[email protected]>
  • Loading branch information
zx2c4 committed Apr 5, 2023
1 parent 6209d3e commit a1670c8
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 5 deletions.
3 changes: 0 additions & 3 deletions ui/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,6 @@ android {
}
}
buildTypes {
all {
buildConfigField('boolean', 'IS_GOOGLE_PLAY', (findProperty('build.google_play') == 'true').toString())
}
release {
if (keystorePropertiesFile.exists()) signingConfig signingConfigs.release
minifyEnabled true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ package com.wireguard.android.preference
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.util.AttributeSet
import android.widget.Toast
import androidx.preference.Preference
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.wireguard.android.BuildConfig
import com.wireguard.android.R
import com.wireguard.android.util.ErrorMessages

Expand All @@ -22,8 +22,21 @@ class DonatePreference(context: Context, attrs: AttributeSet?) : Preference(cont
override fun getTitle() = context.getString(R.string.donate_title)

override fun onClick() {
val installer = try {
val packageName = context.packageName
val pm = context.packageManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
pm.getInstallSourceInfo(packageName).installingPackageName ?: ""
} else {
@Suppress("DEPRECATION")
pm.getInstallerPackageName(packageName) ?: ""
}
} catch (_: Throwable) {
""
}

/* Google Play Store forbids links to our donation page. */
if (BuildConfig.IS_GOOGLE_PLAY) {
if (installer == "com.android.vending") {
MaterialAlertDialogBuilder(context)
.setTitle(R.string.donate_title)
.setMessage(R.string.donate_google_play_disappointment)
Expand Down

0 comments on commit a1670c8

Please sign in to comment.