前言
本文假设你已经了解了android中Binder相关的机制,如果你还未了解相关知识,就没必要阅读本文了。
正文
我们直接看ContextImp相关代码
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
private ComponentName startServiceCommon(Intent service, UserHandle user) {
try {
...
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service, service.resolveTypeIfNeeded(
getContentResolver()), getOpPackageName(), user.getIdentifier());
...
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
看线ActivityManagerNative相关代码
static public IActivityManager getDefault() {
return gDefault.get();
}
...
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
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;
}
};
...
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
综上我们可以知道,ActivityManagerNative.getDefault().startServices实际上是调用了ActivityMangerProxy对象的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;
}
mRemote实际上是
IBinder b = ServiceManager.getService("activity");
的返回值,也就一个IBinder对象,它实际上是ActivityMangerService的一个引用,或者叫句柄。
我们看下AMS对应的这个指令的处理方式,搜了一下发现AMS中没有相关代码,我们去AMS的父类AMN中看下,我们看到
case START_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
String callingPackage = data.readString();
int userId = data.readInt();
ComponentName cn = startService(app, service, resolvedType, callingPackage, userId);
reply.writeNoException();
ComponentName.writeToParcel(cn, reply);
return true;
}
AMN中取出了参数后,交给startService方法去处理,我们看下AMS的startService方法
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, String callingPackage, int userId)
throws TransactionTooLargeException {
...
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;
}
}
我们看下关键代码startServiceLocked,mServices是ActiveService的一个实例
这个方法创建了一个ServiceRecord对象,又做了一些其他事情,但是有一行非常关键的代码
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {
....
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
...
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
...
}
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
...
ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (app != null && app.thread != null) {//要启动的service的进程已经存在
realStartServiceLocked(r, app, execInFg);
}
...
//如果进程不存在,那么先创建目标进程,并把要启动的service加入到mPendingServices中
if (app == null && !permissionsReviewRequired) {
if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags,
"service", 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;
}
}
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
}
重点看下bringUpServiceLocked函数,如果service所在进程已经存在了,那么直接调用realStartServiceLocked,否则的话,先拉起目标进程,并把目标service存进Pending队列中。我们看下realStartServiceLocked这个函数
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
...
app.thread.scheduleCreateService(r, r.serviceInfo,
mAm.compatibilityInfoForPackageLocked(r.serviceInfo.applicationInfo),
app.repProcState);
...
}
其中app是ProcessRecord对象,成员变量thread是IApplicationThread对象,那根据Binder原理,我们知道,thread实际上是一个ApplicationThreadProxy的一个实例。我们看下对应的方法
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();
}
我们看到这个方法实际上通过RPC发送指令SCHEDULE_CREATE_SERVICE_TRANSACTION,接收者应该是ApplicationThread,由于ApplicationThread的父类是ATN,我们去里面看下相应的代码
case SCHEDULE_CREATE_SERVICE_TRANSACTION: {
data.enforceInterface(IApplicationThread.descriptor);
IBinder token = data.readStrongBinder();
ServiceInfo info = ServiceInfo.CREATOR.createFromParcel(data);
CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data);
int processState = data.readInt();
scheduleCreateService(token, info, compatInfo, processState);
return true;
}
我们看到它调用了函数 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);
}
我们看到,ApplicationThread组织了一些参数,交给了ActivityThread去处理了,我们再看下ActivityThread是如何处理的。
case CREATE_SERVICE:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, ("serviceCreate: " + String.valueOf(msg.obj)));
handleCreateService((CreateServiceData)msg.obj);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
我们把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 {
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);
ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
context.setOuterContext(service);
Application app = packageInfo.makeApplication(false, mInstrumentation);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManagerNative.getDefault().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);
}
}
}
通过newInstance创建了一个Service对象,有一句代码比较重要,是
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, SERVICE_DONE_EXECUTING_ANON, 0, 0);
我们知道getDefault返回的是一个AMP对象,它的serviceDoneExecuting方法发出这样一条指令
mRemote.transact(SERVICE_DONE_EXECUTING_TRANSACTION, data, reply, IBinder.FLAG_ONEWAY);
对应的AMN中接收到指令后处理方式为
serviceDoneExecuting(token, type, startId, res);
在AMS中我们看下这个方法
public void serviceDoneExecuting(IBinder token, int type, int startId, int res) {
synchronized(this) {
if (!(token instanceof ServiceRecord)) {
Slog.e(TAG, "serviceDoneExecuting: Invalid service token=" + token);
throw new IllegalArgumentException("Invalid service token");
}
mServices.serviceDoneExecutingLocked((ServiceRecord)token, type, startId, res);
}
}
实际上就是把这个service加到了相应的队列里。
以上就是startService的时候,如果service所在进程存在,切是service第一次create的情况。
如果启动这个service的时候,该service所在进程不存在,那么AMS先创建进程然后创建Application,并且把该service对应的ServiceRecord存到Pending队列里,application创建后会attach到AMS,此时AMS找到对应的Service后,再走realStartServiceLocked流程。