Skip to content

Commit d70b4d0

Browse files
committed
Merge remote-tracking branch 'origin/master' into OverlayNeverNull
2 parents 28570e1 + f5845b2 commit d70b4d0

File tree

47 files changed

+696
-97
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+696
-97
lines changed

appcheck/firebase-appcheck/src/main/java/com/google/firebase/appcheck/FirebaseAppCheckRegistrar.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.firebase.components.Component;
2222
import com.google.firebase.components.ComponentRegistrar;
2323
import com.google.firebase.components.Dependency;
24+
import com.google.firebase.heartbeatinfo.HeartBeatConsumerComponent;
2425
import com.google.firebase.heartbeatinfo.HeartBeatController;
2526
import com.google.firebase.platforminfo.LibraryVersionComponent;
2627
import java.util.Arrays;
@@ -48,6 +49,7 @@ public List<Component<?>> getComponents() {
4849
container.getProvider(HeartBeatController.class)))
4950
.alwaysEager()
5051
.build(),
52+
HeartBeatConsumerComponent.create(),
5153
LibraryVersionComponent.create("fire-app-check", BuildConfig.VERSION_NAME));
5254
}
5355
}

appcheck/firebase-appcheck/src/test/java/com/google/firebase/appcheck/FirebaseAppCheckRegistrarTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public void testGetComponents() {
3434
FirebaseAppCheckRegistrar firebaseAppCheckRegistrar = new FirebaseAppCheckRegistrar();
3535
List<Component<?>> components = firebaseAppCheckRegistrar.getComponents();
3636
assertThat(components).isNotEmpty();
37-
assertThat(components).hasSize(2);
37+
assertThat(components).hasSize(3);
3838
Component<?> firebaseAppCheckComponent = components.get(0);
3939
assertThat(firebaseAppCheckComponent.getDependencies())
4040
.containsExactly(

firebase-abt/gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
version=21.0.1
2-
latestReleasedVersion=21.0.0
1+
version=21.0.2
2+
latestReleasedVersion=21.0.1

firebase-appdistribution/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,4 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
version=0.0.1
15+
version=16.0.1

firebase-common/gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
version=20.0.1
2-
latestReleasedVersion=20.0.0
1+
version=20.1.1
2+
latestReleasedVersion=20.1.0
33
android.enableUnitTestBinaryResources=true

firebase-common/src/main/java/com/google/firebase/FirebaseApp.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import android.os.Looper;
2828
import android.text.TextUtils;
2929
import android.util.Log;
30+
import androidx.annotation.GuardedBy;
3031
import androidx.annotation.NonNull;
3132
import androidx.annotation.Nullable;
3233
import androidx.annotation.RestrictTo;
@@ -59,7 +60,6 @@
5960
import java.util.concurrent.Executor;
6061
import java.util.concurrent.atomic.AtomicBoolean;
6162
import java.util.concurrent.atomic.AtomicReference;
62-
import javax.annotation.concurrent.GuardedBy;
6363

6464
/**
6565
* The entry point of Firebase SDKs. It holds common configuration and state for Firebase APIs. Most

firebase-config/gradle.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# limitations under the License.
1515
#
1616

17-
version=21.0.2
18-
latestReleasedVersion=21.0.1
17+
version=21.0.3
18+
latestReleasedVersion=21.0.2
1919
android.enableUnitTestBinaryResources=true
2020

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
version=18.2.9
2-
latestReleasedVersion=18.2.8
1+
version=18.2.10
2+
latestReleasedVersion=18.2.9
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
version=18.2.9
2-
latestReleasedVersion=18.2.8
1+
version=18.2.10
2+
latestReleasedVersion=18.2.9

firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/common/SessionReportingCoordinatorTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -438,13 +438,13 @@ public void onReportSend_successfulReportsAreDeleted() {
438438
final Task<CrashlyticsReportWithSessionId> failedTask =
439439
Tasks.forException(new Exception("fail"));
440440

441-
when(reportSender.sendReport(mockReport1)).thenReturn(successfulTask);
442-
when(reportSender.sendReport(mockReport2)).thenReturn(failedTask);
441+
when(reportSender.enqueueReport(mockReport1, false)).thenReturn(successfulTask);
442+
when(reportSender.enqueueReport(mockReport2, false)).thenReturn(failedTask);
443443

444444
reportingCoordinator.sendReports(Runnable::run);
445445

446-
verify(reportSender).sendReport(mockReport1);
447-
verify(reportSender).sendReport(mockReport2);
446+
verify(reportSender).enqueueReport(mockReport1, false);
447+
verify(reportSender).enqueueReport(mockReport2, false);
448448
}
449449

450450
@Test

firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/send/DataTransportCrashlyticsReportSenderTest.java

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import com.google.android.gms.tasks.Task;
3030
import com.google.android.gms.tasks.Tasks;
3131
import com.google.firebase.crashlytics.internal.common.CrashlyticsReportWithSessionId;
32+
import com.google.firebase.crashlytics.internal.common.OnDemandCounter;
3233
import com.google.firebase.crashlytics.internal.model.CrashlyticsReport;
3334
import java.io.File;
3435
import java.util.concurrent.ExecutionException;
@@ -51,7 +52,9 @@ public class DataTransportCrashlyticsReportSenderTest {
5152
public void setUp() throws Exception {
5253
MockitoAnnotations.initMocks(this);
5354
when(mockTransform.apply(any())).thenReturn(new byte[0]);
54-
reportSender = new DataTransportCrashlyticsReportSender(mockTransport, mockTransform);
55+
reportSender =
56+
new DataTransportCrashlyticsReportSender(
57+
new ReportQueue(60, 1.2, 3_000, mockTransport, new OnDemandCounter()), mockTransform);
5558
}
5659

5760
@Test
@@ -61,10 +64,13 @@ public void testSendReportsSuccessful() throws Exception {
6164
final CrashlyticsReportWithSessionId report1 = mockReportWithSessionId();
6265
final CrashlyticsReportWithSessionId report2 = mockReportWithSessionId();
6366

64-
final Task<CrashlyticsReportWithSessionId> send1 = reportSender.sendReport(report1);
65-
final Task<CrashlyticsReportWithSessionId> send2 = reportSender.sendReport(report2);
67+
final Task<CrashlyticsReportWithSessionId> send1 =
68+
reportSender.enqueueReport(report1, /*isOnDemand=*/ true);
69+
final Task<CrashlyticsReportWithSessionId> send2 =
70+
reportSender.enqueueReport(report2, /*isOnDemand=*/ true);
6671

6772
try {
73+
Thread.sleep(2_000); // give time to process queue
6874
Tasks.await(send1);
6975
Tasks.await(send2);
7076
} catch (ExecutionException e) {
@@ -85,10 +91,11 @@ public void testSendReportsFailure() throws Exception {
8591
final CrashlyticsReportWithSessionId report1 = mockReportWithSessionId();
8692
final CrashlyticsReportWithSessionId report2 = mockReportWithSessionId();
8793

88-
final Task<CrashlyticsReportWithSessionId> send1 = reportSender.sendReport(report1);
89-
final Task<CrashlyticsReportWithSessionId> send2 = reportSender.sendReport(report2);
94+
final Task<CrashlyticsReportWithSessionId> send1 = reportSender.enqueueReport(report1, false);
95+
final Task<CrashlyticsReportWithSessionId> send2 = reportSender.enqueueReport(report2, false);
9096

9197
try {
98+
Thread.sleep(2_000); // give time to process queue
9299
Tasks.await(send1);
93100
Tasks.await(send2);
94101
} catch (ExecutionException e) {
@@ -112,10 +119,11 @@ public void testSendReports_oneSuccessOneFail() throws Exception {
112119
final CrashlyticsReportWithSessionId report1 = mockReportWithSessionId();
113120
final CrashlyticsReportWithSessionId report2 = mockReportWithSessionId();
114121

115-
final Task<CrashlyticsReportWithSessionId> send1 = reportSender.sendReport(report1);
116-
final Task<CrashlyticsReportWithSessionId> send2 = reportSender.sendReport(report2);
122+
final Task<CrashlyticsReportWithSessionId> send1 = reportSender.enqueueReport(report1, false);
123+
final Task<CrashlyticsReportWithSessionId> send2 = reportSender.enqueueReport(report2, false);
117124

118125
try {
126+
Thread.sleep(2_000); // give time to process queue
119127
Tasks.await(send1);
120128
Tasks.await(send2);
121129
} catch (ExecutionException e) {

firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/settings/TestSettingsData.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ public TestSettingsData(
3737
buildSettingsData(),
3838
buildFeaturesData(),
3939
settingsVersion,
40-
3600);
40+
3600,
41+
10,
42+
1.2,
43+
60);
4144
}
4245

4346
private static FeaturesSettingsData buildFeaturesData() {

firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsController.java

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class CrashlyticsController {
8585
private final SessionReportingCoordinator reportingCoordinator;
8686

8787
private CrashlyticsUncaughtExceptionHandler crashHandler;
88+
private SettingsDataProvider settingsProvider = null;
8889

8990
// A promise that will be resolved when unsent reports are found on the device, and
9091
// send/deleteUnsentReports can be called to decide how to deal with them.
@@ -140,6 +141,7 @@ void enableExceptionHandling(
140141
String sessionIdentifier,
141142
Thread.UncaughtExceptionHandler defaultHandler,
142143
SettingsDataProvider settingsProvider) {
144+
this.settingsProvider = settingsProvider;
143145
// This must be called before installing the controller with
144146
// Thread.setDefaultUncaughtExceptionHandler to ensure that we are ready to handle
145147
// any crashes we catch.
@@ -160,10 +162,18 @@ public void onUncaughtException(
160162
Thread.setDefaultUncaughtExceptionHandler(crashHandler);
161163
}
162164

163-
synchronized void handleUncaughtException(
165+
void handleUncaughtException(
164166
@NonNull SettingsDataProvider settingsDataProvider,
165167
@NonNull final Thread thread,
166168
@NonNull final Throwable ex) {
169+
handleUncaughtException(settingsDataProvider, thread, ex, /*isOnDemand=*/ false);
170+
}
171+
172+
synchronized void handleUncaughtException(
173+
@NonNull SettingsDataProvider settingsDataProvider,
174+
@NonNull final Thread thread,
175+
@NonNull final Throwable ex,
176+
boolean isOnDemand) {
167177

168178
Logger.getLogger()
169179
.d("Handling uncaught " + "exception \"" + ex + "\" from thread " + thread.getName());
@@ -222,13 +232,15 @@ public Task<Void> then(@Nullable AppSettingsData appSettingsData)
222232
// Data collection is enabled, so it's safe to send the report.
223233
return Tasks.whenAll(
224234
logAnalyticsAppExceptionEvents(),
225-
reportingCoordinator.sendReports(executor));
235+
reportingCoordinator.sendReports(
236+
executor, isOnDemand ? currentSessionId : null));
226237
}
227238
});
228239
}
229240
});
230241

231242
try {
243+
// TODO(mrober): Don't block the main thread ever for on-demand fatals.
232244
Utils.awaitEvenIfOnMainThread(handleUncaughtExceptionTask);
233245
} catch (Exception e) {
234246
Logger.getLogger().e("Error handling uncaught exception", e);
@@ -419,6 +431,14 @@ public void run() {
419431
});
420432
}
421433

434+
void logFatalException(Thread thread, Throwable ex) {
435+
if (settingsProvider == null) {
436+
Logger.getLogger().w("settingsProvider not set");
437+
return;
438+
}
439+
handleUncaughtException(settingsProvider, thread, ex, /*isOnDemand=*/ true);
440+
}
441+
422442
void setUserId(String identifier) {
423443
userMetadata.setUserId(identifier);
424444
}

firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/common/CrashlyticsCore.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,19 @@ public class CrashlyticsCore {
6161

6262
static final int DEFAULT_MAIN_HANDLER_TIMEOUT_SEC = 4;
6363

64+
private static final String ON_DEMAND_RECORDED_KEY =
65+
"com.crashlytics.on-demand.recorded-exceptions";
66+
private static final String ON_DEMAND_DROPPED_KEY =
67+
"com.crashlytics.on-demand.dropped-exceptions";
68+
6469
// If this marker sticks around, the app is crashing before we finished initializing
6570
private static final String INITIALIZATION_MARKER_FILE_NAME = "initialization_marker";
6671
static final String CRASH_MARKER_FILE_NAME = "crash_marker";
6772

6873
private final Context context;
6974
private final FirebaseApp app;
7075
private final DataCollectionArbiter dataCollectionArbiter;
76+
private final OnDemandCounter onDemandCounter;
7177

7278
private final long startTime;
7379

@@ -110,6 +116,7 @@ public CrashlyticsCore(
110116
this.backgroundWorker = new CrashlyticsBackgroundWorker(crashHandlerExecutor);
111117

112118
startTime = System.currentTimeMillis();
119+
onDemandCounter = new OnDemandCounter();
113120
}
114121

115122
// endregion
@@ -150,7 +157,8 @@ public boolean onPreExecute(AppData appData, SettingsDataProvider settingsProvid
150157
logFileManager,
151158
userMetadata,
152159
stackTraceTrimmingStrategy,
153-
settingsProvider);
160+
settingsProvider,
161+
onDemandCounter);
154162

155163
controller =
156164
new CrashlyticsController(
@@ -348,6 +356,10 @@ public void setCustomKeys(Map<String, String> keysAndValues) {
348356
controller.setCustomKeys(keysAndValues);
349357
}
350358

359+
// endregion
360+
361+
// region Internal API
362+
351363
/**
352364
* Set a value to be associated with a given key for your crash data. The key/value pairs will be
353365
* reported with any crash that occurs in this session. A maximum of 64 key/value pairs can be
@@ -364,6 +376,19 @@ public void setInternalKey(String key, String value) {
364376
controller.setInternalKey(key, value);
365377
}
366378

379+
/** Logs a fatal Throwable on the Crashlytics servers on-demand. */
380+
public void logFatalException(Throwable throwable) {
381+
Logger.getLogger()
382+
.d("Recorded on-demand fatal events: " + onDemandCounter.getRecordedOnDemandExceptions());
383+
Logger.getLogger()
384+
.d("Dropped on-demand fatal events: " + onDemandCounter.getDroppedOnDemandExceptions());
385+
controller.setInternalKey(
386+
ON_DEMAND_RECORDED_KEY, Integer.toString(onDemandCounter.getRecordedOnDemandExceptions()));
387+
controller.setInternalKey(
388+
ON_DEMAND_DROPPED_KEY, Integer.toString(onDemandCounter.getDroppedOnDemandExceptions()));
389+
controller.logFatalException(Thread.currentThread(), throwable);
390+
}
391+
367392
// endregion
368393

369394
// region Package-protected getters
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright 2022 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package com.google.firebase.crashlytics.internal.common;
16+
17+
import java.util.concurrent.atomic.AtomicInteger;
18+
19+
/** Simple, thread-safe, class to keep count of recorded and dropped on-demand events. */
20+
public final class OnDemandCounter {
21+
private final AtomicInteger recordedOnDemandExceptions;
22+
private final AtomicInteger droppedOnDemandExceptions;
23+
24+
public OnDemandCounter() {
25+
recordedOnDemandExceptions = new AtomicInteger();
26+
droppedOnDemandExceptions = new AtomicInteger();
27+
}
28+
29+
public int getRecordedOnDemandExceptions() {
30+
return recordedOnDemandExceptions.get();
31+
}
32+
33+
public void incrementRecordedOnDemandExceptions() {
34+
recordedOnDemandExceptions.getAndIncrement();
35+
}
36+
37+
public int getDroppedOnDemandExceptions() {
38+
return droppedOnDemandExceptions.get();
39+
}
40+
41+
public void incrementDroppedOnDemandExceptions() {
42+
droppedOnDemandExceptions.getAndIncrement();
43+
}
44+
45+
public void resetDroppedOnDemandExceptions() {
46+
droppedOnDemandExceptions.set(0);
47+
}
48+
}

0 commit comments

Comments
 (0)