Skip to content

RUMM-1580: Fix SDK initialization crash on KitKat for a minified build due to DexVerifier rejecting opcode#690

Merged
0xnm merged 2 commits into
masterfrom
nogorodnikov/rumm-1580/fix-sdk-initialization-crash-on-kitkat
Sep 2, 2021
Merged

RUMM-1580: Fix SDK initialization crash on KitKat for a minified build due to DexVerifier rejecting opcode#690
0xnm merged 2 commits into
masterfrom
nogorodnikov/rumm-1580/fix-sdk-initialization-crash-on-kitkat

Conversation

@0xnm

@0xnm 0xnm commented Aug 31, 2021

Copy link
Copy Markdown
Member

What does this PR do?

Fixes #678. Crash happens only on KitKat with minified build due to DexVerfier rejecting bytecode of the class ActivityViewTrackingStrategy, specifically bytecode of this line

Error says:

I/dalvikvm: Could not find method android.app.Application$ActivityLifecycleCallbacks.onActivityPostResumed, referenced from method com.datadog.android.rum.tracking.ActivityViewTrackingStrategy.onActivityPostResumed
W/dalvikvm: VFY: unable to resolve virtual method 257: Landroid/app/Application$ActivityLifecycleCallbacks;.onActivityPostResumed (Landroid/app/Activity;)V
W/dalvikvm: VFY:  rejecting opcode 0x6f at 0x0005
W/dalvikvm: VFY:  rejected Lcom/datadog/android/rum/tracking/ActivityViewTrackingStrategy;.onActivityPostResumed (Landroid/app/Activity;)V
W/dalvikvm: Verifier rejected class Lcom/datadog/android/rum/tracking/ActivityViewTrackingStrategy;

Opcode 0x6f corresponds to the super invocation. There is nothing special about this opcode, I can see other instances of this opcode being successfully replaced instead of being rejected. And this error happens only on KitKat (hence Dalvik), it doesn't repro with newer APIs (ART).

Not sure why it happens, probably there is something special about backporting default (onActivityPostResumed is a default method) methods to the pre-Lollipop APIs, but the easiest fix is just to remove super call and it is safe to do with current inheritance hierarchy because default implementation is just empty.

Things like using RequiresApi, TargetApi, wrapping in build version check condition didn't help. Adding ProGuard instructions also didn't help: APK explorer shows that the necessary class and method are there, but app still crashes.

Review checklist (to be filled by reviewers)

  • Feature or bugfix MUST have appropriate tests (unit, integration, e2e)
  • Make sure you discussed the feature or bugfix with the maintaining team in an Issue
  • Make sure each commit and the PR mention the Issue number (cf the CONTRIBUTING doc)

@0xnm
0xnm requested a review from a team as a code owner August 31, 2021 07:52

override fun onActivityPostResumed(activity: Activity) {
super.onActivityPostResumed(activity)
// this method doesn't call super, because having super call creates a crash

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't that break the behavior on recent version of the OS ? Instead maybe we could have an

if (Version > KitKat) {
   super.onActivityPostResumed(activity)
   // …
}

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it won't break, since onActivityPostResumed in super is empty. Version check doesn't help as I've stated in the PR description.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still concerned as the super implementation might not be empty in future versions of Android. I don't see any simple way to mitigate this, except maybe creating an ActivityViewTrackingStrategyKitKat class which will be 99.99% the same. Let's keep your fix for now, and keep this in mind for future Android versions

@0xnm 0xnm Sep 2, 2021

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, forward compatibility can be a concern. I'm not sure if ActivityViewTrackingStrategyKitKat would work though, because it means that both ActivityViewTrackingStrategyKitKat and ActivityViewTrackingStrategyLollipop will be referenced from the same class in the import statement, and it means DexVerifier will still go through the class with super call during class load process.

Alternatively we can just schedule dropping KitKat support in the future.

@codecov-commenter

codecov-commenter commented Aug 31, 2021

Copy link
Copy Markdown

Codecov Report

Merging #690 (1fa13e8) into master (e64121f) will decrease coverage by 0.29%.
The diff coverage is n/a.

❗ Current head 1fa13e8 differs from pull request most recent head 87365c1. Consider uploading reports for the commit 87365c1 to get more accurate results

@@             Coverage Diff              @@
##             master     #690      +/-   ##
============================================
- Coverage     88.63%   88.34%   -0.29%     
+ Complexity     1709     1650      -59     
============================================
  Files           189      184       -5     
  Lines          5645     5411     -234     
  Branches        695      672      -23     
============================================
- Hits           5003     4780     -223     
+ Misses          407      400       -7     
+ Partials        235      231       -4     
Impacted Files Coverage Δ
...droid/rum/tracking/ActivityViewTrackingStrategy.kt 88.46% <ø> (-0.22%) ⬇️
.../instrumentation/gestures/WindowCallbackWrapper.kt 76.19% <0.00%> (-6.57%) ⬇️
...m/internal/domain/scope/ExternalResourceTimings.kt 73.53% <0.00%> (-5.88%) ⬇️
...instrumentation/gestures/DatadogGesturesTracker.kt 50.00% <0.00%> (-4.55%) ⬇️
...internal/instrumentation/gestures/GesturesUtils.kt 85.71% <0.00%> (-4.29%) ⬇️
.../datadog/android/core/internal/net/UploadStatus.kt 93.33% <0.00%> (-3.44%) ⬇️
...n/kotlin/com/datadog/android/DatadogInterceptor.kt 69.12% <0.00%> (-2.94%) ⬇️
.../main/kotlin/com/datadog/android/rum/RumMonitor.kt 77.78% <0.00%> (-2.87%) ⬇️
...acing/internal/domain/event/SpanEventSerializer.kt 90.48% <0.00%> (-2.38%) ⬇️
...g/internal/domain/event/DdSpanToSpanEventMapper.kt 97.96% <0.00%> (-2.04%) ⬇️
... and 37 more

@0xnm
0xnm requested a review from xgouchet September 2, 2021 08:12

override fun onActivityPostResumed(activity: Activity) {
super.onActivityPostResumed(activity)
// this method doesn't call super, because having super call creates a crash

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still concerned as the super implementation might not be empty in future versions of Android. I don't see any simple way to mitigate this, except maybe creating an ActivityViewTrackingStrategyKitKat class which will be 99.99% the same. Let's keep your fix for now, and keep this in mind for future Android versions

@0xnm
0xnm force-pushed the nogorodnikov/rumm-1580/fix-sdk-initialization-crash-on-kitkat branch from 1fa13e8 to f633bdb Compare September 2, 2021 08:46
@0xnm
0xnm requested a review from a team as a code owner September 2, 2021 08:46
@0xnm
0xnm changed the base branch from release/1.10.0 to master September 2, 2021 08:46
@0xnm
0xnm force-pushed the nogorodnikov/rumm-1580/fix-sdk-initialization-crash-on-kitkat branch from f633bdb to 87365c1 Compare September 2, 2021 08:51
@0xnm
0xnm merged commit 7062882 into master Sep 2, 2021
@0xnm
0xnm deleted the nogorodnikov/rumm-1580/fix-sdk-initialization-crash-on-kitkat branch September 2, 2021 09:06
@xgouchet xgouchet added this to the 1.11.0 milestone Sep 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

KitKat crash when ProGuard is enabled

3 participants