目录
1、Service在客户端的启动入口
2、Service启动在AMS的处理
3、Service在新进程中的启动
4、Service与AMS的关系再续
上一篇文章中我们了解了Service在新进程中启动的大致流程,同时认识了与客户端进程交互的接口IApplicationThread以及与AMS交互的接口IActivityManager,客户端进程与AMS则借助于Binder驱动实现了二者之间的通信,这一篇文章我们将深入源码分析startService是如何一步步启动新服务的,源码同样基于Android2.3.7。
首先放上上一篇的流程概览图,方便源码分析。
1、Service在客户端的启动入口
该步骤对应流程图中的第一步,通过调用Context.startService启动服务,该动作最终会走到ContextImpl的startService函数中,代码如下:
//frameworks\base\core\java\android\app\Contextlmpl.java
@Override
public ComponentName startService(Intent service) {
try {
ComponentName cn = ActivityManagerNative.getDefault().startService(
mMainThread.getApplicationThread(), service,
service.resolveTypeIfNeeded(getContentResolver()));
if (cn != null && cn.getPackageName().equals("!")) {
throw new SecurityException(
"Not allowed to start service " + service
+ " without permission " + cn.getClassName());
}
return cn;
} catch (RemoteException e) {
return null;
}
}
通过调用ActivityManagerNative.getDefault()来启动服务,ActivityManagerNative.getDefault()返回的是AMS的一个代理对象ActivityManagerProxy,上一篇我们说过ActivityManagerProxy实现了IActivityManager接口,这里通过该代理把请求转发到AMS去,代码如下:
//frameworks\base\core\java\android\app\ActivityManagerNative.java
class ActivityManagerProxy implements IActivityManager
{
public ActivityManagerProxy(IBinder remote)
{
mRemote = remote;
}
public IBinder asBinder()
{
return mRemote;
}
//...
//启动服务
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType) 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);
mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
ComponentName res = ComponentName.readFromParcel(reply);
data.recycle();
reply.recycle();
return res;
}
//停止服务
public int stopService(IApplicationThread caller, Intent service,
String resolvedType) 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);
mRemote.transact(STOP_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
reply.recycle();
data.recycle();
return res;
}
public boolean stopServiceToken(ComponentName className, IBinder token,
int startId) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
ComponentName.writeToParcel(className, data);
data.writeStrongBinder(token);
data.writeInt(startId);
mRemote.transact(STOP_SERVICE_TOKEN_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
data.recycle();
reply.recycle();
return res;
}
public void setServiceForeground(ComponentName className, IBinder token,
int id, Notification notification, boolean removeNotification) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
ComponentName.writeToParcel(className, data);
data.writeStrongBinder(token);
data.writeInt(id);
if (notification != null) {
data.writeInt(1);
notification.writeToParcel(data, 0);
} else {
data.writeInt(0);
}
data.writeInt(removeNotification ? 1 : 0);
mRemote.transact(SET_SERVICE_FOREGROUND_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
//绑定服务
public int bindService(IApplicationThread caller, IBinder token,
Intent service, String resolvedType, IServiceConnection connection,
int flags) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(caller != null ? caller.asBinder() : null);
data.writeStrongBinder(token);
service.writeToParcel(data, 0);
data.writeString(resolvedType);
data.writeStrongBinder(connection.asBinder());
data.writeInt(flags);
mRemote.transact(BIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
int res = reply.readInt();
data.recycle();
reply.recycle();
return res;
}
//解绑服务
public boolean unbindService(IServiceConnection connection) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(connection.asBinder());
mRemote.transact(UNBIND_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
boolean res = reply.readInt() != 0;
data.recycle();
reply.recycle();
return res;
}
public void publishService(IBinder token,
Intent intent, IBinder service) throws RemoteException {
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(token);
intent.writeToParcel(data, 0);
data.writeStrongBinder(service);
mRemote.transact(PUBLISH_SERVICE_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
} //...
}
这里列举了与服务相关的操作,我们关注启动服务mRemote.transact(START_SERVICE_TRANSACTION, data, reply, 0),mRemote代表了远程AMS对象,它会把请求发送给Binder驱动,然后由Binder驱动负责把请求转发到AMS去,参数caller代表了源进程即发起请求的进程,service代表了我们要启动的服务。
以上动作都发生在源进程,下面进入AMS服务侧的系统进程了。
接收到startService动作的是ActivityManagerNative,根据标识START_SERVICE_TRANSACTION回调到以下代码:
//frameworks\base\core\java\android\app\ActivityManagerNative.java
public abstract class ActivityManagerNative extends Binder implements IActivityManager
{
/**
* 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()
{
if (gDefault != null) {
//if (Config.LOGV) Log.v(
// "ActivityManager", "returning cur default = " + gDefault);
return gDefault;
}
IBinder b = ServiceManager.getService("activity");
if (Config.LOGV) Log.v(
"ActivityManager", "default service binder = " + b);
gDefault = asInterface(b);
if (Config.LOGV) Log.v(
"ActivityManager", "default service = " + gDefault);
return gDefault;
}
//...
public ActivityManagerNative()
{
attachInterface(this, descriptor);
}
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();
ComponentName cn = startService(app, service, resolvedType);
reply.writeNoException();
ComponentName.writeToParcel(cn, reply);
return true;
}
case STOP_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();
int res = stopService(app, service, resolvedType);
reply.writeNoException();
reply.writeInt(res);
return true;
}
case STOP_SERVICE_TOKEN_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
ComponentName className = ComponentName.readFromParcel(data);
IBinder token = data.readStrongBinder();
int startId = data.readInt();
boolean res = stopServiceToken(className, token, startId);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
}
case SET_SERVICE_FOREGROUND_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
ComponentName className = ComponentName.readFromParcel(data);
IBinder token = data.readStrongBinder();
int id = data.readInt();
Notification notification = null;
if (data.readInt() != 0) {
notification = Notification.CREATOR.createFromParcel(data);
}
boolean removeNotification = data.readInt() != 0;
setServiceForeground(className, token, id, notification, removeNotification);
reply.writeNoException();
return true;
}
case BIND_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IApplicationThread app = ApplicationThreadNative.asInterface(b);
IBinder token = data.readStrongBinder();
Intent service = Intent.CREATOR.createFromParcel(data);
String resolvedType = data.readString();
b = data.readStrongBinder();
int fl = data.readInt();
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
int res = bindService(app, token, service, resolvedType, conn, fl);
reply.writeNoException();
reply.writeInt(res);
return true;
}
case UNBIND_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder b = data.readStrongBinder();
IServiceConnection conn = IServiceConnection.Stub.asInterface(b);
boolean res = unbindService(conn);
reply.writeNoException();
reply.writeInt(res ? 1 : 0);
return true;
}
case PUBLISH_SERVICE_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
Intent intent = Intent.CREATOR.createFromParcel(data);
IBinder service = data.readStrongBinder();
publishService(token, intent, service);
reply.writeNoException();
return true;
}
case UNBIND_FINISHED_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IBinder token = data.readStrongBinder();
Intent intent = Intent.CREATOR.createFromParcel(data);
boolean doRebind = data.readInt() != 0;
unbindFinished(token, intent, doRebind);
reply.writeNoException();
return true;
}
//...
}
}
这里关注START_SERVICE_TRANSACTION分支的处理, 从binder中读出了IApplicationThread对象,这个对象代表了发起请求的源进程,取出service,该Intent代表了我们要启动的服务。接着调用startService(app, service, resolvedType),该函数的实现正是位于AMS中,接下来我们进入AMS分析它是如何启动服务的。
2、Service启动在AMS的处理
现在我们进入到AMS的处理中,继续调用分析startService函数调用,代码如下:
//frameworks\base\servicesljava\com\android\server\am\ActivityManagerService.java
public ComponentName startService(IApplicationThread caller, Intent service,
String resolvedType) {
// Refuse possible leaked file descriptors
if (service != null && service.hasFileDescriptors() == true) {
throw new IllegalArgumentException("File descriptors passed in Intent");
}
synchronized(this) {
final int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
ComponentName res = startServiceLocked(caller, service,
resolvedType, callingPid, callingUid);
Binder.restoreCallingIdentity(origId);
return res;
}
}
直接转发到函数startServiceLocked中,代码如下:
ComponentName startServiceLocked(IApplicationThread caller,
Intent service, String resolvedType,
int callingPid, int callingUid) {
synchronized(this) {
//...
ServiceLookupResult res =
retrieveServiceLocked(service, resolvedType, callingPid, callingUid);
if (res == null) {
return null;
}
if (res.record == null) {
return new ComponentName("!", res.permission != null
? res.permission : "private to package");
}
ServiceRecord r = res.record;
int targetPermissionUid = checkGrantUriPermissionFromIntentLocked(
callingUid, r.packageName, service);
if (unscheduleServiceRestartLocked(r)) {
if (DEBUG_SERVICE) Slog.v(TAG, "START SERVICE WHILE RESTART PENDING: " + r);
}
r.startRequested = true;
r.callStart = false;
r.lastStartId++;
if (r.lastStartId < 1) {
r.lastStartId = 1;
}
r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId,
service, targetPermissionUid));
r.lastActivity = SystemClock.uptimeMillis();
synchronized (r.stats.getBatteryStats()) {
r.stats.startRunningLocked();
}
if (!bringUpServiceLocked(r, service.getFlags(), false)) {
return new ComponentName("!", "Service process is bad");
}
return r.name;
}
}
首先通过调用retrieveServiceLocked拿到对应的ServiceLookupResult对象,该对象包含了ServiceRecord对象,ServiceRecord则是解析参数service拿到的。
接下来设置ServiceRecord的几个参数startRequested = true、callStart = false、lastStartId++。接着创建ServiceRecord.StartItem对象并放到ServiceRecord的pendingStarts成员变量中,代表了接下来有需要启动的Service。接着继续调用bringUpServiceLocked启动服务,代码如下:
private final boolean bringUpServiceLocked(ServiceRecord r,
int intentFlags, boolean whileRestarting) {
//1
if (r.app != null && r.app.thread != null) {
sendServiceArgsLocked(r, false);
return true;
}
//2
if (!whileRestarting && r.restartDelay > 0) {
// If waiting for a restart, then do nothing.
return true;
}
// We are now bringing the service up, so no longer in the
// restarting state.
mRestartingServices.remove(r);
//3
final String appName = r.processName;
ProcessRecord app = getProcessRecordLocked(appName, r.appInfo.uid);
if (app != null && app.thread != null) {
try {
realStartServiceLocked(r, app);
return true;
} 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.
}
// Not running -- get it started, and enqueue this service record
// to be executed when the app comes up.
//4
if (startProcessLocked(appName, r.appInfo, true, intentFlags,
"service", r.name, false) == null) {
bringDownServiceLocked(r, true);
return false;
}
//5
if (!mPendingServices.contains(r)) {
mPendingServices.add(r);
}
return true;
}
函数参数中ServiceRecord就是我们要启动的Service对应的对象,whileRestarting为false,intentFlags则是与服务相关的一些参数。代码中我标记了5个地方,这里会一一说明:
- r.app != null && r.app.thread != null:这个代表了我们要启动的进程以及起来了,不需要再启动新进程了,所以接下来调用sendServiceArgsLocked执行服务的生命周期函数,函数返回。由于新进程还没有启动,所以不会进入该分支。
- !whileRestarting && r.restartDelay > 0:whileRestarting为false,但是restartDelay参数并没有设置。所以不会进入该分支。
- app != null && app.thread != null:代表新进程是否以及存在,明显不存在;所以也不会进入这里。
- startProcessLocked:由于新进程没有启动,所以调用startProcessLocked启动服务要运行在的进程。
- mPendingServices.add(r):把ServiceRecord对象加入到集合mPendingServices中,也就是说,当进程起来以后需要从集合mPendingServices中拿到需要运行的服务。
第四点启动新进程会把需要运行服务的进程创建起来,接下来我们进入startProcessLocked,代码如下:
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting) {
ProcessRecord app = getProcessRecordLocked(processName, info.uid);
// We don't have to do anything more if:
// (1) There is an existing application record; and
// (2) The caller doesn't think it is dead, OR there is no thread
// object attached to it so we know it couldn't have crashed; and
// (3) There is a pid assigned to it, so it is either starting or
// already running.
//...
if (app == null) {
app = newProcessRecordLocked(null, info, processName);
mProcessNames.put(processName, info.uid, app);
} else {
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName);
}
//...
startProcessLocked(app, hostingType, hostingNameStr);
return (app.pid != 0) ? app : null;
}
代码省略了一些相关的判断,如果需要创建新进程, 则会调用newProcessRecordLocked创建一个ProcessRecord对象用于记录新进程的一些信息。继续调用到startProcessLocked,代码如下:
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
//...
try {
//1 设置一些启动参数
int uid = app.info.uid;
int[] gids = null;
//...
int debugFlags = 0;
if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {
debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;
}
// Run the app in safe mode if its manifest requests so or the
// system is booted in safe mode.
if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||
Zygote.systemInSafeMode == true) {
debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;
}
if ("1".equals(SystemProperties.get("debug.checkjni"))) {
debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;
}
if ("1".equals(SystemProperties.get("debug.assert"))) {
debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;
}
//2 启动新进程,入口类为android.app.ActivityThread
int pid = Process.start("android.app.ActivityThread",
mSimpleProcessManagement ? app.processName : null, uid, uid,
gids, debugFlags, null);
//...
if (pid == 0 || pid == MY_PID) {
// Processes are being emulated with threads.
app.pid = MY_PID;
app.removed = false;
mStartingProcesses.add(app);
} else if (pid > 0) {
//3 发送了一个超时消息
app.pid = pid;
app.removed = false;
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(pid, app);
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, PROC_START_TIMEOUT);
}
} else {
app.pid = 0;
//...
}
} catch (RuntimeException e) {
// XXX do better error recovery.
app.pid = 0;
Slog.e(TAG, "Failure starting process " + app.processName, e);
}
}
该函数中有三个关键位置,接下来我们一一说明:
- 这里主要设置一些新进程的启动参数,比如uid、gids、debugFlags。
- 启动新进程,入口类为android.app.ActivityThread
- 新进程创建成功返回了,获得了进程id,也即是返回值pid ;同时还把ProcessRecord对象放入到集合mPidsSelfLocked中,然后发送了一个超时消息PROC_START_TIMEOUT_MSG。
- mPidsSelfLocked:是AMS用来记录当前启动进程信息的集合。
- PROC_START_TIMEOUT_MSG:则是新进程创建成功后发送的一个延时消息,AMS这里采取的策略是新进程必须在启动之后的一段时间内回调到AMS,此时会把消息该消息移除掉;如果新进程启动太久了,没有及时回调AMS则该消息会弹出ANR弹窗提醒用户。言下之意就是新进程启动太慢了,影响了用户体验,所以通过这种方式告知用户,用户可以选择继续等待或者杀死待启动的应用。
新进程启动的入口类为android.app.ActivityThread,首先调用的是ActivityThread.main,接下来运行流程就到了客户端的MyService进程中了。
有关新进程如何启动,可以再写一遍文章分析,这里关注Service的启动流程,先简单跳过了。
3、Service在新进程中的启动
新进程启动后的入口为android.app.ActivityThread.main,代码如下:
//frameworks\base\core\java\android\app\ActivityThread.java
public static final void main(String[] args) {
SamplingProfilerIntegration.start();
Process.setArgV0("<pre-initialized>");
Looper.prepareMainLooper();
if (sMainThreadHandler == null) {
sMainThreadHandler = new Handler();
}
ActivityThread thread = new ActivityThread();
thread.attach(false);
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
Looper.loop();
if (Process.supportsProcesses()) {
throw new RuntimeException("Main thread loop unexpectedly exited");
}
thread.detach();
String name = (thread.mInitialApplication != null)
? thread.mInitialApplication.getPackageName()
: "<unknown>";
Slog.i(TAG, "Main thread of " + name + " is now exiting");
}
通过Looper.prepareMainLooper()/Looper.loop();建立消息循环,这就是主线程消息循环建立的地方。同时创建了ActivityThread对象,该对象代表了客户端MyService进程,然后调用thread.attach(false),注意参数为false。
创建ActivityThread对象的时候其实还创建了IApplicationThread对象。
//frameworks\base\core\java\android\app\ActivityThread.java
final ApplicationThread mAppThread = new ApplicationThread();
该对象代表了客户端,AMS就是通过这个对象与客户端通信的。attach的实现如下:
private final void attach(boolean system) {
sThreadLocal.set(this);
mSystemThread = system;
if (!system) {
//1
ViewRoot.addFirstDrawHandler(new Runnable() {
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>");
RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
}
} else {
//2
// Don't set application object here -- if the system crashes,
// we can't display an alert, we just want to die die die.
android.ddm.DdmHandleAppName.setAppName("system_process");
try {
mInstrumentation = new Instrumentation();
ContextImpl context = new ContextImpl();
context.init(getSystemContext().mPackageInfo, null, this);
Application app = Instrumentation.newApplication(Application.class, context);
mAllApplications.add(app);
mInitialApplication = app;
app.onCreate();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate Application():" + e.toString(), e);
}
}
ViewRoot.addConfigCallback(new ComponentCallbacks() {
public void onConfigurationChanged(Configuration newConfig) {
synchronized (mPackages) {
// We need to apply this change to the resources
// immediately, because upon returning the view
// hierarchy will be informed about it.
if (applyConfigurationToResourcesLocked(newConfig)) {
// This actually changed the resources! Tell
// everyone about it.
if (mPendingConfiguration == null ||
mPendingConfiguration.isOtherSeqNewer(newConfig)) {
mPendingConfiguration = newConfig;
queueOrSendMessage(H.CONFIGURATION_CHANGED, newConfig);
}
}
}
}
public void onLowMemory() {
}
});
}
这里说明以下两处:
- 参数system为false,所以会进入这个分支,然后调用attachApplication
- 这个分支表示system为true,代表了系统进程。
由于system为false,所以流程走第一个分支,IActivityManager mgr = ActivityManagerNative.getDefault(),拿到AMS的代理,调用attachApplication;该函数调用会进入AMS侧,我们直接到AMS那边分析接下来的流程。
4、Service与AMS的关系再续
进入AMS后,先调用attachApplication,代码如下:
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
直接转发到函数 attachApplicationLocked,代码如下:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
//1 找到ProcessRecord对象,还记得该对象是啥时候加到集合mPidsSelfLocked的吗
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else if (mStartingProcesses.size() > 0) {
app = mStartingProcesses.remove(0);
app.setPid(pid);
} else {
app = null;
}
if (app == null) {
//...
return false;
}
//...
String processName = app.processName;
//...
//2 设置ProcessRecord对象的一些参数
app.thread = thread;
app.curAdj = app.setAdj = -100;
app.curSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.setSchedGroup = Process.THREAD_GROUP_BG_NONINTERACTIVE;
app.forcingToForeground = null;
app.foregroundServices = false;
app.debugging = false;
//3 移除延时消息
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
//...
try {
//...
//4 执行dex优化
ensurePackageDexOpt(app.instrumentationInfo != null
? app.instrumentationInfo.packageName
: app.info.packageName);
if (app.instrumentationClass != null) {
ensurePackageDexOpt(app.instrumentationClass.getPackageName());
}
//5 回调应用程序
thread.bindApplication(processName, app.instrumentationInfo != null
? app.instrumentationInfo : app.info, providers,
app.instrumentationClass, app.instrumentationProfileFile,
app.instrumentationArguments, app.instrumentationWatcher, testMode,
isRestrictedBackupMode || !normalMode,
mConfiguration, getCommonServicesLocked());
updateLruProcessLocked(app, false, true);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
//...
return false;
}
//....
boolean badApp = false;
boolean didSomething = false;
// 6 See if the top visible activity is waiting to run in this process...
ActivityRecord hr = mMainStack.topRunningActivityLocked(null);
if (hr != null && normalMode) {
if (hr.app == null && app.info.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (mMainStack.realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
badApp = true;
}
} else {
mMainStack.ensureActivitiesVisibleLocked(hr, null, processName, 0);
}
}
// 7 Find any services that should be running in this process...
if (!badApp && mPendingServices.size() > 0) {
ServiceRecord sr = null;
try {
for (int i=0; i<mPendingServices.size(); i++) {
sr = mPendingServices.get(i);
if (app.info.uid != sr.appInfo.uid
|| !processName.equals(sr.processName)) {
continue;
}
mPendingServices.remove(i);
i--;
realStartServiceLocked(sr, app);
didSomething = true;
}
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting service "
+ sr.shortName, e);
badApp = true;
}
}
// 8 Check if the next broadcast receiver is in this process...
BroadcastRecord br = mPendingBroadcast;
if (!badApp && br != null && br.curApp == app) {
try {
mPendingBroadcast = null;
processCurBroadcastLocked(br, app);
didSomething = true;
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting receiver "
+ br.curComponent.flattenToShortString(), e);
badApp = true;
logBroadcastReceiverDiscardLocked(br);
finishReceiverLocked(br.receiver, br.resultCode, br.resultData,
br.resultExtras, br.resultAbort, true);
scheduleBroadcastsLocked();
// We need to reset the state if we fails to start the receiver.
br.state = BroadcastRecord.IDLE;
}
}
//...
return true;
}
代码中标记了一些关键的地方,下面一一说明:
- 找到ProcessRecord对象,主要是从mPidsSelfLocked集合中找到pid对应的ProcessRecord对象。
- 设置ProcessRecord对象的一些参数,其中最主要的是设置thread参数,该参数是IApplicationThread对象,代表了客户端;AMS就是通过这个对象与客户端通信的。
- 移除延时消息PROC_START_TIMEOUT_MSG,此时代表了新进程以及成功启动。
- 调用ensurePackageDexOpt执行dex优化,这里我们不关注。
- 调用bindApplication回调客户端,这里会调用到ActivityThread.handleBindApplication函数,然后执行Application的onCreate函数。从这里我们知道Application的onCreate运行于主线程中,所以我们在开发APP的时候最好只在里面做一些必要的初始化,否则会影响APP的启动速度。
- 此处是启动activity的,我们这里不关注。
- 启动service,这是我们需要关注的部分;还记得调用bringUpServiceLocked的时候mPendingServices集合加入了我们要启动的ServiceRecord对象吗?这里取出ServiceRecord对象,然后调用realStartServiceLocked继续启动服务。
- 广播处理,我们这里也不关注。
realStartServiceLocked以ServiceRecord及ProcessRecord为参数,代码如下:
private final void realStartServiceLocked(ServiceRecord r,
ProcessRecord app) throws RemoteException {
//...
r.app = app;
r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
app.services.add(r);
bumpServiceExecutingLocked(r, "create");
updateLruProcessLocked(app, true, true);
boolean created = false;
try {
//...
//1 回调客户端
app.thread.scheduleCreateService(r, r.serviceInfo);
r.postNotification();
created = true;
} finally {
if (!created) {
app.services.remove(r);
scheduleServiceRestartLocked(r, false);
}
}
requestServiceBindingsLocked(r);
//2设置一些参数
if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {
r.lastStartId++;
if (r.lastStartId < 1) {
r.lastStartId = 1;
}
r.pendingStarts.add(new ServiceRecord.StartItem(r, r.lastStartId, null, -1));
}
//3 回调客户端onStart
sendServiceArgsLocked(r, true);
}
scheduleCreateService将会回调到客户端,进入到ActivityThead.handleCreateService,而sendServiceArgsLocked将会回调客户端的onStartCommond方法。
先来看看handleCreateService函数,代码如下:
private final 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);
Service service = null;
try {
//1
java.lang.ClassLoader cl = packageInfo.getClassLoader();
service = (Service) cl.loadClass(data.info.name).newInstance();
} catch (Exception e) {
//...
}
try {
ContextImpl context = new ContextImpl();
context.init(packageInfo, null, this);
Application app = packageInfo.makeApplication(false, mInstrumentation);
context.setOuterContext(service);
service.attach(context, this, data.info.name, data.token, app,
ActivityManagerNative.getDefault());
//2
service.onCreate();
mServices.put(data.token, service);
try {
ActivityManagerNative.getDefault().serviceDoneExecuting(
data.token, 0, 0, 0);
} catch (RemoteException e) {
// nothing to do.
}
} catch (Exception e) {
//...
}
}
这里比较简单,首先loadClass加载了我们实现的服务类,然后调用服务的onCreate方法,嗯,终于看到了熟悉的onCreate了。
好啦,感觉这篇有点长了,先不写了。
这里只是回调到了服务的onCreate,我们知道在服务的onCreate里面执行耗时任务会导致ANR,下一篇,我们将继续分析服务的生命周期调用是如何在AMS侧实现的、同时分析为何onCreate、onStartCommond执行耗时任务会导致ANR。