前言
对于 Android 开发,干上几年后,都要进阶,或者间接转行了。如果你还在干 Android,想要进阶 对 Framework 的理解是必不可少的过程,上面就开始进入明天的主题吧。
咱们晓得,对于任何程序语言而言,入口个别都是 main 函数。
那 Android 的程序入口在哪呢?他的 main 函数是怎么启动起来的呢?
可能相熟 Android 的同学,晓得一个应用程序的入口在 ActivityThread 中,那有个问题,ActivityThread 中的 main 函数是何时被谁被调用的呢?
将从本文中找到以上答案,如果曾经相熟了此过程的同学,能够在复习一下。
Android 架构
Android 平台的根底是 Linux 内核。Android Runtime (ART/Dalvik) 依附 Linux 内核来执行底层性能,例如线程和低层内存治理等。
而在 Android Runtime 之上就是咱们常常接触的 Java API Framework 层,如下图是 Android 的零碎架构图
明天的主题不是此架构图的各个局部解释,而是离应用层更近的 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 是咱们编写利用比拟相熟的类
依赖 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:/ # ls
acct 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 encryption
trigger 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_secondary
on 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<String8>& 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.java
private 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.java
private Process.ProcessStartResult startViaZygote(final String processClass,...){ArrayList<String> argsForZygote = new ArrayList<String>();
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 申请,给 Zygote
private static Process.ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> 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.java
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");
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);
}
本文转自 https://www.jianshu.com/p/5ba93dee3dfd,如有侵权,请分割删除。
相干视频举荐:
【2021 最新版】Android studio 装置教程 +Android(安卓)零基础教程视频(适宜 Android 0 根底,Android 初学入门)含音视频_哔哩哔哩_bilibili
【Android 进阶教程】——Framework 面试必问的 Handler 源码解析_哔哩哔哩_bilibili
Android 进阶零碎学习——Gradle 入门与我的项目实战_哔哩哔哩_bilibili
Android 架构设计原理与实战——Jetpack 联合 MVP 组合利用开发一个优良的 APP!_哔哩哔哩_bilibili