Just An Application

May 23, 2012

Adventures In Distributed Garbage Collection: Part Twelve – Unbinding From A Service

1.0 Process: Service Client

The following code in the Service Client calls the Activity’s implementation of the method

    public abstract void unbindService(ServiceConnection conn)

passing the ServiceConnection object that was originally passed to the bindService() method.

        ...

        unbindService(connection);
        connection = null;

        ...

This eventually results in a call to the ContextImpl implementation of unbindService().

1.1 unbindService(…)

Object: ContextImpl

Definition: ContextImpl.java [888-899]

    public void unbindService(ServiceConnection conn)

Argument: ServiceConnection conn

  • The ServiceConnection object identifying the connection(s) to disconnect.

Method

The method begins by obtaining the IServiceConnection object corresponding to the ServiceConnection argument by calling the method forgetServiceDispatcher() on the LoadedApk object (mPackageInfo).

The static method ActivityManagerNative.getDefault() is then called and the method unbindService() is called on the ActivityManagerProxy object returned, with the IServiceConnection object as the argument

This results in a synchronous remote procedure call to the ActivityManagerService implementation of the unbindService() method.

1.2 forgetServiceDispatcher(…)

Object: LoadedApk

Definition: LoadedApk.java [846-894]

    public final IServiceConnection forgetServiceDispatcher(Context context, ServiceConnection c)

Argument: Context context

Argument: ServiceConnection c

Method

The method begins by getting the ServiceConnection to ServiceDispatcher map for the given Context from the mServices map.

If the map is not null then the ServiceConnection argument c is used as the key to obtain the corresponding ServiceDispatcher object.

If there is a corresponding ServiceDispatcher it is removed from the ServiceConnection to ServiceDispatcher map for the given Context.

The doForget() method is then called on the ServiceDispatcher object.

If the BIND_DEBUG_UNBIND flag is set in the mFlags instance variable of the ServiceDispatcher then

  • The method generates a stack-trace for this method call via a RuntimeException object which is then stored in the mUnbindLocation instance variable of the ServiceDispatcher.

  • The ServiceDispatcher is then added to the ServiceConnection to ServiceDispatcher map for the given Context in the mUnboundServices map.

The method then returns the result of calling the method getIServiceConnection() on the ServiceDispatcher.

If a corresponding ServiceDispatcher is not found the method throws an IllegalArgumentException.

2.0 Process: System

Entry Point: Remote procedure call to the ActivityManagerService implementation of the IActivityManager method unbindService().

2.1 unbindService(…)

Caller: Service client via remote procedure call

Actor: ActivityManagerService

Definition: ActivityManagerService.java [9598-9625]

    public boolean unbindService(IServiceConnection connection)

Argument: IServiceConnection connection

  • A proxy for the object implementating the IServiceConnection in the process in which the Service client is running.

Method

The method starts by calling the asBinder() method on the IServiceConnection connection argument.

It uses the resulting IBinder object as a key into the mServiceConnections map to obtain the ConnectionRecord list associated with the given IServiceConnection.

If the list is null the method returns false.

Otherwise it iterates over the ConnectionRecord list calling the method removeConnectionLocked() on each ConnectionRecord.

2.2 removeConnectionLocked(…)

Definition: ActivityManagerService.java [9542-9596]

    void removeConnectionLocked(ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct)

Argument: ConnectionRecord c

  • The ConnectionRecord which represents the connection to remove.

Argument: ProcessRecord skipApp

  • The ProcessRecord to ignore, or null.

Argument: ActivityRecord skipAct

  • The ActivityRecord to ignore, or null.

Overview

The method removes references to the given ConnectionRecord from data structures held by a number of different objects.

If the connection represented by the ConnectionRecord was the only one using the Intent/IBinder binding then it will also remove that binding.

Method

The method begins by calling asBinder() on the IServiceConnection object held by the ConnectionRecord (conn) to convert it to an IBinder.

It then gets the AppBindRecord held by the ConnectionRecord (binding) and the ServiceRecord held by AppBindRecord (service).

The IBinder object obtained at the beginning of the method is then used as a key into the connections map of the ServiceRecord to obtain the associated ConnectionRecord list. If the list is not null then the ConnectionRecord is removed from it. If the list is now empty it is removed from ServiceRecord‘s connections map.

The ConnectionRecord is then removed from the connections list of the AppBindRecord.

If the ActivityRecord held by the ConnectionRecord (activity) is not null and it is not identical to the skipAct argument, then the ConnectionRecord is removed from its connections list.

If the ProcessRecord held by the AppBindRecord (client) is not identical to the skipApp argument then the ConnectionRecord is removed from its connections list.

The IBinder object obtained at the beginning of the method is then used as a key into the mServiceConnections map to obtain the associated ConnectionRecord list. If the list is not null then the ConnectionRecord is removed from it. If the list is now empty it is removed from mServiceConnections map.

If the AppBindRecord connections list is empty, then the AppBindRecord is removed from the apps list of the IntentBindRecord that it holds (intent).

If the Service is running and the IntentBindRecord held by the AppBindRecord no longer has any associated connections then

Finally if the BIND_AUTO_CREATE flag was set when the connection represented by the ConnectionRecord was created the method calls bringDownServiceLocked() passing it the ServiceRecord and with the force argument set to false.

3.0 Process: Service

Entry Point: remote procedure call call to the ApplicationThread implementation of the IApplicationThread method scheduleUnbindService().

3.1 scheduleUnbindService(…)

Caller: ActivityManagerService via remote procedure call.

Actor: ApplicationThread

Definition: ActivityThread.java [512-518]

    public final void scheduleUnbindService(IBinder token, Intent intent)

Argument: IBinder token

  • The proxy for the ServiceRecord which represents the Service the operation should be invoked upon.

Argument: Intent intent

  • The Intent specifying the binding which should be undone.

Method

The method encapsulates its arguments in an instance of the ActivityThread inner class BindServiceData and then sends it to the ActivityThread as the payload of a message.

This message is handled by the method ActivityThread.handleUnbindService().

3.2 handleUnbindService(…)

Actor: ActivityThread

Definition: ActivityThread.java [1990-2014]

    private final void handleUnbindService(BindServiceData data)

Argument: BindServiceData data

  • The encapsulated arguments passed to the ApplicationThread.scheduleUnbindService() method.

Method

The method starts by retrieving the Service Component from the mServices map using the IBinder object data.token as the key.

If there is no corresponding Service Component the method returns.

Otherwise the onUnbind() method is called on the Service Component passing in the Intent data.intent.

If the call to onUnbind() returns true then the method unbindFinished() is called on the ActivityManagerProxy object returned by a call to the static method ActivityManagerNative.getDefault()

This results in a synchronous remote procedure call to the implementation of the method unbindFinished() in the ActivityManagerService.

If the call to onUnbind() returns true then the method serviceDoneExecuting() is called on the ActivityManagerProxy object returned by a call to the static method ActivityManagerNative.getDefault()

This results in an asynchronous remote procedure call to the implementation of the method serviceDoneExecuting() in the ActivityManagerService running in the System process.

4.0 Process: System

Entry Point: Remote procedure call to the ActivityManagerService implementation of the IActivityManager method unbindFinished()

4.1 unbindFinished(…)

Caller: The ActivityThread in the Service process via remote procedure call.

Actor: ActivityManagerService

Definition: ActivityManagerService.java [9687-9725]

    public void unbindFinished(IBinder token, Intent intent, boolean doRebind)

Argument: IBinder token

  • The ServiceRecord which represents the Service which has finished performing the unbind.

Argument: Intent intent

  • The Intent identifying the binding which has been undone.

Argument: boolean doRebind

  • Not used.

Method

The method begins by explicitly checking whether the token argument is actually a ServiceRecord and throws an IllegalArgumentException if it is not.

It then casts the the token argument to a ServiceRecord.

If the resulting ServiceRecord is null the method does nothing more.

If the resulting ServiceRecord is not null then the method wraps the intent argument in an Intent.FilterComparison instance which is then used as a key into the bindings map of the ServiceRecord.

If a corresponding IntentBindRecord exists then

  • If there are now processes associated with the IntentBindRecord the method calls requestServiceBindingLocked(), otherwise it sets the doRebind instance variable of the IntentBindRecord to true.

The method then calls serviceDoneExecutingLocked()


Copyright (c) 2012 By Simon Lewis. All Rights Reserved.

Advertisements

3 Comments »

  1. […] the client has unbound from the Fastnet Service then on the basis of the source code we would expect that in the Service […]

    Pingback by Adventures In Distributed Garbage Collection: Part Thirteen – Post Unbind Service Client State « Just An Application — May 24, 2012 @ 6:09 am

  2. […] the client has unbound from the Fastnet Service then on the basis of the source code we would expect that in the Service […]

    Pingback by Adventures In Distributed Garbage Collection: Part Fourteen – Post Unbind Service State « Just An Application — May 25, 2012 @ 6:01 am

  3. […] the client has unbound from the Fastnet Service then on the basis of the source code and given that it was the only client […]

    Pingback by Adventures In Dustributed Garbage Collection: Part Fifteen – Post Unbind System State « Just An Application — May 28, 2012 @ 8:41 am


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

%d bloggers like this: