Saturday, 5 February 2022

Spotify Web Player crashes system WebView due to MediaDrm exception

I am working on an android app that uses the Spotify Web Playback SDK. This works fine for about 99% of the time, but that 1% is where my app will crash due to Spotify. Currently I receive the following stack trace:

2022-02-02 11:20:39.931 13285-13285/app.***.musicplayer E/AndroidRuntime: FATAL EXCEPTION: main
    Process: app.***.musicplayer, PID: 13285
    java.lang.NullPointerException: Attempt to read from field 'byte[] ES.a' on a null object reference
        at GS.b(Unknown Source:2)
        at zS.onKeyStatusChange(Unknown Source:10)
        at android.media.MediaDrm.lambda$createOnKeyStatusChangeListener$1$MediaDrm(MediaDrm.java:809)
        at android.media.-$$Lambda$MediaDrm$_FHBF1q3qSxz22Mhv8jmgjN4xt0.accept(Unknown Source:6)
        at android.media.MediaDrm.lambda$postEventFromNative$4(MediaDrm.java:920)
        at android.media.-$$Lambda$MediaDrm$UPVWCanGo24eu9-1S_t6PvJ1Zno.run(Unknown Source:18)
        at android.os.Handler.handleCallback(Handler.java:938)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:223)
        at android.app.ActivityThread.main(ActivityThread.java:7656)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
2022-02-02 12:23:43.223 26211-26249/? E/Finsky:instant_app_inst: [50634] EnabledStatusSyncService.d(47): Failed updateUserPrefs: Account=Account {name=***@***.app, type=com.google}, EnableInstantApps=true

From what I can figure out, Spotify attempts to use the system WebView's Media DRM for managing Key Sessions. At some point, Spotify attempts to do something which causes the WebView to throw this NullPointerException which in-turn crashes my app.

Is there ANY way I can somehow catch this exception and recover to prevent my app from crashing?

I've been looking at maybe trying to find a third-party WebView, but I'd hate to have to bloat my app because of something like this.

I don't know if this is in-fact the offending code, but it was the only thing in the Spotify SDK that I could find that referenced a keyStatusChangeListener:

t.prototype.destroySessions = function () {
    for (var e = [], t = 0, r = this._keySessions; t < r.length; t++) {
        var n = r[t];
        try {
            var i = n.keySession;
            if (!i) continue;
            n.onMessageListener && i.removeEventListener(s.Event.KEY_SESSION_MESSAGE, n.onMessageListener), n.onKeyStatusChangeListener && i.removeEventListener(s.Event.KEY_SESSION_STATUSES_CHANGE, n.onKeyStatusChangeListener);
            var o = Promise.resolve(i.close()).catch(function (e) {
                E.warn("Failed to close KeySession", e);
            });
            e.push(o), n.keySession = null, n.onMessageListener = null, n.onKeyStatusChangeListener = null, E.info("Closed KeySession");
        } catch (e) {
            E.warn("Failed to close KeySession", e);
        }
    }
    return this._keySessions = [], Promise.all(e);
}

They put a try...catch around it to handle errors, but it's not like they can do anything when the WebView itself has no safety checks:

MediaDrm.java from the Android code base

private Consumer<ListenerArgs> createOnKeyStatusChangeListener(
        OnKeyStatusChangeListener listener) {
    return args -> {
        byte[] sessionId = args.sessionId;
        if (sessionId.length > 0) {
            List<KeyStatus> keyStatusList = args.keyStatusList;
            boolean hasNewUsableKey = args.hasNewUsableKey;

            Log.i(TAG, "Drm key status changed");
            listener.onKeyStatusChange(this, sessionId, keyStatusList, hasNewUsableKey);
        }
    };
}


from Spotify Web Player crashes system WebView due to MediaDrm exception

No comments:

Post a Comment