Bugsnag 5.9.3

pull/199/head
M66B 3 years ago
parent e363d5bb34
commit 7ce6d3b50e

@ -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,

@ -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()
}
Loading…
Cancel
Save