From 90322b30578b059ad758bc32b7ca016a5a301a1f Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Tue, 13 Apr 2021 15:49:38 -0400 Subject: [PATCH 1/9] Add collectAnrs to FeatureSettings --- .../internal/settings/SettingsV3JsonTransformTest.java | 1 + .../crashlytics/internal/settings/TestSettingsData.java | 2 +- .../internal/settings/DefaultSettingsJsonTransform.java | 7 ++++++- .../internal/settings/SettingsJsonConstants.java | 2 ++ .../internal/settings/SettingsV3JsonTransform.java | 7 ++++++- .../internal/settings/model/FeaturesSettingsData.java | 4 +++- 6 files changed, 19 insertions(+), 4 deletions(-) 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 1995b6e99d0..b57e9c3a5fb 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 @@ -96,6 +96,7 @@ private void assertSettingsData(SessionSettingsData settingsData) { private void assertFeaturesData(FeaturesSettingsData featuresSettingsData) { assertTrue(featuresSettingsData.collectReports); + assertFalse(featuresSettingsData.collectAnrs); } private void verifySettingsDataObject( 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 index 58349d3cc10..9885d4c1eeb 100644 --- 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 @@ -41,7 +41,7 @@ public TestSettingsData( } private static FeaturesSettingsData buildFeaturesData() { - return new FeaturesSettingsData(true); + return new FeaturesSettingsData(true, false); } private static SessionSettingsData buildSettingsData() { 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 e8bb6ce6a31..d5d3870774a 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 @@ -97,7 +97,12 @@ private static FeaturesSettingsData buildFeaturesSessionDataFrom(JSONObject json SettingsJsonConstants.FEATURES_COLLECT_REPORTS_KEY, SettingsJsonConstants.FEATURES_COLLECT_REPORTS_DEFAULT); - return new FeaturesSettingsData(collectReports); + 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) { 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 c5965059ac5..2d7bfcd7393 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 @@ -29,9 +29,11 @@ class SettingsJsonConstants { // Feature Switch Keys static final String FEATURES_COLLECT_REPORTS_KEY = "collect_reports"; + static final String FEATURES_COLLECT_ANRS_KEY = "collect_anrs"; // Feature Switch Defaults 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"; 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 8f3a2daf32a..5422c4512c5 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 @@ -119,9 +119,14 @@ private static FeaturesSettingsData buildFeaturesSessionDataFrom(JSONObject json 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); + // TODO: Build support back for "collect logged exceptions" - return new FeaturesSettingsData(collectReports); + return new FeaturesSettingsData(collectReports, collectAnrs); } private static SessionSettingsData defaultSessionData() { 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 index 14a6e8cfb59..ab7ead444d8 100644 --- 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 @@ -17,8 +17,10 @@ /** Immutable value object for storing feature switch settings */ public class FeaturesSettingsData { public final boolean collectReports; + public final boolean collectAnrs; - public FeaturesSettingsData(boolean collectReports) { + public FeaturesSettingsData(boolean collectReports, boolean collectAnrs) { this.collectReports = collectReports; + this.collectAnrs = collectAnrs; } } From 4e186a6edcaca64dc571fd2982ed239aeef91801 Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Tue, 13 Apr 2021 16:15:47 -0400 Subject: [PATCH 2/9] Add unit test to test settings received when anr collection is enabled --- .../firebase_settings_collect_anrs.json | 23 +++++++++++++++++++ .../settings/SettingsV3JsonTransformTest.java | 22 +++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 firebase-crashlytics/src/androidTest/assets/firebase_settings_collect_anrs.json diff --git a/firebase-crashlytics/src/androidTest/assets/firebase_settings_collect_anrs.json b/firebase-crashlytics/src/androidTest/assets/firebase_settings_collect_anrs.json new file mode 100644 index 00000000000..c6187ef0255 --- /dev/null +++ b/firebase-crashlytics/src/androidTest/assets/firebase_settings_collect_anrs.json @@ -0,0 +1,23 @@ +{ + "settings_version": 3, + "cache_duration": 7200, + "features": { + "collect_logged_exceptions": true, + "collect_reports": true, + "collect_analytics": false, + "prompt_enabled": false, + "push_enabled": false, + "firebase_crashlytics_enabled": false, + "collect_anrs": true + }, + "app": { + "status": "activated", + "update_required": true, + "report_upload_variant": 2, + "native_report_upload_variant": 2 + }, + "fabric": { + "org_id": "6001bf51c0329dc5da694f7f", + "bundle_id": "com.google.firebase.crashlytics.sdk.test" + } + } \ No newline at end of file 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 b57e9c3a5fb..6495e7f4902 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 @@ -60,6 +60,14 @@ public void testFirebaseSettingsTransform_newApp() throws Exception { verifySettingsDataObject(mockCurrentTimeProvider, settingsData, 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"); @@ -94,9 +102,9 @@ private void assertSettingsData(SessionSettingsData settingsData) { assertEquals(4, settingsData.maxCompleteSessionsCount); } - private void assertFeaturesData(FeaturesSettingsData featuresSettingsData) { + private void assertFeaturesData(FeaturesSettingsData featuresSettingsData, boolean collectAnrs) { assertTrue(featuresSettingsData.collectReports); - assertFalse(featuresSettingsData.collectAnrs); + assertEquals(featuresSettingsData.collectAnrs, collectAnrs); } private void verifySettingsDataObject( @@ -106,6 +114,14 @@ private void verifySettingsDataObject( private void verifySettingsDataObject( CurrentTimeProvider mockCurrentTimeProvider, SettingsData settingsData, boolean isAppNew) { + verifySettingsDataObject(mockCurrentTimeProvider, settingsData, isAppNew, false); + } + + private void verifySettingsDataObject( + CurrentTimeProvider mockCurrentTimeProvider, + SettingsData settingsData, + boolean isAppNew, + boolean collectAnrs) { assertEquals(7200010, settingsData.expiresAtMillis); assertEquals(3, settingsData.settingsVersion); @@ -113,7 +129,7 @@ private void verifySettingsDataObject( assertAppData(settingsData.appData, isAppNew); - assertFeaturesData(settingsData.featuresData); + assertFeaturesData(settingsData.featuresData, collectAnrs); assertSettingsData(settingsData.sessionData); From 62e8c181053cae5f50a43278766554af495731b5 Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Tue, 13 Apr 2021 16:17:56 -0400 Subject: [PATCH 3/9] Cleanup json file --- .../androidTest/assets/firebase_settings_collect_anrs.json | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/firebase-crashlytics/src/androidTest/assets/firebase_settings_collect_anrs.json b/firebase-crashlytics/src/androidTest/assets/firebase_settings_collect_anrs.json index c6187ef0255..f6c4ea7ee29 100644 --- a/firebase-crashlytics/src/androidTest/assets/firebase_settings_collect_anrs.json +++ b/firebase-crashlytics/src/androidTest/assets/firebase_settings_collect_anrs.json @@ -4,10 +4,6 @@ "features": { "collect_logged_exceptions": true, "collect_reports": true, - "collect_analytics": false, - "prompt_enabled": false, - "push_enabled": false, - "firebase_crashlytics_enabled": false, "collect_anrs": true }, "app": { @@ -20,4 +16,4 @@ "org_id": "6001bf51c0329dc5da694f7f", "bundle_id": "com.google.firebase.crashlytics.sdk.test" } - } \ No newline at end of file + } From eb08e6bc1fd9b1954401a84ed957bf5504362b49 Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Wed, 14 Apr 2021 15:09:35 -0400 Subject: [PATCH 4/9] Add ability to get the startTimestampMs of a session --- .../CrashlyticsReportPersistenceTest.java | 11 +++++++ .../common/CrashlyticsController.java | 13 ++++---- .../common/CrashlyticsReportDataCapture.java | 8 ++--- .../common/SessionReportingCoordinator.java | 5 +-- .../CrashlyticsReportPersistence.java | 32 +++++++++++++++++++ 5 files changed, 56 insertions(+), 13 deletions(-) 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 ec2f7496f51..0a84b69b5d0 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 @@ -90,6 +90,17 @@ public void testListSortedOpenSessionIds_noOpenSessions() { assertTrue(openSessionIds.isEmpty()); } + @Test + public void testPersistReports_getStartTimestampMs() { + final String sessionId = "testSession"; + final CrashlyticsReport testReport = makeTestReport(sessionId); + + reportPersistence.persistReport(testReport); + assertEquals( + testReport.getSession().getStartedAt() * 1000, + reportPersistence.getStartTimestampMs(sessionId)); + } + @Test public void testHasFinalizedReports() { final String sessionId = "testSession"; 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 da5857213ba..004bb41a38b 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 @@ -37,7 +37,6 @@ import java.io.FilenameFilter; import java.io.IOException; import java.util.ArrayList; -import java.util.Date; import java.util.List; import java.util.Locale; import java.util.Map; @@ -168,7 +167,7 @@ synchronized void handleUncaughtException( // Capture the time that the crash occurs and close over it so that the time doesn't // reflect when we get around to executing the task later. - final Date time = new Date(); + final long time = System.currentTimeMillis(); final Task handleUncaughtExceptionTask = backgroundWorker.submitTask( @@ -190,7 +189,7 @@ public Task call() throws Exception { reportingCoordinator.persistFatalEvent( ex, thread, currentSessionId, timestampSeconds); - doWriteAppExceptionMarker(time.getTime()); + doWriteAppExceptionMarker(time); doCloseSessions(); doOpenSession(); @@ -397,7 +396,7 @@ public Void call() throws Exception { void writeNonFatalException(@NonNull final Thread thread, @NonNull final Throwable ex) { // Capture and close over the current time, so that we get the exact call time, // rather than the time at which the task executes. - final Date time = new Date(); + final long time = System.currentTimeMillis(); backgroundWorker.submit( new Runnable() { @@ -661,11 +660,11 @@ private void finalizePreviousNativeSession(String previousSessionId) { } private static long getCurrentTimestampSeconds() { - return getTimestampSeconds(new Date()); + return getTimestampSeconds(System.currentTimeMillis()); } - private static long getTimestampSeconds(Date date) { - return date.getTime() / 1000; + private static long getTimestampSeconds(Long timestampMillis) { + return timestampMillis / 1000; } // region Serialization to protobuf diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsReportDataCapture.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsReportDataCapture.java index f736697ae7b..92c37da541a 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsReportDataCapture.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsReportDataCapture.java @@ -79,8 +79,8 @@ public CrashlyticsReportDataCapture( this.stackTraceTrimmingStrategy = stackTraceTrimmingStrategy; } - public CrashlyticsReport captureReportData(String identifier, long timestamp) { - return buildReportData().setSession(populateSessionData(identifier, timestamp)).build(); + public CrashlyticsReport captureReportData(String identifier, long timestampSeconds) { + return buildReportData().setSession(populateSessionData(identifier, timestampSeconds)).build(); } public Event captureEventData( @@ -120,9 +120,9 @@ private CrashlyticsReport.Builder buildReportData() { .setPlatform(REPORT_ANDROID_PLATFORM); } - private CrashlyticsReport.Session populateSessionData(String identifier, long timestamp) { + private CrashlyticsReport.Session populateSessionData(String identifier, long timestampSeconds) { return CrashlyticsReport.Session.builder() - .setStartedAt(timestamp) + .setStartedAt(timestampSeconds) .setIdentifier(identifier) .setGenerator(GENERATOR) .setApp(populateSessionApplicationData()) 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 4d43f75a535..8725dd51c86 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 @@ -88,8 +88,9 @@ public static SessionReportingCoordinator create( } @Override - public void onBeginSession(@NonNull String sessionId, long timestamp) { - final CrashlyticsReport capturedReport = dataCapture.captureReportData(sessionId, timestamp); + public void onBeginSession(@NonNull String sessionId, long timestampSeconds) { + final CrashlyticsReport capturedReport = + dataCapture.captureReportData(sessionId, timestampSeconds); reportPersistence.persistReport(capturedReport); } 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 7dc67afa3bf..aa7a99fcbd7 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 @@ -59,6 +59,9 @@ public class CrashlyticsReportPersistence { private static final String REPORT_FILE_NAME = "report"; private static final String USER_FILE_NAME = "user"; + // We use the lastModified timestamp of this file to quickly store and access the startTime in ms + // of a session. + private static final String SESSION_START_TIMESTAMP_FILE_NAME = "start-time"; private static final String EVENT_FILE_NAME_PREFIX = "event"; private static final int EVENT_COUNTER_WIDTH = 10; // String width of maximum positive int value private static final String EVENT_COUNTER_FORMAT = "%0" + EVENT_COUNTER_WIDTH + "d"; @@ -110,6 +113,10 @@ public void persistReport(@NonNull CrashlyticsReport report) { final File sessionDirectory = prepareDirectory(getSessionDirectoryById(sessionId)); final String json = TRANSFORM.reportToJson(report); writeTextFile(new File(sessionDirectory, REPORT_FILE_NAME), json); + writeTextFile( + new File(sessionDirectory, SESSION_START_TIMESTAMP_FILE_NAME), + "", + session.getStartedAt()); } catch (IOException e) { Logger.getLogger().d("Could not persist report for session " + sessionId, e); } @@ -177,6 +184,19 @@ public List listSortedOpenSessionIds() { return openSessionIds; } + /** + * Gets the startTimestampMs of the given sessionId. + * + * @param sessionId + * @return startTimestampMs + */ + public long getStartTimestampMs(String sessionId) { + final File sessionDirectory = getSessionDirectoryById(sessionId); + final File sessionStartTimestampFile = + new File(sessionDirectory, SESSION_START_TIMESTAMP_FILE_NAME); + return sessionStartTimestampFile.lastModified(); + } + public boolean hasFinalizedReports() { return !getAllFinalizedReportFiles().isEmpty(); } @@ -489,6 +509,14 @@ private static void writeTextFile(File file, String text) throws IOException { } } + private static void writeTextFile(File file, String text, long lastModifiedTimestampSeconds) + throws IOException { + try (OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file), UTF_8)) { + writer.write(text); + file.setLastModified(convertTimestampFromSecondsToMs(lastModifiedTimestampSeconds)); + } + } + @NonNull private static String readTextFile(@NonNull File file) throws IOException { final byte[] readBuffer = new byte[8192]; @@ -532,4 +560,8 @@ private static void recursiveDelete(@Nullable File file) { } file.delete(); } + + private static long convertTimestampFromSecondsToMs(long timestampSeconds) { + return timestampSeconds * 1000; + } } From c5f5f2688096bf966966c2be8ea29450df30ee68 Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Wed, 14 Apr 2021 15:30:36 -0400 Subject: [PATCH 5/9] Change Long to long --- .../crashlytics/internal/common/CrashlyticsController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 004bb41a38b..32b4f4a67d4 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 @@ -663,7 +663,7 @@ private static long getCurrentTimestampSeconds() { return getTimestampSeconds(System.currentTimeMillis()); } - private static long getTimestampSeconds(Long timestampMillis) { + private static long getTimestampSeconds(long timestampMillis) { return timestampMillis / 1000; } From 04229705ed40ecc27b7f7075e73d42e0e3cc0a56 Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Wed, 21 Apr 2021 14:52:38 -0400 Subject: [PATCH 6/9] Add ApplicationExitInfo to CrashlyticsReport --- .../internal/model/CrashlyticsReport.java | 63 +++++++++++++++++++ .../internal/model/CrashlyticsReportTest.java | 46 ++++++++++++-- 2 files changed, 104 insertions(+), 5 deletions(-) diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReport.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReport.java index 75daac3de2d..1908c6c5d47 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReport.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReport.java @@ -105,6 +105,9 @@ public Type getType() { @Nullable public abstract FilesPayload getNdkPayload(); + @Nullable + public abstract ApplicationExitInfo getAppExitInfo(); + @NonNull protected abstract Builder toBuilder(); @@ -155,6 +158,16 @@ public CrashlyticsReport withNdkPayload(@NonNull FilesPayload filesPayload) { return toBuilder().setSession(null).setNdkPayload(filesPayload).build(); } + /** + * Augment an existing {@link CrashlyticsReport} with an ApplicationExitInfoPayload + * + * @return a new {@link CrashlyticsReport} with AppExitInfo data inside of it. + */ + @NonNull + public CrashlyticsReport withAppExitInfo(@NonNull ApplicationExitInfo appExitInfo) { + return toBuilder().setAppExitInfo(appExitInfo).build(); + } + /** * Augment an existing {@link CrashlyticsReport} with fields set at session end. * @@ -1021,6 +1034,53 @@ public abstract static class Builder { } } + @AutoValue + public abstract static class ApplicationExitInfo { + + @NonNull + public static ApplicationExitInfo.Builder builder() { + return new AutoValue_CrashlyticsReport_ApplicationExitInfo.Builder(); + } + + @NonNull + public abstract String getProcessName(); + + @NonNull + public abstract int getReasonCode(); + + @NonNull + public abstract int getImportance(); + + @NonNull + public abstract long getTimestamp(); + + @NonNull + public abstract String getTraceFile(); + + /** Builder for {@link ApplicationExitInfo}. */ + @AutoValue.Builder + public abstract static class Builder { + + @NonNull + public abstract ApplicationExitInfo.Builder setProcessName(@NonNull String value); + + @NonNull + public abstract ApplicationExitInfo.Builder setReasonCode(@NonNull int value); + + @NonNull + public abstract ApplicationExitInfo.Builder setImportance(@NonNull int value); + + @NonNull + public abstract ApplicationExitInfo.Builder setTimestamp(@NonNull long value); + + @Nullable + public abstract ApplicationExitInfo.Builder setTraceFile(@Nullable String value); + + @NonNull + public abstract ApplicationExitInfo build(); + } + } + @AutoValue.Builder public abstract static class Builder { @@ -1048,6 +1108,9 @@ public abstract static class Builder { @NonNull public abstract Builder setNdkPayload(FilesPayload value); + @NonNull + public abstract Builder setAppExitInfo(ApplicationExitInfo value); + @NonNull public abstract CrashlyticsReport build(); } diff --git a/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java b/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java index 93c1ec78f53..d4a38394946 100644 --- a/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java +++ b/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java @@ -36,13 +36,27 @@ public void testWithEvents_returnsNewReportWithEvents() { assertNull(testReport.getSession().getEvents()); - final CrashlyticsReport withEventsReport = testReport.withEvents(makeTestEvents(2)); + final CrashlyticsReport withEventsReport = testReport.withEvents(makeTestEvents(2, false)); assertNotEquals(testReport, withEventsReport); assertNotNull(withEventsReport.getSession().getEvents()); assertEquals(2, withEventsReport.getSession().getEvents().size()); } + @Test + public void testWithEvents_returnsNewReportWithAnr() { + final CrashlyticsReport testReport = makeTestReport(); + + assertNull(testReport.getSession().getEvents()); + final CrashlyticsReport withAnrEventsReport = + testReport.withEvents(makeTestEvents(2, true)).withAppExitInfo(makeAppExitInfo()); + + assertNotEquals(testReport, withAnrEventsReport); + assertNotNull(withAnrEventsReport.getSession().getEvents()); + assertEquals(2, withAnrEventsReport.getSession().getEvents().size()); + assertNotNull(withAnrEventsReport.getAppExitInfo()); + } + @Test public void testWithOrganizationId_returnsNewReportWithOrganizationId() { final CrashlyticsReport testReport = makeTestReport(); @@ -201,17 +215,25 @@ private static Application makeTestApplication() { .build(); } - private static ImmutableList makeTestEvents(int numEvents) { + private static ImmutableList makeTestEvents(int numEvents, boolean includeAnr) { List events = new ArrayList<>(); for (int i = 0; i < numEvents; i++) { - events.add(makeTestEvent()); + if (i == numEvents - 1 && includeAnr) { + events.add(makeAnrEvent()); + } else { + events.add(makeTestEvent()); + } } return ImmutableList.from(events); } - private static Event makeTestEvent() { + private static Event makeAnrEvent() { + return makeTestEvent("ANR"); + } + + private static Event makeTestEvent(String eventType) { return Event.builder() - .setType("type") + .setType(eventType) .setTimestamp(1000) .setApp( Session.Event.Application.builder() @@ -256,6 +278,20 @@ private static Event makeTestEvent() { .build(); } + private static Event makeTestEvent() { + return makeTestEvent("test"); + } + + private static CrashlyticsReport.ApplicationExitInfo makeAppExitInfo() { + return CrashlyticsReport.ApplicationExitInfo.builder() + .setTraceFile("trace") + .setTimestamp(1L) + .setImportance(1) + .setReasonCode(1) + .setProcessName("test") + .build(); + } + private static ImmutableList makeTestFrames() { return ImmutableList.from( Frame.builder() From b928e3f1d46611f2e89ca3debeb51b86209d0ac4 Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Wed, 21 Apr 2021 15:52:38 -0400 Subject: [PATCH 7/9] Comment cleanup --- .../crashlytics/internal/model/CrashlyticsReport.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReport.java b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReport.java index 1908c6c5d47..08ecbb926ef 100644 --- a/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReport.java +++ b/firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReport.java @@ -159,9 +159,9 @@ public CrashlyticsReport withNdkPayload(@NonNull FilesPayload filesPayload) { } /** - * Augment an existing {@link CrashlyticsReport} with an ApplicationExitInfoPayload + * Augment an existing {@link CrashlyticsReport} with an ApplicationExitInfo * - * @return a new {@link CrashlyticsReport} with AppExitInfo data inside of it. + * @return a new {@link CrashlyticsReport} with AppExitInfo inside of it. */ @NonNull public CrashlyticsReport withAppExitInfo(@NonNull ApplicationExitInfo appExitInfo) { From 20b4f30d7d4cfd38984e84e28f230825778b43cf Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Wed, 21 Apr 2021 15:58:43 -0400 Subject: [PATCH 8/9] Revert makeEvents refactoring --- .../internal/model/CrashlyticsReportTest.java | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java b/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java index d4a38394946..149797884ce 100644 --- a/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java +++ b/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java @@ -36,7 +36,7 @@ public void testWithEvents_returnsNewReportWithEvents() { assertNull(testReport.getSession().getEvents()); - final CrashlyticsReport withEventsReport = testReport.withEvents(makeTestEvents(2, false)); + final CrashlyticsReport withEventsReport = testReport.withEvents(makeTestEvents(2)); assertNotEquals(testReport, withEventsReport); assertNotNull(withEventsReport.getSession().getEvents()); @@ -49,11 +49,13 @@ public void testWithEvents_returnsNewReportWithAnr() { assertNull(testReport.getSession().getEvents()); final CrashlyticsReport withAnrEventsReport = - testReport.withEvents(makeTestEvents(2, true)).withAppExitInfo(makeAppExitInfo()); + testReport + .withEvents(ImmutableList.from(makeAnrEvent())) + .withAppExitInfo(makeAppExitInfo()); assertNotEquals(testReport, withAnrEventsReport); assertNotNull(withAnrEventsReport.getSession().getEvents()); - assertEquals(2, withAnrEventsReport.getSession().getEvents().size()); + assertEquals(1, withAnrEventsReport.getSession().getEvents().size()); assertNotNull(withAnrEventsReport.getAppExitInfo()); } @@ -215,14 +217,10 @@ private static Application makeTestApplication() { .build(); } - private static ImmutableList makeTestEvents(int numEvents, boolean includeAnr) { + private static ImmutableList makeTestEvents(int numEvents) { List events = new ArrayList<>(); for (int i = 0; i < numEvents; i++) { - if (i == numEvents - 1 && includeAnr) { - events.add(makeAnrEvent()); - } else { - events.add(makeTestEvent()); - } + events.add(makeTestEvent()); } return ImmutableList.from(events); } From 2c8f5a9239908b94fe3220443cd6dcfc6c1b4828 Mon Sep 17 00:00:00 2001 From: Tejas Deshpande Date: Wed, 21 Apr 2021 16:00:13 -0400 Subject: [PATCH 9/9] More cleanup --- .../crashlytics/internal/model/CrashlyticsReportTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java b/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java index 149797884ce..91d6530401d 100644 --- a/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java +++ b/firebase-crashlytics/src/test/java/com/google/firebase/crashlytics/internal/model/CrashlyticsReportTest.java @@ -229,6 +229,10 @@ private static Event makeAnrEvent() { return makeTestEvent("ANR"); } + private static Event makeTestEvent() { + return makeTestEvent("test"); + } + private static Event makeTestEvent(String eventType) { return Event.builder() .setType(eventType) @@ -276,10 +280,6 @@ private static Event makeTestEvent(String eventType) { .build(); } - private static Event makeTestEvent() { - return makeTestEvent("test"); - } - private static CrashlyticsReport.ApplicationExitInfo makeAppExitInfo() { return CrashlyticsReport.ApplicationExitInfo.builder() .setTraceFile("trace")