Improve decoder crash reporting reliability

This commit is contained in:
Cameron Gutman
2017-11-25 13:19:30 -08:00
parent 5f4aab8f94
commit 02c4ed2724
5 changed files with 72 additions and 41 deletions

View File

@@ -304,6 +304,9 @@ public class AppView extends Activity implements AdapterFragmentCallbacks {
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
// Display a decoder crash notification if we've returned after a crash
UiHelper.showDecoderCrashDialog(this);
inForeground = true; inForeground = true;
startComputerUpdates(); startComputerUpdates();
} }

View File

@@ -105,6 +105,7 @@ public class Game extends Activity implements SurfaceHolder.Callback,
private ShortcutHelper shortcutHelper; private ShortcutHelper shortcutHelper;
private MediaCodecDecoderRenderer decoderRenderer; private MediaCodecDecoderRenderer decoderRenderer;
private boolean reportedCrash;
private WifiManager.WifiLock wifiLock; 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 // 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(); tombstonePrefs.edit().putInt("CrashCount", tombstonePrefs.getInt("CrashCount", 0) + 1).commit();
reportedCrash = true;
} }
}, },
tombstonePrefs.getInt("CrashCount", 0), tombstonePrefs.getInt("CrashCount", 0),
@@ -610,9 +612,12 @@ public class Game extends Activity implements SurfaceHolder.Callback,
Toast.makeText(this, message, Toast.LENGTH_LONG).show(); Toast.makeText(this, message, Toast.LENGTH_LONG).show();
} }
// Clear the tombstone count // Clear the tombstone count if we terminated normally
if (tombstonePrefs.getInt("CrashCount", 0) != 0) { if (!reportedCrash && tombstonePrefs.getInt("CrashCount", 0) != 0) {
tombstonePrefs.edit().putInt("CrashCount", 0).apply(); tombstonePrefs.edit()
.putInt("CrashCount", 0)
.putInt("LastNotifiedCrashCount", 0)
.apply();
} }
} }

View File

@@ -32,7 +32,6 @@ import android.app.Service;
import android.content.ComponentName; import android.content.ComponentName;
import android.content.Intent; import android.content.Intent;
import android.content.ServiceConnection; import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.opengl.GLSurfaceView; import android.opengl.GLSurfaceView;
import android.os.Build; import android.os.Build;
@@ -224,32 +223,6 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
PreferenceConfiguration.readPreferences(this).smallIconMode); PreferenceConfiguration.readPreferences(this).smallIconMode);
initializeViews(); 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() { private void startComputerUpdates() {
@@ -305,6 +278,9 @@ public class PcView extends Activity implements AdapterFragmentCallbacks {
protected void onResume() { protected void onResume() {
super.onResume(); super.onResume();
// Display a decoder crash notification if we've returned after a crash
UiHelper.showDecoderCrashDialog(this);
inForeground = true; inForeground = true;
startComputerUpdates(); startComputerUpdates();
} }

View File

@@ -13,18 +13,18 @@ public class Dialog implements Runnable {
private final String title; private final String title;
private final String message; private final String message;
private final Activity activity; private final Activity activity;
private final boolean endAfterDismiss; private final Runnable runOnDismiss;
private AlertDialog alert; private AlertDialog alert;
private static final ArrayList<Dialog> rundownDialogs = new ArrayList<>(); private static final ArrayList<Dialog> 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.activity = activity;
this.title = title; this.title = title;
this.message = message; this.message = message;
this.endAfterDismiss = endAfterDismiss; this.runOnDismiss = runOnDismiss;
} }
public static void closeDialogs() 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 @Override
@@ -65,9 +77,7 @@ public class Dialog implements Runnable {
alert.dismiss(); alert.dismiss();
} }
if (endAfterDismiss) { runOnDismiss.run();
activity.finish();
}
} }
}); });
alert.setButton(AlertDialog.BUTTON_NEUTRAL, activity.getResources().getText(R.string.help), new DialogInterface.OnClickListener() { 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(); alert.dismiss();
} }
if (endAfterDismiss) { runOnDismiss.run();
activity.finish();
}
HelpLauncher.launchTroubleshooting(activity); HelpLauncher.launchTroubleshooting(activity);
} }

View File

@@ -5,6 +5,7 @@ import android.app.AlertDialog;
import android.app.UiModeManager; import android.app.UiModeManager;
import android.content.Context; import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.content.res.Configuration; import android.content.res.Configuration;
import android.view.View; 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) { public static void displayQuitConfirmationDialog(Activity parent, final Runnable onYes, final Runnable onNo) {
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() { DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override @Override