fix: [SDK-4753] narrow overly broad consumer ProGuard/R8 keep rules#2679
Open
abdulraqeeb33 wants to merge 3 commits into
Open
fix: [SDK-4753] narrow overly broad consumer ProGuard/R8 keep rules#2679abdulraqeeb33 wants to merge 3 commits into
abdulraqeeb33 wants to merge 3 commits into
Conversation
The R8 Configuration Analyzer flagged OneSignal's consumer keep rules as
top contributors of broad -keep directives in consuming apps. The whole-package
"-keepclassmembers class com.onesignal.<pkg>.** { *; }" rules blocked R8 from
obfuscating and member-shrinking nearly the entire SDK.
Replace them with targeted rules that protect only what is reached reflectively:
- service impl constructors (ServiceRegistrationReflection)
- Model getters matched by name in Model.initializeFromJson (kept un-obfuscated)
- IModule impls loaded by FQN string (name + no-arg ctor)
- NSE class named in manifest meta-data and instantiated via newInstance
- shortcut-badger no-arg constructors
Narrow (not delete) the risky ADM handler and JobIntentService shim rules to
constructor-only. Delete stale FCM FirebaseInstanceId/GoogleApiClient keeps and
the consumer observer keeps (no main-source references); these need R8 full-mode
validation. Remove dead/blanket -dontwarn lines.
Co-authored-by: Cursor <cursoragent@cursor.com>
… prevent release-only R8 regressions
2382068 to
4e5953d
Compare
…ei release build The narrowed consumer keep rules left PushRegistratorFCM's direct references to com.google.firebase.* (FirebaseApp/FirebaseOptions/FirebaseMessaging) reachable at R8 time. Huawei-only apps exclude com.google.firebase:firebase-messaging, so those classes are absent and :app:minifyHuaweiReleaseWithR8 fails with "Missing classes detected while running R8". Add -dontwarn com.google.firebase.** to the notifications consumer rules, mirroring the existing optional-provider suppressions for HMS (com.huawei.**) and ADM (com.amazon.**). No-op for GMS builds where Firebase is present. Co-authored-by: Cursor <cursoragent@cursor.com>
Contributor
📊 Diff Coverage Report✓ Coverage check passed (no source files changed) |
Contributor
|
One release-risk item to address before merge: the PR deletes the |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
A developer ran Android's R8 Configuration Analyzer on their app and found that 3 of the top 5 sources of the broadest
-keeprules in their final app came from OneSignal (reported againstcore-5.9.2). Our consumer rules shipped whole-package member keeps like:These keep all members of all classes across nearly the entire SDK, blocking R8 from obfuscating and member-shrinking consumer apps that depend on OneSignal.
What changed (per module)
core/consumer-rules.pro
-keepclassmembers class com.onesignal.{core,session,user,internal,debug,common}.** { *; }rules.com.onesignal.**(service impls are instantiated via reflective constructor selection inServiceRegistrationReflection).Modelgetter keep withoutallowobfuscation(*** get*();+*** is*();) —Model.initializeFromJsonmatches getter method names via reflection, so getters must keep their names.IModulerule from{ *; }to{ <init>(); }(modules are loaded by FQN string viaClass.forName(...).newInstance()).@KeepStubconstructor rule as-is.-dontwarn com.amazon.**; removed the blanket-dontwarn com.onesignal.**.notifications/consumer-rules.pro
-keepclassmembers class com.onesignal.notifications.** { *; }with a constructor-only keep.<init>()(resolved by name from manifest<meta-data>andnewInstance()d).implements Badger { <init>(...); }rule.InputMergerrules.-dontwarn com.onesignal.notification.**(wrong package — the package isnotifications).ADMMessageHandler/ADMMessageHandlerJobandJobIntentService$*changed from{*;}to{ <init>(...); }.com.google.firebase.iid.FirebaseInstanceIdandcom.google.android.gms.common.api.GoogleApiClientkeeps and the three consumer observer keeps (IPermissionObserver,IPushSubscriptionObserver,IUserStateObserver) — no main-source references found (FCM now usesFirebaseMessaging; observers are invoked through their interfaces so R8 keeps reachable overrides automatically). See Validation needed below.in-app-messages/consumer-rules.pro
{ *; }with constructor-only keep; removed dead-dontwarn com.onesignal.iam.**.location/consumer-rules.pro
{ *; }with constructor-only keep; removed-dontwarn com.onesignal.location.**.otel/consumer-rules.pro — no change (only
-dontwarnfor optional Jackson/AutoValue; no shrinking impact).Narrowed vs deleted
JobIntentService$*;IModule.FirebaseInstanceId/GoogleApiClientkeeps; the three observer keeps.Build
./gradlew :onesignal:core:assemble :onesignal:notifications:assemble :onesignal:in-app-messages:assemble :onesignal:location:assemble :onesignal:otel:assemble→ BUILD SUCCESSFUL (consumer-rules are merged at build time; only pre-existing Kotlin warnings remain). Consumer ProGuard/R8 rules are ultimately validated at the consuming app's R8 step, hence the checklist below. Spotless/detekt run in CI but do not apply to.profiles.Validation needed (R8 full-mode sample-app smoke test)
Build a sample app with
android.enableR8.fullMode=true+minifyEnabled trueand verify:INotificationServiceExtension) resolved from manifest<meta-data>Model.initializeFromJsongetter-name reflection)IPermissionObserver,IPushSubscriptionObserver,IUserStateObserver)References
Do not merge until the R8 full-mode validation above is complete.
Made with Cursor