Skip to content

feat(W-23159744): per-user persistent feature flags (Android)#2937

Open
wmathurin wants to merge 2 commits into
forcedotcom:devfrom
wmathurin:W-21167151-feature-flags-per-user
Open

feat(W-23159744): per-user persistent feature flags (Android)#2937
wmathurin wants to merge 2 commits into
forcedotcom:devfrom
wmathurin:W-21167151-feature-flags-per-user

Conversation

@wmathurin

Copy link
Copy Markdown
Contributor

Summary

  • Adds featureFlags field to UserAccount (Set), serialized to JSON and persisted via AccountManager as an encrypted comma-separated string under KEY_FEATURE_FLAGS
  • SalesforceSDKManager gains per-user overloads for registerUsedAppFeature/unregisterUsedAppFeature, getUserAgent(qualifier, user) (returns global ∪ per-user union), isGlobalFeatureRegistered(), and hydratePerUserFeatures() called from init
  • LoginActivity: completedViaBrowserTab flag captures Custom Tab completion for both regular browser login and Login for Admin; onAuthFlowSuccess promotes BW/WD/QR flags to per-user
  • BA/SL flags in AuthenticationUtilities registered per-user; SU in SmartStoreSDKManager; MS/Layout/Metadata in their respective sync managers
  • SalesforceHybridSDKManager adds getUserAgent(qualifier, user) override
  • New unit tests in UserAccountTest and SalesforceSDKManagerTests

GUS Stories

  • W-23159744 (Android per-user feature flags)
  • W-21167151 (spike)

Test plan

  • ./gradlew :libs:SalesforceSDK:assembleAndroidTest — BUILD SUCCESSFUL
  • ./gradlew :libs:SalesforceSDK:testDebugUnitTest — BUILD SUCCESSFUL
  • ./gradlew :libs:SalesforceSDK:lint — BUILD SUCCESSFUL (no new warnings)
  • All libraries compile: SalesforceSDK, SmartStore, MobileSync, SalesforceHybrid
  • Instrumented tests (connectedAndroidTest) — require connected device/emulator, run in CI

Implements per-user feature flag storage and hydration so each
user account's active features are accurately reflected in the
User-Agent string across app restarts.

- UserAccount: featureFlags field (Set<String>), serialized to JSON,
  persisted via AccountManager (KEY_FEATURE_FLAGS, encrypted comma-separated)
- SalesforceSDKManager: perUserFeatures map (ConcurrentHashMap<String,ConcurrentSkipListSet>),
  getUserAgent(qualifier, user) unions global + per-user flags,
  registerUsedAppFeature/unregisterUsedAppFeature per-user overloads,
  hydratePerUserFeatures() called from init block,
  isGlobalFeatureRegistered() helper
- LoginActivity: completedViaBrowserTab flag captures Custom Tab completion
  (covers both regular and Login for Admin); onAuthFlowSuccess promotes
  BW/WD/QR transient global flags to per-user
- AuthenticationUtilities: BA/SL flags registered per-user
- SmartStoreSDKManager: SU flag registered per-user
- SyncManager/LayoutSyncManager/MetadataSyncManager: MS/Layout/Metadata flags per-user
- SalesforceHybridSDKManager: getUserAgent(qualifier, user) override
- UserAccountTest, SalesforceSDKManagerTests: new unit tests
@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
3 Warnings
⚠️ libs/SalesforceSDK/src/com/salesforce/androidsdk/accounts/UserAccountManager.java#L112 - Do not place Android context classes in static fields (static reference to UserAccountManager which has field context pointing to Context); this is a memory leak
⚠️ libs/SalesforceSDK/src/com/salesforce/androidsdk/auth/AuthenticatorService.java#L58 - Do not place Android context classes in static fields (static reference to Authenticator which has field context pointing to Context); this is a memory leak
⚠️ libs/SalesforceSDK/src/com/salesforce/androidsdk/ui/LoginActivity.kt#L710 - Switch statement on an int with known associated constant missing case BiometricManager.BIOMETRIC_ERROR_IDENTITY_CHECK_NOT_ACTIVE

Generated by 🚫 Danger

FEATURE_BROWSER_LOGIN must appear in the UA for requests made during
the login session. Register it globally in loadLoginPageInCustomTab()
(alongside completedViaBrowserTab = true), then clear global and
promote to per-user at onAuthFlowSuccess — matching the WD/QR pattern.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant