之前写过一篇从AIDL看Android跨进程通信 从Java层次去分析AIDL运行的原理,当时主要是为了学习Binder机制而写的,但是Binder机制比较复杂,打算过段时间单独的写一篇来分析。本篇文章分析startService的启动过程,也会涉及到使用Binder机制来进行跨进程通信,但是不会分析Binder机制的细节。不过还是强烈建议大家学习Binder机制,至少要了解Binder的基本架构,Android经常使用Binder来进行跨进程通信。
在Android中启动Service和Activity统一由ActivityManagerService(简称AMS)管理,AMS在系统启动时,就已经在ServiceManager中注册了,存活于system_server进程中。先来了解一下ActivityManagerService相关的类:
从类图可以看到这是典型的Binder机制,如果使用过AIDL的话,对IBinder,IInterface应该很熟悉。IActivityManager继承自IInterface,是用来管理Activity和Service的接口。ActivityManagerProxy从名字可以看出其是代理,并且是AMS在普通应用进程中的代理,通过它可以使用AMS的功能。ActivityManagerNative则可以看做AMS和Binder之间的中介,这样AMS就可以通过它向客户端提供服务了。
一 :从客户进程启动Service
我们还是使用从AIDL看Android跨进程通信 中的例子,从MainActivity来调用startService,一步一步分析:
1.1 ContextWrapper.java
@Override
public ComponentName startService(Intent service) {
return mBase.startService(service);
}
这里的mBase实际是ContextImpl的实例,所以接着看
1.2 ContextImpl.java
/frameworks/base/core/java/android/app/ContextImpl.java
@Override
public ComponentName startService(Intent service) {
warnIfCallingFromSystemProcess();
return startServiceCommon(service, mUser);
}
...省略...
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());
if (cn != null) {
if (cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
} else if (cn.getPackageName().equals("!!")) {
throw new SecurityException(
"Unable to start service " + service
+ ": " + cn.getClassName());
}
}
return cn;
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
在startServiceCommon()方法中首先验证intent是否合法,然后重点看第11~13行。想要继续跟下去就得先搞清楚ActivityManagerNative.getDefault()
是个什么鬼。
1.3 ActivityManagerNative.java
/frameworks/base/core/java/android/app/ActivityManagerNative.java
/**
* Cast a Binder object into an activity manager interface, generating
* a proxy if needed.
*/
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);
}
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
...省略...
private static final Singleton gDefault = new Singleton() {
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;
}
};
第22行,将会回调Singleton的create()方法,对应28~38行代码,第29行通过ServiceManager.getService("activity")
可以获取一个IBinder,AMS在系统启动的时候已经在ServiceManager中注册过,这里我们只用知道通过这个IBinder对象(具体是BinderProxy对象)我们可以发起远程调用。通过第15行生成了一个ActivityManagerProxy并且将其作为单例保存起来,下次调用可以直接使用了。
![这里写图片描述]
上图也可以印证我们的分析。ActivityManagerNative.getDefault()
返回的是ActivityManagerProxy实例,那么1.2中将会调用ActivityManagerProxy.startService()方法。
1.4 ActivityManagerProxy.java
该类是在ActivityMangerNative中声明。
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;
}
第12行mRemote是在ActivityManagerProxy的构造方法中赋值的,还记得刚刚new ActivityManagerProxy时传入了一个IBinder(BinderProxy)吗?通过它的transact()方法像远端AMS发起请求。
二 system_server进程中AMS响应
根据Binder机制,ActivityManagerNative的onTransact()方法将会回调,因为这个方法比较长,我只截取了响应startService动作的代码。
2.1 ActivityManagerNative.java
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
...省略...
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;
}
...省略...
}
}
第9行,这里将要涉及到另外一个跨进程通信,主要是干什么的呢,我们知道MainActivity所在进程A通过IActivityManager接口可以调用AMS的服务,那么如果AMS想要访问进程A的服务该怎么办呢,通过这里的IApplicationThread接口可以做到。下面是相关类图:
和之前的IActivityManager类似,使用IApplicationThread也是基于Binder架构的,所以它们的结构都很像,所以这里的ApplicationThreadProxy就是A进程在AMS的一个Binder代理,通过它AMS就可以调用A进程的服务。
第14行startService()是IActivityManager接口的方法,因为ActivityManagerNative是一个抽象类,并且AMS继承了ActivityManagerNative,所以这里startService()的真正实现在ActivityManagerService中。
2.2 ActivityManagerService.java
/frameworks/base/services/core/java/com/android/server/am
@Override
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType, 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);
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;
}
}
重点看第21,22行
mServices.startServiceLocked(caller, service,resolvedType, callingPid, callingUid, callingPackage, userId);
mServices是ActiveServices的实例,所以将要执行ActiveServices的startServiceLocked()方法,一般带有Locked后缀的都是需要保证线程安全的。
2.3 ActiveServices.java
/frameworks/base/services/core/java/com/android/server/am
ComponentName startServiceLocked(IApplicationThread caller, Intent service, String resolvedType,
int callingPid, int callingUid, String callingPackage, final int userId)
throws TransactionTooLargeException {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "startService: " + service
+ " type=" + resolvedType + " args=" + service.getExtras());
final boolean callerFg;
if (caller != null) {
final ProcessRecord callerApp = mAm.getRecordForAppLocked(caller);
if (callerApp == null) {
throw new SecurityException(
"Unable to find app for caller " + caller
+ " (pid=" + Binder.getCallingPid()
+ ") when starting service " + service);
}
callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
} else {
callerFg = true;
}
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 r = res.record;
if (!mAm.mUserController.exists(r.userId)) {
Slog.w(TAG, "Trying to start service with non-existent user! " + r.userId);
return null;
}
if (!r.startRequested) {
final long token = Binder.clearCallingIdentity();
try {
// Before going further -- if this app is not allowed to run in the
// background, then at this point we aren't going to let it period.
final int allowed = mAm.checkAllowBackgroundLocked(
r.appInfo.uid, r.packageName, callingPid, true);
if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
Slog.w(TAG, "Background start not allowed: service "
+ service + " to " + r.name.flattenToShortString()
+ " from pid=" + callingPid + " uid=" + callingUid
+ " pkg=" + callingPackage);
return null;
}
} finally {
Binder.restoreCallingIdentity(token);
}
}
NeededUriGrants neededGrants = mAm.checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service, service.getFlags(), null, r.userId);
// If permissions need a review before any of the app components can run,
// we do not start the service and launch a review activity if the calling app
// is in the foreground passing it a pending intent to start the service when
// review is completed.
if (Build.PERMISSIONS_REVIEW_REQUIRED) {
if (!requestStartTargetPermissionsReviewIfNeededLocked(r, callingPackage,
callingUid, service, callerFg, userId)) {
return null;
}
}
if (unscheduleServiceRestartLocked(r, callingUid, false)) {
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "START SERVICE WHILE RESTART PENDING: " + r);
}
r.lastActivity = SystemClock.uptimeMillis();
r.startRequested = true;
r.delayedStop = false;
r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),
service, neededGrants));
final ServiceMap smap = getServiceMap(r.userId);
boolean addToStarting = false;
if (!callerFg && r.app == null
&& mAm.mUserController.hasStartedUserState(r.userId)) {
ProcessRecord proc = mAm.getProcessRecordLocked(r.processName, r.appInfo.uid, false);
if (proc == null || proc.curProcState > ActivityManager.PROCESS_STATE_RECEIVER) {
// If this is not coming from a foreground caller, then we may want
// to delay the start if there are already other background services
// that are starting. This is to avoid process start spam when lots
// of applications are all handling things like connectivity broadcasts.
// We only do this for cached processes, because otherwise an application
// can have assumptions about calling startService() for a service to run
// in its own process, and for that process to not be killed before the
// service is started. This is especially the case for receivers, which
// may start a service in onReceive() to do some additional work and have
// initialized some global state as part of that.
if (DEBUG_DELAYED_SERVICE) Slog.v(TAG_SERVICE, "Potential start delay of "
+ r + " in " + proc);
if (r.delayed) {
// This service is already scheduled for a delayed start; just leave
// it still waiting.
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Continuing to delay: " + r);
return r.name;
}
if (smap.mStartingBackground.size() >= mMaxStartingBackground) {
// Something else is starting, delay!
Slog.i(TAG_SERVICE, "Delaying start of: " + r);
smap.mDelayedStartList.add(r);
r.delayed = true;
return r.name;
}
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "Not delaying: " + r);
addToStarting = true;
} else if (proc.curProcState >= ActivityManager.PROCESS_STATE_SERVICE) {
// We slightly loosen when we will enqueue this new service as a background
// starting service we are waiting for, to also include processes that are
// currently running other services or receivers.
addToStarting = true;
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Not delaying, but counting as bg: " + r);
} else if (DEBUG_DELAYED_STARTS) {
StringBuilder sb = new StringBuilder(128);
sb.append("Not potential delay (state=").append(proc.curProcState)
.append(' ').append(proc.adjType);
String reason = proc.makeAdjReason();
if (reason != null) {
sb.append(' ');
sb.append(reason);
}
sb.append("): ");
sb.append(r.toString());
Slog.v(TAG_SERVICE, sb.toString());
}
} else if (DEBUG_DELAYED_STARTS) {
if (callerFg) {
Slog.v(TAG_SERVICE, "Not potential delay (callerFg=" + callerFg + " uid="
+ callingUid + " pid=" + callingPid + "): " + r);
} else if (r.app != null) {
Slog.v(TAG_SERVICE, "Not potential delay (cur app=" + r.app + "): " + r);
} else {
Slog.v(TAG_SERVICE,
"Not potential delay (user " + r.userId + " not started): " + r);
}
}
return startServiceInnerLocked(smap, service, r, callerFg, addToStarting);
}
这个方法比较长,为了方便分析,先把介绍一下方法的参数:
caller:IApplicationThread类型,这里具体是ApplicationThreadProxy类型,通过它可以和应用进程进行通信。
service:Intent类型,主要包含了将要启动service的信息
resolvedType:String 类型,这里为null
callingPid:发起call的进程的pid
callingUid:发起call进程的uid
callingPackage:发起call进程的package信息
userId:这里为0
如图:
第22、23行代码主要是检索服务信息,可以获取到ServiceRecord和相应的权限信息。84~145行主要是对非前台进程的调度。最终会调用第147行startServiceInnerLocked()方法。
ComponentName startServiceInnerLocked(ServiceMap smap, Intent service, ServiceRecord r,
boolean callerFg, boolean addToStarting) throws TransactionTooLargeException {
ServiceState stracker = r.getTracker();
if (stracker != null) {
stracker.setStarted(true, mAm.mProcessStats.getMemFactorLocked(), r.lastActivity);
}
r.callStart = false;
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
if (error != null) {
return new ComponentName("!!", error);
}
if (r.startRequested && addToStarting) {
boolean first = smap.mStartingBackground.size() == 0;
smap.mStartingBackground.add(r);
r.startingBgTimeout = SystemClock.uptimeMillis() + BG_START_TIMEOUT;
if (DEBUG_DELAYED_SERVICE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r, here);
} else if (DEBUG_DELAYED_STARTS) {
Slog.v(TAG_SERVICE, "Starting background (first=" + first + "): " + r);
}
if (first) {
smap.rescheduleDelayedStarts();
}
} else if (callerFg) {
smap.ensureNotStartingBackground(r);
}
return r.name;
}
第11行代码会调用bringUpServiceLocked(),从名字可以看出,这里应该会生成目标Service,并且会判断目标Service的进程是否存在,如果存在则直接去生成,如果不存在,则从Zygote fork一个进程,然后在生成相应的Service实例。
private String bringUpServiceLocked(ServiceRecord r, int intentFlags, boolean execInFg,
boolean whileRestarting, boolean permissionsReviewRequired)
throws TransactionTooLargeException {
//Slog.i(TAG, "Bring up service:");
//r.dump(" ");
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, execInFg, false);
return null;
}
if (!whileRestarting && r.restartDelay > 0) {
// If waiting for a restart, then do nothing.
return null;
}
if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "Bringing up " + r + " " + r.intent);
// We are now bringing the service up, so no longer in the
// restarting state.
if (mRestartingServices.remove(r)) {
r.resetRestartCounter();
clearRestartingIfNeededLocked(r);
}
// Make sure this service is no longer considered delayed, we are starting it now.
if (r.delayed) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (bring up): " + r);
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
// Make sure that the user who owns this service is started. If not,
// we don't want to allow it to run.
if (!mAm.mUserController.hasStartedUserState(r.userId)) {
String msg = "Unable to launch app "
+ r.appInfo.packageName + "/"
+ r.appInfo.uid + " for service "
+ r.intent.getIntent() + ": user " + r.userId + " is stopped";
Slog.w(TAG, msg);
bringDownServiceLocked(r);
return msg;
}
// Service is now being launched, its package can't be stopped.
try {
AppGlobals.getPackageManager().setPackageStoppedState(
r.packageName, false, r.userId);
} catch (RemoteException e) {
} catch (IllegalArgumentException e) {
Slog.w(TAG, "Failed trying to unstop package "
+ r.packageName + ": " + e);
}
final boolean isolated = (r.serviceInfo.flags&ServiceInfo.FLAG_ISOLATED_PROCESS) != 0;
final String procName = r.processName;
ProcessRecord app;
if (!isolated) {
app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false);
if (DEBUG_MU) Slog.v(TAG_MU, "bringUpServiceLocked: appInfo.uid=" + r.appInfo.uid
+ " app=" + app);
if (app != null && app.thread != null) {
try {
app.addPackage(r.appInfo.packageName, r.appInfo.versionCode, mAm.mProcessStats);
realStartServiceLocked(r, app, execInFg);
return null;
} catch (TransactionTooLargeException e) {
throw e;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting service " + r.shortName, e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
} else {
// If this service runs in an isolated process, then each time
// we call startProcessLocked() we will get a new isolated
// process, starting another process if we are currently waiting
// for a previous process to come up. To deal with this, we store
// in the service any current isolated process it is running in or
// waiting to have come up.
app = r.isolatedProc;
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
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);
}
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (in bring up): " + r);
stopServiceLocked(r);
}
}
return null;
}
程序会运行到第60行会获取目标进程的信息,63行会判断进程是否存在,如果存在直接会运行第66行realStartServiceLocked(从方法名可以看出真正的启动Service应该就在这个方法中)方法,并返回。如果不存在则会执行到第89行的mAm.startProcessLocked方法,这里的mAm是AMS的实例,所以程序会回到AMS的startProcessLocked方法。通过分析我们验证了之前的判断。并且还可以预测,将来在目标进程生成之后,还是会调用realStartServiceLocked方法去生成Service。
三 AMS通知Zygote孵化目标进程
根据之前的分析,到这一步,AMS将会通知Zygote去孵化目标进程。这个过程也是一个跨进程的通信,但是并不是Binder去实现的,而是使用的Socket,Zygote孵化进程将来也会去写一篇文章去分析,这里只用知道通过其生成了一个目标进程。目标进程又会通过Binder向system_server进程发起attachApplication请求。那么此时又会回调到AMS的attachApplication方法。
四 AMS通知目标进程创建并启动Service
4.1 ActivityManagerService.java
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
基于第三节的分析,在Zygote孵化目标进程成功后,目标进程会通过Binder请求调用attachApplication服务,所以用调用上边的代码。第6行代码会接着调用attachApplicationLocked(之前已经说过方法名带Locked一般表示线程安全)方法,由于这个方法比较长,由于篇幅限制,我只截取最重要的一部分
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
...省略...
boolean badApp = false;
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
// Find any services that should be running in this process...
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown starting services in " + app, e);
badApp = true;
}
}
...省略...
}
第22行 mServices.attachApplicationLocked(),mServices我们已经遇到过了,就是ActiveServices,那么又会执行其对应的方法。
4.2 ActiveServices.java
boolean attachApplicationLocked(ProcessRecord proc, String processName)
throws RemoteException {
boolean didSomething = false;
// Collect any services that are waiting for this process to come up.
if (mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
for (int i=0; isize(); i++) {
sr = mPendingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mPendingServices.remove(i);
i--;
proc.addPackage(sr.appInfo.packageName, sr.appInfo.versionCode,
mAm.mProcessStats);
realStartServiceLocked(sr, proc, sr.createdFromFg);
didSomething = true;
if (!isServiceNeeded(sr, false, false)) {
// We were waiting for this service to start, but it is actually no
// longer needed. This could happen because bringDownServiceIfNeeded
// won't bring down a service that is pending... so now the pending
// is done, so let's drop it.
bringDownServiceLocked(sr);
}
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortName, e);
throw e;
}
}
// Also, if there are any services that are waiting to restart and
// would run in this process, now is a good time to start them. It would
// be weird to bring up the process but arbitrarily not let the services
// run at this point just because their restart time hasn't come up.
if (mRestartingServices.size() > 0) {
ServiceRecord sr;
for (int i=0; isize(); i++) {
sr = mRestartingServices.get(i);
if (proc != sr.isolatedProc && (proc.uid != sr.appInfo.uid
|| !processName.equals(sr.processName))) {
continue;
}
mAm.mHandler.removeCallbacks(sr.restarter);
mAm.mHandler.post(sr.restarter);
}
}
return didSomething;
}
第19行realStartServiceLocked(sr, proc, sr.createdFromFg);还记得么,在第二节最后,我们分析了孵化目标进程后,最后还是会执行realStartServiceLocked,在这里得到了印证。
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app, boolean execInFg) throws RemoteException {
if (app.thread == null) {
throw new RemoteException();
}
if (DEBUG_MU)
Slog.v(TAG_MU, "realStartServiceLocked, ServiceRecord.uid = " + r.appInfo.uid
+ ", ProcessRecord.uid = " + app.uid);
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 {
if (LOG_SERVICE_START_STOP) {
String nameTerm;
int lastPeriod = r.shortName.lastIndexOf('.');
nameTerm = lastPeriod >= 0 ? r.shortName.substring(lastPeriod) : r.shortName;
EventLogTags.writeAmCreateService(
r.userId, System.identityHashCode(r), nameTerm, r.app.uid, r.app.pid);
}
synchronized (r.stats.getBatteryStats()) {
r.stats.startLaunchedLocked();
}
mAm.notifyPackageUse(r.serviceInfo.packageName,
PackageManager.NOTIFY_PACKAGE_USE_SERVICE);
app.forceProcessStateUpTo(ActivityManager.PROCESS_STATE_SERVICE);
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);
}
}
}
if (r.whitelistManager) {
app.whitelistManager = true;
}
requestServiceBindingsLocked(r, execInFg);
updateServiceClientActivitiesLocked(app, null, true);
// If the service is in the started state, and there are no
// pending arguments, then fake up one so its onStartCommand() will
// be called.
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);
if (r.delayed) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE, "REM FR DELAY LIST (new proc): " + r);
getServiceMap(r.userId).mDelayedStartList.remove(r);
r.delayed = false;
}
if (r.delayedStop) {
// Oh and hey we've already been asked to stop!
r.delayedStop = false;
if (r.startRequested) {
if (DEBUG_DELAYED_STARTS) Slog.v(TAG_SERVICE,
"Applying delayed stop (from start): " + r);
stopServiceLocked(r);
}
}
}
这里主要看32~34行 app.thread.scheduleCreateService()其中app.thread是IApplicationThread,可见这里是system_server进程需要调用目标进程scheduleCreateService,那么在第二节分析,其实IApplicationThread的具体实现也就是ApplicationThreadProxy,通过它发起Binder通信。
4.3 ApplicationThreadProxy.java
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();
}
第10~11行,发起远程Binder通信,标识为SCHEDULE_CREATE_SERVICE_TRANSACTION,通过binder机制,最终将在ApplicationThreadNative的onTransact中响应。
4.4 ApplicationThreadNative.java
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException {
switch (code) {
......
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;
}
......
}
return super.onTransact(code, data, reply, flags);
}
第12行scheduleCreateService方法,真正的实现是在ApplicationThread,原因是ApplicationThreadNative是个抽象类,ApplicationThread是其实现类。
4.5 ActivityThread::ApplicationThread.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);
}
第9行,sendMessage()发送了一个tag为H.CREATE_SERVICE的消息,这里H类继承自Handler,是ActivityThread中的内部类,主要用于处理各种消息
4.6 ActivityThread::H.java
public void handleMessage(Message msg) {
switch (msg.what) {
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;
}
}
第5行,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);
}
}
}
第6~7行获取apk的信息,包括路径,包名。
第10~11行通过ClassLoader将对应名字的Service加载到内存中来,这样就获取到了Service的对象。
第23~24行获取ContextImpl对象。
第26行获取Application对象。
第27~28行通过attach方法将contextImpl,Application与Service对象关联起来。
第29行调用onCreate方法,一般我们在使用Service时会重写该方法。这里Service的生命周期就开始了。
第32~33行通过IActivityManager通知AMS 我们需要的Service已经启动了。
上述整个启动过程的时序图: