From c723777935e0783f1baca8d4f75165c526c21532 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Sun, 30 Aug 2026 15:10:46 -0400 Subject: [PATCH] perf(r8): keep exception names without keeping every exception -keep public class * extends java.lang.Throwable kept 972 classes whole. Only their names are load-bearing: the Coinbase onramp traces send `it::class.simpleName` as `errorType`, and Events.kt does the same for analytics. Those have become plain strings by the time they leave the device, so the Bugsnag mapping upload cannot repair them, which is why the rule cannot simply be deleted. Nothing reads the members, and an exception nothing constructs need not survive, so -keepnames is the rule that matches the requirement. Release R8 drops 341 classes and 455 members, and DEX falls 72,628 bytes (16,101,032 -> 16,028,404). The dropped classes are what the old rule was propping up: AddReactionError and its six subclasses go, because ChatMessagingService.addReaction has no caller outside tests and R8 had already shrunk it in both builds. CoinbaseOnRampApiError and GetJwtError subclass names are unchanged in the mapping. Also corrects two comments against what the code does. The AppRoute rule is not for analytics: annotatedEntry derives each screen's root test tag from the route's simple name via NavMetadata.screenRootTag, so obfuscating those renames the resource-ids the UI tests address. The com.kik.scan wildcard is load-bearing for JNI, which constructs those classes by name from C++ and reads their backing fields through GetFieldID. --- apps/flipcash/app/proguard-rules.pro | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/apps/flipcash/app/proguard-rules.pro b/apps/flipcash/app/proguard-rules.pro index c7f7cc14b..c9ac58d40 100644 --- a/apps/flipcash/app/proguard-rules.pro +++ b/apps/flipcash/app/proguard-rules.pro @@ -1,7 +1,9 @@ # Preserve source file names and line numbers for stack traces (call site tracking, Bugsnag) -keepattributes SourceFile,LineNumberTable -# Keep AppRoute class names for analytics screen tracking +# Keep AppRoute class names. `annotatedEntry` derives each screen's root test tag +# from the route's simple name (NavMetadata.screenRootTag), so obfuscating these +# renames every screen-root resource-id the UI tests address. -keepnames class com.flipcash.app.core.AppRoute -keepnames class com.flipcash.app.core.AppRoute$** @@ -15,7 +17,11 @@ -keep class * extends io.grpc.stub.AbstractStub { *; } -keep class * implements io.grpc.BindableService { *; } -# Keep our scan classes that interact with native +# Keep our scan classes that interact with native. The scanner's JNI constructs +# these from C++ by name (FindClass("com/kik/scan/UsernameKikCode"), GetMethodID +# for ) and reads their backing fields directly (GetFieldID for "_username", +# "nativePtr"), none of which AGP's default native-methods rule covers. Five +# classes, so the wildcard costs little. -keep class com.kik.scan.** { *; } -assumenosideeffects class android.util.Log { @@ -26,4 +32,10 @@ public static int e(...); } --keep public class * extends java.lang.Throwable +# Error telemetry reads exception names at runtime — Coinbase onramp traces send +# `it::class.simpleName` as `errorType`, and Events.kt does the same for analytics. +# Those are plain strings by the time they leave the device, so the Bugsnag mapping +# upload cannot repair them; the names have to survive obfuscation. Nothing reads +# the members, and an exception nothing throws need not survive, so this is +# -keepnames rather than a full keep. +-keepnames public class * extends java.lang.Throwable