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:
onServiceConnected
will be passed null
as second parameter instead of a valid IBinder
returned by remote Service
?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.