在讲应用启动之前,我们需要了解两个知识点
- Binder IPC机制
- Zygote 机制
Binder IPC比较复杂,请移步Binder IPC机制
Zygote?
我们知道,Android 是基于 Linux 内核开发的,而在 Linux 中,所有的进程都是直接或者间接地由 init 进程 fork 出来的。Zygote 进程也不例外,它是在系统启动的过程,由 init 进程创建的。
Zygote 的运行
做过手机系统开发的大佬都知道,init 进程代码在系统启动脚本 system/core/rootdir/init.rc 文件中。 截取一部分代码,可以发现,
是通过运行 service zygote 命令来创建 zygote
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 660 root system
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
...
初始化 Zygote
执行命令后,最终会调用 Zygote 相关的 Java 代码。Zygote 进程的初始化在 ZygoteInit 这个类中的 main 方法
public static void main(String argv[]) {
// zygote 进程的 socketServer
ZygoteServer zygoteServer = new ZygoteServer();
ZygoteHooks.startZygoteNoThreadCreation();
...
final Runnable caller;
try {
boolean startSystemServer = false;
String socketName = "zygote";
String abiList = null;
boolean enableLazyPreload = false;
// 为 zygote 命令连接(ZygoteConnection)注册一个 server socket
// 内部实现类 LocalServerSocket Os.listen 开始一个阻塞监听 socket 连接
zygoteServer.registerServerSocket(socketName);
...
if (startSystemServer) {
// 创建系统进程
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
if (r != null) {
r.run();
return;
}
}
// SocketServer 阻塞监听连接
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();
}
}
ZygoteServer 轮询连接
runSelectLoop 方法,来看看关键的代码,while(true) 死循环,轮询操作,接收一个新的连接,读取命令
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);
// 轮训 FileDescriptor,peers
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
...
try {
if (i == 0) {
// 接收一个新的连接,保存到集合
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
// 下一次 while轮训时, 拿到 socket 连接
ZygoteConnection connection = peers.get(i);
// 处理命令
final Runnable command = connection.processOneCommand(this);
...
}
} catch (Exception e) {
...
}
}
}
使用过 socket 的大佬应该很熟悉,
- ZygoteServer 相当于 SocketServer 服务端包装类
- ZygoteConnection 表示一个远端 Socket 连接
ZygoteConnection 处理命令
我们看看 ZygoteConnection 是怎么处理命令的,
Runnable processOneCommand(ZygoteServer zygoteServer) {
String args[];
Arguments parsedArgs = null;
FileDescriptor[] descriptors;
...
// 实际创建进程的地方还是回到了 Zygote 类中
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo,
parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.instructionSet,
parsedArgs.appDataDir);
// 创建进程后的处理,异常处理,关闭连接等
...
}
回到 Zygote forkAndSpecialize 中,
public static int forkAndSpecialize(int uid, int gid, int[] gids, int debugFlags,
int[][] rlimits, int mountExternal, String seInfo, String niceName, int[] fdsToClose,
int[] fdsToIgnore, String instructionSet, String appDataDir) {
// ZygoteHooks
VM_HOOKS.preFork();
// Resets nice priority for zygote process.
resetNicePriority();
// native 方法创建进程
int pid = nativeForkAndSpecialize(
uid, gid, gids, debugFlags, rlimits, mountExternal, seInfo, niceName, fdsToClose,
fdsToIgnore, instructionSet, appDataDir);
// Enable tracing as soon as possible for the child process.
...
VM_HOOKS.postForkCommon();
return pid;
}
小结
至此, 我们大致了解了 zygote 是什么以及它的作用
- Zygote 是由 init 进程,通过执行脚本命令创建的一个进程,由 ZygoteInit main 方法完成初始化
- 初始化时 启动一个 ZygoteServer,SocketServer 的Java包装类,监听 Socket 连接
- ZygoteServer 拿到 Socket 连接 ZygoteConnection(连接的包装类),处理命令
- ZygoteConnection 主要是处理创建进程的命令,最后会回到 Zygote 类 forkAndSpecialize
- Zygote.forkAndSpecialize 调用 JNI native 方法实现进程的创建
App 的启动
理解了 Zygote 的作用后,我们以 Android O 源码为基础,分析 Android App 启动的流程,这有助于后续学习 Android framework ,
hook技术, dex等知识的学习
Launcher 里启动 App
在 Launcher 源码里启动 App,调用的也是我们常用的 startActivity 方法。Activity 里的最后调用的是,
public void startActivityForResult(@RequiresPermission Intent intent, int requestCode,
@Nullable Bundle options) {
// mParent 指当前的 Activity 是否是嵌套在其他的 Activity 中,我们通常很少嵌套 Activity
if (mParent == null) {
// options 参数处理
options = transferSpringboardActivityOptions(options);
// 通过 Instrumentation 启动Activity
// mMainThread.getApplicationThread()返回的是 ApplicationThread,继承自 IApplicationThread.Stub
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
if (ar != null) {
// 发送启动结果
mMainThread.sendActivityResult(
mToken, mEmbeddedID, requestCode, ar.getResultCode(),
ar.getResultData());
}
...
}
...
}
Instrumentation 里 execStartActivity,关键的代码在 ActivityManager.getService().startActivity(…) 启动 Activity
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, String target,
Intent intent, int requestCode, Bundle options) {
...
// ActivityManager.getService 拿到 IActivityManager 调用 startActivity
int result = ActivityManager.getService()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target, requestCode, 0, null, options);
checkStartActivityResult(result, intent);
...
}
ActivityManager.getService 返回的是 IActivityManager,命名方式可以看出是一个接口
public static IActivityManager getService() {
return IActivityManagerSingleton.get();
}
IActivityManagerSingleton 的初始化,
private static final Singleton<IActivityManager> IActivityManagerSingleton =
new Singleton<IActivityManager>() {
@Override
protected IActivityManager create() {
// 通过 ServiceManager 拿到 ActivityManagerService(AMS) 的 Service IBinder对象
final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
// IActivityManager.Stub.asInterface
final IActivityManager am = IActivityManager.Stub.asInterface(b);
return am;
}
};
看到 IActivityManager.Stub.asInterface 是不是有点似曾相似的感觉,是的,这里使用到的就是 AIDL 跨进程通信的机制, IActivityManager 是定义好的 AIDL 接口。Application 层的源码到这里就结束了,再往下,我们就要找 ServiceManager 了
framework 里启动
Binder 调用AMS
ServiceManager 在 android.os 包下,看看相关方法
public final class ServiceManager {
private static final String TAG = "ServiceManager";
private static IServiceManager sServiceManager;
// 定义 HashMap 缓存各种 IBinder 实例,我们的 AMS 实例也是存储在该 hashmap 中
private static HashMap<String, IBinder> sCache = new HashMap<String, IBinder>();
private static IServiceManager getIServiceManager() {
...
// ServiceManagerNative 将 Binder 转换为 IServiceManager
sServiceManager = ServiceManagerNative
.asInterface(Binder.allowBlocking(BinderInternal.getContextObject()));
return sServiceManager;
}
public static IBinder getService(String name) {
...
// 调用 IServiceManager 的 getService 方法
return Binder.allowBlocking(getIServiceManager().getService(name));
...
}
}
其中 BinderInternal.getContextObject() 是一个 native 方法,返回一个系统全局的 “context” 对象 IBinder,通常是 IServiceManager 的实现。
因为是 native 方法,我们可以猜到这个 IServiceManager 实现是由 C++ 来完成的。 这部分就复杂了,感觉越讲内容越多了,不是我们应用启动的内容暂时就到
这里。
回到 ServiceManager.getService(“activity”), 拿到的是 IActivityManager 的实现,AMS 在 com.android.server.am 包下。 调用的是
startActivityAsUser() ,这里又使用了 ActivityStarter 来启动
public class ActivityManagerService extends IActivityManager.Stub
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
@Override
public final int startActivityAsUser(...) {
enforceNotIsolatedCaller("startActivity");
userId = mUserController.handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(),
userId, false, ALLOW_FULL_ONLY, "startActivity", null);
// 调用 ActivityStarter 方法启动
return mActivityStarter.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, bOptions, false, userId, null, "startActivityAsUser");
}
}
这里面就不一层层介绍了,实在太绕了,归纳如下流程
ActivityStarter.java:
-->startActivityMayWait
-->startActivityLocked
-->startActivity
-->startActivity
-->startActivityUnchecked(来自ActivityStackSupervisor的方法)
ActivityStackSupervisor.java:
-->resumeFocusedStackTopActivityLocked(来自ActivityStack的方法)
ActivityStack.java:
-->resumeTopActivityUncheckedLocked
-->resumeTopActivityInnerLocked
-->startSpecificActivityLocked(来自ActivityStackSupervisor)
-->startProcessLocked(来自AMS,启动新进程)
startSpecificActivityLocked 这个方法,检查应用进程记录是否已经运行,
- 如果App 进程记录已经存在,则执行 realStartActivityLocked
如果不存在则运行 mService.startProcessLocked
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) { // 当前 Activity 的 application 是否在运行? ProcessRecord app = mService.getProcessRecordLocked(r.processName, r.info.applicationInfo.uid, true); r.getStack().setLaunchTime(r); //app 正在运行, if (app != null && app.thread != null) { try { if ((r.info.flags&ActivityInfo.FLAG_MULTIPROCESS) == 0 || !"android".equals(r.info.packageName)) { app.addPackage(r.info.packageName, r.info.applicationInfo.versionCode, mService.mProcessStats); } // 1. 执行 realStartActivityLocked realStartActivityLocked(r, app, andResume, checkConfig); return; } catch (RemoteException e) { Slog.w(TAG, "Exception when starting activity " + r.intent.getComponent().flattenToShortString(), e); } } // 2. app 未启动, 执行 startProcessLocked,启动新进程 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true);
}
zygote fork进程启动app
由上面的分析,我们知道,在 app 尚未启动时,会执行 mService.startProcessLocked 这个方法
final ProcessRecord startProcessLocked(...) {
return startProcessLocked(...);
}
final ProcessRecord startProcessLocked(...) {
long startTime = SystemClock.elapsedRealtime();
ProcessRecord app;
// 一系列检查操作
...
// 开始创建进程,同时记录耗时时间
checkTime(startTime, "startProcess: stepping in to startProcess");
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
checkTime(startTime, "startProcess: done starting proc!");
return (app.pid != 0) ? app : null;
}
startProcessLocked 里, 这里稍微留一下,entryPoint 被赋值为 android.app.ActivityThread
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
...
// Start the process. It will either succeed and return a result containing
// the PID of the new process, or else throw a RuntimeException.
boolean isActivityProcess = (entryPoint == null);
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
...
if (hostingType.equals("webview_service")) {
...
} else {
// 这里就是开始创建进程的地方了
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
}
...
来看看 Process 类里是怎么做的,方法也是一堆参数,先忽略了。 可以看到用到了 zygoteProcess 这个类
public static final ZygoteProcess zygoteProcess =
new ZygoteProcess("zygote", "zygote_secondary");
public static final ProcessStartResult start(...) {
return zygoteProcess.start(...);
}
简单看看 ZygoteProcess 的构造,可以发现跟 Socket 貌似有点关联,前面了解过 Zygote,我们大概能知道,
这里准备要涉及 Socket 来实现进程间的通讯
public class ZygoteProcess {
/**
* socket的名称,用于跟主zygote的交流
*/
private final String mSocket;
/**
* 另外一个 zogote socket名称(适配不同 ABI)
*/
private final String mSecondarySocket;
public ZygoteProcess(String primarySocket, String secondarySocket) {
mSocket = primarySocket;
mSecondarySocket = secondarySocket;
}
public final Process.ProcessStartResult start(...) {
// 通过 Zygote 来启动
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
...
}
startViaZygote,
/**
* 启动一个新的进程,通过 zygote 机制.
*/
private Process.ProcessStartResult startViaZygote(...)
throws ZygoteStartFailedEx {
// zygote 参数集合
ArrayList<String> argsForZygote = new ArrayList<String>();
// --runtime-args, --setuid=, --setgid=,
// and --setgroups= must go first
argsForZygote.add("--runtime-args");
argsForZygote.add("--setuid=" + uid);
argsForZygote.add("--setgid=" + gid);
if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {
argsForZygote.add("--enable-jni-logging");
}
// 省略的这部分都是往参数集合里加配置参数
...
// 这里 processClass 是 AMS 里的 entryPoint
argsForZygote.add(processClass);
synchronized(mLock) {
// 将参数集合传递
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
}
主要做了如下操作
- 添加配置参数
- openZygoteSocketIfNeeded socket连接操作
- zygoteSendArgsAndGetResult 通过 socket 连接发送数据
简单看看 zygoteSendArgsAndGetResult,
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(
ZygoteState zygoteState, ArrayList<String> args)
throws ZygoteStartFailedEx {
...
// IO 写操作
final BufferedWriter writer = zygoteState.writer;
final DataInputStream inputStream = zygoteState.inputStream;
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();
}
// 通过 ZygoteState.writer 写数据
writer.flush();
// 到这里,进程已经创建完成了,后续就是读取进程 pid 了
Process.ProcessStartResult result = new Process.ProcessStartResult();
result.pid = inputStream.readInt();
result.usingWrapper = inputStream.readBoolean();
if (result.pid < 0) {
throw new ZygoteStartFailedEx("fork() failed");
}
return result;
}
了解过 zygote 机制的我们知道,IO 操作,数据会传递给 ZygoteServer 服务端轮询处理,而数据的处理在 ZygoteConnection.processOneCommand,最终通过 Zygote 调用 native 方法 fork 出新的进程
App 进程已存在
在App 的 Application已经在运行的情况下,会执行 ActivityStackSupervisor 的 realStartActivityLocked 方法
final boolean realStartActivityLocked(ActivityRecord r, ProcessRecord app,
boolean andResume, boolean checkConfig) throws RemoteException {
...
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
mergedConfiguration.getGlobalConfiguration(),
mergedConfiguration.getOverrideConfiguration(), r.compat,
r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle,
r.persistentState, results, newIntents, !andResume,
mService.isNextTransitionForward(), profilerInfo);
...
}
scheduleLaunchActivity 是来自 ActivityThread, 最终会使用 Handler 机制,发送 Message 消息去启动Activity
public final void scheduleLaunchActivity(...) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
...
sendMessage(H.LAUNCH_ACTIVITY, r);
}
handleMessage 处理 LAUNCH_ACTIVITY 消息,
public void handleMessage(Message msg) {
if (DEBUG_MESSAGES) Slog.v(TAG, ">>> handling: " + codeToString(msg.what));
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
final ActivityClientRecord r = (ActivityClientRecord) msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null, "LAUNCH_ACTIVITY");
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
break;
}
}
handlerLaunchActivity 里的调用 performLaunchActivity 完成最终的启动
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
// 构建 component
...
ContextImpl appContext = createBaseContextForActivity(r);
Activity activity = null;
try {
// 通过 ClassLoader 加载 Activity 类,启动
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
...
}
try {
// 构建 Application
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
...
// 调用 Activity attach 到 window
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
...
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
}
return activity;
}
至此,Activity 的启动页就大致结束了,其他的细节我们就不关注了。
此外,这里 ActivityThread 也是我们着重关注的对象.
ActivityThread
ActivityThread 在 Android 中它就代表了 Android 的主线程,但是并不是一个 Thread 类。
严格来说,UI主线程不是 ActivityThread。ActivityThread 类是 Android APP 进程的初始类,它的 main 函数是这个 APP 进程的入口。
APP 进程中 UI 事件的执行代码段都是由 ActivityThread 提供的。也就是说,MainThread 实例是存在的,可以理解为 ActivityThread main方法所运行的线程。
public final class ActivityThread {
...
private static ActivityThread sCurrentActivityThread;
final H mH = new H();
private void attach(boolean system) {
sCurrentActivityThread = this;
...
}
public static void main(String[] args) {
...
// 创建 Looper 和 MessageQueue 对象,用于处理主线程的消息
Looper.prepareMainLooper();
// 创建ActivityThread对象
ActivityThread thread = new ActivityThread();
// 建立Binder通道 (创建新线程)
thread.attach(false);
if (sMainThreadHandler == null) {
// sMainThreadHandler 即 mH
sMainThreadHandler = thread.getHandler();
}
// 消息循环运行
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
public static final int EXIT_APPLICATION = 111;
public static final int NEW_INTENT = 112;
public static final int RECEIVER = 113;
public static final int CREATE_SERVICE = 114;
public static final int SERVICE_ARGS = 115;
public static final int STOP_SERVICE = 116;
...
}
}
mH Handler 里处理了四大组件的各种消息,如启动 Activity LAUNCH_ACTIVITY,创建Servie CREATE_SERVICE 等等。 可以说 ActivityThread 是 Activity 生命周期中一个至关重要的管理类, 也可以理解为是主线程操作的管理类。
总结
大致的流程图如下
- 点击桌面App图标,Launcher进程采用Binder IPC 向 system_server 进程发起startActivity请求
- system_server进程接收到请求后,向zygote进程发送创建进程的请求
- Zygote进程fork出新的子进程,即App进程
- App进程,通过Binder IPC向sytem_server进程发起attachApplication请求
- system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求
- App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息
主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法 - App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面