Skip to content

FcmLifecycleCallbacks.onActivityCreated crash in android 7 #3090

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

Closed
EaseTheWorld opened this issue Oct 31, 2021 · 20 comments
Closed

FcmLifecycleCallbacks.onActivityCreated crash in android 7 #3090

EaseTheWorld opened this issue Oct 31, 2021 · 20 comments
Assignees

Comments

@EaseTheWorld
Copy link

EaseTheWorld commented Oct 31, 2021

[READ] Step 1: Are you in the right place?

Yes

[REQUIRED] Step 2: Describe your environment

  • Android Studio version: Arctic Fox 2020.3.1 Patch 3
  • Firebase Component: firebase-messaging
  • Component version: 22.0.0

[REQUIRED] Step 3: Describe the problem

I updated firebase-messaging from 20.1.7 to 22.0.0 then
new crash has appeared from android 5,6,7 devices.
(no crash in android 8 and above)

All stacktraces are related to Bundle & BaseBundle.

Caused by java.lang.IllegalArgumentException: Duplicate key in ArrayMap: 
       at android.util.ArrayMap.validate(ArrayMap.java:567)
       at android.os.Parcel.readArrayMapInternal(Parcel.java:2621)
       at android.os.BaseBundle.unparcel(BaseBundle.java:221)
       at android.os.Bundle.getBundle(Bundle.java:763)
       at com.google.firebase.messaging.FcmLifecycleCallbacks.onActivityCreated(FcmLifecycleCallbacks.java:4)
       at android.app.Application.dispatchActivityCreated(Application.java:219)
       at android.app.Activity.onCreate(Activity.java:1039)
Caused by java.lang.NullPointerException: Attempt to invoke virtual method 'int android.os.Parcel.dataSize()' on a null object reference
       at android.os.BaseBundle.<init>(BaseBundle.java:164)
       at android.os.Bundle.<init>(Bundle.java:106)
       at android.content.Intent.getExtras(Intent.java:7186)
       at com.google.firebase.messaging.FcmLifecycleCallbacks.onActivityCreated(FcmLifecycleCallbacks.java:3)
       at android.app.Application.dispatchActivityCreated(Application.java:221)
       at android.app.Activity.onCreate(Activity.java:1046)
Caused by java.lang.IllegalArgumentException
       at android.os.Parcel.nativeAppendFrom(Parcel.java)
       at android.os.Parcel.appendFrom(Parcel.java:466)
       at android.os.BaseBundle.<init>(BaseBundle.java:164)
       at android.os.Bundle.<init>(Bundle.java:106)
       at android.content.Intent.getExtras(Intent.java:7056)
       at com.google.firebase.messaging.FcmLifecycleCallbacks.onActivityCreated(FcmLifecycleCallbacks.java:3)
       at android.app.Application.dispatchActivityCreated(Application.java:221)
       at android.app.Activity.onCreate(Activity.java:1042)
Caused by java.lang.RuntimeException: Parcel android.os.Parcel@9c96faf: Unmarshalling unknown type code 7274595 at offset 92
       at android.os.Parcel.readValue(Parcel.java:2453)
       at android.os.Parcel.readArrayMapInternal(Parcel.java:2727)
       at android.os.BaseBundle.unparcel(BaseBundle.java:269)
       at android.os.Bundle.getBundle(Bundle.java:817)
       at com.google.firebase.messaging.FcmLifecycleCallbacks.onActivityCreated(FcmLifecycleCallbacks.java:4)
       at android.app.Application.dispatchActivityCreated(Application.java:221)
       at android.app.Activity.onCreate(Activity.java:1042)

I suspect Bundle can be corrupted with some race condition in android 7.
Moreover, BaseBundle copy constructor uses synchronized since android 8.
http://androidxref.com/7.1.1_r6/xref/frameworks/base/core/java/android/os/BaseBundle.java#158
http://androidxref.com/8.0.0_r4/xref/frameworks/base/core/java/android/os/BaseBundle.java#158

I couldn't find similar issue in stackoverflow except Parcel crashes when retrieved from Intent.

Steps to reproduce:

I can't reproduce it. only seen from crashlytics.

Relevant Code:

FcmLifecycleCallbacks.java

@google-oss-bot
Copy link
Contributor

I couldn't figure out how to label this issue, so I've labeled it for a human to triage. Hang tight.

@argzdev
Copy link
Contributor

argzdev commented Nov 1, 2021

Hi @EaseTheWorld, thanks for reporting with a detailed analysis. I'm unable to reproduce the issue as well, and I think you're right, this does look like a race condition. With that said, given that this is a difficult issue to reproduce and debug, does the issue rarely occur?

Also if you're able to reproduce it with an MCVE, that'll be helpful.

@EaseTheWorld
Copy link
Author

The probability is 200~300 crash per day in 90,000 user(android5+6+7).
To find the reproduce step and root cause, I think we need to ask the google guy why they updated the BaseBundle class in android 8...

@gsakakihara
Copy link
Contributor

Unfortunately, without being able to reproduce the issue, it will be more difficult to fix it. Can you tell when this is happening? Is it occurring when the app is being opened from clicking on a notification or is it being opened in some other way? Do you start any of your Activities with unusual Intent extras, something like a large amount of data, custom Parcelables, or anything else that could cause differences in how the Intent is processed?

Also, do you see anything in the distribution of devices that the crash occurs on? Does it happen more on certain devices or manufacturers compared to your app installation numbers?

@EaseTheWorld
Copy link
Author

EaseTheWorld commented Nov 3, 2021 via email

@gsakakihara
Copy link
Contributor

Very little Intent data, but do you pass any to that Activity? I'm trying to narrow down if there's anything special with the Intent's extras that might help me to reproduce the issue. Though if this is a race condition, it's likely that any Intent might be able to trigger this under the right circumstances.

@EaseTheWorld
Copy link
Author

EaseTheWorld commented Nov 4, 2021 via email

@EaseTheWorld
Copy link
Author

EaseTheWorld commented Nov 5, 2021

When I set breakpoint at every synchronized block in BaseBundle.java,
I can see many non-main threads access to Bundle.

One of them is com.google.android.gms.measurement.internal.
스크린샷 2021-11-05 오후 4 31 51

or another one is from facebook.appevents
스크린샷 2021-11-05 오후 4 29 55

this is from firebasecrashlytics.
스크린샷 2021-11-05 오후 4 29 01

I don't know any of them is related...
but now I know BaseBundle can be accessed from many threads.

@gsakakihara
Copy link
Contributor

Probably related to https://cs.android.com/android/_/android/platform/frameworks/base/+/d8e877d27d8e5a87446b9e1030325edad268d9e3, where there can be an issue if multiple threads try to read a Bundle, unparceling it, though I'm not how much that helps in fixing the issue. We may need to add something to try to work around the crash instead since it seems like it could be a platform bug that has already been fixed in later versions.

@EaseTheWorld
Copy link
Author

EaseTheWorld commented Nov 9, 2021 via email

@gsakakihara
Copy link
Contributor

It doesn't seem like there's anything that can be done to completely eliminate the risk as long as something is trying to access the Bundle on another thread, but we may be able to try to reduce the chance that FCM reads the Bundle at the same time. I'm considering posting it back to the main thread so that it will run after onCreate() has finished, but I will have to investigate whether that could cause any other issues.

@EaseTheWorld
Copy link
Author

EaseTheWorld commented Nov 11, 2021 via email

@Zozulinsky
Copy link

Zozulinsky commented Nov 23, 2021

Oh, I have a similar problem with android devices below 7.

Caused by: java.lang.IllegalArgumentException
at android.os.Parcel.nativeAppendFrom(Native Method)
at android.os.Parcel.appendFrom(Parcel.java:449)
at android.os.BaseBundle.(BaseBundle.java:126)
at android.os.Bundle.(Bundle.java:102)
at android.content.Intent.getExtras(Intent.java:5946)
at com.google.firebase.messaging.FcmLifecycleCallbacks.onActivityCreated(com.google.firebase:firebase-messaging@@22.0.0:3)
at android.app.Application.dispatchActivityCreated(Application.java:195)
at android.app.Activity.onCreate(Activity.java:931)
at androidx.core.app.ComponentActivity.onCreate(ComponentActivity.java:85)
at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:323)
at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:273)
at drug.vokrug.activity.BaseFragmentActivity.onCreate(BaseFragmentActivity.kt:71)
at drug.vokrug.activity.material.main.MaterialMainActivity.onCreate(MaterialMainActivity.java:314)
at android.app.Activity.performCreate(Activity.java:6361)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1113)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2532)

@ILikeYourHat
Copy link

ILikeYourHat commented Dec 22, 2021

Same problem for Android 7.X:

java.lang.NullPointerException: Attempt to invoke virtual method 'int android.os.Parcel.dataSize()' on a null object reference
at android.os.BaseBundle.(BaseBundle.java:164)
at android.os.Bundle.(Bundle.java:106)
at android.content.Intent.getExtras(Intent.java:6641)
at com.google.firebase.messaging.FcmLifecycleCallbacks.onActivityCreated(com.google.firebase:firebase-messaging@@23.0.0:3)
at android.app.Application.dispatchActivityCreated(Application.java:197)
at android.app.Activity.onCreate(Activity.java:1008)
at androidx.core.app.ComponentActivity.onCreate(ComponentActivity.java:85)
at androidx.activity.ComponentActivity.onCreate(ComponentActivity.java:314)
at androidx.fragment.app.FragmentActivity.onCreate(FragmentActivity.java:273)
...

If nothing can be done, maybe just add a try-catch block? You can add if-clause for OS version if you want.

gsakakihara added a commit that referenced this issue Feb 10, 2022
…rlier.

#3090

* Switched to log notification open after onActivityCreated() has completed on Android 7.0 and earlier since unparceling a Bundle is not thread safe on those versions. This may help to avoid a race condition with anything else that may be trying to access the Intent extra Bundle from another thread started in onActivityCreated()/onCreate().
gsakakihara added a commit that referenced this issue Feb 14, 2022
…rlier. (#3432)

#3090

* Switched to log notification open after onActivityCreated() has completed on Android 7.0 and earlier since unparceling a Bundle is not thread safe on those versions. This may help to avoid a race condition with anything else that may be trying to access the Intent extra Bundle from another thread started in onActivityCreated()/onCreate().
qdpham13 pushed a commit that referenced this issue Feb 15, 2022
…rlier. (#3432)

#3090

* Switched to log notification open after onActivityCreated() has completed on Android 7.0 and earlier since unparceling a Bundle is not thread safe on those versions. This may help to avoid a race condition with anything else that may be trying to access the Intent extra Bundle from another thread started in onActivityCreated()/onCreate().
jeremyjiang-dev pushed a commit that referenced this issue Mar 9, 2022
…rlier. (#3432)

#3090

* Switched to log notification open after onActivityCreated() has completed on Android 7.0 and earlier since unparceling a Bundle is not thread safe on those versions. This may help to avoid a race condition with anything else that may be trying to access the Intent extra Bundle from another thread started in onActivityCreated()/onCreate().
@hero0812
Copy link

Well..This problem still occurs in Android 7.1.1

@gsakakihara
Copy link
Contributor

The workaround to move the logging after onActivityCreated() should be included in the latest version of the SDK.

@hero0812
Copy link

Even though update to the latest Bom version 29.2.1 , the problem still exists in Android 7.1.1 .
As the code of FcmLifecycleCallbacks.java shows , it only works when VERSION.SDK_INT <= 24 , but not in 25.
public void onActivityCreated(Activity createdActivity, Bundle instanceState) {
Intent startingIntent = createdActivity.getIntent();
if (startingIntent != null && this.seenIntents.add(startingIntent)) {
if (VERSION.SDK_INT <= 24) {
(new Handler(Looper.getMainLooper())).post(() -> {
this.logNotificationOpen(startingIntent);
});
} else {
this.logNotificationOpen(startingIntent);
}

}

}

@hero0812
Copy link

Even though update to the latest Bom version 29.2.1 , the problem still exists in Android 7.1.1 .

@sightsynopsis
Copy link

I am getting the same error on API level 29, I am not sure about the statement that it is thread safe after API level 24.

@noproxy
Copy link

noproxy commented Apr 1, 2022

It's seem that the fix has not been released. Any plan to release a new version for firebase-messaging? @gsakakihara

@firebase firebase locked and limited conversation to collaborators Apr 17, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

9 participants