Just An Application

May 25, 2012

Adventures In Distributed Garbage Collection: Part Fourteen – Post Unbind Service State

Filed under: Android, Android Internals, Java, Mobile Java, Services — Tags: , , , , — Simon Lewis @ 6:00 am

1.0 Object State

Once the client has unbound from the Fastnet Service then on the basis of the source code we would expect that in the Service process

  • there should no longer be a reference to the FastnetService object from the ActivityThread via its mServices instance variable

  • the FastnetService object should no longer exist

  • the FastnetServiceBinder object should no longer exist

The production of a diagram showing the absence of these things is left as an exercise for the reader.

2.0 Java Heap State

This graph was generated from a Java heap dump of the Service process taken after the client has unbound from the Fastnet Service.

Like its counterpart here it was generated using the FastnetService object [0x40517518] as the root. As before greyed out nodes have been filtered, that is, one or more instance variables have been omitted for clarity.

The existence of this graph is problematic. If the FastnetService object is no longer in the Java heap it should not be possible to generate
a graph with it as the root.

Evidently the graph does exist therefore the assumption that the FastnetService object no longer existing in the Java heap is wrong.

The graph shows two references to the FastnetService object

  • one from the FastnetServiceBinder object [0x40517fc0], and

  • one from the ContextImpl object [0x40517548]

However none of these objects are referenced from any other objects in the graph so this does not explain why the FastnetService object still exists. Either it, or something which references it, is being referenced by something else which is not reachable from any object in the graph.

According to MAT there are no other references to the FastnetService object but there is another reference to the FastnetServiceBinder object.

The reference is identified as Native Stack and it is a GC Root, that is, it is a reference that will ensure the FastnetServiceBinder object will not be garbage collected as long as the GC Root continues to exist.

The Native Stack GC Root is described in the MAT documentation as follows.

In or out parameters in native code, such as user defined JNI code or JVM internal code. This is often the case as many methods have native parts and the objects handled as method parameters become GC roots. For example, parameters used for file/network I/O methods or reflection.

It is not obvious what this reference from the native code might be but presumably it is transient. Possibly the continued existence of the FastnetService object is simply an anomaly that happens to have occurred on this occasion.


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

May 24, 2012

Adventures In Distributed Garbage Collection: Part Thirteen – Post Unbind Service Client State

Filed under: Android, Android Internals, Java, Mobile Java, Services — Tags: , , , , — Simon Lewis @ 6:00 am

1.0 Object State

Once the client has unbound from the Fastnet Service then on the basis of the source code we would expect that in the Service client process

2.0 Java Heap State

This graph was generated from a Java heap dump of the Service client process taken after the client Activity has unbound from the Fastnet Service by calling the unbindService() method.

Like its counterpart here it was generated using the LoadedApk object [0x40513e90] as the root. As before greyed out nodes have been filtered, that is, one or more instance variables have been omitted for clarity.

The graph shows that as expected the LoadedApk object does not reference the ServiceDispatcher object [0x405213b8]

In addition the following objects no longer appear in the graph

  • the ServiceDispatcher object [0x405213b8]

  • the ConnectionInfo object [0x40521b40]

  • the InnerConection object [0x405216b8]

  • the FastnetServiceConnection object [0x405211f0]

This on its own does not prove conclusively that these objects are no longer in the Java heap, just that they are not reachable via the LoadedApk any more.

However, after loading the Java heap dump into MAT none of the objects can be found either which should mean that they have been garbage collected.

Inspecting the contents of the Java heap dump file directly confirms this.


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

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.

May 22, 2012

Adventures In Distributed Garbage Collection: Part Eleven – Post Bind System Process State

Filed under: Android, Android Internals, Java, Mobile Java, Services — Tags: , , , , — Simon Lewis @ 6:00 am

1.0 Object State

As in the Service client and Service cases we can use the source code to derive a diagram which shows the Service related objects that should exist in the System process and their relationships after a client has bound to the Service.

2.0 dumpsys Output

We can use the output from the Android dumpsys command to check whether the ActivityManagerService is doing what we think it is when the client binds to the Fastnet Service.

Below are excerpts from the output of the dumpsys command run immediately after the client has successfully bound to the Fastnet Service.
In some cases the output has been slightly re-formatted for clarity.

2.1 ProcessRecords

2.1.1 Service Client ProcessRecord

    ...

    *APP* UID 10054 ProcessRecord{4067a100 293:xper.service.fastnet.client/10054}
      dir=/data/app/xper.service.fastnet.client-2.apk \
          publicDir=/data/app/xper.service.fastnet.client-2.apk data=/data/data/xper.service.fastnet.client
      packageList=[xper.service.fastnet.client]
      thread=android.app.ApplicationThreadProxy@406c1890 curReceiver=null
      pid=293 starting=false lastPss=0
      lastActivityTime=-1m6s575ms lruWeight=253489 keeping=true hidden=false empty=false
      oom: max=15 hidden=7 curRaw=0 setRaw=0 cur=0 set=0
      curSchedGroup=0 setSchedGroup=0
      setIsForeground=false foregroundServices=false forcingToForeground=null
      persistent=false removed=false
      adjSeq=198 lruSeq=57
      lastRequestedGc=-1m6s576ms lastLowMemory=-1m6s576ms reportLowMemory=false
      activities=[HistoryRecord{407ad2d8 xper.service.fastnet.client/.FastnetClientActivity}]
      connections=[ConnectionRecord{40706ac0 xper.service.fastnet/.FastnetService:@40721f08}]
      conProviders={ContentProviderRecord{4051bc78 com.android.providers.settings.SettingsProvider}=1}
    
    ...

The ProcessRecord [0x4067a100] for the Service client process is present and has a reference to a single ConnectionRecord [0x40706ac0] as expected.

2.1.1 Service ProcessRecord

    ...

    *APP* UID 10053 ProcessRecord{4076e000 301:xper.service.fastnet/10053}
      dir=/data/app/xper.service.fastnet-2.apk \
          publicDir=/data/app/xper.service.fastnet-2.apk data=/data/data/xper.service.fastnet
      packageList=[xper.service.fastnet]
      thread=android.app.ApplicationThreadProxy@4077e2a0 curReceiver=null
      pid=301 starting=false lastPss=0
      lastActivityTime=-59s120ms lruWeight=141059 keeping=true hidden=false empty=true
      oom: max=15 hidden=7 curRaw=0 setRaw=0 cur=0 set=0
      curSchedGroup=0 setSchedGroup=0
      setIsForeground=false foregroundServices=false forcingToForeground=null
      persistent=false removed=false
      adjSeq=198 lruSeq=60
      lastRequestedGc=-59s121ms lastLowMemory=-59s121ms reportLowMemory=false
      services=[ServiceRecord{406f89b8 xper.service.fastnet/.FastnetService}]
    
    ...

The ProcessRecord [0x4076e000] for the Service process is present and has a reference to a single ServiceRecord [0x406f89b8] as expected.

2.2 ActivityRecord

    Activities in Current Activity Manager State:
      * TaskRecord{4070aa90 #3 A xper.service.fastnet.client}
        clearOnBackground=false numActivities=1 rootWasReset=true
        affinity=xper.service.fastnet.client
        intent={act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] \
            flg=0x10200000 cmp=xper.service.fastnet.client/.FastnetClientActivity bnds=[83,316][157,395]}
        realActivity=xper.service.fastnet.client/.FastnetClientActivity
        lastActiveTime=253499 (inactive for 66s)
        * Hist #1: HistoryRecord{407ad2d8 xper.service.fastnet.client/.FastnetClientActivity}
            packageName=xper.service.fastnet.client processName=xper.service.fastnet.client
            launchedFromUid=10001 app=ProcessRecord{4067a100 293:xper.service.fastnet.client/10054}
            Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] \
                flg=0x10200000 cmp=xper.service.fastnet.client/.FastnetClientActivity bnds=[83,316][157,395] }
            frontOfTask=true task=TaskRecord{4070aa90 #3 A xper.service.fastnet.client}
            taskAffinity=xper.service.fastnet.client
            realActivity=xper.service.fastnet.client/.FastnetClientActivity
            base=/data/app/xper.service.fastnet.client-2.apk/data/app/xper.service.fastnet.client-2.apk \
                data=/data/data/xper.service.fastnet.client
            labelRes=0x7f040001 icon=0x7f020000 theme=0x0
            stateNotNeeded=false componentSpecified=true isHomeActivity=false
            configuration={ scale=1.0 imsi=310/260 loc=en_US touch=3 keys=2/1/2 nav=3/1 orien=1 layout=18 uiMode=17 seq=4}
            launchFailed=false haveState=false icicle=null
            state=RESUMED stopped=false delayedResume=false finishing=false
            keysPaused=false inHistory=true launchMode=0
            fullscreen=true visible=true frozenBeforeDestroy=false thumbnailNeeded=false idle=true
            waitingVisible=false nowVisible=true
            connections=[ConnectionRecord{40706ac0 xper.service.fastnet/.FastnetService:@40721f08}]
		
    ...

The ActivityRecord [0x4070aa90] representing the Activity running in the Service client process has a reference to a ConnectionRecord
[0x40706ac0] as expected.

Note

When printed an ActivityRecord identifies itself as a HistoryRecord for reasons best known to itself.

2.3 ServiceRecord

    ...

      * ServiceRecord{406f89b8 xper.service.fastnet/.FastnetService}
        intent={act=xper.service.fastnet.ACTION_FASTNET}
        packageName=xper.service.fastnet
        processName=xper.service.fastnet
        baseDir=/data/app/xper.service.fastnet-2.apk
    resDir=/data/app/xper.service.fastnet-2.apk
        dataDir=/data/data/xper.service.fastnet
        app=ProcessRecord{4076e000 301:xper.service.fastnet/10053}
        createTime=-58s92ms lastActivity=-58s696ms
         executingStart=-58s690ms restartTime=-58s696ms
        Bindings:
        * IntentBindRecord{40704020}:
          intent={act=xper.service.fastnet.ACTION_FASTNET}
          binder=android.os.BinderProxy@4069ce20
          requested=true received=true hasBound=true doRebind=false
          * Client AppBindRecord{407040d0 ProcessRecord{4067a100 293:xper.service.fastnet.client/10054}}
            Per-process Connections:
              ConnectionRecord{40706ac0 xper.service.fastnet/.FastnetService:@40721f08}
        All Connections:
          ConnectionRecord{40706ac0 xper.service.fastnet/.FastnetService:@40721f08}

The ServiceRecord [0x406f89b8] representing the Fastnet Service is present and it references a single IntentBindRecord [0x4067a100] as expected.

The IntentBindRecord [0x4067a100] references a single AppBindRecord [0x407040d0] as expected.

The AppBindRecord [0x407040d0] references the ProcessRecord [0x4067a100] which represents the Fastnet Service client and has a single reference to a ConnectionRecord [0x40706ac0] as expected,

2.4 ConnectionRecord

    Connection bindings to services:
    * ConnectionRecord{40706ac0 xper.service.fastnet/.FastnetService:@40721f08}
      binding=AppBindRecord{407040d0 xper.service.fastnet/.FastnetService:xper.service.fastnet.client}
      activity=HistoryRecord{407ad2d8 xper.service.fastnet.client/.FastnetClientActivity}
      conn=android.os.BinderProxy@40721f08 flags=0x1
	
    ...

The ConnectionRecord [0x40706ac0] references the ActivityRecord [0x407040d0] for the FastnetClientActivity and the AppBindRecord [0x407040d0] as expected.

3.0 Java Heap State

In this case we already have the dumpsys output but we can, as in the Service client and Service cases, also use the state of the Java heap of the System process after the client has bound to the Fastnet Service to double-check.

As in the two previous case we can automatically generate a graph which shows the relationships between the objects in the heap.

This graph was generated using the ServiceRecord object [0x406f89b8] representing the Fastnet Service as the root.

The greyed out nodes have been filtered, that is, one or more instance variables have been omitted. This makes the graph only marginally less complicated in this case.

The complexity of the graph makes it difficult to see but it does confirm the output from dumpsys.


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

May 21, 2012

Adventures In Distributed Garbage Collection: Part Ten – Post Bind Service State

Filed under: Android, Android Internals, Java, Mobile Java, Services — Tags: , , , , — Simon Lewis @ 6:00 am

1.0 Object State

As in the Service client case we can use the source code to derive a diagram which shows the Service related objects which should exist in the Service process and their relationships once the Service client has bound to the Service.

2.0 Java Heap State

We can use the state of the Java heap of the Service process once the client has bound to the Service to check whether the code that actually runs in this case is actually doing what we think it is.

We can obtain a dump of the Java heap state and examine it interactively using a tool like MAT.

Alternatively we can automatically generate a graph which shows the relationships between the objects in the heap graphically.

This graph was generated using the FastnetService object [0x40517518] as the root.

The greyed out nodes have been filtered, that is, one or more instance variables have been omitted. This makes the graph a bit less complicated.

Again, although it is not exactly obvious the heap does contain the Service related objects and state we would expect.


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

May 20, 2012

Adventures In Distributed Garbage Collection: Part Nine – Post Bind Service Client State

Filed under: Android, Android Internals, Java, Mobile Java, Services — Tags: , , , , — Simon Lewis @ 6:00 am

1.0 Object State

We can use the source code to derive a diagram which shows the Service related objects which should exist in the Service client process and their
relationships following a successful call to bindService().

2.0 Java Heap State

We can use the state of the Java heap of the Service client process following the call to bindService() to check whether the code that runs
is actually doing what we think it is.

We can obtain a dump of the Java heap state and examine it interactively using a tool like MAT.

Alternatively we can generate a graph from the dump of the Java heap state which shows the relationships between the objects graphically.

This graph was generated using the LoadedApk object [0x40513e90] as the root.

The greyed out nodes have been filtered, that is, one or more instance variables have been omitted. This makes the graph a bit less complicated.

Although it is not exactly obvious the following objects are present in the generated object graph as expected

  • ServiceDispatcher [0x405213b8]

  • ConnectionInfo [0x40521b40]

  • InnerConnection [0x405216b8]

  • FastnetServiceConnection [0x405211f0]

and the relationships between them are also as expected.


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

May 19, 2012

Adventures In Distributed Garbage Collection: Part Eight – Binding To A Service

1.0 Process: Service Client

Actor: Service Client

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

    public abstract boolean bindService(Intent service, ServiceConnection conn, int flags);

passing it a ServiceConnection object

        ...

        connection = new FastnetServiceConnection();
        bindService(
            new Intent("xper.service.fastnet.ACTION_FASTNET"), 
            connection, 
            Service.BIND_AUTO_CREATE);
		
        ...

where the class FastnetServiceConnection is defined as follows

    final class FastnetServiceConnection 
                implements 
                    ServiceConnection 
    {
        public void onServiceConnected(ComponentName theName, IBinder theService) 
        {
            Log.d("FastnetSeviceConnection", "onServiceConnected(" + theName + ", " + theService + ")");
            service = theService;
        }

	public void onServiceDisconnected(ComponentName theName) 
	{
		Log.d("FastnetSeviceConnection", "onServiceDisonnected(" + theName + ")");
	}

        private IBinder	service;
    }

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

1.1 bindService(…)

Object: ContextImpl

Definition: ContextImpl.java [863-885]

    public boolean bindService(Intent service, ServiceConnection conn, int flags)

Argument: Intent service

  • The Intent identifying the Service to bind to.

Argument: ServiceConnection conn

  • ServiceConnection object on which callback methods should be invoked when the status of the connection changes.

Argument: int flags

  • A set of bit-flags used to specify options which control aspects of the behaviour of the method.

Method

The method begins by calling the getServiceDispatcher() method on mPackageInfo to obtain an IServiceConnection object.

It then invokes the bindService() method on the ActivityManagerProxy obtained by a call to the static method ActivityManagerNative.getDefault().

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

1.2 getServiceDispatcher(…)

Object: LoadedApk

Definition: LoadedApk.java [824-844]

    public final IServiceConnection getServiceDispatcher(ServiceConnection c, Context context, Handler handler, int flags)

Argument: ServiceConnection c

Argument: Context context

  • The Context in which ServiceConnection is being used.

Argument: Handler handler

Argument: int flags

  • A setof bit-flags specifying aspects of the required behaviour of the ServiceDispatcher

Method

The method begins by attempting to obtain an existing ServiceDispatcher for the given ServiceConnection from the ServiceConnection to ServiceDispatcher map for the given Context held in the mServices map.

If an existing ServiceDispatcher is found then the validate() method is called on it to ensure that in can be used with the given Context and Handler.

Otherwise a new one is created and added to the ServiceConnection to ServiceDispatcher map for the given Context held in the mServices map.

The method then calls getIServiceConnection() on the new or existing ServiceDispatcher object and returns the result.

2.0 Process: System

Entry Point: remote procedure call to the ActivityManagerService implementation of the IActivityManager method bindService().

2.1 bindService(…)

Caller: Service Client via remote procedure call

Actor: ActivityManagerService

Definition: ActivityManagerService.java [9401-9540]

    public int bindService(
                   IApplicationThread caller, 
                   IBinder            token,
                   Intent             service, 
                   String             resolvedType,
                   IServiceConnection connection, 
                   int                flags)

Argument: IApplicationThread caller

Argument: IBinder token

  • The ActivityRecord which represents the Activity which invoked this method, or null.

Argument: Intent service

  • The Intent specifying the Service to bind to.

Argument: String resolvedType

  • The data type, if any, explicitly or implicitly specified by the service argument.

Argument: IServiceConnection connection

  • The proxy for the InnerConnection object which implements the IServiceConnection interface in the Service Client.

Argument: int flags

  • The set of bit-flags that were passed to the original call to bindService() by the Service client.

Method

The method begins by attempting to get the ProcessRecord which represents the process in which the caller is running by calling the method

    final ProcessRecord getRecordForAppLocked(IApplicationThread thread)

passing the caller argument to it.

If getRecordForAppLocked() returns null a SecurityException is thrown.

It the token argument is not null then

  • The method checks to see whether it is valid.

  • If it is not the method returns at this point, otherwise the corresponding ActivityRecord is obtained.

The method then calls retrieveServiceLocked() to obtain a ServiceRecord object.

If this is not successful the method returns at this point.

If it is successful the method calls retriveAppBindingLocked() on the ServiceRecord object to obtain the AppBindRecord for the calling process.

It then creates a new ConnectionRecord object.

The newly created ConnectionRecord object is added to

If the BIND_AUTO_CREATE flag is set in the flags argument then

If the ServiceRecord has an associated ProcessRecord and the binding for the given Intent already exists then

  • The connected() method is invoked on the IServiceConnection object held by the ConnectionRecord (conn).

  • This results in an asynchronous remote procedure call to the object implementing the IServiceConnection interface in the Service client process.

  • If this is the first connection to use the binding and the doRebind flag of the IntentBindRecord is true

Otherwise if a binding has not already been requested (b.intent.requested == false) then

  • The method calls requestServiceBindingLocked() with the rebind argument set to false.

2.2 retrieveAppBindingLocked(…)

Object: ServiceRecord

Definition: ServiceRecord.java [288-303]

    public AppBindRecord retrieveAppBindingLocked(Intent intent, ProcessRecord app)

Argument: Intent intent

  • The Intent used by the client to bind to the Service.

Argument: ProcessRecord app

  • The ProcessRecord which represents the process in which the client binding to the Service is running.

Method

The method starts by wrapping the intent argument in an Intent.FilterComparison object and then uses the result to retrieve the corresponding IntentBindRecord from the bindings map.

If there is no IntentBindRecord for the given Intent one is created and added to the bindings map.

The AppBindRecord for the process represented by the app argument is then retrieved from the apps map of the IntentBindRecord using the ProcessRecord as the key.

If the corresponding AppBindRecord exists it is returned, otherwise a new AppBindRecord is created added to the IntentBindRecord‘s apps map and then returned.

2.3 requestServiceBindingLocked(…)

Definition: ActivityManagerService.java [8770-8791]

    private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i, boolean rebind)

Argument: ServiceRecord r

  • The ServiceRecord which represents the Service to request the binding from.

Argument: IntentBindRecord i

  • The IntentBindRecord which specifies the Intent the binding is being requested for

Argument: boolean rebind

  • true if this is a rebind notification.

Method

If the Service represented by the ServiceRecord is not already running the method returns false immediately.

If a binding has not already been requested (i.requested == false) or rebind is true and there are one or more clients, then

The method then returns true.

3.0 Process: Service

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

3.1 scheduleBindService(..)

Caller: The ActivityManagerService via remote procedure call

Actor: ApplicationThread

Definition: ActivityThread.java [502-510]

    public final void scheduleBindService(IBinder token, Intent intent, boolean rebind)

Argument: IBinder token

  • A proxy for the ServiceRecord which represents the Service from which the binding is required.

Argument: Intent intent

  • The Intent the binding is required for.

Argument: boolean rebind

  • true if this is a rebind request.

Method

The method encapsulates its arguments in an instance of the ActivityThread inner class BindServiceData

        ...

        private static final class BindServiceData {
            IBinder token;
            Intent  intent;
            boolean rebind;
            ...
        }
		
        ...

and then sends it to the ActivityThread as the payload of a message.

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

3.2 handleBindService(…)

Actor: ActivityThread

Definition: ActivityThread.java [1962-1988]

    private final void handleBindService(BindServiceData data)

Argument: BindServiceData data

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

Method

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

If no Service Component object is found then the method does nothing more.

If there is a corresponding Service Component object then

  • if data.rebind is false then

    The method onBind() is called on the Service Component object with the argument data.intent.

    The static method ActivityManagerNative.getDefault() is called and the method publishService() is called on the ActivityManagerProxy object returned, with arguments

    • data.token

    • data.intent

    • the IBinder object returned from the call to Service.onBind()

    This results in a remote procedure call to the implementation of publishService() in the ActivityManagerService.

  • If data.rebind is true then

    The method onRebind() is called on the Service object with the argument data.intent.

    The static method ActivityManagerNative.getDefault() is called and the method serviceDoneExecuting() is then called on the ActivityManagerProxy returned, with the arguments

    • data.token

    • 0

    • 0

    • 0

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

4.0 Process: SystemServer

Entry Point: remote procedure call call to the ActivityManagerService implementation of the IActivityManager method publishService()

4.1 publishService(…)

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

Actor: ActivityManagerService

Definition: ActivityManagerService.java [9627-9685]

    public void publishService(IBinder token, Intent intent, IBinder service)

Argument: IBinder token

  • The ServiceRecord which represents the Service which is publishing the binding.

Argument: Intent intent

  • The Intent for which the IBinder object passed as the service argument is being published.

Argument: IBinder service

  • The proxy for the IBinder object being published, as returned by the call to the Service.onBind() method on the Service Component.

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 and and an IBinder object for it has not already been received it sets the binder instance variable of the IntentBindRecord to the service argument and the requested and received instance variables to true.

The method then iterates over each ConnectionRecord in the connections map of the ServiceRecord.

If the connection represented by the ConnectionRecord was created as the result of binding using an Intent that is filterEqual() to the intent argument then the connected() method is called on the IServiceConnection object (conn) of that ConnectionRecord.

This results in an asynchronous remote procedure call on the object implementing the IServiceConnection interface in the process that is running the client.

Finally the method calls serviceDoneExecutingLocked().

5.0 Process: ServiceClient

Entry Point: remote procedure call to the InnerConnection implementation of the IServiceConnection method connected().

5.1 InnerConnection.connected(…)

Caller: The ActivityManagerService via remote procedure call

Object: LoadedApk.ServiceDispatcher.InnerConnection

Definition: LoadedApk.java [920-925]

    public void connected(ComponentName name, IBinder service) 
                throws 
                    RemoteException

Argument: ComponentName name

Argument: IBinder service

  • The IBinder object to use to interact with the Service if the connection is being established, null if the connection is being torn-down.

Method

If the weak reference to the ServiceDispatcher object, mDispatcher, is not null then the method invokes the connected() method on the instance passing the name and service arguments.

5.2 ServiceDispatcher.connected(…)

Object: LoadedApk.ServiceDispatcher

Definition: LoadedApk.java [992-998]

    public void connected(ComponentName name, IBinder service)

Argument: ComponentName name

Argument: IBinder service

  • The IBinder object to use to interact with the Service if the connection is being established, null if the connection is being torn-down..

Method

If the reference to the Handler, mActivityThread, is not null then the method posts a Runnable to the Handler. When run the Runnable invokes the doConnected() method on the current ServiceDispatcher instance passing it the name and service arguments.

Otherwise the method invokes the doConnected() method directly passing it the name and service arguments.

5.3 doConnected(…)

Object: LoadedApk.ServiceDispatcher

Definition: LoadedApk.java [1021-1066]

    public void doConnected(ComponentName name, IBinder service)

Argument: ComponentName name

Argument: IBinder service

  • The IBinder object to use to interact with the Service if the connection is being established, null if the connection is being torn-down.

Method

The method starts by determining whether there is an existing ConnectionInfo object in the mActiveConnections map using the name argument as the key.

If there is and the IBinder object referenced by the binder instance variable is identical to the service argument the method returns straight away.

If the service argument is not null, that is, a connection is being established, a new ConnectionInfo instance is created with its binder set to the service argument, and the instance is added to the mActiveConnections map using the name argument as the key.

If there was an existing ConnectionInfo object the method onServiceDisconnected() is called on the mConnection object passing the name argument

If the service argument is not null then the method onServiceConnected() is called on the mConnection object passing the name and service arguments.


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

May 17, 2012

Adventures In Distributed Garbage Collection: Part Seven – Service Destruction

1.0 Service Component Destruction

The component which implements a Service is destroyed either

  • when the Service is explicitly stopped, either by a client or by the Service itself, and there are no current clients of the Service who specified the BIND_AUTO_CREATE flag when they bound to it, or

  • when a client which specified the BIND_AUTO_CREATE flag when it bound to the Service unbinds from it, and there are no other clients of the Service who
    specified the BIND_AUTO_CREATE flag when they bound to it

2.0 Process: System

Actor: ActivityManagerService

2.1 Stopping A Service

A Service is stopped via a remote procedure call to either the ActivityManagerService implementation of the IActivityManager method

     public int stopService(IApplicationThread caller, Intent service, String resolvedType) 
                throws 
                    RemoteException

or the ActivityManagerService implementation of the IActivityManager method

     public boolean stopServiceToken(ComponentName className, IBinder token, int startId)
                    throws
                        RemoteException

Both methods call the method bringDownServiceLocked() to stop the Service.

2.2 Unbinding From A Service

A client unbinds from a Service via a remote procedure call to the ActivityManagerService implementation of the IActivityManager method

    public boolean unbindService(IServiceConnection connection) 
                   throws 
                       RemoteException;

A call to this method can result in a call to the method bringDownServiceLocked() to stop the Service.

2.3 Methods

2.3.1 bringDownServiceLocked(…)

Definition: ActivityManagerService.java [9016-9142]

    private final void bringDownServiceLocked(ServiceRecord r, boolean force) 

Argument: ServiceRecord r

  • The ServiceRecord which represents the Service that should be stopped.

Argument: boolean force

  • true if the Service should be forced to stop.

Method

Checking Whether To Stop The Service

If force is false and the Service was started explicitly then the method returns immediately.

If there are connections associated with the Service and force is false then the method iterates over all the ConnectionRecords in the connections map of the ServiceRecord.

If the BIND_AUTO_CREATE flag is set in the flags instance variable of a ConnectionRecord the method returns immediately.

Preparing To Stop The Service

If there are connections associated with the Service then for each ConnectionRecord in the connections map of the ServiceRecord the method calls connected() on the IServiceConnection object held by the ConnectionRecord (conn) passing null as the second argument to indicate that the connection is being disconnected.

Each call results in an asynchronous remote procedure call to the object implementing the IServiceConnection in the process which created the connection.

If the Service is running, then, for each IntentBindRecord in the bindings map of the ServiceRecord the method calls bumpServiceExecutingLocked(), sets the hasBound instance variable of the IntentBindRecord to false, and then calls scheduleUnbindService() on the ApplicationThreadProxy held by the ProcessRecord which is held by the ServiceRecord.

Stopping The Service

The ServiceRecord is removed from the mServices and mServicesByIntent maps.

If the ServiceRecord has an associated ProcessRecord then

The ServiceRecord is removed from the services set of the ProcessRecord.

If the ProcessRecord has a proxy for the ApplicationThread in the process running the Service then

The method bumpServiceExecutingLocked() is called.

The ServiceRecord is added to the mStoppingServices list.

The method scheduleStopService() is called on the ApplicationThreadProxy.

This results in an asynchronous remote procedure to the ApplicationThread implementation of the scheduleStopService() method in the process running the Service.

3.0 Process: Service

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

3.1 scheduleStopService(…)

Caller: The ActivityManagerService via remote procedure call.

Actor: ApplicationThread

Definition: ActivityThread.java [531-533]

    public final void scheduleStopService(IBinder token)

Argument: IBinder token

  • The proxy for the ServiceRecord which represents the Service to be stopped.

Method

The method forwards the token argument to the ActivityThread in a message.

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

3.2 handleStopService(…)

Actor: ActivityThread

Definition: ActivityThread.java [2060-2089]

    private final void handleStopService(IBinder token)

Argument: IBinder token

  • The proxy for the ServiceRecord which represents the Service to be stopped.

Method

The method begins by retrieving the Service Component object to stop by removing it from the mServices map using the token argument as the key.

If the corresponding Service Component object is not found then the method does nothing more.

Otherwise it calls onDestroy() on the Service Component object.

It then cleans up the Service’s context before calling serviceDoneExecuting() on the ActivityManagerProxy instance returned by a call to the static method ActivityManagerNative.getDefault().

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


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

Adventures In Distributed Garbage Collection: Part Six – Service Creation

1.0 Service Component Creation

An Android Service is specified by an Android Application in its manifest and usually, although not necessarily, runs in that Application’s process.

The component that implements a Service is created in the appropriate process if it does not already exist when an attempt is made to either

  • start that Service explicitly, or

  • bind to it if the client sets the BIND_AUTO_CREATE flag when doing so

The creation of the component is initiated by the ActivityManagerService in response to the attempt to start it or bind to it.

2.0 Process: System

Actor: ActivityManagerService

2.1 Starting A Service

A Service is started either via a remote procedure call to the method

    public ComponentName startService(IApplicationThread caller, Intent service, String resolvedType)

which is defined by the IActivityManager interface, or via an internal call in the ActivityManagerService itself to the method

    ComponentName startServiceInPackage(int uid, Intent service, String resolvedType)

Each method in turn calls startServiceLocked() to do the actual work.

2.1.1 startServiceLocked()

The method calls retrieveServiceLocked() to obtain a ServiceRecord for the Service to be started, and bringUpServiceLocked() to create and start the Service if necessary.

2.2 Binding To A Service

A client binds to a Service via a remote procedure call to the ActivityManagerService implementation of the method

    public int bindService(
                   IApplicationThread caller, 
                   IBinder            token,
                   Intent             service, 
                   String             resolvedType, 
                   IServiceConnection connection,
                   int                flags) 
               throws 
                   RemoteException

defined by the IActivityManager interface.

Like startServiceLocked(), the implementation of the bindService() method calls retrieveServiceLocked() to obtain a ServiceRecord for the Service to be accessed, and bringUpServiceLocked() to create the Service if necessary.

2.3 Methods

2.3.1 retrieveServiceLocked(…)

Definition: ActivityManagerService.java [8634-8701]

    private ServiceLookupResult retrieveServiceLocked(Intent service, String resolvedType, int callingPid, int callingUid)

Argument: Intent service

  • The Intent specifing the Service to retrieve the ServiceRecord for.

Argument: String resolvedType

  • The data type, if any, explicitly or implicitly specified by the service Intent argument.

Argument: int callingPid

  • The id of the process attempting to access the Service.

Argument: int callingUid

  • The user id associated with the process attempting to access the Service.

Method

The method first attempts to obtain a ServiceRecord for the Service specified by the service Intent argument.

If a component is specified by the Intent then it is used as a key into the mServices map.

If a component is not specified or no matching ServiceRecord is found then the service argument is wrapped in an Intent.FilterComparison instance which is then used as a key into the mServicesByIntent map.

If a matching ServiceRecord is not found then one is created and it is added to the mServices and mServicesByIntent maps

A check is then performed using the existing or newly created ServiceRecord to see whether the process attempting to access the Service has permission to do so.

2.3.2 bringUpServiceLocked(…)

Definition: ActivityManagerService.java [8962-9014]

    private final boolean bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean whileRestarting)

Argument: ServiceRecord r

  • The ServiceRecord which represents the Service to be created and started if necessary.

Argument: int intentFlags

  • The set of flags returned by a call to the getFlags() method on the Intent used to bind to or start the Service.

Argument: boolean whileRestarting

  • true if the Service is being restarted.

Method

If the Service is already running then the method sendServiceArgsLocked() is called.

If the process in which the Service should be run is already running but the Service is not then the method realStartServiceLocked() is called.

If the process in which the Service should be run is not already running then the method startProcessLocked() is called to start it. If that method is successful then the ServiceRecord is added to the mPendingServices list.

When the process starts, the method attachApplicationLocked() calls the method realStartServiceLocked() on each ServiceRecord in the mPendingServices list.

2.3.3 realStartServiceLocked(…)

Definition: ActivityManagerService.java [8803-8851]

    private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app) 
                       throws 
                           RemoteException

Argument: ServiceRecord r

  • The ServiceRecord which represents the Service to be started.

Argument: ProcessRecord app

  • The ProcessRecord which represents the process in which the Service should be started.

Method

The method starts by adding the ServiceRecord to the services set of the ProcessRecord.

It then calls bumpServiceExecutingLocked() with "create" as the why argument.

It then calls the method

   void scheduleCreateService(IBinder token, ServiceInfo info) throws RemoteException;

on the IApplicationThread instance held by the ProcessRecord passing the ServiceRecord instance r as the first argument.

This results in an asynchronous remote procedure call to the implementation of this method in the process in which the Service is to be started.

The method then calls requestServiceBindingsLocked() followed by sendServiceArgsLocked().

2.3.4 bumpServiceExecutingLocked(…)

Definition: ActivityManagerService.java [8703-8719]

   private final void bumpServiceExecutingLocked(ServiceRecord r, String why)

Argument: ServiceRecord r

  • The ServiceRecord which represents the Service to be started.

Argument: String why

  • The action the Service is being asked to execute. This is used for debugging purposes only.

Method

This method performs the book-keeping necessary to record that the given Service is about to start performing a specific action requested by the ActivityManagerService.

If the Service is not already performing other actions then the ServiceRecord will be added to the executingSevices set held by the ProcessRecord which represents the process in which the Service is running.

2.3.5 requestServiceBindingsLocked(...)

Definition: ActivityManagerService.java [8793-8801]

   private final void requestServiceBindingsLocked(ServiceRecord r)

Argument: ServiceRecord r

  • The ServiceRecord which represents the Service the method should act upon

Method

If the Service represented by ServiceRecord is not running then the method returns at once.

Otherwise, for each IntentBindRecord in the ServiceRecord's bindings map it requests an IBinder object for use by the clients which bound to the Service using the corresponding Intent.

2.3.6 sendServiceArgsLocked(...)

Definition: ActivityManagerService.java [8721-8768]

   private final void sendServiceArgsLocked(ServiceRecord r, boolean oomAdjusted)

Argument: ServiceRecord r

  • The ServiceRecord which represents the Service ...

Argument: boolean oomAdjusted

  • true if the Out-of-memory behaviour of the process running the Service has already been adjusted, false otherwise.

Method

If the Service has been expicitly started one or more times then the method will invoke the onStartCommand() method on the Service implementation via a remote procedure call one or more times.

3.0 Process: Service

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

3.1 scheduleCreateService(...)

Caller: ActivityManagerService via remote procedure call

Actor: ApplicationThread

Definition: ActivityThread.java [493-499]

    public final void scheduleCreateService(IBinder token, ServiceInfo info)

Argument: IBinder token

  • The proxy for the ServiceRecord which represents the Service to be created.

Argument: ServiceInfo info

  • The ServiceInfo for the Service to be created.

Method

The method encapsulates its arguments in an instance of the ActivityThread inner class CreateServiceData

        ...

        private static final class CreateServiceData {
            IBinder     token;
            ServiceInfo info;
            Intent      intent;
            ...
        }
		
        ...

and then sends it to the ActivityThread as the payload of a message. This message is handled by the method ActivityThread.handleCreateService().

3.2 handleCreateService(...)

Actor: ActivityThread

Definition: ActivityThread.java [1916-1960]

    private final void handleCreateService(CreateServiceData data)

Argument: CreateServiceData data

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

Method

The method first loads the class that implements the Service to be created and then creates an instance of that class.

It then calls attach() on the newly created instance followed by onCreate().

It then adds the Service instance to the mServices map using the using IBinder object held in data.token as the key.

It then calls the IActivityManager method serviceDoneExecuting() on the ActivityManagerProxy instance returned by the static method ActivityManagerNative.getDefault().

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

3.3 attach(...)

Actor: Service Component

Definition: Service.java [654-666]

    public final void attach(
                          Context        context,
                          ActivityThread thread, 
                          String         className, 
                          IBinder        token,
                          Application    application, 
                          Object         activityManager)

Argument: Context context

  • The Context for use by the Service.

Argument: ActivityThread thread

  • The ActivityThread.

Argument: String className

  • The name of the class which implements the Service.

Argument: IBinder token

Argument: Application application

  • The Application which defines the Service.

Argument: Object activityManager

  • The proxy for the ActivityManagerService.

Method

The method sets up the Context for the Service using the context argument and then initializes each of the instance variables with the corresponding argument, for example,

        ...

        mClassName   = className;
        mToken       = token;
        mApplication = application;
		
        ...

4.0 Process: System

Actor: ActivityManagerService

Entry Point: remote procedure call to the ActivityManagerService implementation of the IActivityManager method serviceDoneExecuting()

4.1 serviceDoneExecuting(...)

Caller: ActivityThread in the process running the Service via remote procedure call

Definition: ActivityManagerService.java [9727-9795]

    public void serviceDoneExecuting(IBinder token, int type, int startId, int res)

Argument: IBinder token

  • The ServiceRecord which represents the Service which has finished executing a specific action at the request of the ActivityManagerService.

Argument: int type

  • The type of the action the Service has finished executing. In practice 1 if the action was "start", 0 otherwise.

Argument: int startId

  • Identifier used when the action was "start". For other actions this is always 0.

Argument: int res

  • The result of the action the Service has finished executing. Only ever used when the action was "start". For other actions this is always 0.

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 if the type argument is 1, indicating that the action was "start", various book-keeping is done using the startId and the res arguments.

If the type argument is not 1 then nothing is done and the startId and res arguments are ignored.

Finally the method calls serviceDoneExecutingLocked().

4.2 serviceDoneExecutingLocked(...)

Definition: ActivityManagerService.java [9797-9820]

    public void serviceDoneExecutingLocked(ServiceRecord r, boolean inStopping)

Argument: ServiceRecord r

  • The ServiceRecord which represents the Service which has finished executing a specific action.

Argument: boolean inStopping

  • true if the Service is stopping, false otherwise.

Method

This method does the opposite of bumpServiceExecutingLocked(). It performs the book-keeping necessary to record that the given Service has finished a specific action requested by the ActivityManagerService.

If the Service is not performing any other actions then the ServiceRecord will be removed from the executingSevices set held by the
ProcessRecord which represents the process in which the Service is running.


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

May 16, 2012

Adventures In Distributed Garbage Collection: Part Five – The Cast Of Characters Concluded: Proxies

1.0 ActivityManagerProxy

Process: Service

Process: Service Client

Package: android.app

Source: frameworks/base/core/java/android/app/ActivityManagerNative.java

Definition: 1320-2900

The ActivityManagerProxy class implements the IActivityManager interface.

In an Android Application process a singleton ActivityManagerProxy object is created during the first call to the ActivityManagerNative static method getDefault() and stored in a the gDefault class variable.

All subsequent calls to the getDefault() method return the singleton object.

The ActivityManagerProxy holds an IBinder object obtained by a call to the static method getService() in the hidden class android.os.ServiceManager. The method is passed the argument "activity". In an Android Application process this returns a BinderProxy object for the ActivityManagerService object in the System process.

The ActivityManagerProxy implementations of the IActivityManager methods simply marshall their arguments, dispatch to the ActivityManagerService via the BinderProxy object and unmarshall the result if necessary.

2.0 ApplicationThreadProxy

Process: System Server

Package: android.app

Source: frameworks/base/core/java/android/app/ApplicationThreadNative.java

Definition: 417-832

The ApplicationThreadProxy class implements the IApplicationThread interface.

ApplicationThreadProxy proxy objects are created by the ApplicationThreadNative static method asInterface().

This method is invoked by the ActivityManagerNative onTransact() method when it is unmarshalling arguments of type IApplicationThread.

An ApplicationThreadProxy object holds an IBinder object which in the System process is a BinderProxy object for the
ApplicationThread object in an Android Application process.

The ProcessRecord thread instance variable holds an ApplicationThreadProxy object which is created as a result of the call to the ActivityManagerService’s implementation of the attachApplication() method.

3.0 Relationships


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

Older Posts »

Theme: WordPress Classic. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.