Files
notes/docs/lectures/mdp/07_remotes.md
T

4.3 KiB

Services - Remote

There is no communication between the two virtual address spaces.

img

When a service is bound to, Android will inspect the intent and find the relevant component to instantiate. If it doesn't exist/isn't running, it will create it. The service object that's created will return a binder object.

Remote Services

Making objects appear as if they exist in the local process - abstraction

  • For communicating across process boundaries
    • using a service belonging to a different application / process
      • Handing off to threads in different processes
    • Likely to be used by multiple processes at once
    • Declare the service in the manifest
    • Must not use implicit intents
      • Doing something without the user's knowledge is problematic
  • Examples like an MP3 player or location tracking do not need a remote service
  • However, when using a service for downloading a file, multiple processes might want to use that and have access to progress. Another example is services that are drivers for hardware
  • Communicating with it
    • Using a messenger - preferred way ☑
    • Defining an interface
      • Registering callbacks
      • Wrapping a system service in an API

Communicating with services

Via Messenger

What is a messenger?

  • An IPC for a service
    • Message-based communication between processes
      • Asynchronous - technically but feels sequential
      • Messages with bundles of data as payload instead of method calls
      • Queues messages into a single thread, which are handled sequentially
        • Allows a service to define a handler
    • 'Has' an IBinder that is shared with the client
      • Passed to the client on service connection
      • Used to send messages to the service
  • Bi-directional communication
    • The client can have a messenger too
      • Provide a reference to the return messenger in our message
      • Sending a binder over a binder

Processes, Messengers and Handlers

img

Inter-process communication

java.io.Serializable

  • Short-term persistence
  • Write object ID and fields via reflection/introspection
  • Brittle - If class/variable names are changed, it breaks
  • It is slow

Parcelable

  • Define a simple wire-protocol for writing primitives
    • Re-create an object by passing salient data (deep copy)
  • Immune to minor definition changes
  • Supported by Android Kernel Driver
  • Much faster
public int x = 5;
public int y = 6;
public String text = "Martin";
// salient data is 5,6 & "Martin"

public void writeToParcel(Parcel out, int flags) {
	out.writeInt(this.x);
	out.writeInt(this.y);
	out.writeString(this.text);
}

public void readFromParcel(Parcel in) {
	this.x = in.readInt();
    this.y = in.readInt();
	this.text = in.readString(); 
}

We can change the class definition, e.g. add a private attribute z that we don't wish to communicate.

We can change the attribute names without anything breaking.

Defining Remote Interfaces

Using the Android Interface Definition Language (AIDL)

  • Specify an interface for the service functionality
  • Generates a proxy object
    • To be used locally as if the remote service was not remote
  • Generates a sub implementation
    • The remote side of the transaction
  • Generates a communication protocol
    • Parcelling and un-parcelling steps - a wire protocol for copying and recreating an object.

Similar to Java interface definitions

  • Label method parameters for efficiency
    • in: transferred to the remote method
    • out: returned to the caller
    • inout: both in and out
    • oneway: asynchronous
  • Permitted types
    • Java primitive type: Lists, Maps, Other AIDL generated interfaces
    • Classes implementing the Parcelable protocol

img

AIDL allows us to define something more complicated than just messages.

We define an interface, the IDE then generates a proxy object and a stub object, and also figures out how those two will communicate

We can then use calls on the proxy, which will delegate those calls into the stub object. We are responsible for implementing the methods in the stub object

Binder abstraction

img

The binder driver can receive messages from multiple processes, so the service has to reason about receiving them