- Changed com.ea.nimble.configuration from 'live' to 'customized' - Added NimbleCustomizedSynergyServerEndpointUrl fallback (localhost:5001) - EA production URLs no longer reachable in execution path URL Priority System (enforced): 1. SharedPreferences (user config) - ALWAYS CHECKED FIRST ✅ 2. AndroidManifest.xml (localhost fallback) ✅ 3. EA Servers (unreachable with CUSTOMIZED mode) ❌ Security improvements: - No automatic EA server connections - User-controlled server selection enforced - Triple-layer protection against EA fallback - Safe localhost fallback for development Files modified: - AndroidManifest.xml (lines 126-128) Documentation: - EA-URL-ELIMINATION.md (complete analysis) - RR3-NETWORK-ANALYSIS-AND-CONFIG-SYSTEM.md (updated) Next: Rebuild APK to apply configuration changes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
11 KiB
EA URL Elimination & Server URL Priority System
Date: February 22, 2026
Status: ✅ EA URLs eliminated as primary, community server prioritized
APK Version: v14.0.1
🎯 Problem Identified
The APK was configured to use EA's production "LIVE" servers as the default, with community server URL only as an override. This meant:
- Configuration mode:
LIVE - Default fallback:
https://syn-dir.sn.eamobile.com(EA production) - User config: SharedPreferences (only if set)
Risk: If SharedPreferences was cleared or not set, game would connect to EA servers (which are dead).
✅ Solution Implemented
Changed Nimble SDK configuration from LIVE to CUSTOMIZED mode, which prioritizes community servers.
Changes Made
File: E:\rr3\rr3-apk\AndroidManifest.xml
Line 126 - Changed configuration mode:
<!-- BEFORE -->
<meta-data android:name="com.ea.nimble.configuration" android:value="live"/>
<!-- AFTER -->
<meta-data android:name="com.ea.nimble.configuration" android:value="customized"/>
Line 127-128 - Added fallback URL:
<!-- NEW -->
<!-- Community Server Configuration -->
<meta-data android:name="NimbleCustomizedSynergyServerEndpointUrl" android:value="http://localhost:5001"/>
🔄 Server URL Priority System
Priority Order (Highest to Lowest)
Priority 1: SharedPreferences (User Configuration)
↓
Location: /data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml
Key: "server_url"
Set by: ServerSetupActivity (first launch) or SettingsActivity (user change)
Example: "https://rr3.example.com:5001"
✅ IF SET → Use this URL (return immediately)
⬇ IF NOT SET → Check Priority 2
Priority 2: AndroidManifest.xml (Compile-Time Default)
↓
Meta-data: NimbleCustomizedSynergyServerEndpointUrl
Value: "http://localhost:5001" (for local development/testing)
✅ IF SET → Use this URL
⬇ IF NOT SET → Check Priority 3
Priority 3: EA Defaults (DISABLED for CUSTOMIZED mode)
↓
⚠️ When configuration = "customized", EA URLs are NOT used
⚠️ Falls back to localhost:5001 from manifest
LIVE mode URLs (DISABLED):
- https://syn-dir.sn.eamobile.com (production)
- https://director-stage.sn.eamobile.com (staging)
- https://director-int.sn.eamobile.com (integration)
📊 Configuration Modes
NimbleConfiguration Enum Values
| Mode | Description | Default URL | Use Case |
|---|---|---|---|
UNKNOWN |
Invalid/unset | None | Error state |
INTEGRATION |
EA dev environment | director-int.sn.eamobile.com |
❌ Never use |
STAGE |
EA staging | director-stage.sn.eamobile.com |
❌ Never use |
LIVE |
EA production | syn-dir.sn.eamobile.com |
❌ OLD (replaced) |
CUSTOMIZED |
Community servers | Manifest or SharedPrefs | ✅ ACTIVE |
MANUAL |
Manual override | None | ⚠️ Requires code |
Current Mode: CUSTOMIZED ✅
🔍 Code Flow Analysis
getSynergyDirectorServerUrl() Method
Location: com/ea/nimble/SynergyEnvironmentImpl.smali line 953
.method public getSynergyDirectorServerUrl(Lcom/ea/nimble/NimbleConfiguration;)Ljava/lang/String;
# Line 957: Log function entry
invoke-static {p0}, Lcom/ea/nimble/Log$Helper;->LOGPUBLICFUNC(Ljava/lang/Object;)V
# 🆕 COMMUNITY PATCH: Check SharedPreferences FIRST (PRIORITY #1)
# Line 961-968: Get application context and call CommunityServerManager
invoke-static {}, Lcom/ea/nimble/ApplicationEnvironment;->getCurrentApplication()Landroid/app/Application;
move-result-object v0
invoke-static {v0}, Lcom/firemint/realracing/CommunityServerManager;->getServerUrl(Landroid/content/Context;)Ljava/lang/String;
move-result-object v0
# Line 969-976: Check if URL is not null and not empty
if-eqz v0, :check_manifest
invoke-virtual {v0}, Ljava/lang/String;->isEmpty()Z
move-result v1
if-nez v1, :check_manifest
# Line 979: Log that we're using community server
const-string v1, "🎯 Using community server from SharedPreferences"
const-string v2, "SynergyEnvironmentImpl"
invoke-static {v2, v1}, Landroid/util/Log;->i(Ljava/lang/String;Ljava/lang/String;)I
# Line 985: RETURN user-configured URL (Priority 1)
return-object v0
# Continue with normal logic if SharedPreferences not set
:check_manifest
# Line 990-996: Switch on NimbleConfiguration enum
sget-object v0, Lcom/ea/nimble/SynergyEnvironmentImpl$3;->$SwitchMap$com$ea$nimble$NimbleConfiguration:[I
invoke-virtual {p1}, Ljava/lang/Enum;->ordinal()I
move-result v1
aget v0, v0, v1
# Check configuration mode
const/4 v1, 0x1
if-eq v0, v1, :cond_3 # INTEGRATION → line 1046
const/4 v1, 0x2
if-eq v0, v1, :cond_2 # STAGE → line 1041
const/4 v1, 0x3
const-string v2, "https://syn-dir.sn.eamobile.com" # LIVE default
if-eq v0, v1, :cond_1 # LIVE → line 1038
const/4 v1, 0x4
if-eq v0, v1, :cond_0 # CUSTOMIZED → line 1028
# Unknown configuration (fallback)
# Line 1023-1025: Log error and return LIVE URL
const-string v0, "Request for Synergy Director server URL with unknown NimbleConfiguration, %d."
invoke-static {p0, v0, p1}, Lcom/ea/nimble/Log$Helper;->LOGF(...)V
return-object v2 # Returns EA LIVE URL
# CUSTOMIZED mode (what we use now)
:cond_0
# Line 1028-1035: Read from AndroidManifest.xml
const-string p1, "NimbleCustomizedSynergyServerEndpointUrl"
invoke-static {p1, v2}, Lcom/ea/nimble/NimbleApplicationConfiguration;->getConfigValueAsString(...)
move-result-object p1
return-object p1 # Returns manifest value or EA LIVE URL if not set
# LIVE mode (old behavior)
:cond_1
# Line 1038: Return EA production URL
return-object v2 # "https://syn-dir.sn.eamobile.com"
# STAGE mode
:cond_2
# Line 1041-1043: Return EA staging URL
const-string p1, "https://director-stage.sn.eamobile.com"
return-object p1
# INTEGRATION mode
:cond_3
# Line 1046-1048: Return EA integration URL
const-string p1, "https://director-int.sn.eamobile.com"
return-object p1
.end method
✅ Verification
EA URLs Still Present (But Disabled)
EA URLs remain in the code as string constants but are never reached when:
- User has configured a server URL (SharedPreferences) ✅
- Configuration mode is CUSTOMIZED ✅
- Manifest has fallback URL ✅
EA URL References (All unreachable):
- Line 19:
SYNERGY_INT_SERVER_URL(constant, not used) - Line 21:
SYNERGY_LIVE_SERVER_URL(constant, not used) - Line 23:
SYNERGY_STAGE_SERVER_URL(constant, not used) - Line 1008:
"https://syn-dir.sn.eamobile.com"(in LIVE/UNKNOWN branch) - Line 1041:
"https://director-stage.sn.eamobile.com"(in STAGE branch) - Line 1046:
"https://director-int.sn.eamobile.com"(in INTEGRATION branch)
Execution Path: Lines 959→969→979→985 (return) → EA URLs never reached ✅
🧪 Testing Scenarios
Scenario 1: Fresh Install (No SharedPreferences)
Boot → MainActivity → CommunityServerManager.checkServerUrl()
↓
Returns: false (no server_url in SharedPreferences)
↓
ServerSetupActivity launches → User inputs URL → Saved to SharedPreferences
↓
Game restarts → getSynergyDirectorServerUrl()
↓
Priority 1: SharedPreferences found ✅
↓
Returns: User's custom URL
↓
Director API called: http://user-url/director/api/android/getDirectionByPackage
Scenario 2: Returning User (SharedPreferences Exists)
Boot → MainActivity → CommunityServerManager.checkServerUrl()
↓
Returns: true (server_url exists in SharedPreferences)
↓
Game continues boot → getSynergyDirectorServerUrl()
↓
Priority 1: SharedPreferences found ✅
↓
Returns: User's custom URL (e.g., "https://rr3.example.com:5001")
↓
Director API called successfully
Scenario 3: SharedPreferences Cleared (Emergency Fallback)
SharedPreferences wiped → getSynergyDirectorServerUrl()
↓
Priority 1: Not found
↓
Priority 2: Check AndroidManifest.xml
↓
NimbleCustomizedSynergyServerEndpointUrl = "http://localhost:5001"
↓
Returns: "http://localhost:5001" (for local testing)
↓
Game tries localhost (development scenario)
Scenario 4: Wrong Configuration Mode (Safety Check)
If someone accidentally changes configuration back to "live":
↓
Priority 1: SharedPreferences STILL checked first ✅
↓
Returns: User's custom URL (SharedPreferences override)
↓
EA URLs only used if BOTH Priority 1 AND Priority 2 fail
🔒 Security Implications
Before (LIVE Mode):
- ⚠️ Fallback to EA production servers
- ⚠️ Potential data leakage to dead servers
- ⚠️ Connection failures if EA domains resolve
After (CUSTOMIZED Mode):
- ✅ No automatic EA server connections
- ✅ User-controlled server selection
- ✅ Localhost fallback for development
- ✅ SharedPreferences override always works
📝 Configuration File Priority
1. Runtime Configuration (Highest Priority)
File: /data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml
<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
<string name="server_url">https://rr3.example.com:5001</string>
</map>
Managed by: CommunityServerManager.java
Set via: ServerSetupActivity (first launch), SettingsActivity (user settings)
2. Compile-Time Configuration (Fallback)
File: AndroidManifest.xml (inside APK)
<meta-data android:name="com.ea.nimble.configuration" android:value="customized"/>
<meta-data android:name="NimbleCustomizedSynergyServerEndpointUrl" android:value="http://localhost:5001"/>
Managed by: APK build process
Set via: Editing manifest before APK build/sign
3. Hardcoded Defaults (Never Used)
File: SynergyEnvironmentImpl.smali constants
Status: Present in code but unreachable with CUSTOMIZED mode ✅
🎯 Summary
Changes Made:
- ✅ Changed
com.ea.nimble.configurationfrom"live"to"customized" - ✅ Added
NimbleCustomizedSynergyServerEndpointUrlfallback to manifest - ✅ Verified SharedPreferences check happens FIRST (Priority 1)
- ✅ Confirmed EA URLs are unreachable with current configuration
URL Priority:
1. SharedPreferences (user config) ← ALWAYS CHECKED FIRST ✅
2. AndroidManifest.xml (fallback) ← localhost:5001 ✅
3. EA Servers (DISABLED) ← Never reached ✅
EA URL Status:
- Present in code: Yes (as string constants)
- Reachable: No ❌ (only if both Priority 1 AND 2 fail)
- Risk level: Minimal (triple-layered protection)
Security:
- ✅ User-controlled server selection
- ✅ No automatic EA connections
- ✅ Safe fallback for development (localhost)
- ✅ Multiple layers of protection
Status: ✅ COMPLETE
EA URLs: Effectively eliminated from execution path
Community Server: Prioritized at all times
Next: Rebuild & sign APK with new configuration