mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-10 19:13:03 +02:00
Bugsnag 5.9.3
This commit is contained in:
@@ -25,7 +25,7 @@ internal class BreadcrumbInternal internal constructor(
|
||||
@Throws(IOException::class)
|
||||
override fun toStream(writer: JsonStream) {
|
||||
writer.beginObject()
|
||||
writer.name("timestamp").value(DateUtils.toIso8601(timestamp))
|
||||
writer.name("timestamp").value(timestamp)
|
||||
writer.name("name").value(message)
|
||||
writer.name("type").value(type.toString())
|
||||
writer.name("metaData")
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package com.bugsnag.android;
|
||||
|
||||
import static com.bugsnag.android.ContextExtensionsKt.getActivityManagerFrom;
|
||||
import static com.bugsnag.android.ContextExtensionsKt.getStorageManagerFrom;
|
||||
import static com.bugsnag.android.ImmutableConfigKt.sanitiseConfiguration;
|
||||
import static com.bugsnag.android.SeverityReason.REASON_HANDLED_EXCEPTION;
|
||||
|
||||
@@ -74,7 +76,10 @@ public class Client implements MetadataAware, CallbackAware, UserAware {
|
||||
private final SessionLifecycleCallback sessionLifecycleCallback;
|
||||
|
||||
private final Connectivity connectivity;
|
||||
|
||||
@Nullable
|
||||
private final StorageManager storageManager;
|
||||
|
||||
final Logger logger;
|
||||
final DeliveryDelegate deliveryDelegate;
|
||||
|
||||
@@ -143,7 +148,7 @@ public class Client implements MetadataAware, CallbackAware, UserAware {
|
||||
int maxBreadcrumbs = immutableConfig.getMaxBreadcrumbs();
|
||||
breadcrumbState = new BreadcrumbState(maxBreadcrumbs, callbackState, logger);
|
||||
|
||||
storageManager = (StorageManager) appContext.getSystemService(Context.STORAGE_SERVICE);
|
||||
storageManager = getStorageManagerFrom(appContext);
|
||||
|
||||
contextState = new ContextState();
|
||||
contextState.setContext(configuration.getContext());
|
||||
@@ -153,8 +158,7 @@ public class Client implements MetadataAware, CallbackAware, UserAware {
|
||||
sessionStore, logger, bgTaskService);
|
||||
metadataState = copyMetadataState(configuration);
|
||||
|
||||
ActivityManager am =
|
||||
(ActivityManager) appContext.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
ActivityManager am = getActivityManagerFrom(appContext);
|
||||
|
||||
launchCrashTracker = new LaunchCrashTracker(immutableConfig);
|
||||
appDataCollector = new AppDataCollector(appContext, appContext.getPackageManager(),
|
||||
@@ -256,7 +260,7 @@ public class Client implements MetadataAware, CallbackAware, UserAware {
|
||||
ActivityBreadcrumbCollector activityBreadcrumbCollector,
|
||||
SessionLifecycleCallback sessionLifecycleCallback,
|
||||
Connectivity connectivity,
|
||||
StorageManager storageManager,
|
||||
@Nullable StorageManager storageManager,
|
||||
Logger logger,
|
||||
DeliveryDelegate deliveryDelegate,
|
||||
LastRunInfoStore lastRunInfoStore,
|
||||
|
||||
@@ -24,9 +24,11 @@ internal class ConnectivityCompat(
|
||||
callback: NetworkChangeCallback?
|
||||
) : Connectivity {
|
||||
|
||||
private val cm = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
|
||||
private val cm = context.getConnectivityManager()
|
||||
|
||||
private val connectivity: Connectivity =
|
||||
when {
|
||||
cm == null -> UnknownConnectivity
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N -> ConnectivityApi24(cm, callback)
|
||||
else -> ConnectivityLegacy(context, cm, callback)
|
||||
}
|
||||
@@ -125,3 +127,21 @@ internal class ConnectivityApi24(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Connectivity used in cases where we cannot access the system ConnectivityManager.
|
||||
* We assume that there is some sort of network and do not attempt to report any network changes.
|
||||
*/
|
||||
internal object UnknownConnectivity : Connectivity {
|
||||
override fun registerForNetworkChanges() {}
|
||||
|
||||
override fun unregisterForNetworkChanges() {}
|
||||
|
||||
override fun hasNetworkConnection(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun retrieveNetworkAccessState(): String {
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
package com.bugsnag.android
|
||||
|
||||
import android.app.ActivityManager
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.ConnectivityManager
|
||||
import android.os.RemoteException
|
||||
import android.os.storage.StorageManager
|
||||
import java.lang.RuntimeException
|
||||
|
||||
/**
|
||||
* Calls [Context.registerReceiver] but swallows [SecurityException] and [RemoteException]
|
||||
@@ -45,3 +49,23 @@ internal fun Context.unregisterReceiverSafe(
|
||||
logger?.w("Failed to register receiver", exc)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <reified T> Context.safeGetSystemService(name: String): T? {
|
||||
return try {
|
||||
getSystemService(name) as? T
|
||||
} catch (exc: RuntimeException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
@JvmName("getActivityManagerFrom")
|
||||
internal fun Context.getActivityManager(): ActivityManager? =
|
||||
safeGetSystemService(Context.ACTIVITY_SERVICE)
|
||||
|
||||
@JvmName("getConnectivityManagerFrom")
|
||||
internal fun Context.getConnectivityManager(): ConnectivityManager? =
|
||||
safeGetSystemService(Context.CONNECTIVITY_SERVICE)
|
||||
|
||||
@JvmName("getStorageManagerFrom")
|
||||
internal fun Context.getStorageManager(): StorageManager? =
|
||||
safeGetSystemService(Context.STORAGE_SERVICE)
|
||||
|
||||
@@ -42,7 +42,7 @@ class DeviceWithState internal constructor(
|
||||
writer.name("orientation").value(orientation)
|
||||
|
||||
if (time != null) {
|
||||
writer.name("time").value(DateUtils.toIso8601(time!!))
|
||||
writer.name("time").value(time)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,17 +11,17 @@ internal class ErrorInternal @JvmOverloads internal constructor(
|
||||
|
||||
internal companion object {
|
||||
fun createError(exc: Throwable, projectPackages: Collection<String>, logger: Logger): MutableList<Error> {
|
||||
val errors = mutableListOf<ErrorInternal>()
|
||||
return exc.safeUnrollCauses()
|
||||
.mapTo(mutableListOf()) { currentEx ->
|
||||
// Somehow it's possible for stackTrace to be null in rare cases
|
||||
val stacktrace = currentEx.stackTrace ?: arrayOf<StackTraceElement>()
|
||||
val trace =
|
||||
Stacktrace.stacktraceFromJavaTrace(stacktrace, projectPackages, logger)
|
||||
val errorInternal =
|
||||
ErrorInternal(currentEx.javaClass.name, currentEx.localizedMessage, trace)
|
||||
|
||||
var currentEx: Throwable? = exc
|
||||
while (currentEx != null) {
|
||||
// Somehow it's possible for stackTrace to be null in rare cases
|
||||
val stacktrace = currentEx.stackTrace ?: arrayOf<StackTraceElement>()
|
||||
val trace = Stacktrace.stacktraceFromJavaTrace(stacktrace, projectPackages, logger)
|
||||
errors.add(ErrorInternal(currentEx.javaClass.name, currentEx.localizedMessage, trace))
|
||||
currentEx = currentEx.cause
|
||||
}
|
||||
return errors.map { Error(it, logger) }.toMutableList()
|
||||
return@mapTo Error(errorInternal, logger)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ internal class EventInternal @JvmOverloads internal constructor(
|
||||
val copy = Session.copySession(session)
|
||||
writer.name("session").beginObject()
|
||||
writer.name("id").value(copy.id)
|
||||
writer.name("startedAt").value(DateUtils.toIso8601(copy.startedAt))
|
||||
writer.name("startedAt").value(copy.startedAt)
|
||||
writer.name("events").beginObject()
|
||||
writer.name("handled").value(copy.handledCount.toLong())
|
||||
writer.name("unhandled").value(copy.unhandledCount.toLong())
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
package com.bugsnag.android;
|
||||
|
||||
import static com.bugsnag.android.ContextExtensionsKt.getActivityManagerFrom;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Process;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
class ForegroundDetector {
|
||||
|
||||
@Nullable
|
||||
private final ActivityManager activityManager;
|
||||
|
||||
ForegroundDetector(Context context) {
|
||||
this.activityManager =
|
||||
(ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
this.activityManager = getActivityManagerFrom(context);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,6 +59,10 @@ class ForegroundDetector {
|
||||
|
||||
@Nullable
|
||||
private ActivityManager.RunningAppProcessInfo getProcessInfoPreApi16() {
|
||||
if (activityManager == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<ActivityManager.RunningAppProcessInfo> appProcesses
|
||||
= activityManager.getRunningAppProcesses();
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import android.os.Build;
|
||||
import android.os.storage.StorageManager;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -22,6 +23,8 @@ class InternalReportDelegate implements EventStore.Delegate {
|
||||
|
||||
final Logger logger;
|
||||
final ImmutableConfig config;
|
||||
|
||||
@Nullable
|
||||
final StorageManager storageManager;
|
||||
|
||||
final AppDataCollector appDataCollector;
|
||||
@@ -34,7 +37,7 @@ class InternalReportDelegate implements EventStore.Delegate {
|
||||
InternalReportDelegate(Context context,
|
||||
Logger logger,
|
||||
ImmutableConfig immutableConfig,
|
||||
StorageManager storageManager,
|
||||
@Nullable StorageManager storageManager,
|
||||
AppDataCollector appDataCollector,
|
||||
DeviceDataCollector deviceDataCollector,
|
||||
SessionTracker sessionTracker,
|
||||
@@ -72,7 +75,7 @@ class InternalReportDelegate implements EventStore.Delegate {
|
||||
}
|
||||
|
||||
void recordStorageCacheBehavior(Event event) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
if (storageManager != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
File cacheDir = appContext.getCacheDir();
|
||||
File errDir = new File(cacheDir, "bugsnag-errors");
|
||||
|
||||
@@ -113,7 +116,7 @@ class InternalReportDelegate implements EventStore.Delegate {
|
||||
// can only modify headers if DefaultDelivery is in use
|
||||
if (delivery instanceof DefaultDelivery) {
|
||||
Map<String, String> headers = params.getHeaders();
|
||||
headers.put(HEADER_INTERNAL_ERROR, "true");
|
||||
headers.put(HEADER_INTERNAL_ERROR, "bugsnag-android");
|
||||
headers.remove(DeliveryHeadersKt.HEADER_API_KEY);
|
||||
DefaultDelivery defaultDelivery = (DefaultDelivery) delivery;
|
||||
defaultDelivery.deliver(params.getEndpoint(), payload, headers);
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.io.IOException
|
||||
*/
|
||||
class Notifier @JvmOverloads constructor(
|
||||
var name: String = "Android Bugsnag Notifier",
|
||||
var version: String = "5.9.2",
|
||||
var version: String = "5.9.3",
|
||||
var url: String = "https://bugsnag.com"
|
||||
) : JsonStream.Streamable {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.bugsnag.android
|
||||
|
||||
import java.io.IOException
|
||||
import java.lang.reflect.Array
|
||||
import java.util.Date
|
||||
|
||||
internal class ObjectJsonStreamer {
|
||||
|
||||
@@ -21,6 +22,7 @@ internal class ObjectJsonStreamer {
|
||||
obj is Number -> writer.value(obj)
|
||||
obj is Boolean -> writer.value(obj)
|
||||
obj is JsonStream.Streamable -> obj.toStream(writer)
|
||||
obj is Date -> writer.value(DateUtils.toIso8601(obj))
|
||||
obj is Map<*, *> -> mapToStream(writer, obj, shouldRedactKeys)
|
||||
obj is Collection<*> -> collectionToStream(writer, obj)
|
||||
obj.javaClass.isArray -> arrayToStream(writer, obj)
|
||||
|
||||
@@ -232,7 +232,7 @@ public final class Session implements JsonStream.Streamable, UserAware {
|
||||
void serializeSessionInfo(@NonNull JsonStream writer) throws IOException {
|
||||
writer.beginObject();
|
||||
writer.name("id").value(id);
|
||||
writer.name("startedAt").value(DateUtils.toIso8601(startedAt));
|
||||
writer.name("startedAt").value(startedAt);
|
||||
writer.name("user").value(user);
|
||||
writer.endObject();
|
||||
}
|
||||
|
||||
@@ -2,9 +2,11 @@ package com.bugsnag.android;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -87,12 +89,7 @@ class StrictModeHandler {
|
||||
* @return the root cause of the throwable
|
||||
*/
|
||||
private Throwable getRootCause(Throwable throwable) {
|
||||
Throwable cause = throwable.getCause();
|
||||
|
||||
if (cause == null) {
|
||||
return throwable;
|
||||
} else {
|
||||
return getRootCause(cause);
|
||||
}
|
||||
List<Throwable> causes = ThrowableUtils.safeUnrollCauses(throwable);
|
||||
return causes.get(causes.size() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,14 @@ import java.io.IOException
|
||||
/**
|
||||
* Capture and serialize the state of all threads at the time of an exception.
|
||||
*/
|
||||
internal class ThreadState @JvmOverloads constructor(
|
||||
internal class ThreadState @Suppress("LongParameterList") @JvmOverloads constructor(
|
||||
exc: Throwable?,
|
||||
isUnhandled: Boolean,
|
||||
sendThreads: ThreadSendPolicy,
|
||||
projectPackages: Collection<String>,
|
||||
logger: Logger,
|
||||
currentThread: java.lang.Thread = java.lang.Thread.currentThread(),
|
||||
stackTraces: MutableMap<java.lang.Thread, Array<StackTraceElement>> = java.lang.Thread.getAllStackTraces()
|
||||
stackTraces: MutableMap<java.lang.Thread, Array<StackTraceElement>>? = null
|
||||
) : JsonStream.Streamable {
|
||||
|
||||
internal constructor(
|
||||
@@ -29,7 +29,7 @@ internal class ThreadState @JvmOverloads constructor(
|
||||
|
||||
threads = when {
|
||||
recordThreads -> captureThreadTrace(
|
||||
stackTraces,
|
||||
stackTraces ?: java.lang.Thread.getAllStackTraces(),
|
||||
currentThread,
|
||||
exc,
|
||||
isUnhandled,
|
||||
|
||||
19
app/src/main/java/com/bugsnag/android/ThrowableExtensions.kt
Normal file
19
app/src/main/java/com/bugsnag/android/ThrowableExtensions.kt
Normal file
@@ -0,0 +1,19 @@
|
||||
@file:JvmName("ThrowableUtils")
|
||||
package com.bugsnag.android
|
||||
|
||||
/**
|
||||
* Unroll the list of causes for this Throwable, handling any recursion that may appear within
|
||||
* the chain. The first element returned will be this Throwable, and the last will be the root
|
||||
* cause or last non-recursive Throwable.
|
||||
*/
|
||||
internal fun Throwable.safeUnrollCauses(): List<Throwable> {
|
||||
val causes = LinkedHashSet<Throwable>()
|
||||
var currentEx: Throwable? = this
|
||||
|
||||
// Set.add will return false if we have already "seen" currentEx
|
||||
while (currentEx != null && causes.add(currentEx)) {
|
||||
currentEx = currentEx.cause
|
||||
}
|
||||
|
||||
return causes.toList()
|
||||
}
|
||||
Reference in New Issue
Block a user