diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsControllerTest.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsControllerTest.java index dc9fa053a7c..b24f4cf5ff5 100644 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsControllerTest.java +++ b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsControllerTest.java @@ -39,9 +39,9 @@ import com.google.firebase.crashlytics.internal.analytics.AnalyticsEventLogger; import com.google.firebase.crashlytics.internal.metadata.LogFileManager; import com.google.firebase.crashlytics.internal.persistence.FileStore; -import com.google.firebase.crashlytics.internal.settings.SettingsDataProvider; -import com.google.firebase.crashlytics.internal.settings.TestSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; +import com.google.firebase.crashlytics.internal.settings.Settings; +import com.google.firebase.crashlytics.internal.settings.SettingsProvider; +import com.google.firebase.crashlytics.internal.settings.TestSettings; import com.google.firebase.installations.FirebaseInstallationsApi; import java.io.File; import java.util.Arrays; @@ -58,7 +58,7 @@ public class CrashlyticsControllerTest extends CrashlyticsTestCase { private Context testContext; private IdManager idManager; - private SettingsDataProvider testSettingsDataProvider; + private SettingsProvider testSettingsProvider; private FileStore testFileStore; private SessionReportingCoordinator mockSessionReportingCoordinator; private DataCollectionArbiter mockDataCollectionArbiter; @@ -81,17 +81,16 @@ protected void setUp() throws Exception { testFileStore = new FileStore(testContext); - final SettingsData testSettingsData = new TestSettingsData(3); + Settings testSettings = new TestSettings(3); mockSessionReportingCoordinator = mock(SessionReportingCoordinator.class); mockDataCollectionArbiter = mock(DataCollectionArbiter.class); when(mockDataCollectionArbiter.isAutomaticDataCollectionEnabled()).thenReturn(true); - testSettingsDataProvider = mock(SettingsDataProvider.class); - when(testSettingsDataProvider.getSettings()).thenReturn(testSettingsData); - when(testSettingsDataProvider.getAppSettings()) - .thenReturn(Tasks.forResult(testSettingsData.appData)); + testSettingsProvider = mock(SettingsProvider.class); + when(testSettingsProvider.getSettingsSync()).thenReturn(testSettings); + when(testSettingsProvider.getSettingsAsync()).thenReturn(Tasks.forResult(testSettings)); } /** A convenience class for building CrashlyticsController instances for testing. */ @@ -185,7 +184,7 @@ public void testWriteNonFatal_callsSessionReportingCoordinatorPersistNonFatal() .thenReturn(new TreeSet<>(Collections.singleton(sessionId))); controller.writeNonFatalException(thread, nonFatal); - controller.doCloseSessions(testSettingsDataProvider); + controller.doCloseSessions(testSettingsProvider); verify(mockSessionReportingCoordinator) .persistNonFatalEvent(eq(nonFatal), eq(thread), eq(sessionId), anyLong()); @@ -200,7 +199,7 @@ public void testFatalException_callsSessionReportingCoordinatorPersistFatal() th when(mockSessionReportingCoordinator.listSortedOpenSessionIds()) .thenReturn(new TreeSet<>(Collections.singleton(sessionId))); - controller.handleUncaughtException(testSettingsDataProvider, thread, fatal); + controller.handleUncaughtException(testSettingsProvider, thread, fatal); verify(mockSessionReportingCoordinator) .persistFatalEvent(eq(fatal), eq(thread), eq(sessionId), anyLong()); @@ -274,7 +273,7 @@ public File getOsFile() { final CrashlyticsController controller = builder().setNativeComponent(mockNativeComponent).setLogFileManager(logFileManager).build(); - controller.finalizeSessions(testSettingsDataProvider); + controller.finalizeSessions(testSettingsProvider); verify(mockSessionReportingCoordinator) .finalizeSessionWithNativeEvent(eq(previousSessionId), any()); verify(mockSessionReportingCoordinator, never()) @@ -283,7 +282,7 @@ public File getOsFile() { public void testMissingNativeComponentCausesNoReports() { final CrashlyticsController controller = createController(); - controller.finalizeSessions(testSettingsDataProvider); + controller.finalizeSessions(testSettingsProvider); List sessions = testFileStore.getAllOpenSessionIds(); for (String sessionId : sessions) { @@ -300,7 +299,7 @@ public void testMissingNativeComponentCausesNoReports() { public void testLoggedExceptionsAfterCrashOk() { final CrashlyticsController controller = builder().build(); controller.handleUncaughtException( - testSettingsDataProvider, Thread.currentThread(), new RuntimeException()); + testSettingsProvider, Thread.currentThread(), new RuntimeException()); // This should not throw. controller.writeNonFatalException(Thread.currentThread(), new RuntimeException()); @@ -314,7 +313,7 @@ public void testLoggedExceptionsAfterCrashOk() { public void testLogStringAfterCrashOk() { final CrashlyticsController controller = builder().build(); controller.handleUncaughtException( - testSettingsDataProvider, Thread.currentThread(), new RuntimeException()); + testSettingsProvider, Thread.currentThread(), new RuntimeException()); // This should not throw. controller.writeToLog(System.currentTimeMillis(), "Hi"); @@ -328,10 +327,10 @@ public void testLogStringAfterCrashOk() { public void testFinalizeSessionAfterCrashOk() throws Exception { final CrashlyticsController controller = builder().build(); controller.handleUncaughtException( - testSettingsDataProvider, Thread.currentThread(), new RuntimeException()); + testSettingsProvider, Thread.currentThread(), new RuntimeException()); // This should not throw. - controller.finalizeSessions(testSettingsDataProvider); + controller.finalizeSessions(testSettingsProvider); } public void testUploadWithNoReports() throws Exception { @@ -339,7 +338,7 @@ public void testUploadWithNoReports() throws Exception { final CrashlyticsController controller = createController(); - Task task = controller.submitAllReports(testSettingsDataProvider.getAppSettings()); + Task task = controller.submitAllReports(testSettingsProvider.getSettingsAsync()); await(task); @@ -354,7 +353,7 @@ public void testUploadWithDataCollectionAlwaysEnabled() throws Exception { final CrashlyticsController controller = createController(); - final Task task = controller.submitAllReports(testSettingsDataProvider.getAppSettings()); + final Task task = controller.submitAllReports(testSettingsProvider.getSettingsAsync()); await(task); @@ -380,7 +379,7 @@ public void testUploadDisabledThenOptIn() throws Exception { builder.setDataCollectionArbiter(arbiter); final CrashlyticsController controller = builder.build(); - final Task task = controller.submitAllReports(testSettingsDataProvider.getAppSettings()); + final Task task = controller.submitAllReports(testSettingsProvider.getSettingsAsync()); verify(arbiter).isAutomaticDataCollectionEnabled(); verify(mockSessionReportingCoordinator).hasReportsToSend(); @@ -407,7 +406,7 @@ public void testUploadDisabledThenOptOut() throws Exception { builder.setDataCollectionArbiter(arbiter); final CrashlyticsController controller = builder.build(); - final Task task = controller.submitAllReports(testSettingsDataProvider.getAppSettings()); + final Task task = controller.submitAllReports(testSettingsProvider.getSettingsAsync()); verify(arbiter).isAutomaticDataCollectionEnabled(); verify(mockSessionReportingCoordinator).hasReportsToSend(); @@ -448,7 +447,7 @@ public void testUploadDisabledThenEnabled() throws Exception { builder.setDataCollectionArbiter(arbiter); final CrashlyticsController controller = builder.build(); - final Task task = controller.submitAllReports(testSettingsDataProvider.getAppSettings()); + final Task task = controller.submitAllReports(testSettingsProvider.getSettingsAsync()); verify(mockSessionReportingCoordinator).hasReportsToSend(); verify(mockSessionReportingCoordinator, never()).sendReports(any(Executor.class)); @@ -491,8 +490,8 @@ public void testFatalEvent_sendsAppExceptionEvent() { controller.openSession(SESSION_ID); controller.handleUncaughtException( - testSettingsDataProvider, Thread.currentThread(), new RuntimeException("Fatal")); - controller.finalizeSessions(testSettingsDataProvider); + testSettingsProvider, Thread.currentThread(), new RuntimeException("Fatal")); + controller.finalizeSessions(testSettingsProvider); assertFirebaseAnalyticsCrashEvent(mockFirebaseAnalyticsLogger); } diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCoreInitializationTest.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCoreInitializationTest.java index ec2cf12330c..5fb2daa4952 100644 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCoreInitializationTest.java +++ b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCoreInitializationTest.java @@ -34,9 +34,9 @@ import com.google.firebase.crashlytics.internal.analytics.UnavailableAnalyticsEventLogger; import com.google.firebase.crashlytics.internal.breadcrumbs.DisabledBreadcrumbSource; import com.google.firebase.crashlytics.internal.persistence.FileStore; +import com.google.firebase.crashlytics.internal.settings.Settings; import com.google.firebase.crashlytics.internal.settings.SettingsController; -import com.google.firebase.crashlytics.internal.settings.TestSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; +import com.google.firebase.crashlytics.internal.settings.TestSettings; import com.google.firebase.inject.Deferred; import com.google.firebase.installations.FirebaseInstallationsApi; import java.io.File; @@ -71,9 +71,9 @@ protected void setUp() throws Exception { fileStore = new FileStore(getContext()); mockSettingsController = mock(SettingsController.class); - final SettingsData settingsData = new TestSettingsData(); - when(mockSettingsController.getSettings()).thenReturn(settingsData); - when(mockSettingsController.getAppSettings()).thenReturn(Tasks.forResult(settingsData.appData)); + Settings settings = new TestSettings(); + when(mockSettingsController.getSettingsSync()).thenReturn(settings); + when(mockSettingsController.getSettingsAsync()).thenReturn(Tasks.forResult(settings)); } @Override diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCoreTest.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCoreTest.java index a7475e8b89e..ed8dbc31781 100644 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCoreTest.java +++ b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCoreTest.java @@ -39,9 +39,9 @@ import com.google.firebase.crashlytics.internal.breadcrumbs.DisabledBreadcrumbSource; import com.google.firebase.crashlytics.internal.metadata.UserMetadata; import com.google.firebase.crashlytics.internal.persistence.FileStore; +import com.google.firebase.crashlytics.internal.settings.Settings; import com.google.firebase.crashlytics.internal.settings.SettingsController; -import com.google.firebase.crashlytics.internal.settings.TestSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; +import com.google.firebase.crashlytics.internal.settings.TestSettings; import com.google.firebase.inject.Deferred; import com.google.firebase.installations.FirebaseInstallationsApi; import java.util.HashMap; @@ -339,9 +339,9 @@ private Task startCoreAsync(CrashlyticsCore crashlyticsCore) { Thread.setDefaultUncaughtExceptionHandler(NOOP_HANDLER); SettingsController mockSettingsController = mock(SettingsController.class); - final SettingsData settings = new TestSettingsData(3); - when(mockSettingsController.getSettings()).thenReturn(settings); - when(mockSettingsController.getAppSettings()).thenReturn(Tasks.forResult(settings.appData)); + final Settings settings = new TestSettings(3); + when(mockSettingsController.getSettingsSync()).thenReturn(settings); + when(mockSettingsController.getSettingsAsync()).thenReturn(Tasks.forResult(settings)); AppData appData = new AppData( diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/persistence/CrashlyticsReportPersistenceTest.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/persistence/CrashlyticsReportPersistenceTest.java index 95d5edc9dcc..67794cc16d9 100644 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/persistence/CrashlyticsReportPersistenceTest.java +++ b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/persistence/CrashlyticsReportPersistenceTest.java @@ -28,9 +28,9 @@ import com.google.firebase.crashlytics.internal.model.CrashlyticsReport.Session.Event.Application.Execution.Signal; import com.google.firebase.crashlytics.internal.model.CrashlyticsReport.Session.Event.Application.Execution.Thread.Frame; import com.google.firebase.crashlytics.internal.model.ImmutableList; -import com.google.firebase.crashlytics.internal.settings.SettingsDataProvider; -import com.google.firebase.crashlytics.internal.settings.model.SessionSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.Settings; +import com.google.firebase.crashlytics.internal.settings.Settings; +import com.google.firebase.crashlytics.internal.settings.Settings.FeatureFlagData; +import com.google.firebase.crashlytics.internal.settings.SettingsProvider; import java.io.IOException; import java.text.DecimalFormat; import java.util.ArrayList; @@ -48,15 +48,18 @@ public class CrashlyticsReportPersistenceTest extends CrashlyticsTestCase { private CrashlyticsReportPersistence reportPersistence; private FileStore fileStore; - private static SettingsDataProvider getSettingsMock( + private static SettingsProvider createSettingsProviderMock( int maxCompleteSessionsCount, int maxCustomExceptionEvents) { - SettingsDataProvider settingsDataProvider = mock(SettingsDataProvider.class); - Settings settingsMock = mock(Settings.class); - SessionSettingsData sessionSettingsDataMock = - new SessionSettingsData(maxCustomExceptionEvents, maxCompleteSessionsCount); - when(settingsMock.getSessionData()).thenReturn(sessionSettingsDataMock); - when(settingsDataProvider.getSettings()).thenReturn(settingsMock); - return settingsDataProvider; + + SettingsProvider settingsProvider = mock(SettingsProvider.class); + + Settings.SessionData sessionData = + new Settings.SessionData(maxCustomExceptionEvents, maxCompleteSessionsCount); + Settings settings = + new Settings(0, sessionData, new FeatureFlagData(true, false), 3, 0, 1.0, 1.0, 1); + + when(settingsProvider.getSettingsSync()).thenReturn(settings); + return settingsProvider; } @Override @@ -64,7 +67,7 @@ public void setUp() throws Exception { fileStore = new FileStore(getContext()); reportPersistence = new CrashlyticsReportPersistence( - fileStore, getSettingsMock(VERY_LARGE_UPPER_LIMIT, VERY_LARGE_UPPER_LIMIT)); + fileStore, createSettingsProviderMock(VERY_LARGE_UPPER_LIMIT, VERY_LARGE_UPPER_LIMIT)); } public void testListSortedOpenSessionIds() { @@ -270,7 +273,8 @@ public void testFinalizeReports_skipsCappingCurrentSession() throws IOException public void testFinalizeReports_capsReports() { reportPersistence = - new CrashlyticsReportPersistence(fileStore, getSettingsMock(4, VERY_LARGE_UPPER_LIMIT)); + new CrashlyticsReportPersistence( + fileStore, createSettingsProviderMock(4, VERY_LARGE_UPPER_LIMIT)); for (int i = 0; i < 10; i++) { persistReportWithEvent(reportPersistence, "testSession" + i, true); } @@ -283,15 +287,18 @@ public void testFinalizeReports_capsReports() { } public void testFinalizeReports_whenSettingsChanges_capsReports() throws IOException { - SettingsDataProvider settingsDataProvider = mock(SettingsDataProvider.class); - Settings settingsMock = mock(Settings.class); - SessionSettingsData sessionSettingsDataMock = - new SessionSettingsData(VERY_LARGE_UPPER_LIMIT, 4); - SessionSettingsData sessionSettingsDataMockDifferentValues = - new SessionSettingsData(VERY_LARGE_UPPER_LIMIT, 8); - when(settingsMock.getSessionData()).thenReturn(sessionSettingsDataMock); - when(settingsDataProvider.getSettings()).thenReturn(settingsMock); - reportPersistence = new CrashlyticsReportPersistence(fileStore, settingsDataProvider); + SettingsProvider settingsProvider = mock(SettingsProvider.class); + + Settings.SessionData sessionData1 = new Settings.SessionData(VERY_LARGE_UPPER_LIMIT, 4); + Settings.SessionData sessionData2 = new Settings.SessionData(VERY_LARGE_UPPER_LIMIT, 8); + + Settings settings1 = + new Settings(0, sessionData1, new FeatureFlagData(true, true), 3, 0, 1.0, 1.0, 1); + Settings settings2 = + new Settings(0, sessionData2, new FeatureFlagData(true, true), 3, 0, 1.0, 1.0, 1); + + when(settingsProvider.getSettingsSync()).thenReturn(settings1); + reportPersistence = new CrashlyticsReportPersistence(fileStore, settingsProvider); DecimalFormat format = new DecimalFormat("00"); for (int i = 0; i < 16; i++) { @@ -302,7 +309,7 @@ public void testFinalizeReports_whenSettingsChanges_capsReports() throws IOExcep List finalizedReports = reportPersistence.loadFinalizedReports(); assertEquals(4, finalizedReports.size()); - when(settingsMock.getSessionData()).thenReturn(sessionSettingsDataMockDifferentValues); + when(settingsProvider.getSettingsSync()).thenReturn(settings2); for (int i = 16; i < 32; i++) { persistReportWithEvent(reportPersistence, "testSession" + i, true); @@ -316,7 +323,8 @@ public void testFinalizeReports_whenSettingsChanges_capsReports() throws IOExcep public void testFinalizeReports_removesLowPriorityReportsFirst() throws IOException { reportPersistence = - new CrashlyticsReportPersistence(fileStore, getSettingsMock(4, VERY_LARGE_UPPER_LIMIT)); + new CrashlyticsReportPersistence( + fileStore, createSettingsProviderMock(4, VERY_LARGE_UPPER_LIMIT)); for (int i = 0; i < 10; i++) { boolean priority = i >= 3 && i <= 8; @@ -338,7 +346,8 @@ public void testFinalizeReports_prioritizesNativeAndNonnativeFatals() throws IOE CrashlyticsReport.FilesPayload filesPayload = makeFilePayload(); reportPersistence = - new CrashlyticsReportPersistence(fileStore, getSettingsMock(4, VERY_LARGE_UPPER_LIMIT)); + new CrashlyticsReportPersistence( + fileStore, createSettingsProviderMock(4, VERY_LARGE_UPPER_LIMIT)); persistReportWithEvent(reportPersistence, "testSession1", true); reportPersistence.finalizeSessionWithNativeEvent("testSession1", filesPayload); @@ -360,7 +369,8 @@ public void testFinalizeReports_prioritizesNativeAndNonnativeFatals() throws IOE public void testFinalizeReports_removesOldestReportsFirst() throws IOException { reportPersistence = - new CrashlyticsReportPersistence(fileStore, getSettingsMock(4, VERY_LARGE_UPPER_LIMIT)); + new CrashlyticsReportPersistence( + fileStore, createSettingsProviderMock(4, VERY_LARGE_UPPER_LIMIT)); for (int i = 0; i < 8; i++) { String sessionId = "testSession" + i; persistReportWithEvent(reportPersistence, sessionId, true); @@ -508,7 +518,8 @@ public void testDeleteAllReports_removesAllReports() { public void testPersistEvent_keepsAppropriateNumberOfMostRecentEvents() throws IOException { reportPersistence = - new CrashlyticsReportPersistence(fileStore, getSettingsMock(VERY_LARGE_UPPER_LIMIT, 4)); + new CrashlyticsReportPersistence( + fileStore, createSettingsProviderMock(VERY_LARGE_UPPER_LIMIT, 4)); final String sessionId = "testSession"; final CrashlyticsReport testReport = makeTestReport(sessionId); final CrashlyticsReport.Session.Event testEvent1 = makeTestEvent("type1", "reason1"); @@ -542,15 +553,17 @@ public void testPersistEvent_keepsAppropriateNumberOfMostRecentEvents() throws I public void testPersistEvent_whenSettingsChanges_keepsAppropriateNumberOfMostRecentEvents() throws IOException { - SettingsDataProvider settingsDataProvider = mock(SettingsDataProvider.class); - Settings settingsMock = mock(Settings.class); - SessionSettingsData sessionSettingsDataMock = - new SessionSettingsData(4, VERY_LARGE_UPPER_LIMIT); - SessionSettingsData sessionSettingsDataMockDifferentValues = - new SessionSettingsData(8, VERY_LARGE_UPPER_LIMIT); - when(settingsMock.getSessionData()).thenReturn(sessionSettingsDataMock); - when(settingsDataProvider.getSettings()).thenReturn(settingsMock); - reportPersistence = new CrashlyticsReportPersistence(fileStore, settingsDataProvider); + SettingsProvider settingsProvider = mock(SettingsProvider.class); + Settings.SessionData sessionData1 = new Settings.SessionData(4, VERY_LARGE_UPPER_LIMIT); + Settings.SessionData sessionData2 = new Settings.SessionData(8, VERY_LARGE_UPPER_LIMIT); + + Settings settings1 = + new Settings(0, sessionData1, new FeatureFlagData(true, true), 3, 0, 1.0, 1.0, 1); + Settings settings2 = + new Settings(0, sessionData2, new FeatureFlagData(true, true), 3, 0, 1.0, 1.0, 1); + + when(settingsProvider.getSettingsSync()).thenReturn(settings1); + reportPersistence = new CrashlyticsReportPersistence(fileStore, settingsProvider); final String sessionId = "testSession"; final CrashlyticsReport testReport = makeTestReport(sessionId); @@ -582,7 +595,7 @@ public void testPersistEvent_whenSettingsChanges_keepsAppropriateNumberOfMostRec .withEvents(ImmutableList.from(testEvent2, testEvent3, testEvent4, testEvent5)), finalizedReport); - when(settingsMock.getSessionData()).thenReturn(sessionSettingsDataMockDifferentValues); + when(settingsProvider.getSettingsSync()).thenReturn(settings2); final CrashlyticsReport.Session.Event testEvent6 = makeTestEvent("type6", "reason6"); final CrashlyticsReport.Session.Event testEvent7 = makeTestEvent("type7", "reason7"); @@ -631,7 +644,8 @@ public void testPersistEvent_whenSettingsChanges_keepsAppropriateNumberOfMostRec public void testPersistReportWithAnrEvent() throws IOException { reportPersistence = - new CrashlyticsReportPersistence(fileStore, getSettingsMock(VERY_LARGE_UPPER_LIMIT, 4)); + new CrashlyticsReportPersistence( + fileStore, createSettingsProviderMock(VERY_LARGE_UPPER_LIMIT, 4)); final String sessionId = "testSession"; final CrashlyticsReport testReport = makeTestReport(sessionId); final Event testEvent = makeTestAnrEvent(); diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsControllerTest.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsControllerTest.java index 98918f0cfa9..8d20f9c586b 100644 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsControllerTest.java +++ b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsControllerTest.java @@ -31,9 +31,6 @@ import com.google.firebase.crashlytics.internal.common.DeliveryMechanism; import com.google.firebase.crashlytics.internal.common.ExecutorUtils; import com.google.firebase.crashlytics.internal.common.InstallIdProvider; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SettingsRequest; -import com.google.firebase.crashlytics.internal.settings.network.SettingsSpiCall; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; import org.json.JSONObject; @@ -70,7 +67,7 @@ SettingsController newSettingsController( CachedSettingsIo cachedSettingsIo, SettingsSpiCall settingsSpiCall, DataCollectionArbiter dataCollectionArbiter, - final boolean buildInstanceIdentifierChanged) { + boolean buildInstanceIdentifierChanged) { return new SettingsController( getContext(), settingsRequest, @@ -102,18 +99,18 @@ private T await(Task task) throws Exception { } public void testCachedSettingsLoad() throws Exception { - final JSONObject cachedJson = new JSONObject(); + JSONObject cachedJson = new JSONObject(); when(mockCachedSettingsIo.readCachedSettings()).thenReturn(cachedJson); when(mockCurrentTimeProvider.getCurrentTimeMillis()) .thenReturn(Long.valueOf(UNEXPIRED_CURRENT_TIME_MILLIS)); - final SettingsData cachedSettings = new TestSettingsData(); + Settings cachedSettings = new TestSettings(); when(mockSettingsJsonParser.parseSettingsJson(cachedJson)).thenReturn(cachedSettings); - final SettingsRequest requestData = buildSettingsRequest(); + SettingsRequest requestData = buildSettingsRequest(); - final SettingsController controller = + SettingsController controller = newSettingsController( requestData, mockCurrentTimeProvider, @@ -124,8 +121,7 @@ public void testCachedSettingsLoad() throws Exception { false); await(controller.loadSettingsData(networkExecutor)); - assertEquals(cachedSettings, controller.getSettings()); - assertEquals(cachedSettings.appData, await(controller.getAppSettings())); + assertEquals(cachedSettings, controller.getSettingsSync()); verifyZeroInteractions(mockSettingsSpiCall); verify(mockCachedSettingsIo).readCachedSettings(); @@ -134,9 +130,9 @@ public void testCachedSettingsLoad() throws Exception { } public void testCachedSettingsLoad_newInstanceIdentifier() throws Exception { - final SettingsData fetchedSettings = new TestSettingsData(); + Settings fetchedSettings = new TestSettings(); - final JSONObject fetchedJson = new JSONObject(); + JSONObject fetchedJson = new JSONObject(); when(mockSettingsSpiCall.invoke(any(SettingsRequest.class), eq(true))).thenReturn(fetchedJson); when(mockSettingsJsonParser.parseSettingsJson(fetchedJson)).thenReturn(fetchedSettings); @@ -145,8 +141,8 @@ public void testCachedSettingsLoad_newInstanceIdentifier() throws Exception { when(mockDataCollectionArbiter.waitForDataCollectionPermission(any(Executor.class))) .thenReturn(dataCollectionPermission.getTask()); - final SettingsRequest requestData = buildSettingsRequest(); - final SettingsController controller = + SettingsRequest requestData = buildSettingsRequest(); + SettingsController controller = newSettingsController( requestData, mockCurrentTimeProvider, @@ -157,11 +153,11 @@ public void testCachedSettingsLoad_newInstanceIdentifier() throws Exception { true); controller.loadSettingsData(SettingsCacheBehavior.SKIP_CACHE_LOOKUP, networkExecutor); - assertNotNull(controller.getSettings()); + assertNotNull(controller.getSettingsSync()); dataCollectionPermission.trySetResult(null); - assertEquals(fetchedSettings.appData, await(controller.getAppSettings())); - assertEquals(fetchedSettings, controller.getSettings()); + assertEquals(fetchedSettings, await(controller.getSettingsAsync())); + assertEquals(fetchedSettings, controller.getSettingsSync()); verify(mockSettingsSpiCall).invoke(any(SettingsRequest.class), eq(true)); verify(mockCachedSettingsIo).writeCachedSettings(fetchedSettings.expiresAtMillis, fetchedJson); @@ -171,13 +167,13 @@ public void testCachedSettingsLoad_newInstanceIdentifier() throws Exception { public void testExpiredCachedSettingsLoad() throws Exception { - final SettingsData cachedSettings = new TestSettingsData(); - final SettingsData fetchedSettings = new TestSettingsData(); + Settings cachedSettings = new TestSettings(); + Settings fetchedSettings = new TestSettings(); - final JSONObject fetchedJson = new JSONObject(); + JSONObject fetchedJson = new JSONObject(); when(mockSettingsSpiCall.invoke(any(SettingsRequest.class), eq(true))).thenReturn(fetchedJson); - final JSONObject cachedJson = new JSONObject(); + JSONObject cachedJson = new JSONObject(); when(mockCachedSettingsIo.readCachedSettings()).thenReturn(cachedJson); when(mockCurrentTimeProvider.getCurrentTimeMillis()) @@ -190,8 +186,8 @@ public void testExpiredCachedSettingsLoad() throws Exception { when(mockDataCollectionArbiter.waitForDataCollectionPermission(any(Executor.class))) .thenReturn(dataCollectionPermission.getTask()); - final SettingsRequest requestData = buildSettingsRequest(); - final SettingsController controller = + SettingsRequest requestData = buildSettingsRequest(); + SettingsController controller = newSettingsController( requestData, mockCurrentTimeProvider, @@ -203,14 +199,13 @@ public void testExpiredCachedSettingsLoad() throws Exception { Task loadFinished = controller.loadSettingsData(networkExecutor); - assertEquals(cachedSettings, controller.getSettings()); - assertEquals(cachedSettings.appData, await(controller.getAppSettings())); + assertEquals(cachedSettings, controller.getSettingsSync()); + assertEquals(cachedSettings, await(controller.getSettingsAsync())); dataCollectionPermission.trySetResult(null); await(loadFinished); - assertEquals(fetchedSettings.appData, await(controller.getAppSettings())); - assertEquals(fetchedSettings, controller.getSettings()); + assertEquals(fetchedSettings, controller.getSettingsSync()); verify(mockSettingsSpiCall).invoke(any(SettingsRequest.class), eq(true)); verify(mockCachedSettingsIo, times(2)).readCachedSettings(); @@ -221,17 +216,17 @@ public void testExpiredCachedSettingsLoad() throws Exception { } public void testIgnoreExpiredCachedSettingsLoad() throws Exception { - final JSONObject cachedJson = new JSONObject(); + JSONObject cachedJson = new JSONObject(); when(mockCachedSettingsIo.readCachedSettings()).thenReturn(cachedJson); when(mockCurrentTimeProvider.getCurrentTimeMillis()) .thenReturn(Long.valueOf(EXPIRED_CURRENT_TIME_MILLIS)); - final SettingsData cachedSettings = new TestSettingsData(); + Settings cachedSettings = new TestSettings(); when(mockSettingsJsonParser.parseSettingsJson(cachedJson)).thenReturn(cachedSettings); - final SettingsRequest requestData = buildSettingsRequest(); - final SettingsController controller = + SettingsRequest requestData = buildSettingsRequest(); + SettingsController controller = newSettingsController( requestData, mockCurrentTimeProvider, @@ -241,8 +236,7 @@ public void testIgnoreExpiredCachedSettingsLoad() throws Exception { mockDataCollectionArbiter, false); controller.loadSettingsData(SettingsCacheBehavior.IGNORE_CACHE_EXPIRATION, networkExecutor); - assertEquals(cachedSettings, controller.getSettings()); - assertEquals(cachedSettings.appData, await(controller.getAppSettings())); + assertEquals(cachedSettings, controller.getSettingsSync()); verifyZeroInteractions(mockSettingsSpiCall); verify(mockCachedSettingsIo).readCachedSettings(); @@ -252,20 +246,19 @@ public void testIgnoreExpiredCachedSettingsLoad() throws Exception { public void testSkipCachedSettingsLoad() throws Exception { - final SettingsData fetchedSettings = new TestSettingsData(); - - final JSONObject fetchedJson = new JSONObject(); + Settings fetchedSettings = new TestSettings(); + JSONObject fetchedJson = new JSONObject(); when(mockSettingsSpiCall.invoke(any(SettingsRequest.class), eq(true))).thenReturn(fetchedJson); when(mockSettingsJsonParser.parseSettingsJson(fetchedJson)).thenReturn(fetchedSettings); - final JSONObject expiredCachedSettingsJson = new JSONObject(); + JSONObject expiredCachedSettingsJson = new JSONObject(); when(mockCachedSettingsIo.readCachedSettings()).thenReturn(expiredCachedSettingsJson); when(mockCurrentTimeProvider.getCurrentTimeMillis()) .thenReturn(Long.valueOf(EXPIRED_CURRENT_TIME_MILLIS)); - final SettingsData expiredCachedSettings = new TestSettingsData(); + Settings expiredCachedSettings = new TestSettings(); when(mockSettingsJsonParser.parseSettingsJson(expiredCachedSettingsJson)) .thenReturn(expiredCachedSettings); @@ -273,8 +266,8 @@ public void testSkipCachedSettingsLoad() throws Exception { when(mockDataCollectionArbiter.waitForDataCollectionPermission(any(Executor.class))) .thenReturn(dataCollectionPermission.getTask()); - final SettingsRequest requestData = buildSettingsRequest(); - final SettingsController controller = + SettingsRequest requestData = buildSettingsRequest(); + SettingsController controller = newSettingsController( requestData, mockCurrentTimeProvider, @@ -286,14 +279,12 @@ public void testSkipCachedSettingsLoad() throws Exception { Task loadFinished = controller.loadSettingsData(SettingsCacheBehavior.SKIP_CACHE_LOOKUP, networkExecutor); - assertEquals(expiredCachedSettings.appData, await(controller.getAppSettings())); - assertEquals(expiredCachedSettings, controller.getSettings()); + assertEquals(expiredCachedSettings, controller.getSettingsSync()); dataCollectionPermission.trySetResult(null); await(loadFinished); - assertEquals(fetchedSettings.appData, await(controller.getAppSettings())); - assertEquals(fetchedSettings, controller.getSettings()); + assertEquals(fetchedSettings, controller.getSettingsSync()); verify(mockSettingsSpiCall).invoke(any(SettingsRequest.class), eq(true)); verify(mockCachedSettingsIo).readCachedSettings(); @@ -312,13 +303,13 @@ public void testSkipCachedSettingsLoad() throws Exception { public void testLastDitchSettingsLoad() throws Exception { when(mockSettingsSpiCall.invoke(any(SettingsRequest.class), eq(true))).thenReturn(null); - final JSONObject expiredCachedSettingsJson = new JSONObject(); + JSONObject expiredCachedSettingsJson = new JSONObject(); when(mockCachedSettingsIo.readCachedSettings()).thenReturn(expiredCachedSettingsJson); when(mockCurrentTimeProvider.getCurrentTimeMillis()) .thenReturn(Long.valueOf(EXPIRED_CURRENT_TIME_MILLIS)); - final SettingsData expiredCachedSettings = new TestSettingsData(); + Settings expiredCachedSettings = new TestSettings(); when(mockSettingsJsonParser.parseSettingsJson(expiredCachedSettingsJson)) .thenReturn(expiredCachedSettings); @@ -326,8 +317,8 @@ public void testLastDitchSettingsLoad() throws Exception { when(mockDataCollectionArbiter.waitForDataCollectionPermission(any(Executor.class))) .thenReturn(dataCollectionPermission.getTask()); - final SettingsRequest requestData = buildSettingsRequest(); - final SettingsController controller = + SettingsRequest requestData = buildSettingsRequest(); + SettingsController controller = newSettingsController( requestData, mockCurrentTimeProvider, @@ -339,14 +330,12 @@ public void testLastDitchSettingsLoad() throws Exception { Task loadFinished = controller.loadSettingsData(SettingsCacheBehavior.SKIP_CACHE_LOOKUP, networkExecutor); - assertEquals(expiredCachedSettings, controller.getSettings()); - assertEquals(expiredCachedSettings.appData, await(controller.getAppSettings())); + assertEquals(expiredCachedSettings, controller.getSettingsSync()); dataCollectionPermission.trySetResult(null); await(loadFinished); - assertEquals(expiredCachedSettings.appData, await(controller.getAppSettings())); - assertEquals(expiredCachedSettings, controller.getSettings()); + assertEquals(expiredCachedSettings, controller.getSettingsSync()); verify(mockSettingsSpiCall).invoke(any(SettingsRequest.class), eq(true)); verify(mockCachedSettingsIo).readCachedSettings(); @@ -363,8 +352,8 @@ public void testNoAvailableSettingsLoad() throws Exception { when(mockDataCollectionArbiter.waitForDataCollectionPermission(any(Executor.class))) .thenReturn(dataCollectionPermission.getTask()); - final SettingsRequest requestData = buildSettingsRequest(); - final SettingsController controller = + SettingsRequest requestData = buildSettingsRequest(); + SettingsController controller = newSettingsController( requestData, mockCurrentTimeProvider, @@ -375,14 +364,14 @@ public void testNoAvailableSettingsLoad() throws Exception { false); Task loadFinished = controller.loadSettingsData(networkExecutor); - assertNotNull(controller.getSettings()); - assertFalse(controller.getAppSettings().isComplete()); + assertNotNull(controller.getSettingsSync()); + assertFalse(controller.getSettingsAsync().isComplete()); dataCollectionPermission.trySetResult(null); await(loadFinished); - assertNotNull(controller.getSettings()); - assertFalse(controller.getAppSettings().isComplete()); + assertNotNull(controller.getSettingsSync()); + assertFalse(controller.getSettingsAsync().isComplete()); verify(mockSettingsSpiCall).invoke(any(SettingsRequest.class), eq(true)); verify(mockCachedSettingsIo, times(2)).readCachedSettings(); @@ -391,7 +380,7 @@ public void testNoAvailableSettingsLoad() throws Exception { } private SettingsRequest buildSettingsRequest() { - final InstallIdProvider installIdProvider = + InstallIdProvider installIdProvider = new InstallIdProvider() { @Override public String getCrashlyticsInstallId() { diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsJsonTransformTest.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsJsonTransformTest.java deleted file mode 100644 index 0663b7b40fb..00000000000 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsJsonTransformTest.java +++ /dev/null @@ -1,180 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.firebase.crashlytics.internal.settings; - -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -import com.google.firebase.crashlytics.internal.CrashlyticsTestCase; -import com.google.firebase.crashlytics.internal.common.CommonUtils; -import com.google.firebase.crashlytics.internal.common.CurrentTimeProvider; -import com.google.firebase.crashlytics.internal.settings.model.AppSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.FeaturesSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SessionSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; -import java.io.IOException; -import java.io.InputStream; -import org.json.JSONException; -import org.json.JSONObject; - -public class DefaultSettingsJsonTransformTest extends CrashlyticsTestCase { - - CurrentTimeProvider mockCurrentTimeProvider; - SettingsJsonTransform transform; - - @Override - protected void setUp() throws Exception { - super.setUp(); - - mockCurrentTimeProvider = mock(CurrentTimeProvider.class); - when(mockCurrentTimeProvider.getCurrentTimeMillis()).thenReturn(Long.valueOf(10)); - - transform = new DefaultSettingsJsonTransform(); - } - - public void testLoad09xSettings() throws Exception { - try { - final JSONObject testJson = getTestJSON("0_9_x-settings.json"); - - transform.buildFromJson(mockCurrentTimeProvider, testJson); - fail(); - } catch (JSONException e) { - // expected exception - } - } - - public void testSettingsJsonTransform() throws Exception { - when(mockCurrentTimeProvider.getCurrentTimeMillis()).thenReturn(Long.valueOf(10)); - - final JSONObject testJson = getTestJSON("default_settings.json"); - - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - verifySettingsDataObject(mockCurrentTimeProvider, settingsData); - } - - public void testSettingsJsonTransformWithAnalyticsDefaults() throws Exception { - final JSONObject testJson = getTestJSON("default_settings_omitted.json"); - - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - verifySettingsDataObject(mockCurrentTimeProvider, settingsData); - } - - public void testSettingsJsonTransformWithAnalyticsSampling() throws Exception { - final JSONObject testJson = getTestJSON("settings_with_sampling.json"); - - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - verifySettingsDataObject(mockCurrentTimeProvider, settingsData); - } - - public void testSettingsJsonTransform_customEventTrackingDisabled() throws Exception { - final JSONObject testJson = getTestJSON("settings_without_custom_event_tracking.json"); - - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - verifySettingsDataObject(mockCurrentTimeProvider, settingsData); - } - - public void testToJsonAndBackSurvival() throws IOException, JSONException { - final JSONObject testJson = getTestJSON("default_settings.json"); - - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - final SettingsData roundtrippedSettingsData = - transform.buildFromJson(mockCurrentTimeProvider, transform.toJson(settingsData)); - - verifySettingsDataObject(mockCurrentTimeProvider, roundtrippedSettingsData); - } - - public void testNoIconJsonTransform() throws Exception { - final JSONObject testJson = getTestJSON("no_icon_settings.json"); - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - assertEquals(3600010, settingsData.expiresAtMillis); - assertAppData(settingsData.appData); - assertSettingsData(settingsData.sessionData); - assertFeaturesData(settingsData.featuresData); - - verify(mockCurrentTimeProvider).getCurrentTimeMillis(); - } - - public void testEmptyIconJsonTransform() throws Exception { - final JSONObject testJson = getTestJSON("no_icon_settings.json"); - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - assertEquals(3600010, settingsData.expiresAtMillis); - assertAppData(settingsData.appData); - assertSettingsData(settingsData.sessionData); - assertFeaturesData(settingsData.featuresData); - - verify(mockCurrentTimeProvider).getCurrentTimeMillis(); - } - - public void testCachedJsonTransform() throws Exception { - final JSONObject testJson = getTestJSON("cached_settings.json"); - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - assertEquals(1234567890, settingsData.expiresAtMillis); - assertEquals(3600, settingsData.cacheDuration); - assertAppData(settingsData.appData); - assertSettingsData(settingsData.sessionData); - assertFeaturesData(settingsData.featuresData); - verifyZeroInteractions(mockCurrentTimeProvider); - } - - private void assertAppData(AppSettingsData appData) { - assertEquals("activated", appData.status); - assertEquals("http://localhost:3000/spi/v1/platform/android/apps", appData.url); - assertEquals( - "http://localhost:3000/spi/v1/platform/android/apps/com.crashlytics.android/reports", - appData.reportsUrl); - } - - private void assertSettingsData(SessionSettingsData settingsData) { - assertEquals(64, settingsData.maxCustomExceptionEvents); - assertEquals(4, settingsData.maxCompleteSessionsCount); - } - - private void assertFeaturesData(FeaturesSettingsData featuresSettingsData) { - assertTrue(featuresSettingsData.collectReports); - } - - private void verifySettingsDataObject( - CurrentTimeProvider mockCurrentTimeProvider, SettingsData settingsData) { - assertEquals(3600010, settingsData.expiresAtMillis); - - assertEquals(2, settingsData.settingsVersion); - assertEquals(3600, settingsData.cacheDuration); - - assertAppData(settingsData.appData); - - assertFeaturesData(settingsData.featuresData); - - assertSettingsData(settingsData.sessionData); - - verify(mockCurrentTimeProvider).getCurrentTimeMillis(); - } - - private JSONObject getTestJSON(String fileName) throws IOException, JSONException { - final InputStream jsonInputStream = getContext().getResources().getAssets().open(fileName); - final String testJsonString = CommonUtils.streamToString(jsonInputStream); - final JSONObject testJson = new JSONObject(testJsonString); - return testJson; - } -} diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/network/DefaultSettingsSpiCallTest.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsSpiCallTest.java similarity index 98% rename from firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/network/DefaultSettingsSpiCallTest.java rename to firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsSpiCallTest.java index 7f3d7c0f9eb..d9d34551bd9 100644 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/network/DefaultSettingsSpiCallTest.java +++ b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsSpiCallTest.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.firebase.crashlytics.internal.settings.network; +package com.google.firebase.crashlytics.internal.settings; import static org.mockito.Mockito.*; @@ -24,7 +24,6 @@ import com.google.firebase.crashlytics.internal.network.HttpRequestFactory; import com.google.firebase.crashlytics.internal.network.HttpResponse; import com.google.firebase.crashlytics.internal.network.InspectableHttpGetRequest; -import com.google.firebase.crashlytics.internal.settings.model.SettingsRequest; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonParserTest.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonParserTest.java index e3cde7c8386..45b45e896f4 100644 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonParserTest.java +++ b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonParserTest.java @@ -20,7 +20,6 @@ import com.google.firebase.crashlytics.internal.CrashlyticsTestCase; import com.google.firebase.crashlytics.internal.common.CommonUtils; import com.google.firebase.crashlytics.internal.common.CurrentTimeProvider; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; import java.io.IOException; import java.io.InputStream; import org.json.JSONException; @@ -42,27 +41,13 @@ protected void setUp() throws Exception { settingsJsonParser = new SettingsJsonParser(mockCurrentTimeProvider); } - public void testSettingsV2Parsing() throws Exception { - final JSONObject testJson = getTestJSON("default_settings.json"); - - final SettingsData settingsData = settingsJsonParser.parseSettingsJson(testJson); - - Assert.assertEquals( - "http://localhost:3000/spi/v1/platform/android/apps", settingsData.appData.url); - Assert.assertNull(settingsData.appData.organizationId); - Assert.assertNull(settingsData.appData.bundleId); - } - public void testSettingsV3Parsing() throws Exception { final JSONObject testJson = getTestJSON("firebase_settings.json"); - final SettingsData settingsData = settingsJsonParser.parseSettingsJson(testJson); - - Assert.assertEquals( - "https://update.crashlytics.com/spi/v1/platforms/android/apps/com.google.firebase.crashlytics.sdk.test", - settingsData.appData.url); - Assert.assertEquals("12345abcde12345abcde1234", settingsData.appData.organizationId); - Assert.assertEquals("com.google.firebase.crashlytics.sdk.test", settingsData.appData.bundleId); + Settings settings = settingsJsonParser.parseSettingsJson(testJson); + Assert.assertEquals(3, settings.settingsVersion); + Assert.assertEquals(7200, settings.cacheDuration); + Assert.assertTrue(settings.featureFlagData.collectReports); } private JSONObject getTestJSON(String fileName) throws IOException, JSONException { diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/SettingsV3JsonTransformTest.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/SettingsV3JsonTransformTest.java index 6495e7f4902..9677ee63bd2 100644 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/SettingsV3JsonTransformTest.java +++ b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/SettingsV3JsonTransformTest.java @@ -21,10 +21,6 @@ import com.google.firebase.crashlytics.internal.CrashlyticsTestCase; import com.google.firebase.crashlytics.internal.common.CommonUtils; import com.google.firebase.crashlytics.internal.common.CurrentTimeProvider; -import com.google.firebase.crashlytics.internal.settings.model.AppSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.FeaturesSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SessionSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; import java.io.IOException; import java.io.InputStream; import org.json.JSONException; @@ -45,93 +41,46 @@ protected void setUp() throws Exception { } public void testFirebaseSettingsTransform() throws Exception { - final JSONObject testJson = getTestJSON("firebase_settings.json"); + JSONObject testJson = getTestJSON("firebase_settings.json"); + Settings settings = transform.buildFromJson(mockCurrentTimeProvider, testJson); - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - verifySettingsDataObject(mockCurrentTimeProvider, settingsData, false); + verifySettingsDataObject(mockCurrentTimeProvider, settings, false); } public void testFirebaseSettingsTransform_newApp() throws Exception { - final JSONObject testJson = getTestJSON("firebase_settings_new.json"); - - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); + JSONObject testJson = getTestJSON("firebase_settings_new.json"); + Settings settings = transform.buildFromJson(mockCurrentTimeProvider, testJson); - verifySettingsDataObject(mockCurrentTimeProvider, settingsData, true); + verifySettingsDataObject(mockCurrentTimeProvider, settings, true); } public void testFirebaseSettingsTransform_collectAnrs() throws Exception { - final JSONObject testJson = getTestJSON("firebase_settings_collect_anrs.json"); - - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - verifySettingsDataObject(mockCurrentTimeProvider, settingsData, false, true); - } - - public void testToJsonAndBackSurvival() throws IOException, JSONException { - final JSONObject testJson = getTestJSON("firebase_settings.json"); - - final SettingsData settingsData = transform.buildFromJson(mockCurrentTimeProvider, testJson); - - final SettingsData roundtrippedSettingsData = - transform.buildFromJson(mockCurrentTimeProvider, transform.toJson(settingsData)); - - verifySettingsDataObject(mockCurrentTimeProvider, roundtrippedSettingsData); - } - - private void assertAppData(AppSettingsData appData, boolean isAppNew) { - assertEquals(isAppNew ? "new" : "activated", appData.status); - assertEquals( - isAppNew - ? "https://update.crashlytics.com/spi/v1/platforms/android/apps" - : "https://update.crashlytics.com/spi/v1/platforms/android/apps/com.google.firebase.crashlytics.sdk.test", - appData.url); - assertEquals( - "https://reports.crashlytics.com/spi/v1/platforms/android/apps/com.google.firebase.crashlytics.sdk.test/reports", - appData.reportsUrl); - assertEquals( - "https://reports.crashlytics.com/sdk-api/v1/platforms/android/apps/com.google.firebase.crashlytics.sdk.test/minidumps", - appData.ndkReportsUrl); - assertTrue(appData.updateRequired); - assertEquals(2, appData.reportUploadVariant); - assertEquals(2, appData.nativeReportUploadVariant); - } - - private void assertSettingsData(SessionSettingsData settingsData) { - assertEquals(8, settingsData.maxCustomExceptionEvents); - assertEquals(4, settingsData.maxCompleteSessionsCount); - } + JSONObject testJson = getTestJSON("firebase_settings_collect_anrs.json"); + Settings settings = transform.buildFromJson(mockCurrentTimeProvider, testJson); - private void assertFeaturesData(FeaturesSettingsData featuresSettingsData, boolean collectAnrs) { - assertTrue(featuresSettingsData.collectReports); - assertEquals(featuresSettingsData.collectAnrs, collectAnrs); + verifySettingsDataObject(mockCurrentTimeProvider, settings, false, true); } private void verifySettingsDataObject( - CurrentTimeProvider mockCurrentTimeProvider, SettingsData settingsData) { - verifySettingsDataObject(mockCurrentTimeProvider, settingsData, false); - } - - private void verifySettingsDataObject( - CurrentTimeProvider mockCurrentTimeProvider, SettingsData settingsData, boolean isAppNew) { - verifySettingsDataObject(mockCurrentTimeProvider, settingsData, isAppNew, false); + CurrentTimeProvider mockCurrentTimeProvider, Settings settings, boolean isAppNew) { + verifySettingsDataObject(mockCurrentTimeProvider, settings, isAppNew, false); } private void verifySettingsDataObject( CurrentTimeProvider mockCurrentTimeProvider, - SettingsData settingsData, + Settings settings, boolean isAppNew, boolean collectAnrs) { - assertEquals(7200010, settingsData.expiresAtMillis); - - assertEquals(3, settingsData.settingsVersion); - assertEquals(7200, settingsData.cacheDuration); + assertEquals(7200010, settings.expiresAtMillis); - assertAppData(settingsData.appData, isAppNew); + assertEquals(3, settings.settingsVersion); + assertEquals(7200, settings.cacheDuration); - assertFeaturesData(settingsData.featuresData, collectAnrs); + assertEquals(8, settings.sessionData.maxCustomExceptionEvents); + assertEquals(4, settings.sessionData.maxCompleteSessionsCount); - assertSettingsData(settingsData.sessionData); + assertTrue(settings.featureFlagData.collectReports); + assertEquals(settings.featureFlagData.collectAnrs, collectAnrs); verify(mockCurrentTimeProvider).getCurrentTimeMillis(); } diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsDataProvider.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/TestSettings.java similarity index 51% rename from firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsDataProvider.java rename to firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/TestSettings.java index 3f3ecad1cd4..ae82f468123 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsDataProvider.java +++ b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/TestSettings.java @@ -14,12 +14,25 @@ package com.google.firebase.crashlytics.internal.settings; -import com.google.android.gms.tasks.Task; -import com.google.firebase.crashlytics.internal.settings.model.AppSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.Settings; +public class TestSettings extends Settings { -public interface SettingsDataProvider { - Settings getSettings(); + public TestSettings() { + this(2); + } - Task getAppSettings(); + public TestSettings(int settingsVersion) { + this(settingsVersion, 0, 0); + } + + public TestSettings(int settingsVersion, int reportUploadVariant, int nativeReportUploadVariant) { + super(5, buildSettingsData(), buildFeatureFlagData(), settingsVersion, 3600, 10, 1.2, 60); + } + + private static Settings.FeatureFlagData buildFeatureFlagData() { + return new Settings.FeatureFlagData(true, false); + } + + private static Settings.SessionData buildSettingsData() { + return new Settings.SessionData(64, 4); + } } diff --git a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/TestSettingsData.java b/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/TestSettingsData.java deleted file mode 100644 index 47c3d23f1c0..00000000000 --- a/firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/TestSettingsData.java +++ /dev/null @@ -1,67 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.firebase.crashlytics.internal.settings; - -import com.google.firebase.crashlytics.internal.settings.model.AppSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.FeaturesSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SessionSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; - -public class TestSettingsData extends SettingsData { - - public TestSettingsData() { - this(2); - } - - public TestSettingsData(int settingsVersion) { - this(settingsVersion, 0, 0); - } - - public TestSettingsData( - int settingsVersion, int reportUploadVariant, int nativeReportUploadVariant) { - super( - 5, - buildAppData(reportUploadVariant, nativeReportUploadVariant), - buildSettingsData(), - buildFeaturesData(), - settingsVersion, - 3600, - 10, - 1.2, - 60); - } - - private static FeaturesSettingsData buildFeaturesData() { - return new FeaturesSettingsData(true, false); - } - - private static SessionSettingsData buildSettingsData() { - return new SessionSettingsData(64, 4); - } - - private static AppSettingsData buildAppData( - int reportUploadVariant, int nativeReportUploadVariant) { - return new AppSettingsData( - AppSettingsData.STATUS_ACTIVATED, - "http://localhost", - "http://localhost", - "http://localhost", - "testBundleId", - "testOrganizationId", - false, - reportUploadVariant, - nativeReportUploadVariant); - } -} diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java index 2d8d598975f..6f7f4ae4eb7 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java @@ -35,8 +35,8 @@ import com.google.firebase.crashlytics.internal.metadata.UserMetadata; import com.google.firebase.crashlytics.internal.model.StaticSessionData; import com.google.firebase.crashlytics.internal.persistence.FileStore; -import com.google.firebase.crashlytics.internal.settings.SettingsDataProvider; -import com.google.firebase.crashlytics.internal.settings.model.AppSettingsData; +import com.google.firebase.crashlytics.internal.settings.Settings; +import com.google.firebase.crashlytics.internal.settings.SettingsProvider; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; @@ -85,7 +85,7 @@ class CrashlyticsController { private final SessionReportingCoordinator reportingCoordinator; private CrashlyticsUncaughtExceptionHandler crashHandler; - private SettingsDataProvider settingsProvider = null; + private SettingsProvider settingsProvider = null; // A promise that will be resolved when unsent reports are found on the device, and // send/deleteUnsentReports can be called to decide how to deal with them. @@ -140,7 +140,7 @@ private Context getContext() { void enableExceptionHandling( String sessionIdentifier, Thread.UncaughtExceptionHandler defaultHandler, - SettingsDataProvider settingsProvider) { + SettingsProvider settingsProvider) { this.settingsProvider = settingsProvider; // This must be called before installing the controller with // Thread.setDefaultUncaughtExceptionHandler to ensure that we are ready to handle @@ -150,7 +150,7 @@ void enableExceptionHandling( new CrashlyticsUncaughtExceptionHandler.CrashListener() { @Override public void onUncaughtException( - @NonNull SettingsDataProvider settingsDataProvider, + @NonNull SettingsProvider settingsDataProvider, @NonNull Thread thread, @NonNull Throwable ex) { handleUncaughtException(settingsDataProvider, thread, ex); @@ -163,14 +163,14 @@ public void onUncaughtException( } void handleUncaughtException( - @NonNull SettingsDataProvider settingsDataProvider, + @NonNull SettingsProvider settingsProvider, @NonNull final Thread thread, @NonNull final Throwable ex) { - handleUncaughtException(settingsDataProvider, thread, ex, /*isOnDemand=*/ false); + handleUncaughtException(settingsProvider, thread, ex, /*isOnDemand=*/ false); } synchronized void handleUncaughtException( - @NonNull SettingsDataProvider settingsDataProvider, + @NonNull SettingsProvider settingsProvider, @NonNull final Thread thread, @NonNull final Throwable ex, boolean isOnDemand) { @@ -203,7 +203,7 @@ public Task call() throws Exception { ex, thread, currentSessionId, timestampSeconds); doWriteAppExceptionMarker(timestampMillis); - doCloseSessions(settingsDataProvider); + doCloseSessions(settingsProvider); doOpenSession(new CLSUUID(idManager).toString()); // If automatic data collection is disabled, we'll need to wait until the next run @@ -214,16 +214,15 @@ public Task call() throws Exception { Executor executor = backgroundWorker.getExecutor(); - return settingsDataProvider - .getAppSettings() + return settingsProvider + .getSettingsAsync() .onSuccessTask( executor, - new SuccessContinuation() { + new SuccessContinuation() { @NonNull @Override - public Task then(@Nullable AppSettingsData appSettingsData) - throws Exception { - if (appSettingsData == null) { + public Task then(@Nullable Settings settings) throws Exception { + if (settings == null) { Logger.getLogger() .w( "Received null app settings, cannot send reports at crash time."); @@ -325,7 +324,7 @@ Task deleteUnsentReports() { return unsentReportsHandled.getTask(); } - Task submitAllReports(Task appSettingsDataTask) { + Task submitAllReports(Task settingsDataTask) { if (!reportingCoordinator.hasReportsToSend()) { // Just notify the user that there are no reports and stop. Logger.getLogger().v("No crash reports are available to be sent."); @@ -364,12 +363,12 @@ public Task call() throws Exception { Executor executor = backgroundWorker.getExecutor(); - return appSettingsDataTask.onSuccessTask( + return settingsDataTask.onSuccessTask( executor, - new SuccessContinuation() { + new SuccessContinuation() { @NonNull @Override - public Task then(@Nullable AppSettingsData appSettingsData) + public Task then(@Nullable Settings appSettingsData) throws Exception { if (appSettingsData == null) { Logger.getLogger() @@ -507,9 +506,9 @@ private String getCurrentSessionId() { *

This method can not be called while the {@link CrashlyticsCore} settings lock is held. It * will result in a deadlock! * - * @param settingsDataProvider + * @param settingsProvider */ - boolean finalizeSessions(SettingsDataProvider settingsDataProvider) { + boolean finalizeSessions(SettingsProvider settingsProvider) { backgroundWorker.checkRunningOnThread(); if (isHandlingException()) { @@ -519,7 +518,7 @@ boolean finalizeSessions(SettingsDataProvider settingsDataProvider) { Logger.getLogger().v("Finalizing previously open sessions."); try { - doCloseSessions(true, settingsDataProvider); + doCloseSessions(true, settingsProvider); } catch (Exception e) { Logger.getLogger().e("Unable to finalize previously open sessions.", e); return false; @@ -555,16 +554,15 @@ private void doOpenSession(String sessionIdentifier) { reportingCoordinator.onBeginSession(sessionIdentifier, startedAtSeconds); } - void doCloseSessions(SettingsDataProvider settingsDataProvider) { - doCloseSessions(false, settingsDataProvider); + void doCloseSessions(SettingsProvider settingsProvider) { + doCloseSessions(false, settingsProvider); } /** * Not synchronized/locked. Must be executed from the single thread executor service used by this * class. */ - private void doCloseSessions( - boolean skipCurrentSession, SettingsDataProvider settingsDataProvider) { + private void doCloseSessions(boolean skipCurrentSession, SettingsProvider settingsProvider) { final int offset = skipCurrentSession ? 1 : 0; // :TODO HW2021 this implementation can be cleaned up. @@ -578,7 +576,7 @@ private void doCloseSessions( final String mostRecentSessionIdToClose = sortedOpenSessions.get(offset); - if (settingsDataProvider.getSettings().getFeaturesData().collectAnrs) { + if (settingsProvider.getSettingsSync().featureFlagData.collectAnrs) { writeApplicationExitInfoEventIfRelevant(mostRecentSessionIdToClose); } else { Logger.getLogger().v("ANR feature disabled."); diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCore.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCore.java index 488c861c39b..f074ea13da9 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCore.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCore.java @@ -31,8 +31,8 @@ import com.google.firebase.crashlytics.internal.metadata.LogFileManager; import com.google.firebase.crashlytics.internal.metadata.UserMetadata; import com.google.firebase.crashlytics.internal.persistence.FileStore; -import com.google.firebase.crashlytics.internal.settings.SettingsDataProvider; -import com.google.firebase.crashlytics.internal.settings.model.Settings; +import com.google.firebase.crashlytics.internal.settings.Settings; +import com.google.firebase.crashlytics.internal.settings.SettingsProvider; import com.google.firebase.crashlytics.internal.stacktrace.MiddleOutFallbackStrategy; import com.google.firebase.crashlytics.internal.stacktrace.RemoveRepeatsStrategy; import com.google.firebase.crashlytics.internal.stacktrace.StackTraceTrimmingStrategy; @@ -123,7 +123,7 @@ public CrashlyticsCore( // region Initialization - public boolean onPreExecute(AppData appData, SettingsDataProvider settingsProvider) { + public boolean onPreExecute(AppData appData, SettingsProvider settingsProvider) { // before starting the crash detector make sure that this was built with our build // tools. // Throw an exception and halt the app if the build ID is required and not present. @@ -208,7 +208,7 @@ public boolean onPreExecute(AppData appData, SettingsDataProvider settingsProvid } /** Performs background initialization asynchronously on the background worker's thread. */ - public Task doBackgroundInitializationAsync(SettingsDataProvider settingsProvider) { + public Task doBackgroundInitializationAsync(SettingsProvider settingsProvider) { return Utils.callTask( crashHandlerExecutor, new Callable>() { @@ -220,16 +220,16 @@ public Task call() throws Exception { } /** Performs background initialization synchronously on the calling thread. */ - private Task doBackgroundInitialization(SettingsDataProvider settingsProvider) { + private Task doBackgroundInitialization(SettingsProvider settingsProvider) { // create the marker for this run markInitializationStarted(); try { breadcrumbSource.registerBreadcrumbHandler(this::log); - final Settings settingsData = settingsProvider.getSettings(); + final Settings settingsData = settingsProvider.getSettingsSync(); - if (!settingsData.getFeaturesData().collectReports) { + if (!settingsData.featureFlagData.collectReports) { Logger.getLogger().d("Collection of crash reports disabled in Crashlytics settings."); // TODO: This isn't actually an error condition, so figure out the right way to // handle this case. @@ -244,7 +244,7 @@ private Task doBackgroundInitialization(SettingsDataProvider settingsProvi // TODO: Move this call out of this method, so that the return value merely indicates // initialization is complete. Callers that want to know when report sending is complete can // handle that as a separate call. - return controller.submitAllReports(settingsProvider.getAppSettings()); + return controller.submitAllReports(settingsProvider.getSettingsAsync()); } catch (Exception e) { Logger.getLogger() .e("Crashlytics encountered a problem during asynchronous initialization.", e); @@ -405,13 +405,13 @@ CrashlyticsController getController() { * When a startup crash occurs, Crashlytics must lock on the main thread and complete * initializaiton to upload crash result. 4 seconds is chosen for the lock to prevent ANR */ - private void finishInitSynchronously(SettingsDataProvider settingsDataProvider) { + private void finishInitSynchronously(SettingsProvider settingsProvider) { final Runnable runnable = new Runnable() { @Override public void run() { - doBackgroundInitialization(settingsDataProvider); + doBackgroundInitialization(settingsProvider); } }; diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsUncaughtExceptionHandler.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsUncaughtExceptionHandler.java index c168af4e28a..9a4bba92952 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsUncaughtExceptionHandler.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsUncaughtExceptionHandler.java @@ -16,19 +16,18 @@ import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponent; import com.google.firebase.crashlytics.internal.Logger; -import com.google.firebase.crashlytics.internal.settings.SettingsDataProvider; +import com.google.firebase.crashlytics.internal.settings.SettingsProvider; import java.util.concurrent.atomic.AtomicBoolean; class CrashlyticsUncaughtExceptionHandler implements Thread.UncaughtExceptionHandler { interface CrashListener { - void onUncaughtException( - SettingsDataProvider settingsDataProvider, Thread thread, Throwable ex); + void onUncaughtException(SettingsProvider settingsProvider, Thread thread, Throwable ex); } private final CrashListener crashListener; - private final SettingsDataProvider settingsDataProvider; + private final SettingsProvider settingsProvider; private final Thread.UncaughtExceptionHandler defaultHandler; private final CrashlyticsNativeComponent nativeComponent; @@ -37,11 +36,11 @@ void onUncaughtException( public CrashlyticsUncaughtExceptionHandler( CrashListener crashListener, - SettingsDataProvider settingsProvider, + SettingsProvider settingsProvider, Thread.UncaughtExceptionHandler defaultHandler, CrashlyticsNativeComponent nativeComponent) { this.crashListener = crashListener; - this.settingsDataProvider = settingsProvider; + this.settingsProvider = settingsProvider; this.defaultHandler = defaultHandler; this.isHandlingException = new AtomicBoolean(false); this.nativeComponent = nativeComponent; @@ -52,7 +51,7 @@ public void uncaughtException(Thread thread, Throwable ex) { isHandlingException.set(true); try { if (shouldRecordUncaughtException(thread, ex)) { - crashListener.onUncaughtException(settingsDataProvider, thread, ex); + crashListener.onUncaughtException(settingsProvider, thread, ex); } else { Logger.getLogger().d("Uncaught exception will not be recorded by Crashlytics."); } diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/SessionReportingCoordinator.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/SessionReportingCoordinator.java index c954b1de697..48a4903be4d 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/SessionReportingCoordinator.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/SessionReportingCoordinator.java @@ -33,7 +33,7 @@ import com.google.firebase.crashlytics.internal.persistence.CrashlyticsReportPersistence; import com.google.firebase.crashlytics.internal.persistence.FileStore; import com.google.firebase.crashlytics.internal.send.DataTransportCrashlyticsReportSender; -import com.google.firebase.crashlytics.internal.settings.SettingsDataProvider; +import com.google.firebase.crashlytics.internal.settings.SettingsProvider; import com.google.firebase.crashlytics.internal.stacktrace.StackTraceTrimmingStrategy; import java.io.ByteArrayOutputStream; import java.io.File; @@ -67,7 +67,7 @@ public static SessionReportingCoordinator create( LogFileManager logFileManager, UserMetadata userMetadata, StackTraceTrimmingStrategy stackTraceTrimmingStrategy, - SettingsDataProvider settingsProvider, + SettingsProvider settingsProvider, OnDemandCounter onDemandCounter) { final CrashlyticsReportDataCapture dataCapture = new CrashlyticsReportDataCapture(context, idManager, appData, stackTraceTrimmingStrategy); diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/persistence/CrashlyticsReportPersistence.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/persistence/CrashlyticsReportPersistence.java index ace9394f878..9cd224ceb3d 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/persistence/CrashlyticsReportPersistence.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/persistence/CrashlyticsReportPersistence.java @@ -24,7 +24,7 @@ import com.google.firebase.crashlytics.internal.model.CrashlyticsReport.Session.Event; import com.google.firebase.crashlytics.internal.model.ImmutableList; import com.google.firebase.crashlytics.internal.model.serialization.CrashlyticsReportJsonTransform; -import com.google.firebase.crashlytics.internal.settings.SettingsDataProvider; +import com.google.firebase.crashlytics.internal.settings.SettingsProvider; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; @@ -79,12 +79,11 @@ public class CrashlyticsReportPersistence { private final FileStore fileStore; - @NonNull private final SettingsDataProvider settingsDataProvider; + @NonNull private final SettingsProvider settingsProvider; - public CrashlyticsReportPersistence( - FileStore fileStore, SettingsDataProvider settingsDataProvider) { + public CrashlyticsReportPersistence(FileStore fileStore, SettingsProvider settingsProvider) { this.fileStore = fileStore; - this.settingsDataProvider = settingsDataProvider; + this.settingsProvider = settingsProvider; } public void persistReport(@NonNull CrashlyticsReport report) { @@ -128,8 +127,7 @@ public void persistEvent( @NonNull CrashlyticsReport.Session.Event event, @NonNull String sessionId, boolean isHighPriority) { - int maxEventsToKeep = - settingsDataProvider.getSettings().getSessionData().maxCustomExceptionEvents; + int maxEventsToKeep = settingsProvider.getSettingsSync().sessionData.maxCustomExceptionEvents; final String json = TRANSFORM.eventToJson(event); final String fileName = generateEventFilename(eventCounter.getAndIncrement(), isHighPriority); try { @@ -248,8 +246,7 @@ private SortedSet capAndGetOpenSessions(@Nullable String currentSessionI } private void capFinalizedReports() { - int maxReportsToKeep = - settingsDataProvider.getSettings().getSessionData().maxCompleteSessionsCount; + int maxReportsToKeep = settingsProvider.getSettingsSync().sessionData.maxCompleteSessionsCount; List finalizedReportFiles = getAllFinalizedReportFiles(); int fileCount = finalizedReportFiles.size(); diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/DataTransportCrashlyticsReportSender.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/DataTransportCrashlyticsReportSender.java index 3659b741349..7637f7218d8 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/DataTransportCrashlyticsReportSender.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/DataTransportCrashlyticsReportSender.java @@ -26,7 +26,7 @@ import com.google.firebase.crashlytics.internal.common.OnDemandCounter; import com.google.firebase.crashlytics.internal.model.CrashlyticsReport; import com.google.firebase.crashlytics.internal.model.serialization.CrashlyticsReportJsonTransform; -import com.google.firebase.crashlytics.internal.settings.SettingsDataProvider; +import com.google.firebase.crashlytics.internal.settings.SettingsProvider; import java.nio.charset.Charset; /** @@ -49,7 +49,7 @@ public class DataTransportCrashlyticsReportSender { private final Transformer transportTransform; public static DataTransportCrashlyticsReportSender create( - Context context, SettingsDataProvider settingsProvider, OnDemandCounter onDemandCounter) { + Context context, SettingsProvider settingsProvider, OnDemandCounter onDemandCounter) { TransportRuntime.initialize(context); final Transport transport = TransportRuntime.getInstance() @@ -60,7 +60,7 @@ public static DataTransportCrashlyticsReportSender create( Encoding.of("json"), DEFAULT_TRANSFORM); ReportQueue reportQueue = - new ReportQueue(transport, settingsProvider.getSettings(), onDemandCounter); + new ReportQueue(transport, settingsProvider.getSettingsSync(), onDemandCounter); return new DataTransportCrashlyticsReportSender(reportQueue, DEFAULT_TRANSFORM); } diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/ReportQueue.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/ReportQueue.java index b41ca882dbc..404cc77d9af 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/ReportQueue.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/send/ReportQueue.java @@ -21,7 +21,7 @@ import com.google.firebase.crashlytics.internal.common.CrashlyticsReportWithSessionId; import com.google.firebase.crashlytics.internal.common.OnDemandCounter; import com.google.firebase.crashlytics.internal.model.CrashlyticsReport; -import com.google.firebase.crashlytics.internal.settings.model.Settings; +import com.google.firebase.crashlytics.internal.settings.Settings; import java.util.Locale; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -50,9 +50,9 @@ final class ReportQueue { ReportQueue( Transport transport, Settings settings, OnDemandCounter onDemandCounter) { this( - settings.onDemandUploadRatePerMinute(), - settings.onDemandBackoffBase(), - (long) settings.onDemandBackoffStepDurationSeconds() * MS_PER_SECOND, + settings.onDemandUploadRatePerMinute, + settings.onDemandBackoffBase, + (long) settings.onDemandBackoffStepDurationSeconds * MS_PER_SECOND, transport, onDemandCounter); } diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsJsonTransform.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsJsonTransform.java index 48de80d5e56..e6fdf11b479 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsJsonTransform.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsJsonTransform.java @@ -15,176 +15,50 @@ package com.google.firebase.crashlytics.internal.settings; import com.google.firebase.crashlytics.internal.common.CurrentTimeProvider; -import com.google.firebase.crashlytics.internal.settings.model.AppSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.FeaturesSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SessionSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.Settings; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; -import org.json.JSONException; import org.json.JSONObject; -/** Default implementation of the JSON <-> {@link SettingsData} transform logic. */ +/** + * Default implementation of a SettingsJsonTransform that ignores the JSON and populates all fields + * with default values. + */ class DefaultSettingsJsonTransform implements SettingsJsonTransform { @Override - public SettingsData buildFromJson(CurrentTimeProvider currentTimeProvider, JSONObject json) - throws JSONException { + public Settings buildFromJson(CurrentTimeProvider currentTimeProvider, JSONObject json) { - final int settingsVersion = - json.optInt( - SettingsJsonConstants.SETTINGS_VERSION, SettingsJsonConstants.SETTINGS_VERSION_DEFAULT); - final int cacheDuration = - json.optInt( - SettingsJsonConstants.CACHE_DURATION_KEY, - SettingsJsonConstants.SETTINGS_CACHE_DURATION_DEFAULT); - final double onDemandUploadRatePerMinute = - json.optDouble( - SettingsJsonConstants.ON_DEMAND_UPLOAD_RATE_PER_MINUTE_KEY, - SettingsJsonConstants.SETTINGS_ON_DEMAND_UPLOAD_RATE_PER_MINUTE_DEFAULT); - final double onDemandBackoffBase = - json.optDouble( - SettingsJsonConstants.ON_DEMAND_BACKOFF_BASE_KEY, - SettingsJsonConstants.SETTINGS_ON_DEMAND_BACKOFF_BASE_DEFAULT); - final int onDemandBackoffStepDurationSeconds = - json.optInt( - SettingsJsonConstants.ON_DEMAND_BACKOFF_STEP_DURATION_SECONDS_KEY, - SettingsJsonConstants.SETTINGS_ON_DEMAND_BACKOFF_STEP_DURATION_SECONDS_DEFAULT); - - final AppSettingsData appData = - buildAppDataFrom(json.getJSONObject(SettingsJsonConstants.APP_KEY)); - final SessionSettingsData settingsData = - buildSessionDataFrom(json.getJSONObject(SettingsJsonConstants.SESSION_KEY)); - final FeaturesSettingsData featureData = - buildFeaturesSessionDataFrom(json.getJSONObject(SettingsJsonConstants.FEATURES_KEY)); - - final long expiresAtMillis = getExpiresAtFrom(currentTimeProvider, cacheDuration, json); - - return new SettingsData( - expiresAtMillis, - appData, - settingsData, - featureData, - settingsVersion, - cacheDuration, - onDemandUploadRatePerMinute, - onDemandBackoffBase, - onDemandBackoffStepDurationSeconds); + return defaultSettings(currentTimeProvider); } /** Creates a new Settings with reasonable default values. */ static Settings defaultSettings(CurrentTimeProvider currentTimeProvider) { - final int settingsVersion = SettingsJsonConstants.SETTINGS_VERSION_DEFAULT; - final int cacheDuration = SettingsJsonConstants.SETTINGS_CACHE_DURATION_DEFAULT; - - JSONObject empty = new JSONObject(); - final AppSettingsData appData = null; - final SessionSettingsData settingsData = buildSessionDataFrom(empty); - final FeaturesSettingsData featureData = buildFeaturesSessionDataFrom(empty); + int settingsVersion = SettingsJsonConstants.SETTINGS_VERSION_DEFAULT; + int cacheDurationSeconds = SettingsJsonConstants.SETTINGS_CACHE_DURATION_DEFAULT; + double onDemandUploadRatePerMinute = + SettingsJsonConstants.SETTINGS_ON_DEMAND_UPLOAD_RATE_PER_MINUTE_DEFAULT; + double onDemandBackoffBase = SettingsJsonConstants.SETTINGS_ON_DEMAND_BACKOFF_BASE_DEFAULT; + int onDemandBackoffStepDurationSeconds = + SettingsJsonConstants.SETTINGS_ON_DEMAND_BACKOFF_STEP_DURATION_SECONDS_DEFAULT; + + final Settings.SessionData sessionData = + new Settings.SessionData( + SettingsJsonConstants.SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_DEFAULT, + SettingsJsonConstants.SETTINGS_MAX_COMPLETE_SESSIONS_COUNT_DEFAULT); + final Settings.FeatureFlagData featureFlagData = + new Settings.FeatureFlagData( + SettingsJsonConstants.FEATURES_COLLECT_REPORTS_DEFAULT, + SettingsJsonConstants.FEATURES_COLLECT_ANRS_DEFAULT); - final long expiresAtMillis = getExpiresAtFrom(currentTimeProvider, cacheDuration, empty); + long expiresAtMillis = + currentTimeProvider.getCurrentTimeMillis() + (cacheDurationSeconds * 1000); - return new SettingsData( + return new Settings( expiresAtMillis, - appData, - settingsData, - featureData, + sessionData, + featureFlagData, settingsVersion, - cacheDuration, - SettingsJsonConstants.SETTINGS_ON_DEMAND_UPLOAD_RATE_PER_MINUTE_DEFAULT, - SettingsJsonConstants.SETTINGS_ON_DEMAND_BACKOFF_BASE_DEFAULT, - SettingsJsonConstants.SETTINGS_ON_DEMAND_BACKOFF_STEP_DURATION_SECONDS_DEFAULT); - } - - @Override - public JSONObject toJson(SettingsData settingsData) throws JSONException { - return new JSONObject() - .put(SettingsJsonConstants.EXPIRES_AT_KEY, settingsData.expiresAtMillis) - .put(SettingsJsonConstants.CACHE_DURATION_KEY, settingsData.cacheDuration) - .put(SettingsJsonConstants.SETTINGS_VERSION, settingsData.settingsVersion) - .put(SettingsJsonConstants.FEATURES_KEY, toFeaturesJson(settingsData.featuresData)) - .put(SettingsJsonConstants.APP_KEY, toAppJson(settingsData.appData)) - .put(SettingsJsonConstants.SESSION_KEY, toSessionJson(settingsData.sessionData)); - } - - private static AppSettingsData buildAppDataFrom(JSONObject json) throws JSONException { - final String status = json.getString(SettingsJsonConstants.APP_STATUS_KEY); - final String url = json.getString(SettingsJsonConstants.APP_URL_KEY); - final String reportsUrl = json.getString(SettingsJsonConstants.APP_REPORTS_URL_KEY); - final String ndkReportsUrl = json.getString(SettingsJsonConstants.APP_NDK_REPORTS_URL_KEY); - final boolean updateRequired = - json.optBoolean( - SettingsJsonConstants.APP_UPDATE_REQUIRED_KEY, - SettingsJsonConstants.APP_UPDATE_REQUIRED_DEFAULT); - - return new AppSettingsData(status, url, reportsUrl, ndkReportsUrl, updateRequired); - } - - private static FeaturesSettingsData buildFeaturesSessionDataFrom(JSONObject json) { - final boolean collectReports = - json.optBoolean( - SettingsJsonConstants.FEATURES_COLLECT_REPORTS_KEY, - SettingsJsonConstants.FEATURES_COLLECT_REPORTS_DEFAULT); - - final boolean collectAnrs = - json.optBoolean( - SettingsJsonConstants.FEATURES_COLLECT_ANRS_KEY, - SettingsJsonConstants.FEATURES_COLLECT_ANRS_DEFAULT); - - return new FeaturesSettingsData(collectReports, collectAnrs); - } - - private static SessionSettingsData buildSessionDataFrom(JSONObject json) { - final int maxCustomExceptionEvents = - json.optInt( - SettingsJsonConstants.SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_KEY, - SettingsJsonConstants.SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_DEFAULT); - final int maxCompleteSessionsCount = - SettingsJsonConstants.SETTINGS_MAX_COMPLETE_SESSIONS_COUNT_DEFAULT; - - return new SessionSettingsData(maxCustomExceptionEvents, maxCompleteSessionsCount); - } - - private static long getExpiresAtFrom( - CurrentTimeProvider currentTimeProvider, long cacheDurationSeconds, JSONObject json) { - long expiresAtMillis = 0; - - if (json.has(SettingsJsonConstants.EXPIRES_AT_KEY)) { - // If the JSON we receive has an expires_at key, use that value - expiresAtMillis = json.optLong(SettingsJsonConstants.EXPIRES_AT_KEY); - } else { - // If not, construct a new one from the current time and the loaded cache duration - // (in seconds) - final long currentTimeMillis = currentTimeProvider.getCurrentTimeMillis(); - expiresAtMillis = currentTimeMillis + (cacheDurationSeconds * 1000); - } - - return expiresAtMillis; - } - - private JSONObject toAppJson(AppSettingsData appData) throws JSONException { - final JSONObject json = - new JSONObject() - .put(SettingsJsonConstants.APP_STATUS_KEY, appData.status) - .put(SettingsJsonConstants.APP_URL_KEY, appData.url) - .put(SettingsJsonConstants.APP_REPORTS_URL_KEY, appData.reportsUrl) - .put(SettingsJsonConstants.APP_NDK_REPORTS_URL_KEY, appData.ndkReportsUrl) - .put(SettingsJsonConstants.APP_UPDATE_REQUIRED_KEY, appData.updateRequired); - - return json; - } - - private JSONObject toFeaturesJson(FeaturesSettingsData features) throws JSONException { - return new JSONObject() - .put(SettingsJsonConstants.FEATURES_COLLECT_REPORTS_KEY, features.collectReports); - } - - private JSONObject toSessionJson(SessionSettingsData data) throws JSONException { - return new JSONObject() - .put( - SettingsJsonConstants.SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_KEY, - data.maxCustomExceptionEvents) - .put( - SettingsJsonConstants.SETTINGS_MAX_COMPLETE_SESSIONS_COUNT_KEY, - data.maxCompleteSessionsCount); + cacheDurationSeconds, + onDemandUploadRatePerMinute, + onDemandBackoffBase, + onDemandBackoffStepDurationSeconds); } } diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/network/DefaultSettingsSpiCall.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsSpiCall.java similarity index 97% rename from firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/network/DefaultSettingsSpiCall.java rename to firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsSpiCall.java index 4eedaef5a19..9dc0df91144 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/network/DefaultSettingsSpiCall.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/DefaultSettingsSpiCall.java @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.firebase.crashlytics.internal.settings.network; +package com.google.firebase.crashlytics.internal.settings; import android.text.TextUtils; import com.google.firebase.crashlytics.internal.Logger; @@ -20,7 +20,6 @@ import com.google.firebase.crashlytics.internal.network.HttpGetRequest; import com.google.firebase.crashlytics.internal.network.HttpRequestFactory; import com.google.firebase.crashlytics.internal.network.HttpResponse; -import com.google.firebase.crashlytics.internal.settings.model.SettingsRequest; import java.io.IOException; import java.net.HttpURLConnection; import java.util.HashMap; @@ -28,7 +27,7 @@ import org.json.JSONObject; /** Default implementation of the {@link SettingsSpiCall} */ -public class DefaultSettingsSpiCall implements SettingsSpiCall { +class DefaultSettingsSpiCall implements SettingsSpiCall { static final String HEADER_GOOGLE_APP_ID = "X-CRASHLYTICS-GOOGLE-APP-ID"; static final String HEADER_CLIENT_TYPE = "X-CRASHLYTICS-API-CLIENT-TYPE"; diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/SettingsData.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/Settings.java similarity index 53% rename from firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/SettingsData.java rename to firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/Settings.java index afd53e0751a..fdf231290f7 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/SettingsData.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/Settings.java @@ -12,13 +12,34 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.firebase.crashlytics.internal.settings.model; +package com.google.firebase.crashlytics.internal.settings; -/** Immutable value object used to represent hold settings in memory. */ -public class SettingsData implements Settings { - public final AppSettingsData appData; - public final SessionSettingsData sessionData; - public final FeaturesSettingsData featuresData; +/** Immutable value object used to represent settings in memory. */ +public class Settings { + + // Subsections of the Settings payload include session-specific params & feature flags. + public static class SessionData { + public final int maxCustomExceptionEvents; + public final int maxCompleteSessionsCount; + + public SessionData(int maxCustomExceptionEvents, int maxCompleteSessionsCount) { + this.maxCustomExceptionEvents = maxCustomExceptionEvents; + this.maxCompleteSessionsCount = maxCompleteSessionsCount; + } + } + + public static class FeatureFlagData { + public final boolean collectReports; + public final boolean collectAnrs; + + public FeatureFlagData(boolean collectReports, boolean collectAnrs) { + this.collectReports = collectReports; + this.collectAnrs = collectAnrs; + } + } + + public final SessionData sessionData; + public final FeatureFlagData featureFlagData; public final long expiresAtMillis; public final int settingsVersion; public final int cacheDuration; @@ -26,20 +47,18 @@ public class SettingsData implements Settings { public final double onDemandBackoffBase; public final int onDemandBackoffStepDurationSeconds; - public SettingsData( + public Settings( long expiresAtMillis, - AppSettingsData appData, - SessionSettingsData sessionData, - FeaturesSettingsData featuresData, + SessionData sessionData, + FeatureFlagData featureFlagData, int settingsVersion, int cacheDuration, double onDemandUploadRatePerMinute, double onDemandBackoffBase, int onDemandBackoffStepDurationSeconds) { this.expiresAtMillis = expiresAtMillis; - this.appData = appData; this.sessionData = sessionData; - this.featuresData = featuresData; + this.featureFlagData = featureFlagData; this.settingsVersion = settingsVersion; this.cacheDuration = cacheDuration; this.onDemandUploadRatePerMinute = onDemandUploadRatePerMinute; @@ -47,52 +66,7 @@ public SettingsData( this.onDemandBackoffStepDurationSeconds = onDemandBackoffStepDurationSeconds; } - public AppSettingsData getAppSettingsData() { - return appData; - } - - @Override public boolean isExpired(long currentTimeMillis) { return expiresAtMillis < currentTimeMillis; } - - @Override - public SessionSettingsData getSessionData() { - return sessionData; - } - - @Override - public FeaturesSettingsData getFeaturesData() { - return featuresData; - } - - @Override - public long getExpiresAtMillis() { - return expiresAtMillis; - } - - @Override - public int getSettingsVersion() { - return settingsVersion; - } - - @Override - public int getCacheDuration() { - return cacheDuration; - } - - @Override - public double onDemandUploadRatePerMinute() { - return onDemandUploadRatePerMinute; - } - - @Override - public double onDemandBackoffBase() { - return onDemandBackoffBase; - } - - @Override - public int onDemandBackoffStepDurationSeconds() { - return onDemandBackoffStepDurationSeconds; - } } diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsCacheBehavior.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsCacheBehavior.java index 3df128aa84c..44f0ee7260d 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsCacheBehavior.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsCacheBehavior.java @@ -15,7 +15,7 @@ package com.google.firebase.crashlytics.internal.settings; /** Enum defining possible behaviors when looking up settings from cache */ -public enum SettingsCacheBehavior { +enum SettingsCacheBehavior { /** * The normal behavior - tries to return settings from the cache, respecting their expiration * date/time. diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsController.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsController.java index e16a7841683..d44c37257e3 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsController.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsController.java @@ -32,12 +32,6 @@ import com.google.firebase.crashlytics.internal.common.SystemCurrentTimeProvider; import com.google.firebase.crashlytics.internal.network.HttpRequestFactory; import com.google.firebase.crashlytics.internal.persistence.FileStore; -import com.google.firebase.crashlytics.internal.settings.model.AppSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.Settings; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SettingsRequest; -import com.google.firebase.crashlytics.internal.settings.network.DefaultSettingsSpiCall; -import com.google.firebase.crashlytics.internal.settings.network.SettingsSpiCall; import java.util.Locale; import java.util.concurrent.Executor; import java.util.concurrent.atomic.AtomicReference; @@ -45,7 +39,7 @@ import org.json.JSONObject; /** Implements the logic of when to use cached settings, and when to load them from the network. */ -public class SettingsController implements SettingsDataProvider { +public class SettingsController implements SettingsProvider { private static final String PREFS_BUILD_INSTANCE_IDENTIFIER = "existing_instance_identifier"; private static final String SETTINGS_URL_FORMAT = @@ -62,7 +56,7 @@ public class SettingsController implements SettingsDataProvider { private final DataCollectionArbiter dataCollectionArbiter; private final AtomicReference settings = new AtomicReference<>(); - private final AtomicReference> appSettingsData = + private final AtomicReference> settingsTask = new AtomicReference<>(new TaskCompletionSource<>()); SettingsController( @@ -132,17 +126,22 @@ public static SettingsController create( dataCollectionArbiter); } - /** Gets the best available settings that have been loaded. */ - public Settings getSettings() { - return settings.get(); + /** + * Returns a Task that will be resolved with SettingsData, once it has been fetched from the + * network or loaded from the cache. + */ + @Override + public Task getSettingsAsync() { + return settingsTask.get().getTask(); } /** - * Returns a Task that will be resolved with AppSettingsData, once it has been fetched from the + * Returns a Task that will be resolved with SettingsData, once it has been fetched from the * network or loaded from the cache. */ - public Task getAppSettings() { - return appSettingsData.get().getTask(); + @Override + public Settings getSettingsSync() { + return settings.get(); } /** @@ -166,10 +165,10 @@ public Task loadSettingsData(SettingsCacheBehavior cacheBehavior, Executor // We need to bypass the cache if this is the first time a new build has run so the // backend will know about it. if (!buildInstanceIdentifierChanged()) { - final SettingsData cachedSettings = getCachedSettingsData(cacheBehavior); + final Settings cachedSettings = getCachedSettingsData(cacheBehavior); if (cachedSettings != null) { settings.set(cachedSettings); - appSettingsData.get().trySetResult(cachedSettings.getAppSettingsData()); + settingsTask.get().trySetResult(cachedSettings); return Tasks.forResult(null); } } @@ -179,11 +178,11 @@ public Task loadSettingsData(SettingsCacheBehavior cacheBehavior, Executor // This has been true in production for some time, though, so no rush to "fix" it. // The cached settings are too old, so if there are expired settings, use those for now. - final SettingsData expiredSettings = + final Settings expiredSettings = getCachedSettingsData(SettingsCacheBehavior.IGNORE_CACHE_EXPIRATION); if (expiredSettings != null) { settings.set(expiredSettings); - appSettingsData.get().trySetResult(expiredSettings.getAppSettingsData()); + settingsTask.get().trySetResult(expiredSettings); } // Kick off fetching fresh settings. @@ -201,10 +200,10 @@ public Task then(@Nullable Void aVoid) throws Exception { settingsSpiCall.invoke(settingsRequest, dataCollectionToken); if (settingsJson != null) { - final SettingsData fetchedSettings = + final Settings fetchedSettings = settingsJsonParser.parseSettingsJson(settingsJson); cachedSettingsIo.writeCachedSettings( - fetchedSettings.getExpiresAtMillis(), settingsJson); + fetchedSettings.expiresAtMillis, settingsJson); logSettings(settingsJson, "Loaded settings: "); setStoredBuildInstanceIdentifier(settingsRequest.instanceId); @@ -212,14 +211,8 @@ public Task then(@Nullable Void aVoid) throws Exception { // Update the regular settings. settings.set(fetchedSettings); - // Signal the app settings on any Tasks that already exist, and then replace the - // task so - // that any new callers get the new app settings instead of any old ones. - appSettingsData.get().trySetResult(fetchedSettings.getAppSettingsData()); - TaskCompletionSource fetchedAppSettings = - new TaskCompletionSource<>(); - fetchedAppSettings.trySetResult(fetchedSettings.getAppSettingsData()); - appSettingsData.set(fetchedAppSettings); + // Signal the Task that we have a new valid settings + settingsTask.get().trySetResult(fetchedSettings); } return Tasks.forResult(null); @@ -227,24 +220,24 @@ public Task then(@Nullable Void aVoid) throws Exception { }); } - private SettingsData getCachedSettingsData(SettingsCacheBehavior cacheBehavior) { - SettingsData toReturn = null; + private Settings getCachedSettingsData(SettingsCacheBehavior cacheBehavior) { + Settings toReturn = null; try { if (!SettingsCacheBehavior.SKIP_CACHE_LOOKUP.equals(cacheBehavior)) { final JSONObject settingsJson = cachedSettingsIo.readCachedSettings(); if (settingsJson != null) { - final SettingsData settingsData = settingsJsonParser.parseSettingsJson(settingsJson); + final Settings settings = settingsJsonParser.parseSettingsJson(settingsJson); - if (settingsData != null) { + if (settings != null) { logSettings(settingsJson, "Loaded cached settings: "); final long currentTimeMillis = currentTimeProvider.getCurrentTimeMillis(); if (SettingsCacheBehavior.IGNORE_CACHE_EXPIRATION.equals(cacheBehavior) - || !settingsData.isExpired(currentTimeMillis)) { - toReturn = settingsData; + || !settings.isExpired(currentTimeMillis)) { + toReturn = settings; Logger.getLogger().v("Returning cached settings."); } else { Logger.getLogger().v("Cached settings have expired."); diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonConstants.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonConstants.java index 6042906b8cc..f34e0a18209 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonConstants.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonConstants.java @@ -17,12 +17,10 @@ class SettingsJsonConstants { // Top-level JSON Keys static final String EXPIRES_AT_KEY = "expires_at"; - static final String APP_KEY = "app"; static final String SESSION_KEY = "session"; static final String SETTINGS_VERSION = "settings_version"; static final String FEATURES_KEY = "features"; static final String CACHE_DURATION_KEY = "cache_duration"; - static final String FABRIC_KEY = "fabric"; static final String ON_DEMAND_UPLOAD_RATE_PER_MINUTE_KEY = "on_demand_upload_rate_per_minute"; static final String ON_DEMAND_BACKOFF_BASE_KEY = "on_demand_backoff_base"; static final String ON_DEMAND_BACKOFF_STEP_DURATION_SECONDS_KEY = @@ -39,23 +37,8 @@ class SettingsJsonConstants { static final boolean FEATURES_COLLECT_REPORTS_DEFAULT = true; static final boolean FEATURES_COLLECT_ANRS_DEFAULT = false; - // Fabric JSON Keys - static final String FABRIC_BUNDLE_ID = "bundle_id"; - static final String FABRIC_ORGANIZATION_ID = "org_id"; - // App JSON Keys static final String APP_STATUS_KEY = "status"; - static final String APP_URL_KEY = "url"; - static final String APP_REPORTS_URL_KEY = "reports_url"; - static final String APP_NDK_REPORTS_URL_KEY = "ndk_reports_url"; - static final String APP_UPDATE_REQUIRED_KEY = "update_required"; - static final String APP_REPORT_UPLOAD_VARIANT_KEY = "report_upload_variant"; - static final String APP_NATIVE_REPORT_UPLOAD_VARIANT_KEY = "native_report_upload_variant"; - - // App JSON Defaults - static final boolean APP_UPDATE_REQUIRED_DEFAULT = false; - static final int APP_REPORT_UPLOAD_VARIANT_DEFAULT = 0; - static final int APP_NATIVE_REPORT_UPLOAD_VARIANT_DEFAULT = 0; // Settings JSON Keys static final String SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_KEY = "max_custom_exception_events"; diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonParser.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonParser.java index 5510eb64774..e24208b9a4a 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonParser.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonParser.java @@ -14,8 +14,8 @@ package com.google.firebase.crashlytics.internal.settings; +import com.google.firebase.crashlytics.internal.Logger; import com.google.firebase.crashlytics.internal.common.CurrentTimeProvider; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; import org.json.JSONException; import org.json.JSONObject; @@ -28,7 +28,7 @@ public class SettingsJsonParser { this.currentTimeProvider = currentTimeProvider; } - public SettingsData parseSettingsJson(JSONObject settingsJson) throws JSONException { + public Settings parseSettingsJson(JSONObject settingsJson) throws JSONException { final int version = settingsJson.getInt(SettingsJsonConstants.SETTINGS_VERSION); final SettingsJsonTransform jsonTransform = getJsonTransformForVersion(version); return jsonTransform.buildFromJson(currentTimeProvider, settingsJson); @@ -39,6 +39,11 @@ private static SettingsJsonTransform getJsonTransformForVersion(int settingsVers case 3: return new SettingsV3JsonTransform(); default: + Logger.getLogger() + .e( + "Could not determine SettingsJsonTransform for settings version " + + settingsVersion + + ". Using default settings values."); return new DefaultSettingsJsonTransform(); } } diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonTransform.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonTransform.java index 89d2166a331..e6ba3424ff7 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonTransform.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsJsonTransform.java @@ -15,35 +15,24 @@ package com.google.firebase.crashlytics.internal.settings; import com.google.firebase.crashlytics.internal.common.CurrentTimeProvider; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; import org.json.JSONException; import org.json.JSONObject; /** - * Internal interface defining bi-direction conversion to-from settings JSON and {@link - * SettingsData} a model object. + * Internal interface defining bi-direction conversion to-from settings JSON and {@link Settings} a + * model object. */ interface SettingsJsonTransform { /** - * Transforms the input JSON into the corresponding {@link SettingsData} model object. Should - * throw an exception rather than returning null in the event of a problem. + * Transforms the input JSON into the corresponding {@link Settings} model object. Should throw an + * exception rather than returning null in the event of a problem. * * @param currentTimeProvider {@link CurrentTimeProvider} to be used in filling in the {@link - * SettingsData#expiresAtMillis} value + * Settings#expiresAtMillis} value * @param json {@link JSONObject} to be translated - * @return {@link SettingsData} representing the translated JSON data + * @return {@link Settings} representing the translated JSON data * @throws JSONException if an exception occurs while handling the JSON */ - SettingsData buildFromJson(CurrentTimeProvider currentTimeProvider, JSONObject json) + Settings buildFromJson(CurrentTimeProvider currentTimeProvider, JSONObject json) throws JSONException; - - /** - * Transforms the provided {@link SettingsData} model object to its JSON representation. Should - * throw an exception rather than returning null in the event of a problem. - * - * @param settingsData {@link SettingsData} to translate - * @return {@link JSONObject} representing the settings data - * @throws JSONException if a problem occurs while translating the settings data. - */ - JSONObject toJson(SettingsData settingsData) throws JSONException; } diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/package-info.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsProvider.java similarity index 73% rename from firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/package-info.java rename to firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsProvider.java index 8b263e1e2f3..4470f53498e 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/package-info.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsProvider.java @@ -12,5 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -/** @hide */ -package com.google.firebase.crashlytics.internal.settings.model; +package com.google.firebase.crashlytics.internal.settings; + +import com.google.android.gms.tasks.Task; + +public interface SettingsProvider { + Settings getSettingsSync(); + + Task getSettingsAsync(); +} diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/SettingsRequest.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsRequest.java similarity index 89% rename from firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/SettingsRequest.java rename to firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsRequest.java index ea2b0cf75ae..48746100ae2 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/SettingsRequest.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsRequest.java @@ -12,12 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.firebase.crashlytics.internal.settings.model; +package com.google.firebase.crashlytics.internal.settings; import com.google.firebase.crashlytics.internal.common.InstallIdProvider; /** Immutable value object capturing the data needed to make an settings query SPI web request. */ -public class SettingsRequest { +class SettingsRequest { public final String googleAppId; public final String deviceModel; public final String osBuildVersion; @@ -33,7 +33,7 @@ public SettingsRequest( String deviceModel, String osBuildVersion, String osDisplayVersion, - InstallIdProvider installIdProvier, + InstallIdProvider installIdProvider, String instanceId, String displayVersion, String buildVersion, @@ -42,7 +42,7 @@ public SettingsRequest( this.deviceModel = deviceModel; this.osBuildVersion = osBuildVersion; this.osDisplayVersion = osDisplayVersion; - this.installIdProvider = installIdProvier; + this.installIdProvider = installIdProvider; this.instanceId = instanceId; this.displayVersion = displayVersion; this.buildVersion = buildVersion; diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/network/SettingsSpiCall.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsSpiCall.java similarity index 85% rename from firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/network/SettingsSpiCall.java rename to firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsSpiCall.java index cb6f47b36b3..62bdac1bfcf 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/network/SettingsSpiCall.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsSpiCall.java @@ -12,13 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.google.firebase.crashlytics.internal.settings.network; +package com.google.firebase.crashlytics.internal.settings; -import com.google.firebase.crashlytics.internal.settings.model.SettingsRequest; import org.json.JSONObject; /** Internal interface representing the SPI REST call to get settings from the server. */ -public interface SettingsSpiCall { +interface SettingsSpiCall { /** * @param requestData {@link SettingsRequest} data to be sent to the server * @return the {@link JSONObject} created from JSON returned from the server, or null diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsV3JsonTransform.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsV3JsonTransform.java index b2b24a676ef..1503b44e85d 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsV3JsonTransform.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/SettingsV3JsonTransform.java @@ -15,63 +15,50 @@ package com.google.firebase.crashlytics.internal.settings; import com.google.firebase.crashlytics.internal.common.CurrentTimeProvider; -import com.google.firebase.crashlytics.internal.settings.model.AppSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.FeaturesSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SessionSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.SettingsData; -import java.util.Locale; import org.json.JSONException; import org.json.JSONObject; class SettingsV3JsonTransform implements SettingsJsonTransform { - private static final String CRASHLYTICS_APP_URL = - "https://update.crashlytics.com/spi/v1/platforms/android/apps"; - private static final String CRASHLYTICS_APP_URL_FORMAT = - "https://update.crashlytics.com/spi/v1/platforms/android/apps/%s"; - private static final String REPORTS_URL_FORMAT = - "https://reports.crashlytics.com/spi/v1/platforms/android/apps/%s/reports"; - private static final String NDK_REPORTS_URL_FORMAT = - "https://reports.crashlytics.com/sdk-api/v1/platforms/android/apps/%s/minidumps"; - @Override - public SettingsData buildFromJson(CurrentTimeProvider currentTimeProvider, JSONObject json) + public Settings buildFromJson(CurrentTimeProvider currentTimeProvider, JSONObject json) throws JSONException { - final int settingsVersion = + int settingsVersion = json.optInt( SettingsJsonConstants.SETTINGS_VERSION, SettingsJsonConstants.SETTINGS_VERSION_DEFAULT); - final int cacheDuration = + int cacheDuration = json.optInt( SettingsJsonConstants.CACHE_DURATION_KEY, SettingsJsonConstants.SETTINGS_CACHE_DURATION_DEFAULT); - final double onDemandUploadRatePerMinute = + double onDemandUploadRatePerMinute = json.optDouble( SettingsJsonConstants.ON_DEMAND_UPLOAD_RATE_PER_MINUTE_KEY, SettingsJsonConstants.SETTINGS_ON_DEMAND_UPLOAD_RATE_PER_MINUTE_DEFAULT); - final double onDemandBackoffBase = + double onDemandBackoffBase = json.optDouble( SettingsJsonConstants.ON_DEMAND_BACKOFF_BASE_KEY, SettingsJsonConstants.SETTINGS_ON_DEMAND_BACKOFF_BASE_DEFAULT); - final int onDemandBackoffStepDurationSeconds = + int onDemandBackoffStepDurationSeconds = json.optInt( SettingsJsonConstants.ON_DEMAND_BACKOFF_STEP_DURATION_SECONDS_KEY, SettingsJsonConstants.SETTINGS_ON_DEMAND_BACKOFF_STEP_DURATION_SECONDS_DEFAULT); - final AppSettingsData appData = - buildAppDataFrom( - json.getJSONObject(SettingsJsonConstants.FABRIC_KEY), - json.getJSONObject(SettingsJsonConstants.APP_KEY)); - final SessionSettingsData sessionData = defaultSessionData(); - final FeaturesSettingsData featureData = - buildFeaturesSessionDataFrom(json.getJSONObject(SettingsJsonConstants.FEATURES_KEY)); + // There's an "app" section that includes deprecated fields. We skip reading those. + + // "session" section is not returned in current Settings values. + Settings.SessionData sessionData = + json.has(SettingsJsonConstants.SESSION_KEY) + ? buildSessionDataFrom(json.getJSONObject(SettingsJsonConstants.SESSION_KEY)) + : buildSessionDataFrom(new JSONObject()); + Settings.FeatureFlagData featureFlagData = + buildFeatureFlagDataFrom(json.getJSONObject(SettingsJsonConstants.FEATURES_KEY)); - final long expiresAtMillis = getExpiresAtFrom(currentTimeProvider, cacheDuration, json); + long expiresAtMillis = getExpiresAtFrom(currentTimeProvider, cacheDuration, json); - return new SettingsData( + return new Settings( expiresAtMillis, - appData, sessionData, - featureData, + featureFlagData, settingsVersion, cacheDuration, onDemandUploadRatePerMinute, @@ -79,61 +66,7 @@ public SettingsData buildFromJson(CurrentTimeProvider currentTimeProvider, JSONO onDemandBackoffStepDurationSeconds); } - @Override - public JSONObject toJson(SettingsData settingsData) throws JSONException { - return new JSONObject() - .put(SettingsJsonConstants.EXPIRES_AT_KEY, settingsData.expiresAtMillis) - .put(SettingsJsonConstants.CACHE_DURATION_KEY, settingsData.cacheDuration) - .put(SettingsJsonConstants.SETTINGS_VERSION, settingsData.settingsVersion) - .put(SettingsJsonConstants.FEATURES_KEY, toFeaturesJson(settingsData.featuresData)) - .put(SettingsJsonConstants.APP_KEY, toAppJson(settingsData.appData)) - .put(SettingsJsonConstants.FABRIC_KEY, toFabricJson(settingsData.appData)); - } - - private static AppSettingsData buildAppDataFrom(JSONObject fabricJson, JSONObject appJson) - throws JSONException { - final String status = appJson.getString(SettingsJsonConstants.APP_STATUS_KEY); - final boolean isNewApp = AppSettingsData.STATUS_NEW.equals(status); - - final String bundleId = fabricJson.getString(SettingsJsonConstants.FABRIC_BUNDLE_ID); - final String organizationId = - fabricJson.getString(SettingsJsonConstants.FABRIC_ORGANIZATION_ID); - - final String url = - isNewApp - ? CRASHLYTICS_APP_URL - : String.format(Locale.US, CRASHLYTICS_APP_URL_FORMAT, bundleId); - final String reportsUrl = String.format(Locale.US, REPORTS_URL_FORMAT, bundleId); - final String ndkReportsUrl = String.format(Locale.US, NDK_REPORTS_URL_FORMAT, bundleId); - - final boolean updateRequired = - appJson.optBoolean( - SettingsJsonConstants.APP_UPDATE_REQUIRED_KEY, - SettingsJsonConstants.APP_UPDATE_REQUIRED_DEFAULT); - - final int reportUploadVariant = - appJson.optInt( - SettingsJsonConstants.APP_REPORT_UPLOAD_VARIANT_KEY, - SettingsJsonConstants.APP_REPORT_UPLOAD_VARIANT_DEFAULT); - - final int nativeReportUploadVariant = - appJson.optInt( - SettingsJsonConstants.APP_NATIVE_REPORT_UPLOAD_VARIANT_KEY, - SettingsJsonConstants.APP_NATIVE_REPORT_UPLOAD_VARIANT_DEFAULT); - - return new AppSettingsData( - status, - url, - reportsUrl, - ndkReportsUrl, - bundleId, - organizationId, - updateRequired, - reportUploadVariant, - nativeReportUploadVariant); - } - - private static FeaturesSettingsData buildFeaturesSessionDataFrom(JSONObject json) { + private static Settings.FeatureFlagData buildFeatureFlagDataFrom(JSONObject json) { final boolean collectReports = json.optBoolean( SettingsJsonConstants.FEATURES_COLLECT_REPORTS_KEY, @@ -144,61 +77,31 @@ private static FeaturesSettingsData buildFeaturesSessionDataFrom(JSONObject json SettingsJsonConstants.FEATURES_COLLECT_ANRS_KEY, SettingsJsonConstants.FEATURES_COLLECT_ANRS_DEFAULT); - // TODO: Build support back for "collect logged exceptions" - - return new FeaturesSettingsData(collectReports, collectAnrs); + return new Settings.FeatureFlagData(collectReports, collectAnrs); } - private static SessionSettingsData defaultSessionData() { + private static Settings.SessionData buildSessionDataFrom(JSONObject json) { final int maxCustomExceptionEvents = - SettingsJsonConstants.SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_DEFAULT; + json.optInt( + SettingsJsonConstants.SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_KEY, + SettingsJsonConstants.SETTINGS_MAX_CUSTOM_EXCEPTION_EVENTS_DEFAULT); final int maxCompleteSessionsCount = SettingsJsonConstants.SETTINGS_MAX_COMPLETE_SESSIONS_COUNT_DEFAULT; - return new SessionSettingsData(maxCustomExceptionEvents, maxCompleteSessionsCount); - } - - private JSONObject toFabricJson(AppSettingsData appData) throws JSONException { - final JSONObject json = - new JSONObject() - .put(SettingsJsonConstants.FABRIC_BUNDLE_ID, appData.bundleId) - .put(SettingsJsonConstants.FABRIC_ORGANIZATION_ID, appData.organizationId); - - return json; - } - - private JSONObject toAppJson(AppSettingsData appData) throws JSONException { - final JSONObject json = - new JSONObject() - .put(SettingsJsonConstants.APP_STATUS_KEY, appData.status) - .put(SettingsJsonConstants.APP_UPDATE_REQUIRED_KEY, appData.updateRequired) - .put(SettingsJsonConstants.APP_REPORT_UPLOAD_VARIANT_KEY, appData.reportUploadVariant) - .put( - SettingsJsonConstants.APP_NATIVE_REPORT_UPLOAD_VARIANT_KEY, - appData.nativeReportUploadVariant); - - return json; - } - - private JSONObject toFeaturesJson(FeaturesSettingsData features) throws JSONException { - return new JSONObject() - .put(SettingsJsonConstants.FEATURES_COLLECT_REPORTS_KEY, features.collectReports); + return new Settings.SessionData(maxCustomExceptionEvents, maxCompleteSessionsCount); } private static long getExpiresAtFrom( CurrentTimeProvider currentTimeProvider, long cacheDurationSeconds, JSONObject json) { - long expiresAtMillis = 0; + long expiresAtMillis; if (json.has(SettingsJsonConstants.EXPIRES_AT_KEY)) { // If the JSON we receive has an expires_at key, use that value expiresAtMillis = json.optLong(SettingsJsonConstants.EXPIRES_AT_KEY); } else { - // If not, construct a new one from the current time and the loaded cache duration - // (in seconds) - final long currentTimeMillis = currentTimeProvider.getCurrentTimeMillis(); - expiresAtMillis = currentTimeMillis + (cacheDurationSeconds * 1000); + // If not, make a new one from the current time and the loaded cache duration (in seconds) + expiresAtMillis = currentTimeProvider.getCurrentTimeMillis() + (cacheDurationSeconds * 1000); } - return expiresAtMillis; } } diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/AppRequestData.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/AppRequestData.java deleted file mode 100644 index d596441f101..00000000000 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/AppRequestData.java +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.firebase.crashlytics.internal.settings.model; - -/** Immutable value object capturing the data needed to make an App-related SPI web request. */ -public class AppRequestData { - - public final String organizationId; - public final String googleAppId; - public final String appId; - public final String displayVersion; - public final String buildVersion; - - public final String instanceIdentifier; - public final String name; - public final int source; - public final String minSdkVersion; - public final String builtSdkVersion; - - public AppRequestData( - String organizationId, - String googleAppId, - String appId, - String displayVersion, - String buildVersion, - String instanceIdentifier, - String name, - int source, - String minSdkVersion, - String builtSdkVersion) { - this.organizationId = organizationId; - this.googleAppId = googleAppId; - this.appId = appId; - this.displayVersion = displayVersion; - this.buildVersion = buildVersion; - - this.instanceIdentifier = instanceIdentifier; - this.name = name; - this.source = source; - this.minSdkVersion = minSdkVersion; - this.builtSdkVersion = builtSdkVersion; - } -} diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/AppSettingsData.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/AppSettingsData.java deleted file mode 100644 index 114e9d1a452..00000000000 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/AppSettingsData.java +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.firebase.crashlytics.internal.settings.model; - -/** Immutable value object used to represent the App portion of settings in memory. */ -public class AppSettingsData { - public static final String STATUS_NEW = "new"; - public static final String STATUS_CONFIGURED = "configured"; - public static final String STATUS_ACTIVATED = "activated"; - - public final String status; - public final String url; - public final String reportsUrl; - public final String ndkReportsUrl; - public final String bundleId; - public final String organizationId; - public final boolean updateRequired; - public final int reportUploadVariant; - public final int nativeReportUploadVariant; - - public AppSettingsData( - String status, - String url, - String reportsUrl, - String ndkReportsUrl, - String bundleId, - String organizationId, - boolean updateRequired, - int reportUploadVariant, - int nativeReportUploadVariant) { - this.status = status; - this.url = url; - this.reportsUrl = reportsUrl; - this.ndkReportsUrl = ndkReportsUrl; - this.bundleId = bundleId; - this.organizationId = organizationId; - this.updateRequired = updateRequired; - this.reportUploadVariant = reportUploadVariant; - this.nativeReportUploadVariant = nativeReportUploadVariant; - } - - public AppSettingsData( - String status, String url, String reportsUrl, String ndkReportsUrl, boolean updateRequired) { - this(status, url, reportsUrl, ndkReportsUrl, null, null, updateRequired, 0, 0); - } -} diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/FeaturesSettingsData.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/FeaturesSettingsData.java deleted file mode 100644 index ab7ead444d8..00000000000 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/FeaturesSettingsData.java +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.firebase.crashlytics.internal.settings.model; - -/** Immutable value object for storing feature switch settings */ -public class FeaturesSettingsData { - public final boolean collectReports; - public final boolean collectAnrs; - - public FeaturesSettingsData(boolean collectReports, boolean collectAnrs) { - this.collectReports = collectReports; - this.collectAnrs = collectAnrs; - } -} diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/SessionSettingsData.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/SessionSettingsData.java deleted file mode 100644 index 39a58dae65c..00000000000 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/SessionSettingsData.java +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.firebase.crashlytics.internal.settings.model; - -/** - * Immutable value object used to represent the "session" portion of the App settings data in - * memory. - */ -public class SessionSettingsData { - public final int maxCustomExceptionEvents; - public final int maxCompleteSessionsCount; - - public SessionSettingsData(int maxCustomExceptionEvents, int maxCompleteSessionsCount) { - this.maxCustomExceptionEvents = maxCustomExceptionEvents; - this.maxCompleteSessionsCount = maxCompleteSessionsCount; - } -} diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/Settings.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/Settings.java deleted file mode 100644 index 9cc3130c2f0..00000000000 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/model/Settings.java +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package com.google.firebase.crashlytics.internal.settings.model; - -public interface Settings { - SessionSettingsData getSessionData(); - - FeaturesSettingsData getFeaturesData(); - - long getExpiresAtMillis(); - - int getSettingsVersion(); - - int getCacheDuration(); - - double onDemandUploadRatePerMinute(); - - double onDemandBackoffBase(); - - int onDemandBackoffStepDurationSeconds(); - - boolean isExpired(long currentTimeMillis); -} diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/network/package-info.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/network/package-info.java deleted file mode 100644 index c2a58e031aa..00000000000 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/settings/network/package-info.java +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2019 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -/** @hide */ -package com.google.firebase.crashlytics.internal.settings.network; diff --git a/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/common/CrashlyticsControllerRobolectricTest.java b/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/common/CrashlyticsControllerRobolectricTest.java index b73943fc506..217e676e6f0 100644 --- a/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/common/CrashlyticsControllerRobolectricTest.java +++ b/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/common/CrashlyticsControllerRobolectricTest.java @@ -35,9 +35,10 @@ import com.google.firebase.crashlytics.internal.metadata.LogFileManager; import com.google.firebase.crashlytics.internal.metadata.UserMetadata; import com.google.firebase.crashlytics.internal.persistence.FileStore; -import com.google.firebase.crashlytics.internal.settings.SettingsDataProvider; -import com.google.firebase.crashlytics.internal.settings.model.FeaturesSettingsData; -import com.google.firebase.crashlytics.internal.settings.model.Settings; +import com.google.firebase.crashlytics.internal.settings.Settings; +import com.google.firebase.crashlytics.internal.settings.Settings.FeatureFlagData; +import com.google.firebase.crashlytics.internal.settings.Settings.SessionData; +import com.google.firebase.crashlytics.internal.settings.SettingsProvider; import com.google.firebase.inject.Deferred; import java.util.Collections; import java.util.List; @@ -56,7 +57,7 @@ public class CrashlyticsControllerRobolectricTest { private Context testContext; @Mock private IdManager idManager; - @Mock private SettingsDataProvider mockSettingsDataProvider; + @Mock private SettingsProvider mockSettingsProvider; @Mock private FileStore testFileStore; @Mock private SessionReportingCoordinator mockSessionReportingCoordinator; @Mock private DataCollectionArbiter mockDataCollectionArbiter; @@ -85,8 +86,8 @@ public void testDoCloseSession_enabledAnrs_doesNotPersistsAppExitInfoIfItDoesntE when(mockSessionReportingCoordinator.listSortedOpenSessionIds()) .thenReturn(new TreeSet<>(Collections.singletonList(sessionId))); - mockSettingsData(true); - controller.doCloseSessions(mockSettingsDataProvider); + mockSettingsProvider(true); + controller.doCloseSessions(mockSettingsProvider); // Since we haven't added any app exit info to the shadow activity manager, there won't exist a // single app exit info, and so this method won't be called. verify(mockSessionReportingCoordinator, never()) @@ -106,8 +107,8 @@ public void testDoCloseSession_enabledAnrs_persistsAppExitInfoIfItExists() { when(mockSessionReportingCoordinator.listSortedOpenSessionIds()) .thenReturn(new TreeSet<>(Collections.singletonList(sessionId))); - mockSettingsData(true); - controller.doCloseSessions(mockSettingsDataProvider); + mockSettingsProvider(true); + controller.doCloseSessions(mockSettingsProvider); verify(mockSessionReportingCoordinator) .persistRelevantAppExitInfoEvent( eq(sessionId), @@ -123,17 +124,18 @@ public void testDoCloseSession_disabledAnrs_doesNotPersistsAppExitInfo() { when(mockSessionReportingCoordinator.listSortedOpenSessionIds()) .thenReturn(new TreeSet<>(Collections.singletonList(sessionId))); - mockSettingsData(false); - controller.doCloseSessions(mockSettingsDataProvider); + mockSettingsProvider(false); + controller.doCloseSessions(mockSettingsProvider); verify(mockSessionReportingCoordinator, never()) .persistRelevantAppExitInfoEvent( eq(sessionId), any(), any(LogFileManager.class), any(UserMetadata.class)); } - private void mockSettingsData(boolean collectAnrs) { - Settings mockSettings = mock(Settings.class); - when(mockSettingsDataProvider.getSettings()).thenReturn(mockSettings); - when(mockSettings.getFeaturesData()).thenReturn(new FeaturesSettingsData(true, collectAnrs)); + private void mockSettingsProvider(boolean collectAnrs) { + Settings settings = + new Settings( + 0, new SessionData(4, 4), new FeatureFlagData(true, collectAnrs), 3, 0, 1.0, 1.0, 1); + when(mockSettingsProvider.getSettingsSync()).thenReturn(settings); } /** Creates a new CrashlyticsController with default options and opens a session. */