点击桌面图标如何启动的app Android8.0
概述
首先附上我的几篇其它文章链接感兴趣的可以看看,如果文章有异议的地方欢迎指出,共同进步,顺便点赞谢谢!!!
Android studio编写第一个NDK工程的过程详解(附Demo下载地址)
面试必备1:HashMap(JDK1.8)原理以及源码分析
面试必备2:JDK1.8LinkedHashMap实现原理及源码分析
Android事件分发机制原理及源码分析
View事件的滑动冲突以及解决方案
Handler机制一篇文章深入分析Handler、Message、MessageQueue、Looper流程和源码
Android三级缓存原理及用LruCache、DiskLruCache实现一个三级缓存的ImageLoader
本文是在上文Android framework 源码分析之Activity启动流程(android 8.0)的基础上多应用进程创建、启动以及进程启动后启动activity过程分析。中间涉及Launcher、AMS、Binder、Process、LocalSocket、Zygote、fork等知识。
上一篇文章中对Activity的启动流程做了详细的分析,在第三部分的Step13中ActivityStackSupervisor类的startSpecificActivityLocked
方法中分析到如果activity所在进程已经启动的情况,今天就来分析一下进程未启动的情况,即App的启动流程。
其实app的启动最后也是通过调用Activity的startActivity方法,最终走到上图中AMS的startProcessLocked
方法,在startProcessLocked
先去启动App所在的进程,启动这个进程的过程牵扯了:Zygote
进程和 system_server
进程,在这个过程中所有跨进城都离不开Binder机制。
1:APP启动的入口Launcher的分析
Android 系统启动后已经启动了 Zygote,ServiceManager,SystemServer 等系统进程;ServiceManager 进程中完成了 Binder 初始化;SystemServer 进程中 ActivityManagerService,WindowManagerService,PackageManagerService 等系统服务在 ServiceManager 中已经注册;最后启动了 Launcher 桌面应用。
Launcher本神就是一个应用,被系统启动,这里不详细分析分析Launcher的源码,我们从点击桌面上的图标入手分析,即启动APP的入口
Step1: Launcher中条目的点击监听的onClick方法开始:
/**
* Launches the intent referred by the clicked shortcut.
* 启动被单击的快捷方式引用的意图
*/
public void onClick(View v) {
....代码
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {
onClickAppShortcut(v);
} else if (tag instanceof FolderInfo) {
if (v instanceof FolderIcon) {
onClickFolderIcon(v);
}
} else if ((v instanceof PageIndicator) ||
(v == mAllAppsButton && mAllAppsButton != null)) {
onClickAllAppsButton(v);
} else if (tag instanceof AppInfo) {//如果属于AppInfo,里面包含了启动的APP的信息
//交给startAppShortcutOrInfoActivity 去处理
startAppShortcutOrInfoActivity(v);
} else if (tag instanceof LauncherAppWidgetInfo) {
if (v instanceof PendingAppWidgetHostView) {
onClickPendingWidget((PendingAppWidgetHostView) v);
}
}
}
经过一些简单校验交给交给startAppShortcutOrInfoActivity
去处理。
Step2: Launcher的startAppShortcutOrInfoActivity
方法启动APP:
private void startAppShortcutOrInfoActivity(View v) {
...省略部分代码,主要是对intent进行校验
//交给startActivitySafely去启动
boolean success = startActivitySafely(v, intent, item);
getUserEventDispatcher().logAppLaunch(v, intent); // TODO for discovered apps b/35802115
if (success && v instanceof BubbleTextView) {
mWaitingForResume = (BubbleTextView) v;
mWaitingForResume.setStayPressed(true);
}
}
首先对intent进行校验,最终将将启动任务交给了startActivitySafely
方法
Step3: Launcher的startActivitySafely
方法启动APP:
public boolean startActivitySafely(View v, Intent intent, ItemInfo item) {
...省略部分代码
try {
if (Utilities.ATLEAST_MARSHMALLOW
&& (item instanceof ShortcutInfo)
&& (item.itemType == Favorites.ITEM_TYPE_SHORTCUT
|| item.itemType == Favorites.ITEM_TYPE_DEEP_SHORTCUT)
&& !((ShortcutInfo) item).isPromise()) {
//快捷启动需要进行一些校验
startShortcutIntentSafely(intent, optsBundle, item);
} else if (user == null || user.equals(Process.myUserHandle())) {
// 最终执行父类Activity的startActivity方法
startActivity(intent, optsBundle);
}
...省略代码
return false;
}
**小结:**这startActivitySafely方法中,最终将启动任务交给了父类Activity的startActivity方法去启动APP,自己在进入onPause状态。自此APP的的启动流程就进入了Activity的启动流程,如果没有看过请先阅读我的第一篇文章Android framework 源码分析之Activity启动流程(android 8.0)
2:APP的启动在Activity中启动过程
在Activity中启动过程在Android framework 源码分析之Activity启动流程(android 8.0)中已做了详细分析,都是从Activity的startActivityForResult开始一直到上文Step12 都是一致的在此不做分析,接下来我们着重看一下Step13ActivityStackSupervisor
类的startSpecificActivityLocked
方法
Step4: ActivityStackSupervisor的startSpecificActivityLocked
方法启动分析:
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
if (app != null && app.thread != null) {
//app进程已经在运行,直接去启动
try {
if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0
|| !"android".equals(r.info.packageName)) {
// Don't add this if it is a platform component that is marked
// to run in multiple processes, because this is actually
// part of the framework so doesn't make sense to track as a
// separate apk in the process.
//如果它是一个被标记为在多个进程中运行的平台组件,那么不要添加它,因为它实际上是框架的一部分,所以在进程中作为单独的apk进行跟踪是没有意义的
app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode,
mService.mProcessStats);
}
//重点:将activity的启动工作转交给realStartActivityLocked方法
realStartActivityLocked(r, app, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
}
// 如果进程为app 为null或者有异常,则AMS重新fork一个进程来起来,点击桌面启动图标如果该应用进程未启动,走到这里
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
分析:
startSpecificActivityLocked方法逻辑比较简单,主要负责跟要启动的Activity进程相关的工作,首先由AMS根据参数通过getProcessRecordLocked
方法获取当前APP进程的记录ProcessRecord ,如果获取到ProcessRecord即应用所在进程已经启动,则执行realStartActivityLocked
方法,否则应用进程未启动,则交给AMS的startProcessLocked
方法去启动该进程。
至于方法里if里面realStartActivityLocked
方法的内容已经在上文中分析了,接下来我们继续分析else部分的逻辑,即APP的启动。
3:APP的启动在AMS中启动过程
Step5: ActivityManagerService的startProcessLocked
方法去启动进程的逻辑分析:
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
//调用它的重载方法,需要注意的是,加入一个参数叫做entryPoint,并且参数为null
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
继续分析重载方法
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;
// isolated表示当前需要启动的app是不是一个独立的进程,如果是独立的话那就重新
// 创建一个ProcessRecord,如果不是的话那就从正在运行的进程列表中找。
if (!isolated) {
//根据进程名和进程uid获取进程对应的ProcessRecord,ProcessRecord封装了正在运行的进程的完整信息
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
....省略部分代码
// 这是一个独立的进程或者在正在运行的列表中没有找到相应的记录
if (app == null) {
checkTime(startTime, "startProcess: creating new process record");
//创建ProcessRecord
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
Slog.w(TAG, "Failed making new process record for "
+ processName + "/" + info.uid + " isolated=" + isolated);
return null;
}
//一堆赋值操作
app.crashHandler = crashHandler;
app.isolatedEntryPoint = entryPoint;
app.isolatedEntryPointArgs = entryPointArgs;
checkTime(startTime, "startProcess: done creating new process record");
} else {
// // 如果这是该进程中的一个新的package,那就添加到package列表
// If this is a new package in the process, add the package to the list
app.addPackage(info.packageName, info.versionCode, mProcessStats);
checkTime(startTime, "startProcess: added package to existing proc");
}
// 如果系统还没有准备就绪,那就暂停该进程启动,将当前进程加入到mProcessesOnHold,直到准备就绪
if (!mProcessesReady
&& !isAllowedWhileBooting(info)
&& !allowWhileBooting) {
if (!mProcessesOnHold.contains(app)) {
mProcessesOnHold.add(app);
}
if (DEBUG_PROCESSES) Slog.v(TAG_PROCESSES,
"System not ready, putting on hold: " + app);
checkTime(startTime, "startProcess: returning with proc on hold");
return app;
}
checkTime(startTime, "startProcess: stepping in to startProcess");
//重点,经过上面判断如果需要创建进程,最终交给 startProcessLocked方法去创建进程,注意这个方法的返回值boolean
final boolean success = startProcessLocked(app, hostingType, hostingNameStr, abiOverride);
checkTime(startTime, "startProcess: done starting proc!");
return success ? app : null;
}
**分析:这里逻辑比较简单, 这里再次检查是否已经有以process + uid命名的进程存在,如果我们首次启动这个app,则app==null,因此,后面会创建一个ProcessRecord,并存保存在成员变量mProcessNames中,最终即进程的启动交给了startProcessLocked 方法,注意此方法的返回值是boolean。
Step6: AMS的boolean startProcessLocked
方法分析:
private final boolean startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr, String abiOverride) {
//继续调用重载方法传入参数disableHiddenApiChecks 为false
return startProcessLocked(app, hostingType, hostingNameStr,
false /* disableHiddenApiChecks */, abiOverride);
}
继续分析重载方法
private final boolean startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) {
....省略部分代码,这着重看流程
//重点: 这里给一开传进来的entryPoint赋值给"android.app.ActivityThread"后面通过它进行反射来调用ActivityThread 的main方法
final String entryPoint = "android.app.ActivityThread";
//最后交给重载方法startProcessLocked去完成启动进程的工作
return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
startTime);
} catch (RuntimeException e) {
Slog.e(TAG, "Failure starting process " + app.processName, e);
//异常时强制停止启动
forceStopPackageLocked(app.info.packageName, UserHandle.getAppId(app.uid), false,
false, true, false, false, UserHandle.getUserId(app.userId), "start failure");
return false;
}
}
继续分析其重载方法:
private boolean startProcessLocked(String hostingType, String hostingNameStr, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
//给ProcessRecord的一些属性进行一波赋值操作
app.pendingStart = true;
app.killedByAm = false;
app.removed = false;
app.killed = false;
final long startSeq = app.startSeq = ++mProcStartSeqCounter;
app.setStartParams(uid, hostingType, hostingNameStr, seInfo, startTime);
if (mConstants.FLAG_PROCESS_START_ASYNC) {//异步时
if (DEBUG_PROCESSES) Slog.i(TAG_PROCESSES,
"Posting procStart msg for " + app.toShortString());
mProcStartHandler.post(() -> {
try {
...省略部分代码
}
//最终调用startProcess去启动
final ProcessStartResult startResult = startProcess(app.hostingType, entryPoint,
app, app.startUid, gids, runtimeFlags, mountExternal, app.seInfo,
requiredAbi, instructionSet, invokeWith, app.startTime);
synchronized (ActivityManagerService.this) {
handleProcessStartedLocked(app, startResult, startSeq);
}
} catch (RuntimeException e) {
//异常时强制停止启动
}
});
return true;
} else {
try {
//最终调用startProcess去启动
final ProcessStartResult startResult = startProcess(hostingType, entryPoint, app,
uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
invokeWith, startTime);
handleProcessStartedLocked(app, startResult.pid, startResult.usingWrapper,
startSeq, false);
} catch (RuntimeException e) {
//异常时强制停止启动
}
return app.pid > 0;
}
}
分析:经过上面无论if还是else,最终将启动进程的工作转移到startProcess
方法上
Step7: AMS的startProcess
方法启动分析:
private ProcessStartResult startProcess(String hostingType, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
try {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
final ProcessStartResult startResult;
if (hostingType.equals("webview_service")) {
//在最初ActivityStackSupervisor的startSpecificActivityLocked方法那可以看出传入的hostingType 等于activity,所以if语句不执行
startResult = startWebView(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, null,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
} else {
//最终执行到这 这里主要是调用Process.start接口来创建一个新的进程,成功后会返回进程的pid foui 否则就会抛出异常, 需要注意的是这个过程是一个阻塞过程, 还有传入的entryPoint值就是上面传入的android.app.ActivityThread
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
}
checkTime(startTime, "startProcess: returned from zygote!");
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
分析:
最后是通过Process.start
来创建应用进程;原理是通过socket向Zygote进程发送创建新进程的请求;Zygote进程启动后有一个runSelectLoop
循环,当收到客户端请求便会执行ZygoteConnection.runOnce()
方法,再经过层层调用后fork出新的应用进程,创建新进程后将ActivityThread类加载到新进程,并反射调用ActivityThread.main()方法,就这样创建进程的启动app的任务就转移到Process的start
方法中。接下来我就来详细分析这个流程。
4:Process、ZygoteProcess的启动过程
Step8: **Process的star
方法分析:
/**
* 需要注意processClass参数就是上文提到entryPoint的值 android.app.ActivityThread
*/
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
这个方法的逻辑比较简单主要是通过 ZygoteProcess的start
方法创建新进程。
Step9: ZygoteProcess的startProcess
方法分析:
public final Process.ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
try {
//最后交给startViaZygote方法去创建新进程
return startViaZygote(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */,
zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}
Step10: ZygoteProcess的startViaZygote
方法创建进程的过程分析:
先大致说明一下接下来的工作流程:在Process类的startViaZygote方法里,会计算启动应用进程用的各个参数,然后再调用zygoteSendArgsAndGetResult方法将这些参数通过socket发送给zygote进程,zygote进程会孵化出新的dalvik应用进程,然后告诉ActivityManagerService新启动的进程的pid。接下来我们将详细分析这一过程。
private Process.ProcessStartResult startViaZygote(final String processClass,
final String niceName,
final int uid, final int gid,
final int[] gids,
int runtimeFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
boolean startChildZygote,
String[] extraArgs)
throws ZygoteStartFailedEx {
ArrayList<String> argsForZygote = new ArrayList<String>();
...省略部分代码 主要是将进程相关的uid、gid等一系列信息保存到argsForZygote集合中
synchronized(mLock) {
//最终将创建进程的工作交过zygoteSendArgsAndGetResult方法
//需要注意的是第一个参数是通过openZygoteSocketIfNeeded方法去构建的,几下来就依次分析这两个方法
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
分析:这个方法逻辑比较简单,首先是将进程相关的信息保存到argsForZygote
集合中,并将该集合作为参数,交给zygoteSendArgsAndGetResult方法去创建进程,需要注意的是第一个参数是通过openZygoteSocketIfNeeded方法去构建的。
Step11: ZygoteProcess的openZygoteSocketIfNeeded
方法分析:
private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx {
Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held");
// 调用该方法时传入的参数就是上面我们说 的abi了,也就是我们要启动的目标进程到底是调用Zygote32来fork,还是调用Zygote64来fork
if (primaryZygoteState == null || primaryZygoteState.isClosed()) {
//primaryZygoteState是否为空或者已经关闭
try {
//调用ZygoteState.connect(mSocket),尝试与Zygote进程建立socket连接
primaryZygoteState = ZygoteState.connect(mSocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe);
}
maybeSetApiBlacklistExemptions(primaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState);
}
//然后去匹配abi
if (primaryZygoteState.matches(abi)) {
//如果成功则返回ZygoteState来启动目标进程
return primaryZygoteState;
}
// The primary zygote didn't match. Try the secondary.
// //当主zygote没能匹配成功,则采用第二个zygote,发起connect()操作,逻辑和上面一样
if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) {
try {
secondaryZygoteState = ZygoteState.connect(mSecondarySocket);
} catch (IOException ioe) {
throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe);
}
maybeSetApiBlacklistExemptions(secondaryZygoteState, false);
maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState);
}
//根据abi去匹配
if (secondaryZygoteState.matches(abi)) {
return secondaryZygoteState;
}
//如果都匹配失败则直接抛出ABI
throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi);
}
分析:简单总结一下openZygoteSocketIfNeeded
,通过ZygoteState.connect
方法尝试与Zygote进程建立socket连接,返回一个ZygoteStatee
连接状态,拿到这个ZygoteState连接状态后就可以进行写操作,而与之建立连接的Zygote进程会读取到这个信息。
Step12: ZygoteProcess的静态内部类ZygoteState的connect
方法分析:
public static class ZygoteState {
final LocalSocket socket;
final DataInputStream inputStream;
final BufferedWriter writer;
final List<String> abiList;
boolean mClosed;
private ZygoteState(LocalSocket socket, DataInputStream inputStream,
BufferedWriter writer, List<String> abiList) {
this.socket = socket;
this.inputStream = inputStream;
this.writer = writer;
this.abiList = abiList;
}
//重点:传进来本地Socket的地址
public static ZygoteState connect(LocalSocketAddress address) throws IOException {
DataInputStream zygoteInputStream = null;
BufferedWriter zygoteWriter = null;
//传说中的Socket
final LocalSocket zygoteSocket = new LocalSocket();
try {
//建立LocalSocket 连接,根据地址LocalSocketAddress
zygoteSocket.connect(address);
//指向zygoteSocket输入
zygoteInputStream = new DataInputStream(zygoteSocket.getInputStream());
//指向zygoteSocket输出
zygoteWriter = new BufferedWriter(new OutputStreamWriter(zygoteSocket.getOutputStream()), 256);
} catch (IOException ex) {
try {
zygoteSocket.close();
} catch (IOException ignore) {
}
throw ex;
}
//获取zygote 进程支持的 ABI类标Application Binary Interface
String abiListString = getAbiList(zygoteWriter, zygoteInputStream);
Log.i("Zygote", "Process: zygote socket " + address.getNamespace() + "/"
+ address.getName() + " opened, supported ABIS: " + abiListString);
//通过socket 输入 输出 abi 列表创建 ZygoteState
return new ZygoteState(zygoteSocket, zygoteInputStream, zygoteWriter,
Arrays.asList(abiListString.split(",")));
}
boolean matches(String abi) {
return abiList.contains(abi);
}
public void close() {
try {
socket.close();
} catch (IOException ex) {
Log.e(LOG_TAG,"I/O exception on routine close", ex);
}
mClosed = true;
}
boolean isClosed() {
return mClosed;
}
}
分析:ZygoteState内部类的主要作:表示和Zygote进程的连接状态,里面有几个成员变量存储LocalSocket ,以及指向LocalSocket的输入、输出流等。而里面的connect
方法就是初始化这些变量,创建并返回ZygoteState。这里需要简单分析一下LocalSocket和connect方法的参数LocalSocketAddress 。
小插曲LocalSocket、LocalSocketAddress 和LocalServerSocket的关系
这里只是简单看一下远离流程以及它们之间的关系,至于他们的详细源码就不一一贴出分析了。
LocalSocketAddress 就是LocalSocket的地址看看它的初始化过程:
1: public static ZygoteState connect(LocalSocketAddress address)
方法中传进来的LocalSocketAddress
就是ZygotePrecess的成员变量,初始化是在构造器中,如下图:
2:接下来再看看ZygotePrecess构造器中的参数是什么:ZygotePrecess构造器在Precess中调用
接下来再说说LocalSocket和LocalServerSocket的关系:他门俩个之间的关系类似于Socket编程中:Socekt和ServerSocket的关系
平时用到的Socket,Socket通常是为了方便**两台不同的机器之间的通信,**它封装了TCP/IP协议,向外提供一些API简化了网络通信过程,可以实现不同层面,不同应用,跨进程跨网络的通信;一般由Socket(client)和ServerSocket(Server)组成通信双方。
而Android中的LocalSocket是基于UNIX-domain Socket的,UNIX-domain Socket是在Socket的基础上衍生出来的一种IPC通信机制,**因此LocalSocket解决的是同一台主机上不同进程间互相通信的问题。其相对于网络通信使用的socket不需要经过网络协议栈,不需要打包拆包、计算校验,自然的执行效率也高。**与binder机制作用一样,都在Android系统中作为IPC通信手段被广泛使用;一般由LocalSocket(Client)和LocalServerSocket(Server)组成通信双方。
那么在本文中AMS所在的system-server进程就充当了Client,zygote进程充当Server,因为zygote进程在创建的时候会在ZygoteInit.main方法中调用ZygoteInit.registerZygoteSocket方法,会实例化一个LocalServerSocket,并且在ZygoteInit.runSelectLoop方法中不停的获取客户端的请求。
关于LocalSocket、LocalSocketAddress 和LocalServerSocket分析先到这里,详细源码我就不在这里粘出了,接下我们继续回到ZygoteProcess的zygoteSendArgsAndGetResult
方法,通过LocalSocket发送参数给Zygote进程。
Step13: ZygoteProcess的zygoteSendArgsAndGetResult
方法分析:
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
try {
//首先校验上一步传递过来的参数格式,如果参数不合法,抛出异常
int sz = args.size();
for (int i = 0; i < sz; i++) {
if (args.get(i).indexOf('\n') >= 0) {
throw new ZygoteStartFailedEx("embedded newlines not allowed");
}
}
/**
* See com.android.internal.os.SystemZygoteInit.readArgumentList()
* Presently the wire format to the zygote process is:
* a) a count of arguments (argc, in essence)
* b) a number of newline-separated argument strings equal to count
*
* After the zygote process reads these it will write the pid of
* the child or -1 on failure, followed by boolean to
* indicate whether a wrapper process was used.
*/
//通过连接状态 获取输入输出流
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
//将参数通过Socket写出去,至于从哪里读,请看上面的英文注解,至于读取将在ZygoteInit类中找
writer.write(Integer.toString(args.size()));
writer.newLine();
for (int i = 0; i < sz; i++) {
String arg = args.get(i);
writer.write(arg);
writer.newLine();
}
writer.flush();
// Should there be a timeout on this?
// 新建进程启动结果类,把新建的结果例如进程pid等赋值给这个结果类,用来返回
Process.ProcessStartResult result = new Process.ProcessStartResult();
// Always read the entire result from the input stream to avoid leaving
// bytes in the stream for future process starts to accidentally stumble
// upon.
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
//将启动结果返回
return result;
} catch (IOException ex) {
zygoteState.close();
throw new ZygoteStartFailedEx(ex);
}
}
分析 :这里zygoteSendArgsAndGetResult
方法,通过上一步中的连接状态获取输出流,将创建进程的参数通过Socket发送给给Zygote进程,通知Zygote去创建进程,并返回结果。Zygote进程是在系统启动初始化的,Zygote在启动之后开启了socket 监听功能,监听需要创建 Process 的请求,关于zygote进程什么时候开启这个socket的需要去看Zygote的源码。
这里为止,创建APP进程的工作交给了Zygote进程去完成。
5:Zygote完成创建APP进程的过程:ZygoteInit、ZygoteServer和ZygoteConnection
Zygote进程是在Android系统启动时就会完成Zygote的启动,在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,关于Zygote的启动以后我会单独写一篇文章去分析,在这里我将详细分析一下Zygote进程作为服务端什么时候开启的Socket监听,完成进程的创建过并将进程pid返回的过程,而这个过程与ZygoteInit、ZygoteServer和ZygoteConnection
三个类密切相关。
Zygote进程启动的时候会调用ZygoteInit的main方法接下我将从它入手。
Step14: ZygoteInit的main
方法分析:
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
//...省略部分代码
try {
//...省略部分代码
if (abiList == null) {
throw new RuntimeException("No ABI list supplied.");
}
//为Zygote注册socket监听 :LocalServerSocket,具源码很简单,就不在下面粘贴了,感兴趣和可以自己查阅
zygoteServer.registerServerSocketFromEnv(socketName);
//...省略部分代码
//初始化Zygote进程 非重点
Zygote.nativeSecurityInit();
//...省略部分代码
// The select loop returns early in the child process after a fork and
// loops forever in the zygote.
//进入循环模式,通过zygoteServer获取客户端Socket连接并处理
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
Log.e(TAG, "System zygote died with exception", ex);
throw ex;
} finally {
zygoteServer.closeServerSocket();
}
// We're in the child process and have exited the select loop. Proceed to execute the
// command.
if (caller != null) {
caller.run();
}
}
分析:在 ZygoteInit的main
方法中为通过zygoteServer.registerServerSocketFromEnv
方法为Zygote注册socket
监听LocalServerSocket
;并开启循环,通过zygoteServer的runSelectLoop(abiList)
方法获取客户端Socket连接并处理。至于注册socket
监听LocalServerSocket
的过程比较简单就不在这里分析了,接下来着重分析runSelectLoop(abiList)
获取客户端Socket连接并处理的过程。
Step15: ZygoteServer的runSelectLoop
方法分析:
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
// sServerSocket是socket通信中的服务端,即zygote进程。保存到fds[0]
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);
//开启循环
while (true) {
// ...省略部分源码
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
try {
//处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
Os.poll(pollFds, -1);
Os.poll(pollFds, -1);
} catch (ErrnoException ex) {
throw new RuntimeException("poll failed", ex);
}
for (int i = pollFds.length - 1; i >= 0; --i) {
if ((pollFds[i].revents & POLLIN) == 0) {
continue;
}
// 即fds[0],代表的是sServerSocket,则意味着有客户端连接请求;
// 则创建ZygoteConnection对象,并添加到peers
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
//i>0,则代表通过socket接收来自对端的数据,并执行相应操作
try {
//通过processOneCommand去处理客户端发来的Socket请求
ZygoteConnection connection = peers.get(i);
final Runnable command = connection.processOneCommand(this);
if (mIsForkChild) {
//Set by the child process, immediately after a call to {@code Zygote.forkAndSpecialize}.
//由子进程设置,后立即调用Zygote.forkAndSpecialize
if (command == null) {
throw new IllegalStateException("command == null");
}
return command;
} else {
// We're in the server - we should never have any commands to run.
if (command != null) {
throw new IllegalStateException("command != null");
}
// We don't know whether the remote side of the socket was closed or
// not until we attempt to read from it from processOneCommand. This shows up as
// a regular POLLIN event in our regular processing loop.
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(i);
fds.remove(i);
}
}
} catch (Exception e) {
//...省略异常信息的处理
}
} finally {
// Reset the child flag, in the event that the child process is a child-
// zygote. The flag will not be consulted this loop pass after the Runnable
// is returned.
mIsForkChild = false;
}
}
}
}
}
继续分析ZygoteConnection 的 connection.processOneCommand(this)
方法如何处理客户端发送来的请求
Step16: ZygoteConnection的processOneCommand
方法分析:
/**
* Reads one start command from the command socket. If successful, a child is and a
* {@code Runnable} that calls the childs main method (or equivalent) is returned in the child
* process. {@code null} is always returned in the parent process (the zygote).
* If the client closes the socket, an {@code EOF} condition is set, which callers can test
* for by calling {@code ZygoteConnection.isClosedByPeer}.
*/
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
try {
//读取上文提到client端发送来创建进程需要的参数列表
args = readArgumentList();
descriptors = mSocket.getAncillaryFileDescriptors();
} catch (IOException ex) {
throw new IllegalStateException("IOException on command socket", ex);
}
// readArgumentList returns null only when it has reached EOF with no available
// data to read. This will only happen when the remote socket has disconnected.
//readArgumentList只有在到达EOF且没有可用数据可读时才返回null。这只会在客户端断开连接时发生。
if (args == null) {
isEof = true;
return null;
}
int pid = -1;
FileDescriptor childPipeFd = null;
FileDescriptor serverPipeFd = null;
//将从客户端读取来的参数封装成 Arguments对象
parsedArgs = new Arguments(args);
//... 省略部分代码
fd = null;
//通过Zygote进程的forkAndSpecialize方法去创建进程,并返回进程的pid
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote,
parsedArgs.instructionSet, parsedArgs.appDataDir);
//上面创建进程,下面负责启动
try {
//Zygote 创建进程完成后 将分成一下两种情况处理
if (pid == 0) {
// in child 当前返回的是子进程
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
//子进程处理流程
return handleChildProc(parsedArgs, descriptors, childPipeFd,
parsedArgs.startChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in
// handleParentProc. 当前返回的是父进程 ,Zygote进程
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
//父进程处理
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
} finally {
IoUtils.closeQuietly(childPipeFd);
IoUtils.closeQuietly(serverPipeFd);
}
}
分析: processOneCommand
方法首先读取客户端发送过来的参数列表,并将这些参数列表封装成Arguments
对象,并交给Zygote.forkAndSpecialize
去完成进程的创建工作,并返回目标进程的pid,再往下就是根据pid==0说明当前返回的是子进程,交给handleChildProc
方法去处理;否则返回的是父进程交给handleParentProc
去处理。
Step17: Zygote的forkAndSpecialize
方法分析:
public static int forkAndSpecialize(int uid, int gid, int[] gids, int runtimeFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir) {
//调用preFork方法做一些准备工作
//这个方法的主要目的是停止zygote进程的四个daemon子线程,分别是ReferenceQueueDaemon,FinalizerDaemon,FinalizerWatchdogDaemon,HeapTaskDaemon;
//直到zygote是是单线程,以便于提高fork效率;
VM_HOOKS.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
//重点是调用这个native方法去创建进程返回进程的pid,这个过程经过JNI完成的
int pid = nativeForkAndSpecialize(
uid, gid, gids, runtimeFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, startChildZygote, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
if (pid == 0) {
Trace.setTracingEnabled(true, runtimeFlags);
// Note that this event ends at the end of handleChildProc,
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "PostFork");
}
VM_HOOKS.postForkCommon();
return pid;
}
//nativie 接口 它的实现完成进程的创建工作
native private static int nativeForkAndSpecialize(int uid, int gid, int[] gids,int runtimeFlags,int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose, int[] fdsToIgnore, boolean startChildZygote, String instructionSet, String appDataDir);
分析: forkAndSpecialize
方法逻辑比较简单首先通过VM_HOOKS.preFork()为创建进程做一些准备工作,然后调用native方法nativeForkAndSpecialize
去完成具体创建进程的工作。
Native层调用Linux系统fork函数完成创建进程的过程
接下来看看native方法nativeForkAndSpecialize
的实现,此方法的实现是在com_android_internal_os_Zygote.cpp
文件中,目录路径为:frameworks\base\core\jni\com_android_internal_os_Zygote.cpp
Step18: native的nativeForkAndSpecialize
方法:
static jint com_android_internal_os_Zygote_nativeForkAndSpecialize(
JNIEnv* env, jclass, jint uid, jint gid, jintArray gids,
jint debug_flags, jobjectArray rlimits,
jint mount_external, jstring se_info, jstring se_name,
jintArray fdsToClose,
jintArray fdsToIgnore,
jstring instructionSet, jstring appDataDir) {
jlong capabilities = 0;
if (multiuser_get_app_id(uid) == AID_BLUETOOTH) {
capabilities |= (1LL << CAP_WAKE_ALARM);
capabilities |= (1LL << CAP_NET_RAW);
capabilities |= (1LL << CAP_NET_BIND_SERVICE);
capabilities |= (1LL << CAP_SYS_NICE);
}
// Grant CAP_BLOCK_SUSPEND to processes that belong to GID "wakelock"
bool gid_wakelock_found = false;
if (gid == AID_WAKELOCK) {
gid_wakelock_found = true;
} else if (gids != NULL) {
jsize gids_num = env->GetArrayLength(gids);
ScopedIntArrayRO ar(env, gids);
if (ar.get() == NULL) {
RuntimeAbort(env, __LINE__, "Bad gids array");
}
for (int i = 0; i < gids_num; i++) {
if (ar[i] == AID_WAKELOCK) {
gid_wakelock_found = true;
break;
}
}
}
if (gid_wakelock_found) {
capabilities |= (1LL << CAP_BLOCK_SUSPEND);
}
//最终将创建进程的工作交给ForkAndSpecializeCommon方法去完成
return ForkAndSpecializeCommon(env, uid, gid, gids, debug_flags,
rlimits, capabilities, capabilities, mount_external, se_info,
se_name, false, fdsToClose, fdsToIgnore, instructionSet, appDataDir);
}
Step19: native的ForkAndSpecializeCommon
方法:
static pid_t ForkAndSpecializeCommon(JNIEnv*env, uid_t uid, gid_t gid, jintArray javaGids,
jint debug_flags, jobjectArray javaRlimits,
jlong permittedCapabilities, jlong effectiveCapabilities,
jint mount_external,
jstring java_se_info, jstring java_se_name,
bool is_system_server, jintArray fdsToClose,
jintArray fdsToIgnore,
jstring instructionSet, jstring dataDir) {
//设置子进程的signal信号处理函数
SetSigChldHandler();
sigset_t sigchld;
sigemptyset( & sigchld);
sigaddset( & sigchld, SIGCHLD);
//... 省略部分代码
// 重点:fork是Linux的系统函数,是真正执行复制进程的工作,因为Zygote进程的权限很高,
// fork方法会一模一样的复制Zygote作为我们要创建的目标进程,这样的话就会导致目标应用进程也有很高的权限去操作各种文件
// fork出来的进程就是我们要启动的进程,接下来我们要为目标进程设置一系列的属性
pid_t pid = fork();
if (pid == 0) {//进入子进程
// The child process.
gMallocLeakZygoteChild = 1;
// Set the jemalloc decay time to 1.
mallopt(M_DECAY_TIME, 1);
// Clean up any descriptors which must be closed immediately
//关闭并清除文件描述符
DetachDescriptors(env, fdsToClose);
//... 省略部分代码
if (!is_system_server) {
//对于非system_server子进程,则创建进程组
int rc = createProcessGroup(uid, getpid());
if (rc != 0) {
if (rc == -EROFS) {
ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
} else {
ALOGE("createProcessGroup(%d, %d) failed: %s", uid, pid, strerror(-rc));
}
}
}
//下面为目标进程的属性赋值
//设置group
SetGids(env, javaGids);
//设置调度策略
SetRLimits(env, javaRlimits);
if (use_native_bridge) {
ScopedUtfChars isa_string (env, instructionSet);
ScopedUtfChars data_dir (env, dataDir);
android::PreInitializeNativeBridge (data_dir.c_str(), isa_string.c_str());
}
//设置目标进程的gid
int rc = setresgid(gid, gid, gid);
if (rc == -1) {
ALOGE("setresgid(%d) failed: %s", gid, strerror(errno));
RuntimeAbort(env, __LINE__, "setresgid failed");
}
//设置目标进程的uid
rc = setresuid(uid, uid, uid);
if (rc == -1) {
ALOGE("setresuid(%d) failed: %s", uid, strerror(errno));
RuntimeAbort(env, __LINE__, "setresuid failed");
}
if (NeedsNoRandomizeWorkaround()) {
// Work around ARM kernel ASLR lossage (http://b/5817320).
int old_personality = personality(0xffffffff);
int new_personality = personality(old_personality | ADDR_NO_RANDOMIZE);
if (new_personality == -1) {
ALOGW("personality(%d) failed: %s", new_personality, strerror(errno));
}
}
SetCapabilities(env, permittedCapabilities, effectiveCapabilities, permittedCapabilities);
//为目标进程设置调度策略
SetSchedulerPolicy(env);
//... 省略部分代码
//在Zygote子进程中,设置信号SIGCHLD的处理器恢复为默认行为
UnsetSigChldHandler();
// 等价于调用zygote.callPostForkChildHooks()
env -> CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, debug_flags,
is_system_server, instructionSet);
if (env -> ExceptionCheck()) {
RuntimeAbort(env, __LINE__, "Error calling post fork hooks.");
}
} else if (pid > 0) {
// the parent process 进入父进程,即Zygote进程
// We blocked SIGCHLD prior to a fork, we unblock it here.
if (sigprocmask(SIG_UNBLOCK, & sigchld,nullptr) ==-1){
ALOGE("sigprocmask(SIG_SETMASK, { SIGCHLD }) failed: %s", strerror(errno));
RuntimeAbort(env, __LINE__, "Call to sigprocmask(SIG_UNBLOCK, { SIGCHLD }) failed.");
}
}
return pid;
}
分析: ForkAndSpecializeCommon
方法最核心的就是pid_t pid = fork()
,通过Linux的fork机制复制Zygote进程作为要启动的目标进程,接下来在为复制的目标进程的属性赋值,最后返回目标进程的pid。到这里就回到Step16: ZygoteConnection中processOneCommand
方法创建进程后子进程(即目标进程)的处理流程,即handleChildProc
方法;看下图:
Step20: ZygoteConnection的handleChildProc
方法:
private Runnable handleChildProc(Arguments parsedArgs, FileDescriptor[] descriptors,
FileDescriptor pipeFd, boolean isZygote) {
/**
* By the time we get here, the native code has closed the two actual Zygote
* socket connections, and substituted /dev/null in their place. The LocalSocket
* objects still need to be closed properly.
*/
//关闭Socket
closeSocket();
if (descriptors != null) {
try {
Os.dup2(descriptors[0], STDIN_FILENO);
Os.dup2(descriptors[1], STDOUT_FILENO);
Os.dup2(descriptors[2], STDERR_FILENO);
for (FileDescriptor fd: descriptors) {
IoUtils.closeQuietly(fd);
}
} catch (ErrnoException ex) {
Log.e(TAG, "Error reopening stdio", ex);
}
}
if (parsedArgs.niceName != null) {
//设置进程名
Process.setArgV0(parsedArgs.niceName);
}
// End of the postFork event.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//应用进程首次启动时,parsedArgs.invokeWith参数为空,所以执行else
if (parsedArgs.invokeWith != null) {
WrapperInit.execApplication(parsedArgs.invokeWith,
parsedArgs.niceName, parsedArgs.targetSdkVersion,
VMRuntime.getCurrentInstructionSet(),
pipeFd, parsedArgs.remainingArgs);
// Should not get here.
throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned");
} else {
/**
* isZygote :whether this new child process is itself a new Zygote
* isZygote来自上面的parsedArgs中的startChildZygote属性---》 parsedArgs = new Arguments(args);
* args上面分析过是从客户端发来的参数---》去客户端发送参数那看:
* 可以追踪到ZygotePrecess类的startViaZygote方法:再startViaZygote方法中的参数 boolean startChildZygote
* 传进来 是 false
* 所以:这里 isZygote 为false !isZygote 为true
*/
if (!isZygote) {
//所以会执行这里
return ZygoteInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs,
null /* classLoader */);
} else {
//启动一个子的Zygote
return ZygoteInit.childZygoteInit(parsedArgs.targetSdkVersion,
parsedArgs.remainingArgs, null /* classLoader */);
}
}
}
分析: handleChildProc
这个方法逻辑比较简单,注释也标注的很清楚,最后交给了 ZygoteInit的zygoteInit
方法去处理。
Step21: ZygoteInit的zygoteInit
方法分析:
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) {
if (RuntimeInit.DEBUG) {
Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
}
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
///把标准输出和标准错误重定向给log.i和log.e
RuntimeInit.redirectLogStreams();
//针对日志和异常处理进行初始化
RuntimeInit.commonInit();
//这里的作用是在新进程中引入Binder,也就说通过nativeZygoteInit以后,新的进程就可以使用Binder进程通信了。
ZygoteInit.nativeZygoteInit();
//初始化我们的应用进程。重点
return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);
}
**分析:**最后就是调用RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader)来初始化我们的应用程序。继续往下看。
Step22: RuntimeInit的applicationInit
方法分析:
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
ClassLoader classLoader) {
//如果应用程序调用System.exit(),则终止进程
nativeSetExitWithoutCleanup(true);
// We want to be fairly aggressive about heap utilization, to avoid
// holding on to a lot of memory that isn't needed.
//我们希望相当积极地处理堆利用率,以避免占用大量不需要的内存。
VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
//传入的参数封装成一个Arguments对象
final Arguments args = new Arguments(argv);
// The end of of the RuntimeInit event (see #zygoteInit).
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// 会通过调用findStaticMain来调用args.startClass这个类的main()方法。
// 在前面介绍socket的客户端代码时,在startProcessLocked()中传入的这个类为"android.app.ActivityThread"。
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
分析: 在applicationInit() 方法的最后,会通过调用findStaticMain
来调用args.startClass
这个类的main()
方法。在前面介绍socket的客户端代码时,在startProcessLocked()
中传入的这个类为"android.app.ActivityThread
"。所以接下来findStaticMain()
的主要功能就是通过反射调用调用ActivityThread类的main()方法
Step23: RuntimeInit的findStaticMain
方法分析:
protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {
Class<?> cl;
try {
//通过类加载器获取 Activitythread 类对象
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
throw new RuntimeException(
"Missing class when invoking static main " + className,
ex);
}
Method m;
try {
//获取反射获取Activitythread main方法
m = cl.getMethod("main", new Class[] { String[].class });
} catch (NoSuchMethodException ex) {
throw new RuntimeException(
"Missing static main on " + className, ex);
} catch (SecurityException ex) {
throw new RuntimeException(
"Problem getting static main on " + className, ex);
}
int modifiers = m.getModifiers();
if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
throw new RuntimeException(
"Main method is not public and static on " + className);
}
//交给 MethodAndArgsCaller去处理 ,8.0之前是通过抛出异常的形式反射调用main方法
return new MethodAndArgsCaller(m, argv);
}
再往下看,就是反射调用main
static class MethodAndArgsCaller implements Runnable {
private final Method mMethod;
private final String[] mArgs;
public MethodAndArgsCaller(Method method, String[] args) {
mMethod = method;
mArgs = args;
}
public void run() {
try {
//反射调用 ActivityThread的main方法启动应用程序
mMethod.invoke(null, new Object[] { mArgs });
} catch (IllegalAccessException ex) {
throw new RuntimeException(ex);
} catch (InvocationTargetException ex) {
Throwable cause = ex.getCause();
if (cause instanceof RuntimeException) {
throw (RuntimeException) cause;
} else if (cause instanceof Error) {
throw (Error) cause;
}
throw new RuntimeException(ex);
}
}
}
Step24: ActivityThread的Main
方法分析:
public static void main(String[] args) {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
// CloseGuard defaults to true and can be quite spammy. We
// disable it here, but selectively enable it later (via
// StrictMode) on debug builds, but using DropBox, not logs.
CloseGuard.setEnabled(false);
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
// Make sure TrustedCertificateStore looks in the right place for CA certificates
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
Process.setArgV0("<pre-initialized>");
//初始化主线成的looper
Looper.prepareMainLooper();
// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
// It will be in the format "seq=114"
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
ActivityThread thread = new ActivityThread();
//重点 attach方法:
thread.attach(false, startSeq);
//初始化主线成的handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
if (false) {
Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//开启消息循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
分析: ActivityThrad的main
方法就是应用程序的入口,main方法执行表示应用程序的启动,再往后面的的几步分析主要是讲应用进程启动后,启动Activity 和关联Context等操作过程。下面简单过一下启动Activity的过程,至于详细过程以及关联Context操作以后将会专门写一篇ActivityThrad的工作流程源码分析中详细介绍。
6:应用的进程启动后,启动Activity 和关联Context的过程。
Step25: ActivityThread的attach
方法分析:
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
//mgr 就是ActivityManagerService对象.
final IActivityManager mgr = ActivityManager.getService();
try {
// 重点
//通过Binder机制调用ActivityManagerService的attachApplication方法
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
//...省略部分代码
ViewRootImpl.addConfigCallback(configChangedCallback);
}
}
分析: attach
方法中, mgr.attachApplication(mAppThread, startSeq)
是通过Binder机制回掉AMS的attachApplication方法,这一过程在上一篇文章Android framework 源码分析之Activity启动流程(android 8.0)中详细分析过,如果不明白的可以查阅一下,这里不在赘述。
Step26: AMS的attachApplication
方法分析:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
ProcessRecord app;
//...省略部分代码
//初始化数据
app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToImportant = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
app.killed = false;
//....代码
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
//重点: 调用mStackSupervisor.attachApplicationLocked(app))
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
//...代码
return true;
}
分析:
在AMS的attachApplication
中,重点看这一句mStackSupervisor.attachApplicationLocked
,将启动和绑定工作交给了ActivityStackSupervisor的attachApplicationLocked
方法去完成。
Step27: ActivityStackSupervisor的attachApplicationLocked
方法分析:
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ActivityDisplay display = mActivityDisplays.valueAt(displayNdx);
for (int stackNdx = display.getChildCount() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = display.getChildAt(stackNdx);
if (!isFocusedStack(stack)) {
continue;
}
stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
final ActivityRecord top = stack.topRunningActivityLocked();
final int size = mTmpActivityList.size();
for (int i = 0; i < size; i++) {
final ActivityRecord activity = mTmpActivityList.get(i);
if (activity.app == null && app.uid == activity.info.applicationInfo.uid
&& processName.equals(activity.processName)) {
try {
//重点 ;realStartActivityLocked启动acrivity
if (realStartActivityLocked(activity, app,
top == activity /* andResume */, true /* checkConfig */)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ top.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0, !PRESERVE_WINDOWS);
}
return didSomething;
}
分析: 在attachApplicationLocked
方法中调用了realStartActivityLocked
方法去完成启动Activity工作,至于realStartActivityLocked
的工作流程请阅读上文Android framework 源码分析之Activity启动流程(android 8.0)的Step14-Step18。
7:总结
到此应用进程的启动流程也分析完毕,如果文中有不对的地方欢迎请大家留言指出,共同进步,稍后根据这两篇文章整理一张app启动以及activity启动流程总图以便理解记忆。顺便给点个赞谢谢祝,大家周末愉快!!!。