airbnb / DeepLinkDispatch

A simple, annotation-based library for making deep link handling better on Android
http://nerds.airbnb.com/deeplinkdispatch/
4.38k stars 406 forks source link

Fix crash that could happen with no arg deep Link handler in R8 full mode. #342

Closed rossbacher closed 2 years ago

rossbacher commented 2 years ago

The bytecode in the .dex file for the DeepLinkHander interface looks like this after normal compilation:

###### Class com.airbnb.deeplinkdispatch.handler.DeepLinkHandler (com.airbnb.deeplinkdispatch.handler.DeepLinkHandler)
.class public interface abstract Lcom/airbnb/deeplinkdispatch/handler/DeepLinkHandler;
.super Ljava/lang/Object;
.source "DeepLinkHandler.kt"

# annotations
.annotation system Ldalvik/annotation/Signature;
    value = {
        "<T:",
        "Ljava/lang/Object;",
        ">",
        "Ljava/lang/Object;"
    }
.end annotation

If we run R8 with full mode enabled on this it looks like this:

###### Class com.airbnb.deeplinkdispatch.handler.DeepLinkHandler (com.airbnb.deeplinkdispatch.handler.DeepLinkHandler)
.class public interface abstract Lcom/airbnb/deeplinkdispatch/handler/DeepLinkHandler;
.super Ljava/lang/Object;

The dalvik/annotation/Signature that describes the generic type got removed. (See https://r8.googlesource.com/r8/+/refs/heads/main/compatibility-faq.md).

This is no issue at runtime as this is not needed and the generic type of anything implementing the interface is still kept.

e.g.

###### Class com.airbnb.deeplinkdispatch.sample.handler.SampleKotlinDeepLinkHandler (com.airbnb.deeplinkdispatch.sample.handler.SampleKotlinDeepLinkHandler)
.class public final Lcom/airbnb/deeplinkdispatch/sample/handler/SampleKotlinDeepLinkHandler;
.super Lcom/airbnb/deeplinkdispatch/sample/handler/IntermediateDeepLinkHandler1;

# annotations
.annotation runtime Lcom/airbnb/deeplinkdispatch/sample/WebDeepLink;
.end annotation

.annotation system Ldalvik/annotation/Signature;
    value = {
        "Lcom/airbnb/deeplinkdispatch/sample/handler/IntermediateDeepLinkHandler1<",
        "Lcom/airbnb/deeplinkdispatch/sample/handler/TestKotlinDeepLinkHandlerDeepLinkArgs;",
        ">;"
    }
.end annotation

but the type is fully erased if it is just Any e.g.

###### Class com.airbnb.deeplinkdispatch.sample.handler.SampleNoParamsKotlinDeepLinkHandler (com.airbnb.deeplinkdispatch.sample.handler.SampleNoParamsKotlinDeepLinkHandler)
.class public final Lcom/airbnb/deeplinkdispatch/sample/handler/SampleNoParamsKotlinDeepLinkHandler;
.super Ljava/lang/Object;

# interfaces
.implements Lcom/airbnb/deeplinkdispatch/handler/DeepLinkHandler;

# annotations
.annotation runtime Lcom/airbnb/deeplinkdispatch/sample/WebDeepLink;
.end annotation

.annotation system Ldalvik/annotation/Signature;
    value = {
        "Ljava/lang/Object;",
        "Lcom/airbnb/deeplinkdispatch/handler/DeepLinkHandler;"
    }
.end annotation

Directly keeping the DeepLinkHandler class is fixing this issue. I also added some other code to make this safer and allow error reporting when type determination does not work.