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 theIntent
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
-
The proxy for the
ServiceRecord
which represents the Service in theActivityManagerService
.
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 theActivityManagerService
.
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.