From d144aec8532d952ea36b236502c2cf967fb9f931 Mon Sep 17 00:00:00 2001 From: Daniel Elliott Date: Tue, 17 Feb 2026 22:06:36 -0800 Subject: [PATCH] Add decompiled reference source files - Key Java files showing custom server implementation - Original AndroidManifest.xml for reference - SynergyEnvironmentImpl.java - Custom server configuration - HttpRequest.java - HTTP implementation details - Documentation explaining each file's purpose Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- decompiled-reference/README.md | 131 +++ .../com/ea/nimble/SynergyEnvironmentImpl.java | 490 +++++++++ .../com/ea/nimble/SynergyRequest.java | 144 +++ .../firemonkeys/cloudcellapi/HttpRequest.java | 116 +++ .../resources/AndroidManifest.xml | 982 ++++++++++++++++++ 5 files changed, 1863 insertions(+) create mode 100644 decompiled-reference/README.md create mode 100644 decompiled-reference/com/ea/nimble/SynergyEnvironmentImpl.java create mode 100644 decompiled-reference/com/ea/nimble/SynergyRequest.java create mode 100644 decompiled-reference/com/firemonkeys/cloudcellapi/HttpRequest.java create mode 100644 decompiled-reference/resources/AndroidManifest.xml diff --git a/decompiled-reference/README.md b/decompiled-reference/README.md new file mode 100644 index 000000000..728fc92b8 --- /dev/null +++ b/decompiled-reference/README.md @@ -0,0 +1,131 @@ +# Decompiled Reference Files + +This directory contains **reference files** decompiled from Real Racing 3 APK using JADX. These files are included for: + +- 📚 **Educational purposes** - Understanding how the game communicates with servers +- 🔍 **Reference documentation** - See how custom server support is implemented +- 🛠️ **Modification guidance** - Know exactly what files to modify + +## ⚠️ Important Legal Notice + +These files are **decompiled from the original Real Racing 3 APK** and are: +- © Electronic Arts Inc. - All rights reserved +- Included for **educational and preservation purposes only** +- **NOT** to be used for commercial purposes +- **NOT** to be redistributed outside this private repository + +## 📁 Directory Structure + +``` +decompiled-reference/ +├── com/ +│ ├── ea/ +│ │ └── nimble/ +│ │ ├── SynergyEnvironmentImpl.java - Custom server configuration +│ │ └── SynergyRequest.java - HTTP request handling +│ └── firemonkeys/ +│ └── cloudcellapi/ +│ └── HttpRequest.java - Low-level HTTP implementation +└── resources/ + └── AndroidManifest.xml - App manifest (original) +``` + +## 🔑 Key Files Explained + +### SynergyEnvironmentImpl.java +**Location**: Lines 166-183 contain the custom server implementation + +This file contains the `NimbleConfiguration` enum and shows how RR3 reads the custom server URL: + +```java +public String getSynergyDirectorServerUrl() { + switch (this.m_configuration) { + case CUSTOMIZED: + // 🎯 This is what we're using! + return ComponentManager.getComponent(ApplicationEnvironment.class) + .getApplicationInfo() + .metaData + .getString("NimbleCustomizedSynergyServerEndpointUrl"); + case LIVE: + return "https://api.firemonkeys.ea.com/"; + // ... other cases + } +} +``` + +### HttpRequest.java +Shows how the game makes HTTP requests, including: +- JNI callbacks for response streaming +- Custom SSL certificate validation +- Header management (EAM-SESSION, EAM-USER-ID, etc.) + +### AndroidManifest.xml +Original manifest showing: +- Current configuration: `com.ea.nimble.configuration = "live"` +- Package name: `com.ea.game.realracing3_row` +- Permissions and activities +- **This is the file we modify** to point to community servers + +## 🎓 How to Use These Files + +### For Understanding +Read these files to understand: +1. How RR3 determines which server to connect to +2. What headers are required for API calls +3. How authentication and sessions work +4. SSL/certificate validation implementation + +### For Modification Reference +When modifying APKs: +1. Check `SynergyEnvironmentImpl.java` to see expected metadata keys +2. Review `AndroidManifest.xml` to see original configuration +3. Reference `HttpRequest.java` to understand HTTP implementation + +### For Server Development +Use these files to: +- Understand expected API behavior +- See what headers the client sends +- Know how SSL is validated +- Implement compatible server responses + +## 🔍 Decompilation Details + +**Tool Used**: JADX (Java Decompiler) +- Version: JADX 1.4.7+ +- Command: `jadx realracing3.apk -d decompiled/` +- Source: Real Racing 3 v14.0.1 + +**Quality**: These files are decompiled from Dalvik bytecode: +- ✅ Structure is accurate +- ✅ Logic flow is correct +- ⚠️ Variable names may be obfuscated +- ⚠️ Some comments are from decompiler + +## 📖 Related Documentation + +For complete analysis of the protocol, see: +- [NETWORK_COMMUNICATION_ANALYSIS.md](../NETWORK_COMMUNICATION_ANALYSIS.md) + +For modification instructions, see: +- [APK_MODIFICATION_GUIDE.md](../APK_MODIFICATION_GUIDE.md) + +## 🚫 What's NOT Included + +We do **NOT** include: +- ❌ Full game source code (too large, unnecessary) +- ❌ Game assets (textures, models, sounds) +- ❌ Native libraries (.so files) +- ❌ Compiled APK files +- ❌ Obfuscated/minified classes + +Only the **essential files** needed to understand custom server support are included. + +## 📝 Attribution + +**Original Software**: Real Racing 3 +**Developer**: Firemonkeys Studios / Electronic Arts +**Decompilation**: For educational research and game preservation + +--- + +*These files are provided for educational purposes under fair use for interoperability and preservation research.* diff --git a/decompiled-reference/com/ea/nimble/SynergyEnvironmentImpl.java b/decompiled-reference/com/ea/nimble/SynergyEnvironmentImpl.java new file mode 100644 index 000000000..cc06d486f --- /dev/null +++ b/decompiled-reference/com/ea/nimble/SynergyEnvironmentImpl.java @@ -0,0 +1,490 @@ +package com.ea.nimble; + +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import com.ea.nimble.Error; +import com.ea.nimble.Log; +import com.ea.nimble.Network; +import com.ea.nimble.Persistence; +import com.ea.nimble.SynergyEnvironmentUpdater; +import java.io.Serializable; +import java.util.HashMap; + +/* loaded from: classes2.dex */ +public class SynergyEnvironmentImpl extends Component implements ISynergyEnvironment, LogSource { + private static final String PERSISTENCE_DATA_ID = "environmentData"; + public static final int SYNERGY_APP_VERSION_OK = 0; + public static final int SYNERGY_APP_VERSION_UPDATE_RECOMMENDED = 1; + public static final int SYNERGY_APP_VERSION_UPDATE_REQUIRED = 2; + private static final String SYNERGY_INT_SERVER_URL = "https://director-int.sn.eamobile.com"; + private static final String SYNERGY_LIVE_SERVER_URL = "https://syn-dir.sn.eamobile.com"; + private static final String SYNERGY_STAGE_SERVER_URL = "https://director-stage.sn.eamobile.com"; + public static final double SYNERGY_UPDATE_RATE_LIMIT_PERIOD_IN_SECONDS = 60.0d; + public static final double SYNERGY_UPDATE_REFRESH_PERIOD_IN_SECONDS = 300.0d; + private BaseCore m_core; + private EnvironmentDataContainer m_environmentDataContainer; + private EnvironmentDataContainer m_previousValidEnvironmentDataContainer; + private Long m_synergyEnvironmentUpdateRateLimitTriggerTimestamp; + private SynergyEnvironmentUpdater m_synergyStartupObject; + private BroadcastReceiver m_networkStatusChangeReceiver = null; + private boolean m_dataLoadedOnComponentSetup = false; + private boolean m_pendingStartupFinishedNotification = false; + + @Override // com.ea.nimble.Component + public String getComponentId() { + return SynergyEnvironment.COMPONENT_ID; + } + + @Override // com.ea.nimble.LogSource + public String getLogSourceTitle() { + return "SynergyEnv"; + } + + public SynergyEnvironmentImpl(BaseCore baseCore) { + this.m_core = baseCore; + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getEADeviceId() { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return null; + } + return environmentDataContainer.getEADeviceId(); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getSynergyId() { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return null; + } + return environmentDataContainer.getSynergyId(); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getSellId() { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return null; + } + return environmentDataContainer.getSellId(); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getProductId() { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return null; + } + return environmentDataContainer.getProductId(); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getEAHardwareId() { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return null; + } + return environmentDataContainer.getEAHardwareId(); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public Error setServerUrl(String str, String str2) { + return this.m_environmentDataContainer.setServerUrl(str, str2); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getServerUrlWithKey(String str) { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return null; + } + return environmentDataContainer.getServerUrlWithKey(str); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public int getLatestAppVersionCheckResult() { + Log.Helper.LOGPUBLICFUNC(this); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return 0; + } + return environmentDataContainer.getLatestAppVersionCheckResult(); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public int getTrackingPostInterval() { + Log.Helper.LOGPUBLICFUNC(this); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return -1; + } + return environmentDataContainer.getTrackingPostInterval(); + } + + /* renamed from: com.ea.nimble.SynergyEnvironmentImpl$3, reason: invalid class name */ + public static /* synthetic */ class AnonymousClass3 { + static final /* synthetic */ int[] $SwitchMap$com$ea$nimble$NimbleConfiguration; + + static { + int[] iArr = new int[NimbleConfiguration.values().length]; + $SwitchMap$com$ea$nimble$NimbleConfiguration = iArr; + try { + iArr[NimbleConfiguration.INTEGRATION.ordinal()] = 1; + } catch (NoSuchFieldError unused) { + } + try { + $SwitchMap$com$ea$nimble$NimbleConfiguration[NimbleConfiguration.STAGE.ordinal()] = 2; + } catch (NoSuchFieldError unused2) { + } + try { + $SwitchMap$com$ea$nimble$NimbleConfiguration[NimbleConfiguration.LIVE.ordinal()] = 3; + } catch (NoSuchFieldError unused3) { + } + try { + $SwitchMap$com$ea$nimble$NimbleConfiguration[NimbleConfiguration.CUSTOMIZED.ordinal()] = 4; + } catch (NoSuchFieldError unused4) { + } + } + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getSynergyDirectorServerUrl(NimbleConfiguration nimbleConfiguration) { + Log.Helper.LOGPUBLICFUNC(this); + int i = AnonymousClass3.$SwitchMap$com$ea$nimble$NimbleConfiguration[nimbleConfiguration.ordinal()]; + if (i == 1) { + return SYNERGY_INT_SERVER_URL; + } + if (i == 2) { + return SYNERGY_STAGE_SERVER_URL; + } + if (i == 3) { + return SYNERGY_LIVE_SERVER_URL; + } + if (i == 4) { + return NimbleApplicationConfiguration.getConfigValueAsString("NimbleCustomizedSynergyServerEndpointUrl", SYNERGY_LIVE_SERVER_URL); + } + Log.Helper.LOGF(this, "Request for Synergy Director server URL with unknown NimbleConfiguration, %d.", nimbleConfiguration); + return SYNERGY_LIVE_SERVER_URL; + } + + @Override // com.ea.nimble.ISynergyEnvironment + public boolean isDataAvailable() { + Log.Helper.LOGPUBLICFUNC(this); + return this.m_environmentDataContainer != null; + } + + @Override // com.ea.nimble.ISynergyEnvironment + public boolean isUpdateInProgress() { + Log.Helper.LOGPUBLICFUNC(this); + return this.m_synergyStartupObject != null; + } + + @Override // com.ea.nimble.ISynergyEnvironment + public Error checkAndInitiateSynergyEnvironmentUpdate() { + Log.Helper.LOGPUBLICFUNC(this); + if (isUpdateInProgress()) { + return new Error(Error.Code.SYNERGY_ENVIRONMENT_UPDATE_FAILURE, "Update in progress."); + } + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer != null && environmentDataContainer.getMostRecentDirectorResponseTimestamp() != null) { + return new Error(Error.Code.SYNERGY_ENVIRONMENT_UPDATE_FAILURE, "Environment data already cached."); + } + if (isInSynergyEnvironmentUpdateRateLimitingPeriod()) { + Log.Helper.LOGD(this, "Attempt to re-initiate Synergy environment update blocked by rate limiting. %.2f seconds of rate limiting left", Double.valueOf(60.0d - ((System.currentTimeMillis() - this.m_synergyEnvironmentUpdateRateLimitTriggerTimestamp.longValue()) / 1000.0d))); + return new Error(Error.Code.SYNERGY_ENVIRONMENT_UPDATE_FAILURE, "Synergy environment update rate limit in effect."); + } + startSynergyEnvironmentUpdate(); + return null; + } + + @Override // com.ea.nimble.ISynergyEnvironment + public boolean isFeatureDisabled(String str) { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + return environmentDataContainer != null && environmentDataContainer.isFeatureDisabled(str); + } + + @Override // com.ea.nimble.Component + public void setup() { + Log.Helper.LOGFUNC(this); + this.m_dataLoadedOnComponentSetup = restoreEnvironmentDataFromPersistent(true); + } + + @Override // com.ea.nimble.Component + public void restore() { + Log.Helper.LOGFUNC(this); + if (this.m_dataLoadedOnComponentSetup) { + this.m_dataLoadedOnComponentSetup = false; + Utility.sendBroadcast(SynergyEnvironment.NOTIFICATION_RESTORED_FROM_PERSISTENT); + } else { + restoreEnvironmentDataFromPersistent(false); + } + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null || environmentDataContainer.getMostRecentDirectorResponseTimestamp() == null || (System.currentTimeMillis() - this.m_environmentDataContainer.getMostRecentDirectorResponseTimestamp().longValue()) / 1000.0d > 300.0d) { + startSynergyEnvironmentUpdate(); + } else { + checkAndInitiateSynergyEnvironmentUpdate(); + } + } + + @Override // com.ea.nimble.Component + public void suspend() { + Log.Helper.LOGFUNC(this); + SynergyEnvironmentUpdater synergyEnvironmentUpdater = this.m_synergyStartupObject; + if (synergyEnvironmentUpdater != null) { + synergyEnvironmentUpdater.cancel(); + this.m_synergyStartupObject = null; + } + BroadcastReceiver broadcastReceiver = this.m_networkStatusChangeReceiver; + if (broadcastReceiver != null) { + Utility.unregisterReceiver(broadcastReceiver); + this.m_networkStatusChangeReceiver = null; + } + saveEnvironmentDataToPersistent(); + } + + @Override // com.ea.nimble.Component + public void resume() { + Log.Helper.LOGFUNC(this); + clearSynergyEnvironmentUpdateRateLimiting(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null || environmentDataContainer.getMostRecentDirectorResponseTimestamp() == null || (System.currentTimeMillis() - this.m_environmentDataContainer.getMostRecentDirectorResponseTimestamp().longValue()) / 1000.0d > 300.0d) { + startSynergyEnvironmentUpdate(); + } + if (this.m_pendingStartupFinishedNotification) { + this.m_pendingStartupFinishedNotification = false; + HashMap hashMap = new HashMap(); + hashMap.put("result", "1"); + Log.Helper.LOGD(this, "App is running in forground, sending delayed the NOTIFICATION_STARTUP_REQUESTS_FINISHED notification", new Object[0]); + Utility.sendBroadcast(SynergyEnvironment.NOTIFICATION_STARTUP_REQUESTS_FINISHED, hashMap); + } + } + + @Override // com.ea.nimble.Component + public void cleanup() { + Log.Helper.LOGFUNC(this); + SynergyEnvironmentUpdater synergyEnvironmentUpdater = this.m_synergyStartupObject; + if (synergyEnvironmentUpdater != null) { + synergyEnvironmentUpdater.cancel(); + this.m_synergyStartupObject = null; + } + BroadcastReceiver broadcastReceiver = this.m_networkStatusChangeReceiver; + if (broadcastReceiver != null) { + Utility.unregisterReceiver(broadcastReceiver); + this.m_networkStatusChangeReceiver = null; + } + saveEnvironmentDataToPersistent(); + this.m_environmentDataContainer = null; + } + + @Override // com.ea.nimble.Component + public void teardown() { + Log.Helper.LOGFUNC(this); + this.m_environmentDataContainer = null; + } + + private void startSynergyEnvironmentUpdate() { + SynergyEnvironmentUpdater synergyEnvironmentUpdater; + Log.Helper.LOGFUNC(this); + synchronized (this) { + try { + if (this.m_synergyStartupObject == null) { + synergyEnvironmentUpdater = new SynergyEnvironmentUpdater(this.m_core); + this.m_synergyStartupObject = synergyEnvironmentUpdater; + } else { + synergyEnvironmentUpdater = null; + } + } catch (Throwable th) { + throw th; + } + } + if (synergyEnvironmentUpdater == null) { + Log.Helper.LOGD(this, "Attempt made to start Synergy environment update while a previous one is active. Exiting.", new Object[0]); + return; + } + if (Network.getComponent().getStatus() == Network.Status.OK) { + startSynergyEnvironmentUpdateImpl(synergyEnvironmentUpdater); + } else if (this.m_networkStatusChangeReceiver == null) { + this.m_networkStatusChangeReceiver = new BroadcastReceiver() { // from class: com.ea.nimble.SynergyEnvironmentImpl.1 + @Override // android.content.BroadcastReceiver + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Global.NOTIFICATION_NETWORK_STATUS_CHANGE) && Network.getComponent().getStatus() == Network.Status.OK) { + Log.Helper.LOGD(this, "Network restored. Starting Synergy environment update.", new Object[0]); + Utility.unregisterReceiver(SynergyEnvironmentImpl.this.m_networkStatusChangeReceiver); + SynergyEnvironmentImpl.this.m_networkStatusChangeReceiver = null; + SynergyEnvironmentImpl synergyEnvironmentImpl = SynergyEnvironmentImpl.this; + synergyEnvironmentImpl.startSynergyEnvironmentUpdateImpl(synergyEnvironmentImpl.m_synergyStartupObject); + } + } + }; + Log.Helper.LOGD(this, "Network not available to perform environment update. Setting receiver to listen for network status change.", new Object[0]); + Utility.registerReceiver(Global.NOTIFICATION_NETWORK_STATUS_CHANGE, this.m_networkStatusChangeReceiver); + } + } + + /* JADX INFO: Access modifiers changed from: private */ + public void startSynergyEnvironmentUpdateImpl(final SynergyEnvironmentUpdater synergyEnvironmentUpdater) { + Log.Helper.LOGFUNC(this); + if (synergyEnvironmentUpdater == null) { + Log.Helper.LOGD(this, "Synergy Environment Update canceled before it could start", new Object[0]); + return; + } + this.m_previousValidEnvironmentDataContainer = this.m_environmentDataContainer; + HashMap hashMap = new HashMap(); + hashMap.put("result", "1"); + Utility.sendBroadcast(SynergyEnvironment.NOTIFICATION_STARTUP_REQUESTS_STARTED, hashMap); + synergyEnvironmentUpdater.startSynergyStartupSequence(this.m_previousValidEnvironmentDataContainer, new SynergyEnvironmentUpdater.CompletionCallback() { // from class: com.ea.nimble.SynergyEnvironmentImpl.2 + @Override // com.ea.nimble.SynergyEnvironmentUpdater.CompletionCallback + public void callback(Exception exc) { + if (exc == null) { + if (SynergyEnvironmentImpl.this.m_synergyStartupObject != null && synergyEnvironmentUpdater.getEnvironmentDataContainer() != null) { + SynergyEnvironmentImpl.this.m_environmentDataContainer = synergyEnvironmentUpdater.getEnvironmentDataContainer(); + SynergyEnvironmentImpl.this.saveEnvironmentDataToPersistent(); + if (SynergyEnvironmentImpl.this.m_environmentDataContainer.getKeysOfDifferences(SynergyEnvironmentImpl.this.m_previousValidEnvironmentDataContainer) != null) { + Utility.sendBroadcast(SynergyEnvironment.NOTIFICATION_STARTUP_ENVIRONMENT_DATA_CHANGED); + } + HashMap hashMap2 = new HashMap(); + hashMap2.put("result", "1"); + if (ApplicationEnvironment.isMainApplicationActive()) { + Log.Helper.LOGD(this, "App is running in forground, send the NOTIFICATION_STARTUP_REQUESTS_FINISHED notification", new Object[0]); + Utility.sendBroadcast(SynergyEnvironment.NOTIFICATION_STARTUP_REQUESTS_FINISHED, hashMap2); + } else { + Log.Helper.LOGI(this, "App is not running in forground, discard the NOTIFICATION_STARTUP_REQUESTS_FINISHED notification", new Object[0]); + SynergyEnvironmentImpl.this.m_pendingStartupFinishedNotification = true; + } + } else { + Log.Helper.LOGD(this, "Synergy Environment Update object or dataContainer null at callback. Update was canceled", new Object[0]); + } + } else { + Log.Helper.LOGE(this, "StartupError(%s)", exc); + if (!(exc instanceof Error)) { + if (SynergyEnvironmentImpl.this.m_synergyStartupObject == null || synergyEnvironmentUpdater.getEnvironmentDataContainer() == null) { + Log.Helper.LOGD(this, "Synergy Environment Update object or dataContainer null at callback. More than one update was being peroformed", new Object[0]); + } + } else { + Error error = (Error) exc; + if (error.isError(Error.Code.SYNERGY_GET_DIRECTION_TIMEOUT) || error.isError(Error.Code.SYNERGY_SERVER_FULL)) { + Log.Helper.LOGD(this, "GetDirection request timed out or ServerUnavailable signal received. Start rate limiting of /getDirection call.", new Object[0]); + SynergyEnvironmentImpl.this.startSynergyEnvironmentUpdateRateLimiting(); + } + } + HashMap hashMap3 = new HashMap(); + hashMap3.put("result", "0"); + hashMap3.put("error", exc.toString()); + if (ApplicationEnvironment.isMainApplicationActive()) { + Log.Helper.LOGD(this, "App is running in forground, send the NOTIFICATION_STARTUP_REQUESTS_FINISHED notification", new Object[0]); + Utility.sendBroadcast(SynergyEnvironment.NOTIFICATION_STARTUP_REQUESTS_FINISHED, hashMap3); + } else { + Log.Helper.LOGI(this, "App is not running in forground, discard the NOTIFICATION_STARTUP_REQUESTS_FINISHED notification", new Object[0]); + } + } + SynergyEnvironmentImpl.this.m_synergyStartupObject = null; + } + }); + } + + /* JADX INFO: Access modifiers changed from: private */ + public void startSynergyEnvironmentUpdateRateLimiting() { + Log.Helper.LOGFUNC(this); + this.m_synergyEnvironmentUpdateRateLimitTriggerTimestamp = Long.valueOf(System.currentTimeMillis()); + } + + private boolean isInSynergyEnvironmentUpdateRateLimitingPeriod() { + Log.Helper.LOGFUNC(this); + return this.m_synergyEnvironmentUpdateRateLimitTriggerTimestamp != null && ((double) (System.currentTimeMillis() - this.m_synergyEnvironmentUpdateRateLimitTriggerTimestamp.longValue())) <= 60000.0d; + } + + private void clearSynergyEnvironmentUpdateRateLimiting() { + Log.Helper.LOGFUNC(this); + this.m_synergyEnvironmentUpdateRateLimitTriggerTimestamp = null; + } + + private boolean restoreEnvironmentDataFromPersistent(boolean z) { + Log.Helper.LOGFUNC(this); + Persistence persistenceForNimbleComponent = PersistenceService.getPersistenceForNimbleComponent(SynergyEnvironment.COMPONENT_ID, Persistence.Storage.CACHE); + if (persistenceForNimbleComponent != null) { + Serializable value = persistenceForNimbleComponent.getValue(PERSISTENCE_DATA_ID); + if (value == null) { + Log.Helper.LOGD(this, "Environment persistence data value not found in persistence object. Probably first install.", new Object[0]); + } else { + try { + EnvironmentDataContainer environmentDataContainer = (EnvironmentDataContainer) value; + this.m_environmentDataContainer = environmentDataContainer; + Log.Helper.LOGD(this, "Restored environment data from persistent. Restored data timestamp, %s", environmentDataContainer.getMostRecentDirectorResponseTimestamp()); + if (!z) { + Utility.sendBroadcast(SynergyEnvironment.NOTIFICATION_RESTORED_FROM_PERSISTENT); + } + return true; + } catch (ClassCastException unused) { + Log.Helper.LOGE(this, "Environment persistence data value is not the expected type.", new Object[0]); + } + } + } else { + Log.Helper.LOGE(this, "Could not get environment persistence object to restore from", new Object[0]); + } + this.m_environmentDataContainer = null; + return false; + } + + /* JADX INFO: Access modifiers changed from: private */ + public void saveEnvironmentDataToPersistent() { + Log.Helper.LOGFUNC(this); + Persistence persistenceForNimbleComponent = PersistenceService.getPersistenceForNimbleComponent(SynergyEnvironment.COMPONENT_ID, Persistence.Storage.CACHE); + if (persistenceForNimbleComponent != null) { + Log.Helper.LOGD(this, "Saving environment data to persistent.", new Object[0]); + persistenceForNimbleComponent.setValue(PERSISTENCE_DATA_ID, this.m_environmentDataContainer); + persistenceForNimbleComponent.lambda$new$0(); + return; + } + Log.Helper.LOGE(this, "Could not get environment persistence object to save to.", new Object[0]); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getNexusClientId() { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return null; + } + return environmentDataContainer.getNexusClientId(); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getNexusClientSecret() { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return null; + } + return environmentDataContainer.getNexusClientSecret(); + } + + @Override // com.ea.nimble.ISynergyEnvironment + public String getGosMdmAppKey() { + Log.Helper.LOGPUBLICFUNC(this); + checkAndInitiateSynergyEnvironmentUpdate(); + EnvironmentDataContainer environmentDataContainer = this.m_environmentDataContainer; + if (environmentDataContainer == null) { + return null; + } + return environmentDataContainer.getGosMdmAppKey(); + } +} diff --git a/decompiled-reference/com/ea/nimble/SynergyRequest.java b/decompiled-reference/com/ea/nimble/SynergyRequest.java new file mode 100644 index 000000000..d25f2e1d0 --- /dev/null +++ b/decompiled-reference/com/ea/nimble/SynergyRequest.java @@ -0,0 +1,144 @@ +package com.ea.nimble; + +import com.ea.nimble.Error; +import com.ea.nimble.IHttpRequest; +import com.ea.nimble.ISynergyRequest; +import com.ea.nimble.Log; +import com.ironsource.nb; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; + +/* loaded from: classes2.dex */ +public class SynergyRequest implements ISynergyRequest { + public String api; + public String baseUrl; + public HttpRequest httpRequest; + public ISynergyRequest.IJsonData jsonData; + private SynergyNetworkConnection m_connection = null; + public SynergyRequestPreparingCallback prepareRequestCallback; + public Map urlParameters; + + public interface SynergyRequestPreparingCallback { + void prepareRequest(SynergyRequest synergyRequest); + } + + public SynergyRequest(String str, IHttpRequest.Method method, SynergyRequestPreparingCallback synergyRequestPreparingCallback) { + this.api = str; + HttpRequest httpRequest = new HttpRequest(); + this.httpRequest = httpRequest; + this.prepareRequestCallback = synergyRequestPreparingCallback; + this.urlParameters = null; + this.jsonData = null; + httpRequest.method = method; + httpRequest.headers.put("Content-Type", nb.L); + this.httpRequest.headers.put("SDK-VERSION", Global.NIMBLE_RELEASE_VERSION); + this.httpRequest.headers.put("SDK-TYPE", Global.NIMBLE_ID); + String sessionId = ((SynergyNetworkImpl) SynergyNetwork.getComponent()).getSessionId(); + if (Utility.validString(sessionId)) { + this.httpRequest.headers.put("EAM-SESSION", sessionId); + } else { + Log.Helper.LOGES("SynergyRequest", "Synergy Network session ID is null", new Object[0]); + } + String synergyId = SynergyIdManager.getComponent().getSynergyId(); + if (Utility.validString(synergyId)) { + this.httpRequest.headers.put("EAM-USER-ID", synergyId); + } + String sellId = SynergyEnvironment.getComponent().getSellId(); + if (Utility.validString(sellId)) { + this.httpRequest.headers.put("EA-SELL-ID", sellId); + } + } + + @Override // com.ea.nimble.ISynergyRequest + public HttpRequest getHttpRequest() { + Log.Helper.LOGPUBLICFUNC(this); + return this.httpRequest; + } + + @Override // com.ea.nimble.ISynergyRequest + public String getBaseUrl() { + Log.Helper.LOGPUBLICFUNC(this); + return this.baseUrl; + } + + @Override // com.ea.nimble.ISynergyRequest + public String getApi() { + Log.Helper.LOGPUBLICFUNC(this); + return this.api; + } + + public IHttpRequest.Method getMethod() { + Log.Helper.LOGPUBLICFUNC(this); + return this.httpRequest.getMethod(); + } + + public void setMethod(IHttpRequest.Method method) { + Log.Helper.LOGPUBLICFUNC(this); + this.httpRequest.method = method; + } + + @Override // com.ea.nimble.ISynergyRequest + public Map getUrlParameters() { + Log.Helper.LOGPUBLICFUNC(this); + return this.urlParameters; + } + + @Override // com.ea.nimble.ISynergyRequest + public ISynergyRequest.IJsonData getJsonData() { + Log.Helper.LOGPUBLICFUNC(this); + return this.jsonData; + } + + public void send() { + Log.Helper.LOGPUBLICFUNC(this); + this.m_connection.send(); + } + + public void prepare(SynergyNetworkConnection synergyNetworkConnection) { + Log.Helper.LOGFUNC(this); + this.m_connection = synergyNetworkConnection; + SynergyRequestPreparingCallback synergyRequestPreparingCallback = this.prepareRequestCallback; + if (synergyRequestPreparingCallback != null) { + synergyRequestPreparingCallback.prepareRequest(this); + } else { + send(); + } + } + + public void build() throws Error { + ISynergyRequest.IJsonData iJsonData; + Log.Helper.LOGFUNC(this); + if (!Utility.validString(this.baseUrl) || !Utility.validString(this.api)) { + throw new Error(Error.Code.INVALID_ARGUMENT, String.format("Invalid synergy request parameter (%s, %s) to build http request url", this.baseUrl, this.api)); + } + IApplicationEnvironment component = ApplicationEnvironment.getComponent(); + HashMap hashMap = new HashMap(); + hashMap.put("appVer", component.getApplicationVersion()); + hashMap.put("appLang", component.getShortApplicationLanguageCode()); + hashMap.put("localization", component.getApplicationLanguageCode()); + hashMap.put("deviceLanguage", Locale.getDefault().getLanguage()); + hashMap.put(ApplicationEnvironment.NIMBLE_PARAMETER_DEVICE_LOCALE, Locale.getDefault().toString()); + String eAHardwareId = SynergyEnvironment.getComponent().getEAHardwareId(); + if (Utility.validString(eAHardwareId)) { + hashMap.put("hwId", eAHardwareId); + } + Map map = this.urlParameters; + if (map != null) { + hashMap.putAll(map); + } + this.httpRequest.url = Network.generateURL(this.baseUrl + this.api, hashMap); + IHttpRequest.Method method = this.httpRequest.method; + if ((method == IHttpRequest.Method.POST || method == IHttpRequest.Method.PUT) && (iJsonData = this.jsonData) != null && iJsonData.size() > 0) { + String convertObjectToJSONString = Utility.convertObjectToJSONString(this.jsonData.getData()); + this.httpRequest.data = new ByteArrayOutputStream(); + try { + this.httpRequest.data.write(convertObjectToJSONString.getBytes()); + } catch (IOException e) { + throw new Error(Error.Code.INVALID_ARGUMENT, "Error converting jsonData in SynergyRequest to a data stream", e); + } + } + } +} diff --git a/decompiled-reference/com/firemonkeys/cloudcellapi/HttpRequest.java b/decompiled-reference/com/firemonkeys/cloudcellapi/HttpRequest.java new file mode 100644 index 000000000..77e1f509b --- /dev/null +++ b/decompiled-reference/com/firemonkeys/cloudcellapi/HttpRequest.java @@ -0,0 +1,116 @@ +package com.firemonkeys.cloudcellapi; + +import com.mbridge.msdk.newreward.function.common.MBridgeCommon; +import java.security.SecureRandom; +import java.util.List; +import java.util.Map; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLContext; +import javax.net.ssl.TrustManager; +import org.apache.http.conn.ssl.SSLSocketFactory; + +/* loaded from: classes2.dex */ +public class HttpRequest { + private static final String CLASSNAME = "HttpRequest"; + private static boolean s_sslContextInit = false; + public static String s_userAgent; + HttpThread m_thread = null; + private double m_serverTime = 0.0d; + private boolean m_bSSLCheck = false; + private int m_TimeoutMilliseconds = MBridgeCommon.DEFAULT_LOAD_TIMEOUT; + + public native void completeCallback(long j, int i); + + public native void dataCallback(long j, byte[] bArr, int i); + + public native void errorCallback(long j, int i); + + public boolean getSSLCheck() { + return this.m_bSSLCheck; + } + + public double getServerTime() { + return this.m_serverTime; + } + + public int getTimeoutMilliseconds() { + return this.m_TimeoutMilliseconds; + } + + public native void headerCallback(long j, int i, Map> map); + + public boolean isClosed() { + return this.m_thread == null; + } + + public HttpRequest() { + System.setProperty("http.keepAlive", "false"); + } + + public void init(String str, String str2, String str3, byte[] bArr, int i, long j, boolean z, double d, boolean z2, boolean z3, int i2) { + this.m_serverTime = d; + this.m_bSSLCheck = z2; + if (i2 > 0) { + this.m_TimeoutMilliseconds = i2 * 1000; + } + initSSLContext(); + initUserAgent(str); + this.m_thread = new HttpThread(this, str2, str3, bArr, i, j, z, z3); + } + + public void setClosedBySSLCheck(boolean z) { + this.m_thread.setClosedBySSLCheck(z); + } + + public void shutdown() { + HttpThread httpThread = this.m_thread; + if (httpThread != null) { + httpThread.shutdown(); + } + } + + public void addHeader(String str, String str2) { + this.m_thread.addHeader(str, str2); + } + + public void post() { + HttpThread httpThread = this.m_thread; + if (httpThread == null) { + Logging.CC_ERROR(CLASSNAME, "post() called but thread is already closed"); + } else if (httpThread.isAlive()) { + Logging.CC_ERROR(CLASSNAME, "post() called but thread is already running"); + } else { + this.m_thread.start(); + } + } + + public void close() { + HttpThread httpThread = this.m_thread; + if (httpThread != null) { + httpThread.interrupt(); + } + this.m_thread = null; + } + + private static void initUserAgent(String str) { + if (s_userAgent != null) { + return; + } + s_userAgent = str + " " + System.getProperty("http.agent"); + StringBuilder sb = new StringBuilder(); + sb.append("User Agent: "); + sb.append(s_userAgent); + Logging.CC_INFO(CLASSNAME, sb.toString()); + } + + private void initSSLContext() { + try { + SSLContext sSLContext = SSLContext.getInstance("TLS"); + sSLContext.init(null, new TrustManager[]{new CloudcellTrustManager(this)}, new SecureRandom()); + HttpsURLConnection.setDefaultSSLSocketFactory(new TLSSocketFactory(sSLContext.getSocketFactory())); + HttpsURLConnection.setDefaultHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); + } catch (Exception unused) { + Logging.CC_ERROR(CLASSNAME, "Exception when trying to init SSLContext!"); + } + } +} diff --git a/decompiled-reference/resources/AndroidManifest.xml b/decompiled-reference/resources/AndroidManifest.xml new file mode 100644 index 000000000..8b1f1e3f7 --- /dev/null +++ b/decompiled-reference/resources/AndroidManifest.xml @@ -0,0 +1,982 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +