Android 10窗口计算流程,Android 10 Service 工作过程

本次源码分析是熟悉Service启动过程,让我们对Service的工作原理有进一步的了解。Service分为启动过程和绑定过程,启动状态执行后台计算,绑定状态是其他组件与Service交互。这两种状态可以同时存在。

startService 过程

现在我们开始分析startService启动过程,下图是启动过程的时序图,如图:

d3d5f3673829

当我们调用startService方法时候,紧接着都会调用startServiceCommon,我们来看看这个方法做了哪些事情。

private ComponentName startServiceCommon(Intent service, boolean requireForeground,

UserHandle user) {

...

ComponentName cn = ActivityManager.getService().startService(

mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(

getContentResolver()), requireForeground,

getOpPackageName(), user.getIdentifier());

...

}

上述代码看出,直接调用了AMS的startService,在此方法中引入了mServices这个引用实则是ActiveServices类,它是辅助AMS进行Service管理,主要包括启动、绑定和停止等。接着开始调用ActiveServices的startServiceLocked方法。

@Override

public ComponentName startService(IApplicationThread caller, Intent service,

String resolvedType, boolean requireForeground, String callingPackage, int userId)

throws TransactionTooLargeException {

...

synchronized (this) {

res = mServices.startServiceLocked(caller, service,

resolvedType, callingPid, callingUid,

requireForeground, callingPackage, userId);

}

...

}

进入startServiceLocked后我们发现,解析了service且把Service信息封装到了ServiceRecord中,然后在调用startServiceInnerLocked方法。

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

int callingPid, int callingUid, boolean fgRequired, String callingPackage,

final int userId, boolean allowBackgroundActivityStarts)

throws TransactionTooLargeException {

...

//1

ServiceLookupResult res =

retrieveServiceLocked(service, null, resolvedType, callingPackage,

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

ServiceRecord r = res.record;

...

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

return cmp;

}

在上述代码标记1)解析参数service里面的数据,获取到对应的Service信息并且封装到ServiceRecord,每个Service都有一个ServiceRecord对象,都像Activity都有一个ActivityRecord。ServiceRecord继承Binder可以进程之间通讯。在调用startServiceInnerLocked后接着有调用了bringUpServiceLocked方法。

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

boolean whileRestarting, boolean permissionsReviewRequired)

throws TransactionTooLargeException {

//1

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

sendServiceArgsLocked(r, execInFg, false);

return null;

}

//2

final String procName = r.processName;

HostingRecord hostingRecord = new HostingRecord("service", r.instanceName);

ProcessRecord app;

if (!isolated) {

//3

app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);

//4

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

app.addPackage(r.appInfo.packageName, r.appInfo.longVersionCode, mAm.mProcessStats);

realStartServiceLocked(r, app, execInFg);

return null;

}

}

//5

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

if ((app = mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,

hostingRecord, false, isolated, false)) == null) {

bringDownServiceLocked(r);

return msg;

}

if (isolated) {

r.isolatedProc = app;

}

}

return null;

}

在上述代码标记

1)多次调用startService会多次调用onStartCommand 后面不在执行。

2)描述service需要在那个进程运行,AndroidManifest.xml设置的android:process属性来开启进程。

3)查询service对应的ProcessRecord类型的app。

4)发现有对应的进程都开始执行创建Service。

5)当没有发现有service运行的进程,都需要重新创建进程。

我们分析的是Service创建流程,接下来都应该执行方法realStartServiceLocked。

private final void realStartServiceLocked(ServiceRecord r,

ProcessRecord app, boolean execInFg) throws RemoteException {

//1

r.setProcess(app);

boolean created = false;

//2

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

mAm.compatibilityInfoForPackage(r.serviceInfo.applicationInfo),

app.getReportedProcState());

created = true;

//3

sendServiceArgsLocked(r, execInFg, true);

}

1)ServiceRecord绑定进程。

2)这里开始执行创建Service过程。

3)执行onStartCommand过程,接下来会分析。

我们现在分析创建Service过程,从代码可以看出,我们马上都要跨进程到ApplicationThread调用scheduleCreateService这个方法。此方法里面通过H继承Handler发送了CREATE_SERVICE消息到ActivityThread执行创建Service。

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);

}

最后代码执行到了ActivityThread的handleCreateService方法里面。

private void handleCreateService(CreateServiceData data) {

//创建对象

LoadedApk packageInfo = getPackageInfoNoCheck(

data.info.applicationInfo, data.compatInfo);

Service service = null;

try {

ClassLoader cl = packageInfo.getClassLoader();

//创建service对象

service = packageInfo.getAppFactory()

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

} catch (Exception e) {}

try {

//创建上下文

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

//关联service对象

context.setOuterContext(service);

//获取Application对象

Application app = packageInfo.makeApplication(false, mInstrumentation);

//关联上下文和Application对象

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

ActivityManager.getService());

service.onCreate();

//data.token都是ServiceRecord,它是binder对象,token与service建立映射关系存储在mServices的map中

mServices.put(data.token, service);

} catch (Exception e) {}

}

通过上述代码,我们可以看出创建了Service对象,创建上下文,然后service调用attach关联Application和上下文,最后调用创建onCreate。mServices是一个ArrayMap,用来存储service对象,ServiceRecord为key值。

接下来我们分析上面提到的sendServiceArgsLocked方法,调用了scheduleServiceArgs方法。

private final void sendServiceArgsLocked(ServiceRecord r, boolean execInFg,

boolean oomAdjusted) throws TransactionTooLargeException {

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

}

我们在ApplicationThread找了scheduleServiceArgs方法,里面通过H发送SERVICE_ARGS消息到ActivityThread,调用了handleServiceArgs方法。

private void handleServiceArgs(ServiceArgsData data) {

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

if (s != null) {

try {

if (!data.taskRemoved) {

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

} else {

s.onTaskRemoved(data.args);

res = Service.START_TASK_REMOVED_COMPLETE;

}

} catch (Exception e) {

}

}

}

获取ServiceRecord对应的Service,并且调用了onStartCommand方法。

到此我们把Service的启动流程都分析完了

bindService 过程

我们分析bindService过程。我们先来看一张序列图,如图所示:

d3d5f3673829

当我们在调用bindService后,接着调用了bindServiceCommon方法,

private boolean bindServiceCommon(Intent service, ServiceConnection conn, int flags,

String instanceName, Handler handler, Executor executor, UserHandle user) {

IServiceConnection sd;

if (mPackageInfo != null) {

// 1

if (executor != null) {

sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), executor, flags);

} else {

sd = mPackageInfo.getServiceDispatcher(conn, getOuterContext(), handler, flags);

}

}

try {

//此token都是AMS创建ActivityRecord创建

IBinder token = getActivityToken();

if (token == null && (flags & BIND_AUTO_CREATE) == 0 && mPackageInfo != null

&& mPackageInfo.getApplicationInfo().targetSdkVersion

< Build.VERSION_CODES.ICE_CREAM_SANDWICH) {

flags |= BIND_WAIVE_PRIORITY;

}

service.prepareToLeaveProcess(this);

int res = ActivityManager.getService().bindIsolatedService(

mMainThread.getApplicationThread(), getActivityToken(), service,

service.resolveTypeIfNeeded(getContentResolver()),

sd, flags, instanceName, getOpPackageName(), user.getIdentifier());

return res != 0;

} catch (RemoteException e) {

throw e.rethrowFromSystemServer();

}

}

private IServiceConnection getServiceDispatcherCommon(ServiceConnection c,

Context context, Handler handler, Executor executor, int flags) {

synchronized (mServices) {

ServiceDispatcher sd = null;

//根据启动者的context获取arrayMap

ArrayMap map = mServices.get(context);

if (map != null) {

sd = map.get(c);

}

if (sd == null) {

//创建ServiceDispatcher对象,此类是ServiceConnection和InnerConnection桥梁,

if (executor != null) {

sd = new ServiceDispatcher(c, context, executor, flags);

} else {

sd = new ServiceDispatcher(c, context, handler, flags);

}

if (map == null) {

map = new ArrayMap<>();

mServices.put(context, map);

}

//ServiceConnection与ServiceDispatcher建立映射关系

map.put(c, sd);

} else {

sd.validate(context, handler, executor);

}

return sd.getIServiceConnection();

}

}

在标记1)处创建IServiceConnection对象,调用getServiceDispatcherCommon方法作用是将ServiceConnection对象封装成IServiceConnection类型的sd引用,IServiceConnection类实现了Binder机制,这样的封装都是为了支持跨进程。当我们Service绑定成功后会回调ServiceConnection这个类的方法,此类无法跨进程使用,所以必须封装成支持跨进程的IServiceConnection。我们继续调用AMS的bindIsolatedService方法,然后调用了mServices(提到过的ActiveServices)的bindServiceLocked方法。

int bindServiceLocked(IApplicationThread caller, IBinder token, Intent service,

String resolvedType, final IServiceConnection connection, int flags,

String instanceName, String callingPackage, final int userId)

throws TransactionTooLargeException {

//创建ServiceRecord对象,这个类继承Binder

ServiceLookupResult res =

retrieveServiceLocked(service, instanceName, resolvedType, callingPackage,

Binder.getCallingPid(), Binder.getCallingUid(), userId, true,

callerFg, isBindExternal, allowInstant);

ServiceRecord s = res.record;

try {

//1

AppBindRecord b = s.retrieveAppBindingLocked(service, callerApp);

//2

ConnectionRecord c = new ConnectionRecord(b, activity,

connection, flags, clientLabel, clientIntent,

callerApp.uid, callerApp.processName, callingPackage);

if ((flags&Context.BIND_AUTO_CREATE) != 0) {

s.lastActivity = SystemClock.uptimeMillis();

//3

if (bringUpServiceLocked(s, service.getFlags(), callerFg, false,

permissionsReviewRequired) != null) {

return 0;

}

}

if (s.app != null && b.intent.received) {

try {

c.conn.connected(s.name, b.intent.binder, false);

} catch (Exception e) {

}

if (b.intent.apps.size() == 1 && b.intent.doRebind) {

//4

requestServiceBindingLocked(s, b.intent, callerFg, true);

}

} else if (!b.intent.requested) {

//5

requestServiceBindingLocked(s, b.intent, callerFg, false);

}

} finally {

Binder.restoreCallingIdentity(origId);

}

return 1;

}

1)应用进程通过Intent来绑定Service,AppBindRecord是Service和应用程序进程桥梁。

2)ConnectionRecord 用于描述应用进程和Service建立一次通信。

3)这都是我们创建Service的过程,创建流程已经写过。

4)首先设置onUnbind返回值true,当我们startService--bindService--unBindService--bindService都会调用onRebind。

5)我们第一次调用bindService都走的是第五步。

我们接着看requestServiceBindingLocked方法,又走到ApplicationThread的scheduleBindService方法。

private final boolean requestServiceBindingLocked(ServiceRecord r, IntentBindRecord i,

boolean execInFg, boolean rebind) throws TransactionTooLargeException {

if ((!i.requested || rebind) && i.apps.size() > 0) {

try {

r.app.thread.scheduleBindService(r, i.intent.getIntent(), rebind,

r.app.getReportedProcState());

if (!rebind) {

i.requested = true;

}

i.hasBound = true;

i.doRebind = false;

} catch (TransactionTooLargeException e) {

} catch (RemoteException e) {

}

}

return true;

}

通过H发送BIND_SERVICE到主线程管理类ActivityThread,然后执行handleBindService这个方法。

private void handleBindService(BindServiceData data) {

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

if (s != null) {

try {

data.intent.setExtrasClassLoader(s.getClassLoader());

data.intent.prepareToEnterProcess();

try {

//1

if (!data.rebind) {

IBinder binder = s.onBind(data.intent);

ActivityManager.getService().publishService(

data.token, data.intent, binder);

} else {

//2

s.onRebind(data.intent);

ActivityManager.getService().serviceDoneExecuting(

data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);

}

} catch (RemoteException ex) {

throw ex.rethrowFromSystemServer();

}

} catch (Exception e) {

}

}

}

1)在bindServiceLocked方法提到的走的第5步,调用绑定onBind方法,并且再次调用AMS的publishService方法中去。

2)在bindServiceLocked方法提到的走的第4步,解绑后的重新绑定调用onRebind方法。

接下来我们再去看看publishService方法,调用了ActiveServices的publishServiceLocked方法。

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {

try {

if (r != null) {

Intent.FilterComparison filter

= new Intent.FilterComparison(intent);

IntentBindRecord b = r.bindings.get(filter);

if (b != null && !b.received) {

b.binder = service;

b.requested = true;

b.received = true;

ArrayMap> connections = r.getConnections();

for (int conni = connections.size() - 1; conni >= 0; conni--) {

ArrayList clist = connections.valueAt(conni);

for (int i=0; i

ConnectionRecord c = clist.get(i);

if (!filter.equals(c.binding.intent.intent)) {

continue;

}

try {

c.conn.connected(r.name, service, false);

} catch (Exception e) {

}

}

}

}

}

} finally {

Binder.restoreCallingIdentity(origId);

}

}

走到这里都明白了,这里是准备bind回调,connected方法跨进程调用了这个类IServiceConnection的connected,然后调用了ServiceDispatcher的connected方法

//ServiceDispatcher.java

public void connected(ComponentName name, IBinder service, boolean dead) {

if (mActivityExecutor != null) {

mActivityExecutor.execute(new RunConnection(name, service, 0, dead));

} else if (mActivityThread != null) {

mActivityThread.post(new RunConnection(name, service, 0, dead));

} else {

doConnected(name, service, dead);

}

}

private final class RunConnection implements Runnable {

public void run() {

if (mCommand == 0) {

doConnected(mName, mService, mDead);

} else if (mCommand == 1) {

doDeath(mName, mService);

}

}

}

public void doConnected(ComponentName name, IBinder service, boolean dead) {

if (service != null) {

mConnection.onServiceConnected(name, service);

} else {

mConnection.onNullBinding(name);

}

}

上述代码看出最终调用了ServiceConnection的onServiceConnected方法。

上面都是所有分析bindService的过程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值