From 6db59cb896984b6e7fe611733b15c9b8cc9927f6 Mon Sep 17 00:00:00 2001 From: Cody Henthorne Date: Tue, 18 Jul 2023 10:19:17 -0400 Subject: [PATCH] Prevent menu creation slowing data load performance in CFv2. --- .../benchmark/BenchmarkSetupActivity.kt | 9 ------ .../org/signal/benchmark/setup/TestUsers.kt | 19 ++++++++++-- .../conversation/ConversationFragment.java | 1 - .../conversation/ConversationOptionsMenu.kt | 30 ++++++++++++++++++- .../ConversationParentFragment.java | 8 ++++- .../conversation/v2/ConversationFragment.kt | 6 +++- .../res/menu/conversation_first_render.xml | 20 +++++++++++++ .../benchmark/StartupBenchmarks.kt | 5 ---- 8 files changed, 78 insertions(+), 20 deletions(-) create mode 100644 app/src/main/res/menu/conversation_first_render.xml diff --git a/app/src/benchmark/java/org/signal/benchmark/BenchmarkSetupActivity.kt b/app/src/benchmark/java/org/signal/benchmark/BenchmarkSetupActivity.kt index aeb5cb98de..78e8f66e2b 100644 --- a/app/src/benchmark/java/org/signal/benchmark/BenchmarkSetupActivity.kt +++ b/app/src/benchmark/java/org/signal/benchmark/BenchmarkSetupActivity.kt @@ -6,8 +6,6 @@ import org.signal.benchmark.setup.TestMessages import org.signal.benchmark.setup.TestUsers import org.thoughtcrime.securesms.BaseActivity import org.thoughtcrime.securesms.database.SignalDatabase -import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord -import org.thoughtcrime.securesms.mms.QuoteModel import org.thoughtcrime.securesms.recipients.Recipient class BenchmarkSetupActivity : BaseActivity() { @@ -53,13 +51,6 @@ class BenchmarkSetupActivity : BaseActivity() { TestMessages.insertOutgoingTextMessage(other = recipient, body = "Test message $i", timestamp = generator.nextTimestamp()) } - val voiceMessageId = TestMessages.insertIncomingVoiceMessage(other = recipient, timestamp = generator.nextTimestamp()) - val mmsRecord = SignalDatabase.messages.getMessageRecord(voiceMessageId) as MediaMmsMessageRecord - TestMessages.insertOutgoingImageMessage(other = recipient, body = "test", 2, generator.nextTimestamp()) - TestMessages.insertIncomingTextMessage(other = recipient, "reply to the test message", generator.nextTimestamp()) - TestMessages.insertIncomingQuoteTextMessage(other = recipient, quote = QuoteModel(mmsRecord.timestamp, recipient.id, "Fake voice message text", false, mmsRecord.slideDeck.asAttachments(), null, QuoteModel.Type.NORMAL, null), body = "Here is a cool quote", timestamp = generator.nextTimestamp()) - TestMessages.insertOutgoingTextMessage(other = recipient, body = "longaweorijoaijwerijoiajwer", timestamp = generator.nextTimestamp()) - SignalDatabase.threads.update(SignalDatabase.threads.getOrCreateThreadIdFor(recipient = recipient), true) } } diff --git a/app/src/benchmark/java/org/signal/benchmark/setup/TestUsers.kt b/app/src/benchmark/java/org/signal/benchmark/setup/TestUsers.kt index e47a093183..0bb7c6bf4e 100644 --- a/app/src/benchmark/java/org/signal/benchmark/setup/TestUsers.kt +++ b/app/src/benchmark/java/org/signal/benchmark/setup/TestUsers.kt @@ -4,6 +4,7 @@ import android.app.Application import android.content.SharedPreferences import android.preference.PreferenceManager import org.signal.benchmark.DummyAccountManagerFactory +import org.signal.core.util.concurrent.safeBlockingGet import org.signal.libsignal.protocol.SignalProtocolAddress import org.thoughtcrime.securesms.crypto.IdentityKeyUtil import org.thoughtcrime.securesms.crypto.MasterSecretUtil @@ -28,6 +29,7 @@ import org.whispersystems.signalservice.internal.ServiceResponse import org.whispersystems.signalservice.internal.ServiceResponseProcessor import org.whispersystems.signalservice.internal.push.VerifyAccountResponse import java.util.UUID + object TestUsers { private var generatedOthers: Int = 0 @@ -42,6 +44,9 @@ object TestUsers { val preferences: SharedPreferences = application.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0) preferences.edit().putBoolean("passphrase_initialized", true).commit() + SignalStore.account().generateAciIdentityKeyIfNecessary() + SignalStore.account().generatePniIdentityKeyIfNecessary() + val registrationRepository = RegistrationRepository(application) val registrationData = RegistrationData( code = "123123", @@ -53,13 +58,23 @@ object TestUsers { pniRegistrationId = registrationRepository.pniRegistrationId, recoveryPassword = "asdfasdfasdfasdf" ) - val verifyResponse = VerifyResponse(VerifyAccountResponse(UUID.randomUUID().toString(), UUID.randomUUID().toString(), false), null, null, null, null) + + val verifyResponse = VerifyResponse( + VerifyAccountResponse(UUID.randomUUID().toString(), UUID.randomUUID().toString(), false), + masterKey = null, + pin = null, + aciPreKeyCollection = RegistrationRepository.generateSignedAndLastResortPreKeys(SignalStore.account().aciIdentityKey, SignalStore.account().aciPreKeys), + pniPreKeyCollection = RegistrationRepository.generateSignedAndLastResortPreKeys(SignalStore.account().aciIdentityKey, SignalStore.account().pniPreKeys) + ) + AccountManagerFactory.setInstance(DummyAccountManagerFactory()) + val response: ServiceResponse = registrationRepository.registerAccount( registrationData, verifyResponse, false - ).blockingGet() + ).safeBlockingGet() + ServiceResponseProcessor.DefaultProcessor(response).resultOrThrow SignalStore.svr().optOut() diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java index eb99d1d0bc..f3a7f9f3a8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -291,7 +291,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect super.onCreate(icicle); this.locale = Locale.getDefault(); startupStopwatch = new Stopwatch("conversation-open"); - SignalLocalMetrics.ConversationOpen.start(); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationOptionsMenu.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationOptionsMenu.kt index 70f5b80709..9be510aaf5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationOptionsMenu.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationOptionsMenu.kt @@ -32,10 +32,17 @@ internal object ConversationOptionsMenu { */ class Provider( private val callback: Callback, - private val lifecycleDisposable: LifecycleDisposable + private val lifecycleDisposable: LifecycleDisposable, + var afterFirstRenderMode: Boolean = false ) : MenuProvider { + private var createdPreRenderMenu = false + override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { + if (createdPreRenderMenu && !afterFirstRenderMode) { + return + } + menu.clear() val ( @@ -57,6 +64,27 @@ internal object ConversationOptionsMenu { return } + if (!afterFirstRenderMode) { + createdPreRenderMenu = true + if (recipient.isSelf) { + return + } + + menuInflater.inflate(R.menu.conversation_first_render, menu) + + if (recipient.isGroup) { + hideMenuItem(menu, R.id.menu_call_secure) + if (!isActiveV2Group) { + hideMenuItem(menu, R.id.menu_video_secure) + } + } else if (!isPushAvailable) { + hideMenuItem(menu, R.id.menu_call_secure) + hideMenuItem(menu, R.id.menu_video_secure) + } + + return + } + if (isInMessageRequest && !recipient.isBlocked) { if (isActiveGroup) { menuInflater.inflate(R.menu.conversation_message_requests_group, menu) diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java index 5ece0fcdeb..3ea83b7ab9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationParentFragment.java @@ -484,6 +484,12 @@ public class ConversationParentFragment extends Fragment return fragment; } + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + SignalLocalMetrics.ConversationOpen.start(); + } + @Override public @NonNull View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { return inflater.inflate(R.layout.conversation_activity, container, false); @@ -2095,7 +2101,7 @@ public class ConversationParentFragment extends Fragment } protected void initializeActionBar() { - toolbar.addMenuProvider(new ConversationOptionsMenu.Provider(this, disposables)); + toolbar.addMenuProvider(new ConversationOptionsMenu.Provider(this, disposables, true)); invalidateOptionsMenu(); toolbar.setNavigationContentDescription(R.string.ConversationFragment__content_description_back_button); if (isInBubble()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt index 6d3fb056d0..b2efec88e5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationFragment.kt @@ -434,6 +434,7 @@ class ConversationFragment : private lateinit var threadHeaderMarginDecoration: ThreadHeaderMarginDecoration private lateinit var conversationItemDecorations: ConversationItemDecorations private lateinit var optionsMenuCallback: ConversationOptionsMenuCallback + private lateinit var menuProvider: ConversationOptionsMenu.Provider private lateinit var typingIndicatorDecoration: TypingIndicatorDecoration private lateinit var backPressedCallback: BackPressedDelegate @@ -778,6 +779,8 @@ class ConversationFragment : backPressedCallback = BackPressedDelegate() requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressedCallback) + menuProvider.afterFirstRenderMode = true + attachmentManager = AttachmentManager(requireContext(), requireView(), AttachmentManagerListener()) EventBus.getDefault().registerForLifecycle(groupCallViewModel, viewLifecycleOwner) @@ -1105,7 +1108,8 @@ class ConversationFragment : private fun presentActionBarMenu() { optionsMenuCallback = ConversationOptionsMenuCallback() - binding.toolbar.addMenuProvider(ConversationOptionsMenu.Provider(optionsMenuCallback, disposables)) + menuProvider = ConversationOptionsMenu.Provider(optionsMenuCallback, disposables) + binding.toolbar.addMenuProvider(menuProvider) invalidateOptionsMenu() when (args.conversationScreenType) { diff --git a/app/src/main/res/menu/conversation_first_render.xml b/app/src/main/res/menu/conversation_first_render.xml new file mode 100644 index 0000000000..b09cb02f31 --- /dev/null +++ b/app/src/main/res/menu/conversation_first_render.xml @@ -0,0 +1,20 @@ + + + + + + + + + \ No newline at end of file diff --git a/benchmark/src/main/java/org/thoughtcrime/benchmark/StartupBenchmarks.kt b/benchmark/src/main/java/org/thoughtcrime/benchmark/StartupBenchmarks.kt index 08fbcd0f92..730c3abaf2 100644 --- a/benchmark/src/main/java/org/thoughtcrime/benchmark/StartupBenchmarks.kt +++ b/benchmark/src/main/java/org/thoughtcrime/benchmark/StartupBenchmarks.kt @@ -1,17 +1,12 @@ package org.thoughtcrime.benchmark -import android.content.ComponentName -import android.content.Intent import androidx.benchmark.macro.CompilationMode import androidx.benchmark.macro.ExperimentalMetricApi -import androidx.benchmark.macro.MacrobenchmarkScope import androidx.benchmark.macro.StartupMode import androidx.benchmark.macro.StartupTimingMetric import androidx.benchmark.macro.TraceSectionMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule import androidx.test.ext.junit.runners.AndroidJUnit4 -import androidx.test.uiautomator.By -import androidx.test.uiautomator.Until import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith