From 0b77b339026b2ac0aa404a4f3c2bf206e6996fa5 Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 10 Nov 2020 12:40:50 -0500 Subject: [PATCH] Add the ability to trace methods in internal builds. Currently only for internal builds. Use the @Trace annotation to trace methods for viewing in Perfetto. --- .github/workflows/android.yml | 2 +- app/build.gradle | 20 +- .../securesms/tracing/TraceAspect.java | 103 ++++++++++ .../securesms/tracing/TracerImpl.java | 193 ++++++++++++++++++ app/src/internal/proto/Trace.proto | 151 ++++++++++++++ .../securesms/ApplicationContext.java | 2 + .../thoughtcrime/securesms/MainActivity.java | 2 + .../contacts/sync/DirectoryHelper.java | 2 + .../conversation/ConversationActivity.java | 2 + .../conversation/ConversationDataSource.java | 2 + .../conversation/ConversationFragment.java | 2 + .../ConversationListArchiveFragment.java | 2 + .../ConversationListDataSource.java | 2 + .../ConversationListFragment.java | 2 + .../database/AttachmentDatabase.java | 2 + .../securesms/database/DraftDatabase.java | 2 + .../securesms/database/GroupDatabase.java | 2 + .../database/GroupReceiptDatabase.java | 2 + .../securesms/database/IdentityDatabase.java | 2 + .../securesms/database/JobDatabase.java | 2 + .../securesms/database/KeyValueDatabase.java | 2 + .../securesms/database/MediaDatabase.java | 2 + .../securesms/database/MegaphoneDatabase.java | 2 + .../securesms/database/MentionDatabase.java | 2 + .../securesms/database/MmsDatabase.java | 2 + .../securesms/database/MmsSmsDatabase.java | 2 + .../securesms/database/PushDatabase.java | 2 + .../securesms/database/RecipientDatabase.java | 2 + .../database/RemappedRecordsDatabase.java | 2 + .../securesms/database/SearchDatabase.java | 2 + .../securesms/database/SessionDatabase.java | 2 + .../database/SignedPreKeyDatabase.java | 2 + .../securesms/database/SmsDatabase.java | 2 + .../securesms/database/StickerDatabase.java | 2 + .../database/StorageKeyDatabase.java | 2 + .../securesms/database/ThreadDatabase.java | 2 + .../securesms/jobs/PushDecryptMessageJob.java | 2 + .../securesms/jobs/PushGroupSendJob.java | 2 + .../securesms/jobs/PushMediaSendJob.java | 2 + .../securesms/jobs/PushProcessMessageJob.java | 2 + .../securesms/jobs/PushTextSendJob.java | 2 + .../securesms/jobs/RetrieveProfileJob.java | 2 + .../securesms/jobs/StorageSyncJob.java | 2 + .../securesms/logsubmit/LogSectionTrace.java | 38 ++++ .../logsubmit/SubmitDebugLogAdapter.java | 7 +- .../logsubmit/SubmitDebugLogRepository.java | 4 + .../securesms/mediasend/CameraXFragment.java | 1 + .../securesms/storage/StorageSyncHelper.java | 2 + .../thoughtcrime/securesms/tracing/Trace.java | 14 ++ .../securesms/tracing/Tracer.java | 45 ++++ .../securesms/tracing/TracerImpl.java | 34 +++ .../securesms/tracing/TracerImpl.java | 34 +++ 52 files changed, 720 insertions(+), 4 deletions(-) create mode 100644 app/src/internal/java/org/thoughtcrime/securesms/tracing/TraceAspect.java create mode 100644 app/src/internal/java/org/thoughtcrime/securesms/tracing/TracerImpl.java create mode 100644 app/src/internal/proto/Trace.proto create mode 100644 app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionTrace.java create mode 100644 app/src/main/java/org/thoughtcrime/securesms/tracing/Trace.java create mode 100644 app/src/main/java/org/thoughtcrime/securesms/tracing/Tracer.java create mode 100644 app/src/play/java/org/thoughtcrime/securesms/tracing/TracerImpl.java create mode 100644 app/src/website/java/org/thoughtcrime/securesms/tracing/TracerImpl.java diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 2034d5b31..87b991251 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -22,7 +22,7 @@ jobs: java-version: 1.8 - name: Install NDK - run: echo "y" | sudo /usr/local/lib/android/sdk/tools/bin/sdkmanager --install "ndk;20.0.5594570" --sdk_root=${ANDROID_SDK_ROOT} + run: echo "y" | sudo /usr/local/lib/android/sdk/tools/bin/sdkmanager --install "ndk;21.0.6113669" --sdk_root=${ANDROID_SDK_ROOT} - name: Validate Gradle Wrapper uses: gradle/wrapper-validation-action@v1 diff --git a/app/build.gradle b/app/build.gradle index 87bfe0696..4a7a019e5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -11,13 +11,15 @@ buildscript { jcenter { content { includeVersion 'org.jetbrains.trove4j', 'trove4j', '20160824' + includeGroupByRegex "com\\.archinamon.*" } } } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:4.0.2' classpath 'androidx.navigation:navigation-safe-args-gradle-plugin:2.1.0' classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10' + classpath 'com.archinamon:android-gradle-aspectj:4.2.0' } } @@ -25,9 +27,22 @@ apply plugin: 'com.android.application' apply plugin: 'com.google.protobuf' apply plugin: 'androidx.navigation.safeargs' apply plugin: 'witness' +apply plugin: 'com.archinamon.aspectj-ext' apply from: 'translations.gradle' apply from: 'witness-verifications.gradle' +if (getGradle().getStartParameter().getTaskRequests().toString().contains("Internal")) { + aspectj { + includeJar 'sqlcipher' + includeAspectsFromJar 'Signal-Android' + java = JavaVersion.VERSION_1_8 + } +} else if (getGradle().getStartParameter().getTaskRequests().toString().contains("Test")) { + aspectj { + compileTests = false + } +} + repositories { maven { url "https://raw.github.com/signalapp/maven/master/photoview/releases/" @@ -144,6 +159,7 @@ android { buildConfigField "String", "ZKGROUP_SERVER_PUBLIC_PARAMS", "\"AMhf5ywVwITZMsff/eCyudZx9JDmkkkbV6PInzG4p8x3VqVJSFiMvnvlEKWuRob/1eaIetR31IYeAbm0NdOuHH8Qi+Rexi1wLlpzIo1gstHWBfZzy1+qHRV5A4TqPp15YzBPm0WSggW6PbSn+F4lf57VCnHF7p8SvzAA2ZZJPYJURt8X7bbg+H3i+PEjH9DXItNEqs2sNcug37xZQDLm7X0=\"" buildConfigField "String[]", "LANGUAGES", "new String[]{\"" + autoResConfig().collect { s -> s.replace('-r', '_') }.join('", "') + '"}' buildConfigField "int", "CANONICAL_VERSION_CODE", "$canonicalVersionCode" + buildConfigField "int", "TRACE_EVENT_MAX", "2000" ndk { abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' @@ -243,6 +259,7 @@ android { ext.websiteUpdateUrl = "null" buildConfigField "boolean", "PLAY_STORE_DISABLED", "false" buildConfigField "String", "NOPLAY_UPDATE_URL", "$ext.websiteUpdateUrl" + buildConfigField "int", "TRACE_EVENT_MAX", "30_000" } prod { @@ -425,7 +442,6 @@ dependencyVerification { configuration = '(play|website)(Prod|Staging)(Debug|Release)RuntimeClasspath' } - def assembleWebsiteDescriptor = { variant, file -> if (file.exists()) { MessageDigest md = MessageDigest.getInstance("SHA-256"); diff --git a/app/src/internal/java/org/thoughtcrime/securesms/tracing/TraceAspect.java b/app/src/internal/java/org/thoughtcrime/securesms/tracing/TraceAspect.java new file mode 100644 index 000000000..6142e2395 --- /dev/null +++ b/app/src/internal/java/org/thoughtcrime/securesms/tracing/TraceAspect.java @@ -0,0 +1,103 @@ +package org.thoughtcrime.securesms.tracing; + +import androidx.annotation.NonNull; + +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.thoughtcrime.securesms.logging.Log; + +/** + * Uses AspectJ to augment relevant methods to be traced with the {@link TracerImpl}. + */ +@Aspect +public class TraceAspect { + + @Pointcut("within(@org.thoughtcrime.securesms.tracing.Trace *)") + public void withinAnnotatedClass() {} + + @Pointcut("execution(!synthetic * *(..)) && withinAnnotatedClass()") + public void methodInsideAnnotatedType() {} + + @Pointcut("execution(!synthetic *.new(..)) && withinAnnotatedClass()") + public void constructorInsideAnnotatedType() {} + + @Pointcut("execution(@org.thoughtcrime.securesms.tracing.Trace * *(..)) || methodInsideAnnotatedType()") + public void annotatedMethod() {} + + @Pointcut("execution(@org.thoughtcrime.securesms.tracing.Trace *.new(..)) || constructorInsideAnnotatedType()") + public void annotatedConstructor() {} + + @Pointcut("execution(* *(..)) && within(net.sqlcipher.database.*)") + public void sqlcipher() {} + + @Pointcut("execution(* net.sqlcipher.database.SQLiteDatabase.rawQuery(..)) || " + + "execution(* net.sqlcipher.database.SQLiteDatabase.query(..)) || " + + "execution(* net.sqlcipher.database.SQLiteDatabase.insert(..)) || " + + "execution(* net.sqlcipher.database.SQLiteDatabase.insertOrThrow(..)) || " + + "execution(* net.sqlcipher.database.SQLiteDatabase.insertWithOnConflict(..)) || " + + "execution(* net.sqlcipher.database.SQLiteDatabase.delete(..)) || " + + "execution(* net.sqlcipher.database.SQLiteDatabase.update(..))") + public void sqlcipherQuery() {} + + @Around("annotatedMethod() || annotatedConstructor() || (sqlcipher() && !sqlcipherQuery())") + public @NonNull Object profile(@NonNull ProceedingJoinPoint joinPoint) throws Throwable { + String methodName = joinPoint.getSignature().toShortString(); + + Tracer.getInstance().start(methodName); + Object result = joinPoint.proceed(); + Tracer.getInstance().end(methodName); + return result; + } + + @Around("sqlcipherQuery()") + public @NonNull Object profileQuery(@NonNull ProceedingJoinPoint joinPoint) throws Throwable { + String table; + String query; + + if (joinPoint.getSignature().getName().equals("query")) { + if (joinPoint.getArgs().length == 9) { + table = (String) joinPoint.getArgs()[1]; + query = (String) joinPoint.getArgs()[3]; + } else if (joinPoint.getArgs().length == 7 || joinPoint.getArgs().length == 8) { + table = (String) joinPoint.getArgs()[0]; + query = (String) joinPoint.getArgs()[2]; + } else { + table = "N/A"; + query = "N/A"; + } + } else if (joinPoint.getSignature().getName().equals("rawQuery")) { + table = ""; + query = (String) joinPoint.getArgs()[0]; + } else if (joinPoint.getSignature().getName().equals("insert")) { + table = (String) joinPoint.getArgs()[0]; + query = ""; + } else if (joinPoint.getSignature().getName().equals("insertOrThrow")) { + table = (String) joinPoint.getArgs()[0]; + query = ""; + } else if (joinPoint.getSignature().getName().equals("insertWithOnConflict")) { + table = (String) joinPoint.getArgs()[0]; + query = ""; + } else if (joinPoint.getSignature().getName().equals("delete")) { + table = (String) joinPoint.getArgs()[0]; + query = (String) joinPoint.getArgs()[1]; + } else if (joinPoint.getSignature().getName().equals("update")) { + table = (String) joinPoint.getArgs()[0]; + query = (String) joinPoint.getArgs()[2]; + } else { + table = "N/A"; + query = "N/A"; + } + + query = query == null ? "null" : query; + query = "[" + table + "] " + query; + + String methodName = joinPoint.getSignature().toShortString(); + + Tracer.getInstance().start(methodName, "query", query); + Object result = joinPoint.proceed(); + Tracer.getInstance().end(methodName); + return result; + } +} diff --git a/app/src/internal/java/org/thoughtcrime/securesms/tracing/TracerImpl.java b/app/src/internal/java/org/thoughtcrime/securesms/tracing/TracerImpl.java new file mode 100644 index 000000000..395e495e4 --- /dev/null +++ b/app/src/internal/java/org/thoughtcrime/securesms/tracing/TracerImpl.java @@ -0,0 +1,193 @@ +package org.thoughtcrime.securesms.tracing; + +import android.os.SystemClock; +import androidx.annotation.NonNull; + +import com.google.protobuf.ByteString; + +import org.thoughtcrime.securesms.BuildConfig; +import org.thoughtcrime.securesms.trace.TraceProtos; +import org.thoughtcrime.securesms.trace.TraceProtos.Trace; +import org.thoughtcrime.securesms.trace.TraceProtos.TracePacket; +import org.thoughtcrime.securesms.trace.TraceProtos.TrackDescriptor; +import org.thoughtcrime.securesms.trace.TraceProtos.TrackEvent; +import org.whispersystems.signalservice.api.util.UuidUtil; + +import java.util.Map; +import java.util.Queue; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * A class to create Perfetto-compatible traces. Currently keeps the entire trace in memory to + * avoid weirdness with synchronizing to disk. + * + * Some general info on how the Perfetto format works: + * - The file format is just a Trace proto (see Trace.proto) + * - The Trace proto is just a series of TracePackets + * - TracePackets can describe: + * - Threads + * - Start of a method + * - End of a method + * - (And a bunch of other stuff that's not relevant to use at this point) + * + * We keep a circular buffer of TracePackets for method calls, and we keep a separate list of + * TracePackets for threads so we don't lose any of those. + * + * Serializing is just a matter of throwing all the TracePackets we have into a proto. + * + * Note: This class aims to be largely-thread-safe, but prioritizes speed and memory efficiency + * above all else. These methods are going to be called very quickly from every thread imaginable, + * and we want to create as little overhead as possible. The idea being that it's ok if we don't, + * for example, keep a perfect circular buffer size if it allows us to reduce overhead. The only + * cost of screwing up would be dropping a trace packet or something, which, while sad, won't affect + * how the app functions. + */ +public final class TracerImpl implements Tracer { + + private static final int TRUSTED_SEQUENCE_ID = 1; + private static final byte[] SYNCHRONIZATION_MARKER = UuidUtil.toByteArray(UUID.fromString("82477a76-b28d-42ba-81dc-33326d57a079")); + + private final Clock clock; + private final Map threadPackets; + private final Queue eventPackets; + private final AtomicInteger eventCount; + + TracerImpl() { + this.clock = SystemClock::elapsedRealtimeNanos; + this.threadPackets = new ConcurrentHashMap<>(); + this.eventPackets = new ConcurrentLinkedQueue<>(); + this.eventCount = new AtomicInteger(0); + } + + @Override + public boolean isEnabled() { + return true; + } + + @Override + public void start(@NonNull String methodName) { + long time = clock.getTimeNanos(); + Thread currentThread = Thread.currentThread(); + + if (!threadPackets.containsKey(currentThread.getId())) { + threadPackets.put(currentThread.getId(), forThread(currentThread)); + } + + addPacket(forMethodStart(methodName, time, currentThread.getId())); + } + + @Override + public void start(@NonNull String methodName, @NonNull String key, @NonNull String value) { + long time = clock.getTimeNanos(); + Thread currentThread = Thread.currentThread(); + + if (!threadPackets.containsKey(currentThread.getId())) { + threadPackets.put(currentThread.getId(), forThread(currentThread)); + } + + addPacket(forMethodStart(methodName, time, currentThread.getId(), key, value)); + } + + @Override + public void end(@NonNull String methodName) { + addPacket(forMethodEnd(methodName, clock.getTimeNanos(), Thread.currentThread().getId())); + } + + public @NonNull byte[] serialize() { + Trace.Builder trace = Trace.newBuilder(); + + for (TracePacket thread : threadPackets.values()) { + trace.addPacket(thread); + } + + for (TracePacket event : eventPackets) { + trace.addPacket(event); + } + + trace.addPacket(forSynchronization(clock.getTimeNanos())); + + return trace.build().toByteArray(); + } + + /** + * Attempts to add a packet to our list while keeping the size of our circular buffer in-check. + * The tracking of the event count is not perfectly thread-safe, but doing it in a thread-safe + * way would likely involve adding a lock, which we really don't want to do, since it'll add + * unnecessary overhead. + * + * Note that we keep track of the event count separately because + * {@link ConcurrentLinkedQueue#size()} is NOT a constant-time operation. + */ + private void addPacket(@NonNull TracePacket packet) { + eventPackets.add(packet); + + int size = eventCount.incrementAndGet(); + + for (int i = size; i > BuildConfig.TRACE_EVENT_MAX; i--) { + eventPackets.poll(); + eventCount.decrementAndGet(); + } + } + + private static TracePacket forThread(@NonNull Thread thread) { + return TracePacket.newBuilder() + .setTrustedPacketSequenceId(TRUSTED_SEQUENCE_ID) + .setTrackDescriptor(TrackDescriptor.newBuilder() + .setUuid(thread.getId()) + .setName(thread.getName())) + .build(); + + } + + private static TracePacket forMethodStart(@NonNull String name, long time, long threadId) { + return TracePacket.newBuilder() + .setTrustedPacketSequenceId(TRUSTED_SEQUENCE_ID) + .setTimestamp(time) + .setTrackEvent(TrackEvent.newBuilder() + .setTrackUuid(threadId) + .setName(name) + .setType(TrackEvent.Type.TYPE_SLICE_BEGIN)) + .build(); + } + + private static TracePacket forMethodStart(@NonNull String name, long time, long threadId, @NonNull String key, @NonNull String value) { + return TracePacket.newBuilder() + .setTrustedPacketSequenceId(TRUSTED_SEQUENCE_ID) + .setTimestamp(time) + .setTrackEvent(TrackEvent.newBuilder() + .setTrackUuid(threadId) + .setName(name) + .setType(TrackEvent.Type.TYPE_SLICE_BEGIN) + .addDebugAnnotations(TraceProtos.DebugAnnotation.newBuilder() + .setName(key) + .setStringValue(value) + .build())) + .build(); + } + + private static TracePacket forMethodEnd(@NonNull String name, long time, long threadId) { + return TracePacket.newBuilder() + .setTrustedPacketSequenceId(TRUSTED_SEQUENCE_ID) + .setTimestamp(time) + .setTrackEvent(TrackEvent.newBuilder() + .setTrackUuid(threadId) + .setName(name) + .setType(TrackEvent.Type.TYPE_SLICE_END)) + .build(); + } + + private static TracePacket forSynchronization(long time) { + return TracePacket.newBuilder() + .setTrustedPacketSequenceId(TRUSTED_SEQUENCE_ID) + .setTimestamp(time) + .setSynchronizationMarker(ByteString.copyFrom(SYNCHRONIZATION_MARKER)) + .build(); + } + + private interface Clock { + long getTimeNanos(); + } +} diff --git a/app/src/internal/proto/Trace.proto b/app/src/internal/proto/Trace.proto new file mode 100644 index 000000000..a892e32a1 --- /dev/null +++ b/app/src/internal/proto/Trace.proto @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2018 The Android Open Source Project + * + * 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. + */ + + +syntax = "proto2"; + +package signal; + +option java_package = "org.thoughtcrime.securesms.trace"; +option java_outer_classname = "TraceProtos"; + +/* + * Minimal interface needed to work with Perfetto. + * + * https://cs.android.com/android/platform/superproject/+/master:external/perfetto/protos/perfetto/trace/trace.proto + */ +message Trace { + repeated TracePacket packet = 1; +} + +message TracePacket { + optional uint64 timestamp = 8; + optional uint32 timestamp_clock_id = 58; + + oneof data { + TrackEvent track_event = 11; + TrackDescriptor track_descriptor = 60; + bytes synchronization_marker = 36; + } + + oneof optional_trusted_packet_sequence_id { + uint32 trusted_packet_sequence_id = 10; + } +} + +message TrackEvent { + repeated uint64 category_iids = 3; + repeated string categories = 22; + + repeated DebugAnnotation debug_annotations = 4; + + oneof name_field { + uint64 name_iid = 10; + string name = 23; + } + + enum Type { + TYPE_UNSPECIFIED = 0; + TYPE_SLICE_BEGIN = 1; + TYPE_SLICE_END = 2; + TYPE_INSTANT = 3; + TYPE_COUNTER = 4; + } + + optional Type type = 9; + optional uint64 track_uuid = 11; + optional int64 counter_value = 30; + + oneof timestamp { + int64 timestamp_delta_us = 1; + int64 timestamp_absolute_us = 16; + } + + oneof thread_time { + int64 thread_time_delta_us = 2; + int64 thread_time_absolute_us = 17; + } +} + +message TrackDescriptor { + optional uint64 uuid = 1; + optional uint64 parent_uuid = 5; + optional string name = 2; + optional ThreadDescriptor thread = 4; + optional CounterDescriptor counter = 8; +} + + +message ThreadDescriptor { + optional int32 pid = 1; + optional int32 tid = 2; + + optional string thread_name = 5; +} + +message CounterDescriptor { + enum BuiltinCounterType { + COUNTER_UNSPECIFIED = 0; + COUNTER_THREAD_TIME_NS = 1; + COUNTER_THREAD_INSTRUCTION_COUNT = 2; + } + + enum Unit { + UNIT_UNSPECIFIED = 0; + UNIT_TIME_NS = 1; + UNIT_COUNT = 2; + UNIT_SIZE_BYTES = 3; + } + optional BuiltinCounterType type = 1; + repeated string categories = 2; + optional Unit unit = 3; + optional int64 unit_multiplier = 4; + optional bool is_incremental = 5; +} + +message DebugAnnotation { + message NestedValue { + enum NestedType { + UNSPECIFIED = 0; + DICT = 1; + ARRAY = 2; + } + + optional NestedType nested_type = 1; + repeated string dict_keys = 2; + repeated NestedValue dict_values = 3; + repeated NestedValue array_values = 4; + optional int64 int_value = 5; + optional double double_value = 6; + optional bool bool_value = 7; + optional string string_value = 8; + } + + oneof name_field { + uint64 name_iid = 1; + string name = 10; + } + + oneof value { + bool bool_value = 2; + uint64 uint_value = 3; + int64 int_value = 4; + double double_value = 5; + string string_value = 6; + uint64 pointer_value = 7; + NestedValue nested_value = 8; + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java index 34aab4169..56b5697f9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java +++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java @@ -71,6 +71,7 @@ import org.thoughtcrime.securesms.service.RotateSignedPreKeyListener; import org.thoughtcrime.securesms.service.UpdateApkRefreshListener; import org.thoughtcrime.securesms.storage.StorageSyncHelper; import org.thoughtcrime.securesms.util.DynamicTheme; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; @@ -93,6 +94,7 @@ import java.util.concurrent.TimeUnit; * * @author Moxie Marlinspike */ +@Trace public class ApplicationContext extends MultiDexApplication implements DefaultLifecycleObserver { private static final String TAG = ApplicationContext.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/MainActivity.java b/app/src/main/java/org/thoughtcrime/securesms/MainActivity.java index 21fc304f0..fb3a6af8f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/MainActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/MainActivity.java @@ -6,10 +6,12 @@ import android.os.Bundle; import androidx.annotation.NonNull; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme; import org.thoughtcrime.securesms.util.DynamicTheme; +@Trace public class MainActivity extends PassphraseRequiredActivity { private final DynamicTheme dynamicTheme = new DynamicNoActionBarTheme(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/DirectoryHelper.java b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/DirectoryHelper.java index 39df48397..3d63290ee 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/DirectoryHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/sync/DirectoryHelper.java @@ -43,6 +43,7 @@ import org.thoughtcrime.securesms.storage.StorageSyncHelper; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.sms.IncomingJoinedMessage; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.ProfileUtil; import org.thoughtcrime.securesms.util.SetUtil; import org.thoughtcrime.securesms.util.Stopwatch; @@ -72,6 +73,7 @@ import java.util.concurrent.TimeoutException; /** * Manages all the stuff around determining if a user is registered or not. */ +@Trace public class DirectoryHelper { private static final String TAG = Log.tag(DirectoryHelper.class); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java index 1bd6cedb8..dfc94dc84 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationActivity.java @@ -234,6 +234,7 @@ import org.thoughtcrime.securesms.stickers.StickerLocator; import org.thoughtcrime.securesms.stickers.StickerManagementActivity; import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent; import org.thoughtcrime.securesms.stickers.StickerSearchRepository; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.AsynchronousCallback; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.BitmapUtil; @@ -290,6 +291,7 @@ import static org.whispersystems.libsignal.SessionCipher.SESSION_LOCK; * @author Moxie Marlinspike * */ +@Trace @SuppressLint("StaticFieldLeak") public class ConversationActivity extends PassphraseRequiredActivity implements ConversationFragment.ConversationFragmentListener, diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java index 0289b752a..c70f8b90b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationDataSource.java @@ -17,6 +17,7 @@ import org.thoughtcrime.securesms.database.MmsSmsDatabase; import org.thoughtcrime.securesms.database.model.Mention; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; import org.thoughtcrime.securesms.util.paging.Invalidator; import org.thoughtcrime.securesms.util.paging.SizeFixResult; @@ -32,6 +33,7 @@ import java.util.concurrent.Executor; /** * Core data source for loading an individual conversation. */ +@Trace class ConversationDataSource extends PositionalDataSource { private static final String TAG = Log.tag(ConversationDataSource.class); 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 6829684fc..66f6e22c5 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationFragment.java @@ -119,6 +119,7 @@ import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.stickers.StickerLocator; import org.thoughtcrime.securesms.stickers.StickerPackPreviewActivity; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.CachedInflater; import org.thoughtcrime.securesms.util.CommunicationActions; import org.thoughtcrime.securesms.util.HtmlUtil; @@ -144,6 +145,7 @@ import java.util.List; import java.util.Locale; import java.util.Set; +@Trace @SuppressLint("StaticFieldLeak") public class ConversationFragment extends LoggingFragment { private static final String TAG = ConversationFragment.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListArchiveFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListArchiveFragment.java index efc7f6b30..b2e52e931 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListArchiveFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListArchiveFragment.java @@ -37,11 +37,13 @@ import com.google.android.material.snackbar.Snackbar; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton; import org.thoughtcrime.securesms.database.DatabaseFactory; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask; import java.util.Set; +@Trace public class ConversationListArchiveFragment extends ConversationListFragment implements ActionMode.Callback { private RecyclerView list; diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListDataSource.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListDataSource.java index e28b82315..85914ab37 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListDataSource.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListDataSource.java @@ -20,6 +20,7 @@ import org.thoughtcrime.securesms.database.model.ThreadRecord; import org.thoughtcrime.securesms.dependencies.ApplicationDependencies; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.recipients.Recipient; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.ThrottledDebouncer; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; import org.thoughtcrime.securesms.util.paging.Invalidator; @@ -30,6 +31,7 @@ import java.util.LinkedList; import java.util.List; import java.util.concurrent.Executor; +@Trace abstract class ConversationListDataSource extends PositionalDataSource { public static final Executor EXECUTOR = SignalExecutors.newFixedLifoThreadExecutor("signal-conversation-list", 1, 1); diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java index 31687a061..4e59de9a9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversationlist/ConversationListFragment.java @@ -116,6 +116,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.service.KeyCachingService; import org.thoughtcrime.securesms.sms.MessageSender; import org.thoughtcrime.securesms.storage.StorageSyncHelper; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.AvatarUtil; import org.thoughtcrime.securesms.util.PlayStoreUtil; import org.thoughtcrime.securesms.util.ServiceUtil; @@ -140,6 +141,7 @@ import java.util.Set; import static android.app.Activity.RESULT_OK; +@Trace public class ConversationListFragment extends MainFragment implements ActionMode.Callback, ConversationListAdapter.OnConversationClickListener, ConversationListSearchAdapter.EventListener, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java index b17fb234c..a4d56e0a2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/AttachmentDatabase.java @@ -54,6 +54,7 @@ import org.thoughtcrime.securesms.mms.MediaStream; import org.thoughtcrime.securesms.mms.MmsException; import org.thoughtcrime.securesms.mms.PartAuthority; import org.thoughtcrime.securesms.stickers.StickerLocator; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.CursorUtil; import org.thoughtcrime.securesms.util.FileUtils; @@ -83,6 +84,7 @@ import java.util.Locale; import java.util.Map; import java.util.Set; +@Trace public class AttachmentDatabase extends Database { private static final String TAG = AttachmentDatabase.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DraftDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/DraftDatabase.java index bda4de1bd..034790dea 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/DraftDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/DraftDatabase.java @@ -12,11 +12,13 @@ import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; +import org.thoughtcrime.securesms.tracing.Trace; import java.util.LinkedList; import java.util.List; import java.util.Set; +@Trace public class DraftDatabase extends Database { static final String TABLE_NAME = "drafts"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java index 35da2372f..4b2fa472d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupDatabase.java @@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.groups.GroupId; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.CursorUtil; import org.thoughtcrime.securesms.util.SqlUtil; import org.whispersystems.libsignal.util.guava.Optional; @@ -46,6 +47,7 @@ import java.util.List; import java.util.Locale; import java.util.UUID; +@Trace public final class GroupDatabase extends Database { private static final String TAG = Log.tag(GroupDatabase.class); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/GroupReceiptDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/GroupReceiptDatabase.java index 4fb767f78..d2e33ddf8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/GroupReceiptDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/GroupReceiptDatabase.java @@ -11,12 +11,14 @@ import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.tracing.Trace; import org.whispersystems.libsignal.util.Pair; import java.util.Collection; import java.util.LinkedList; import java.util.List; +@Trace public class GroupReceiptDatabase extends Database { public static final String TABLE_NAME = "group_receipts"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/IdentityDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/IdentityDatabase.java index 835637775..ddce2bee3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/IdentityDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/IdentityDatabase.java @@ -30,6 +30,7 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.database.identity.IdentityRecordList; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.IdentityUtil; import org.whispersystems.libsignal.IdentityKey; @@ -40,6 +41,7 @@ import java.io.IOException; import java.util.LinkedList; import java.util.List; +@Trace public class IdentityDatabase extends Database { @SuppressWarnings("unused") diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java index 825536955..9c8e9fbf3 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/JobDatabase.java @@ -14,10 +14,12 @@ import org.thoughtcrime.securesms.jobmanager.persistence.ConstraintSpec; import org.thoughtcrime.securesms.jobmanager.persistence.DependencySpec; import org.thoughtcrime.securesms.jobmanager.persistence.FullSpec; import org.thoughtcrime.securesms.jobmanager.persistence.JobSpec; +import org.thoughtcrime.securesms.tracing.Trace; import java.util.LinkedList; import java.util.List; +@Trace public class JobDatabase extends Database { public static String JOBS_TABLE_NAME = "job_spec"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/KeyValueDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/KeyValueDatabase.java index 742ac7dc0..81bb9d0ad 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/KeyValueDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/KeyValueDatabase.java @@ -10,10 +10,12 @@ import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.keyvalue.KeyValueDataSet; +import org.thoughtcrime.securesms.tracing.Trace; import java.util.Collection; import java.util.Map; +@Trace public class KeyValueDatabase extends Database { public static final String TABLE_NAME = "key_value"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MediaDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MediaDatabase.java index 57e4d114c..f70ce897b 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MediaDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MediaDatabase.java @@ -12,10 +12,12 @@ import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.attachments.DatabaseAttachment; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.MediaUtil; import java.util.List; +@Trace public class MediaDatabase extends Database { public static final int ALL_THREADS = -1; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MegaphoneDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MegaphoneDatabase.java index ae7cfb5fd..e52cf1c6e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MegaphoneDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MegaphoneDatabase.java @@ -12,6 +12,7 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.database.model.MegaphoneRecord; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.megaphone.Megaphones.Event; +import org.thoughtcrime.securesms.tracing.Trace; import java.util.ArrayList; import java.util.Collection; @@ -22,6 +23,7 @@ import java.util.Set; /** * IMPORTANT: Writes should only be made through {@link org.thoughtcrime.securesms.megaphone.MegaphoneRepository}. */ +@Trace public class MegaphoneDatabase extends Database { private static final String TAG = Log.tag(MegaphoneDatabase.class); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MentionDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MentionDatabase.java index 0bbc54a74..e6d27e37e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MentionDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MentionDatabase.java @@ -15,6 +15,7 @@ import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.database.model.Mention; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.CursorUtil; import org.thoughtcrime.securesms.util.SqlUtil; @@ -24,6 +25,7 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; +@Trace public class MentionDatabase extends Database { static final String TABLE_NAME = "mention"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java index c8643e5a3..ff1f74677 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -72,6 +72,7 @@ import org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo; import org.thoughtcrime.securesms.revealable.ViewOnceUtil; import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.CursorUtil; import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.SqlUtil; @@ -94,6 +95,7 @@ import java.util.Set; import static org.thoughtcrime.securesms.contactshare.Contact.Avatar; +@Trace public class MmsDatabase extends MessageDatabase { private static final String TAG = MmsDatabase.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java index 9252d358f..c0e16f7df 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsSmsDatabase.java @@ -33,6 +33,7 @@ import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.tracing.Trace; import org.whispersystems.libsignal.util.Pair; import java.io.Closeable; @@ -41,6 +42,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +@Trace public class MmsSmsDatabase extends Database { @SuppressWarnings("unused") diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/PushDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/PushDatabase.java index 1a9d1d0f3..8d5708ddb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/PushDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/PushDatabase.java @@ -10,6 +10,7 @@ import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.Base64; import org.whispersystems.libsignal.util.guava.Optional; import org.whispersystems.signalservice.api.messages.SignalServiceEnvelope; @@ -18,6 +19,7 @@ import org.whispersystems.signalservice.internal.util.Util; import java.io.IOException; +@Trace public class PushDatabase extends Database { private static final String TAG = PushDatabase.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java index 0b5bb0e41..a50c2735f 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java @@ -41,6 +41,7 @@ import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.storage.StorageSyncHelper; import org.thoughtcrime.securesms.storage.StorageSyncHelper.RecordUpdate; import org.thoughtcrime.securesms.storage.StorageSyncModels; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.Bitmask; import org.thoughtcrime.securesms.util.CursorUtil; @@ -80,6 +81,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; +@Trace public class RecipientDatabase extends Database { private static final String TAG = RecipientDatabase.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RemappedRecordsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/RemappedRecordsDatabase.java index 7757f36e6..f2353f6d2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/RemappedRecordsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/RemappedRecordsDatabase.java @@ -10,6 +10,7 @@ import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.CursorUtil; import java.util.HashMap; @@ -20,6 +21,7 @@ import java.util.Map; /** * The backing datastore for {@link RemappedRecords}. See that class for more details. */ +@Trace public class RemappedRecordsDatabase extends Database { public static final String[] CREATE_TABLE = { Recipients.CREATE_TABLE, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SearchDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SearchDatabase.java index 285a74e9e..a874e8d66 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SearchDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SearchDatabase.java @@ -11,10 +11,12 @@ import net.sqlcipher.Cursor; import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; +import org.thoughtcrime.securesms.tracing.Trace; /** * Contains all databases necessary for full-text search (FTS). */ +@Trace public class SearchDatabase extends Database { public static final String SMS_FTS_TABLE_NAME = "sms_fts"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SessionDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SessionDatabase.java index 751e1055c..3045094a4 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SessionDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SessionDatabase.java @@ -12,6 +12,7 @@ import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.SqlUtil; import org.whispersystems.libsignal.state.SessionRecord; import org.whispersystems.signalservice.api.push.SignalServiceAddress; @@ -20,6 +21,7 @@ import java.io.IOException; import java.util.LinkedList; import java.util.List; +@Trace public class SessionDatabase extends Database { private static final String TAG = SessionDatabase.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyDatabase.java index 810cb54c7..f180bbde9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SignedPreKeyDatabase.java @@ -11,6 +11,7 @@ import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; import org.thoughtcrime.securesms.logging.Log; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.Base64; import org.whispersystems.libsignal.InvalidKeyException; import org.whispersystems.libsignal.ecc.Curve; @@ -23,6 +24,7 @@ import java.io.IOException; import java.util.LinkedList; import java.util.List; +@Trace public class SignedPreKeyDatabase extends Database { private static final String TAG = SignedPreKeyDatabase.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java index 8e457c213..d8a1c539e 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/SmsDatabase.java @@ -51,6 +51,7 @@ import org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo; import org.thoughtcrime.securesms.sms.IncomingGroupUpdateMessage; import org.thoughtcrime.securesms.sms.IncomingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.SqlUtil; @@ -74,6 +75,7 @@ import java.util.Set; * * @author Moxie Marlinspike */ +@Trace public class SmsDatabase extends MessageDatabase { private static final String TAG = SmsDatabase.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/StickerDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/StickerDatabase.java index 7edcc1e0e..c03d3dc38 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/StickerDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/StickerDatabase.java @@ -23,6 +23,7 @@ import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri; import org.thoughtcrime.securesms.stickers.BlessedPacks; import org.thoughtcrime.securesms.stickers.StickerPackInstallEvent; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.CursorUtil; import org.thoughtcrime.securesms.util.SqlUtil; import org.thoughtcrime.securesms.util.Util; @@ -36,6 +37,7 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +@Trace public class StickerDatabase extends Database { private static final String TAG = Log.tag(StickerDatabase.class); diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/StorageKeyDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/StorageKeyDatabase.java index c94fae16b..3ebe79c81 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/StorageKeyDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/StorageKeyDatabase.java @@ -10,6 +10,7 @@ import androidx.annotation.Nullable; import net.sqlcipher.database.SQLiteDatabase; import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.Base64; import org.whispersystems.signalservice.api.storage.SignalStorageRecord; import org.whispersystems.signalservice.api.storage.StorageId; @@ -23,6 +24,7 @@ import java.util.List; * A list of storage keys whose types we do not currently have syncing logic for. We need to * remember that these keys exist so that we don't blast any data away. */ +@Trace public class StorageKeyDatabase extends Database { private static final String TABLE_NAME = "storage_key"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java index 57d035bf5..6bb50588d 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -52,6 +52,7 @@ import org.thoughtcrime.securesms.recipients.RecipientDetails; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.storage.StorageSyncHelper; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.CursorUtil; import org.thoughtcrime.securesms.util.JsonUtils; import org.thoughtcrime.securesms.util.SqlUtil; @@ -76,6 +77,7 @@ import java.util.Map; import java.util.Objects; import java.util.Set; +@Trace public class ThreadDatabase extends Database { private static final String TAG = ThreadDatabase.class.getSimpleName(); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptMessageJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptMessageJob.java index e87cef64d..2db5f39cb 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptMessageJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushDecryptMessageJob.java @@ -36,6 +36,7 @@ import org.thoughtcrime.securesms.jobmanager.Job; import org.thoughtcrime.securesms.jobmanager.JobManager; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.notifications.NotificationChannels; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -51,6 +52,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +@Trace public final class PushDecryptMessageJob extends BaseJob { public static final String KEY = "PushDecryptJob"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java index d549ba51e..347470097 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushGroupSendJob.java @@ -38,6 +38,7 @@ import org.thoughtcrime.securesms.mms.OutgoingMediaMessage; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.transport.UndeliverableMessageException; import org.thoughtcrime.securesms.util.FeatureFlags; @@ -69,6 +70,7 @@ import java.util.Set; import java.util.UUID; import java.util.concurrent.TimeUnit; +@Trace public final class PushGroupSendJob extends PushSendJob { public static final String KEY = "PushGroupSendJob"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java index 8334e5d1a..6c7c6c0dc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushMediaSendJob.java @@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.service.ExpiringMessageManager; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.transport.UndeliverableMessageException; @@ -48,6 +49,7 @@ import java.io.IOException; import java.util.List; import java.util.Set; +@Trace public class PushMediaSendJob extends PushSendJob { public static final String KEY = "PushMediaSendJob"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java index b110fd4cd..faa398ac9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java @@ -81,6 +81,7 @@ import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.stickers.StickerLocator; import org.thoughtcrime.securesms.storage.StorageSyncHelper; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.GroupUtil; import org.thoughtcrime.securesms.util.Hex; @@ -133,6 +134,7 @@ import java.util.Map; import java.util.Objects; import java.util.concurrent.TimeUnit; +@Trace public final class PushProcessMessageJob extends BaseJob { public static final String KEY = "PushProcessJob"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java index b07054349..c961af1bd 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushTextSendJob.java @@ -18,6 +18,7 @@ import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; import org.thoughtcrime.securesms.service.ExpiringMessageManager; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.transport.InsecureFallbackApprovalException; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -33,6 +34,7 @@ import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserExce import java.io.IOException; +@Trace public class PushTextSendJob extends PushSendJob { public static final String KEY = "PushTextSendJob"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java index a6b7c3092..632914166 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/RetrieveProfileJob.java @@ -29,6 +29,7 @@ import org.thoughtcrime.securesms.profiles.ProfileName; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; import org.thoughtcrime.securesms.recipients.RecipientUtil; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.IdentityUtil; @@ -66,6 +67,7 @@ import java.util.concurrent.TimeoutException; /** * Retrieves a users profile and sets the appropriate local fields. */ +@Trace public class RetrieveProfileJob extends BaseJob { public static final String KEY = "RetrieveProfileJob"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/StorageSyncJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/StorageSyncJob.java index a4abe45fc..af749b493 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/StorageSyncJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/StorageSyncJob.java @@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.storage.StorageSyncHelper.MergeResult; import org.thoughtcrime.securesms.storage.StorageSyncHelper.WriteOperationResult; import org.thoughtcrime.securesms.storage.StorageSyncModels; import org.thoughtcrime.securesms.storage.StorageSyncValidations; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.transport.RetryLaterException; import org.thoughtcrime.securesms.util.FeatureFlags; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -56,6 +57,7 @@ import java.util.concurrent.TimeUnit; * This should be performed whenever a change is made locally, or whenever we want to retrieve * changes that have been made remotely. */ +@Trace public class StorageSyncJob extends BaseJob { public static final String KEY = "StorageSyncJob"; diff --git a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionTrace.java b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionTrace.java new file mode 100644 index 000000000..4441b4fe3 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/LogSectionTrace.java @@ -0,0 +1,38 @@ +package org.thoughtcrime.securesms.logsubmit; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import org.thoughtcrime.securesms.tracing.Tracer; +import org.thoughtcrime.securesms.util.Base64; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.zip.GZIPOutputStream; + +public class LogSectionTrace implements LogSection { + + @Override + public @NonNull String getTitle() { + return "TRACE"; + } + + @Override + public @NonNull CharSequence getContent(@NonNull Context context) { + try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + GZIPOutputStream compressedStream = new GZIPOutputStream(outputStream)) + { + compressedStream.write(Tracer.getInstance().serialize()); + compressedStream.flush(); + compressedStream.close(); + + outputStream.flush(); + outputStream.close(); + + return Base64.encodeBytes(outputStream.toByteArray()); + } catch (IOException e) { + return ""; + } + } +} diff --git a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogAdapter.java index 4436043fd..8a7897e12 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogAdapter.java @@ -23,6 +23,8 @@ import java.util.concurrent.CopyOnWriteArrayList; public class SubmitDebugLogAdapter extends RecyclerView.Adapter { + private static final int MAX_LINE_LENGTH = 1000; + private final List lines; private final ScrollManager scrollManager; private final Listener listener; @@ -68,6 +70,7 @@ public class SubmitDebugLogAdapter extends RecyclerView.Adapter Math.max(currentMax, line.getText().length())); + this.longestLine = Math.min(longestLine, MAX_LINE_LENGTH); notifyDataSetChanged(); } @@ -122,7 +125,9 @@ public class SubmitDebugLogAdapter extends RecyclerView.Adapter longestLine) { + text.setText(line.getText().substring(0, longestLine)); + } else if (line.getText().length() < longestLine) { text.setText(padRight(line.getText(), longestLine)); } else { text.setText(line.getText()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogRepository.java b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogRepository.java index 41520f03e..60c18dc59 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/logsubmit/SubmitDebugLogRepository.java @@ -15,6 +15,7 @@ import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.logsubmit.util.Scrubber; import org.thoughtcrime.securesms.net.StandardUserAgentInterceptor; import org.thoughtcrime.securesms.push.SignalServiceNetworkAccess; +import org.thoughtcrime.securesms.tracing.Tracer; import org.thoughtcrime.securesms.util.concurrent.SignalExecutors; import org.whispersystems.libsignal.util.guava.Optional; @@ -60,6 +61,9 @@ public class SubmitDebugLogRepository { add(new LogSectionCapabilities()); add(new LogSectionFeatureFlags()); add(new LogSectionPermissions()); + if (Tracer.getInstance().isEnabled()) { + add(new LogSectionTrace()); + } add(new LogSectionThreads()); add(new LogSectionLogcat()); add(new LogSectionLogger()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java index 728d03132..a6542cd97 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java +++ b/app/src/main/java/org/thoughtcrime/securesms/mediasend/CameraXFragment.java @@ -389,6 +389,7 @@ public class CameraXFragment extends LoggingFragment implements CameraFragment { } } + @SuppressLint({"MissingPermission"}) private void initializeFlipButton(@NonNull View flipButton, @NonNull CameraXFlashToggleView flashButton) { if (camera.hasCameraWithLensFacing(CameraSelector.LENS_FACING_FRONT) && camera.hasCameraWithLensFacing(CameraSelector.LENS_FACING_BACK)) { flipButton.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.java b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.java index c87cfd949..080de2c63 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.java +++ b/app/src/main/java/org/thoughtcrime/securesms/storage/StorageSyncHelper.java @@ -21,6 +21,7 @@ import org.thoughtcrime.securesms.keyvalue.SignalStore; import org.thoughtcrime.securesms.logging.Log; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientId; +import org.thoughtcrime.securesms.tracing.Trace; import org.thoughtcrime.securesms.util.Base64; import org.thoughtcrime.securesms.util.SetUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; @@ -52,6 +53,7 @@ import java.util.Objects; import java.util.Set; import java.util.concurrent.TimeUnit; +@Trace public final class StorageSyncHelper { private static final String TAG = Log.tag(StorageSyncHelper.class); diff --git a/app/src/main/java/org/thoughtcrime/securesms/tracing/Trace.java b/app/src/main/java/org/thoughtcrime/securesms/tracing/Trace.java new file mode 100644 index 000000000..ad5cab43a --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/tracing/Trace.java @@ -0,0 +1,14 @@ +package org.thoughtcrime.securesms.tracing; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.CONSTRUCTOR; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.CLASS; + +@Target({TYPE, METHOD, CONSTRUCTOR}) @Retention(CLASS) +public @interface Trace { +} + diff --git a/app/src/main/java/org/thoughtcrime/securesms/tracing/Tracer.java b/app/src/main/java/org/thoughtcrime/securesms/tracing/Tracer.java new file mode 100644 index 000000000..83e8c2157 --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/tracing/Tracer.java @@ -0,0 +1,45 @@ +package org.thoughtcrime.securesms.tracing; + +import androidx.annotation.NonNull; + +/** + * A class to create Perfetto-compatible traces. + */ +public interface Tracer { + + TracerImpl INSTANCE = new TracerImpl(); + + static @NonNull Tracer getInstance() { + return INSTANCE; + } + + /** + * True if enabled, otherwise false. + */ + boolean isEnabled(); + + /** + * Marks the start of a method call. Always follow this with a call to {@link #end(String)}. + */ + void start(@NonNull String methodName); + + /** + * Marks the start of a method call. Always follow this with a call to {@link #end(String)}. + * + * Includes the ability to pass a key-value pair that will be shown in the trace when you click + * on the slice. + */ + void start(@NonNull String methodName, @NonNull String key, @NonNull String value); + + /** + * Marks the end of a method call. + */ + void end(@NonNull String methodName); + + /** + * Serializes the current state of the trace to a Perfetto-compatible byte array. Note that + * there's no locking here, and therefore tracing will continue. We're just grabbing a best-effort + * snapshot. + */ + @NonNull byte[] serialize(); +} diff --git a/app/src/play/java/org/thoughtcrime/securesms/tracing/TracerImpl.java b/app/src/play/java/org/thoughtcrime/securesms/tracing/TracerImpl.java new file mode 100644 index 000000000..b356f7a31 --- /dev/null +++ b/app/src/play/java/org/thoughtcrime/securesms/tracing/TracerImpl.java @@ -0,0 +1,34 @@ +package org.thoughtcrime.securesms.tracing; + +import androidx.annotation.NonNull; + +/** + * Dummy implementation. + */ +final class TracerImpl implements Tracer { + + @Override + public boolean isEnabled() { + return false; + } + + @Override + public void start(@NonNull String methodName) { + throw new UnsupportedOperationException(); + } + + @Override + public void start(@NonNull String methodName, @NonNull String key, @NonNull String value) { + throw new UnsupportedOperationException(); + } + + @Override + public void end(@NonNull String methodName) { + throw new UnsupportedOperationException(); + } + + @Override + public @NonNull byte[] serialize() { + throw new UnsupportedOperationException(); + } +} diff --git a/app/src/website/java/org/thoughtcrime/securesms/tracing/TracerImpl.java b/app/src/website/java/org/thoughtcrime/securesms/tracing/TracerImpl.java new file mode 100644 index 000000000..b356f7a31 --- /dev/null +++ b/app/src/website/java/org/thoughtcrime/securesms/tracing/TracerImpl.java @@ -0,0 +1,34 @@ +package org.thoughtcrime.securesms.tracing; + +import androidx.annotation.NonNull; + +/** + * Dummy implementation. + */ +final class TracerImpl implements Tracer { + + @Override + public boolean isEnabled() { + return false; + } + + @Override + public void start(@NonNull String methodName) { + throw new UnsupportedOperationException(); + } + + @Override + public void start(@NonNull String methodName, @NonNull String key, @NonNull String value) { + throw new UnsupportedOperationException(); + } + + @Override + public void end(@NonNull String methodName) { + throw new UnsupportedOperationException(); + } + + @Override + public @NonNull byte[] serialize() { + throw new UnsupportedOperationException(); + } +}