-
Notifications
You must be signed in to change notification settings - Fork 626
Description
Firebase Component: Performance 20.5.2 (BOM 32.8.0)
Steps to reproduce:
- Install an app that uses Firebase Performance on an Android 14 (API 34) Pixel 7.
- Note that this does not reproduce on an API 34 emulator. I haven't tried other physical devices.
- Open the app.
- Observe that there are no app start traces sent.
I noticed this when I was trying to figure out why we aren't getting any app start traces at all. That turned out to be because we were manually initializing Firebase. But even after switching back to the automatic initialization I didn't see any app start traces being sent on my development device, an Android 14 (API 34) Pixel 7. When I installed the app on an API 24 emulator I did see app start traces being sent.
As described in the linked issue, when I ran with a debugger attached (using adb shell am set-debug-app
so I could attach as early as possible) I was seeing that this:
firebase-android-sdk/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java
Lines 568 to 572 in bb0823f
// if no activity has ever been created. | |
if (trace.onCreateTime == null) { | |
trace.isStartedFromBackground = true; | |
} | |
} |
was being executed before onActivityCreated
is able to set onCreateTime
:
firebase-android-sdk/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java
Line 328 in bb0823f
onCreateTime = clock.getTime(); |
Which meant that the ordering assumptions described here:
firebase-android-sdk/firebase-perf/src/main/java/com/google/firebase/perf/metrics/AppStartTrace.java
Lines 552 to 559 in bb0823f
/** | |
* We use StartFromBackgroundRunnable to detect if app is started from background or foreground. | |
* If app is started from background, we do not generate AppStart trace. This runnable is posted | |
* to main UI thread from FirebasePerfEarly. If app is started from background, this runnable will | |
* be executed before any activity's onCreate() method. If app is started from foreground, | |
* activity's onCreate() method is executed before this runnable. | |
*/ | |
public static class StartFromBackgroundRunnable implements Runnable { |
don't hold, Firebase Performance considers every launch to be a background launch and never sends app start traces.
Relevant Code:
Here's a simple demonstration that mimics the ordering assumptions Firebase Performance is making. Copy-paste this provider into a new sample project:
class SampleProvider : ContentProvider() {
private var activityCreated = false
private var mainThreadRunnableRun = false
override fun onCreate(): Boolean {
(context!!.applicationContext as Application).registerActivityLifecycleCallbacks(object :
ActivityLifecycleCallbacks {
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
Log.d(
"FirebasePerf",
"onActivityCreated: mainThreadRunnableRun = $mainThreadRunnableRun"
)
activityCreated = true
}
override fun onActivityStarted(activity: Activity) {}
override fun onActivityResumed(activity: Activity) {}
override fun onActivityPaused(activity: Activity) {}
override fun onActivityStopped(activity: Activity) {}
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) {}
override fun onActivityDestroyed(activity: Activity) {}
})
Handler(Looper.getMainLooper()).post {
Log.d("FirebasePerf", "mainThreadRunnable.run(): activityCreated = $activityCreated")
mainThreadRunnableRun = true
}
return true
}
override fun query(
uri: Uri,
projection: Array<out String>?,
selection: String?,
selectionArgs: Array<out String>?,
sortOrder: String?
): Cursor? {
TODO("Not yet implemented")
}
override fun getType(uri: Uri): String? {
TODO("Not yet implemented")
}
override fun insert(uri: Uri, values: ContentValues?): Uri? {
TODO("Not yet implemented")
}
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int {
TODO("Not yet implemented")
}
override fun update(
uri: Uri,
values: ContentValues?,
selection: String?,
selectionArgs: Array<out String>?
): Int {
TODO("Not yet implemented")
}
}
You'll need to register it in the manifest, install it on an Android 14 (API 34) Pixel 7 and launch the default activity. Then you'll see this in logcat:
15:13:17.036 FirebasePerf D mainThreadRunnable.run(): activityCreated = false
15:13:17.352 FirebasePerf D onActivityCreated: mainThreadRunnableRun = true
which demonstrates that the runnable posted to the main thread executes before the Activity's onCreate, even when the process was started in order to launch an activity.