android服务的启动过程,Android Service启动流程

一、Service生命周期

首先我们先回忆一下Service的声明周期

60411ffad569

image

第一次调用startServie(): Service.onCreate()->Service.onStartCommand()

第二次调用startService(): Service.onStartCommand()

本周主要分析上面两步操作,Service的启动行为。

二、Service启动分析

60411ffad569

image

阶段一:app进程startService(),向SystemServer进程发送启动Service的请求

首先明确一点,启动Service、启动Activity、发送广播,这些都是Context上下文的本职工作。

在Applciation、Activity或者Service中都可以调用startService(),最终会调用到ContextImpl.startService()

ContextImpl.StartService

ContextImpl.startServiceCommon

ActivityManager.getService().startService()

阶段二:SystemService进程 处理启动Service请求

在ActivityManagerService中,启动service的操作 是委托给ActiveServices执行的。

ActivityManagerService.startService()

ActiveServices.startServiceLocked()

startServiceLocked方法中会解析要启动的Service,创建对应的ServiceRecord实例,最终调用自身bringUpServiceLocked方法。

## ActiveServices.java

ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,

int callingPid, int callingUid, boolean fgRequired, String callingPackage, final int userId)

throws TransactionTooLargeException {

//(1)解析、创建响应的ServiceRecord

ServiceLookupResult res =retrieveServiceLocked(service, resolvedType, callingPackage,

callingPid, callingUid, userId, true, callerFg, false, false);

ServiceRecord r = res.record;

//(2)调用内部方法

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

}

ActiveServices.startServiceInnerLocked()

ActiveServices.bringUpServiceLocked()

bringUpServiceLocked是处理Service启动逻辑的核心方法。

private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,

boolean whileRestarting, boolean permissionsReviewRequired)

throws TransactionTooLargeException {

//注释一:如果Service已经创建,则直接调用sendServiceArgsLocked(),最终会触发Service.onStartCommand()方法调用

if (r.app != null && r.app.thread != null) {

sendServiceArgsLocked(r, execInFg, false);

return null;

}

final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;

if (!isolated) {

//注释二:非独立进程,则直接启动Service:onCreate(),onStartCommad()方法

realStartServiceLocked(r, app, execInFg);

}else {

//注释三: 如果Service要运行独立进程,且进程不存在,则创建新进程.

if (app == null && !permissionsReviewRequired) {

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;

}

}

}

}

注释一:如果Service已经创建,则直接调用sendServiceArgsLocked(),最终调用Service.onStartCommand()方法。对应第二次调用StartService方法的场景,此场景Service仅会回调onStartCommand()回调

注释二:如果Service不要求运行在新的进程,则调用realStartServiceLocked()方法,该方法 会触发Service.onCreate()和onStartCommand()方法

注释三: 如果Service要运行独立进程,且进程不存在,则创建新进程.

阶段三:ActivityMangaerService 与 ActivityThread IPC互动过程。

下面我们一起来看一下ActiveServices是 如何创建,并启动Service的。

核心方法在realStartServiceLocked()

private final void realStartServiceLocked(ServiceRecord r,

ProcessRecord app, boolean execInFg) throws RemoteException {

//(1)向ApplicationThread发送消息,创建Service

app.thread.scheduleCreateService(r, r.serviceInfo,

mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),

app.repProcState);

//(2)向Service发送参数

sendServiceArgsLocked(r, execInFg, true);

}

1、scheduleCreateService

利用ApplicationThread 向app进程发送IPC消息

ApplicationThread.scheduleCreateService()

ApplicationThread发送H.CREATE_SERVICE消息

ActivityThread.handleCreateService()

private void handleCreateService(CreateServiceData data) {

//(1)创建Service

service = packageInfo.getAppFactory()

.instantiateService(cl, data.info.name, data.intent);

//(2)创建ContextImpl

ContextImpl context = ContextImpl.createAppContext(this, packageInfo);

context.setOuterContext(service);

//(3)调用Service.attah()

service.attach(context, this, data.info.name, data.token, app,

ActivityManager.getService());

//(4)调用Service.onCreate()

service.onCreate();

}

handleCreateService()中完成了以下操作:

利用LoadedApk创建了Service实例,

创建ContextImpl()实例

调用Service.attach()完成ContextImpl的绑定

调用Service.onCreate()方法

2、 sendServiceArgsLocked 启动Service的参数处理

ActiveServices.sendServiceArgsLocked 主要做的操作就是,通过ApplicationThread发送scheduleServiceArgs的IPC消息

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,boolean oomAdjusted) throws TransactionTooLargeException {

r.app.thread.scheduleServiceArgs(r, slice);

}

ApplicationThread.scheduleServiceArgs()

public final void scheduleServiceArgs(IBinder token, ParceledListSlice args) {

List list = args.getList();

for (int i = 0; i < list.size(); i++) {

ServiceStartArgs ssa = list.get(i);

ServiceArgsData s = new ServiceArgsData();

s.token = token;

s.taskRemoved = ssa.taskRemoved;

s.startId = ssa.startId;

s.flags = ssa.flags;

s.args = ssa.args;

sendMessage(H.SERVICE_ARGS, s);

}

}

发送H.SERVICE_ARGS 消息

ActivityThread.handleServiceArgs(),调用Service.onStartCommand()

private void handleServiceArgs(ServiceArgsData data) {

Service s = mServices.get(data.token);

if (!data.taskRemoved) {

res = s.onStartCommand(data.args, data.flags, data.startId);

} else {

s.onTaskRemoved(data.args);

res = Service.START_TASK_REMOVED_COMPLETE;

}

}

三、参考文章

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值