Skip to content

Commit

Permalink
feature: added more information about thermals, exit reasons etc...
Browse files Browse the repository at this point in the history
  • Loading branch information
CraZyLegenD committed Jun 21, 2020
1 parent dd5f314 commit bb13384
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 10 deletions.
1 change: 0 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
xmlns:tools="http://schemas.android.com/tools"
package="com.crazylegend.crashy">

<uses-permission android:name="android.permission.INTERNET"/>

<application
android:allowBackup="true"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
package com.crazylegend.crashyreporter

import android.content.Context
import android.util.Log
import com.crazylegend.crashyreporter.extensions.*
import com.crazylegend.crashyreporter.extensions.getExitReasons
import com.crazylegend.crashyreporter.extensions.getThermalStatus
import com.crazylegend.crashyreporter.extensions.isInPowerSaveMode
import com.crazylegend.crashyreporter.extensions.isSustainedPerformanceModeSupported
import com.crazylegend.crashyreporter.handlers.CrashyExceptionHandler
import com.crazylegend.crashyreporter.handlers.CrashyNotInitializedException
import com.crazylegend.crashyreporter.utils.DeviceUtils
Expand Down Expand Up @@ -60,6 +66,17 @@ object CrashyReporter {
*/
fun initialize(context: Context) {
applicationContext = context

Log.d("THERMAL", context.getThermalStatus.toString())
context.getExitReasons(0, Int.MAX_VALUE).forEach {
Log.d("EXIT REASON", it.toString())
}
Log.d("SUSTAINED PERFORMANCE", context.isSustainedPerformanceModeSupported.toString())
Log.d("isInPowerSaveMode", context.isInPowerSaveMode.toString())
Log.d("isInInteractiveState", context.isInInteractiveState.toString())
Log.d("IgnoringBatteryOptimiz", context.isIgnoringBatteryOptimization.toString())
Log.d("locationPowerSaveMode", context.locationPowerSaveMode.toString())
Log.d("isDeviceIdle", context.isDeviceIdle.toString())
}


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package com.crazylegend.crashyreporter.extensions

import android.app.ActivityManager
import android.app.ActivityManager.RunningAppProcessInfo.*
import android.app.ApplicationExitInfo.*
import android.content.Context
import android.os.Build
import android.os.PowerManager
import android.os.PowerManager.*
import androidx.annotation.RequiresApi
import com.crazylegend.crashyreporter.CrashyReporter
import java.util.*


/**
* Created by crazy on 6/21/20 to long live and prosper !
*/

internal data class AppDeathInfo(
val description: String?,
val importance: String,
val reason: String,
val timestamp: String
)

private inline val Context.powerManager
get() = getSystemService(Context.POWER_SERVICE) as PowerManager?

private inline val Context.activityManager: ActivityManager
get() = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager

internal val Context.isSustainedPerformanceModeSupported
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
powerManager?.isSustainedPerformanceModeSupported.booleanAsYesOrNo()
} else {
notAvailableString
}

internal val Context.isInPowerSaveMode
get() = powerManager?.isPowerSaveMode.booleanAsYesOrNo()

internal val Context.isInInteractiveState
get() = powerManager?.isInteractive.booleanAsYesOrNo()

internal val Context.isIgnoringBatteryOptimization
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
powerManager?.isIgnoringBatteryOptimizations(packageName).booleanAsYesOrNo()
} else {
notAvailableString
}

private fun Boolean?.booleanAsYesOrNo() =
when (this) {
true -> "Yes"
false -> "No"
null -> notAvailableString
}


/**
* THERMAL_STATUS_NONE if device in not under thermal throttling. Value is
* THERMAL_STATUS_NONE, THERMAL_STATUS_LIGHT,
* THERMAL_STATUS_MODERATE, THERMAL_STATUS_SEVERE, THERMAL_STATUS_CRITICAL, THERMAL_STATUS_EMERGENCY, or THERMAL_STATUS_SHUTDOWN
*/
internal val Context.getThermalStatus: String
@RequiresApi(Build.VERSION_CODES.Q)
get() {
return when (powerManager?.currentThermalStatus) {
THERMAL_STATUS_NONE -> "STATUS_NONE"
THERMAL_STATUS_LIGHT -> "STATUS_LIGHT"
THERMAL_STATUS_MODERATE -> "STATUS_MODERATE"
THERMAL_STATUS_SEVERE -> "STATUS_SEVERE"
THERMAL_STATUS_CRITICAL -> "STATUS_CRITICAL"
THERMAL_STATUS_EMERGENCY -> "STATUS_EMERGENCY"
THERMAL_STATUS_SHUTDOWN -> "STATUS_SHUTDOWN"

else -> notAvailableString
}
}

/**
* Value is LOCATION_MODE_NO_CHANGE, LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF,
* LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF,
* LOCATION_MODE_FOREGROUND_ONLY, or LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF
*/
internal val Context.locationPowerSaveMode: String
get() {

return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
when (powerManager?.locationPowerSaveMode) {
LOCATION_MODE_NO_CHANGE -> "MODE_NO_CHANGE"
LOCATION_MODE_GPS_DISABLED_WHEN_SCREEN_OFF -> "MODE_GPS_DISABLED_WHEN_SCREEN_OFF"
LOCATION_MODE_ALL_DISABLED_WHEN_SCREEN_OFF -> "MODE_ALL_DISABLED_WHEN_SCREEN_OFF"
LOCATION_MODE_FOREGROUND_ONLY -> "MODE_FOREGROUND_ONLY"
LOCATION_MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF -> "MODE_THROTTLE_REQUESTS_WHEN_SCREEN_OFF"
else -> notAvailableString
}
} else {
notAvailableString
}
}

internal val Context.isDeviceIdle
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
powerManager?.isDeviceIdleMode.booleanAsYesOrNo()
} else {
notAvailableString
}


private fun buildExitReason(reason: Int) = when (reason) {
REASON_ANR -> "ANR"
REASON_CRASH -> "CRASH"
REASON_CRASH_NATIVE -> "CRASH_NATIVE"
REASON_DEPENDENCY_DIED -> "DEPENDENCY_DIED"
REASON_EXCESSIVE_RESOURCE_USAGE -> "EXCESSIVE_RESOURCE_USAGE"
REASON_EXIT_SELF -> "EXIT_SELF"
REASON_INITIALIZATION_FAILURE -> "INITIALIZATION_FAILURE"
REASON_LOW_MEMORY -> "LOW_MEMORY"
REASON_OTHER -> "OTHER"
REASON_PERMISSION_CHANGE -> "PERMISSION_CHANGE"
REASON_SIGNALED -> "SIGNALED"
REASON_USER_REQUESTED -> "USER_REQUESTED"
REASON_USER_STOPPED -> "USER_STOPPED"
android.app.ApplicationExitInfo.REASON_UNKNOWN -> "UNKNOWN"
else -> notAvailableString
}

internal fun Context.getExitReasons(pid: Int = 0, maxRes: Int = 1) =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
activityManager.getHistoricalProcessExitReasons(packageName, pid, maxRes).mapIndexed { index, it ->
"~~~~~~~~~~~ Exit reason #${index+1} ~~~~~~~~~~~\n" +
"\n" +
"Description: ${it.description}\n" +
"Importance: ${buildImportance(it.importance)}\n" +
"Importance: ${buildExitReason(it.reason)}\n" +
"Timestamp: ${CrashyReporter.dateFormat.format(Date(it.timestamp))}\n" +
"\n" +
"~~~~~~~~~~~ END of exit reason #${index+1} ~~~~~~~~~~~" +
"\n" +
"\n"
}
} else {
emptyList()
}

fun buildImportance(importance: Int): String {
return when(importance){
IMPORTANCE_FOREGROUND-> "FOREGROUND"
IMPORTANCE_FOREGROUND_SERVICE-> "FOREGROUND_SERVICE"
IMPORTANCE_TOP_SLEEPING-> "TOP_SLEEPING"
IMPORTANCE_VISIBLE-> "VISIBLE"
IMPORTANCE_PERCEPTIBLE-> "PERCEPTIBLE"
IMPORTANCE_CANT_SAVE_STATE-> "CANT_SAVE_STATE"
IMPORTANCE_SERVICE-> "SERVICE"
IMPORTANCE_CACHED-> "CACHED"
IMPORTANCE_GONE -> "GONE"
else-> notAvailableString
}
}

internal const val notAvailableString = "N/A"

internal fun <T> Collection<T>?.notAvailableIfNullNewLine(): String = if (this.isNullOrEmpty()) "N/A" else "\n${this}"
internal fun <T> Collection<T>?.notAvailableIfNull(): String = if (this.isNullOrEmpty()) "N/A" else "$this"
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import android.os.Build
import android.provider.Settings
import androidx.core.app.ActivityCompat
import com.crazylegend.crashyreporter.CrashyReporter
import com.crazylegend.crashyreporter.extensions.*
import com.crazylegend.crashyreporter.extensions.isIgnoringBatteryOptimization
import com.crazylegend.crashyreporter.extensions.isInInteractiveState
import com.crazylegend.crashyreporter.extensions.isInPowerSaveMode
import com.crazylegend.crashyreporter.extensions.isSustainedPerformanceModeSupported
import java.util.*


Expand All @@ -18,7 +23,7 @@ import java.util.*
*/
internal object DeviceUtils {

internal data class FingerprintPartition(val name: String, val fingerprint: String, val buildTimeMillis: Long)


fun getDeviceDetails(context: Context) =
"----------- Device info -----------\n" +
Expand All @@ -34,9 +39,9 @@ internal object DeviceUtils {
"Board: ${Build.BOARD}\n" +
"Bootloader: ${Build.BOOTLOADER}\n" +
"Brand: ${Build.BRAND}\n" +
"CPU_ABIS_32: ${Build.SUPPORTED_32_BIT_ABIS.map { it }}\n" +
"CPU_ABIS_64: ${Build.SUPPORTED_64_BIT_ABIS.map { it }}\n" +
"Supported ABIS: ${Build.SUPPORTED_ABIS.map { it }}\n" +
"CPU_ABIS_32: ${Build.SUPPORTED_32_BIT_ABIS.map { it }.notAvailableIfNull()}\n" +
"CPU_ABIS_64: ${Build.SUPPORTED_64_BIT_ABIS.map { it }.notAvailableIfNull()}\n" +
"Supported ABIS: ${Build.SUPPORTED_ABIS.map { it }.notAvailableIfNull()}\n" +
"Device: ${Build.DEVICE}\n" +
"Display: ${Build.DISPLAY}\n" +
"Fingerprint: ${Build.FINGERPRINT}\n" +
Expand All @@ -51,12 +56,21 @@ internal object DeviceUtils {
"Radio: ${getRadioVersion()}\n" +
"Tags: ${Build.TAGS}\n" +
"User: ${Build.USER}\n" +
"User IDs: ${getUserPlayIDs(context)}\n" +
"Build partition name system: ${Build.Partition.PARTITION_NAME_SYSTEM}\n" +
"User IDs: ${getUserPlayIDs(context).notAvailableIfNull()}\n" +
"Is sustained performance mode supported: ${context.isSustainedPerformanceModeSupported}\n" +
"Is in power save mode: ${context.isInPowerSaveMode}\n" +
"Is in interactive state: ${context.isInInteractiveState}\n" +
"Is ignoring battery optimizations: ${context.isIgnoringBatteryOptimization}\n" +
"Thermal status: ${context.getThermalStatus}\n" +
"Location power save mode: ${context.locationPowerSaveMode}\n" +
"Is device idle: ${context.isDeviceIdle}\n" +
"\n" +
"----------- END of Device info -----------" +
"\n" +
"\n"
"\n" +
"*********** Exit reasons ***********\n" +
"${context.getExitReasons(maxRes = 3).notAvailableIfNullNewLine().replace("[", "").replace("]", "").replace(",", "\n")}\n" +
"*********** END of exit reasons ***********"



Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package com.crazylegend.crashyreporter.utils
internal object ThreadUtil {

fun getThreadInfo(thread: Thread) =
"----------- Thread info -----------\n" +
"``````````` Thread info ```````````\n" +
"\n" +
"Name: ${thread.name}\n" +
"ID: ${thread.id}\n" +
Expand All @@ -17,7 +17,7 @@ internal object ThreadUtil {
"Thread group parent: ${thread.threadGroup?.parent?.name}\n" +
"Thread group active count: ${thread.threadGroup?.activeCount()}\n" +
"\n" +
"----------- END of thread info -----------\n"
"``````````` END of thread info ```````````\n"


fun buildStackTraceString(stackTrace: String) =
Expand Down
Binary file modified screens/screen_2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screens/screen_3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit bb13384

Please sign in to comment.