From 02c4ed272487a7465e78ab93baef728cbbdd32dd Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 25 Nov 2017 13:19:30 -0800 Subject: [PATCH] Improve decoder crash reporting reliability --- app/src/main/java/com/limelight/AppView.java | 3 ++ app/src/main/java/com/limelight/Game.java | 11 ++++-- app/src/main/java/com/limelight/PcView.java | 30 ++------------ .../main/java/com/limelight/utils/Dialog.java | 30 ++++++++------ .../java/com/limelight/utils/UiHelper.java | 39 +++++++++++++++++++ 5 files changed, 72 insertions(+), 41 deletions(-) diff --git a/app/src/main/java/com/limelight/AppView.java b/app/src/main/java/com/limelight/AppView.java index f08cdd25..43e45193 100644 --- a/app/src/main/java/com/limelight/AppView.java +++ b/app/src/main/java/com/limelight/AppView.java @@ -304,6 +304,9 @@ public class AppView extends Activity implements AdapterFragmentCallbacks { protected void onResume() { super.onResume(); + // Display a decoder crash notification if we've returned after a crash + UiHelper.showDecoderCrashDialog(this); + inForeground = true; startComputerUpdates(); } diff --git a/app/src/main/java/com/limelight/Game.java b/app/src/main/java/com/limelight/Game.java index d582464a..1ad92b4f 100644 --- a/app/src/main/java/com/limelight/Game.java +++ b/app/src/main/java/com/limelight/Game.java @@ -105,6 +105,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, private ShortcutHelper shortcutHelper; private MediaCodecDecoderRenderer decoderRenderer; + private boolean reportedCrash; private WifiManager.WifiLock wifiLock; @@ -274,6 +275,7 @@ public class Game extends Activity implements SurfaceHolder.Callback, // We must use commit because the app will crash when we return from this function tombstonePrefs.edit().putInt("CrashCount", tombstonePrefs.getInt("CrashCount", 0) + 1).commit(); + reportedCrash = true; } }, tombstonePrefs.getInt("CrashCount", 0), @@ -610,9 +612,12 @@ public class Game extends Activity implements SurfaceHolder.Callback, Toast.makeText(this, message, Toast.LENGTH_LONG).show(); } - // Clear the tombstone count - if (tombstonePrefs.getInt("CrashCount", 0) != 0) { - tombstonePrefs.edit().putInt("CrashCount", 0).apply(); + // Clear the tombstone count if we terminated normally + if (!reportedCrash && tombstonePrefs.getInt("CrashCount", 0) != 0) { + tombstonePrefs.edit() + .putInt("CrashCount", 0) + .putInt("LastNotifiedCrashCount", 0) + .apply(); } } diff --git a/app/src/main/java/com/limelight/PcView.java b/app/src/main/java/com/limelight/PcView.java index 0efff0bc..019596f4 100644 --- a/app/src/main/java/com/limelight/PcView.java +++ b/app/src/main/java/com/limelight/PcView.java @@ -32,7 +32,6 @@ import android.app.Service; import android.content.ComponentName; import android.content.Intent; import android.content.ServiceConnection; -import android.content.SharedPreferences; import android.content.res.Configuration; import android.opengl.GLSurfaceView; import android.os.Build; @@ -224,32 +223,6 @@ public class PcView extends Activity implements AdapterFragmentCallbacks { PreferenceConfiguration.readPreferences(this).smallIconMode); initializeViews(); - - SharedPreferences prefs = getSharedPreferences("DecoderTombstone", 0); - int crashCount = prefs.getInt("CrashCount", 0); - int lastNotifiedCrashCount = prefs.getInt("LastNotifiedCrashCount", 0); - - // Remember the last crash count we notified at, so we don't - // display the crash dialog every time the app is started until - // they stream again - if (crashCount != 0 && crashCount != lastNotifiedCrashCount) { - if (crashCount % 3 == 0) { - // At 3 consecutive crashes, we'll forcefully reset their settings - PreferenceConfiguration.resetStreamingSettings(this); - Dialog.displayDialog(this, - getResources().getString(R.string.title_decoding_reset), - getResources().getString(R.string.message_decoding_reset), - false); - } - else { - Dialog.displayDialog(this, - getResources().getString(R.string.title_decoding_error), - getResources().getString(R.string.message_decoding_error), - false); - } - - prefs.edit().putInt("LastNotifiedCrashCount", crashCount).apply(); - } } private void startComputerUpdates() { @@ -305,6 +278,9 @@ public class PcView extends Activity implements AdapterFragmentCallbacks { protected void onResume() { super.onResume(); + // Display a decoder crash notification if we've returned after a crash + UiHelper.showDecoderCrashDialog(this); + inForeground = true; startComputerUpdates(); } diff --git a/app/src/main/java/com/limelight/utils/Dialog.java b/app/src/main/java/com/limelight/utils/Dialog.java index 66d1ddb9..7b3f9fd7 100644 --- a/app/src/main/java/com/limelight/utils/Dialog.java +++ b/app/src/main/java/com/limelight/utils/Dialog.java @@ -13,18 +13,18 @@ public class Dialog implements Runnable { private final String title; private final String message; private final Activity activity; - private final boolean endAfterDismiss; + private final Runnable runOnDismiss; private AlertDialog alert; private static final ArrayList rundownDialogs = new ArrayList<>(); - private Dialog(Activity activity, String title, String message, boolean endAfterDismiss) + private Dialog(Activity activity, String title, String message, Runnable runOnDismiss) { this.activity = activity; this.title = title; this.message = message; - this.endAfterDismiss = endAfterDismiss; + this.runOnDismiss = runOnDismiss; } public static void closeDialogs() @@ -40,9 +40,21 @@ public class Dialog implements Runnable { } } - public static void displayDialog(Activity activity, String title, String message, boolean endAfterDismiss) + public static void displayDialog(final Activity activity, String title, String message, final boolean endAfterDismiss) { - activity.runOnUiThread(new Dialog(activity, title, message, endAfterDismiss)); + activity.runOnUiThread(new Dialog(activity, title, message, new Runnable() { + @Override + public void run() { + if (endAfterDismiss) { + activity.finish(); + } + } + })); + } + + public static void displayDialog(Activity activity, String title, String message, Runnable runOnDismiss) + { + activity.runOnUiThread(new Dialog(activity, title, message, runOnDismiss)); } @Override @@ -65,9 +77,7 @@ public class Dialog implements Runnable { alert.dismiss(); } - if (endAfterDismiss) { - activity.finish(); - } + runOnDismiss.run(); } }); alert.setButton(AlertDialog.BUTTON_NEUTRAL, activity.getResources().getText(R.string.help), new DialogInterface.OnClickListener() { @@ -77,9 +87,7 @@ public class Dialog implements Runnable { alert.dismiss(); } - if (endAfterDismiss) { - activity.finish(); - } + runOnDismiss.run(); HelpLauncher.launchTroubleshooting(activity); } diff --git a/app/src/main/java/com/limelight/utils/UiHelper.java b/app/src/main/java/com/limelight/utils/UiHelper.java index 201f9e98..f2e49617 100644 --- a/app/src/main/java/com/limelight/utils/UiHelper.java +++ b/app/src/main/java/com/limelight/utils/UiHelper.java @@ -5,6 +5,7 @@ import android.app.AlertDialog; import android.app.UiModeManager; import android.content.Context; import android.content.DialogInterface; +import android.content.SharedPreferences; import android.content.res.Configuration; import android.view.View; @@ -58,6 +59,44 @@ public class UiHelper { } } + public static void showDecoderCrashDialog(Activity activity) { + final SharedPreferences prefs = activity.getSharedPreferences("DecoderTombstone", 0); + final int crashCount = prefs.getInt("CrashCount", 0); + int lastNotifiedCrashCount = prefs.getInt("LastNotifiedCrashCount", 0); + + // Remember the last crash count we notified at, so we don't + // display the crash dialog every time the app is started until + // they stream again + if (crashCount != 0 && crashCount != lastNotifiedCrashCount) { + if (crashCount % 3 == 0) { + // At 3 consecutive crashes, we'll forcefully reset their settings + PreferenceConfiguration.resetStreamingSettings(activity); + Dialog.displayDialog(activity, + activity.getResources().getString(R.string.title_decoding_reset), + activity.getResources().getString(R.string.message_decoding_reset), + new Runnable() { + @Override + public void run() { + // Mark notification as acknowledged on dismissal + prefs.edit().putInt("LastNotifiedCrashCount", crashCount).apply(); + } + }); + } + else { + Dialog.displayDialog(activity, + activity.getResources().getString(R.string.title_decoding_error), + activity.getResources().getString(R.string.message_decoding_error), + new Runnable() { + @Override + public void run() { + // Mark notification as acknowledged on dismissal + prefs.edit().putInt("LastNotifiedCrashCount", crashCount).apply(); + } + }); + } + } + } + public static void displayQuitConfirmationDialog(Activity parent, final Runnable onYes, final Runnable onNo) { DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { @Override