mirror of
https://gitlab.linphone.org/BC/public/linphone-android.git
synced 2026-01-17 11:28:06 +00:00
Added onTrimMemory callback + trying to properly shut down Core when latest activity is being destroyed
This commit is contained in:
parent
897312831e
commit
780c2f55dc
4 changed files with 89 additions and 16 deletions
|
|
@ -21,6 +21,7 @@ package org.linphone
|
|||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.Application
|
||||
import android.content.ComponentCallbacks2
|
||||
import androidx.annotation.MainThread
|
||||
import coil.ImageLoader
|
||||
import coil.ImageLoaderFactory
|
||||
|
|
@ -28,6 +29,7 @@ import coil.decode.ImageDecoderDecoder
|
|||
import coil.decode.SvgDecoder
|
||||
import coil.decode.VideoFrameDecoder
|
||||
import coil.disk.DiskCache
|
||||
import coil.imageLoader
|
||||
import coil.memory.MemoryCache
|
||||
import coil.request.CachePolicy
|
||||
import com.google.android.material.color.DynamicColors
|
||||
|
|
@ -41,6 +43,8 @@ import org.linphone.core.tools.Log
|
|||
@MainThread
|
||||
class LinphoneApplication : Application(), ImageLoaderFactory {
|
||||
companion object {
|
||||
private const val TAG = "[Linphone Application]"
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
lateinit var corePreferences: CorePreferences
|
||||
|
||||
|
|
@ -70,7 +74,7 @@ class LinphoneApplication : Application(), ImageLoaderFactory {
|
|||
Factory.instance().loggingService.setLogLevel(LogLevel.Message)
|
||||
Factory.instance().enableLogcatLogs(corePreferences.printLogsInLogcat)
|
||||
|
||||
Log.i("[Linphone Application] Report Core preferences initialized")
|
||||
Log.i("$TAG Report Core preferences initialized")
|
||||
|
||||
coreContext = CoreContext(context)
|
||||
coreContext.start()
|
||||
|
|
@ -78,6 +82,26 @@ class LinphoneApplication : Application(), ImageLoaderFactory {
|
|||
DynamicColors.applyToActivitiesIfAvailable(this)
|
||||
}
|
||||
|
||||
override fun onLowMemory() {
|
||||
super.onLowMemory()
|
||||
Log.w("$TAG onLowMemory !")
|
||||
}
|
||||
|
||||
override fun onTrimMemory(level: Int) {
|
||||
Log.w("$TAG onTrimMemory called with level [${trimLevelToString(level)}]($level) !")
|
||||
when (level) {
|
||||
ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW,
|
||||
ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL,
|
||||
ComponentCallbacks2.TRIM_MEMORY_MODERATE,
|
||||
ComponentCallbacks2.TRIM_MEMORY_COMPLETE -> {
|
||||
Log.i("$TAG Memory trim required, clearing imageLoader memory cache")
|
||||
imageLoader.memoryCache?.clear()
|
||||
}
|
||||
else -> {}
|
||||
}
|
||||
super.onTrimMemory(level)
|
||||
}
|
||||
|
||||
override fun newImageLoader(): ImageLoader {
|
||||
return ImageLoader.Builder(this)
|
||||
.crossfade(false)
|
||||
|
|
@ -102,4 +126,17 @@ class LinphoneApplication : Application(), ImageLoaderFactory {
|
|||
.memoryCachePolicy(CachePolicy.ENABLED)
|
||||
.build()
|
||||
}
|
||||
|
||||
private fun trimLevelToString(level: Int): String {
|
||||
return when (level) {
|
||||
ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN -> "Hidden UI"
|
||||
ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE -> "Moderate (Running)"
|
||||
ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW -> "Low"
|
||||
ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL -> "Critical"
|
||||
ComponentCallbacks2.TRIM_MEMORY_BACKGROUND -> "Background"
|
||||
ComponentCallbacks2.TRIM_MEMORY_MODERATE -> "Moderate"
|
||||
ComponentCallbacks2.TRIM_MEMORY_COMPLETE -> "Complete"
|
||||
else -> level.toString()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -262,27 +262,34 @@ class CoreContext @UiThread constructor(val context: Context) : HandlerThread("C
|
|||
Log.i("$TAG Report Core created and started")
|
||||
}
|
||||
|
||||
@Deprecated("Deprecated in Java")
|
||||
@WorkerThread
|
||||
override fun destroy() {
|
||||
Log.i("$TAG Stopping Core")
|
||||
private fun destroyCore() {
|
||||
if (!::core.isInitialized) {
|
||||
return
|
||||
}
|
||||
|
||||
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
|
||||
|
||||
core.stop()
|
||||
|
||||
contactsManager.onCoreStopped(core)
|
||||
telecomManager.onCoreStopped(core)
|
||||
notificationsManager.onCoreStopped(core)
|
||||
val state = core.globalState
|
||||
if (state != GlobalState.On) {
|
||||
Log.w("$TAG Core is in state [$state], do not continue destroy process")
|
||||
return
|
||||
}
|
||||
Log.w("$TAG Stopping Core and destroying context related objects")
|
||||
|
||||
postOnMainThread {
|
||||
(context as Application).unregisterActivityLifecycleCallbacks(activityMonitor)
|
||||
}
|
||||
|
||||
Log.i("$TAG Core has been stopped, app can gracefully quit")
|
||||
Factory.instance().loggingService.removeListener(loggingServiceListener)
|
||||
quitSafely()
|
||||
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
||||
audioManager.unregisterAudioDeviceCallback(audioDeviceCallback)
|
||||
|
||||
core.stopAsync()
|
||||
|
||||
contactsManager.onCoreStopped(core)
|
||||
telecomManager.onCoreStopped(core)
|
||||
notificationsManager.onCoreStopped(core)
|
||||
|
||||
// It's very unlikely the process will survive until the Core reaches GlobalStateOff sadly
|
||||
Log.w("$TAG Core is shutting down but probably won't reach Off state")
|
||||
}
|
||||
|
||||
@AnyThread
|
||||
|
|
@ -334,6 +341,14 @@ class CoreContext @UiThread constructor(val context: Context) : HandlerThread("C
|
|||
}
|
||||
}
|
||||
|
||||
@UiThread
|
||||
fun onAppDestroyed() {
|
||||
postOnCoreThread {
|
||||
Log.w("$TAG App has been destroyed, stopping Core")
|
||||
destroyCore()
|
||||
}
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
fun isAddressMyself(address: Address): Boolean {
|
||||
val found = core.accountList.find {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@ class CoreForegroundService : CoreService() {
|
|||
|
||||
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
|
||||
Log.i("$TAG onStartCommand")
|
||||
|
||||
coreContext.notificationsManager.onServiceStarted(this)
|
||||
|
||||
return super.onStartCommand(intent, flags, startId)
|
||||
|
|
|
|||
|
|
@ -24,10 +24,15 @@ import android.app.Application.ActivityLifecycleCallbacks
|
|||
import android.os.Bundle
|
||||
import androidx.annotation.UiThread
|
||||
import org.linphone.LinphoneApplication.Companion.coreContext
|
||||
import org.linphone.core.tools.Log
|
||||
import org.linphone.core.tools.service.AndroidDispatcher
|
||||
|
||||
@UiThread
|
||||
class ActivityMonitor : ActivityLifecycleCallbacks {
|
||||
companion object {
|
||||
private const val TAG = "[Activity Monitor]"
|
||||
}
|
||||
|
||||
private val activities = ArrayList<Activity>()
|
||||
private var mActive = false
|
||||
private var mRunningActivities = 0
|
||||
|
|
@ -35,14 +40,17 @@ class ActivityMonitor : ActivityLifecycleCallbacks {
|
|||
|
||||
@Synchronized
|
||||
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
||||
Log.d("$TAG onActivityCreated [$activity]")
|
||||
if (!activities.contains(activity)) activities.add(activity)
|
||||
}
|
||||
|
||||
override fun onActivityStarted(activity: Activity) {
|
||||
Log.d("$TAG onActivityStarted [$activity]")
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onActivityResumed(activity: Activity) {
|
||||
Log.d("$TAG onActivityResumed [$activity]")
|
||||
if (!activities.contains(activity)) {
|
||||
activities.add(activity)
|
||||
}
|
||||
|
|
@ -52,6 +60,7 @@ class ActivityMonitor : ActivityLifecycleCallbacks {
|
|||
|
||||
@Synchronized
|
||||
override fun onActivityPaused(activity: Activity) {
|
||||
Log.d("$TAG onActivityPaused [$activity]")
|
||||
if (!activities.contains(activity)) {
|
||||
activities.add(activity)
|
||||
} else {
|
||||
|
|
@ -61,11 +70,17 @@ class ActivityMonitor : ActivityLifecycleCallbacks {
|
|||
}
|
||||
|
||||
override fun onActivityStopped(activity: Activity) {
|
||||
Log.d("$TAG onActivityStopped [$activity]")
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun onActivityDestroyed(activity: Activity) {
|
||||
Log.d("$TAG onActivityDestroyed [$activity]")
|
||||
activities.remove(activity)
|
||||
|
||||
if (activities.isEmpty()) {
|
||||
onAppDestroyed()
|
||||
}
|
||||
}
|
||||
|
||||
private fun startInactivityChecker() {
|
||||
|
|
@ -91,11 +106,18 @@ class ActivityMonitor : ActivityLifecycleCallbacks {
|
|||
}
|
||||
}
|
||||
|
||||
private fun onAppDestroyed() {
|
||||
Log.w("$TAG onAppDestroyed()")
|
||||
coreContext.onAppDestroyed()
|
||||
}
|
||||
|
||||
private fun onBackgroundMode() {
|
||||
Log.i("$TAG onBackgroundMode()")
|
||||
coreContext.onBackground()
|
||||
}
|
||||
|
||||
private fun onForegroundMode() {
|
||||
Log.i("$TAG onForegroundMode()")
|
||||
coreContext.onForeground()
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue