From bd2f85f8768b1e4bc7bd3c62e64376525e0fc4c4 Mon Sep 17 00:00:00 2001 From: emanuele-f Date: Mon, 10 Jan 2022 23:21:10 +0100 Subject: [PATCH] Detect build type to customize error reporting The error reporting dialog now shows the build type. The dialog is now shown only on unsupported builds. Closes #177 --- .../emanuelef/remote_capture/PCAPdroid.java | 18 +++++-- .../com/emanuelef/remote_capture/Utils.java | 54 +++++++++++++++++++ .../activities/ErrorActivity.java | 11 ++-- 3 files changed, 76 insertions(+), 7 deletions(-) diff --git a/app/src/main/java/com/emanuelef/remote_capture/PCAPdroid.java b/app/src/main/java/com/emanuelef/remote_capture/PCAPdroid.java index 70bf5664..bfea5636 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/PCAPdroid.java +++ b/app/src/main/java/com/emanuelef/remote_capture/PCAPdroid.java @@ -22,6 +22,7 @@ package com.emanuelef.remote_capture; import android.app.Application; import android.content.Context; import android.content.SharedPreferences; +import android.util.Log; import androidx.annotation.NonNull; import androidx.preference.PreferenceManager; @@ -45,6 +46,7 @@ import cat.ereza.customactivityoncrash.config.CaocConfig; * https://stackoverflow.com/questions/56496714/android-webview-causing-runtimeexception-at-webviewdelegate-getpackageid */ public class PCAPdroid extends Application { + private static final String TAG = "PCAPdroid"; private MatchList mVisMask; private MatchList mMalwareWhitelist; private MatchList mBlocklist; @@ -57,10 +59,18 @@ public class PCAPdroid extends Application { public void onCreate() { super.onCreate(); - CaocConfig.Builder.create() - .errorDrawable(R.drawable.ic_app_crash) - .errorActivity(ErrorActivity.class) - .apply(); + Utils.BuildType buildtp = Utils.getBuildType(this); + Log.d(TAG, "Build type: " + buildtp); + + CaocConfig.Builder builder = CaocConfig.Builder.create(); + if((buildtp == Utils.BuildType.PLAYSTORE) || (buildtp == Utils.BuildType.UNKNOWN)) { + // Disabled to get reports via the Android system reporting facility + builder.enabled(false); + } else { + builder.errorDrawable(R.drawable.ic_app_crash) + .errorActivity(ErrorActivity.class); + } + builder.apply(); mInstance = new WeakReference<>(this); mLocalizedContext = createConfigurationContext(Utils.getLocalizedConfig(this)); diff --git a/app/src/main/java/com/emanuelef/remote_capture/Utils.java b/app/src/main/java/com/emanuelef/remote_capture/Utils.java index 48ea7ee1..07a3dd88 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/Utils.java +++ b/app/src/main/java/com/emanuelef/remote_capture/Utils.java @@ -34,6 +34,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; +import android.content.pm.Signature; import android.content.res.Configuration; import android.content.res.Resources; import android.database.Cursor; @@ -87,6 +88,8 @@ import java.net.URL; import java.net.UnknownHostException; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -106,6 +109,15 @@ public class Utils { private static Boolean rootAvailable = null; private static Locale primaryLocale = null; + public enum BuildType { + UNKNOWN, + DEBUG, + WORKFLOW, // debug build from the Github workflow + GITHUB, // Github release + FDROID, // F-droid release + PLAYSTORE, // Google play release + } + public static String[] list2array(List l) { return l.toArray(new String[0]); } @@ -870,4 +882,46 @@ public class Utils { else h.post(r); } + + // Returns true on the playstore branch + public static boolean isPlaystore() { + return false; + } + + public static BuildType getBuildType(Context ctx) { + try { + Signature[] signatures; + + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { + // NOTE: PCAPdroid does not use multiple signatures + PackageInfo pInfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), PackageManager.GET_SIGNING_CERTIFICATES); + signatures = pInfo.signingInfo.getSigningCertificateHistory(); + } else { + PackageInfo pInfo = ctx.getPackageManager().getPackageInfo(ctx.getPackageName(), PackageManager.GET_SIGNATURES); + signatures = pInfo.signatures; + } + + if(signatures.length < 1) + return BuildType.UNKNOWN; + + MessageDigest sha1 = MessageDigest.getInstance("SHA"); + sha1.update(signatures[0].toByteArray()); + + // keytool -printcert -jarfile file.apk + String hex = byteArrayToHex(sha1.digest(), sha1.getDigestLength()); + switch(hex) { + case "511140392BFF2CFB4BD825895DD6510CE1807F6D": + return BuildType.DEBUG; + case "EE953D4F988C8AC17575DFFAA1E3BBCE2E29E81D": + return isPlaystore() ? BuildType.PLAYSTORE : BuildType.GITHUB; + case "72777D6939EF150099219BBB68C17220DB28EA8E": + return BuildType.FDROID; + case "9F030FABC158A428CFDB90570A426EA88B39A153": + return BuildType.WORKFLOW; + } + } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) { + Log.e("Utils", "Could not retrieve package version"); + } + return BuildType.UNKNOWN; + } } diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/ErrorActivity.java b/app/src/main/java/com/emanuelef/remote_capture/activities/ErrorActivity.java index 18b30c21..bad61b5d 100644 --- a/app/src/main/java/com/emanuelef/remote_capture/activities/ErrorActivity.java +++ b/app/src/main/java/com/emanuelef/remote_capture/activities/ErrorActivity.java @@ -102,7 +102,7 @@ public final class ErrorActivity extends AppCompatActivity { AlertDialog dialog = new AlertDialog.Builder(ErrorActivity.this) .setTitle(R.string.customactivityoncrash_error_activity_error_details_title) - .setMessage(CustomActivityOnCrash.getAllErrorDetailsFromIntent(ErrorActivity.this, getIntent())) + .setMessage(getErrorDetails()) .setPositiveButton(R.string.customactivityoncrash_error_activity_error_details_close, null) .setNeutralButton(R.string.customactivityoncrash_error_activity_error_details_copy, new DialogInterface.OnClickListener() { @@ -129,7 +129,7 @@ public final class ErrorActivity extends AppCompatActivity { emailIntent.putExtra(Intent.EXTRA_SUBJECT, "PCAPdroid crash"); if(emailIntent.resolveActivity(getPackageManager()) != null) { emailButton.setOnClickListener(v -> { - String errorInformation = CustomActivityOnCrash.getAllErrorDetailsFromIntent(ErrorActivity.this, getIntent()); + String errorInformation = getErrorDetails(); emailIntent.putExtra(Intent.EXTRA_TEXT, errorInformation); Utils.startActivity(this, emailIntent); }); @@ -145,7 +145,7 @@ public final class ErrorActivity extends AppCompatActivity { } private void copyErrorToClipboard() { - String errorInformation = CustomActivityOnCrash.getAllErrorDetailsFromIntent(ErrorActivity.this, getIntent()); + String errorInformation = getErrorDetails(); ClipboardManager clipboard = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE); @@ -156,4 +156,9 @@ public final class ErrorActivity extends AppCompatActivity { Toast.makeText(ErrorActivity.this, R.string.customactivityoncrash_error_activity_error_details_copied, Toast.LENGTH_SHORT).show(); } } + + private String getErrorDetails() { + return "Build type: " + Utils.getBuildType(this).toString().toLowerCase() + "\n" + + CustomActivityOnCrash.getAllErrorDetailsFromIntent(ErrorActivity.this, getIntent()); + } } \ No newline at end of file