Skip to content

Commit

Permalink
fix(lowMemory): align the app.lowMemory field for JVM and NDK
Browse files Browse the repository at this point in the history
  • Loading branch information
lemnik committed Aug 13, 2021
1 parent 9da9c4d commit 6184f98
Show file tree
Hide file tree
Showing 10 changed files with 107 additions and 35 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Changelog

## TBD

* The `app.lowMemory` value always report the most recent `onTrimMemory`/`onLowMemory` status
[#1342](https://github.com/bugsnag/bugsnag-android/pull/1342)

## 5.11.0 (2021-08-05)

### Enhancements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ class AppDataCollectorTest {
client.immutableConfig,
client.sessionTracker,
am,
client.launchCrashTracker,
NoopLogger
client.launchCrashTracker
)
val app = collector.getAppDataMetadata()
assertNull(app["backgroundWorkRestricted"])
Expand All @@ -67,8 +66,7 @@ class AppDataCollectorTest {
client.immutableConfig,
client.sessionTracker,
am,
client.launchCrashTracker,
NoopLogger
client.launchCrashTracker
)
client.context = "Some Custom Context"
client.sessionTracker.updateForegroundTracker("MyActivity", true, 0L)
Expand All @@ -90,8 +88,7 @@ class AppDataCollectorTest {
client.immutableConfig,
client.sessionTracker,
am,
client.launchCrashTracker,
NoopLogger
client.launchCrashTracker
)
val app = collector.getAppDataMetadata()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,13 @@ internal class AppDataCollector(
private val config: ImmutableConfig,
private val sessionTracker: SessionTracker,
private val activityManager: ActivityManager?,
private val launchCrashTracker: LaunchCrashTracker,
private val logger: Logger
private val launchCrashTracker: LaunchCrashTracker
) {
/**
* Is the app considered to be an a low-memory state as defined by
* [android.content.ComponentCallbacks]
*/
var isLowMemory: Boolean = false
var codeBundleId: String? = null

private val packageName: String = appContext.packageName
Expand Down Expand Up @@ -52,7 +56,7 @@ internal class AppDataCollector(
map["name"] = appName
map["activeScreen"] = sessionTracker.contextActivity
map["memoryUsage"] = getMemoryUsage()
map["lowMemory"] = isLowMemory()
map["lowMemory"] = isLowMemory

bgWorkRestricted?.let {
map["backgroundWorkRestricted"] = bgWorkRestricted
Expand Down Expand Up @@ -86,22 +90,6 @@ internal class AppDataCollector(
}
}

/**
* Check if the device is currently running low on memory.
*/
private fun isLowMemory(): Boolean? {
try {
if (activityManager != null) {
val memInfo = ActivityManager.MemoryInfo()
activityManager.getMemoryInfo(memInfo)
return memInfo.lowMemory
}
} catch (exception: Exception) {
logger.w("Could not check lowMemory status")
}
return null
}

fun setBinaryArch(binaryArch: String) {
this.binaryArch = binaryArch
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ public Unit invoke(String oldOrientation, String newOrientation) {
}, new Function1<Boolean, Unit>() {
@Override
public Unit invoke(Boolean isLowMemory) {
appDataCollector.setLowMemory(isLowMemory == Boolean.TRUE);
clientObservable.postMemoryTrimEvent(isLowMemory);
return null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.bugsnag.android

import android.content.ComponentCallbacks
import android.content.ComponentCallbacks2
import android.content.res.Configuration

internal class ClientComponentCallbacks(
private val deviceDataCollector: DeviceDataCollector,
private val cb: (oldOrientation: String?, newOrientation: String?) -> Unit,
val callback: (Boolean) -> Unit
) : ComponentCallbacks {
) : ComponentCallbacks2 {

override fun onConfigurationChanged(newConfig: Configuration) {
val oldOrientation = deviceDataCollector.getOrientationAsString()
Expand All @@ -18,6 +18,14 @@ internal class ClientComponentCallbacks(
}
}

override fun onTrimMemory(level: Int) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_COMPLETE) {
callback(true)
} else {
callback(false)
}
}

override fun onLowMemory() {
callback(true)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,7 @@ internal class DataCollectionModule(
cfg,
trackerModule.sessionTracker,
systemServiceModule.activityManager,
trackerModule.launchCrashTracker,
logger
trackerModule.launchCrashTracker
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,7 @@ class AppDataCollectorForegroundTest {
BugsnagTestUtils.generateImmutableConfig(),
sessionTracker,
null,
launchCrashTracker,
NoopLogger
launchCrashTracker
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ internal class AppDataCollectorSerializationTest {
convert(config),
sessionTracker,
am,
launchCrashTracker,
NoopLogger
launchCrashTracker
)
appData.codeBundleId = "foo-99"
appData.setBinaryArch("x86")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ internal class AppMetadataSerializationTest {
convertToImmutableConfig(config, null, null, ApplicationInfo()),
sessionTracker,
am,
launchCrashTracker,
NoopLogger
launchCrashTracker
)
appData.codeBundleId = "foo-99"
appData.setBinaryArch("x86")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package com.bugsnag.android

import android.content.ComponentCallbacks2
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mock
import org.mockito.junit.MockitoJUnitRunner

@RunWith(MockitoJUnitRunner::class)
class ClientComponentCallbacksMemoryCallbackTest {

@Mock
internal lateinit var deviceDataCollector: DeviceDataCollector
private lateinit var clientComponentCallbacks: ClientComponentCallbacks

private var isLowMemory: Boolean? = null

@Before
fun setUp() {
clientComponentCallbacks = ClientComponentCallbacks(
deviceDataCollector,
{ _: String?, _: String? -> },
this::isLowMemory::set
)
isLowMemory = null
}

@Test
fun testLegacyLowMemory() {
clientComponentCallbacks.onLowMemory()
assertEquals(true, isLowMemory)
}

@Test
fun trimMemoryRunningModerate() {
clientComponentCallbacks.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE)
assertEquals(false, isLowMemory)
}

@Test
fun trimMemoryRunningLow() {
clientComponentCallbacks.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW)
assertEquals(false, isLowMemory)
}

@Test
fun trimMemoryRunningCritical() {
clientComponentCallbacks.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL)
assertEquals(false, isLowMemory)
}

@Test
fun trimMemoryUiHidden() {
clientComponentCallbacks.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN)
assertEquals(false, isLowMemory)
}

@Test
fun trimMemoryBackground() {
clientComponentCallbacks.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_BACKGROUND)
assertEquals(false, isLowMemory)
}

@Test
fun trimMemoryModerate() {
clientComponentCallbacks.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_MODERATE)
assertEquals(false, isLowMemory)
}

@Test
fun trimMemoryComplete() {
clientComponentCallbacks.onTrimMemory(ComponentCallbacks2.TRIM_MEMORY_COMPLETE)
assertEquals(true, isLowMemory)
}
}

0 comments on commit 6184f98

Please sign in to comment.