diff --git a/app/build.gradle b/app/build.gradle index d99e0baa71..d7a861d2ee 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -67,11 +67,13 @@ def selectableVariants = [ 'nightlyPnpRelease', 'playProdDebug', 'playProdSpinner', + 'playProdCanary', 'playProdPerf', 'playProdBenchmark', 'playProdInstrumentation', 'playProdRelease', 'playStagingDebug', + 'playStagingCanary', 'playStagingSpinner', 'playStagingPerf', 'playStagingInstrumentation', @@ -318,6 +320,14 @@ android { buildConfigField "String", "BUILD_VARIANT_TYPE", "\"Benchmark\"" buildConfigField "boolean", "TRACING_ENABLED", "true" } + + canary { + initWith debug + isDefault false + minifyEnabled false + matchingFallbacks = ['debug'] + buildConfigField "String", "BUILD_VARIANT_TYPE", "\"Canary\"" + } } productFlavors { @@ -559,7 +569,8 @@ dependencies { implementation libs.kotlinx.collections.immutable spinnerImplementation project(":spinner") - spinnerImplementation libs.square.leakcanary + + canaryImplementation libs.square.leakcanary testImplementation testLibs.junit.junit testImplementation testLibs.assertj.core diff --git a/app/src/canary/AndroidManifest.xml b/app/src/canary/AndroidManifest.xml new file mode 100644 index 0000000000..c48ea25565 --- /dev/null +++ b/app/src/canary/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/app/src/canary/java/org/thoughtcrime/securesms/CanaryApplicationContext.kt b/app/src/canary/java/org/thoughtcrime/securesms/CanaryApplicationContext.kt new file mode 100644 index 0000000000..c8c8b963c4 --- /dev/null +++ b/app/src/canary/java/org/thoughtcrime/securesms/CanaryApplicationContext.kt @@ -0,0 +1,65 @@ +package org.thoughtcrime.securesms + +import android.os.StrictMode +import android.os.StrictMode.ThreadPolicy +import leakcanary.LeakCanary +import shark.AndroidReferenceMatchers + +class CanaryApplicationContext : ApplicationContext() { + override fun onCreate() { + super.onCreate() + + StrictMode.setThreadPolicy( + ThreadPolicy.Builder() + .detectDiskReads() + .detectDiskWrites() + .detectNetwork() + .penaltyLog() + .build() + ) + + try { + Class.forName("dalvik.system.CloseGuard") + .getMethod("setEnabled", Boolean::class.javaPrimitiveType) + .invoke(null, true) + } catch (e: ReflectiveOperationException) { + throw RuntimeException(e) + } + + LeakCanary.config = LeakCanary.config.copy( + referenceMatchers = AndroidReferenceMatchers.appDefaults + + AndroidReferenceMatchers.ignoredInstanceField( + className = "android.service.media.MediaBrowserService\$ServiceBinder", + fieldName = "this\$0" + ) + + AndroidReferenceMatchers.ignoredInstanceField( + className = "androidx.media.MediaBrowserServiceCompat\$MediaBrowserServiceImplApi26\$MediaBrowserServiceApi26", + fieldName = "mBase" + ) + + AndroidReferenceMatchers.ignoredInstanceField( + className = "android.support.v4.media.MediaBrowserCompat", + fieldName = "mImpl" + ) + + AndroidReferenceMatchers.ignoredInstanceField( + className = "android.support.v4.media.session.MediaControllerCompat", + fieldName = "mToken" + ) + + AndroidReferenceMatchers.ignoredInstanceField( + className = "android.support.v4.media.session.MediaControllerCompat", + fieldName = "mImpl" + ) + + AndroidReferenceMatchers.ignoredInstanceField( + className = "org.thoughtcrime.securesms.components.voice.VoiceNotePlaybackService", + fieldName = "mApplication" + ) + + AndroidReferenceMatchers.ignoredInstanceField( + className = "org.thoughtcrime.securesms.service.GenericForegroundService\$LocalBinder", + fieldName = "this\$0" + ) + + AndroidReferenceMatchers.ignoredInstanceField( + className = "org.thoughtcrime.securesms.contacts.ContactsSyncAdapter", + fieldName = "mContext" + ) + ) + } +} diff --git a/app/src/spinner/java/org/thoughtcrime/securesms/SpinnerApplicationContext.kt b/app/src/spinner/java/org/thoughtcrime/securesms/SpinnerApplicationContext.kt index 3efb4dc37e..2ca32db998 100644 --- a/app/src/spinner/java/org/thoughtcrime/securesms/SpinnerApplicationContext.kt +++ b/app/src/spinner/java/org/thoughtcrime/securesms/SpinnerApplicationContext.kt @@ -2,9 +2,6 @@ package org.thoughtcrime.securesms import android.content.ContentValues import android.os.Build -import android.os.StrictMode -import android.os.StrictMode.ThreadPolicy -import leakcanary.LeakCanary import org.signal.spinner.Spinner import org.signal.spinner.Spinner.DatabaseConfig import org.thoughtcrime.securesms.database.DatabaseMonitor @@ -24,22 +21,12 @@ import org.thoughtcrime.securesms.database.TimestampTransformer import org.thoughtcrime.securesms.keyvalue.SignalStore import org.thoughtcrime.securesms.recipients.Recipient import org.thoughtcrime.securesms.util.AppSignatureUtil -import shark.AndroidReferenceMatchers import java.util.Locale class SpinnerApplicationContext : ApplicationContext() { override fun onCreate() { super.onCreate() - StrictMode.setThreadPolicy( - ThreadPolicy.Builder() - .detectDiskReads() - .detectDiskWrites() - .detectNetwork() - .penaltyLog() - .build() - ) - try { Class.forName("dalvik.system.CloseGuard") .getMethod("setEnabled", Boolean::class.javaPrimitiveType) @@ -93,41 +80,5 @@ class SpinnerApplicationContext : ApplicationContext() { Spinner.onUpdate("signal", table, values, selection, args) } }) - - LeakCanary.config = LeakCanary.config.copy( - referenceMatchers = AndroidReferenceMatchers.appDefaults + - AndroidReferenceMatchers.ignoredInstanceField( - className = "android.service.media.MediaBrowserService\$ServiceBinder", - fieldName = "this\$0" - ) + - AndroidReferenceMatchers.ignoredInstanceField( - className = "androidx.media.MediaBrowserServiceCompat\$MediaBrowserServiceImplApi26\$MediaBrowserServiceApi26", - fieldName = "mBase" - ) + - AndroidReferenceMatchers.ignoredInstanceField( - className = "android.support.v4.media.MediaBrowserCompat", - fieldName = "mImpl" - ) + - AndroidReferenceMatchers.ignoredInstanceField( - className = "android.support.v4.media.session.MediaControllerCompat", - fieldName = "mToken" - ) + - AndroidReferenceMatchers.ignoredInstanceField( - className = "android.support.v4.media.session.MediaControllerCompat", - fieldName = "mImpl" - ) + - AndroidReferenceMatchers.ignoredInstanceField( - className = "org.thoughtcrime.securesms.components.voice.VoiceNotePlaybackService", - fieldName = "mApplication" - ) + - AndroidReferenceMatchers.ignoredInstanceField( - className = "org.thoughtcrime.securesms.service.GenericForegroundService\$LocalBinder", - fieldName = "this\$0" - ) + - AndroidReferenceMatchers.ignoredInstanceField( - className = "org.thoughtcrime.securesms.contacts.ContactsSyncAdapter", - fieldName = "mContext" - ) - ) } }