Adding way to enable leak canary at runtime

This commit is contained in:
Maxime NATUREL 2022-08-08 17:52:58 +02:00
parent 31a350eea7
commit 36c69a46fd
8 changed files with 103 additions and 2 deletions

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.leakcanary
import leakcanary.LeakCanary
import javax.inject.Inject
class LeakCanaryProxy @Inject constructor() {
fun enable(enable: Boolean) {
LeakCanary.config = LeakCanary.config.copy(dumpHeap = enable)
}
}

View File

@ -61,6 +61,8 @@ import im.vector.app.features.settings.VectorLocale
import im.vector.app.features.settings.VectorPreferences import im.vector.app.features.settings.VectorPreferences
import im.vector.app.features.themes.ThemeUtils import im.vector.app.features.themes.ThemeUtils
import im.vector.app.features.version.VersionProvider import im.vector.app.features.version.VersionProvider
import im.vector.app.leakcanary.LeakCanaryProxy
import im.vector.app.push.fcm.FcmHelper
import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler import org.jitsi.meet.sdk.log.JitsiMeetDefaultLogHandler
import org.matrix.android.sdk.api.Matrix import org.matrix.android.sdk.api.Matrix
import org.matrix.android.sdk.api.auth.AuthenticationService import org.matrix.android.sdk.api.auth.AuthenticationService
@ -102,6 +104,7 @@ class VectorApplication :
@Inject lateinit var matrix: Matrix @Inject lateinit var matrix: Matrix
@Inject lateinit var fcmHelper: FcmHelper @Inject lateinit var fcmHelper: FcmHelper
@Inject lateinit var buildMeta: BuildMeta @Inject lateinit var buildMeta: BuildMeta
@Inject lateinit var leakCanaryProxy: LeakCanaryProxy
// font thread handler // font thread handler
private var fontThreadHandler: Handler? = null private var fontThreadHandler: Handler? = null
@ -196,6 +199,8 @@ class VectorApplication :
// Initialize Mapbox before inflating mapViews // Initialize Mapbox before inflating mapViews
Mapbox.getInstance(this) Mapbox.getInstance(this)
initMemoryLeakAnalysis()
} }
private fun enableStrictModeIfNeeded() { private fun enableStrictModeIfNeeded() {
@ -251,4 +256,8 @@ class VectorApplication :
handlerThread.start() handlerThread.start()
return Handler(handlerThread.looper) return Handler(handlerThread.looper)
} }
private fun initMemoryLeakAnalysis() {
leakCanaryProxy.enable(vectorPreferences.isMemoryLeakAnalysisEnabled())
}
} }

View File

@ -150,6 +150,7 @@ import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRul
import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment import im.vector.app.features.roomprofile.uploads.RoomUploadsFragment
import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment import im.vector.app.features.roomprofile.uploads.files.RoomUploadsFilesFragment
import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment import im.vector.app.features.roomprofile.uploads.media.RoomUploadsMediaFragment
import im.vector.app.features.settings.VectorSettingsAdvancedSettingsFragment
import im.vector.app.features.settings.VectorSettingsGeneralFragment import im.vector.app.features.settings.VectorSettingsGeneralFragment
import im.vector.app.features.settings.VectorSettingsHelpAboutFragment import im.vector.app.features.settings.VectorSettingsHelpAboutFragment
import im.vector.app.features.settings.VectorSettingsLabsFragment import im.vector.app.features.settings.VectorSettingsLabsFragment
@ -624,6 +625,11 @@ interface FragmentModule {
@FragmentKey(VectorSettingsSecurityPrivacyFragment::class) @FragmentKey(VectorSettingsSecurityPrivacyFragment::class)
fun bindVectorSettingsSecurityPrivacyFragment(fragment: VectorSettingsSecurityPrivacyFragment): Fragment fun bindVectorSettingsSecurityPrivacyFragment(fragment: VectorSettingsSecurityPrivacyFragment): Fragment
@Binds
@IntoMap
@FragmentKey(VectorSettingsAdvancedSettingsFragment::class)
fun bindVectorSettingsAdvancedSettingsFragment(fragment: VectorSettingsAdvancedSettingsFragment): Fragment
@Binds @Binds
@IntoMap @IntoMap
@FragmentKey(VectorSettingsHelpAboutFragment::class) @FragmentKey(VectorSettingsHelpAboutFragment::class)

View File

@ -168,6 +168,7 @@ class VectorPreferences @Inject constructor(
private const val SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY = "SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY" private const val SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY = "SETTINGS_LABS_ENABLE_SWIPE_TO_REPLY"
private const val SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY = "SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY" private const val SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY = "SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY"
private const val SETTINGS_DEVELOPER_MODE_SHOW_INFO_ON_SCREEN_KEY = "SETTINGS_DEVELOPER_MODE_SHOW_INFO_ON_SCREEN_KEY" private const val SETTINGS_DEVELOPER_MODE_SHOW_INFO_ON_SCREEN_KEY = "SETTINGS_DEVELOPER_MODE_SHOW_INFO_ON_SCREEN_KEY"
const val SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY = "SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY"
const val SETTINGS_LABS_MSC3061_SHARE_KEYS_HISTORY = "SETTINGS_LABS_MSC3061_SHARE_KEYS_HISTORY" const val SETTINGS_LABS_MSC3061_SHARE_KEYS_HISTORY = "SETTINGS_LABS_MSC3061_SHARE_KEYS_HISTORY"
@ -268,6 +269,7 @@ class VectorPreferences @Inject constructor(
SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY, SETTINGS_LABS_SHOW_HIDDEN_EVENTS_PREFERENCE_KEY,
SETTINGS_LABS_ALLOW_EXTENDED_LOGS, SETTINGS_LABS_ALLOW_EXTENDED_LOGS,
SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY,
SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY,
SETTINGS_USE_RAGE_SHAKE_KEY, SETTINGS_USE_RAGE_SHAKE_KEY,
SETTINGS_SECURITY_USE_FLAG_SECURE, SETTINGS_SECURITY_USE_FLAG_SECURE,
@ -368,6 +370,10 @@ class VectorPreferences @Inject constructor(
return buildMeta.isDebug || (developerMode() && defaultPrefs.getBoolean(SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, false)) return buildMeta.isDebug || (developerMode() && defaultPrefs.getBoolean(SETTINGS_DEVELOPER_MODE_FAIL_FAST_PREFERENCE_KEY, false))
} }
fun isMemoryLeakAnalysisEnabled(): Boolean {
return buildMeta.isDebug && developerMode() && defaultPrefs.getBoolean(SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY, false)
}
fun didAskUserToEnableSessionPush(): Boolean { fun didAskUserToEnableSessionPush(): Boolean {
return defaultPrefs.getBoolean(DID_ASK_TO_ENABLE_SESSION_PUSH, false) return defaultPrefs.getBoolean(DID_ASK_TO_ENABLE_SESSION_PUSH, false)
} }

View File

@ -19,14 +19,19 @@ package im.vector.app.features.settings
import android.os.Bundle import android.os.Bundle
import androidx.preference.Preference import androidx.preference.Preference
import androidx.preference.SeekBarPreference import androidx.preference.SeekBarPreference
import im.vector.app.BuildConfig
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.preference.VectorPreferenceCategory import im.vector.app.core.preference.VectorPreferenceCategory
import im.vector.app.core.preference.VectorSwitchPreference import im.vector.app.core.preference.VectorSwitchPreference
import im.vector.app.features.analytics.plan.MobileScreen import im.vector.app.features.analytics.plan.MobileScreen
import im.vector.app.features.rageshake.RageShake import im.vector.app.features.rageshake.RageShake
import im.vector.app.leakcanary.LeakCanaryProxy
import javax.inject.Inject
class VectorSettingsAdvancedSettingsFragment : VectorSettingsBaseFragment() { class VectorSettingsAdvancedSettingsFragment @Inject constructor(
private val leakCanaryProxy: LeakCanaryProxy,
) : VectorSettingsBaseFragment() {
override var titleRes = R.string.settings_advanced_settings override var titleRes = R.string.settings_advanced_settings
override val preferenceXmlRes = R.xml.vector_settings_advanced_settings override val preferenceXmlRes = R.xml.vector_settings_advanced_settings
@ -82,5 +87,17 @@ class VectorSettingsAdvancedSettingsFragment : VectorSettingsBaseFragment() {
} else { } else {
findPreference<VectorPreferenceCategory>("SETTINGS_RAGE_SHAKE_CATEGORY_KEY")!!.isVisible = false findPreference<VectorPreferenceCategory>("SETTINGS_RAGE_SHAKE_CATEGORY_KEY")!!.isVisible = false
} }
bindMemoryLeakSetting()
}
private fun bindMemoryLeakSetting() {
findPreference<VectorSwitchPreference>(VectorPreferences.SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY)?.let { pref ->
pref.isVisible = BuildConfig.DEBUG
pref.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { _, newValue ->
leakCanaryProxy.enable(newValue as? Boolean ?: false)
true
}
}
} }
} }

View File

@ -2185,6 +2185,9 @@
<!-- Note to translators: the translation MUST contain the string "${app_name}", which will be replaced by the application name --> <!-- Note to translators: the translation MUST contain the string "${app_name}", which will be replaced by the application name -->
<string name="settings_developer_mode_fail_fast_summary">${app_name} may crash more often when an unexpected error occurs</string> <string name="settings_developer_mode_fail_fast_summary">${app_name} may crash more often when an unexpected error occurs</string>
<string name="settings_enable_memory_leak_analysis_title">Enable memory leak analysis</string>
<string name="settings_enable_memory_leak_analysis_summary">App performances may be impacted when enabled.</string>
<string name="settings_developer_mode_show_info_on_screen_title">Show debug info on screen</string> <string name="settings_developer_mode_show_info_on_screen_title">Show debug info on screen</string>
<string name="settings_developer_mode_show_info_on_screen_summary">Show some useful info to help debugging the application</string> <string name="settings_developer_mode_show_info_on_screen_summary">Show some useful info to help debugging the application</string>

View File

@ -44,6 +44,13 @@
android:summary="@string/settings_developer_mode_fail_fast_summary" android:summary="@string/settings_developer_mode_fail_fast_summary"
android:title="@string/settings_developer_mode_fail_fast_title" /> android:title="@string/settings_developer_mode_fail_fast_title" />
<im.vector.app.core.preference.VectorSwitchPreference
android:defaultValue="false"
android:dependency="SETTINGS_DEVELOPER_MODE_PREFERENCE_KEY"
android:key="SETTINGS_ENABLE_MEMORY_LEAK_ANALYSIS_KEY"
android:summary="@string/settings_enable_memory_leak_analysis_summary"
android:title="@string/settings_enable_memory_leak_analysis_title" />
</im.vector.app.core.preference.VectorPreferenceCategory> </im.vector.app.core.preference.VectorPreferenceCategory>
<im.vector.app.core.preference.VectorPreferenceCategory <im.vector.app.core.preference.VectorPreferenceCategory
@ -95,4 +102,4 @@
</im.vector.app.core.preference.VectorPreferenceCategory> </im.vector.app.core.preference.VectorPreferenceCategory>
</androidx.preference.PreferenceScreen> </androidx.preference.PreferenceScreen>

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2022 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.leakcanary
import javax.inject.Inject
/**
* No op version.
*/
@Suppress("UNUSED_PARAMETER")
class LeakCanaryProxy @Inject constructor() {
fun enable(enable: Boolean) {}
}