Skip to content

Commit f104b6a

Browse files
authored
Set DevelopmentPlatform info for Flutter apps. (#3206)
1 parent 7c9c133 commit f104b6a

File tree

15 files changed

+111
-55
lines changed

15 files changed

+111
-55
lines changed

firebase-crashlytics-ndk/src/main/java/com/google/firebase/crashlytics/ndk/CrashlyticsNdkRegistrar.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@
1414

1515
package com.google.firebase.crashlytics.ndk;
1616

17-
import static com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider.UNITY_PLATFORM;
18-
1917
import android.content.Context;
2018
import com.google.firebase.components.Component;
2119
import com.google.firebase.components.ComponentContainer;
@@ -43,8 +41,7 @@ private CrashlyticsNativeComponent buildCrashlyticsNdk(ComponentContainer contai
4341
Context context = container.get(Context.class);
4442
// The signal handler is installed immediately for non-Unity apps. For Unity apps, it will
4543
// be installed when the Firebase Unity SDK explicitly calls installSignalHandler().
46-
boolean installHandlerDuringPrepSession =
47-
!UNITY_PLATFORM.equals(new DevelopmentPlatformProvider(context).getDevelopmentPlatform());
44+
boolean installHandlerDuringPrepSession = !DevelopmentPlatformProvider.isUnity(context);
4845
return FirebaseCrashlyticsNdk.create(context, installHandlerDuringPrepSession);
4946
}
5047
}

firebase-crashlytics-ndk/src/main/java/com/google/firebase/crashlytics/ndk/CrashpadController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ public void writeSessionApp(String sessionId, StaticSessionData.AppData appData)
118118
appData.versionName(),
119119
appData.installUuid(),
120120
appData.deliveryMechanism(),
121-
appData.developmentPlatform(),
122-
appData.developmentPlatformVersion());
121+
appData.developmentPlatformProvider().getDevelopmentPlatform(),
122+
appData.developmentPlatformProvider().getDevelopmentPlatformVersion());
123123
writeSessionJsonFile(fileStore, sessionId, json, APP_METADATA_FILE);
124124
}
125125

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
matt says hi

firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/CrashlyticsNativeComponentDeferredProxyTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package com.google.firebase.crashlytics.internal;
1616

1717
import static org.mockito.ArgumentMatchers.eq;
18+
import static org.mockito.Mockito.mock;
1819

1920
import androidx.annotation.NonNull;
2021
import androidx.test.runner.AndroidJUnit4;
@@ -57,7 +58,7 @@ public void whenAvailable(
5758

5859
StaticSessionData.AppData appData =
5960
StaticSessionData.AppData.create(
60-
"appId", "123", "1.2.3", "install_id", 0, "unity", "unityVersion");
61+
"appId", "123", "1.2.3", "install_id", 0, mock(DevelopmentPlatformProvider.class));
6162
StaticSessionData.OsData osData = StaticSessionData.OsData.create("release", "codeName", false);
6263
StaticSessionData.DeviceData deviceData =
6364
StaticSessionData.DeviceData.create(

firebase-crashlytics/src/androidTest/java/com/google/firebase/crashlytics/internal/DevelopmentPlatformProviderTest.java

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
package com.google.firebase.crashlytics.internal;
1616

17-
import static com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider.UNITY_PLATFORM;
1817
import static org.mockito.ArgumentMatchers.eq;
1918
import static org.mockito.Mockito.doReturn;
2019
import static org.mockito.Mockito.mock;
@@ -27,20 +26,36 @@
2726

2827
public class DevelopmentPlatformProviderTest extends CrashlyticsTestCase {
2928
private static final String PACKAGE_NAME = "package.name";
29+
private static final String UNITY_PLATFORM = "Unity";
3030
private static final String UNITY_VERSION = "2.0.0";
31+
private static final String FLUTTER_PLATFORM = "Flutter";
3132

3233
public void testDevelopmentPlatformInfo_withUnity_returnsPlatformAndVersion() throws Exception {
3334
Context context = createMockContext(/*withUnityResource=*/ true);
3435

36+
assertTrue(DevelopmentPlatformProvider.isUnity(context));
37+
3538
DevelopmentPlatformProvider provider = new DevelopmentPlatformProvider(context);
3639

3740
assertEquals(UNITY_PLATFORM, provider.getDevelopmentPlatform());
3841
assertEquals(UNITY_VERSION, provider.getDevelopmentPlatformVersion());
3942
}
4043

44+
public void testDevelopmentPlatformInfo_withFlutter_returnsPlatformAndNoVersion() {
45+
Context context = getContext(); // has asset in DevelopmentPlatformProvider.FLUTTER_ASSETS_PATH
46+
47+
DevelopmentPlatformProvider provider = new DevelopmentPlatformProvider(context);
48+
49+
assertEquals(FLUTTER_PLATFORM, provider.getDevelopmentPlatform());
50+
assertNull(provider.getDevelopmentPlatformVersion());
51+
assertFalse(DevelopmentPlatformProvider.isUnity(context));
52+
}
53+
4154
public void testDevelopmentPlatformInfo_unknownPlatform_returnsNull() throws Exception {
4255
Context context = createMockContext(/*withUnityResource=*/ false);
4356

57+
assertFalse(DevelopmentPlatformProvider.isUnity(context));
58+
4459
DevelopmentPlatformProvider provider = new DevelopmentPlatformProvider(context);
4560

4661
assertNull(provider.getDevelopmentPlatform());

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.google.firebase.FirebaseApp;
3535
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponent;
3636
import com.google.firebase.crashlytics.internal.CrashlyticsTestCase;
37+
import com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider;
3738
import com.google.firebase.crashlytics.internal.NativeSessionFileProvider;
3839
import com.google.firebase.crashlytics.internal.analytics.AnalyticsEventLogger;
3940
import com.google.firebase.crashlytics.internal.log.LogFileManager;
@@ -142,8 +143,7 @@ public CrashlyticsController build() {
142143
"packageName",
143144
"versionCode",
144145
"versionName",
145-
/*developmentPlatform=*/ null,
146-
/*developmentPlatformVersion=*/ null);
146+
mock(DevelopmentPlatformProvider.class));
147147

148148
final CrashlyticsController controller =
149149
new CrashlyticsController(

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponent;
3131
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponentDeferredProxy;
3232
import com.google.firebase.crashlytics.internal.CrashlyticsTestCase;
33+
import com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider;
3334
import com.google.firebase.crashlytics.internal.analytics.UnavailableAnalyticsEventLogger;
3435
import com.google.firebase.crashlytics.internal.breadcrumbs.DisabledBreadcrumbSource;
3536
import com.google.firebase.crashlytics.internal.persistence.FileStore;
@@ -263,8 +264,7 @@ private void setupAppData(String buildId) {
263264
"packageName",
264265
"versionCode",
265266
"versionName",
266-
"Unity",
267-
"1.0");
267+
mock(DevelopmentPlatformProvider.class));
268268
}
269269

270270
private void setupResource(Integer resId, String type, String name, String value) {

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponent;
3333
import com.google.firebase.crashlytics.internal.CrashlyticsNativeComponentDeferredProxy;
3434
import com.google.firebase.crashlytics.internal.CrashlyticsTestCase;
35+
import com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider;
3536
import com.google.firebase.crashlytics.internal.analytics.UnavailableAnalyticsEventLogger;
3637
import com.google.firebase.crashlytics.internal.breadcrumbs.BreadcrumbHandler;
3738
import com.google.firebase.crashlytics.internal.breadcrumbs.BreadcrumbSource;
@@ -343,8 +344,7 @@ private Task<CrashlyticsCore> startCoreAsync(CrashlyticsCore crashlyticsCore) {
343344
"packageName",
344345
"versionCode",
345346
"versionName",
346-
"Unity",
347-
"1.0");
347+
mock(DevelopmentPlatformProvider.class));
348348

349349
crashlyticsCore.onPreExecute(appData, mockSettingsController);
350350

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
package com.google.firebase.crashlytics.internal.common;
1616

17-
import static com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider.UNITY_PLATFORM;
1817
import static com.google.firebase.crashlytics.internal.common.CrashlyticsReportDataCapture.GENERATOR;
1918
import static com.google.firebase.crashlytics.internal.common.CrashlyticsReportDataCapture.GENERATOR_TYPE;
2019
import static org.junit.Assert.assertArrayEquals;
@@ -51,6 +50,7 @@
5150

5251
@RunWith(AndroidJUnit4.class)
5352
public class CrashlyticsReportDataCaptureTest {
53+
private static final String UNITY_PLATFORM = "Unity";
5454

5555
private Context context = getContext();
5656
private IdManager idManager;

firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/DevelopmentPlatformProvider.java

Lines changed: 68 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,28 +18,22 @@
1818

1919
import android.content.Context;
2020
import androidx.annotation.Nullable;
21+
import java.io.IOException;
2122

2223
/** Provider for the development platform info. */
2324
public class DevelopmentPlatformProvider {
24-
public static final String UNITY_PLATFORM = "Unity";
25+
private static final String UNITY_PLATFORM = "Unity";
26+
private static final String FLUTTER_PLATFORM = "Flutter";
2527

2628
private static final String UNITY_VERSION_FIELD = "com.google.firebase.crashlytics.unity_version";
29+
private static final String FLUTTER_ASSETS_PATH = "flutter_assets";
2730

28-
@Nullable private final String developmentPlatform;
29-
@Nullable private final String developmentPlatformVersion;
31+
private final Context context;
32+
@Nullable private DevelopmentPlatform developmentPlatform;
3033

3134
public DevelopmentPlatformProvider(Context context) {
32-
// Unity
33-
int unityEditorId = getResourcesIdentifier(context, UNITY_VERSION_FIELD, "string");
34-
if (unityEditorId != 0) {
35-
developmentPlatform = UNITY_PLATFORM;
36-
developmentPlatformVersion = context.getResources().getString(unityEditorId);
37-
Logger.getLogger().v("Unity Editor version is: " + developmentPlatformVersion);
38-
return;
39-
}
40-
35+
this.context = context;
4136
developmentPlatform = null;
42-
developmentPlatformVersion = null;
4337
}
4438

4539
/**
@@ -49,7 +43,7 @@ public DevelopmentPlatformProvider(Context context) {
4943
*/
5044
@Nullable
5145
public String getDevelopmentPlatform() {
52-
return developmentPlatform;
46+
return initDevelopmentPlatform().developmentPlatform;
5347
}
5448

5549
/**
@@ -59,6 +53,65 @@ public String getDevelopmentPlatform() {
5953
*/
6054
@Nullable
6155
public String getDevelopmentPlatformVersion() {
62-
return developmentPlatformVersion;
56+
return initDevelopmentPlatform().developmentPlatformVersion;
57+
}
58+
59+
/**
60+
* Returns if the development platform is Unity, without initializing the rest of the
61+
* DevelopmentPlatform object.
62+
*
63+
* <p>This is useful for the NDK to avoid an expensive file operation during start up.
64+
*/
65+
public static boolean isUnity(Context context) {
66+
return getResourcesIdentifier(context, UNITY_VERSION_FIELD, "string") != 0;
67+
}
68+
69+
/** Quickly and safely check if the given asset path exists. */
70+
private boolean assetPathExists(String path) {
71+
try {
72+
if (context.getAssets() == null) {
73+
return false;
74+
}
75+
String[] list = context.getAssets().list(path);
76+
return list != null && list.length > 0;
77+
} catch (IOException ex) {
78+
return false;
79+
}
80+
}
81+
82+
private DevelopmentPlatform initDevelopmentPlatform() {
83+
if (developmentPlatform == null) {
84+
developmentPlatform = new DevelopmentPlatform();
85+
}
86+
return developmentPlatform;
87+
}
88+
89+
private class DevelopmentPlatform {
90+
@Nullable private final String developmentPlatform;
91+
@Nullable private final String developmentPlatformVersion;
92+
93+
private DevelopmentPlatform() {
94+
// Unity
95+
int unityEditorId = getResourcesIdentifier(context, UNITY_VERSION_FIELD, "string");
96+
if (unityEditorId != 0) {
97+
developmentPlatform = UNITY_PLATFORM;
98+
developmentPlatformVersion = context.getResources().getString(unityEditorId);
99+
Logger.getLogger().v("Unity Editor version is: " + developmentPlatformVersion);
100+
return;
101+
}
102+
103+
// Flutter
104+
if (assetPathExists(FLUTTER_ASSETS_PATH)) {
105+
developmentPlatform = FLUTTER_PLATFORM;
106+
// TODO: Get the version when available - https://github.com/flutter/flutter/issues/92681
107+
developmentPlatformVersion = null;
108+
Logger.getLogger().v("Development platform is: " + FLUTTER_PLATFORM);
109+
return;
110+
}
111+
112+
// Unknown/no development platform
113+
developmentPlatform = null;
114+
developmentPlatformVersion = null;
115+
}
63116
}
64117
}

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

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
import android.content.Context;
1818
import android.content.pm.PackageInfo;
1919
import android.content.pm.PackageManager;
20-
import androidx.annotation.Nullable;
2120
import com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider;
2221

2322
/** Carries static information about the app. */
@@ -31,8 +30,7 @@ public class AppData {
3130
public final String versionCode;
3231
public final String versionName;
3332

34-
@Nullable public final String developmentPlatform;
35-
@Nullable public final String developmentPlatformVersion;
33+
public final DevelopmentPlatformProvider developmentPlatformProvider;
3634

3735
public static AppData create(
3836
Context context,
@@ -56,8 +54,7 @@ public static AppData create(
5654
packageName,
5755
versionCode,
5856
versionName,
59-
developmentPlatformProvider.getDevelopmentPlatform(),
60-
developmentPlatformProvider.getDevelopmentPlatformVersion());
57+
developmentPlatformProvider);
6158
}
6259

6360
public AppData(
@@ -67,15 +64,13 @@ public AppData(
6764
String packageName,
6865
String versionCode,
6966
String versionName,
70-
@Nullable String developmentPlatform,
71-
@Nullable String developmentPlatformVersion) {
67+
DevelopmentPlatformProvider developmentPlatformProvider) {
7268
this.googleAppId = googleAppId;
7369
this.buildId = buildId;
7470
this.installerPackageName = installerPackageName;
7571
this.packageName = packageName;
7672
this.versionCode = versionCode;
7773
this.versionName = versionName;
78-
this.developmentPlatform = developmentPlatform;
79-
this.developmentPlatformVersion = developmentPlatformVersion;
74+
this.developmentPlatformProvider = developmentPlatformProvider;
8075
}
8176
}

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -696,8 +696,7 @@ private static StaticSessionData.AppData createAppData(IdManager idManager, AppD
696696
appData.versionName,
697697
idManager.getCrashlyticsInstallId(),
698698
DeliveryMechanism.determineFrom(appData.installerPackageName).getId(),
699-
appData.developmentPlatform,
700-
appData.developmentPlatformVersion);
699+
appData.developmentPlatformProvider);
701700
}
702701

703702
private static StaticSessionData.OsData createOsData(Context context) {

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,8 +153,9 @@ private CrashlyticsReport.Session.Application populateSessionApplicationData() {
153153
.setVersion(appData.versionCode)
154154
.setDisplayVersion(appData.versionName)
155155
.setInstallationUuid(idManager.getCrashlyticsInstallId())
156-
.setDevelopmentPlatform(appData.developmentPlatform)
157-
.setDevelopmentPlatformVersion(appData.developmentPlatformVersion);
156+
.setDevelopmentPlatform(appData.developmentPlatformProvider.getDevelopmentPlatform())
157+
.setDevelopmentPlatformVersion(
158+
appData.developmentPlatformProvider.getDevelopmentPlatformVersion());
158159
return builder.build();
159160
}
160161

firebase-crashlytics/src/main/java/com/google/firebase/crashlytics/internal/model/StaticSessionData.java

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414

1515
package com.google.firebase.crashlytics.internal.model;
1616

17-
import androidx.annotation.Nullable;
1817
import com.google.auto.value.AutoValue;
18+
import com.google.firebase.crashlytics.internal.DevelopmentPlatformProvider;
1919

2020
@AutoValue
2121
public abstract class StaticSessionData {
@@ -44,28 +44,22 @@ public abstract static class AppData {
4444

4545
public abstract int deliveryMechanism();
4646

47-
@Nullable
48-
public abstract String developmentPlatform();
49-
50-
@Nullable
51-
public abstract String developmentPlatformVersion();
47+
public abstract DevelopmentPlatformProvider developmentPlatformProvider();
5248

5349
public static AppData create(
5450
String appIdentifier,
5551
String versionCode,
5652
String versionName,
5753
String installUuid,
5854
int deliveryMechanism,
59-
@Nullable String developmentPlatform,
60-
@Nullable String developmentPlatformVersion) {
55+
DevelopmentPlatformProvider developmentPlatformProvider) {
6156
return new AutoValue_StaticSessionData_AppData(
6257
appIdentifier,
6358
versionCode,
6459
versionName,
6560
installUuid,
6661
deliveryMechanism,
67-
developmentPlatform,
68-
developmentPlatformVersion);
62+
developmentPlatformProvider);
6963
}
7064
}
7165

0 commit comments

Comments
 (0)