diff --git a/telemetry/src/firebase/kotlin/mihon/telemetry/PackageInfo.kt b/telemetry/src/firebase/kotlin/mihon/telemetry/PackageInfo.kt new file mode 100644 index 000000000..eb81ca842 --- /dev/null +++ b/telemetry/src/firebase/kotlin/mihon/telemetry/PackageInfo.kt @@ -0,0 +1,46 @@ +package mihon.telemetry + +import android.content.pm.PackageInfo +import android.content.pm.PackageManager +import android.content.pm.Signature +import android.os.Build +import java.security.MessageDigest + +internal fun PackageInfo.getCertificateFingerprints(): List { + return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + val signingInfo = signingInfo!! + if (signingInfo.hasMultipleSigners()) { + signingInfo.apkContentsSigners + } else { + signingInfo.signingCertificateHistory + } + } else { + @Suppress("DEPRECATION") + signatures + } + ?.map(Signature::getCertificateFingerprint) + ?.toList() + ?: emptyList() +} + +internal val SignatureFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + PackageManager.GET_SIGNING_CERTIFICATES +} else { + @Suppress("DEPRECATION") + PackageManager.GET_SIGNATURES +} + +@OptIn(ExperimentalStdlibApi::class) +private val CertificateFingerprintHexFormat = HexFormat { + upperCase = true + bytes { + byteSeparator = ":" + } +} + +@OptIn(ExperimentalStdlibApi::class) +private fun Signature.getCertificateFingerprint(): String { + return MessageDigest.getInstance("SHA-256") + .digest(toByteArray()) + .toHexString(CertificateFingerprintHexFormat) +} diff --git a/telemetry/src/firebase/kotlin/mihon/telemetry/TelemetryConfig.kt b/telemetry/src/firebase/kotlin/mihon/telemetry/TelemetryConfig.kt index 34d3986fb..b3b22f6ee 100644 --- a/telemetry/src/firebase/kotlin/mihon/telemetry/TelemetryConfig.kt +++ b/telemetry/src/firebase/kotlin/mihon/telemetry/TelemetryConfig.kt @@ -6,20 +6,35 @@ import com.google.firebase.analytics.FirebaseAnalytics import com.google.firebase.crashlytics.FirebaseCrashlytics object TelemetryConfig { - private lateinit var analytics: FirebaseAnalytics - private lateinit var crashlytics: FirebaseCrashlytics + private var analytics: FirebaseAnalytics? = null + private var crashlytics: FirebaseCrashlytics? = null fun init(context: Context) { + // To stop forks/test builds from polluting our data + if (!context.isMihonProductionApp()) return + analytics = FirebaseAnalytics.getInstance(context) FirebaseApp.initializeApp(context) crashlytics = FirebaseCrashlytics.getInstance() } fun setAnalyticsEnabled(enabled: Boolean) { - analytics.setAnalyticsCollectionEnabled(enabled) + analytics?.setAnalyticsCollectionEnabled(enabled) } fun setCrashlyticsEnabled(enabled: Boolean) { - crashlytics.isCrashlyticsCollectionEnabled = enabled + crashlytics?.isCrashlyticsCollectionEnabled = enabled + } + + private fun Context.isMihonProductionApp(): Boolean { + if (packageName !in MIHON_PACKAGES) return false + + return packageManager.getPackageInfo(packageName, SignatureFlags) + .getCertificateFingerprints() + .any { it == MIHON_CERTIFICATE_FINGERPRINT } } } + +private val MIHON_PACKAGES = hashSetOf("app.mihon", "app.mihon.debug") +private const val MIHON_CERTIFICATE_FINGERPRINT = + "9A:DD:65:5A:78:E9:6C:4E:C7:A5:3E:F8:9D:CC:B5:57:CB:5D:76:74:89:FA:C5:E7:85:D6:71:A5:A7:5D:4D:A2" diff --git a/telemetry/src/main/AndroidManifest.xml b/telemetry/src/main/AndroidManifest.xml index 9d0be9170..65e3e4a52 100644 --- a/telemetry/src/main/AndroidManifest.xml +++ b/telemetry/src/main/AndroidManifest.xml @@ -2,6 +2,10 @@ + + + +