Fix TetherPreferenceController ANR

getAvailabilityStatus() is called in main thread, so we should avoid
time consuming works in it.

Fix: 377146536
Flag: EXEMPT bug fix
Test: manual - on Network & internet
Test: unit test
Change-Id: Ib5ee19744cf164f91aa90be982f5fc5eead5d4d3
This commit is contained in:
Chaohui Wang
2024-12-02 11:46:46 +08:00
parent a25c82a346
commit e731f7cce2
2 changed files with 63 additions and 12 deletions

View File

@@ -35,19 +35,35 @@ import com.android.settingslib.TetherUtil
import com.android.settingslib.Utils
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.conflate
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
class TetherPreferenceController(context: Context, key: String) :
BasePreferenceController(context, key) {
class TetherPreferenceController(
context: Context,
key: String,
private val tetheredRepository: TetheredRepository = TetheredRepository(context),
) : BasePreferenceController(context, key) {
private val tetheredRepository = TetheredRepository(context)
private val tetheringManager = mContext.getSystemService(TetheringManager::class.java)!!
private var preference: Preference? = null
override fun getAvailabilityStatus() =
if (TetherUtil.isTetherAvailable(mContext)) AVAILABLE else CONDITIONALLY_UNAVAILABLE
private val isTetherAvailableFlow =
flow { emit(TetherUtil.isTetherAvailable(mContext)) }
.distinctUntilChanged()
.conflate()
.flowOn(Dispatchers.Default)
/**
* Always returns available here to avoid ANR.
* - Actual UI visibility is handled in [onViewCreated].
* - Search visibility is handled in [updateNonIndexableKeys].
*/
override fun getAvailabilityStatus() = AVAILABLE
override fun displayPreference(screen: PreferenceScreen) {
super.displayPreference(screen)
@@ -55,6 +71,9 @@ class TetherPreferenceController(context: Context, key: String) :
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
isTetherAvailableFlow.collectLatestWithLifecycle(viewLifecycleOwner) {
preference?.isVisible = it
}
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
getTitleResId()?.let { preference?.setTitle(it) }
@@ -84,6 +103,12 @@ class TetherPreferenceController(context: Context, key: String) :
}
}
override fun updateNonIndexableKeys(keys: MutableList<String>) {
if (!TetherUtil.isTetherAvailable(mContext)) {
keys += preferenceKey
}
}
companion object {
@JvmStatic
fun isTetherConfigDisallowed(context: Context?): Boolean =