diff --git a/bugsnag-plugin-android-exitinfo/api/bugsnag-plugin-android-exitinfo.api b/bugsnag-plugin-android-exitinfo/api/bugsnag-plugin-android-exitinfo.api index 9d055a22c5..5a3a43aded 100644 --- a/bugsnag-plugin-android-exitinfo/api/bugsnag-plugin-android-exitinfo.api +++ b/bugsnag-plugin-android-exitinfo/api/bugsnag-plugin-android-exitinfo.api @@ -1,10 +1,22 @@ public final class com/bugsnag/android/BugsnagExitInfoPlugin : com/bugsnag/android/Plugin { public fun ()V - public fun (Z)V - public fun (ZZ)V - public fun (ZZZ)V - public synthetic fun (ZZZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun (Lcom/bugsnag/android/ExitInfoPluginConfiguration;)V + public synthetic fun (Lcom/bugsnag/android/ExitInfoPluginConfiguration;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public fun load (Lcom/bugsnag/android/Client;)V public fun unload ()V } +public final class com/bugsnag/android/ExitInfoPluginConfiguration { + public fun ()V + public fun (ZZZ)V + public synthetic fun (ZZZILkotlin/jvm/internal/DefaultConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z + public final fun getDisableProcessStateSummaryOverride ()Z + public final fun getIncludeLogcat ()Z + public final fun getListOpenFds ()Z + public fun hashCode ()I + public final fun setDisableProcessStateSummaryOverride (Z)V + public final fun setIncludeLogcat (Z)V + public final fun setListOpenFds (Z)V +} + diff --git a/bugsnag-plugin-android-exitinfo/build.gradle b/bugsnag-plugin-android-exitinfo/build.gradle index f97d4f819e..835102de1c 100644 --- a/bugsnag-plugin-android-exitinfo/build.gradle +++ b/bugsnag-plugin-android-exitinfo/build.gradle @@ -15,6 +15,12 @@ dependencies { implementation 'com.google.protobuf:protobuf-javalite:3.24.2' } +android.libraryVariants.configureEach { variant -> + variant.processJavaResourcesProvider.configure { + exclude('**/*.proto') + } +} + protobuf { protoc { artifact = 'com.google.protobuf:protoc:3.24.2' @@ -22,7 +28,7 @@ protobuf { generateProtoTasks { all().configureEach { task -> task.builtins { - java{ + java { option "lite" } } diff --git a/bugsnag-plugin-android-exitinfo/detekt-baseline.xml b/bugsnag-plugin-android-exitinfo/detekt-baseline.xml index da7162b681..a022fb6b72 100644 --- a/bugsnag-plugin-android-exitinfo/detekt-baseline.xml +++ b/bugsnag-plugin-android-exitinfo/detekt-baseline.xml @@ -24,6 +24,7 @@ MaxLineLength:TraceParserTest.kt$TraceParserTest$"void* std::__1::__thread_proxy<std::__1::tuple<std::__1::unique_ptr<std::__1::__thread_struct, std::__1::default_delete<std::__1::__thread_struct> >, void (android::AsyncWorker::*)(), android::AsyncWorker*> >(void*)" NestedBlockDepth:TraceParser.kt$TraceParser$private fun parseThreadAttributes(line: String) ReturnCount:TraceParser.kt$TraceParser$@VisibleForTesting internal fun parseNativeFrame(line: String): Stackframe? + SwallowedException:BugsnagExitInfoPlugin.kt$BugsnagExitInfoPlugin$e: Exception SwallowedException:ExitInfoCallback.kt$ExitInfoCallback$exc: Throwable diff --git a/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/BugsnagExitInfoPlugin.kt b/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/BugsnagExitInfoPlugin.kt index 21ff7aef5b..a1179ef8c3 100644 --- a/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/BugsnagExitInfoPlugin.kt +++ b/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/BugsnagExitInfoPlugin.kt @@ -7,34 +7,17 @@ import androidx.annotation.RequiresApi @RequiresApi(Build.VERSION_CODES.R) class BugsnagExitInfoPlugin @JvmOverloads constructor( - - /** - * Whether to add the list of open FDs to correlated reports - */ - private val listOpenFds: Boolean = true, - - /** - * Whether to report stored logcat messages metadata - */ - private val includeLogcat: Boolean = false, - - /** - * Turn of event correlation based on the processStateSummary field, this can - * set to `true` if the field is required by the app - */ - private val disableProcessStateSummaryOverride: Boolean = false - + configuration: ExitInfoPluginConfiguration = ExitInfoPluginConfiguration() ) : Plugin { - private var exitInfoCallback: ExitInfoCallback? = null + private val configuration = configuration.copy() override fun load(client: Client) { - if (!disableProcessStateSummaryOverride) { + if (!configuration.disableProcessStateSummaryOverride) { client.addOnSession( OnSessionCallback { session: Session -> - val am = - client.appContext.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager - am.setProcessStateSummary(session.id.toByteArray()) + val am = client.appContext.safeGetActivityManager() + am?.setProcessStateSummary(session.id.toByteArray()) return@OnSessionCallback true } ) @@ -44,15 +27,28 @@ class BugsnagExitInfoPlugin @JvmOverloads constructor( val oldPid = exitInfoPluginStore.load() exitInfoPluginStore.persist(android.os.Process.myPid()) - exitInfoCallback = ExitInfoCallback( + val exitInfoCallback = ExitInfoCallback( client.appContext, oldPid, - TombstoneEventEnhancer(client.logger, listOpenFds, includeLogcat), - TraceEventEnhancer(client.logger, client.immutableConfig.projectPackages) + TombstoneEventEnhancer( + client.logger, + configuration.listOpenFds, + configuration.includeLogcat + ), + TraceEventEnhancer( + client.logger, + client.immutableConfig.projectPackages + ) ) + client.addOnSend(exitInfoCallback) } - override fun unload() { + override fun unload() = Unit + + private fun Context.safeGetActivityManager(): ActivityManager? = try { + getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager + } catch (e: Exception) { + null } } diff --git a/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/ExitInfoPluginConfiguration.kt b/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/ExitInfoPluginConfiguration.kt new file mode 100644 index 0000000000..a9882bd84b --- /dev/null +++ b/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/ExitInfoPluginConfiguration.kt @@ -0,0 +1,39 @@ +package com.bugsnag.android + +class ExitInfoPluginConfiguration( + /** + * Whether to add the list of open file descriptors to correlated reports + */ + var listOpenFds: Boolean = true, + + /** + * Whether to report stored logcat messages metadata + */ + var includeLogcat: Boolean = false, + + /** + * Turn off event correlation based on the + * [processStateSummary](ActivityManager.setProcessStateSummary) field. This can set to `true` + * to stop `BugsnagExitInfoPlugin` overwriting the field if it is being used by the app. + */ + var disableProcessStateSummaryOverride: Boolean = false +) { + constructor() : this(true, false, false) + + internal fun copy() = + ExitInfoPluginConfiguration(listOpenFds, includeLogcat, disableProcessStateSummaryOverride) + + override fun equals(other: Any?): Boolean { + return other is ExitInfoPluginConfiguration && + listOpenFds == other.listOpenFds && + includeLogcat == other.includeLogcat && + disableProcessStateSummaryOverride == other.disableProcessStateSummaryOverride + } + + override fun hashCode(): Int { + var result = listOpenFds.hashCode() + result = 31 * result + includeLogcat.hashCode() + result = 31 * result + disableProcessStateSummaryOverride.hashCode() + return result + } +} diff --git a/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/ExitInfoPluginStore.kt b/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/ExitInfoPluginStore.kt index b3f77b7dde..18f0dd895f 100644 --- a/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/ExitInfoPluginStore.kt +++ b/bugsnag-plugin-android-exitinfo/src/main/java/com/bugsnag/android/ExitInfoPluginStore.kt @@ -15,7 +15,6 @@ internal class ExitInfoPluginStore(config: ImmutableConfig) { try { val text = pid.toString() file.writeText(text) - logger.d("Persisted: $text") } catch (exc: Throwable) { logger.w("Unexpectedly failed to persist PID.", exc) }