Skip to content

Migrate firebase-crashlytics SDK to FIS #1760

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jul 8, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions firebase-crashlytics/firebase-crashlytics.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,8 @@ dependencies {
implementation project(':transport:transport-api')
implementation project(':transport:transport-runtime')
implementation project(':transport:transport-backend-cct')
implementation ('com.google.firebase:firebase-iid:20.1.5') {
exclude group: "com.google.firebase", module: "firebase-common"
exclude group: "com.google.firebase", module: "firebase-components"
}
implementation 'com.google.firebase:firebase-iid-interop:17.0.0'
implementation project(':firebase-installations-interop')
runtimeOnly project(':firebase-installations')
implementation 'com.google.firebase:firebase-measurement-connector:18.0.0'
implementation "com.google.android.gms:play-services-tasks:17.0.0"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
package com.google.firebase.crashlytics.internal.common;

import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.android.gms.tasks.Tasks;
import com.google.firebase.crashlytics.internal.CrashlyticsTestCase;
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;

public class CLSUUIDTest extends CrashlyticsTestCase {

Expand All @@ -26,7 +28,8 @@ public class CLSUUIDTest extends CrashlyticsTestCase {

protected void setUp() throws Exception {
super.setUp();
FirebaseInstanceIdInternal instanceIdMock = mock(FirebaseInstanceIdInternal.class);
FirebaseInstallationsApi instanceIdMock = mock(FirebaseInstallationsApi.class);
when(instanceIdMock.getId()).thenReturn(Tasks.forResult("instanceId"));
idManager = new IdManager(getContext(), getContext().getPackageName(), instanceIdMock);
uuid = new CLSUUID(idManager);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,10 @@
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.util.Log;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.crashlytics.internal.CrashlyticsTestCase;
import com.google.firebase.crashlytics.internal.Logger;
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;
import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
Expand Down Expand Up @@ -352,7 +353,8 @@ public void testCapFileCount() throws Exception {

private File createEmptyClsFile(File dir) throws IOException {
final Context context = getContext();
FirebaseInstanceIdInternal instanceIdMock = mock(FirebaseInstanceIdInternal.class);
FirebaseInstallationsApi instanceIdMock = mock(FirebaseInstallationsApi.class);
when(instanceIdMock.getId()).thenReturn(Tasks.forResult("instanceId"));
final CLSUUID id =
new CLSUUID(new IdManager(context, context.getPackageName(), instanceIdMock));
final File f = new File(dir, id.toString() + ".cls");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@
import com.google.firebase.crashlytics.internal.settings.model.SessionSettingsData;
import com.google.firebase.crashlytics.internal.settings.model.SettingsData;
import com.google.firebase.crashlytics.internal.unity.UnityVersionProvider;
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
Expand Down Expand Up @@ -99,7 +99,8 @@ protected void setUp() throws Exception {

testContext = getContext();

FirebaseInstanceIdInternal instanceIdMock = mock(FirebaseInstanceIdInternal.class);
FirebaseInstallationsApi instanceIdMock = mock(FirebaseInstallationsApi.class);
when(instanceIdMock.getId()).thenReturn(Tasks.forResult("instanceId"));
idManager = new IdManager(testContext, testContext.getPackageName(), instanceIdMock);

BatteryIntentProvider.returnNull = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
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.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
Expand Down Expand Up @@ -94,7 +94,8 @@ public CoreBuilder(Context context, FirebaseOptions firebaseOptions) {
when(app.getApplicationContext()).thenReturn(context);
when(app.getOptions()).thenReturn(firebaseOptions);

FirebaseInstanceIdInternal instanceIdMock = mock(FirebaseInstanceIdInternal.class);
FirebaseInstallationsApi instanceIdMock = mock(FirebaseInstallationsApi.class);
when(instanceIdMock.getId()).thenReturn(Tasks.forResult("instanceId"));
idManager = new IdManager(context, context.getPackageName(), instanceIdMock);

nativeComponent = new MissingNativeComponent();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
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.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
Expand Down Expand Up @@ -681,7 +681,8 @@ CrashlyticsCore build(Context context) {
FirebaseApp app = mock(FirebaseApp.class);
when(app.getApplicationContext()).thenReturn(context);
when(app.getOptions()).thenReturn(testFirebaseOptions);
FirebaseInstanceIdInternal instanceIdMock = mock(FirebaseInstanceIdInternal.class);
FirebaseInstallationsApi instanceIdMock = mock(FirebaseInstallationsApi.class);
when(instanceIdMock.getId()).thenReturn(Tasks.forResult("instanceId"));
BreadcrumbSource breadcrumbSource =
this.breadcrumbSource == null ? new DisabledBreadcrumbSource() : this.breadcrumbSource;
final CrashlyticsCore crashlyticsCore =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@
import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.crashlytics.internal.model.CrashlyticsReport;
import com.google.firebase.crashlytics.internal.model.CrashlyticsReport.Session.Event.Application.Execution;
import com.google.firebase.crashlytics.internal.stacktrace.StackTraceTrimmingStrategy;
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
Expand All @@ -43,12 +44,12 @@ public class CrashlyticsReportDataCaptureTest {

@Mock private StackTraceTrimmingStrategy stackTraceTrimmingStrategy;

@Mock private FirebaseInstanceIdInternal instanceIdMock;
@Mock private FirebaseInstallationsApi instanceIdMock;

@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
when(instanceIdMock.getId()).thenReturn("installId");
when(instanceIdMock.getId()).thenReturn(Tasks.forResult("installId"));
when(stackTraceTrimmingStrategy.getTrimmedStackTrace(any(StackTraceElement[].class)))
.thenAnswer(i -> i.getArguments()[0]);
final Context context = ApplicationProvider.getApplicationContext();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
import static org.mockito.Mockito.when;

import android.content.SharedPreferences;
import com.google.android.gms.tasks.Tasks;
import com.google.firebase.crashlytics.internal.CrashlyticsTestCase;
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;
import java.util.concurrent.TimeoutException;

public class IdManagerTest extends CrashlyticsTestCase {

Expand Down Expand Up @@ -56,8 +58,8 @@ private void clearPrefs() {
}

private IdManager createIdManager(String instanceId) {
FirebaseInstanceIdInternal iid = mock(FirebaseInstanceIdInternal.class);
when(iid.getId()).thenReturn(instanceId);
FirebaseInstallationsApi iid = mock(FirebaseInstallationsApi.class);
when(iid.getId()).thenReturn(Tasks.forResult(instanceId));
return new IdManager(getContext(), getContext().getPackageName(), iid);
}

Expand All @@ -75,6 +77,23 @@ public void testCreateUUID() {
assertEquals(installId, idManager.getCrashlyticsInstallId());
}

public void testGetIdExceptionalCase() {
FirebaseInstallationsApi iid = mock(FirebaseInstallationsApi.class);
final String expectedInstallId = "expectedInstallId";
when(iid.getId())
.thenReturn(Tasks.forException(new TimeoutException("Fetching id timed out.")));
prefs
.edit()
.putString(IdManager.PREFKEY_INSTALLATION_UUID, expectedInstallId)
.putString(IdManager.PREFKEY_FIREBASE_IID, "firebase-iid")
.apply();

final IdManager idManager = new IdManager(getContext(), getContext().getPackageName(), iid);
final String actualInstallId = idManager.getCrashlyticsInstallId();
assertNotNull(actualInstallId);
assertEquals(expectedInstallId, actualInstallId);
}

public void testInstanceIdChanges() {
// Set up the initial state with a valid iid and uuid.
final String oldUuid = "old_uuid";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import com.google.firebase.components.ComponentRegistrar;
import com.google.firebase.components.Dependency;
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponent;
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;
import com.google.firebase.platforminfo.LibraryVersionComponent;
import java.util.Arrays;
import java.util.List;
Expand All @@ -33,7 +33,7 @@ public List<Component<?>> getComponents() {
return Arrays.asList(
Component.builder(FirebaseCrashlytics.class)
.add(Dependency.required(FirebaseApp.class))
.add(Dependency.requiredProvider(FirebaseInstanceIdInternal.class))
.add(Dependency.required(FirebaseInstallationsApi.class))
.add(Dependency.optional(AnalyticsConnector.class))
.add(Dependency.optional(CrashlyticsNativeComponent.class))
.factory(this::buildCrashlytics)
Expand All @@ -49,9 +49,9 @@ private FirebaseCrashlytics buildCrashlytics(ComponentContainer container) {

AnalyticsConnector analyticsConnector = container.get(AnalyticsConnector.class);

FirebaseInstanceIdInternal instanceId =
container.getProvider(FirebaseInstanceIdInternal.class).get();
FirebaseInstallationsApi firebaseInstallations = container.get(FirebaseInstallationsApi.class);

return FirebaseCrashlytics.init(app, instanceId, nativeComponent, analyticsConnector);
return FirebaseCrashlytics.init(
app, firebaseInstallations, nativeComponent, analyticsConnector);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
import com.google.firebase.crashlytics.internal.common.ExecutorUtils;
import com.google.firebase.crashlytics.internal.common.IdManager;
import com.google.firebase.crashlytics.internal.settings.SettingsController;
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
Expand All @@ -60,13 +60,13 @@ public class FirebaseCrashlytics {

static @Nullable FirebaseCrashlytics init(
@NonNull FirebaseApp app,
@NonNull FirebaseInstanceIdInternal instanceId,
@NonNull FirebaseInstallationsApi firebaseInstallationsApi,
@Nullable CrashlyticsNativeComponent nativeComponent,
@Nullable AnalyticsConnector analyticsConnector) {
Context context = app.getApplicationContext();
// Set up the IdManager.
final String appIdentifier = context.getPackageName();
final IdManager idManager = new IdManager(context, appIdentifier, instanceId);
final IdManager idManager = new IdManager(context, appIdentifier, firebaseInstallationsApi);

final DataCollectionArbiter arbiter = new DataCollectionArbiter(app);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@
import android.content.SharedPreferences;
import android.os.Build;
import androidx.annotation.NonNull;
import com.google.android.gms.tasks.Task;
import com.google.firebase.crashlytics.internal.Logger;
import com.google.firebase.iid.internal.FirebaseInstanceIdInternal;
import com.google.firebase.installations.FirebaseInstallationsApi;
import java.util.Locale;
import java.util.UUID;
import java.util.regex.Pattern;

public class IdManager implements InstallIdProvider {

public static final String DEFAULT_VERSION_NAME = "0.0";

static final String PREFKEY_ADVERTISING_ID = "crashlytics.advertising.id";
Expand All @@ -41,8 +43,8 @@ public class IdManager implements InstallIdProvider {
private final Context appContext;
private final String appIdentifier;

// The FirebaseInstanceIdInternal encapsulates a Firebase-wide install id
private final FirebaseInstanceIdInternal firebaseInstallId;
// The FirebaseInstallationsApi encapsulates a Firebase-wide install id
private final FirebaseInstallationsApi firebaseInstallationsApi;
// Crashlytics maintains a Crashlytics-specific install id, used in the crash processing backend
private String crashlyticsInstallId;

Expand All @@ -54,7 +56,7 @@ public class IdManager implements InstallIdProvider {
* null
*/
public IdManager(
Context appContext, String appIdentifier, FirebaseInstanceIdInternal firebaseInstallId) {
Context appContext, String appIdentifier, FirebaseInstallationsApi firebaseInstallationsApi) {
if (appContext == null) {
throw new IllegalArgumentException("appContext must not be null");
}
Expand All @@ -63,7 +65,7 @@ public IdManager(
}
this.appContext = appContext;
this.appIdentifier = appIdentifier;
this.firebaseInstallId = firebaseInstallId;
this.firebaseInstallationsApi = firebaseInstallationsApi;

installerPackageNameProvider = new InstallerPackageNameProvider();
}
Expand Down Expand Up @@ -99,11 +101,25 @@ public synchronized String getCrashlyticsInstallId() {

// Crashlytics rotates the Crashlytics-specific IID if the Firebase IID ("FID") is reset.
// This way, Crashlytics privacy controls are consistent with the rest of Firebase.
final String currentFid = firebaseInstallId.getId();
Task<String> currentFidTask = firebaseInstallationsApi.getId();
String currentFid = null;
final String cachedFid = prefs.getString(PREFKEY_FIREBASE_IID, null);

try {
currentFid = Utils.awaitEvenIfOnMainThread(currentFidTask);
} catch (Exception e) {
Logger.getLogger().d("Failed to retrieve installation id", e);

// this avoids rotating the identifier in the case that there was an exception which is likely
// to succeed in a future invocation
if (cachedFid != null) {
currentFid = cachedFid;
}
}

if (cachedFid == null) {
// This must be either 1) a new installation or 2) an upgrade from the legacy Crashlytics SDK.
// This must be either 1) a new installation or 2) an upgrade from the legacy
// Crashlytics SDK.
// If it is a legacy upgrade, we'll migrate the legacy ID to the new pref store.
final SharedPreferences legacyPrefs = CommonUtils.getLegacySharedPrefs(appContext);
final String legacyId = legacyPrefs.getString(PREFKEY_LEGACY_INSTALLATION_UUID, null);
Expand Down