dede手机网站仿站,无锡网站设,青岛万维网站设计,网站更新方案目录
1、Service在客户端的启动入口
2、Service启动在AMS的处理
3、Service在新进程中的启动
4、Service与AMS的关系再续 上一篇文章中我们了解了Service在新进程中启动的大致流程#xff0c;同时认识了与客户端进程交互的接口IApplicationThread以及与AMS交互的接口IActi…
目录
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.javaOverridepublic 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 systems 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为falseintentFlags则是与服务相关的一些参数。代码中我标记了5个地方这里会一一说明
r.app ! null r.app.thread ! null这个代表了我们要启动的进程以及起来了不需要再启动新进程了所以接下来调用sendServiceArgsLocked执行服务的生命周期函数函数返回。由于新进程还没有启动所以不会进入该分支。!whileRestarting r.restartDelay 0whileRestarting为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 dont have to do anything more if:// (1) There is an existing application record; and// (2) The caller doesnt think it is dead, OR there is no thread// object attached to it so we know it couldnt 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 // Dont set application object here -- if the system crashes,// we cant 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 i0; imPendingServices.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。