理解Android进程启动之全过程
yatd1288
8年前
<h2><strong>一. 概述</strong></h2> <p>Android系统将进程做得很友好的封装,对于上层app开发者来说进程几乎是透明的. 了解Android的朋友,一定知道Android四大组件,但对于进程可能会相对较陌生. 一个进程里面可以跑多个app(通过share uid的方式), 一个app也可以跑在多个进程里(通过配置Android:process属性).</p> <p>再进一步进程是如何创建的, 可能很多人不知道fork的存在. 在我的文章 <a href="/misc/goto?guid=4959720056802377481" rel="nofollow,noindex">理解Android进程创建流程</a> 集中一点详细介绍了 Process.start 的过程是如何一步步创建进程.本文则是从另个角度来全局性讲解android进程启动全过程所涉及的根脉, 先来看看AMS.startProcessLocked方法.</p> <h2><strong>二. 四大组件与进程</strong></h2> <h3><strong>2.1 startProcessLocked</strong></h3> <p>在 ActivityManagerService.java 关于启动进程有4个同名不同参数的重载方法, 为了便于说明,以下4个方法依次记为 1(a) , 1(b) , 2(a) , 2(b) :</p> <pre> <code class="language-java">//方法 1(a) final ProcessRecord startProcessLocked( String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) //方法 1(b) final ProcessRecord startProcessLocked( String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) //方法 2(a) private final void startProcessLocked( ProcessRecord app, String hostingType, String hostingNameStr) //方法 2(b) private final void startProcessLocked( ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs)</code></pre> <p>1(a) ==> 1(b):方法1(a)将isolatedUid=0,其他参数赋值为null,再调用给1(b)</p> <pre> <code class="language-java">final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, boolean keepIfLarge) { return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType, hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */); }</code></pre> <p>2(a) ==> 2(b):方法2(a)将其他3个参数abiOverride,entryPoint, entryPointArgs赋值为null,再调用给2(b)</p> <pre> <code class="language-java">private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) { startProcessLocked(app, hostingType, hostingNameStr, null /* abiOverride */, null /* entryPoint */, null /* entryPointArgs */); }</code></pre> <p>小结:</p> <ul> <li>1(a),1(b)的第一个参数为String类型的进程名processName,</li> <li>2(a), 2(b)的第一个参数为ProcessRecord类型进程记录信息ProcessRecord;</li> <li>1系列的方法最终调用到2系列的方法;</li> </ul> <h3><strong>2.2 四大组件与进程</strong></h3> <p>Activity, Service, ContentProvider, BroadcastReceiver这四大组件,在启动的过程,当其所承载的进程不存在时需要先创建进程. 这个创建进程的过程是调用前面讲到的startProcessLocked方法1(a) . 调用流程: 1(a) => 1(b) ==> 2(b). 下面再简单说说这4大组件与进程创建是在何时需要创建的.</p> <p>2.2.1 Activity</p> <p>启动Activity过程: 调用startActivity,该方法经过层层调用,最终会调用ActivityStackSupervisor.java中的 startSpecificActivityLocked ,当activity所属进程还没启动的情况下,则需要创建相应的进程.</p> <p>[-> ActivityStackSupervisor.java]</p> <pre> <code class="language-java">void startSpecificActivityLocked(...) { ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); if (app != null && app.thread != null) { ... //进程已创建的case return } mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true); }</code></pre> <p>2.2.2 Service</p> <p>启动服务过程: 调用startService,该方法经过层层调用,最终会调用ActiveServices.java中的 bringUpServiceLocked ,当Service进程没有启动的情况(app==null), 则需要创建相应的进程. 更多关于Service, 见startService流程分析</p> <p>[-> ActiveServices.java]</p> <pre> <code class="language-java">private final String bringUpServiceLocked(...){ ... ProcessRecord app = mAm.getProcessRecordLocked(procName, r.appInfo.uid, false); if (app == null) { if ((app=mAm.startProcessLocked(procName, r.appInfo, true, intentFlags, "service", r.name, false, isolated, false)) == null) { ... } } ... }</code></pre> <p>2.2.3 ContentProvider</p> <p>ContentProvider处理过程: 调用ContentResolver.query该方法经过层层调用, 最终会调用到AMS.java中的 getContentProviderImpl ,当ContentProvider所对应进程不存在,则需要创建新进程. 更多关于ContentProvider,见 <a href="/misc/goto?guid=4959713441761390939" rel="nofollow,noindex">理解ContentProvider原理(一)</a></p> <p>[-> AMS.java]</p> <pre> <code class="language-java">private final ContentProviderHolder getContentProviderImpl(...) { ... ProcessRecord proc = getProcessRecordLocked(cpi.processName, cpr.appInfo.uid, false); if (proc != null && proc.thread != null) { ... //进程已创建的case } else { proc = startProcessLocked(cpi.processName, cpr.appInfo, false, 0, "content provider", new ComponentName(cpi.applicationInfo.packageName,cpi.name), false, false, false); } ... }</code></pre> <p>2.2.4 Broadcast</p> <p>广播处理过程: 调用sendBroadcast,该方法经过层层调用, 最终会调用到BroadcastQueue.java中的 processNextBroadcast ,当BroadcastReceiver所对应的进程尚未启动,则创建相应进程. 更多关于broadcast, 见 <a href="/misc/goto?guid=4959720056933178880" rel="nofollow,noindex">Android Broadcast广播机制分析</a> .</p> <p>[-> BroadcastQueue.java]</p> <pre> <code class="language-java">final void processNextBroadcast(boolean fromMsg) { ... ProcessRecord app = mService.getProcessRecordLocked(targetProcess, info.activityInfo.applicationInfo.uid, false); if (app != null && app.thread != null) { ... //进程已创建的case return } if ((r.curApp=mService.startProcessLocked(targetProcess, info.activityInfo.applicationInfo, true, r.intent.getFlags() | Intent.FLAG_FROM_BACKGROUND, "broadcast", r.curComponent, (r.intent.getFlags()&Intent.FLAG_RECEIVER_BOOT_UPGRADE) != 0, false, false)) == null) { ... } ... }</code></pre> <h3><strong>2.3 小节</strong></h3> <p>Activity, Service, ContentProvider, BroadcastReceiver这四大组件在启动时,当所承载的进程不存在时,都需要创建. 进程的创建过程交由系统进程system_server来完成的.</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/1204e621a2a766e3cea67eba41f65865.jpg"></p> <p>简称:</p> <ul> <li>ATP: ApplicationThreadProxy</li> <li>AT: ApplicationThread (继承于ApplicationThreadNative)</li> <li>AMP: ActivityManagerProxy</li> <li>AMS: ActivityManagerService (继承于ActivityManagerNative)</li> </ul> <ol> <li>system_server进程中调用 startProcessLocked 方法,该方法最终通过socket方式,将需要创建新进程的消息告知Zygote进程,并阻塞等待Socket返回新创建进程的pid;</li> <li>Zygote进程接收到system_server发送过来的消息, 则通过fork的方法,将zygote自身进程复制生成新的进程,并将ActivityThread相关的资源加载到新进程app process,这个进程可能是用于承载activity等组件;</li> <li>创建完新进程后fork返回两次, 在新进程app process向servicemanager查询system_server进程中binder服务端AMS,获取相对应的Client端,也就是AMP. 有了这一对binder c/s对, 那么app process便可以通过binder向跨进程system_server发送请求,即attachApplication()</li> <li>system_server进程接收到相应binder操作后,经过多次调用,利用ATP向app process发送binder请求, 即bindApplication.</li> </ol> <p>system_server拥有ATP/AMS, 每一个新创建的进程都会有一个相应的AT/AMS,从而可以跨进程 进行相互通信. 这便是进程创建过程的完整生态链.</p> <h2><strong>三. 进程启动全过程</strong></h2> <p>前面刚已介绍四大组件的创建进程的过程是调用1(a) startProcessLocked 方法,该方法会再调用1(b)方法. 接下来从该方法开始往下讲述.</p> <h3><strong>3.1 AMS.startProcessLocked</strong></h3> <pre> <code class="language-java">final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) { long startTime = SystemClock.elapsedRealtime(); ProcessRecord app; if (!isolated) { //根据进程名和uid检查相应的ProcessRecord app = getProcessRecordLocked(processName, info.uid, keepIfLarge); if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) { //如果当前处于后台进程,检查当前进程是否处于bad进程列表 if (mBadProcesses.get(info.processName, info.uid) != null) { return null; } } else { //当用户明确地启动进程,则清空crash次数,以保证其不处于bad进程直到下次再弹出crash对话框。 mProcessCrashTimes.remove(info.processName, info.uid); if (mBadProcesses.get(info.processName, info.uid) != null) { mBadProcesses.remove(info.processName, info.uid); if (app != null) { app.bad = false; } } } } else { //对于孤立进程,无法再利用已存在的进程 app = null; } //当存在ProcessRecord,且已分配pid(正在启动或者已经启动), // 且caller并不认为该进程已死亡或者没有thread对象attached到该进程.则不应该清理该进程 if (app != null && app.pid > 0) { if (!knownToBeDead || app.thread == null) { //如果这是进程中新package,则添加到列表 app.addPackage(info.packageName, info.versionCode, mProcessStats); return app; } //当ProcessRecord已经被attached到先前的一个进程,则杀死并清理该进程 killProcessGroup(app.info.uid, app.pid); handleAppDiedLocked(app, true, true); } String hostingNameStr = hostingName != null? hostingName.flattenToShortString() : null; if (app == null) { // 创建新的Process Record对象 app = newProcessRecordLocked(info, processName, isolated, isolatedUid); if (app == null) { return null; } app.crashHandler = crashHandler; } else { //如果这是进程中新package,则添加到列表 app.addPackage(info.packageName, info.versionCode, mProcessStats); } //当系统未准备完毕,则将当前进程加入到mProcessesOnHold if (!mProcessesReady && !isAllowedWhileBooting(info) && !allowWhileBooting) { if (!mProcessesOnHold.contains(app)) { mProcessesOnHold.add(app); } return app; } // 启动进程【见小节3.2】 startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs); return (app.pid != 0) ? app : null; }</code></pre> <p>主要功能:</p> <ul> <li>对于非isolated进程,则根据进程名和uid来查询相应的ProcessRecord结构体. 如果当前进程处于后台且当前进程处于mBadProcesses列表,则直接返回;否则清空crash次数,以保证其不处于bad进程直到下次再弹出crash对话框。</li> <li>当存在ProcessRecord,且已分配pid(正在启动或者已经启动)的情况下 <ul> <li>当caller并不认为该进程已死亡或者没有thread对象attached到该进程.则不应该清理该进程,则直接返回;</li> <li>否则杀死并清理该进程;</li> </ul> </li> <li>当ProcessRecord为空则新建一个,当创建失败则直接返回;</li> <li>当系统未准备完毕,则将当前进程加入到mProcessesOnHold, 并直接返回;</li> <li>最后启动新进程,其中参数含义: <ul> <li>hostingType可取值为”activity”,”service”,”broadcast”,”content provider”;</li> <li>hostingNameStr数据类型为ComponentName,代表的是具体相对应的组件名.</li> </ul> </li> </ul> <h3><strong>3.2 AMS.startProcessLocked</strong></h3> <pre> <code class="language-java">private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) { long startTime = SystemClock.elapsedRealtime(); //当app的pid大于0且不是当前进程的pid,则从mPidsSelfLocked中移除该app.pid if (app.pid > 0 && app.pid != MY_PID) { synchronized (mPidsSelfLocked) { mPidsSelfLocked.remove(app.pid); mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); } app.setPid(0); } //从mProcessesOnHold移除该app mProcessesOnHold.remove(app); updateCpuStats(); //更新cpu统计信息 try { try { if (AppGlobals.getPackageManager().isPackageFrozen(app.info.packageName)) { //当前package已被冻结,则抛出异常 throw new RuntimeException("Package " + app.info.packageName + " is frozen!"); } } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } int uid = app.uid; int[] gids = null; int mountExternal = Zygote.MOUNT_EXTERNAL_NONE; if (!app.isolated) { int[] permGids = null; try { //通过Package Manager获取gids final IPackageManager pm = AppGlobals.getPackageManager(); permGids = pm.getPackageGids(app.info.packageName, app.userId); MountServiceInternal mountServiceInternal = LocalServices.getService( MountServiceInternal.class); mountExternal = mountServiceInternal.getExternalStorageMountMode(uid, app.info.packageName); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } //添加共享app和gids,用于app直接共享资源 if (ArrayUtils.isEmpty(permGids)) { gids = new int[2]; } else { gids = new int[permGids.length + 2]; System.arraycopy(permGids, 0, gids, 2, permGids.length); } gids[0] = UserHandle.getSharedAppGid(UserHandle.getAppId(uid)); gids[1] = UserHandle.getUserGid(UserHandle.getUserId(uid)); } //根据不同参数,设置相应的debugFlags ... app.gids = gids; app.requiredAbi = requiredAbi; app.instructionSet = instructionSet; boolean isActivityProcess = (entryPoint == null); if (entryPoint == null) entryPoint = "android.app.ActivityThread"; //请求Zygote创建新进程[见3.3] Process.ProcessStartResult startResult = Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet, app.info.dataDir, entryPointArgs); ... if (app.persistent) { Watchdog.getInstance().processStarted(app.processName, startResult.pid); } //重置ProcessRecord的成员变量 app.setPid(startResult.pid); app.usingWrapper = startResult.usingWrapper; app.removed = false; app.killed = false; app.killedByAm = false; //将新创建的进程加入到mPidsSelfLocked synchronized (mPidsSelfLocked) { this.mPidsSelfLocked.put(startResult.pid, app); if (isActivityProcess) { Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG); msg.obj = app; //延迟发送消息PROC_START_TIMEOUT_MSG mHandler.sendMessageDelayed(msg, startResult.usingWrapper ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT); } } } catch (RuntimeException e) { app.setPid(0); //进程创建失败,则重置pid } }</code></pre> <ul> <li>根据不同参数,设置相应的debugFlags,比如在AndroidManifest.xml中设置androidd:debuggable为true,代表app运行在debug模式,则增加debugger标识以及开启JNI check功能</li> <li>调用Process.start来创建新进程;</li> <li>重置ProcessRecord的成员变量, 一般情况下超时10s后发送PROC_START_TIMEOUT_MSG的handler消息;</li> </ul> <p>关于Process.start()是通过socket通信告知Zygote创建fork子进程,创建新进程后将ActivityThread类加载到新进程,并调用ActivityThread.main()方法。详细过程见 <a href="/misc/goto?guid=4959720056802377481" rel="nofollow,noindex">理解Android进程创建流程</a> ,接下来进入AT.main方法.</p> <h3><strong>3.3 ActivityThread.main</strong></h3> <p>[-> ActivityThread.java]</p> <pre> <code class="language-java">public static void main(String[] args) { //性能统计默认是关闭的 SamplingProfilerIntegration.start(); //将当前进程所在userId赋值给sCurrentUser Environment.initForCurrentUser(); EventLogger.setReporter(new EventLoggingReporter()); AndroidKeyStoreProvider.install(); //确保可信任的CA证书存放在正确的位置 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); Process.setArgV0("<pre-initialized>"); //创建主线程的Looper对象, 该Looper是不运行退出 Looper.prepareMainLooper(); //创建ActivityThread对象 ActivityThread thread = new ActivityThread(); //建立Binder通道 【见流程3.4】 thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } // 当设置为true时,可打开消息队列的debug log信息 if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } Looper.loop(); //消息循环运行 throw new RuntimeException("Main thread loop unexpectedly exited"); }</code></pre> <ul> <li> <p>创建主线程的Looper对象: 该Looper是不运行退出. 也就是说主线程的Looper是在进程创建完成时自动创建完成,如果子线程也需要创建handler通信过程,那么就需要手动创建Looper对象,并且每个线程只能创建一次.</p> </li> <li> <p>创建ActivityThread对象 thread = new ActivityThread() : 该过程会初始化几个很重要的变量:</p> <ul> <li> <p>mAppThread = new ApplicationThread()</p> </li> <li> <p>mLooper = Looper.myLooper()</p> </li> <li> <p>mH = new H(), H 继承于 Handler ;用于处理组件的生命周期.</p> </li> </ul> </li> <li> <p>attach过程是当前主线程向system_server进程通信的过程, 将thread信息告知AMS.接下来还会进一步说明该过程.</p> </li> <li> <p>sMainThreadHandler通过getHandler(),获取的对象便是 mH ,这就是主线程的handler对象.</p> </li> </ul> <p>之后主线程调用Looper.loop(),进入消息循环状态, 当没有消息时主线程进入休眠状态, 一旦有消息到来则唤醒主线程并执行相关操作.</p> <h3><strong>3.4. ActivityThread.attach</strong></h3> <p>[-> ActivityThread.java]</p> <pre> <code class="language-java">private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; if (!system) { //开启虚拟机的jit即时编译功能 ViewRootImpl.addFirstDrawHandler(new Runnable() { @Override public void run() { ensureJitEnabled(); } }); android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); RuntimeInit.setApplicationObject(mAppThread.asBinder()); //创建ActivityManagerProxy对象 final IActivityManager mgr = ActivityManagerNative.getDefault(); try { //调用基于IActivityManager接口的Binder通道【见流程3.5】 mgr.attachApplication(mAppThread); } catch (RemoteException ex) { } //观察是否快接近heap的上限 BinderInternal.addGcWatcher(new Runnable() { @Override public void run() { if (!mSomeActivitiesChanged) { return; } Runtime runtime = Runtime.getRuntime(); long dalvikMax = runtime.maxMemory(); long dalvikUsed = runtime.totalMemory() - runtime.freeMemory(); if (dalvikUsed > ((3*dalvikMax)/4)) { mSomeActivitiesChanged = false; try { //当已用内存超过最大内存的3/4,则请求释放内存空间 mgr.releaseSomeActivities(mAppThread); } catch (RemoteException e) { } } } }); } else { ... } //添加dropbox日志到libcore DropBox.setReporter(new DropBoxReporter()); //添加Config回调接口 ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { @Override public void onConfigurationChanged(Configuration newConfig) { synchronized (mResourcesManager) { if (mResourcesManager.applyConfigurationToResourcesLocked(newConfig, null)) { if (mPendingConfiguration == null || mPendingConfiguration.isOtherSeqNewer(newConfig)) { mPendingConfiguration = newConfig; sendMessage(H.CONFIGURATION_CHANGED, newConfig); } } } } @Override public void onLowMemory() { } @Override public void onTrimMemory(int level) { } }); }</code></pre> <p>对于非系统attach的处理流程:</p> <ul> <li> <p>创建线程来开启虚拟机的jit即时编译;</p> </li> <li> <p>通过binder, 调用到AMS.attachApplication, 其参数mAppThread的数据类型为 ApplicationThread</p> </li> <li> <p>观察是否快接近heap的上限,当已用内存超过最大内存的3/4,则请求释放内存空间</p> </li> <li> <p>添加dropbox日志到libcore</p> </li> <li> <p>添加Config回调接口</p> </li> </ul> <h3><strong>3.5 AMP.attachApplication</strong></h3> <p>[-> ActivityManagerProxy.java]</p> <pre> <code class="language-java">public void attachApplication(IApplicationThread app) throws RemoteException { Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeInterfaceToken(IActivityManager.descriptor); data.writeStrongBinder(app.asBinder()); mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0); //【见流程3.6】 reply.readException(); data.recycle(); reply.recycle(); }</code></pre> <p>此处 descriptor = “android.app.IActivityManager”</p> <h3><strong>3.6 AMN.onTransact</strong></h3> <p>[-> ActivityManagerNative.java]</p> <pre> <code class="language-java">public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { ... case ATTACH_APPLICATION_TRANSACTION: { data.enforceInterface(IActivityManager.descriptor); //获取ApplicationThread的binder代理类 ApplicationThreadProxy IApplicationThread app = ApplicationThreadNative.asInterface( data.readStrongBinder()); if (app != null) { attachApplication(app); //此处是ActivityManagerService类中的方法 【见流程3.7】 } reply.writeNoException(); return true; } } }</code></pre> <h3><strong>3.7 AMS.attachApplication</strong></h3> <p>[-> ActivityManagerService.java]</p> <pre> <code class="language-java">public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); // 【见流程3.8】 Binder.restoreCallingIdentity(origId); } }</code></pre> <p>此处的 thread 便是ApplicationThreadProxy对象,用于跟前面通过Process.start()所创建的进程中ApplicationThread对象进行通信.</p> <h3><strong>3.8 AMS.attachApplicationLocked</strong></h3> <p>[-> ActivityManagerService.java]</p> <pre> <code class="language-java">private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { ProcessRecord app; if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { app = mPidsSelfLocked.get(pid); // 根据pid获取ProcessRecord } } else { app = null; } if (app == null) { if (pid > 0 && pid != MY_PID) { //ProcessRecord为空,则杀掉该进程 Process.killProcessQuiet(pid); } else { //退出新建进程的Looper thread.scheduleExit(); } return false; } //还刚进入attach过程,此时thread应该为null,若不为null则表示该app附到上一个进程,则立刻清空 if (app.thread != null) { handleAppDiedLocked(app, true, true); } final String processName = app.processName; try { //绑定死亡通知 AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread); thread.asBinder().linkToDeath(adr, 0); app.deathRecipient = adr; } catch (RemoteException e) { app.resetPackageList(mProcessStats); startProcessLocked(app, "link fail", processName); //重新启动进程 return false; } //重置进程信息 app.makeActive(thread, mProcessStats); //执行完该语句,则app.thread便不再为空 app.curAdj = app.setAdj = -100; app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT; app.forcingToForeground = null; updateProcessForegroundLocked(app, false, false); app.hasShownUi = false; app.debugging = false; app.cached = false; app.killedByAm = false; mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); //移除进程启动超时的消息 //系统处于ready状态或者该app为FLAG_PERSISTENT进程,则为true boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info); List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null; //app进程存在正在启动中的provider,则超时10s后发送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息 if (providers != null && checkAppInLaunchingProvidersLocked(app)) { Message msg = mHandler.obtainMessage(CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG); msg.obj = app; mHandler.sendMessageDelayed(msg, CONTENT_PROVIDER_PUBLISH_TIMEOUT); } try { ... ensurePackageDexOpt(app.instrumentationInfo != null ? app.instrumentationInfo.packageName : app.info.packageName); ApplicationInfo appInfo = app.instrumentationInfo != null ? app.instrumentationInfo : app.info; ... // 绑定应用 [见流程3.9] thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked()); //更新进程LRU队列 updateLruProcessLocked(app, false, null); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { app.resetPackageList(mProcessStats); app.unlinkDeathRecipient(); //每当bind操作失败,则重启启动进程, 此处有可能会导致进程无限重启 startProcessLocked(app, "bind fail", processName); return false; } mPersistentStartingProcesses.remove(app); mProcessesOnHold.remove(app); boolean badApp = false; boolean didSomething = false; //Activity: 检查最顶层可见的Activity是否等待在该进程中运行 if (normalMode) { try { if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { badApp = true; } } //Service: 寻找所有需要在该进程中运行的服务 if (!badApp) { try { didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { badApp = true; } } //广播:检查是否在这个进程中有下一个广播接收者 if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { didSomething |= sendPendingBroadcastsLocked(app); } catch (Exception e) { badApp = true; } } //检查是否在这个进程中有下一个backup代理 if (!badApp && mBackupTarget != null && mBackupTarget.appInfo.uid == app.uid) { ensurePackageDexOpt(mBackupTarget.appInfo.packageName); try { thread.scheduleCreateBackupAgent(mBackupTarget.appInfo, compatibilityInfoForPackageLocked(mBackupTarget.appInfo), mBackupTarget.backupMode); } catch (Exception e) { badApp = true; } } if (badApp) { //杀掉bad应用 app.kill("error during init", true); handleAppDiedLocked(app, false, true); return false; } if (!didSomething) { updateOomAdjLocked(); //更新adj的值 } return true; }</code></pre> <ol> <li> <p>根据pid从mPidsSelfLocked中查询到相应的ProcessRecord对象app;</p> </li> <li> <p>当app==null,意味着本次创建的进程不存在, 则直接返回.</p> </li> <li> <p>还刚进入attach过程,此时thread应该为null,若不为null则表示该app附到上一个进程,则调用handleAppDiedLocked清理.</p> </li> <li> <p>绑定死亡通知,当进程pid死亡时会通过binder死亡回调,来通知system_server进程死亡的消息;</p> </li> <li> <p>重置ProcessRecord进程信息, 此时app.thread也赋予了新值,便不再为空.</p> </li> <li> <p>app进程存在正在启动中的provider,则超时10s后发送CONTENT_PROVIDER_PUBLISH_TIMEOUT_MSG消息</p> </li> <li> <p>调用thread.bindApplication绑定应用进程, 后面再进一步说明</p> </li> <li> <p>处理Provider, Activity, Service, Broadcast相应流程</p> </li> </ol> <p>下面,再来说说thread.bindApplication的过程.</p> <h3><strong>3.9 ATP.bindApplication</strong></h3> <p>[-> ApplicationThreadNative.java ::ApplicationThreadProxy]</p> <pre> <code class="language-java">class ApplicationThreadProxy implements IApplicationThread { ... public final void bindApplication(String packageName, ApplicationInfo info, List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo, Bundle testArgs, IInstrumentationWatcher testWatcher, IUiAutomationConnection uiAutomationConnection, int debugMode, boolean openGlTrace, boolean restrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) throws RemoteException { Parcel data = Parcel.obtain(); data.writeInterfaceToken(IApplicationThread.descriptor); data.writeString(packageName); info.writeToParcel(data, 0); data.writeTypedList(providers); if (testName == null) { data.writeInt(0); } else { data.writeInt(1); testName.writeToParcel(data, 0); } if (profilerInfo != null) { data.writeInt(1); profilerInfo.writeToParcel(data, Parcelable.PARCELABLE_WRITE_RETURN_VALUE); } else { data.writeInt(0); } data.writeBundle(testArgs); data.writeStrongInterface(testWatcher); data.writeStrongInterface(uiAutomationConnection); data.writeInt(debugMode); data.writeInt(openGlTrace ? 1 : 0); data.writeInt(restrictedBackupMode ? 1 : 0); data.writeInt(persistent ? 1 : 0); config.writeToParcel(data, 0); compatInfo.writeToParcel(data, 0); data.writeMap(services); data.writeBundle(coreSettings); mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null, IBinder.FLAG_ONEWAY); data.recycle(); } ... }</code></pre> <p>ATP经过binder ipc传递到ATN的onTransact过程.</p> <h3><strong>3.10 ATN.onTransact</strong></h3> <p>[-> ApplicationThreadNative.java]</p> <pre> <code class="language-java">public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException { switch (code) { ... case BIND_APPLICATION_TRANSACTION: { data.enforceInterface(IApplicationThread.descriptor); String packageName = data.readString(); ApplicationInfo info = ApplicationInfo.CREATOR.createFromParcel(data); List<ProviderInfo> providers = data.createTypedArrayList(ProviderInfo.CREATOR); ComponentName testName = (data.readInt() != 0) ? new ComponentName(data) : null; ProfilerInfo profilerInfo = data.readInt() != 0 ? ProfilerInfo.CREATOR.createFromParcel(data) : null; Bundle testArgs = data.readBundle(); IBinder binder = data.readStrongBinder(); IInstrumentationWatcher testWatcher = IInstrumentationWatcher.Stub.asInterface(binder); binder = data.readStrongBinder(); IUiAutomationConnection uiAutomationConnection = IUiAutomationConnection.Stub.asInterface(binder); int testMode = data.readInt(); boolean openGlTrace = data.readInt() != 0; boolean restrictedBackupMode = (data.readInt() != 0); boolean persistent = (data.readInt() != 0); Configuration config = Configuration.CREATOR.createFromParcel(data); CompatibilityInfo compatInfo = CompatibilityInfo.CREATOR.createFromParcel(data); HashMap<String, IBinder> services = data.readHashMap(null); Bundle coreSettings = data.readBundle(); //[见流程3.11] bindApplication(packageName, info, providers, testName, profilerInfo, testArgs, testWatcher, uiAutomationConnection, testMode, openGlTrace, restrictedBackupMode, persistent, config, compatInfo, services, coreSettings); return true; } ... }</code></pre> <h3><strong>3.11 AT.bindApplication</strong></h3> <p>[-> ActivityThread.java ::ApplicationThread]</p> <pre> <code class="language-java">public final void bindApplication(String processName, ApplicationInfo appInfo, List<ProviderInfo> providers, ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent, Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services, Bundle coreSettings) { if (services != null) { //将services缓存起来, 减少binder检索服务的次数 ServiceManager.initServiceCache(services); } //发送消息H.SET_CORE_SETTINGS setCoreSettings(coreSettings); IPackageManager pm = getPackageManager(); android.content.pm.PackageInfo pi = null; try { pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId()); } catch (RemoteException e) { } if (pi != null) { boolean sharedUserIdSet = (pi.sharedUserId != null); boolean processNameNotDefault = (pi.applicationInfo != null && !appInfo.packageName.equals(pi.applicationInfo.processName)); boolean sharable = (sharedUserIdSet || processNameNotDefault); if (!sharable) { VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir, appInfo.processName); } } //初始化AppBindData, 再发送消息H.BIND_APPLICATION AppBindData data = new AppBindData(); data.processName = processName; data.appInfo = appInfo; data.providers = providers; data.instrumentationName = instrumentationName; data.instrumentationArgs = instrumentationArgs; data.instrumentationWatcher = instrumentationWatcher; data.instrumentationUiAutomationConnection = instrumentationUiConnection; data.debugMode = debugMode; data.enableOpenGlTrace = enableOpenGlTrace; data.restrictedBackupMode = isRestrictedBackupMode; data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; sendMessage(H.BIND_APPLICATION, data); }</code></pre> <p>其中setCoreSettings()过程就是调用sendMessage(H.SET_CORE_SETTINGS, coreSettings) 来向主线程发送SET_CORE_SETTINGS消息.bindApplication方法的主要功能是依次向主线程发送消息 H.SET_CORE_SETTINGS 和 H.BIND_APPLICATION . 接下来再来说说这两个消息的处理过程</p> <h3><strong>3.12 H.SET_CORE_SETTINGS</strong></h3> <p>[-> ActivityThread.java ::H]</p> <p>当主线程收到H.SET_CORE_SETTINGS,则调用handleSetCoreSettings</p> <pre> <code class="language-java">private void handleSetCoreSettings(Bundle coreSettings) { synchronized (mResourcesManager) { mCoreSettings = coreSettings; } onCoreSettingsChange(); } private void onCoreSettingsChange() { boolean debugViewAttributes = mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; if (debugViewAttributes != View.mDebugViewAttributes) { View.mDebugViewAttributes = debugViewAttributes; // 由于发生改变, 请求所有的activities重启启动 for (Map.Entry<IBinder, ActivityClientRecord> entry : mActivities.entrySet()) { requestRelaunchActivity(entry.getKey(), null, null, 0, false, null, null, false); } } }</code></pre> <h3><strong>3.13 H.BIND_APPLICATION</strong></h3> <p>[-> ActivityThread.java ::H]</p> <p>当主线程收到H.BIND_APPLICATION,则调用handleBindApplication</p> <pre> <code class="language-java">private void handleBindApplication(AppBindData data) { mBoundApplication = data; mConfiguration = new Configuration(data.config); mCompatConfiguration = new Configuration(data.config); ... //设置进程名 Process.setArgV0(data.processName); android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId()); if (data.persistent) { //低内存设备, persistent进程不采用硬件加速绘制,以节省内存使用量 if (!ActivityManager.isHighEndGfx()) { HardwareRenderer.disable(false); } } //重置时区 TimeZone.setDefault(null); Locale.setDefault(data.config.locale); //更新系统配置 mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo); mCurDefaultDisplayDpi = data.config.densityDpi; applyCompatConfiguration(mCurDefaultDisplayDpi); data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); ... // 创建ContextImpl上下文 final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); if (!Process.isIsolated()) { final File cacheDir = appContext.getCacheDir(); if (cacheDir != null) { System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath()); } //用于存储产生/编译的图形代码 final File codeCacheDir = appContext.getCodeCacheDir(); if (codeCacheDir != null) { setupGraphicsSupport(data.info, codeCacheDir); } } final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24)); DateFormat.set24HourTimePref(is24Hr); View.mDebugViewAttributes = mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; ... //当处于调试模式,则运行应用生成systrace信息 boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0; Trace.setAppTracingAllowed(appTracingAllowed); //初始化 默认的http代理 IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); if (b != null) { IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); final ProxyInfo proxyInfo = service.getProxyForNetwork(null); Proxy.setHttpProxySystemProperty(proxyInfo); } if (data.instrumentationName != null) { InstrumentationInfo ii = null; ii = appContext.getPackageManager().getInstrumentationInfo(data.instrumentationName, 0); mInstrumentationPackageName = ii.packageName; mInstrumentationAppDir = ii.sourceDir; mInstrumentationSplitAppDirs = ii.splitSourceDirs; mInstrumentationLibDir = ii.nativeLibraryDir; mInstrumentedAppDir = data.info.getAppDir(); mInstrumentedSplitAppDirs = data.info.getSplitAppDirs(); mInstrumentedLibDir = data.info.getLibDir(); ApplicationInfo instrApp = new ApplicationInfo(); instrApp.packageName = ii.packageName; instrApp.sourceDir = ii.sourceDir; instrApp.publicSourceDir = ii.publicSourceDir; instrApp.splitSourceDirs = ii.splitSourceDirs; instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs; instrApp.dataDir = ii.dataDir; instrApp.nativeLibraryDir = ii.nativeLibraryDir; LoadedApk pi = getPackageInfo(instrApp, data.compatInfo, appContext.getClassLoader(), false, true, false); ContextImpl instrContext = ContextImpl.createAppContext(this, pi); //通过反射,创建目标类 java.lang.ClassLoader cl = instrContext.getClassLoader(); mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance(); mInstrumentation.init(this, instrContext, appContext, new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher, data.instrumentationUiAutomationConnection); ... } else { mInstrumentation = new Instrumentation(); } //FLAG_LARGE_HEAP则清除内存增长上限 if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); } else { dalvik.system.VMRuntime.getRuntime().clampGrowthLimit(); } try { Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; if (!data.restrictedBackupMode) { List<ProviderInfo> providers = data.providers; if (providers != null) { installContentProviders(app, providers); mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } } mInstrumentation.onCreate(data.instrumentationArgs); //调用app.onCreate()方法. mInstrumentation.callApplicationOnCreate(app); } finally { StrictMode.setThreadPolicy(savedPolicy); } }</code></pre> <h2><strong>四. 总结</strong></h2> <p>本文首先介绍AMS的4个同名不同参数的方法startProcessLocked; 紧接着讲述了四大组件与进程的关系, Activity, Service, ContentProvider, BroadcastReceiver这四大组件,在启动的过程,当其所承载的进程不存在时需要先创建进程. 再然后进入重点以startProcessLocked以引线一路讲解整个过程所遇到的核心方法. 在整个过程中有新创建的进程与system_server进程之间的交互过程 是通过binder进行通信的, 这里有两条binder通道分别为AMP/AMN 和 ATP/ATN.</p> <p style="text-align:center"><img src="https://simg.open-open.com/show/a678656b4fb8f43dc79947a600a61e4b.jpg"></p> <p>上图便是一次完整的进程创建过程,app的任何组件需要有一个承载其运行的容器,那就是进程, 那么进程的创建过程都是由系统进程system_server通过socket向zygote进程来请求fork()新进程, 当创建出来的app process与system_server进程之间的通信便是通过binder IPC机制.</p> <p> </p> <p> </p> <p>来自:http://gityuan.com/2016/10/09/app-process-create-2/</p> <p> </p>