Skip to content

Commit

Permalink
feat(metadata): process importance
Browse files Browse the repository at this point in the history
  • Loading branch information
YYChen01988 committed Feb 6, 2024
1 parent c41050e commit c27f836
Show file tree
Hide file tree
Showing 3 changed files with 94 additions and 0 deletions.
1 change: 1 addition & 0 deletions bugsnag-android-core/detekt-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<SmellBaseline>
<ManuallySuppressedIssues/>
<CurrentIssues>
<ID>CyclomaticComplexMethod:AppDataCollector.kt$AppDataCollector$@SuppressLint("SwitchIntDef") @Suppress("DEPRECATION") private fun getProcessImportance(): String?</ID>
<ID>CyclomaticComplexMethod:ConfigInternal.kt$ConfigInternal$fun getConfigDifferences(): Map&lt;String, Any></ID>
<ID>ImplicitDefaultLocale:DeliveryHeaders.kt$String.format("%02x", byte)</ID>
<ID>LongParameterList:App.kt$App$( /** * The architecture of the running application binary */ var binaryArch: String?, /** * The package name of the application */ var id: String?, /** * The release stage set in [Configuration.releaseStage] */ var releaseStage: String?, /** * The version of the application set in [Configuration.version] */ var version: String?, /** The revision ID from the manifest (React Native apps only) */ var codeBundleId: String?, /** * The unique identifier for the build of the application set in [Configuration.buildUuid] */ var buildUuid: String?, /** * The application type set in [Configuration#version] */ var type: String?, /** * The version code of the application set in [Configuration.versionCode] */ var versionCode: Number? )</ID>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,35 @@ class AppDataCollectorTest {
val result = collector.getInstallerPackageName()
assertEquals("Test Installer name", result)
}

@Test
fun testGetProcessImportance() = withBuildSdkInt(Build.VERSION_CODES.Q) {
val packageManager = mock(PackageManager::class.java)
`when`(packageManager.getApplicationLabel(any())).thenReturn("Test App name")
`when`(am.runningAppProcesses).thenReturn(
listOf(
ActivityManager.RunningAppProcessInfo().apply {
importance = ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
}
)
)

val collector = AppDataCollector(
context,
packageManager,
client.immutableConfig,
client.sessionTracker,
am,
client.launchCrashTracker,
client.memoryTrimState
)

val result = collector.getAppDataMetadata()["processImportance"]

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
assertEquals(null, result)
} else {
assertEquals("foreground", result)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,31 @@ package com.bugsnag.android

import android.annotation.SuppressLint
import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CACHED
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_CANT_SAVE_STATE
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_EMPTY
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_GONE
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_PERCEPTIBLE_PRE_26
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_TOP_SLEEPING
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_TOP_SLEEPING_PRE_28
import android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_VISIBLE
import android.app.ActivityManager.RunningAppProcessInfo.REASON_PROVIDER_IN_USE
import android.app.ActivityManager.RunningAppProcessInfo.REASON_SERVICE_IN_USE
import android.app.Application
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build.VERSION
import android.os.Build.VERSION_CODES
import android.os.Process
import android.os.SystemClock
import com.bugsnag.android.internal.ImmutableConfig

const val IMPORTANCE_CANT_SAVE_STATE_PRE_26 = 170

/**
* Collects various data on the application state
*/
Expand Down Expand Up @@ -49,12 +66,55 @@ internal class AppDataCollector(
)
}

@SuppressLint("SwitchIntDef")
@Suppress("DEPRECATION")
private fun getProcessImportance(): String? {
try {
val appInfo = ActivityManager.RunningAppProcessInfo()
if (appInfo.pid == 0) {
return null
}

if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {
ActivityManager.getMyMemoryState(appInfo)
} else {
activityManager?.runningAppProcesses?.find {
it.pid == Process.myPid()
}?.let {
appInfo.importance = it.importance
}
}

return when (appInfo.importance) {
IMPORTANCE_FOREGROUND -> "foreground"
IMPORTANCE_FOREGROUND_SERVICE -> "foreground service"
IMPORTANCE_TOP_SLEEPING -> "top sleeping"
IMPORTANCE_TOP_SLEEPING_PRE_28 -> "top sleeping"
IMPORTANCE_VISIBLE -> "visible"
IMPORTANCE_PERCEPTIBLE -> "perceptible"
IMPORTANCE_PERCEPTIBLE_PRE_26 -> "perceptible"
IMPORTANCE_CANT_SAVE_STATE -> "can't save state"
IMPORTANCE_CANT_SAVE_STATE_PRE_26 -> "can't save state"
IMPORTANCE_SERVICE -> "service"
IMPORTANCE_CACHED -> "cached/background"
IMPORTANCE_GONE -> "gone"
IMPORTANCE_EMPTY -> "empty"
REASON_PROVIDER_IN_USE -> "provider in use"
REASON_SERVICE_IN_USE -> "service in use"
else -> "unknown importance (${activityManager?.runningAppProcesses?.last()?.importance})"
}
} catch (e: Exception) {
return null
}
}

fun getAppDataMetadata(): MutableMap<String, Any?> {
val map = HashMap<String, Any?>()
map["name"] = appName
map["activeScreen"] = sessionTracker.contextActivity
map["lowMemory"] = memoryTrimState.isLowMemory
map["memoryTrimLevel"] = memoryTrimState.trimLevelDescription
map["processImportance"] = getProcessImportance()

populateRuntimeMemoryMetadata(map)

Expand Down Expand Up @@ -128,6 +188,7 @@ internal class AppDataCollector(
packageManager != null && copy != null -> {
packageManager.getApplicationLabel(copy).toString()
}

else -> null
}
}
Expand Down Expand Up @@ -156,6 +217,7 @@ internal class AppDataCollector(
VERSION.SDK_INT >= VERSION_CODES.P -> {
Application.getProcessName()
}

else -> {
// see https://stackoverflow.com/questions/19631894
val clz = Class.forName("android.app.ActivityThread")
Expand Down

0 comments on commit c27f836

Please sign in to comment.