Search code examples
androidipcandroid-binder

Why does Android Bound Services documentation suggest IBinder can't be used across processes?


From https://developer.android.com/guide/components/bound-services.html:

If your service is private to your own application and runs in the same process as the client (which is common), you should create your interface by extending the Binder class and returning an instance of it from onBind(). The client receives the Binder and can use it to directly access public methods available in either the Binder implementation or the Service.

This is the preferred technique when your service is merely a background worker for your own application. The only reason you would not create your interface this way is because your service is used by other applications or across separate processes.

If you need your interface to work across different processes, you can create an interface for the service with a Messenger...

This seems to imply you wouldn't use Binder for inter-process communication, but IBinder documentation says the opposite:

Base interface for a remotable object, the core part of a lightweight remote procedure call mechanism designed for high performance when performing in-process and cross-process calls. This interface describes the abstract protocol for interacting with a remotable object. Do not implement this interface directly, instead extend from Binder.

The key IBinder API is transact() matched by Binder.onTransact(). These methods allow you to send a call to an IBinder object and receive a call coming in to a Binder object, respectively. This transaction API is synchronous, such that a call to transact() does not return until the target has returned from Binder.onTransact(); this is the expected behavior when calling an object that exists in the local process, and the underlying inter-process communication (IPC) mechanism ensures that these same semantics apply when going across processes.

And Binder documentation:

You can, however, derive directly from Binder to implement your own custom RPC protocol or simply instantiate a raw Binder object directly to use as a token that can be shared across processes.

This class is just a basic IPC primitive...

Many other pages also mention binders in IPC context. What am I misunderstanding?


Solution

  • IBinder provides base interface for remotable object. Binder is an implementation of IBinder that provides the standard support creating a local implementation of remotable an object.

    When both services and clients are running in same process, simply extending Binder and returning instance of the subclass of Binder is enough to communicate with service by binding to it as Binder is an implementation of IBinder that provides the standard support creating a local implementation of remotable an object.

    When service is running in separate process and service's client can be running in any other process, we need to implement IBinder and provide implementation that provides support for remote implementation of remotable object. This can be achieved in one of two ways:

    Using AIDL

    Using AIDL, we can write an interface which we would like to expose. aidl tool then can parse this file and auto-generate Stub and some boiler plate code which is common for all apps for IPC. We can then extend Interface.Stub to provide implementation on service side.

    Clients can include this AIDL file in their projects and code for IPC is auto-generated by aidl tool. Now, client can bind to your service and communicate using the interface declared in the AIDL file.

    Using Messenger

    Messenger is a reference to a Handler, which others can use to send messages to it. This allows for the implementation of message-based communication across processes, by creating a Messenger pointing to a Handler in one process, and handing that Message to another process. This IPC is internally implemented using AIDL itself. Here is the IMessenger.aidl interface which Messenger uses internally to expose contract that clients can use to communicate to host process.

    Summary

    IBinder can be used for both in-process and inter-process communication. When using it for inter-process communication, just expose the interface using AIDL.