Prevent menu creation slowing data load performance in CFv2.
This commit is contained in:
parent
3db83c1602
commit
6db59cb896
8 changed files with 78 additions and 20 deletions
|
@ -6,8 +6,6 @@ import org.signal.benchmark.setup.TestMessages
|
||||||
import org.signal.benchmark.setup.TestUsers
|
import org.signal.benchmark.setup.TestUsers
|
||||||
import org.thoughtcrime.securesms.BaseActivity
|
import org.thoughtcrime.securesms.BaseActivity
|
||||||
import org.thoughtcrime.securesms.database.SignalDatabase
|
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
|
import org.thoughtcrime.securesms.recipients.Recipient
|
||||||
|
|
||||||
class BenchmarkSetupActivity : BaseActivity() {
|
class BenchmarkSetupActivity : BaseActivity() {
|
||||||
|
@ -53,13 +51,6 @@ class BenchmarkSetupActivity : BaseActivity() {
|
||||||
TestMessages.insertOutgoingTextMessage(other = recipient, body = "Test message $i", timestamp = generator.nextTimestamp())
|
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)
|
SignalDatabase.threads.update(SignalDatabase.threads.getOrCreateThreadIdFor(recipient = recipient), true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import android.app.Application
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.preference.PreferenceManager
|
import android.preference.PreferenceManager
|
||||||
import org.signal.benchmark.DummyAccountManagerFactory
|
import org.signal.benchmark.DummyAccountManagerFactory
|
||||||
|
import org.signal.core.util.concurrent.safeBlockingGet
|
||||||
import org.signal.libsignal.protocol.SignalProtocolAddress
|
import org.signal.libsignal.protocol.SignalProtocolAddress
|
||||||
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
|
||||||
import org.thoughtcrime.securesms.crypto.MasterSecretUtil
|
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.ServiceResponseProcessor
|
||||||
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse
|
import org.whispersystems.signalservice.internal.push.VerifyAccountResponse
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
object TestUsers {
|
object TestUsers {
|
||||||
|
|
||||||
private var generatedOthers: Int = 0
|
private var generatedOthers: Int = 0
|
||||||
|
@ -42,6 +44,9 @@ object TestUsers {
|
||||||
val preferences: SharedPreferences = application.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0)
|
val preferences: SharedPreferences = application.getSharedPreferences(MasterSecretUtil.PREFERENCES_NAME, 0)
|
||||||
preferences.edit().putBoolean("passphrase_initialized", true).commit()
|
preferences.edit().putBoolean("passphrase_initialized", true).commit()
|
||||||
|
|
||||||
|
SignalStore.account().generateAciIdentityKeyIfNecessary()
|
||||||
|
SignalStore.account().generatePniIdentityKeyIfNecessary()
|
||||||
|
|
||||||
val registrationRepository = RegistrationRepository(application)
|
val registrationRepository = RegistrationRepository(application)
|
||||||
val registrationData = RegistrationData(
|
val registrationData = RegistrationData(
|
||||||
code = "123123",
|
code = "123123",
|
||||||
|
@ -53,13 +58,23 @@ object TestUsers {
|
||||||
pniRegistrationId = registrationRepository.pniRegistrationId,
|
pniRegistrationId = registrationRepository.pniRegistrationId,
|
||||||
recoveryPassword = "asdfasdfasdfasdf"
|
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())
|
AccountManagerFactory.setInstance(DummyAccountManagerFactory())
|
||||||
|
|
||||||
val response: ServiceResponse<VerifyResponse> = registrationRepository.registerAccount(
|
val response: ServiceResponse<VerifyResponse> = registrationRepository.registerAccount(
|
||||||
registrationData,
|
registrationData,
|
||||||
verifyResponse,
|
verifyResponse,
|
||||||
false
|
false
|
||||||
).blockingGet()
|
).safeBlockingGet()
|
||||||
|
|
||||||
ServiceResponseProcessor.DefaultProcessor(response).resultOrThrow
|
ServiceResponseProcessor.DefaultProcessor(response).resultOrThrow
|
||||||
|
|
||||||
SignalStore.svr().optOut()
|
SignalStore.svr().optOut()
|
||||||
|
|
|
@ -291,7 +291,6 @@ public class ConversationFragment extends LoggingFragment implements Multiselect
|
||||||
super.onCreate(icicle);
|
super.onCreate(icicle);
|
||||||
this.locale = Locale.getDefault();
|
this.locale = Locale.getDefault();
|
||||||
startupStopwatch = new Stopwatch("conversation-open");
|
startupStopwatch = new Stopwatch("conversation-open");
|
||||||
SignalLocalMetrics.ConversationOpen.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -32,10 +32,17 @@ internal object ConversationOptionsMenu {
|
||||||
*/
|
*/
|
||||||
class Provider(
|
class Provider(
|
||||||
private val callback: Callback,
|
private val callback: Callback,
|
||||||
private val lifecycleDisposable: LifecycleDisposable
|
private val lifecycleDisposable: LifecycleDisposable,
|
||||||
|
var afterFirstRenderMode: Boolean = false
|
||||||
) : MenuProvider {
|
) : MenuProvider {
|
||||||
|
|
||||||
|
private var createdPreRenderMenu = false
|
||||||
|
|
||||||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||||
|
if (createdPreRenderMenu && !afterFirstRenderMode) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
menu.clear()
|
menu.clear()
|
||||||
|
|
||||||
val (
|
val (
|
||||||
|
@ -57,6 +64,27 @@ internal object ConversationOptionsMenu {
|
||||||
return
|
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 (isInMessageRequest && !recipient.isBlocked) {
|
||||||
if (isActiveGroup) {
|
if (isActiveGroup) {
|
||||||
menuInflater.inflate(R.menu.conversation_message_requests_group, menu)
|
menuInflater.inflate(R.menu.conversation_message_requests_group, menu)
|
||||||
|
|
|
@ -484,6 +484,12 @@ public class ConversationParentFragment extends Fragment
|
||||||
return fragment;
|
return fragment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
SignalLocalMetrics.ConversationOpen.start();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public @NonNull View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
public @NonNull View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
||||||
return inflater.inflate(R.layout.conversation_activity, container, false);
|
return inflater.inflate(R.layout.conversation_activity, container, false);
|
||||||
|
@ -2095,7 +2101,7 @@ public class ConversationParentFragment extends Fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void initializeActionBar() {
|
protected void initializeActionBar() {
|
||||||
toolbar.addMenuProvider(new ConversationOptionsMenu.Provider(this, disposables));
|
toolbar.addMenuProvider(new ConversationOptionsMenu.Provider(this, disposables, true));
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
toolbar.setNavigationContentDescription(R.string.ConversationFragment__content_description_back_button);
|
toolbar.setNavigationContentDescription(R.string.ConversationFragment__content_description_back_button);
|
||||||
if (isInBubble()) {
|
if (isInBubble()) {
|
||||||
|
|
|
@ -434,6 +434,7 @@ class ConversationFragment :
|
||||||
private lateinit var threadHeaderMarginDecoration: ThreadHeaderMarginDecoration
|
private lateinit var threadHeaderMarginDecoration: ThreadHeaderMarginDecoration
|
||||||
private lateinit var conversationItemDecorations: ConversationItemDecorations
|
private lateinit var conversationItemDecorations: ConversationItemDecorations
|
||||||
private lateinit var optionsMenuCallback: ConversationOptionsMenuCallback
|
private lateinit var optionsMenuCallback: ConversationOptionsMenuCallback
|
||||||
|
private lateinit var menuProvider: ConversationOptionsMenu.Provider
|
||||||
private lateinit var typingIndicatorDecoration: TypingIndicatorDecoration
|
private lateinit var typingIndicatorDecoration: TypingIndicatorDecoration
|
||||||
private lateinit var backPressedCallback: BackPressedDelegate
|
private lateinit var backPressedCallback: BackPressedDelegate
|
||||||
|
|
||||||
|
@ -778,6 +779,8 @@ class ConversationFragment :
|
||||||
backPressedCallback = BackPressedDelegate()
|
backPressedCallback = BackPressedDelegate()
|
||||||
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressedCallback)
|
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, backPressedCallback)
|
||||||
|
|
||||||
|
menuProvider.afterFirstRenderMode = true
|
||||||
|
|
||||||
attachmentManager = AttachmentManager(requireContext(), requireView(), AttachmentManagerListener())
|
attachmentManager = AttachmentManager(requireContext(), requireView(), AttachmentManagerListener())
|
||||||
|
|
||||||
EventBus.getDefault().registerForLifecycle(groupCallViewModel, viewLifecycleOwner)
|
EventBus.getDefault().registerForLifecycle(groupCallViewModel, viewLifecycleOwner)
|
||||||
|
@ -1105,7 +1108,8 @@ class ConversationFragment :
|
||||||
|
|
||||||
private fun presentActionBarMenu() {
|
private fun presentActionBarMenu() {
|
||||||
optionsMenuCallback = ConversationOptionsMenuCallback()
|
optionsMenuCallback = ConversationOptionsMenuCallback()
|
||||||
binding.toolbar.addMenuProvider(ConversationOptionsMenu.Provider(optionsMenuCallback, disposables))
|
menuProvider = ConversationOptionsMenu.Provider(optionsMenuCallback, disposables)
|
||||||
|
binding.toolbar.addMenuProvider(menuProvider)
|
||||||
invalidateOptionsMenu()
|
invalidateOptionsMenu()
|
||||||
|
|
||||||
when (args.conversationScreenType) {
|
when (args.conversationScreenType) {
|
||||||
|
|
20
app/src/main/res/menu/conversation_first_render.xml
Normal file
20
app/src/main/res/menu/conversation_first_render.xml
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item android:title="@string/conversation_callable_secure__menu_video"
|
||||||
|
android:id="@+id/menu_video_secure"
|
||||||
|
android:icon="@drawable/ic_video_call_24"
|
||||||
|
app:iconTint="@color/signal_icon_tint_primary"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
|
<item android:title="@string/conversation_callable_secure__menu_call"
|
||||||
|
android:id="@+id/menu_call_secure"
|
||||||
|
android:icon="@drawable/ic_phone_right_24"
|
||||||
|
app:iconTint="@color/signal_icon_tint_primary"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_conversation_settings"
|
||||||
|
android:title="@string/conversation__menu_conversation_settings" />
|
||||||
|
</menu>
|
|
@ -1,17 +1,12 @@
|
||||||
package org.thoughtcrime.benchmark
|
package org.thoughtcrime.benchmark
|
||||||
|
|
||||||
import android.content.ComponentName
|
|
||||||
import android.content.Intent
|
|
||||||
import androidx.benchmark.macro.CompilationMode
|
import androidx.benchmark.macro.CompilationMode
|
||||||
import androidx.benchmark.macro.ExperimentalMetricApi
|
import androidx.benchmark.macro.ExperimentalMetricApi
|
||||||
import androidx.benchmark.macro.MacrobenchmarkScope
|
|
||||||
import androidx.benchmark.macro.StartupMode
|
import androidx.benchmark.macro.StartupMode
|
||||||
import androidx.benchmark.macro.StartupTimingMetric
|
import androidx.benchmark.macro.StartupTimingMetric
|
||||||
import androidx.benchmark.macro.TraceSectionMetric
|
import androidx.benchmark.macro.TraceSectionMetric
|
||||||
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
|
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.uiautomator.By
|
|
||||||
import androidx.test.uiautomator.Until
|
|
||||||
import org.junit.Rule
|
import org.junit.Rule
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
|
|
Loading…
Add table
Reference in a new issue