Fix ANR-like bug when resuming MainActivity.

This commit is contained in:
Cody Henthorne 2023-08-17 15:02:16 -04:00 committed by GitHub
parent 74d5faf3fa
commit 39c1c1e371
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 101 additions and 17 deletions

View file

@ -1,10 +1,10 @@
package org.thoughtcrime.securesms;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.view.View;
import android.view.ViewTreeObserver;
@ -16,6 +16,7 @@ import androidx.lifecycle.ViewModelProvider;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.signal.core.util.concurrent.LifecycleDisposable;
import org.thoughtcrime.securesms.components.DebugLogsPromptDialogFragment;
import org.thoughtcrime.securesms.components.PromptBatterySaverDialogFragment;
import org.thoughtcrime.securesms.components.voice.VoiceNoteMediaController;
@ -24,8 +25,7 @@ import org.thoughtcrime.securesms.conversationlist.RelinkDevicesReminderBottomSh
import org.thoughtcrime.securesms.devicetransfer.olddevice.OldDeviceExitActivity;
import org.thoughtcrime.securesms.keyvalue.SignalStore;
import org.thoughtcrime.securesms.net.DeviceTransferBlockingInterceptor;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics;
import org.thoughtcrime.securesms.notifications.SlowNotificationsViewModel;
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabRepository;
import org.thoughtcrime.securesms.stories.tabs.ConversationListTabsViewModel;
import org.thoughtcrime.securesms.util.AppStartup;
@ -33,7 +33,6 @@ import org.thoughtcrime.securesms.util.CachedInflater;
import org.thoughtcrime.securesms.util.CommunicationActions;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.PowerManagerCompat;
import org.thoughtcrime.securesms.util.SplashScreenUtil;
import org.thoughtcrime.securesms.util.WindowUtil;
@ -46,6 +45,9 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
private VoiceNoteMediaController mediaController;
private ConversationListTabsViewModel conversationListTabsViewModel;
private SlowNotificationsViewModel slowNotificationsViewModel;
private final LifecycleDisposable lifecycleDisposable = new LifecycleDisposable();
private boolean onFirstRender = false;
@ -80,6 +82,7 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
}
});
lifecycleDisposable.bindTo(this);
mediaController = new VoiceNoteMediaController(this, true);
@ -95,6 +98,28 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
conversationListTabsViewModel = new ViewModelProvider(this, factory).get(ConversationListTabsViewModel.class);
updateTabVisibility();
slowNotificationsViewModel = new ViewModelProvider(this).get(SlowNotificationsViewModel.class);
lifecycleDisposable.add(
slowNotificationsViewModel
.getSlowNotificationState()
.subscribe(this::presentSlowNotificationState)
);
}
@SuppressLint("NewApi")
private void presentSlowNotificationState(SlowNotificationsViewModel.State slowNotificationState) {
switch (slowNotificationState) {
case NONE:
break;
case PROMPT_BATTERY_SAVER_DIALOG:
PromptBatterySaverDialogFragment.show(getSupportFragmentManager());
break;
case PROMPT_DEBUGLOGS:
DebugLogsPromptDialogFragment.show(this, getSupportFragmentManager());
break;
}
}
@Override
@ -143,15 +168,7 @@ public class MainActivity extends PassphraseRequiredActivity implements VoiceNot
updateTabVisibility();
if (SlowNotificationHeuristics.isHavingDelayedNotifications()) {
if (SlowNotificationHeuristics.isPotentiallyCausedByBatteryOptimizations() && Build.VERSION.SDK_INT >= 23) {
if (SlowNotificationHeuristics.shouldPromptBatterySaver()) {
PromptBatterySaverDialogFragment.show(this, getSupportFragmentManager());
}
} else if (SlowNotificationHeuristics.shouldPromptUserForLogs()) {
DebugLogsPromptDialogFragment.show(this, getSupportFragmentManager());
}
}
slowNotificationsViewModel.checkSlowNotificationHeuristics();
}
@Override

View file

@ -5,7 +5,6 @@
package org.thoughtcrime.securesms.components
import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@ -27,7 +26,7 @@ class PromptBatterySaverDialogFragment : FixedRoundedCornerBottomSheetDialogFrag
companion object {
@JvmStatic
fun show(context: Context, fragmentManager: FragmentManager) {
fun show(fragmentManager: FragmentManager) {
if (fragmentManager.findFragmentByTag(BottomSheetUtil.STANDARD_BOTTOM_SHEET_FRAGMENT_TAG) == null) {
PromptBatterySaverDialogFragment().apply {
arguments = bundleOf()

View file

@ -190,7 +190,7 @@ class NotificationsSettingsFragment : DSLSettingsFragment(R.string.preferences__
title = DSLSettingsText.from(R.string.preferences_notifications__troubleshoot),
isEnabled = true,
onClick = {
PromptBatterySaverDialogFragment.show(requireContext(), childFragmentManager)
PromptBatterySaverDialogFragment.show(childFragmentManager)
}
)
}

View file

@ -0,0 +1,68 @@
/*
* Copyright 2023 Signal Messenger, LLC
* SPDX-License-Identifier: AGPL-3.0-only
*/
package org.thoughtcrime.securesms.notifications
import android.os.Build
import androidx.lifecycle.ViewModel
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Observable
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.schedulers.Schedulers
import io.reactivex.rxjava3.subjects.BehaviorSubject
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics.isHavingDelayedNotifications
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics.isPotentiallyCausedByBatteryOptimizations
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics.shouldPromptBatterySaver
import org.thoughtcrime.securesms.notifications.SlowNotificationHeuristics.shouldPromptUserForLogs
import java.util.concurrent.TimeUnit
/**
* View model for checking for slow notifications and if we should prompt the user with help or for information.
*/
class SlowNotificationsViewModel : ViewModel() {
private val checkSubject = BehaviorSubject.create<Unit>()
val slowNotificationState: Observable<State>
init {
slowNotificationState = checkSubject
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.throttleFirst(1, TimeUnit.MINUTES)
.switchMapSingle {
checkHeuristics()
}
.distinctUntilChanged()
.observeOn(AndroidSchedulers.mainThread())
}
fun checkSlowNotificationHeuristics() {
checkSubject.onNext(Unit)
}
private fun checkHeuristics(): Single<State> {
return Single.fromCallable {
var state = State.NONE
if (isHavingDelayedNotifications()) {
if (isPotentiallyCausedByBatteryOptimizations() && Build.VERSION.SDK_INT >= 23) {
if (shouldPromptBatterySaver()) {
state = State.PROMPT_BATTERY_SAVER_DIALOG
}
} else if (shouldPromptUserForLogs()) {
state = State.PROMPT_DEBUGLOGS
}
}
return@fromCallable state
}.subscribeOn(Schedulers.io())
}
enum class State {
NONE,
PROMPT_BATTERY_SAVER_DIALOG,
PROMPT_DEBUGLOGS
}
}

View file

@ -1,4 +1,4 @@
org.gradle.jvmargs=-Xmx4g -Xms256m -XX:MaxMetaspaceSize=1g
org.gradle.jvmargs=-Xmx6g -Xms256m -XX:MaxMetaspaceSize=1g
android.useAndroidX=true
android.enableJetifier=true
kapt.incremental.apt=false