Commit 813d02b
authored
Restore SessionLifecycleService as no-op (#7318)
In context of class not found exception:
#7296
This PR restore a previously deleted service as no operational
The user reported a crash after upgrading to BoM 34.1.0 only for some
Samsung and Oppo devices in Android 14/15.
https://firebase.google.com/support/release-notes/android
There was a major refactor on the way of monitoring application
lifecycle events and determining when/if a new session should be
generated. Which was the main purpose for `SessionLifecycleService`.
[Firebase
Session](https://github.com/firebase/firebase-android-sdk/blob/main/firebase-sessions/README.md)
is used by Crashlytics and Performance internally to measure sessions
[The
refactor](https://github.com/firebase/firebase-android-sdk/pull/7039/files#diff-ea2eb8012abccd4cb5dccba37ec109f0eaa2a82fe6be852b5be7c32ed8de2b45)
proposes the elimination of the service `SessionLifecycleService` in
favor of `SharedSessionRepository`.
This refactor was released on version `releases/m167` ([see commit
here](c9a4a3d)).
See diff of m167 with m166
[here](releases/m166...releases/m167).
Looking for `SessionLifecycleService` usages into the SDK I found just a
leftover reference in an Android Test Manifest. So I can conclude this
is not production code.
Reviewing the original `SessionLifecycleService` class I found out this
service contains a `Binder` implementation
It sounds like the Android system on those specific devices
(Samsung/Oppo on Android 14/15) might be trying to recreate the
`SessionLifecycleService` based on a cached manifest from the previous
version of the host app, even though the service class itself is no
longer present in the new version. This leads to the
`ClassNotFoundException`.
**Conclusions:**
A) Stale Service Connections (I see this as the root cause, I’d like to
review g3 code to confirm there is not source code having references to
the removed service):
If any component within the host app (or the SDK itself) was bound to
`SessionLifecycleService` and the `ServiceConnection` wasn't properly
released or unbound before the app update (or if the system is trying to
restore a previous binding state), the system will attempt to call
`onBind` on the service.
When it tries to instantiate `SessionLifecycleService` to do this and
finds the class missing, it results in the `ClassNotFoundException`.
The git diff showed `android:exported="false"` for the service, which is
good as it means only the SDK could bind to it.
Why this still leads to `ClassNotFoundException` on update:
Even if the new code doesn't try to bind to the removed service anymore,
the Android system might still attempt to re-establish connections that
it considers active or pending from the previous app session, especially
if the app process didn't terminate cleanly or if the system is trying
to restore the app's state after an update. If a `ServiceConnection` was
active when the app was last running the old version, the system might
try to call `onServiceConnected` for that connection, which requires
instantiating the service.
tl; dr:
B) Android /System Caching/State Retention:
The Android Package Manager or Activity Manager on certain devices/OS
versions might retain information about previously registered services.
If the service was started in a "sticky" way, the system will try to
restart it after it's killed or after an app update if it believes the
service should still be running. When it tries to do so with the updated
app that lacks the service class, it crashes.
C) Stale System State: Sometimes, especially with certain OEM
customizations or newer Android versions, the system's package manager
or activity manager might not perfectly clear all references to
components from an old app version immediately upon an update. For users
experiencing this: The most reliable fix is often a clean reinstall.
D) OEM Customizations: Samsung and Oppo devices have their own
modifications to Android, which can sometimes lead to different
behaviors in how app updates and service lifecycles are handled.
**Proposed workaround:**
Future Service Removals (Refined Mitigation Strategy for Bound
Services):
**Version N+1** (Graceful Shutdown & Deprecation): Return the service
class in the codebase, modify its onBind(Intent intent) method to return
null immediately. This signals to any clients attempting to bind that
the service is not available or is shutting down. Crucially, mark the
service as `android:enabled="false"` in the AndroidManifest.xml. **This
explicitly tells the system the service should not be started or
bound**.
**Version N+2** (Full Removal): Now that clients have had a version
where the service gracefully refuses bindings and is disabled, it's
safer to remove the service class and its manifest entry.1 parent 5be1c09 commit 813d02b
File tree
3 files changed
+40
-0
lines changed- firebase-sessions
- src/main
- kotlin/com/google/firebase/sessions
3 files changed
+40
-0
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
4 | 5 | | |
5 | 6 | | |
6 | 7 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
20 | 24 | | |
21 | 25 | | |
22 | 26 | | |
| |||
Lines changed: 35 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
0 commit comments