Search code examples
androidservicenullpointerexceptionipcaidl

Android IPC: onServiceConnected called, followed by NullPointerException


Our application connects to IPC Service exposed via AIDL interface. Everything worked fine up until now, but suddenly we observed a NullPointerException being thrown right after invocation of onServiceConnected callback.

We bind to the service in the following way:

boolean isServiceBound = context.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);

Then we ensure that the service was bound successfully and a background thread waits for onServiceConnected callback to be invoked:

private ServiceConnection serviceConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className,
                                   IBinder binder) {
        Log.d(TAG, "converting Binder into IAidlService");

        aidlService = IAidlService.Stub.asInterface(binder);

        serviceConnected(); // this call releases background thread that waits for connection to be established

    }

    public void onServiceDisconnected(ComponentName className) {
        Log.d(TAG, "IAidlService disconnected unexpectedly");

        aidlService = null;
    }
};

Once serviceConnected() is called during invocation of onServiceConnected callback, we assume that the connection was established and aidlService variable was initialized (unless onServiceDisconnected gets invoked afterwards, but it is not the case here).

As I said, this scheme worked fine for some time, but suddenly we encountered NullPointerException being thrown right after onServiceConnected. Logcat output:

01-21 14:06:32.717 22651-22651/com.xxx.xxx D/LocalService: converting Binder into IAidlService
01-21 14:06:32.721 22651-9574/com.xxx.xxx E/AndroidRuntime: FATAL EXCEPTION: IntentService[LocalService]
01-21 14:06:32.721 22651-9574/com.xxx.xxx E/AndroidRuntime: Process: com.xxx.xxx, PID: 22651
01-21 14:06:32.721 22651-9574/com.xxx.xxx E/AndroidRuntime: java.lang.NullPointerException: Attempt to invoke interface method 'void com.yyy.yyy.IAidlService.someMethod(android.os.Bundle)' on a null object reference

As you can see, aidlService is used in background thread after onServiceConnected was invoked on main thread. I'm 99.9% confident that there is no multi-threading issue here and the logic that makes the background thread wait until serviceConnected() is called works fine (and the 4ms delay seen in logcat supports this claim).

We couldn't reproduce this behavior.

So, we know that onServiceConnected was called, but aidlService variable wasn't initialized. I see only one potential cause for this behavior: IBinder object passed to onServiceConnected by the system was null (I'm 100% confident that the object returned in onBind() of an IPC service was valid)

I couldn't find any information regarding this scenario on the web, therefore my questions are:

  1. Have anyone encountered a similar behavior?
  2. Are there any scenarios in which onServiceConnected will be passed null as second parameter instead of a valid IBinder returned by remote Service?

Solution

  • Thanks to @pskink's help I realized that neither onServiceConnected can be called with null IBinder, nor AIDL's Stub.asInterface can return null.

    Bottom line: no need for null checks in onServiceConnected callback.