Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit 60d804b

Browse files
committed
Improve error reporting & fix some app crashes.
1 parent 22bfae4 commit 60d804b

File tree

8 files changed

+117
-8
lines changed

8 files changed

+117
-8
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
*.iml
22
.gradle
3+
/sentry.properties
34
/local.properties
45
/.idea/
56
.DS_Store

app/build.gradle

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
plugins {
22
id 'com.android.application'
33
id 'com.mikepenz.aboutlibraries.plugin'
4+
id "io.sentry.android.gradle" version "3.1.5"
45
}
56

67
android {
@@ -78,8 +79,25 @@ aboutLibraries {
7879
additionalLicenses = ["LGPL_3_0_only"]
7980
}
8081

82+
sentry {
83+
ignoredBuildTypes = ["debug"]
84+
85+
includeProguardMapping = true
86+
87+
autoUploadProguardMapping = isLocalSentry
88+
89+
tracingInstrumentation {
90+
enabled = false
91+
}
92+
93+
autoInstallation {
94+
enabled = false
95+
}
96+
}
97+
8198
configurations {
8299
implementation.exclude group: 'org.jetbrains' , module: 'annotations'
100+
implementation.exclude group: 'io.sentry' , module: 'sentry-android-okhttp'
83101
}
84102

85103
dependencies {
@@ -109,8 +127,8 @@ dependencies {
109127
implementation 'com.github.Fox2Code:AndroidANSI:1.0.1'
110128

111129
// Error reporting
112-
implementation 'io.sentry:sentry-android:6.4.0'
113-
implementation 'io.sentry:sentry-android-fragment:6.4.0'
130+
implementation 'io.sentry:sentry-android:6.4.1'
131+
implementation 'io.sentry:sentry-android-fragment:6.4.1'
114132

115133
// Markdown
116134
implementation "io.noties.markwon:core:4.6.2"

app/src/main/java/com/fox2code/mmm/MainApplication.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@
99
import android.graphics.Color;
1010
import android.os.Build;
1111
import android.os.SystemClock;
12-
import android.system.ErrnoException;
13-
import android.system.Os;
1412
import android.text.SpannableStringBuilder;
1513
import android.util.Log;
1614

@@ -50,8 +48,8 @@
5048
import io.sentry.JsonObjectWriter;
5149
import io.sentry.NoOpLogger;
5250
import io.sentry.TypeCheckHint;
53-
import io.sentry.UncaughtExceptionHandlerIntegration;
5451
import io.sentry.android.core.SentryAndroid;
52+
import io.sentry.android.fragment.FragmentLifecycleIntegration;
5553
import io.sentry.hints.DiskFlushNotification;
5654

5755
@PrismBundle(
@@ -371,6 +369,7 @@ public void onCreate() {
371369
}
372370

373371
SentryAndroid.init(this, options -> {
372+
options.addIntegration(new FragmentLifecycleIntegration(this, true, false));
374373
// Note: Sentry library only take a screenshot of Fox Magisk Module Manager.
375374
// The screen shot doesn't and cannot contain other applications (if in multi windows)
376375
// status bar and notifications (even if notification shade is pulled down)
@@ -381,6 +380,10 @@ public void onCreate() {
381380
options.setAttachScreenshot(true);
382381
// User interaction tracing is not needed to get context of crash
383382
options.setEnableUserInteractionTracing(false);
383+
// Send client reports has nothing to do with error reporting
384+
options.setSendClientReports(false);
385+
// Auto session tracking has nothing to do with error reporting
386+
options.setEnableAutoSessionTracking(false);
384387
// Add a callback that will be used before the event is sent to Sentry.
385388
// With this callback, you can modify the event or, when returning null, also discard the event.
386389
options.setBeforeSend((event, hint) -> {

app/src/main/java/com/fox2code/mmm/XHooks.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@ public static void onWebViewInitialize(WebView webView,boolean allowInstall) {
5050

5151
@Keep
5252
public static XRepo addXRepo(String url, String fallbackName) {
53-
return RepoManager.getINSTANCE().addOrGet(url, fallbackName);
53+
return RepoManager.getINSTANCE_UNSAFE().addOrGet(url, fallbackName);
5454
}
5555

5656
@Keep
5757
public static XRepo getXRepo(String url) {
58-
return RepoManager.getINSTANCE().get(url);
58+
return RepoManager.getINSTANCE_UNSAFE().get(url);
5959
}
6060
}

app/src/main/java/com/fox2code/mmm/installer/InstallerActivity.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@
4949
import java.util.zip.ZipFile;
5050
import java.util.zip.ZipInputStream;
5151

52+
import io.sentry.Breadcrumb;
53+
import io.sentry.Sentry;
54+
import io.sentry.SentryLevel;
55+
5256
public class InstallerActivity extends FoxActivity {
5357
private static final String TAG = "InstallerActivity";
5458
public LinearProgressIndicator progressIndicator;
@@ -99,6 +103,17 @@ protected void onCreate(Bundle savedInstanceState) {
99103
return;
100104
}
101105
Log.i(TAG, "Install link: " + target);
106+
// Note: Sentry only send this info on crash.
107+
if (MainApplication.isCrashReportingEnabled()) {
108+
Breadcrumb breadcrumb = new Breadcrumb();
109+
breadcrumb.setType("install");
110+
breadcrumb.setData("target", target);
111+
breadcrumb.setData("name", name);
112+
breadcrumb.setData("checksum", checksum);
113+
breadcrumb.setCategory("app.action.preinstall");
114+
breadcrumb.setLevel(SentryLevel.INFO);
115+
Sentry.addBreadcrumb(breadcrumb);
116+
}
102117
boolean urlMode = target.startsWith("http://") || target.startsWith("https://");
103118
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
104119
setTitle(name);
@@ -138,9 +153,10 @@ protected void onCreate(Bundle savedInstanceState) {
138153
!new SuFile(moduleCache.getAbsolutePath()).delete())
139154
Log.e(TAG, "Failed to delete module cache");
140155
String errMessage = "Failed to download module zip";
156+
byte[] rawModule;
141157
try {
142158
Log.i(TAG, (urlMode ? "Downloading: " : "Loading: ") + target);
143-
byte[] rawModule = urlMode ? Http.doHttpGet(target, (progress, max, done) -> {
159+
rawModule = urlMode ? Http.doHttpGet(target, (progress, max, done) -> {
144160
if (max <= 0 && this.progressIndicator.isIndeterminate())
145161
return;
146162
this.runOnUiThread(() -> {
@@ -227,6 +243,14 @@ protected void onCreate(Bundle savedInstanceState) {
227243
Log.e(TAG, errMessage, e);
228244
this.setInstallStateFinished(false,
229245
"! " + errMessage, "");
246+
} catch (OutOfMemoryError e) {
247+
//noinspection UnusedAssignment (Important to avoid OutOfMemoryError)
248+
rawModule = null; // Because reference is kept when calling setInstallStateFinished
249+
if ("Failed to install module zip".equals(errMessage))
250+
throw e; // Ignore if in installation state.
251+
Log.e(TAG, "Module too large", e);
252+
this.setInstallStateFinished(false,
253+
"! Module is too large to be loaded on this device", "");
230254
}
231255
}, "Module install Thread").start();
232256
}
@@ -416,6 +440,19 @@ private void doInstall(File file, boolean noExtensions, boolean rootless) {
416440
"cd \"" + this.moduleCache.getAbsolutePath() + "\"",
417441
installCommand).to(installerController, installerMonitor);
418442
}
443+
// Note: Sentry only send this info on crash.
444+
if (MainApplication.isCrashReportingEnabled()) {
445+
Breadcrumb breadcrumb = new Breadcrumb();
446+
breadcrumb.setType("install");
447+
breadcrumb.setData("moduleId", moduleId == null ? "<null>" : moduleId);
448+
breadcrumb.setData("isAnyKernel3", anyKernel3 ? "true" : "false");
449+
breadcrumb.setData("noExtensions", noExtensions ? "true" : "false");
450+
breadcrumb.setData("ansi", this.installerTerminal
451+
.isAnsiEnabled() ? "enabled" : "disabled");
452+
breadcrumb.setCategory("app.action.install");
453+
breadcrumb.setLevel(SentryLevel.INFO);
454+
Sentry.addBreadcrumb(breadcrumb);
455+
}
419456
}
420457
boolean success = installJob.exec().isSuccess();
421458
// Wait one UI cycle before disabling controller or processing results

app/src/main/java/com/fox2code/mmm/repo/RepoManager.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,23 @@ public final class RepoManager extends SyncManager {
5757
private static volatile RepoManager INSTANCE;
5858

5959
public static RepoManager getINSTANCE() {
60+
if (INSTANCE == null || !INSTANCE.initialized) {
61+
synchronized (lock) {
62+
if (INSTANCE == null) {
63+
MainApplication mainApplication = MainApplication.getINSTANCE();
64+
if (mainApplication != null) {
65+
INSTANCE = new RepoManager(mainApplication);
66+
XHooks.onRepoManagerInitialized();
67+
} else {
68+
throw new RuntimeException("Getting RepoManager too soon!");
69+
}
70+
}
71+
}
72+
}
73+
return INSTANCE;
74+
}
75+
76+
public static RepoManager getINSTANCE_UNSAFE() {
6077
if (INSTANCE == null) {
6178
synchronized (lock) {
6279
if (INSTANCE == null) {

app/src/main/java/com/fox2code/mmm/utils/Hashes.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import android.util.Log;
44

5+
import java.io.IOException;
6+
import java.io.InputStream;
57
import java.security.MessageDigest;
68
import java.security.NoSuchAlgorithmException;
79
import java.util.Locale;
@@ -88,6 +90,35 @@ public static boolean checkSumMatch(byte[] data, String checksum) {
8890
return hash.equals(checksum.toLowerCase(Locale.ROOT));
8991
}
9092

93+
/**
94+
* Check if the checksum match a file by picking the correct
95+
* hashing algorithm depending on the length of the checksum
96+
*/
97+
public static boolean checkSumMatch(InputStream data, String checksum) throws IOException {
98+
String hash;
99+
if (checksum == null) return false;
100+
String checksumAlgorithm = checkSumName(checksum);
101+
if (checksumAlgorithm == null) {
102+
Log.e(TAG, "No hash algorithm for " +
103+
checksum.length() * 8 + "bit checksums");
104+
return false;
105+
}
106+
try {
107+
MessageDigest md = MessageDigest.getInstance(checksumAlgorithm);
108+
109+
byte[] bytes = new byte[2048];
110+
int nRead;
111+
while ((nRead = data.read(bytes)) > 0) {
112+
md.update(bytes, 0, nRead);
113+
}
114+
hash = bytesToHex(md.digest());
115+
} catch (NoSuchAlgorithmException e) {
116+
throw new RuntimeException(e);
117+
}
118+
Log.d(TAG, "Checksum result (data: " + hash + ",expected: " + checksum + ")");
119+
return hash.equals(checksum.toLowerCase(Locale.ROOT));
120+
}
121+
91122
public static boolean checkSumValid(String checksum) {
92123
if (checksum == null) return false;
93124
switch (checksum.length()) {

build.gradle

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ buildscript {
66
gradlePluginPortal()
77
}
88
project.ext.latestAboutLibsRelease = "10.4.1-a01"
9+
project.ext.isLocalSentry = new File(
10+
rootProject.rootDir, "sentry.properties").exists()
911
dependencies {
1012
classpath 'com.android.tools.build:gradle:7.3.0-rc01'
1113
classpath "com.mikepenz.aboutlibraries.plugin:aboutlibraries-plugin:${latestAboutLibsRelease}"

0 commit comments

Comments
 (0)