Service工作过程

Service基础知识

Android Study Plan II - Service

Service工作过程

Service分为两种工作状态,一种是启动状态,主要用于执行后台计算;另一种是绑定状态,主要用于其他组件和Service的交互。

Service的这两种状态是可以共存的,即Service既可以处于启动状态也可以同时处于绑定状态。

1
2
3
4
5
6
7
//启动Service
Intent intent= new Intent(this,MyService.class);
startService(intent);

//绑定Service
Intent intent= new Intent(this,MyService.class);
bindService(intent,mServiceConnection,BIND_AUTO_CREATE);

Service启动过程 - startService

Service的启动过程从ContextWrapper.startService()开始

1
2
3
4
5
6
// ../android/content/ContextWrapper.java
Context mBase;
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}

在Activity启动的时候performLaunActivity时,会创建上下文对象Context,然后在Activity.attach()调用了attachBaseContext()将得到的contenxt进行赋值。最终操作的就是ContextImpl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// ../android/app/ContextImpl.jsvs
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, false, mUser);
}

private ComponentName startServiceCommon(Intent service, boolean requireForeground,
UserHandle user)
{
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
//启动Service
ComponentName cn = ActivityManager.getService().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), requireForeground,
getOpPackageName(), user.getIdentifier());
if (cn != null) {
...
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

ActivityManager.getService()在Activity启动过程中有介绍它是得到IActiivtyManager实际就是指向AMS的一个Binder对象,调用到的就是AMS.startService()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// ../core/java/com/android/server/am/ActivityManagerService.java
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, boolean requireForeground, String callingPackage, int userId)

throws TransactionTooLargeException
{
enforceNotIsolatedCaller("startService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}

if (callingPackage == null) {
throw new IllegalArgumentException("callingPackage cannot be null");
}

if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
"*** startService: " + service + " type=" + resolvedType + " fg=" + requireForeground);
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res;
try {
res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid,
requireForeground, callingPackage, userId);
} finally {
Binder.restoreCallingIdentity(origId);
}
return res;
}
}

mServices的类型是ActiveServices.ActiveServices是一个辅助AMS进行Service管理的类,其中包括Service的启动,绑定和停止等功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// ../core/java/com/android/server/am/ActiveServices.java
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)

throws TransactionTooLargeException
{
...
//去查找是否有与参数 service 对应的ServiceRecord。
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
//封装一个ServiceRecord对象
ServiceRecord r = res.record;
...

ComponentName cmp = startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}

ServiceRecord描述的是一个Service记录,一直贯穿着整个Service的启动过程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting)
throws TransactionTooLargeException
{
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}

...

return r.name;
}

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)

throws TransactionTooLargeException
{
...
//获取Service想在那个进程中运行 process
final String procName = r.processName;
String hostingType = "service";
ProcessRecord app;
//当前不止一个进程
if (!isolated) {
//查询是否存在一个 与Service类型对应的ProcessRecord对象的app进程
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
//Service的运行进程已经存在
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
//启动service
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
}
} else {
app = r.isolatedProc;
if (WebViewZygote.isMultiprocessEnabled()
&& r.serviceInfo.packageName.equals(WebViewZygote.getPackageName())) {
hostingType = "webview_service";
}
}

//没有对应的运行进程启动
if (app == null && !permissionsReviewRequired) {
//需要新启动一个应用进程 承载Service
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
hostingType, r.name, false, isolated, false)) == null) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": process is bad";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
if (isolated) {
r.isolatedProc = app;
}
}
...
}

bringUpServiceLocked()中,优先获取Service需要的运行进程--通过android:process设置,然后去判断当前进程中是否存在符合要求的

  • 不存在,调用AMS.startProcessLocked()去新建对应应用进程,这个函数在Activity启动过程中有讲解
  • 存在,直接调用realStartServiceLocked()去启动Service,命名方法类似Activity启动过程中的realStartActivityLocked()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg)
throws RemoteException
{
...
boolean created = false;
try {
...
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
Slog.w(TAG, "Application dead when creating service " + r);
mAm.appDiedLocked(app);
throw e;
} finally {
if (!created) {
// Keep the executeNesting count accurate.
final boolean inDestroying = mDestroyingServices.contains(r);
serviceDoneExecutingLocked(r, inDestroying, inDestroying);

// Cleanup.
if (newService) {
app.services.remove(r);
r.app = null;
}

// Retry.
if (!inDestroying) {
scheduleServiceRestartLocked(r, false);
}
}
}

...
//由于 必须startRequested 参数为true
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null, 0));
}
//调用Service中的其他方法,例如 onStartCommand
sendServiceArgsLocked(r, execInFg, true);

}


private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,
boolean oomAdjusted)
throws TransactionTooLargeException
{
...
//通知ActivityThread初始化已经完成,然后调用后续方法
r.app.thread.scheduleServiceArgs(r, slice);
...
}

app.threadIApplicationThread类型的,实际上是一个Binder对象,它的实现是ApplicationThread,用于和ActivityThread进行通信。

1
2
3
4
5
6
7
8
9
10
11
// ../android/app/ActivityThread.java       
public final void scheduleCreateService(IBinder token,
ServiceInfo info, CompatibilityInfo compatInfo, int processState)
{
updateProcessState(processState, false);
CreateServiceData s = new CreateServiceData();
s.token = token;
s.info = info;
s.compatInfo = compatInfo;

sendMessage(H.CREATE_SERVICE, s);
}

这里与Activity启动过程是一致的,通过ActivityThread.H这个Handler对象发送消息,切换到主线程去处理消息。这个发送的是CREATE_SERVICE,最后调用到了ActivityThread.handleCreateService()去启动Service

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();    
private void handleCreateService(CreateServiceData data) {
// If we are getting ready to gc after going to the background, well
// we are back active so skip it.
unscheduleGcIdler();
//获取LoaderApk对象 是一个Apk文件的描述器
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to instantiate service " + data.info.name
+ ": " + e.toString(), e);
}
}

try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
//创建Service的ContextImpl对象
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);

Application app = packageInfo.makeApplication(false, mInstrumentation);
//初始化Service
service.attach(context, this, data.info.name, data.token, app,
ActivityManager.getService());
//调用 onCreate 生命周期
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(service, e)) {
throw new RuntimeException(
"Unable to create service " + data.info.name
+ ": " + e.toString(), e);
}
}
}

handleCreateService()执行了以下的几件事:

  • 通过类加载器创建Service实例,Actiivty启动过程是利用了 Instrumention.newActivity() 执行相同创建实例
  • makeApplication()创建Application对象并调用其onCreate
  • 创建ContextImpl对象并调用Service.attach()建立关系
  • 最后调用Service.onCreate()开始创建过程,并存储至ArrayMap<IBinder,Service>中,在下一节会介绍这里存储数据的作用
  • 调用onCreate()之后,Service也已经启动了。
{% fullimage /images/Service启动过程.png,Service启动过程,Service启动过程%}

Service绑定过程 - bindService

和Service的启动过程一样,Service的绑定过程也是从ContextWrapper开始

1
2
3
4
5
6
// ../android/content/ContextWrapper.java    
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags)
{
return mBase.bindService(service, conn, flags);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// ../android/app/ContextImpl.java
@Override
public boolean bindService(Intent service, ServiceConnection conn,
int flags)
{
warnIfCallingFromSystemProcess();
return bindServiceCommon(service, conn, flags, mMainThread.getHandler(),
Process.myUserHandle());
}

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags, Handler
handler, UserHandle user)
{
IServiceConnection sd;
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);
} else {
throw new RuntimeException("Not supported in system context");
}
validateServiceIntent(service);
try {
...
service.prepareToLeaveProcess(this);
int res = ActivityManager.getService().bindService(
mMainThread.getApplicationThread(), getActivityToken(), service,
service.resolveTypeIfNeeded(getContentResolver()),
sd, flags, getOpPackageName(), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to bind to service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

bindServiceCommon()主要做了两件事情:

  • getServiceDispatcher() 将传进来的ServiceConnection转化成IServiceConnection,通过Binder对象进行通信。使得Service的绑定支持跨进程调用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    // ../android/app/LoaderApk.java    
    public final IServiceConnection getServiceDispatcher(ServiceConnection c,
    Context context, Handler handler, int flags)
    {
    synchronized (mServices) {
    LoadedApk.ServiceDispatcher sd = null;
    ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map = mServices.get(context);
    if (map != null) {
    if (DEBUG) Slog.d(TAG, "Returning existing dispatcher " + sd + " for conn " + c);
    sd = map.get(c);
    }
    if (sd == null) {
    sd = new ServiceDispatcher(c, context, handler, flags);
    if (DEBUG) Slog.d(TAG, "Creating new dispatcher " + sd + " for conn " + c);
    if (map == null) {
    map = new ArrayMap<>();
    mServices.put(context, map);
    }
    map.put(c, sd);
    } else {
    sd.validate(context, handler);
    }
    return sd.getIServiceConnection();
    }
    }

    mServices存储了一个应用当前活动的ServiceConnection和ServiceDispatcher的映射关系。ServiceDispatcher的作用是连接ServiceConnection和IServiceConnection。

  • bindService()开始Service的绑定流程

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    // ../core/java/com/android/server/am/ActivityManagerService.java
    public int bindService(IApplicationThread caller, IBinder token, Intent service,
    String resolvedType, IServiceConnection connection, int flags, String callingPackage,
    int userId)
    throws TransactionTooLargeException
    {
    enforceNotIsolatedCaller("bindService");

    // Refuse possible leaked file descriptors
    if (service != null && service.hasFileDescriptors() == true) {
    throw new IllegalArgumentException("File descriptors passed in Intent");
    }

    if (callingPackage == null) {
    throw new IllegalArgumentException("callingPackage cannot be null");
    }

    synchronized(this) {
    return mServices.bindServiceLocked(caller, token, service,
    resolvedType, connection, flags, callingPackage, userId);
    }
    }

存储好对应的ServiceConnectionServiceDispatcher映射的关系,之后开始继续绑定流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
// ../core/java/com/android/server/am/ActiveServices.java
int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,
String resolvedType, final IServiceConnection connection, int flags,
String callingPackage, final int userId)
throws TransactionTooLargeException
{
// 获取应用进程信息
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when binding service " + service);
}
//获取绑定Activity信息
ActivityRecord activity = null;
if (token != null) {
activity = ActivityRecord.isInStackLocked(token);
if (activity == null) {
Slog.w(TAG, "Binding with unknown activity: " + token);
return 0;
}
}
//获取Service相关信息
ServiceRecord s = res.record;
//启动Activity成功后 ,再启动Service
if (mAm.mPermissionReviewRequired) {
if (mAm.getPackageManagerInternalLocked().isPermissionsReviewRequired(
s.packageName, s.userId)) {
RemoteCallback callback = new RemoteCallback(
new RemoteCallback.OnResultListener() {
@Override
public void onResult(Bundle result) {
synchronized(mAm) {
final long identity = Binder.clearCallingIdentity();
try {
...
if (...) {
try {
// 启动 Service
bringUpServiceLocked(...);
} catch (RemoteException e) {
/* ignore - local call */
}
} else {
...
}
} finally {
...
}
}
}
});

final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSIONS);
// 注意 callback
intent.putExtra(Intent.EXTRA_REMOTE_CALLBACK, callback);

// 启动 Activity,成功启动后回调 callback
mAm.mHandler.post(new Runnable() {
@Override
public void run() {
mAm.mContext.startActivityAsUser(intent, new UserHandle(userId));
}
});
}
}
try{
// 如果设置了绑定后自动启动
if ((flags&Context.BIND_AUTO_CREATE) != 0) {
s.lastActivity = SystemClock.uptimeMillis();
// 启动 Service
if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,
permissionsReviewRequired) != null) {
return 0;
}
}
// Service 已经在运行中,直接回调 onServiceConnected 即可
if (s.app != null && b.intent.received) {
// Service is already running, so we can immediately
// publish the connection.
try {
// 回调 onServiceConnected
c.conn.connected(s.name, b.intent.binder, false);
} catch (Exception e) {
...
}
//
if (b.intent.apps.size() == 1 && b.intent.doRebind) {
requestServiceBindingLocked(s, b.intent, callerFg, true);
}
...
//没有进行过绑定Service请求
} else if (!b.intent.requested) {
// 回调 onBind,内部调用了 scheduleBindService
requestServiceBindingLocked(s, b.intent, callerFg, false);
}
...
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}

介绍几个与Service有关的对象类型:

  • ServiceRecord:描述一个Service
  • ProcessREcord:描述一个进程的信息
  • ConnectionRecord:描述应用程序进程和Service建立的一次通信。
  • AppBindRecord:维护Srvice与应用程序进程之间的关联。
  • IntentBindRecord:描述绑定Service的Intent

bindServiceLocked()内部会通过bringUpServiceLocked()自动启动Service。然后向下走启动Service流程

还会多调用一个requestServiceBindingLocked()请求绑定过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// ../core/java/com/android/server/am/ActiveServices.java
private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,
boolean execInFg, boolean rebind/*是否重新绑定*/)
throws TransactionTooLargeException
{
if (r.app == null || r.app.thread == null) {
// If service is not currently running, can't yet bind.
return false;
}
if (DEBUG_SERVICE) Slog.d(TAG_SERVICE, "requestBind " + i + ": requested=" + i.requested
+ " rebind=" + rebind);
//是否发送过 绑定Service的请求
if ((!i.requested || rebind) && i.apps.size() > 0) {
try {
bumpServiceExecutingLocked(r, execInFg, "bind");
r.app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,
r.app.repProcState);
if (!rebind) {
i.requested = true;
}
i.hasBound = true;
i.doRebind = false;
} catch (... ) {//最大通常限制为1M.
...
}
}
return true;
}

app.thread把逻辑切换到了 ActivityThread中了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// ../android/app/ActivityThread.java       
public final void scheduleBindService(IBinder token, Intent intent,
boolean rebind, int processState)
{
updateProcessState(processState, false);
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;
s.rebind = rebind;

if (DEBUG_SERVICE)
Slog.v(TAG, "scheduleBindService token=" + token + " intent=" + intent + " uid="
+ Binder.getCallingUid() + " pid=" + Binder.getCallingPid());
sendMessage(H.BIND_SERVICE, s);
}

// 处理绑定Service流程
private void handleBindService(BindServiceData data) {
//获取要绑定的Service对象
Service s = mServices.get(data.token);
if (DEBUG_SERVICE)
Slog.v(TAG, "handleBindService s=" + s + " rebind=" + data.rebind);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
try {
//绑定Service
if (!data.rebind) {
//调用 onBind 方法,此时已绑定Service
IBinder binder = s.onBind(data.intent);
//通知绑定成功
ActivityManager.getService().publishService(
data.token, data.intent, binder);
} else {
//执行重新绑定流程
s.onRebind(data.intent);
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
ensureJitEnabled();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
if (!mInstrumentation.onException(s, e)) {
throw new RuntimeException(
"Unable to bind to service " + s
+ " with " + data.intent + ": " + e.toString(), e);
}
}
}
}

Service.onRebind()执行条件为:使用Service的流程是,先startService()然后bindService(),在Activity退出的时候,Service并不会停止,再进入Activity重新进行bindService(),会触发onRebind()方法。但是先前Activity退出时调用的onUnbind()返回为true,直接写死返回结果。

当多次绑定同一个Service时,onBind()只会执行一次,除非Service被终止。

Service绑定过程

Service绑定通知

发现Service未绑定时,就会调用到onBind(),Service就处于绑定状态,但是客户端无法感知到Service已经连接成功,所以需要AMS进行通知。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ../core/java/com/android/server/am/ActivityManagerService.java
public void publishService(IBinder token, Intent intent, IBinder service) {
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}

synchronized(this) {
if (!(token instanceof ServiceRecord)) {
throw new IllegalArgumentException("Invalid service token");
}
mServices.publishServiceLocked((ServiceRecord)token, intent, service);
}
}

mServices就是ActiveServices对象,调用其内部的publishServiceLocked()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// ../core/java/com/android/server/am/ActiveServices.java
void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
final long origId = Binder.clearCallingIdentity();
try {
...
for (int conni=r.connections.size()-1; conni>=0; conni--) {
ArrayList<ConnectionRecord> clist = r.connections.valueAt(conni);
for (int i=0; i<clist.size(); i++) {
ConnectionRecord c = clist.get(i);
try {
c.conn.connected(r.name, service, false);
} catch (Exception e) {
Slog.w(TAG, "Failure sending service " + r.name +
" to connection " + c.conn.asBinder() +
" (in " + c.binding.client.processName + ")", e);
}
}
}
}

serviceDoneExecutingLocked(r, mDestroyingServices.contains(r), false);
}
} finally {
Binder.restoreCallingIdentity(origId);
}
}

c.conn指向IServiceConnection,他是ServiceConnection在本地的代理对象,用于解决当前应用程序进程和Service跨进程通信的问题。

他的具体实现为ServiceDispatcher.InnerConnection

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// ../android/app/LoaderApk.java
static final class ServiceDispatcher {
...
private static class InnerConnection extends IServiceConnection.Stub {
final WeakReference<LoadedApk.ServiceDispatcher> mDispatcher;

InnerConnection(LoadedApk.ServiceDispatcher sd) {
mDispatcher = new WeakReference<LoadedApk.ServiceDispatcher>(sd);
}

public void connected(ComponentName name, IBinder service, boolean dead)
throws RemoteException
{
LoadedApk.ServiceDispatcher sd = mDispatcher.get();
if (sd != null) {
sd.connected(name, service, dead);
}
}
}

public void connected(ComponentName name, IBinder service, boolean dead) {
if (mActivityThread != null) {
mActivityThread.post(new RunConnection(name, service, 0, dead));
} else {
doConnected(name, service, dead);
}
}

...
}

mActivityThread是一个Handler对象,指向的就是ActivityThread.H。因此可以通过调用post()直接发送RunConnection对象的内容运行在主线程中。mActivityThread不可能为空。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
private final class RunConnection implements Runnable {
RunConnection(ComponentName name, IBinder service, int command, boolean dead) {
mName = name;
mService = service;
mCommand = command;
mDead = dead;
}

public void run() {
if (mCommand == 0) {
doConnected(mName, mService, mDead);
} else if (mCommand == 1) {
doDeath(mName, mService);
}
}

final ComponentName mName;
final IBinder mService;
final int mCommand;
final boolean mDead;
}

调用了RunConnection实际上还是调用了doConnected()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
ServiceConnection mConnection;
public void doConnected(ComponentName name, IBinder service, boolean dead) {
ServiceDispatcher.ConnectionInfo old;
ServiceDispatcher.ConnectionInfo info;

synchronized (this) {
...
// 如果存在老Service 会优先断掉连接
if (old != null) {
mConnection.onServiceDisconnected(name);
}
// Service已消失 死亡回调
if (dead) {
mConnection.onBindingDied(name);
}
// 全新的Service 通知绑定成功
if (service != null) {
mConnection.onServiceConnected(name, service);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
//使用场景 
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//绑定成功回调
}

@Override
public void onServiceDisconnected(ComponentName name) {

}
};

Service解绑过程 - unbindService()

Service的解绑过程也是从ContextWrapper开始

1
2
3
4
@Override
public void unbindService(ServiceConnection conn) {
mBase.unbindService(conn);
}

实际调用的是ContextImpl.unbindService()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// ../android/app/ContextImpl.java
@Override
public void unbindService(ServiceConnection conn) {
if (conn == null) {
throw new IllegalArgumentException("connection is null");
}
if (mPackageInfo != null) {
IServiceConnection sd = mPackageInfo.forgetServiceDispatcher(
getOuterContext(), conn);
try {
ActivityManager.getService().unbindService(sd);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} else {
throw new RuntimeException("Not supported in system context");
}
}

这里主要分为两部分:

  • LoadedApk.forgetServiceDispatcher()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    // ../android/app/LoaderApk.java
    public final IServiceConnection forgetServiceDispatcher(Context context,
    ServiceConnection c)
    {
    synchronized (mServices) {
    //获取当前存储的ServiceConnection
    ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> map
    = mServices.get(context);
    LoadedApk.ServiceDispatcher sd = null;
    if (map != null) {
    //获取对应的ServiceDispatcher
    sd = map.get(c);
    if (sd != null) {
    if (DEBUG) Slog.d(TAG, "Removing dispatcher " + sd + " for conn " + c);
    map.remove(c);
    sd.doForget();
    if (map.size() == 0) {
    mServices.remove(context);
    }
    if ((sd.getFlags()&Context.BIND_DEBUG_UNBIND) != 0) {
    ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher> holder
    = mUnboundServices.get(context);
    if (holder == null) {
    holder = new ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>();
    mUnboundServices.put(context, holder);
    }
    RuntimeException ex = new IllegalArgumentException(
    "Originally unbound here:");
    ex.fillInStackTrace();
    sd.setUnbindLocation(ex);
    holder.put(c, sd);
    }
    return sd.getIServiceConnection();
    }
    }
    ...

    }

    在这个函数中移除掉存储的映射关系

  • AMS.unbindService()

    1
    2
    3
    4
    5
    6
    // ../core/java/android/com/server/am/ActivityManagerService.java
    public boolean unbindService(IServiceConnection connection) {
    synchronized (this) {
    return mServices.unbindServiceLocked(connection);
    }
    }

调用到ActiveServices.unbindServiceLocked()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// ../core/java/android/com/server/am/ActiveServices.java
boolean unbindServiceLocked(IServiceConnection connection) {
IBinder binder = connection.asBinder();
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "unbindService: conn=" + binder);
ArrayList<ConnectionRecord> clist = mServiceConnections.get(binder);
if (clist == null) {
Slog.w(TAG, "Unbind failed: could not find connection for "
+ connection.asBinder());
return false;
}

final long origId = Binder.clearCallingIdentity();
try {
while (clist.size() > 0) {
ConnectionRecord r = clist.get(0);
//移除掉对应Service的绑定
removeConnectionLocked(r, null, null);

...
//从映射表中移除对应的ServiceConnection

}

mAm.updateOomAdjLocked();

} finally {
Binder.restoreCallingIdentity(origId);
}

return true;
}

void removeConnectionLocked(
ConnectionRecord c, ProcessRecord skipApp, ActivityRecord skipAct)
{
IBinder binder = c.conn.asBinder();
AppBindRecord b = c.binding;
ServiceRecord s = b.service;
ArrayList<ConnectionRecord> clist = s.connections.get(binder);
if (clist != null) {
clist.remove(c);
if (clist.size() == 0) {
s.connections.remove(binder);
}
}
b.connections.remove(c);
...
if (!c.serviceDead) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Disconnecting binding " + b.intent
+ ": shouldUnbind=" + b.intent.hasBound);
if (s.app != null && s.app.thread != null && b.intent.apps.size() == 0
&& b.intent.hasBound) {
try {
bumpServiceExecutingLocked(s, false, "unbind");
if (b.client != s.app && (c.flags&Context.BIND_WAIVE_PRIORITY) == 0
&& s.app.setProcState <= ActivityManager.PROCESS_STATE_RECEIVER) {
// If this service's process is not already in the cached list,
// then update it in the LRU list here because this may be causing
// it to go down there and we want it to start out near the top.
mAm.updateLruProcessLocked(s.app, false, null);
}
mAm.updateOomAdjLocked(s.app, true);
b.intent.hasBound = false;
// Assume the client doesn't want to know about a rebind;
// we will deal with that later if it asks for one.
b.intent.doRebind = false;
s.app.thread.scheduleUnbindService(s, b.intent.intent.getIntent());
} catch (Exception e) {
Slog.w(TAG, "Exception when unbinding service " + s.shortName, e);
serviceProcessGoneLocked(s);
}
}

...
//如果是利用 BIND_AUTO_CREATE的flag就会向下调用
if ((c.flags&Context.BIND_AUTO_CREATE) != 0) {
boolean hasAutoCreate = s.hasAutoCreateConnections();
if (!hasAutoCreate) {
if (s.tracker != null) {
s.tracker.setBound(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
}
//这里走的是stopService的流程
bringDownServiceIfNeededLocked(s, true, hasAutoCreate);
}
}
}

又看到了熟悉的app.thread就知道切换回到了ActivityThread

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// ../android/app/ActivityThread.java
public final void scheduleUnbindService(IBinder token, Intent intent) {
BindServiceData s = new BindServiceData();
s.token = token;
s.intent = intent;

sendMessage(H.UNBIND_SERVICE, s);
}

private void handleUnbindService(BindServiceData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
data.intent.setExtrasClassLoader(s.getClassLoader());
data.intent.prepareToEnterProcess();
//调用到 onUnbind() 生命周期
boolean doRebind = s.onUnbind(data.intent);
try {
if (doRebind) {
//需要重新绑定
ActivityManager.getService().unbindFinished(
data.token, data.intent, doRebind);
} else {
//取消绑定
ActivityManager.getService().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
}
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} catch (Exception e) {
...
}
}
}

当Service调用onUnbind()之后,还需要做一件事情,如果是靠bindService()并配置flagBIND_AUTO_CREATE。那么后续还会执行到stopService()中的流程,即会调用到Service.onDestroy()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// ../core/java/android/com/server/am/ActiveServices.java
void removeConnectionLocked(
//如果是利用 BIND_AUTO_CREATE的flag就会向下调用
if ((c.flags&Context.BIND_AUTO_CREATE)
!
= 0) {
boolean hasAutoCreate = s.hasAutoCreateConnections();
if (!hasAutoCreate) {
if (s.tracker != null) {
s.tracker.setBound(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
}
//这里走的是stopService的流程
bringDownServiceIfNeededLocked(s, true, hasAutoCreate); //true true
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
boolean hasConn)
{
//由于bindService过程中的Service不是由startService()进行启动的,所有这里可以向下执行
if (isServiceNeededLocked(r, knowConn, hasConn)) {
return;
}
// Are we in the process of launching?
if (mPendingServices.contains(r)) {
return;
}
bringDownServiceLocked(r);
}

private final boolean isServiceNeededLocked(ServiceRecord r, boolean knowConn,
boolean hasConn)
{
// 是否由startService()执行
if (r.startRequested) {
return true;
}
// Is someone still bound to us keeping us running?
if (!knowConn) {
hasConn = r.hasAutoCreateConnections();
}
if (hasConn) {
return true;
}
return false;
}
Service解绑过程

Service停止过程 - stopService()

还是由ContextWrapper.stopService()开始执行

1
2
3
4
@Override
public boolean stopService(Intent name) {
return mBase.stopService(name);
}

向下执行到ContextImpl.stopService()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Override
public boolean stopService(Intent service) {
warnIfCallingFromSystemProcess();
return stopServiceCommon(service, mUser);
}

private boolean stopServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
int res = ActivityManager.getService().stopService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()), user.getIdentifier());
if (res < 0) {
throw new SecurityException(
"Not allowed to stop service " + service);
}
return res != 0;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}

ActivityManager.getService()实际就是指向ActivityManagerService的一个Binder对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// ../core/java/android/com/server/am/ActivityManagerService.java   
@Override
public int stopService(IApplicationThread caller, Intent service,
String resolvedType, int userId)
{
enforceNotIsolatedCaller("stopService");
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}

synchronized(this) {
return mServices.stopServiceLocked(caller, service, resolvedType, userId);
}
}

mServicesActiveServices的一个实际对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
int stopServiceLocked(IApplicationThread caller, Intent service,
String resolvedType, int userId)
{
...
// If this service is active, make sure it is stopped.
ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, null,
Binder.getCallingPid(), Binder.getCallingUid(), userId, false, false, false);
if (r != null) {
if (r.record != null) {
final long origId = Binder.clearCallingIdentity();
try {
stopServiceLocked(r.record);
} finally {
Binder.restoreCallingIdentity(origId);
}
return 1;
}
return -1;
}

return 0;
}

private void stopServiceLocked(ServiceRecord service) {
...
service.startRequested = false;
if (service.tracker != null) {
service.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
SystemClock.uptimeMillis());
}
service.callStart = false;
bringDownServiceIfNeededLocked(service, false, false);
}

private final boolean isServiceNeededLocked(ServiceRecord r, boolean knowConn,
boolean hasConn)
{
// Are we still explicitly being asked to run?
if (r.startRequested) {
return true;
}

if (!knowConn) {
hasConn = r.hasAutoCreateConnections();
}
if (hasConn) {
return true;
}

return false;
}

private final void bringDownServiceIfNeededLocked(ServiceRecord r, boolean knowConn,
boolean hasConn)
{
if (isServiceNeededLocked(r, knowConn, hasConn)) {
return;
}

if (mPendingServices.contains(r)) {
return;
}

bringDownServiceLocked(r);
}

最后调用到了bringDownServiceLocked()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private final void bringDownServiceLocked(ServiceRecord r) {    
...
if (r.app != null) {
synchronized (r.stats.getBatteryStats()) {
r.stats.stopLaunchedLocked();
}
r.app.services.remove(r);
if (r.whitelistManager) {
updateWhitelistManagerLocked(r.app);
}
if (r.app.thread != null) {
updateServiceForegroundLocked(r.app, false);
try {
bumpServiceExecutingLocked(r, false, "destroy");
mDestroyingServices.add(r);
r.destroying = true;
mAm.updateOomAdjLocked(r.app, true);
r.app.thread.scheduleStopService(r);
} catch (Exception e) {
Slog.w(TAG, "Exception when destroying service "
+ r.shortName, e);
serviceProcessGoneLocked(r);
}
} else {
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Removed service that has no process: " + r);
}
} else {
if (DEBUG_SERVICE) Slog.v(
TAG_SERVICE, "Removed service that is not running: " + r);
}
...
}

app.thread切换到ApplicaitonThread继续执行流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// ../android/app/ActivityThread.java
public final void scheduleStopService(IBinder token) {
sendMessage(H.STOP_SERVICE, token);
}

private void handleStopService(IBinder token) {
Service s = mServices.remove(token);
if (s != null) {
try {
if (localLOGV) Slog.v(TAG, "Destroying service " + s);
s.onDestroy();
s.detachAndCleanUp();
Context context = s.getBaseContext();
if (context instanceof ContextImpl) {
final String who = s.getClassName();
((ContextImpl) context).scheduleFinalCleanup(who, "Service");
}

QueuedWork.waitToFinish();

try {
ActivityManager.getService().serviceDoneExecuting(
token, SERVICE_DONE_EXECUTING_STOP, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
...
}
} else {
...
}

}

最后执行到Service.onDestroy完成停止流程。

Service停止流程

拓展

为什么Activity退出时bindService()的Service会一并销毁?

观察源码发现,bindService()也会去启动Service,但为什么没有回调到onStartCommand()


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!