Android(安卓)Framework启动流程浅析
前言
对于Android开发,干上几年后,都要进阶,或者直接转行了。如果你还在干Android,想要进阶 对Framework的了解是必不可少的过程,下面就开始进入今天的主题吧。
我们知道,对于任何程序语言而言,入口一般都是main函数。
那Android的程序入口在哪呢? 他的main函数是怎么启动起来的呢?
可能熟悉Android的同学,知道一个应用程序的入口在ActivityThread中,那有个问题,ActivityThread中的main函数是何时被谁被调用的呢?
将从本文中找到以上答案,如果已经熟悉了此过程的同学,可以在温习一下。
Android架构
Android 平台的基础是 Linux 内核。Android Runtime (ART/Dalvik) 依靠 Linux 内核来执行底层功能,例如线程和低层内存管理等。
而在Android Runtime之上就是我们经常接触的Java API Framework层, 如下图是Android的系统架构图
image今天的主题不是此架构图的各个部分解释,而是离应用层更近的Framework层启动过程分析。
Android Framework概述
如果我们这里抛开Android架构图,那狭义的Framewrok主要包含那些内容呢?
按我的理解,可以分为三个部分 服务端,客户端,和依赖Linux底层能力的驱动部分。
服务端
主要是ActivityManagerService(AMS), WindowManagerService(WMS),PackageM anerService(PMS)
- AMS 主要用于管理所有应用程序的Activity
- WMS 管理各个窗口,隐藏,显示等
- PMS 用来管理跟踪所有应用APK,安装,解析,控制权限等.
还有用来处理触摸消息的两个类KeyInputQueue和InputDispatchThread,一个用来读消息,一个用来分发消息.
客户端
主要包括ActivityThread,Activity,DecodeView及父类View,PhoneWindow,ViewRootImpl及内部类W等
- ActivityThread主要用来和AMS通讯的客户端,Activity是我们编写应用比较熟悉的类
- 后面几个类的介绍,可以参考我的另一篇博客 Android 绘制原理浅析【干货】
依赖Linux底层能力的驱动
主要是SurfaceFlingger(SF)和Binder驱动
- 每一个窗口都对应一个Surface,SF驱动的作用就是把每一个Surface显示到同一个屏幕上
- Binder 内核驱动的作用,就是为上面的服务端和客户端(或者服务端和服务端之间),提供IPC通讯用的。
Zygote
系统中运行的第一个Dalvik虚拟机程序叫做zygote,该名称的意义是“一个卵”,,因为接下来的所有 Dalvik虚拟机进程都是通过这个“卵” 孵化出来的。
zygote进程中包含两个主要模块,分别如下:
- Socket服务端。该 Socket服务端用于接收启动新的Dalvik进程的命令。
- Framework共享类及共享资源。当zygote进程启动后,会装载一些共享的类及资源,其中共享类是在preload-classes文件中被定义,共享资源是在preload-resources中被定义。因为zygote进程用于孵化出其他Dalvik进程,因此,这些类和资源装载后,新的Dalvik进程就不需要再装载这些类和资源了,这也就是所谓的共享。
zygote进程对应的具体程序是app_rocess,该程序存在于system/bin目录下,启动该程序的指令是
在 init.rc中进行配置的。
Zygote 有️两个优秀的特点
- 每fork出的一个进程都是一个Dalvik虚拟机,独立的进程可以防止一个程序的崩溃导致所有程序都崩溃,这种虚拟机类似Java虚拟机,对于程序员来说,可以直接使用Java开发应用
- zygote进程预先会装载共享类和共享资源,这些类及资源实际上就是SDK中定义的大部分类和资源。因此,当通过zygote孵化出新的进程后,新的APK进程只需要去装载A PK 自身包含的类和资源即可,这就有效地解决了多个APK共享Framework资源的问题。
SystemServer
zygote孵化出的第一个Dalvik进程叫做SystemServer,SystemServer仅仅是该进程的别名,而该进程具体对应的程序依然是app_process,因为SystemServer是从app_process中孵化出来的。
SystemServer中创建了一个Socket客户端,并有AmS负责管理该客户端,之后所有的Dalvik进程都将通过该Socket客户端间接被启动。当需要启动新的APK进程时,AmS中会通过该Socket客户端向 zygote进程的Socket服务端发送一个启动命令,然 后 zygote会孵化出新的进程。 上面提到的服务端,AMS,PMS,WMS等都是在SystemServer中启动的.
Android Framework 源头
操作系统的一般启动流程,分为三个步骤
- 开机通电后,加载bootloader程序
- 操作系统内核初始化
- 执行第一个应用程序
Android 系统是基于Linux 内核Kernel,前面Linux bootloader这里不做介绍,直接介绍操作系统内核初始化,在这个时候,它会加载init.rc文件.
init.rc文件
在Android根目录下面,可以直接找到init.rc
generic_x86:/ # lsacct bin cache config data dev init init.rc init.usb.rc lost+found mnt oem product sdcard sys ueventd.rc adb_keys bugreports charger d default.prop etc init.environ.rc init.usb.configfs.rc init.zygote32.rc metadata odm proc sbin storage system vendor
打开init.rc
generic_x86:/ # cat init.rc# ..... 省略其他 # Now we can start zygote for devices with file based encryptiontrigger zygote-start# It is recommended to put unnecessary data/ initialization from post-fs-data# to start-zygote in device's init.rc to unblock zygote start.on zygote-start # A/B update verifier that marks a successful boot. exec_start update_verifier_nonencrypted start netd start zygote start zygote_secondaryon property:vold.decrypt=trigger_restart_framework stop surfaceflinger# 启动SF start surfaceflinger # ..... 省略其他 media(媒体) network(网络)等启动
也就是在 init.rc时,启动Android 内核。
app_process
Android 内核也是main方法开始,他的main方法在 frameworks/base/cmds/app_process/app_main.cpp下
int main(int argc, char* const argv[]){ ... //初始化AndroidRuntime AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); bool zygote = false; bool startSystemServer = false; bool application = false; String8 niceName; String8 className; // 根据参数具体判断启动那个服务 ++i; // Skip unused "parent dir" argument. while (i < argc) { const char* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) { zygote = true; niceName = ZYGOTE_NICE_NAME; } else if (strcmp(arg, "--start-system-server") == 0) { startSystemServer = true; } else if (strcmp(arg, "--application") == 0) { application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) { niceName.setTo(arg + 12); } else if (strncmp(arg, "--", 2) != 0) { className.setTo(arg); break; } else { --i; break; } } if (!className.isEmpty()) { args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i); }else{ .... //启动SystemServer if (startSystemServer) { args.add(String8("start-system-server")); } } .... if (zygote) { //启动Zygote runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); }}
在这个Main方法中,先初始化了AppRuntime,他的父类是AndroidRuntime。然后我们看到了启动了Java类ZygoteInit。
那c++代码里怎么启动Java类呢,我们继续看 start方法
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote){ ... //启动Java虚拟机 if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { return; } ... //找到Java 里面的Main方法 jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); /* keep going */ } else { //执行Main方法 env->CallStaticVoidMethod(startClass, startMeth, strArray); } .... }
可以看到最后先创建了Java虚拟机,调用了Java的main方法,是不是感觉有些熟悉感了。
ZygoteInit
上面介绍到,会启动Java的ZygoteInit类,那他里面干了些什么呢? 我们来看一下关键代码,还是从Main方法开始
//ZygoteInit.java public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); ZygoteHooks.startZygoteNoThreadCreation(); //创建socket zygoteServer.createZygoteSocket(socketName); Zygote.createBlastulaSocket(blastulaSocketName); if (!enableLazyPreload) { bootTimingsTraceLog.traceBegin("ZygotePreload"); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); //预加载系统资源 preload(bootTimingsTraceLog); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); bootTimingsTraceLog.traceEnd(); // ZygotePreload } else { Zygote.resetNicePriority(); } //fork SystemServer进程 if (startSystemServer) { Runnable r = forkSystemServer(abiList, socketName, zygoteServer); // child (system_server) process. if (r != null) { r.run(); return; } } //等待Socket的接入 if (caller == null) { Log.i(TAG, "Accepting command socket connections"); // The select loop returns early in the child process after a fork and // loops forever in the zygote. caller = zygoteServer.runSelectLoop(abiList); }
注释写了大概Zygote 启动里面的初始化内容
- 创建Socket
- 加载系统资源
- 启动SystemServer
- runSelectLoop 等待socket接入,开始执行fork新的进程.
SystemServer
下面继续看SystemServer 启动的过程,从Main方法开始
//SystemServer.java /** * The main entry point from zygote. */ public static void main(String[] args) { new SystemServer().run(); }
很简单,创建一个自己的对象,并执行run方法,看一下run方法
private void run() { ... if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } VMRuntime.getRuntime().clearGrowthLimit(); // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage. VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper(); // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, mRuntimeStartUptime); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); try { traceBeginAndSlog("StartServices"); startBootstrapServices(); startCoreServices(); startOtherServices(); SystemServerInitThreadPool.shutdown(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } finally { traceEnd(); } Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited");}
run方法里面主要进行了设置手机时间,设置虚拟机内存大小,创建消息循环Looper,创建SystemServiceManager等,最主要的是启动了各类服务,我们接着看一下startBootstrapServices ,startCoreServices,startOtherServices方法
private void startBootstrapServices() { Installer installer = mSystemServiceManager.startService(Installer.class); mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class); mActivityManagerService = mSystemServiceManager.startService( ActivityManagerService.Lifecycle.class).getService(); mActivityManagerService.setSystemServiceManager(mSystemServiceManager); mActivityManagerService.setInstaller(installer); ....}private void startCoreServices() { ... mSystemServiceManager.startService(BatteryService.class); ...} private void startOtherServices() { final Context context = mSystemContext; VibratorService vibrator = null; DynamicAndroidService dynamicAndroid = null; IStorageManager storageManager = null; NetworkManagementService networkManagement = null; IpSecService ipSecService = null; NetworkStatsService networkStats = null; NetworkPolicyManagerService networkPolicy = null; ConnectivityService connectivity = null; NsdService serviceDiscovery= null; WindowManagerService wm = null; SerialService serial = null; NetworkTimeUpdateService networkTimeUpdater = null; InputManagerService inputManager = null; TelephonyRegistry telephonyRegistry = null; ConsumerIrService consumerIr = null; MmsServiceBroker mmsService = null; HardwarePropertiesManagerService hardwarePropertiesService = null; ....}
在这些方法中启动了,我们的核心服务,和常用服务。 代码中也可以看到AMS,PMS,WMS等相关服务.
Launcher启动介绍
一般服务启动完成后,就会想继调用systemReady()方法。
在SysytemServer startOtherServices中看到一个监听回调
mActivityManagerService.systemReady(() -> { try { startSystemUi(context, windowManagerF); } catch (Throwable e) { reportWtf("starting System UI", e); } }}static final void startSystemUi(Context context, WindowManagerService windowManager) { Intent intent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING); //Slog.d(TAG, "Starting service: " + intent); context.startServiceAsUser(intent, UserHandle.SYSTEM); windowManager.onSystemUiStarted();}
而Ams启动完成后,显示Launcher
//AMS.java public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) { ... startHomeActivityLocked(currentUserId, "systemReady"); // mStackSupervisor.resumeFocusedStackTopActivityLocked(); ... }
其实到这里大致流程就介绍完了,但是文章开始的ActivityThread的main方法是何时被调用的,还没回答,这里不详细展开,简略回答一些.
ActivityThread的main方法如何被调用的?
AMS是管理Activity的启动结束等,查看AMS代码,当当前启动的APP没有创建进程时,会最终调用到ZygoteProcess,然后向 Zygote发送一个socket请求。
resumeTopActivityLocked -> startProcessLocked -> Process.start() -> ZygoteProcess.start() -> ZygoteProcess.startViaZygote() —> ZygoteProcess.zygoteSendArgsAndGetResult()
接下来,看一下大致代码
//AMS.javaprivate final boolean startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, boolean disableHiddenApiChecks, String abiOverride) { //这里entryPoint为ActivityThread final String entryPoint = "android.app.ActivityThread"; return startProcessLocked(hostingType, hostingNameStr, entryPoint, app, uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith, startTime); }
//ZygoteProcess.javaprivate Process.ProcessStartResult startViaZygote(final String processClass,... ){ ArrayList argsForZygote = new ArrayList(); argsForZygote.add("--runtime-args"); argsForZygote.add("--setuid=" + uid); argsForZygote.add("--setgid=" + gid); argsForZygote.add("--runtime-flags=" + runtimeFlags); argsForZygote.add("--target-sdk-version=" + targetSdkVersion); if (startChildZygote) { argsForZygote.add("--start-child-zygote"); } argsForZygote.add(processClass); synchronized(mLock) { return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), useBlastulaPool, argsForZygote); }}//发起Socket请求,给Zygoteprivate static Process.ProcessStartResult zygoteSendArgsAndGetResult( ArrayList args,..){ blastulaSessionSocket = zygoteState.getBlastulaSessionSocket(); final BufferedWriter blastulaWriter = new BufferedWriter( new OutputStreamWriter(blastulaSessionSocket.getOutputStream()), Zygote.SOCKET_BUFFER_SIZE); final DataInputStream blastulaReader = new DataInputStream(blastulaSessionSocket.getInputStream()); blastulaWriter.write(msgStr); blastulaWriter.flush(); ...}
最终 Zygote收到请求调用ZygoteInit中zygoteinit方法
//ZygoteInit.javapublic 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"); RuntimeInit.redirectLogStreams(); RuntimeInit.commonInit(); ZygoteInit.nativeZygoteInit(); return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); }
在 RuntimeInit中findStaticMain,最后在ZygoteInit中执行最终返回的这个Runnable,达到调用main方法的目的.
protected static Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { nativeSetExitWithoutCleanup(true); VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); final Arguments args = new Arguments(argv); Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); return findStaticMain(args.startClass, args.startArgs, classLoader); }protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) { .. m = cl.getMethod("main", new Class[] { String[].class }); return new MethodAndArgsCaller(m, argv); }
总结
如果你都看到这了,希望帮忙点个赞,谢谢啦。
因为本人水平有限,各路大佬如看到文中有错误,欢迎指出,在此表示感谢。
推荐阅读
- Android 相关知识点个人总结
- Android "画"美妆,修图(换证件照背景,污点修复等)
参考书籍
《Android 内核剖析》 柯元旦
更多相关文章
- 浅谈Java中Collections.sort对List排序的两种方法
- Python list sort方法的具体使用
- python list.sort()根据多个关键字排序的方法实现
- android上一些方法的区别和用法的注意事项
- 浅析android通过jni控制service服务程序的简易流程
- android实现字体闪烁动画的方法
- Android(安卓)Wifi模块分析(三)
- Android中dispatchDraw分析
- Android四大基本组件介绍与生命周期