目录
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@Overridepublic 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.javapublic ComponentName startService(IApplicationThread caller, Intent service,String resolvedType) {// Refuse possible leaked file descriptorsif (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) {//1if (r.app != null && r.app.thread != null) {sendServiceArgsLocked(r, false);return true;}//2if (!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);//3final 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.//4if (startProcessLocked(appName, r.appInfo, true, intentFlags,"service", r.name, false) == null) {bringDownServiceLocked(r, true);return false;}//5if (!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 listapp.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.ActivityThreadint 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.javapublic 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(newLogPrinter(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 回调客户端onStartsendServiceArgsLocked(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 {//1java.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());//2service.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。