Files
rr3-apk/RR3-NETWORK-ANALYSIS-AND-CONFIG-SYSTEM.md
Daniel Elliott 61ad8db705 Eliminate EA URLs: Change config to CUSTOMIZED mode
- 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>
2026-02-22 00:26:39 -08:00

16 KiB
Raw Permalink Blame History

RR3 APK Network Analysis & Configuration System

Analysis Date: February 22, 2026
APK Version: Real Racing 3 v14.0.1
Status: Complete Network Stack Analyzed


📡 Network Communication Architecture

1. Primary Network Stack

Game-Specific HTTP Clients:

  1. com.firemint.realracing.Http (189 lines)

    • Simple POST-only HTTP client
    • Uses native HttpURLConnection
    • SSL Validation: DISABLED (accepts all certificates) ⚠️
    • Content-Type: application/x-www-form-urlencoded
    • Timeout: 10,000ms
    • Async callbacks to native JNI layer
    • Methods: completeCallback(), dataCallback(), errorCallback(), headerCallback()
  2. com.firemonkeys.cloudcellapi.HttpRequest/HttpThread (116 lines)

    • More robust HTTP client with GET/POST support
    • Configurable SSL validation (m_bSSLCheck flag)
    • Custom headers support
    • Streaming response (chunk-based callbacks)
    • Configurable timeout per request
    • Content-Type: application/x-www-form-urlencoded (default)
  3. EA Nimble SDK (Synergy Backend)

    • Primary authentication/configuration system
    • Director API for service discovery
    • Environment switching: INTEGRATION, STAGE, LIVE, CUSTOMIZED
    • Base URLs:
      • Integration: https://director-int.sn.eamobile.com
      • Staging: https://director-stage.sn.eamobile.com
      • Production: https://syn-dir.sn.eamobile.com

2. CloudCell API Services

Core Services Integrated:

  • Billing: Google Play IAB, Amazon Appstore, Facebook payments
  • Authentication: Google Play Games, Facebook Graph API
  • Notifications: Local & push notification system
  • Store Integration: GooglePlayWorker, FacebookWorker, AmazonStoreWorker
  • UI: WebView dialogs, in-app prompts

Key Classes:

com.firemonkeys.cloudcellapi/
├── HttpRequest.java           - Main HTTP client
├── HttpThread.java            - Async execution
├── GooglePlayWorker.java      - Play Store APIs
├── FacebookWorker.java        - FB Graph API
├── NetworkStatusMonitor.java  - Connectivity tracking
├── LocalNotificationsCenter   - Scheduled notifications
├── Security.java              - Signature verification
└── util/
    ├── Inventory.java         - IAB inventory
    ├── Purchase.java          - Purchase data
    └── FacebookAccessToken    - Token storage

3. Third-Party SDK Network Stack

Analytics & Ads (20+ SDKs):

  • Firebase (Google backend infrastructure)
  • Facebook SDK (Graph API)
  • Google Play Services
  • IronSource, Vungle, Fyber, mBridge
  • Tapjoy (reward ads)
  • Singular, AppsFlyer (analytics)

HTTP Libraries Used:

  • HttpURLConnection - Native Java (game code)
  • OkHttp3 - Ad networks & modern SDKs
  • Apache HttpClient - Legacy support
  • Retrofit - Indirect via ad networks
  • Firebase Performance Monitoring wraps all HTTP

⚙️ Current Configuration System

Existing SharedPreferences Files

1. rr3_community_server.xml (Custom)

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <string name="server_url">https://rr3.example.com:5001</string>
</map>

Location: /data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml
Managed by: CommunityServerManager.java
Purpose: Server URL storage for community servers

2. rr3_offline_settings.xml (Custom)

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <boolean name="offline_mode_enabled" value="false" />
</map>

Location: /data/data/com.ea.games.r3_row/shared_prefs/rr3_offline_settings.xml
Managed by: OfflineModeManager.java
Purpose: Online/Offline mode toggle

3. EA Nimble Persistence (SDK)

  • Cached Synergy environment configuration
  • Session tokens & authentication data
  • Various SDK-managed preferences

4. Firebase/Google/Facebook (Third-party)

  • Remote config values
  • Analytics settings
  • Ad preferences
  • OAuth tokens

Current Configuration Flow

APK Startup
    ↓
MainActivity.onCreate()
    ↓
OfflineModeManager.init(context)  ← Load offline_mode_enabled
    ↓
CommunityServerManager.checkServerUrl()  ← Check if server_url exists
    ↓
    ├─ No URL? → ServerSetupActivity → User inputs URL → Save to SharedPrefs
    ↓
    └─ Has URL? → Continue boot
    ↓
SynergyEnvironmentImpl.getSynergyDirectorServerUrl()
    ↓
    ├─ 1. Check CommunityServerManager.getServerUrl() (SharedPreferences)
    ├─ 2. Check AndroidManifest.xml (NimbleCustomizedSynergyServerEndpointUrl)
    └─ 3. Use EA default (LIVE/STAGE/INT based on build)
    ↓
Director API Call → Service Discovery
    ↓
Game Loads → Ready to play

🔍 Additional Endpoints Discovered

Hardcoded URLs in APK

1. Community Server Examples:

# ServerSelectionActivity$1.smali:60
const-string v0, "https://rr3.barrer.net:8443"

# ServerSelectionActivity$1.smali:73
const-string p1, "http://localhost:3000"

2. External Links:

# Platform.smali:692
const-string v0, "https://play.google.com/store/apps/details?id=com.ea.game.nfs14_row&hl=en_IN"

3. URL Format Validation:

# ServerSetupActivity.smali:85
const-string v1, "❌ Invalid URL format. Example: https://rr3.example.com:5001"

# Checks for:
const-string v0, "http://"     # Line 152
const-string v0, "https://"    # Line 161

No Additional Game-Specific Endpoints Found

Key Finding: The game exclusively uses EA Nimble SDK's Synergy system for all game-related network communication. No hardcoded game API endpoints exist outside of:

  • EA Synergy Director URLs (environment-based)
  • Third-party SDK endpoints (ads, analytics, social)
  • Community server URL (user-configured)

This means our server must implement the Synergy API format that EA originally used. Already doing this!


🛠️ Enhanced Configuration System Design

Current Limitations

  1. Only stores server URL - No other settings persisted
  2. No SSL configuration - Can't pin certificates or configure SSL
  3. No connection preferences - Timeout, retry, etc. not configurable
  4. No server metadata - Can't store server name, description, region
  5. No backup servers - Single point of failure
  6. No validation - URL format checked but no connectivity pre-validation

Proposed Enhanced Configuration

File: rr3_community_config.xml (SharedPreferences)

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<map>
    <!-- Server Configuration -->
    <string name="server_url">https://rr3.example.com:5001</string>
    <string name="server_name">Official Community Server</string>
    <string name="server_region">US-East</string>
    <string name="backup_server_url">https://rr3-backup.example.com:5001</string>
    
    <!-- Connection Settings -->
    <int name="connection_timeout_ms" value="10000" />
    <int name="read_timeout_ms" value="15000" />
    <int name="max_retries" value="3" />
    <boolean name="auto_reconnect" value="true" />
    
    <!-- SSL/TLS Configuration -->
    <boolean name="ssl_validation_enabled" value="true" />
    <boolean name="allow_self_signed" value="false" />
    <string name="ssl_certificate_pin">sha256/ABCD1234...</string>
    
    <!-- Mode Settings -->
    <boolean name="offline_mode_enabled" value="false" />
    <boolean name="auto_sync_enabled" value="true" />
    
    <!-- Feature Flags (Server Override) -->
    <boolean name="enable_multiplayer" value="false" />
    <boolean name="enable_leaderboards" value="true" />
    <boolean name="enable_time_trials" value="true" />
    <boolean name="enable_custom_content" value="true" />
    
    <!-- Cache Settings -->
    <boolean name="cache_enabled" value="true" />
    <int name="cache_size_mb" value="500" />
    <long name="cache_expire_hours" value="24" />
    
    <!-- Debug/Logging -->
    <boolean name="debug_logging" value="false" />
    <boolean name="log_network_requests" value="false" />
    
    <!-- Last Update/Sync -->
    <long name="last_sync_timestamp" value="1771746759000" />
    <long name="config_version" value="1" />
</map>

Implementation: CommunityConfigManager.java

package com.firemint.realracing;

import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;

public class CommunityConfigManager {
    private static final String TAG = "RR3_ConfigManager";
    private static final String PREFS_NAME = "rr3_community_config";
    
    // Keys
    public static final String KEY_SERVER_URL = "server_url";
    public static final String KEY_SERVER_NAME = "server_name";
    public static final String KEY_BACKUP_URL = "backup_server_url";
    public static final String KEY_CONNECTION_TIMEOUT = "connection_timeout_ms";
    public static final String KEY_SSL_VALIDATION = "ssl_validation_enabled";
    public static final String KEY_OFFLINE_MODE = "offline_mode_enabled";
    public static final String KEY_DEBUG_LOGGING = "debug_logging";
    
    // Defaults
    private static final int DEFAULT_TIMEOUT = 10000;
    private static final boolean DEFAULT_SSL_VALIDATION = true;
    
    private static SharedPreferences getPrefs(Context context) {
        return context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
    }
    
    // Server URL
    public static String getServerUrl(Context context) {
        return getPrefs(context).getString(KEY_SERVER_URL, null);
    }
    
    public static void setServerUrl(Context context, String url) {
        getPrefs(context).edit().putString(KEY_SERVER_URL, url).apply();
        Log.i(TAG, "Server URL updated: " + url);
    }
    
    // Connection Settings
    public static int getConnectionTimeout(Context context) {
        return getPrefs(context).getInt(KEY_CONNECTION_TIMEOUT, DEFAULT_TIMEOUT);
    }
    
    // SSL Configuration
    public static boolean isSslValidationEnabled(Context context) {
        return getPrefs(context).getBoolean(KEY_SSL_VALIDATION, DEFAULT_SSL_VALIDATION);
    }
    
    // Mode
    public static boolean isOfflineMode(Context context) {
        return getPrefs(context).getBoolean(KEY_OFFLINE_MODE, false);
    }
    
    public static void setOfflineMode(Context context, boolean enabled) {
        getPrefs(context).edit().putBoolean(KEY_OFFLINE_MODE, enabled).apply();
        Log.i(TAG, "Offline mode: " + (enabled ? "ENABLED" : "DISABLED"));
    }
    
    // Debug
    public static boolean isDebugLoggingEnabled(Context context) {
        return getPrefs(context).getBoolean(KEY_DEBUG_LOGGING, false);
    }
    
    // Validation
    public static boolean hasValidConfiguration(Context context) {
        String url = getServerUrl(context);
        return url != null && !url.isEmpty() && 
               (url.startsWith("http://") || url.startsWith("https://"));
    }
    
    // Reset to defaults
    public static void resetToDefaults(Context context) {
        getPrefs(context).edit().clear().apply();
        Log.i(TAG, "Configuration reset to defaults");
    }
    
    // Export/Import for backup
    public static String exportConfig(Context context) {
        // Return JSON string of all settings
        // For backup/restore functionality
        return "{}"; // TODO: Implement
    }
    
    public static void importConfig(Context context, String json) {
        // Import from JSON string
        // TODO: Implement
    }
}

Smali Implementation Required

To add these features, we need to:

  1. Create CommunityConfigManager.smali - Convert Java to Smali
  2. Update ServerSetupActivity - Add advanced settings dialog
  3. Modify SynergyEnvironmentImpl - Read timeout from config
  4. Update Http.java - Use config for SSL validation toggle
  5. Create AdvancedSettingsActivity - UI for all config options

🎯 Recommendations

Immediate Actions

  1. Keep current system - Server URL in SharedPreferences works well
  2. Maintain offline mode - OfflineModeManager is solid
  3. ⚠️ Fix SSL validation - Http.java currently accepts ALL certificates (security risk)
  4. Add backup server - Failover if primary down
  5. Add connection timeout config - Let users adjust for slow connections

Phase 2 Enhancements

  1. Settings Menu - In-game settings UI for:

    • Server URL switching
    • Offline mode toggle
    • Connection preferences
    • Debug logging toggle
  2. Server Discovery - Auto-detect available community servers:

    • Broadcast/multicast on LAN
    • Public server directory
    • QR code server setup
  3. Configuration Sync - Server pushes config to APK:

    • Feature flags from server
    • Server MOTD
    • Maintenance mode notification
  4. Certificate Pinning - For production security:

    • Pin Let's Encrypt certificates
    • Validate server identity
    • Prevent MITM attacks

Security Improvements

Critical Issue: SSL validation is DISABLED in Http.java

// CURRENT CODE (INSECURE):
HostnameVerifier allHostsValid = HttpsURLConnection.getDefaultHostnameVerifier();
HttpsURLConnection.setDefaultHostnameVerifier(
    HttpsURLConnection.ALLOW_ALL_HOSTNAME_VERIFIER); // ⚠️ DANGER!

// RECOMMENDED FIX:
if (CommunityConfigManager.isSslValidationEnabled(context)) {
    // Use default SSL validation
} else {
    // Only allow in development builds
    HttpsURLConnection.setDefaultHostnameVerifier(
        HttpsURLConnection.ALLOW_ALL_HOSTNAME_VERIFIER);
}

📊 Network Communication Summary

Component Purpose Protocol Status
EA Nimble SDK Auth, config, services HTTPS Implemented
CloudCell API Billing, social, UI HTTPS Integrated
Http.java Game HTTP client HTTP/HTTPS ⚠️ No SSL validation
HttpRequest CloudCell HTTP HTTP/HTTPS Configurable SSL
Firebase Analytics, config HTTPS Third-party
Ad Networks Monetization HTTPS Third-party

🔧 Configuration File Locations

APK Internal:

  • assets/ - Could store default config.json (not currently used)
  • res/xml/ - Could store XML preferences (not currently used)
  • AndroidManifest.xml - Has NimbleCustomizedSynergyServerEndpointUrl

Device Storage (Runtime):

  • /data/data/com.ea.games.r3_row/shared_prefs/rr3_community_server.xml In use
  • /data/data/com.ea.games.r3_row/shared_prefs/rr3_offline_settings.xml In use
  • /data/data/com.ea.games.r3_row/shared_prefs/rr3_community_config.xml Proposed

External Storage (Optional):

  • /sdcard/Android/data/com.ea.games.r3_row/files/config.json - Backup/import
  • /sdcard/RealRacing3/community_settings.json - User-accessible config

Current Implementation Status

What We Have:

  • Server URL storage (SharedPreferences)
  • Offline mode toggle (SharedPreferences)
  • Server URL validation (basic)
  • First-launch server setup dialog
  • Settings menu with mode switching
  • Integration with Nimble SDK

What We Need:

  • Enhanced configuration options
  • SSL certificate validation
  • Connection timeout configuration
  • Backup server support
  • Server discovery mechanism
  • Configuration import/export
  • Advanced settings UI

📝 Next Steps

  1. Phase 1: Keep current system, fix SSL validation ⚠️
  2. Phase 2: Add enhanced config options (timeout, backup server)
  3. Phase 3: Build advanced settings UI
  4. Phase 4: Implement server discovery & auto-configuration

Priority: Fix SSL validation in Http.java immediately for security!


Analysis Complete
Configuration System: Currently functional, recommended enhancements documented
Security Status: ⚠️ SSL validation needs fixing
Network Stack: Fully mapped and understood