主目录见:Android高级进阶知识(这是总目录索引)
文章之前应一位网友所托,推荐一下他的公众号,我也是关注了下,里面文章还是有质量的,公众号名字是:我就是马云飞,大家有兴趣可以关注哈。
今天这一篇同样的是为了讲插件化框架做的铺垫,我们知道,插件化框架的开发对程序员对framework知识的熟悉程度非常有要求,同时又要求大家广而采纳众人的思想和自己多思考。今天我们讲的这个startService的流程应该是不可或缺的一部分。首先呢我们来上一张图来理理整体流程:
我这里简略说下流程,首先服务会从
ContextImpl
调用startService
方法到AMS,然后AMS调用到bringUpServiceLocked
方法的时候会判断是否启动的服务在不同的进程中,如果是则调用startProcessLocked
创建一个新的进程,然后调用realStartServiceLocked
跨进程调用ActivityThread中的hanleCreateService
创建一个新的目标服务并回调目标服务的onCreate方法,最后AMS调用sendServiceARgsLocked
跨进程调用ActivityThread中的handleServiceArgs
方法回调目标service的onStartCommand
方法。
一.目标
今天我们的目标也是非常明确,毕竟无目的地分析源码是非常痛苦的一个过程:
1.了解startService的整体流程;
2.为插件化做准备工作;
二.源码分析
我们知道,服务的启动有两种方式:bindService()和startService()两种,bindService
这种方式其实我们在讲从framework分析AIDL生成文件这篇文章的时候已经讲过了,我们今天这里就是讲startService
这种方式,我们在Activity
中调用startService()
,其实是调用了ContextWrapper
里面的方法:
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);//这里的mBase就是ContextImpl类
}
这个地方其实是应用了一个装饰设计模式,如果对这个模式不是很清楚可以看Decorator装饰模式,ContextImpl这里代表的装饰模式里面的具体组件角色,这样我们就可以看到ContextImpl中的startService:
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();//如果是系统进程直接调用的startService方法就会报错
return startServiceCommon(service, mUser);
}
这里我们直接看到startServiceCommon方法:
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
validateServiceIntent(service);
service.prepareToLeaveProcess(this);
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());
..........
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
我们如果有看到上一篇startActivity的源码分析的话,那么应该非常熟悉ActivityManagerNative#getDefault()
得到的是远程AMS的ActivityManagerProxy
,这里startService
方法就是ActivityManagerProxy
类中的,我们首先看下ActivityManagerNative
类:
public abstract class ActivityManagerNative extends Binder implements IActivityManager
接着我们看他的getDefault方法:
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton gDefault = new Singleton() {
protected IActivityManager create() {
//这里获取到的其实是ActivityManagerService这个服务,在SystemServer启动的时候,就会把ActivityManagerService 注册到ServiceManager中来
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
这里其实就是一个单例的设计模式,获取到服务对象的IBinder
,并且调用asInterface()
方法把这个IBinder
转换成IActivityManager
返回了。这应该熟悉AIDL的人知道,这里的asInterface其实返回的是ActivityManagerProxy
对象。这样我们看ActivityManagerProxy
的startService方法:
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeString(callingPackage);
data.writeInt(userId);
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
ComponentName res = ComponentName.readFromParcel(reply);
data.recycle();
reply.recycle();
return res;
}
这里的service
就是Intent
实例,它里面指定了要启动服务的名称。 参数caller
是一个IApplicationThread
实例,它是一个在主进程创建的一个Binder
对象。在Android应用程序中,每一个进程都用一个ActivityThread
实例来表示,而在ActivityThread
类中,有一个成员变量mAppThread,它是一个ApplicationThread
实例,实现了IApplicationThread
接口,它的作用是用来辅助ActivityThread
类来执行一些操作,这个我们在后面会看到它是如何用来启动服务的。
参数resolvedType
是一个字符串,表示服务这个Intent的MIME类型,在解析Intent的时候会用到,这里我们没有指定所以为null。
ActivityManagerProxy
类的startService
函数把这三个参数写入到data本地变量去,接着通过mRemote.transact
函数进入到Binder
驱动程序,然后Binder
驱动程序唤醒正在等待Client请求的ActivityManagerService
进程,最后进入到ActivityManagerService
的startService函数中:
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {
enforceNotIsolatedCaller("startService");
.......
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = mServices.startServiceLocked(caller, service,
resolvedType, callingPid, callingUid, callingPackage, userId);
Binder.restoreCallingIdentity(origId);
return res;
}
}
这里的参数caller、service和resolvedType分别对应ActivityManagerProxy#startService
传进来的三个参数。然后程序会交给mServices
这个对象即ActiveServices
类的实例,这个类是后面版本出来的,前面旧版本并没有这个类(这次的分析是基于android-25的),所以我们看到ActiveServices
的startServiceLocked
方法:
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {
......
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPackage,
callingPid, callingUid, userId, true, callerFg, false);
......
ServiceRecord r = res.record;
......
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
startServiceInnerLocked调用了 bringUpServiceLocked(),bringUpServiceLocked()内部调用了realStartServiceLocked()(当然这个地方如果我们配置了android:process属性值的话,那么程序会创建一个ActivityThread进程,在Android应用程序中,每一个进程对应一个ActivityThread实例,所以,这个函数会创建一个thread实例,然后调用ActivityThread.attach函数进一步处理),我们这里不考虑启动的服务在新进程中,我们看realStartServiceLocked()方法:
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
.....
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
final boolean newService = app.services.add(r);
bumpServiceExecutingLocked(r, execInFg, "create");
mAm.updateLruProcessLocked(app, false, null);
mAm.updateOomAdjLocked();
boolean created = false;
try {
........
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
r.postNotification();
created = true;
} catch (DeadObjectException e) {
......
} finally {
......
}
if (r.whitelistManager) {
app.whitelistManager = true;
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
null, null));
}
sendServiceArgsLocked(r, execInFg, true);
.......
}
我们看到程序里面关键有一句app.thread.scheduleCreateService,这里的app
是一个ProcessRecord
实例,app.thread是ApplicationThreadProxy
对象,我们知道客户端与远程服务进程的AIDL是双向通信的关系,ActivityManagerProxy
是客户端用来与远程服务进程通讯的,ApplicationThreadProxy
是远程服务进程用来与客户端通讯的,所以这里我们看到ApplicationThreadProxy
的scheduleCreateService
方法:
public final void scheduleCreateService(IBinder token, ServiceInfo info,
CompatibilityInfo compatInfo, int processState) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
data.writeStrongBinder(token);
info.writeToParcel(data, 0);
compatInfo.writeToParcel(data, 0);
data.writeInt(processState);
try {
mRemote.transact(SCHEDULE_CREATE_SERVICE_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
} catch (TransactionTooLargeException e) {
Log.e("CREATE_SERVICE", "Binder failure starting service; service=" + info);
throw e;
}
data.recycle();
}
这里通过Binder驱动程序回到新进程的ApplicationThread对象中去执行scheduleCreateService方法:
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);
}
发送一个消息,这个消息都是由H类处理的,H
类就是系统Hander
,专门处理系统请求的,比如一些Activity
的生命周期等全在这里面。这个H
对象是在应用进程的主线程中创建的,所以最终的结果是把创建 Service
的消息传到了主线程,因此Service
是运行在主线程中的:
private final class H extends Handler {
......
public void handleMessage(Message msg) {
......
switch (msg.what) {
......
case CREATE_SERVICE:
handleCreateService((CreateServiceData)msg.obj);
break;
......
}
......
}
......
}
这里要处理的消息是CREATE_SERVICE
,它调用ActivityThread
类的handleCreateService
成员方法进一步处理:
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();
LoadedApk packageInfo = getPackageInfoNoCheck(
data.info.applicationInfo, data.compatInfo);
Service service = null;
try {
//packageInfo是LoadedApk对象,包含了apk的信息,通过类加载器加载service类,然后反射创建
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
......
}
try {
if (localLOGV) Slog.v(TAG, "Creating service " + data.info.name);
//创建ContextImpl对象
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
//创建Application对象
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
//回调要启动的service中的onCreate方法
service.onCreate();
mServices.put(data.token, service);
try {
//通知远程服务,service创建完成
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} catch (Exception e) {
......
}
}
到这一步service的创建就已经完成,那么service的其他回调方法的调用时机是在什么时候呢?在realStartServiceLocked()
方法中调用了scheduleCreateService
之后,在方法最后会调用sendServiceArgsLocked()
方法,和scheduleCreateService
类似地,最终也会调用到H类中的handleMessage:
case SERVICE_ARGS:
handleServiceArgs((ServiceArgsData)msg.obj);
break;
然后会调用ActivityThread类中的handleServiceArgs方法:
private void handleServiceArgs(ServiceArgsData data) {
Service s = mServices.get(data.token);
if (s != null) {
try {
......
int res;
if (!data.taskRemoved) {
//回调目标service的onStartCommand方法
res = s.onStartCommand(data.args, data.flags, data.startId);
} else {
s.onTaskRemoved(data.args);
res = Service.START_TASK_REMOVED_COMPLETE;
}
QueuedWork.waitToFinish();
try {
//同样地通知远程服务service启动完成
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_START, data.startId, res);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
ensureJitEnabled();
} catch (Exception e) {
.......
}
}
}
这里的onCreate和onStartCommand方法的回调流程大致一样,大家可以自己走下流程应该就很清楚了,从流程上看,其实启动服务不是非常复杂,如果有不明白的,大家可以对照前面画的流程图看看。
总结:启动服务的流程相对而言不会太难,我们这里只要明白整体的流程,到时讲插件化框架的时候,如果有必要会把某个部分拿出来讲解清楚,希望大家发现错误能即时提出哈,共同进步。