Author: Nubia technical team
Source code source: Nubian technical team
1 Introduction
From the user's finger clicking the application icon on the desktop to the display of the application's main Activity interface on the screen to complete the application launch, it often takes less than a second if it is fast, but the whole process is very complicated, which involves almost all aspects of the Android system. All core knowledge points. At the same time, the startup speed of the application is definitely one of the core user experience indicators of the system. effort. But in order to really do a good job of optimizing the application startup speed, I think it is necessary to have a full understanding and understanding of the entire process of application startup, so whether as an Android system or an application developer, it is necessary to study and understand Learn about this process. There are many articles on the Internet that introduce the source code of the application startup process, but I always feel that most of them are not comprehensive. Many of them only introduce part of the application startup process, but do not have a clear understanding of the overall context and system architecture design ideas of the application startup process. . Therefore, this article will combine the author's work experience over the years, combined with the systrace analysis tool, and based on the latest Android R AOSP source code to completely analyze the entire application startup process from the user's finger touch to click the screen application icon to the application interface displayed on the screen. A summary and induction of what has been done and learned before.
2. Outline
- Android touch event processing mechanism
- Zygote process startup and application process creation process
- Handler message mechanism
- Activity component management of AMS
- Application Application and Activity component creation and initialization
- Application UI layout and drawing
- RenderThread rendering
- SurfaceFlinger synthetic display
- write at the end
- reference
3. Input touch event processing flow
3.1 System Mechanism Analysis
Android
The system is event-driven, and input
it is one of the most common events. The user's click, slide, long press and other operations are all input
event-driven, and the core is InputReader
and InputDispatcher
. InputReader
and InputDispatcher
are SystemServer
two native
loop threads running in the process, responsible for reading and dispatching Input
events. The whole processing process is roughly as follows:
InputReader
Responsible for reading the event fromEventHub
itInput
, and then handing it over toInputDispatcher
the event distribution;InputDispatcher
After gettingInputReader
the acquired event, after wrapping the event, find and distribute it to the target window;InboundQueue
The queue ("iq") holds the events receivedInputDispatcher
from it ;InputReader
input
OutboundQueue
("oq") queue contains events that will be dispatched to each target window App;WaitQueue
The records in the queue are events that have been dispatched toApp
("wq"), butApp
are still being processed and have not been returned successfully;PendingInputEventQueue
The events that the application needs to process are recorded in the queue ("aq")Input
, where you can see thatinput
the events have been delivered to the application process;deliverInputEvent
The flagApp
UI Thread
isInput
awakened by the event;InputResponse
IdentifyInput
the event area, where you can see that the processing stages of oneInput_Down
event + severalInput_Move
events + oneInput_Up
event are counted here;App
In response to processingInput
events,View
processing will be passed internally in its interface tree.
Using a picture to describe the whole process is roughly as follows:
3.2 Combined with Systrace analysis
Click the application icon on the desktop to start the application. system_server
The native
thread InputReader
is first responsible EventHub
for monitoring the mechanism linux
used epolle
and reading the reported touch events from the screen driver, and then wakes up another native thread InputDispatcher
to be responsible for further event distribution. InputDispatcher
It will first put the event into InboundQueue
the "iq" queue, then find the target application window that specifically handles input
the event, and put the event into the corresponding target window, OutboundQueue
which is the "oq" queue, waiting to SocketPair
be sent to the application target through the duplex channel window. Finally, when the event is sent to the specific application target window, the event will be moved to WaitQueue
"wq" to wait for the target application to process the event and start the countdown. If the target application window has not processed the touch event within 5S, system_server
An ANR exception event will be reported to the application . The above whole process Android
has a corresponding systrace tag added to the system source code, as shown in the systrace screenshot below:
Then the above process continues to analyze: when input
the touch event is delivered to the desktop application process, the event is put into the "aq" local pending queue through the function Input
after the event arrives , and the UI thread of the application is woken up to process the event in the process Specific distribution and processing. The details will be handed over to multiple different types of processes created in the process of creating the application interface for processing in turn (such as the encapsulation of input method processing logic ), and the entire processing process is carried out in accordance with the design pattern of the chain of responsibility . Finally, it will be handed over to the center for specific processing, which will traverse each sub -or interface on the entire tree from the root node of the layout tree to perform event distribution, interception, and processing logic. Finally, after the touch event processing is completed, it will call the end application to handle the touch event logic, which will notify the completion of the event processing by calling the function of the layer , and remove the pending event from the "wq" queue in time to avoid exceptions.enqueueInputEvent
deliverInputEvent
input
Window
ViewRootImpl#setView
InputStage
ImeInputStage
ViewPostImeInputStage
View
DecorView
View
View
ViewGroup
finishInputEvent
JNI
native
InputConsumer
sendFinishedSignal
InputDispatcher
ANR
In the desktop application interface View, one touch event and multiple touch events are processed continuously ACTION_DOWN
, TouchEvent
until the last event ACTION_MOVE
occurs , it is judged to be a click event, and then the logic of starting the application is triggered through the called service interface . From systrace, it is shown in the following figure:ACTION_UP
TouchEvent
onClick
ActivityManager
Binder
AMS
startActivity
4. Create and start the application process
4.1 Pause desktop application
Continue to look down from the previous section. The desktop process receives the input touch event and processes it and binder
calls the interface AMS
of the framework to start the application. The relevant simplified code is as follows:startActivity
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, Task inTask,
boolean restrictedBgActivity, NeededUriGrants intentGrants) {
...
try {
...
// 添加“startActivityInner”的systrace tag
Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "startActivityInner");
// 执行startActivityInner启动应用的逻辑
result = startActivityInner(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, restrictedBgActivity, intentGrants);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
...
}
...
}
In the implementation of startActivityInner
the startup application logic, the stack management logic AMS
in the check finds that the desktop application is currently in the foreground state , so the first step is to notify the desktop application of the entry status . The related simplified code logic is as follows:Activity
Resume
Activity
Activity
Paused
/*frameworks/base/services/core/java/com/android/server/wm/ActivityStack.java*/
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
// mResumedActivity不为null,说明当前存在处于resume状态的Activity且不是新需要启动的应用
if (mResumedActivity != null) {
// 执行startPausingLocked通知桌面应用进入paused状态
pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next);
}
...
}
final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
ActivityRecord resuming) {
...
ActivityRecord prev = mResumedActivity;
...
if (prev.attachedToProcess()) {
try {
...
// 相关执行动作封装事务,binder通知mResumedActivity也就是桌面执行pause动作
mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
prev.appToken, PauseActivityItem.obtain(prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately));
} catch (Exception e) {
...
}
}
...
}
The desktop application process executes the life cycle after receiving the pause
message , and after the execution is completed, the interface will be called to notify the system of the completed action . The relevant code is as follows:Activity
onPause
binder
AMS
activityPaused
activity
pause
@Override
public void postExecute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
...
try {
// binder通知AMS当前应用activity已经执行完pause的流程
ActivityTaskManager.getService().activityPaused(token);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
AMS
After receiving the application activityPaused
call here, continue to execute the logic of starting the application, and judge that Activity
the process of the application to be started does not exist, so startProcessAsync
the application process needs to be created first , and the related simplified code is as follows:
/*frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java*/
void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
...
// 1.如果wpc不为null且hasThread表示应用Activity所属进程存在,直接realStartActivityLocked启动Activity
if (wpc != null && wpc.hasThread()) {
try {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
...
}
...
// 2.否则,调用AMS的startProcessAsync正式开始创建应用进程
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
The above process is viewed from systrace, as shown in the following figure:
- Notify the pause desktop application:
2. activityPaused
After confirming the status of the desktop, start creating the application process:
4.2 Create application process
Following the analysis in the previous section, we can know that Android
the startup of the application process is passive . When clicking the icon on the desktop to start an application component such as Activity
, if Activity
the process does not exist, the process will be created and started. ** Android
The creation of general application processes in the system is uniformly created by zygote
the process . When an application process needs to be created, it will be connected and notified to the server that the process has created during the startup phase , and then the process will create the application process. ** The overall structure is shown in the figure below:fork
AMS
socket
zygote
socket
zygote
fork
Let's continue the analysis in the previous section, continue to AMS#startProcessAsync
start with the creation process function, and continue to look at the simplified process code related to application process creation:
4.2.1 AMS sends socket request
/*frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java*/
@GuardedBy("this")
final ProcessRecord startProcessLocked(...) {
return mProcessList.startProcessLocked(...);
}
/*frameworks/base/services/core/java/com/android/server/am/ProcessList.java*/
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int zygotePolicyFlags,
int mountExternal, String seInfo, String requiredAbi, String instructionSet,
String invokeWith, long startTime) {
try {
// 原生标识应用进程创建所加的systrace tag
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
...
// 调用Process的start方法创建进程
startResult = Process.start(...);
...
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
/*frameworks/base/core/java/android/os/Process.java*/
public static ProcessStartResult start(...) {
// 调用ZygoteProcess的start函数
return ZYGOTE_PROCESS.start(...);
}
/*frameworks/base/core/java/android/os/ZygoteProcess.java*/
public final Process.ProcessStartResult start(...){
try {
return startViaZygote(...);
} catch (ZygoteStartFailedEx ex) {
...
}
}
private Process.ProcessStartResult startViaZygote(...){
ArrayList<String> argsForZygote = new ArrayList<String>();
...
return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}
In ZygoteProcess#startViaZygote
the logic that finally creates the application process:
openZygoteSocketIfNeeded
The function opens the localsocket
client to connect to the serverzygote
of the processsocket
;zygoteSendArgsAndGetResult
Sendsocket
the request parameters with the created application process parameter information ;return
The returned data structure will have fieldsProcessStartResult
for the newly created processpid
.
Looking at the process from systrace is as follows:
4.2.2 Zygote handles socket requests
In fact, as early as the system boot stage, zygote
when the process is created, ZygoteInit#main
the server will be created in the entry function socket
, and the system resources and framework classes will be preloaded (accelerating the startup speed of the application process) . The code is as follows:
/*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
public static void main(String[] argv) {
ZygoteServer zygoteServer = null;
...
try {
...
// 1.preload提前加载框架通用类和系统资源到进程,加速进程启动
preload(bootTimingsTraceLog);
...
// 2.创建zygote进程的socket server服务端对象
zygoteServer = new ZygoteServer(isPrimaryZygote);
...
// 3.进入死循环,等待AMS发请求过来
caller = zygoteServer.runSelectLoop(abiList);
} catch (Throwable ex) {
...
} finally {
...
}
...
}
Continue to see ZygoteServer#runSelectLoop
how to monitor and process AMS client requests:
/*frameworks/base/core/java/com/android/internal/os/ZygoteServer.java*/
Runnable runSelectLoop(String abiList) {
// 进入死循环监听
while (true) {
while (--pollIndex >= 0) {
if (pollIndex == 0) {
...
} else if (pollIndex < usapPoolEventFDIndex) {
// Session socket accepted from the Zygote server socket
// 得到一个请求连接封装对象ZygoteConnection
ZygoteConnection connection = peers.get(pollIndex);
// processCommand函数中处理AMS客户端请求
final Runnable command = connection.processCommand(this, multipleForksOK);
}
}
}
}
Runnable processCommand(ZygoteServer zygoteServer, boolean multipleOK) {
...
// 1.fork创建应用子进程
pid = Zygote.forkAndSpecialize(...);
try {
if (pid == 0) {
...
// 2.pid为0,当前处于新创建的子应用进程中,处理请求参数
return handleChildProc(parsedArgs, childPipeFd, parsedArgs.mStartChildZygote);
} else {
...
handleParentProc(pid, serverPipeFd);
}
} finally {
...
}
}
private Runnable handleChildProc(ZygoteArguments parsedArgs,
FileDescriptor pipeFd, boolean isZygote) {
...
// 关闭从父进程zygote继承过来的ZygoteServer服务端地址
closeSocket();
...
if (parsedArgs.mInvokeWith != null) {
...
} else {
if (!isZygote) {
// 继续进入ZygoteInit#zygoteInit继续完成子应用进程的相关初始化工作
return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
parsedArgs.mDisabledCompatChanges,
parsedArgs.mRemainingArgs, null /* classLoader */);
} else {
...
}
}
}
The above process is shown in the following figure from systrace:
4.2.3 Application Process Initialization
Continuing from the analysis in the previous section, zygote
the process listens to the received AMS
request, fork
creates a sub-application process, and then pid
enters the sub-process space when it is 0, and then ZygoteInit#zygoteInit
completes the process initialization action in it. The related simplified code is as follows:
/*frameworks/base/core/java/com/android/internal/os/ZygoteInit.java*/
public static Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
...
// 原生添加名为“ZygoteInit ”的systrace tag以标识进程初始化流程
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
RuntimeInit.redirectLogStreams();
// 1.RuntimeInit#commonInit中设置应用进程默认的java异常处理机制
RuntimeInit.commonInit();
// 2.ZygoteInit#nativeZygoteInit函数中JNI调用启动进程的binder线程池
ZygoteInit.nativeZygoteInit();
// 3.RuntimeInit#applicationInit中反射创建ActivityThread对象并调用其“main”入口方法
return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
classLoader);
}
After the application process starts, the initialization process mainly completes the following things in sequence:
- The default
java
exception handling mechanism of the application process (can realizeJava crash
the logic of monitoring and intercepting all the application process); JNI
Call the thread pool of the starting processbinder
(note that the thread pool resource of the application processbinder
is created by itself and notzygote
inherited from the parent process);- Create an object through reflection
ActivityThread
and call its "main
" entry method.
Let's continue to look at RuntimeInit#applicationInit
the simplified code flow:
/*frameworks/base/core/java/com/android/internal/os/RuntimeInit.java*/
protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
String[] argv, ClassLoader classLoader) {
...
// 结束“ZygoteInit ”的systrace tag
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Remaining arguments are passed to the start class's static main
return findStaticMain(args.startClass, args.startArgs, classLoader);
}
protected static Runnable findStaticMain(String className, String[] argv,
ClassLoader classLoader) {
Class<?> cl;
try {
// 1.反射加载创建ActivityThread类对象
cl = Class.forName(className, true, classLoader);
} catch (ClassNotFoundException ex) {
...
}
Method m;
try {
// 2.反射调用其main方法
m = cl.getMethod("main", new Class[] {
String[].class });
} catch (NoSuchMethodException ex) {
...
} catch (SecurityException ex) {
...
}
...
// 3.触发执行以上逻辑
return new MethodAndArgsCaller(m, argv);
}
What is done in the function we continue to look down ActivityThread
:main
/*frameworks/base/core/java/android/app/ActivityThread.java*/
public static void main(String[] args) {
// 原生添加的标识进程ActivityThread初始化过程的systrace tag,名为“ActivityThreadMain”
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
...
// 1.创建并启动主线程的loop消息循环
Looper.prepareMainLooper();
...
// 2.attachApplication注册到系统AMS中
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
...
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
Looper.loop();
...
}
private void attach(boolean system, long startSeq) {
...
if (!system) {
...
final IActivityManager mgr = ActivityManager.getService();
try {
// 通过binder调用AMS的attachApplication接口将自己注册到AMS中
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
}
It can be seen that the main logic of process ActivityThread#main
function initialization is:
- Create and start
loop
the message loop of the main thread; - Register yourself in by
binder
callingAMS
the interface .attachApplication
attach
AMS
The above initialization process. From systrace, it is shown in the following figure:
5. Establishment of application main thread message loop mechanism
Continuing from the analysis in the previous section, we know that after the application process is created, objects will be created through reflection ActivityThread
and its main
functions will be executed to initialize the main thread:
/*frameworks/base/core/java/android/app/ActivityThread.java*/
public static void main(String[] args) {
...
// 1.创建Looper、MessageQueue
Looper.prepareMainLooper();
...
// 2.启动loop消息循环,开始准备接收消息
Looper.loop();
...
}
// 3.创建主线程Handler对象
final H mH = new H();
class H extends Handler {
...
}
/*frameworks/base/core/java/android/os/Looper.java*/
public static void prepareMainLooper() {
// 准备主线程的Looper
prepare(false);
synchronized (Looper.class) {
if (sMainLooper != null) {
throw new IllegalStateException("The main Looper has already been prepared.");
}
sMainLooper = myLooper();
}
}
private static void prepare(boolean quitAllowed) {
if (sThreadLocal.get() != null) {
throw new RuntimeException("Only one Looper may be created per thread");
}
// 创建主线程的Looper对象,并通过ThreadLocal机制实现与主线程的一对一绑定
sThreadLocal.set(new Looper(quitAllowed));
}
private Looper(boolean quitAllowed) {
// 创建MessageQueue消息队列
mQueue = new MessageQueue(quitAllowed);
mThread = Thread.currentThread();
}
After the initialization of the main thread is completed, the main thread has complete Looper
, MessageQueue
, , and can start processing at Handler
this time , including the life cycle functions of components such as , , , , etc., in the form of , which will be processed in the main thread in orderActivityThread
Handler
Message
Application
Activity
ContentProvider
Service
Broadcast
Message
, which is App
The initialization and operation principle of the main thread, part of the processing Message
is as follows
/*frameworks/base/core/java/android/app/ActivityThread.java*/
class H extends Handler {
public static final int BIND_APPLICATION = 110;
@UnsupportedAppUsage
public static final int RECEIVER = 113;
@UnsupportedAppUsage
public static final int CREATE_SERVICE = 114;
@UnsupportedAppUsage
public static final int BIND_SERVICE = 121;
public void handleMessage(Message msg) {
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
...
}
After the initialization of the main thread is completed, the main thread enters the blocking state and waits. Message
Once a Message
message is sent, the main thread will be woken up and Message
processed. After the processing is completed, if there is no other Message
need to be processed, the main thread will enter the dormant blocking state to continue wait. It can be said that Android
the operation of the system is driven by the message mechanism, and the entire message mechanism is realized by the cooperation of the four key roles mentioned above ( , , , Handler
) Looper
. MessageQueue
Its Message
operating principle is shown in the following figure:
Handler
:Handler
Mainly used for processingMessage
, the application can be created in any threadHandler
, as long as the corresponding is specified at the time of creationLooper
, if not specified, the default isThread
corresponding to the currentLooper
.Looper
:Looper
It can be regarded as a circulator. After itsloop
method is opened, it continuously obtainsMessageQueue
fromMessage
,Message
sumsDelivery
withDispatch
, and finally sends it to the correspondingHandler
for processing.**MessageQueue**:MessageQueue
It is aMessage
manager. In the queueMessage
, when there is noMessage
,MessageQueue
with the helpLinux
ofePoll
the mechanism, it blocks and waits for sleep until there isMessage
a queuing to wake it up .**Message**:Message
It is the object to transmit the message, which contains the content to be transmitted, the most commonly used ones includewhat
,arg
, andcallback
so on.
6. Application Application and Activity component creation and initialization
6.1 Application creation and initialization
ActivityThread#main
From the analysis in the previous 4.2.3 summary, we know that during the process of starting the initialization execution function of the application process , loop
before starting the main thread message loop, it will register itself in the system by calling the interface of Binder
the core service of the system . Next, let's continue this process and look down. Let's first look at how the service interface handles the attach registration request of the application process from the systrace:AMS
attachApplication
AMS
AMS
attachApplication
Let's continue to look at the simplified process of the relevant code:
/*frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java*/
@GuardedBy("this")
private boolean attachApplicationLocked(@NonNull IApplicationThread thread,
int pid, int callingUid, long startSeq) {
...
if (app.isolatedEntryPoint != null) {
...
} else if (instr2 != null) {
// 1.通过oneway异步类型的binder调用应用进程ActivityThread#IApplicationThread#bindApplication接口
thread.bindApplication(...);
} else {
thread.bindApplication(...);
}
...
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
// 2.继续执行启动应用Activity的流程
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
}
/*frameworks/base/core/java/android/app/ActivityThread.java*/
private class ApplicationThread extends IApplicationThread.Stub {
@Override
public final void bindApplication(...) {
...
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
...
// 向应用进程主线程Handler发送BIND_APPLICATION消息,触发在应用主线程执行handleBindApplication初始化动作
sendMessage(H.BIND_APPLICATION, data);
}
...
}
class H extends Handler {
...
public void handleMessage(Message msg) {
switch (msg.what) {
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
// 在应用主线程执行handleBindApplication初始化动作
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
...
}
}
...
}
@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
...
}
From the above code flow, it can be seen that during the process AMS
of executing the registration request of the application, the service will call the interface of the application process by type , and the implementation of the interface function will trigger the execution of the initialization function by sending a post message to the message queue of the main thread of the applicationattachApplication
oneway
binder
ActivityThread#IApplicationThread
bindApplication
bindApplication
BIND_APPLICATION
handleBindApplication
. From systrace, it is shown in the following figure:
Let's continue to combine the code to see the simplified key process of handleBindApplication:
/*frameworks/base/core/java/android/app/ActivityThread.java*/
@UnsupportedAppUsage
private void handleBindApplication(AppBindData data) {
...
// 1.创建应用的LoadedApk对象
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
...
// 2.创建应用Application的Context、触发Art虚拟机加载应用APK的Dex文件到内存中,并加载应用APK的Resource资源
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
...
// 3.调用LoadedApk的makeApplication函数,实现创建应用的Application对象
app = data.info.makeApplication(data.restrictedBackupMode, null);
...
// 4.执行应用Application#onCreate生命周期函数
mInstrumentation.onCreate(data.instrumentationArgs);
...
}
During ActivityThread#**handleBindApplication
the initialization process, the following events are mainly completed in the main thread of the application**:
ApplicationInfo
Create the objectAPK
corresponding to the application according to the information passed in by the frameworkLoadedApk
;- Create application
Application
objectsContext
; - Create a class loader
ClassLoader
object and triggerArt
the virtual machine to executeOpenDexFilesFromOat
an action to load theAPK
applicationDex
file ; - By
LoadedApk
loading the applicationAPK
'sResource
resources ; LoadedApk
The function calledmakeApplication
to create the applicationApplication
object;- Execute the application
Application#onCreate
lifecycle function (APP
the first line of code that the application developer can control);
Let's focus on APK Dex
the loading of files and Resource
the loading process of resources in combination with the code.
6.1.1 Dex file loading of application APK
/*frameworks/base/core/java/android/app/ContextImpl.java*/
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo,
String opPackageName) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
// 1.创建应用Application的Context对象
ContextImpl context = new ContextImpl(null, mainThread, packageInfo, null, null, null, null,
0, null, opPackageName);
// 2.触发加载APK的DEX文件和Resource资源
context.setResources(packageInfo.getResources());
context.mIsSystemOrSystemUiContext = isSystemOrSystemUI(context);
return context;
}
/*frameworks/base/core/java/android/app/LoadedApk.java*/
@UnsupportedAppUsage
public Resources getResources() {
if (mResources == null) {
...
// 加载APK的Resource资源
mResources = ResourcesManager.getInstance().getResources(null, mResDir,
splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
getClassLoader()/*触发加载APK的DEX文件*/, null);
}
return mResources;
}
@UnsupportedAppUsage
public ClassLoader getClassLoader() {
synchronized (this) {
if (mClassLoader == null) {
createOrUpdateClassLoaderLocked(null /*addedPaths*/);
}
return mClassLoader;
}
}
private void createOrUpdateClassLoaderLocked(List<String> addedPaths) {
...
if (mDefaultClassLoader == null) {
...
// 创建默认的mDefaultClassLoader对象,触发art虚拟机加载dex文件
mDefaultClassLoader = ApplicationLoaders.getDefault().getClassLoaderWithSharedLibraries(
zip, mApplicationInfo.targetSdkVersion, isBundledApp, librarySearchPath,
libraryPermittedPath, mBaseClassLoader,
mApplicationInfo.classLoaderName, sharedLibraries);
...
}
...
if (mClassLoader == null) {
// 赋值给mClassLoader对象
mClassLoader = mAppComponentFactory.instantiateClassLoader(mDefaultClassLoader,
new ApplicationInfo(mApplicationInfo));
}
}
/*frameworks/base/core/java/android/app/ApplicationLoaders.java*/
ClassLoader getClassLoaderWithSharedLibraries(...) {
// For normal usage the cache key used is the same as the zip path.
return getClassLoader(zip, targetSdkVersion, isBundled, librarySearchPath,
libraryPermittedPath, parent, zip, classLoaderName, sharedLibraries);
}
private ClassLoader getClassLoader(String zip, ...) {
...
synchronized (mLoaders) {
...
if (parent == baseParent) {
...
// 1.创建BootClassLoader加载系统框架类,并增加相应的systrace tag
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
ClassLoader classloader = ClassLoaderFactory.createClassLoader(
zip, librarySearchPath, libraryPermittedPath, parent,
targetSdkVersion, isBundled, classLoaderName, sharedLibraries);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
...
return classloader;
}
// 2.创建PathClassLoader加载应用APK的Dex类,并增加相应的systrace tag
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, zip);
ClassLoader loader = ClassLoaderFactory.createClassLoader(
zip, null, parent, classLoaderName, sharedLibraries);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
return loader;
}
}
/*frameworks/base/core/java/com/android/internal/os/ClassLoaderFactory.java*/
public static ClassLoader createClassLoader(...) {
// 通过new的方式创建ClassLoader对象,最终会触发art虚拟机加载APK的dex文件
ClassLoader[] arrayOfSharedLibraries = (sharedLibraries == null)
? null
: sharedLibraries.toArray(new ClassLoader[sharedLibraries.size()]);
if (isPathClassLoaderName(classloaderName)) {
return new PathClassLoader(dexPath, librarySearchPath, parent, arrayOfSharedLibraries);
}
...
}
As can be seen from the above code: after the object is created, Application
it Context
will try to load the resource immediately APK
, Resource
but before that, it needs to LoadedApk
create a class loader ClassLoader
object, and this process will eventually trigger Art
the virtual machine to load the application APK
file dex
, from systrace See the picture below:
The specific art virtual machine loading dex file process will not be discussed here due to space limitations. Here is a flow chart drawn for reference. Interested readers can follow the source code process by comparison:
6.1.2 Application APK Resource resource loading
/*frameworks/base/core/java/android/app/LoadedApk.java*/
@UnsupportedAppUsage
public Resources getResources() {
if (mResources == null) {
...
// 加载APK的Resource资源
mResources = ResourcesManager.getInstance().getResources(null, mResDir,
splitPaths, mOverlayDirs, mApplicationInfo.sharedLibraryFiles,
Display.DEFAULT_DISPLAY, null, getCompatibilityInfo(),
getClassLoader()/*触发加载APK的DEX文件*/, null);
}
return mResources;
}
/*frameworks/base/core/java/android/app/ResourcesManager.java*/
public @Nullable Resources getResources(...) {
try {
// 原生Resource资源加载的systrace tag
Trace.traceBegin(Trace.TRACE_TAG_RESOURCES, "ResourcesManager#getResources");
...
return createResources(activityToken, key, classLoader, assetsSupplier);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_RESOURCES);
}
}
private @Nullable Resources createResources(...) {
synchronized (this) {
...
// 执行创建Resources资源对象
ResourcesImpl resourcesImpl = findOrCreateResourcesImplForKeyLocked(key, apkSupplier);
if (resourcesImpl == null) {
return null;
}
...
}
}
private @Nullable ResourcesImpl findOrCreateResourcesImplForKeyLocked(
@NonNull ResourcesKey key, @Nullable ApkAssetsSupplier apkSupplier) {
...
impl = createResourcesImpl(key, apkSupplier);
...
}
private @Nullable ResourcesImpl createResourcesImpl(@NonNull ResourcesKey key,
@Nullable ApkAssetsSupplier apkSupplier) {
...
// 创建AssetManager对象,真正实现的APK文件加载解析动作
final AssetManager assets = createAssetManager(key, apkSupplier);
...
}
private @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key,
@Nullable ApkAssetsSupplier apkSupplier) {
...
for (int i = 0, n = apkKeys.size(); i < n; i++) {
final ApkKey apkKey = apkKeys.get(i);
try {
// 通过loadApkAssets实现应用APK文件的加载
builder.addApkAssets(
(apkSupplier != null) ? apkSupplier.load(apkKey) : loadApkAssets(apkKey));
} catch (IOException e) {
...
}
}
...
}
private @NonNull ApkAssets loadApkAssets(@NonNull final ApkKey key) throws IOException {
...
if (key.overlay) {
...
} else {
// 通过ApkAssets从APK文件所在的路径去加载
apkAssets = ApkAssets.loadFromPath(key.path,
key.sharedLib ? ApkAssets.PROPERTY_DYNAMIC : 0);
}
...
}
/*frameworks/base/core/java/android/content/res/ApkAssets.java*/
public static @NonNull ApkAssets loadFromPath(@NonNull String path, @PropertyFlags int flags)
throws IOException {
return new ApkAssets(FORMAT_APK, path, flags, null /* assets */);
}
private ApkAssets(@FormatType int format, @NonNull String path, @PropertyFlags int flags,
@Nullable AssetsProvider assets) throws IOException {
...
// 通过JNI调用Native层的系统system/lib/libandroidfw.so库中的相关C函数实现对APK文件压缩包的解析与加载
mNativePtr = nativeLoad(format, path, flags, assets);
...
}
It can be seen from the above code: **The process of loading application APK
file resources by the system is actually the process of creating resource objects in the application process , in which the parsing of resource files Resources
is actually realized , and finally it is through JNI calling the related system layer. function implementation. **The whole process is shown in the figure below from systrace:APK
I/O
AssetManager
Native
C
6.2 Activity creation and initialization
Let's go back to the 6.1 summary and see that AMS
after receiving the registration request of the application process , first call the # interface attachApplication
of the application and process through the oneway type binder , trigger the application process to perform initialization operations on the main thread, and then continue to execute the operation of starting the application , let's take a look at how the system starts to create an application . The simplified code flow is as follows:IApplicationThread
bindApplication
handleBindeApplication
Activity
Activity
/*frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java*/
@GuardedBy("this")
private boolean attachApplicationLocked(...) {
...
if (app.isolatedEntryPoint != null) {
...
} else if (instr2 != null) {
// 1.通过oneway异步类型的binder调用应用进程ActivityThread#IApplicationThread#bindApplication接口
thread.bindApplication(...);
} else {
thread.bindApplication(...);
}
...
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
// 2.继续执行启动应用Activity的流程
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
}
/*frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java*/
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLockWithoutBoost) {
if (Trace.isTagEnabled(TRACE_TAG_WINDOW_MANAGER)) {
// 原生标识attachApplication过程的systrace tag
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "attachApplication:" + wpc.mName);
}
try {
return mRootWindowContainer.attachApplication(wpc);
} finally {
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
}
}
}
/*frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java*/
boolean attachApplication(WindowProcessController app) throws RemoteException {
...
final PooledFunction c = PooledLambda.obtainFunction(
// startActivityForAttachedApplicationIfNeeded执行启动应用Activity流程
RootWindowContainer::startActivityForAttachedApplicationIfNeeded, this,
PooledLambda.__(ActivityRecord.class), app,
rootTask.topRunningActivity());
...
}
private boolean startActivityForAttachedApplicationIfNeeded(ActivityRecord r,
WindowProcessController app, ActivityRecord top) {
...
try {
// ActivityStackSupervisor的realStartActivityLocked真正实现启动应用Activity流程
if (mStackSupervisor.realStartActivityLocked(r, app,
top == r && r.isFocusable() /*andResume*/, true /*checkConfig*/)) {
...
}
} catch (RemoteException e) {
..
}
}
/*frameworks/base/services/core/java/com/android/server/wm/ActivityStackSupervisor.java*/
boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
boolean andResume, boolean checkConfig) throws RemoteException {
...
// 1.先通过LaunchActivityItem封装Binder通知应用进程执行Launch Activity动作
clientTransaction.addCallback(LaunchActivityItem.obtain(...);
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
if (andResume) {
// 2.再通过ResumeActivityItem封装Binder通知应用进程执行Launch Resume动作
lifecycleItem = ResumeActivityItem.obtain(dc.isNextTransitionForward());
}
...
clientTransaction.setLifecycleStateRequest(lifecycleItem);
// 执行以上封装的Binder调用
mService.getLifecycleManager().scheduleTransaction(clientTransaction);
...
}
From the above code analysis, it can be seen that the framework system_server
process finally implements the binder call to notify the application process of the Launch and Resume actions executed here through the encapsulation of the two classes in the # function. Let's continue to look at the relevant ActivityStackSupervisor
code realStartActivityLocked
flow :LaunchActivityItem
ResumeActivityItem
Activity
6.2.1 Activity Create
/*frameworks/base/core/java/android/app/servertransaction/LaunchActivityItem.java*/
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
// 原生标识Activity Launch的systrace tag
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = new ActivityClientRecord(token, mIntent, mIdent, mInfo,
mOverrideConfig, mCompatInfo, mReferrer, mVoiceInteractor, mState, mPersistentState,
mPendingResults, mPendingNewIntents, mIsForward,
mProfilerInfo, client, mAssistToken, mFixedRotationAdjustments);
// 调用到ActivityThread的handleLaunchActivity函数在主线程执行应用Activity的Launch创建动作
client.handleLaunchActivity(r, pendingActions, null /* customIntent */);
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
/*frameworks/base/core/java/android/app/ActivityThread.java*/
@Override
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
...
final Activity a = performLaunchActivity(r, customIntent);
...
}
/** Core implementation of activity launch. */
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
...
// 1.创建Activity的Context
ContextImpl appContext = createBaseContextForActivity(r);
try {
//2.反射创建Activity对象
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
...
} catch (Exception e) {
...
}
try {
...
if (activity != null) {
...
// 3.执行Activity的attach动作
activity.attach(...);
...
// 4.执行应用Activity的onCreate生命周期函数,并在setContentView调用中创建DecorView对象
mInstrumentation.callActivityOnCreate(activity, r.state);
...
}
...
} catch (SuperNotCalledException e) {
...
}
}
/*frameworks/base/core/java/android/app/Activity.java*/
@UnsupportedAppUsage
final void attach(...) {
...
// 1.创建表示应用窗口的PhoneWindow对象
mWindow = new PhoneWindow(this, window, activityConfigCallback);
...
// 2.为PhoneWindow配置WindowManager
mWindow.setWindowManager(
(WindowManager)context.getSystemService(Context.WINDOW_SERVICE),
mToken, mComponent.flattenToString(),
(info.flags & ActivityInfo.FLAG_HARDWARE_ACCELERATED) != 0);
...
}
As can be seen from the above code, after the application process receives the system binder call, the main steps of the process created in the main threadActiviy
are as follows :
- Created ;
Activity
_Context
- Create
Activity
objects through reflection; Activity
The action performedattach
, in which the object of the application window is createdPhoneWindow
and setWindowManage
;- Execute the life cycle function
Activity
of the applicationonCreate
andsetContentView
create a windowDecorView
object in it ;
Looking at the whole process from systrace is shown in the figure below:
6.2.2 Activity Resume
/*frameworks/base/core/java/android/app/servertransaction/ResumeActivityItem.java*/
@Override
public void execute(ClientTransactionHandler client, IBinder token,
PendingTransactionActions pendingActions) {
// 原生标识Activity Resume的systrace tag
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "activityResume");
client.handleResumeActivity(token, true /* finalStateRequest */, mIsForward,
"RESUME_ACTIVITY");
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
/*frameworks/base/core/java/android/app/ActivityThread.java*/
@Override
public void handleResumeActivity(...){
...
// 1.执行performResumeActivity流程,执行应用Activity的onResume生命周期函数
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
...
if (r.window == null && !a.mFinished && willBeVisible) {
...
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
...
// 2.执行WindowManager#addView动作开启视图绘制逻辑
wm.addView(decor, l);
} else {
...
}
}
}
...
}
public ActivityClientRecord performResumeActivity(...) {
...
// 执行应用Activity的onResume生命周期函数
r.activity.performResume(r.startsNotResumed, reason);
...
}
/*frameworks/base/core/java/android/view/WindowManagerGlobal.java*/
public void addView(...) {
// 创建ViewRootImpl对象
root = new ViewRootImpl(view.getContext(), display);
...
try {
// 执行ViewRootImpl的setView函数
root.setView(view, wparams, panelParentView, userId);
} catch (RuntimeException e) {
...
}
}
As can be seen from the above code, after the application process receives the system Binder call request, the main steps of the process in the main threadActiviy
Resume
are as follows :
- Execute application
Activity
lifecycleonResume
functions ; WindowManager
The action performedaddView
starts the view drawing logic;Activity
the createdViewRootImpl
object;ViewRootImpl
The executedsetView
function starts the UI interface drawing action ;
Looking at the whole process from systrace is shown in the figure below:
7. Application UI layout and drawing
Continuing from the analysis in the previous section, at the end of the Resume process executed in the main thread of the application Activity
, an object is created ViewRootImpl
and its setView function is called, which starts the process of UI layout and drawing of the application interface. Before starting to explain this process, let's sort out the concepts mentioned in the previous code, such as Activity
, PhoneWindow
, DecorView
, ViewRootImpl
, WindowManager
the relationship and responsibilities between them, because these core classes basically constitute the GUI display system of the Android system in the application process. The core architecture on the side, its overall architecture is shown in the figure below:
Window
It is an abstract class that provides some standard UI solutions through controlDecorView
背景、标题、虚拟按键等
, for example, the only implementation class ofPhoneWindow
but , which is created in the attach process after creation, and the content displayed by the application is loaded into its internal ( );Window
Activity
mDecor
DecorView
DecorView
It is the root node of the entire interface layout View control tree, through which you can traverse and access any node on the entire View control tree;WindowManager
It is an interface, which inherits fromViewManager
the interface and providesView
basic operation methods;WindowManagerImp
implementsWindowManager
the interface, and组合
holds it internallyWindowManagerGlobal
for operationView
;WindowManagerGlobal
it is a global singleton, which can beViewRootImpl
addedView
to it窗口
internally ;ViewRootImpl
It is allView
,Parent
used for overall managementView
drawing andWMS
IPC interaction with the system window management service to achieve development窗口
; itViewRootImpl
is the engine of the application process running, you can see thatViewRootImpl
it containsmView
(that isDecorView
),mSurface
,Choregrapher
,mView
representing the entire control tree,mSurfacce
representing the canvas, The UI rendering of the application will be directly placedmSurface
in the middle,Choregorapher
so that the application requestsvsync
the signal and starts the rendering process after receiving the signal;
weViewRootImpl
continue to combine the code from the setView process to look down:
/*frameworks/base/core/java/android/view/ViewRootImpl.java*/
public void setView(View view, WindowManager.LayoutParams attrs, View panelParentView,
int userId) {
synchronized (this) {
if (mView == null) {
mView = view;
}
...
// 开启绘制硬件加速,初始化RenderThread渲染线程运行环境
enableHardwareAcceleration(attrs);
...
// 1.触发绘制动作
requestLayout();
...
inputChannel = new InputChannel();
...
// 2.Binder调用访问系统窗口管理服务WMS接口,实现addWindow添加注册应用窗口的操作,并传入inputChannel用于接收触控事件
res = mWindowSession.addToDisplayAsUser(mWindow, mSeq, mWindowAttributes,
getHostVisibility(), mDisplay.getDisplayId(), userId, mTmpFrame,
mAttachInfo.mContentInsets, mAttachInfo.mStableInsets,
mAttachInfo.mDisplayCutout, inputChannel,
mTempInsets, mTempControls);
...
// 3.创建WindowInputEventReceiver对象,实现应用窗口接收触控事件
mInputEventReceiver = new WindowInputEventReceiver(inputChannel,
Looper.myLooper());
...
// 4.设置DecorView的mParent为ViewRootImpl
view.assignParent(this);
...
}
}
As can be seen from the above code, ViewRootImpl
the key internal process of setView is as follows:
- requestLayout() triggers interface drawing (measure, layout, draw) actions through a series of calls , which will be analyzed in detail below;
- Call the interface to access the system window management service through Binder
WMS
,addWindow
realize the operation of adding and registering the application window , and pass in the local inputChannel object to receive the touch event of the system later. After this step is executed, we canView
display it on the screen. . The internalWMS
implementation process is also very complicated. Due to the limited space, this article will not analyze it in detail. - Create a WindowInputEventReceiver object to encapsulate the logic for the application window to receive system touch events;
- Execute view.assignParent(this), and set
DecorView
mParent toViewRootImpl
. So, whileViewRootImpl
not oneView
, it'sView
the top layer of allParent
.
Let's continue to look down at the process code of the interface drawing along the action ViewRootImpl
:requestLayout
/*frameworks/base/core/java/android/view/ViewRootImpl.java*/
public void requestLayout() {
if (!mHandlingLayoutInLayoutRequest) {
// 检查当前UI绘制操作是否发生在主线程,如果发生在子线程则会抛出异常
checkThread();
mLayoutRequested = true;
// 触发绘制操作
scheduleTraversals();
}
}
@UnsupportedAppUsage
void scheduleTraversals() {
if (!mTraversalScheduled) {
...
// 注意此处会往主线程的MessageQueue消息队列中添加同步栏删,因为系统绘制消息属于异步消息,需要更高优先级的处理
mTraversalBarrier = mHandler.getLooper().getQueue().postSyncBarrier();
// 通过Choreographer往主线程消息队列添加CALLBACK_TRAVERSAL绘制类型的待执行消息,用于触发后续UI线程真正实现绘制动作
mChoreographer.postCallback(
Choreographer.CALLBACK_TRAVERSAL, mTraversalRunnable, null);
...
}
}
Choreographer
The introduction is mainly to cooperate with Vsync
the vertical synchronization mechanism of the system (one of the mechanisms introduced in the Android "butter project", which coordinates the APP to generate UI data and SurfaceFlinger
synthesized images, and avoids tearing of the tearing screen), and provides a stable rendering for the upper-layer App. Message
The timing of processing, that is, Vsync
the arrival of , the system Vsync
controls the timing of each frame drawing operation by adjusting the signal cycle. Choreographer
Play the role of linking up and down in the Android rendering chain :
- Inheritance : Responsible for receiving and processing various update messages and callbacks of the App, and
Vsync
processing them uniformly when the App arrives. For example, centralized processing of Input (mainly the processing of Input events), Animation (related to animation), Traversal (includingmeasure、layout、draw
operations such as ), judging frame drops and recording CallBack time-consuming, etc.; - Qixia : Responsible for requesting and receiving Vsync signals. Receive Vsync event callback (via
FrameDisplayEventReceiver
.onVsync
), requestVsync
(FrameDisplayEventReceiver
.scheduleVsync
).
Choreographer
After receiving CALLBACK_TRAVERSAL
a type of drawing task, its internal workflow is shown in the following figure:
It can be seen from the above flow chart that after the called interface puts the drawing message to be executed, it ViewRootImpl
will first apply to the system for a signal of type , and then wait for the system signal to arrive, and then execute the real drawing action (measure, layout, draw). This drawing process is shown in the following figure from systrace:Choreographer
postCallback
Choreographer
APP
vsync
vsync
ViewRootImpl
doTraversal
The simplified code flow of our next ViewRootImpl
function looks as follows:doTraversal
/*frameworks/base/core/java/android/view/ViewRootImpl.java*/
void doTraversal() {
if (mTraversalScheduled) {
mTraversalScheduled = false;
// 调用removeSyncBarrier及时移除主线程MessageQueue中的Barrier同步栏删,以避免主线程发生“假死”
mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);
...
// 执行具体的绘制任务
performTraversals();
...
}
}
private void performTraversals() {
...
// 1.从DecorView根节点出发,遍历整个View控件树,完成整个View控件树的measure测量操作
windowSizeMayChange |= measureHierarchy(...);
...
if (mFirst...) {
// 2.第一次执行traversals绘制任务时,Binder调用访问系统窗口管理服务WMS的relayoutWindow接口,实现WMS计算应用窗口尺寸并向系统surfaceflinger正式申请Surface“画布”操作
relayoutResult = relayoutWindow(params, viewVisibility, insetsPending);
}
...
// 3.从DecorView根节点出发,遍历整个View控件树,完成整个View控件树的layout测量操作
performLayout(lp, mWidth, mHeight);
...
// 4.从DecorView根节点出发,遍历整个View控件树,完成整个View控件树的draw测量操作
performDraw();
...
}
private int relayoutWindow(WindowManager.LayoutParams params, int viewVisibility,
boolean insetsPending) throws RemoteException {
...
// 通过Binder IPC访问系统WMS服务的relayout接口,申请Surface“画布”操作
int relayoutResult = mWindowSession.relayout(mWindow, mSeq, params,
(int) (mView.getMeasuredWidth() * appScale + 0.5f),
(int) (mView.getMeasuredHeight() * appScale + 0.5f), viewVisibility,
insetsPending ? WindowManagerGlobal.RELAYOUT_INSETS_PENDING : 0, frameNumber,
mTmpFrame, mTmpRect, mTmpRect, mTmpRect, mPendingBackDropFrame,
mPendingDisplayCutout, mPendingMergedConfiguration, mSurfaceControl, mTempInsets,
mTempControls, mSurfaceSize, mBlastSurfaceControl);
if (mSurfaceControl.isValid()) {
if (!useBLAST()) {
// 本地Surface对象获取指向远端分配的Surface的引用
mSurface.copyFrom(mSurfaceControl);
} else {
...
}
}
...
}
private void performMeasure(int childWidthMeasureSpec, int childHeightMeasureSpec) {
...
// 原生标识View树的measure测量过程的trace tag
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "measure");
try {
// 从mView指向的View控件树的根节点DecorView出发,遍历访问整个View树,并完成整个布局View树的测量工作
mView.measure(childWidthMeasureSpec, childHeightMeasureSpec);
} finally {
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
}
private void performDraw() {
...
boolean canUseAsync = draw(fullRedrawNeeded);
...
}
private boolean draw(boolean fullRedrawNeeded) {
...
if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
...
// 如果开启并支持硬件绘制加速,则走硬件绘制的流程(从Android 4.+开始,默认情况下都是支持跟开启了硬件加速的)
mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
} else {
// 否则走drawSoftware软件绘制的流程
if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset,
scalingRequired, dirty, surfaceInsets)) {
return false;
}
}
}
As can be seen from the above code flow, ViewRootImpl
the main flow of drawing the entire application interface in charge of is as follows :
- Starting from the root node of the interface View control tree
DecorView
, recursively traverse the entire View control tree, and complete the measurement operationView
of the entire control treemeasure
. Due to space limitations, this article will not analyze the detailed process of this piece; - When the interface executes the drawing task for the first time, it will
Binder
IPC
access the relayout interface of the system window management service WMS to realize the calculation of the window size and apply to the system for the operation of the Surface "canvas" for local drawing and rendering (specifically, the corresponding interface responsible for creatingSurfaceFlinger
the application interface object , and pass the address reference back to the application process through WMSBufferQueueLayer
through memory sharingBinder
), due to space limitations, this article will not analyze the detailed process of this piece; - Starting from the root node of the interface View control tree
DecorView
, recursively traverse the entire View control tree to complete the measurement operationView
of the entire control treelayout
; - Start from the root node of the interface View control tree
DecorView
, recursively traverse the entire control tree, and complete the measurement operationView
on the entireView
control tree . If hardware acceleration is enabled and supported (Google has enabled hardware acceleration by default since Android 4.X), then use the hardware The drawing process, otherwise follow the software drawing process ;draw
GPU
CPU
The above drawing process is shown in the following figure from systrace:
Borrow a picture to summarize the process of application UI drawing, as follows:
8. RenderThread rendering
So far, ViewRootImpl
after completing the drawing process of the interface such as measure, layout, and draw, the user still cannot see the content of the application interface displayed on the screen, because the display process of the entire system is in addition to the drawing Android
of the UI thread mentioned above. In addition, the interface also needs to be RenderThread
rendered by threads. After the rendering is completed, it needs to be handed Binder
over to the process by calling "upframe" surfaceflinger
for synthesis and then sent to display before it can be finally displayed on the screen. ViewRootImpl
In this section, we will follow the last draw process in the previous section and continue to analyze RenderThread
the workflow of the rendering thread when hardware acceleration is enabled. Since the current system default interface after Android 4.X is to enable hardware acceleration, so in this article we focus on analyzing the interface rendering process under hardware acceleration conditions. Let's first analyze the simplified code process:
/*frameworks/base/core/java/android/view/ViewRootImpl.java*/
private boolean draw(boolean fullRedrawNeeded) {
...
if (mAttachInfo.mThreadedRenderer != null && mAttachInfo.mThreadedRenderer.isEnabled()) {
...
// 硬件加速条件下的界面渲染流程
mAttachInfo.mThreadedRenderer.draw(mView, mAttachInfo, this);
} else {
...
}
}
/*frameworks/base/core/java/android/view/ThreadedRenderer.java*/
void draw(View view, AttachInfo attachInfo, DrawCallbacks callbacks) {
...
// 1.从DecorView根节点出发,递归遍历View控件树,记录每个View节点的绘制操作命令,完成绘制操作命令树的构建
updateRootDisplayList(view, callbacks);
...
// 2.JNI调用同步Java层构建的绘制命令树到Native层的RenderThread渲染线程,并唤醒渲染线程利用OpenGL执行渲染任务;
int syncResult = syncAndDrawFrame(choreographer.mFrameInfo);
...
}
As can be seen from the above code, hardware accelerated drawing mainly includes two stages :
- Starting from
DecorView
the root node, recursively traverseView
the control tree, record the drawing operation commandView
of each node , and complete the construction of the drawing operation command tree;drawOp
JNI
CallJava
the drawing command tree built by the synchronization layer to the rendering threadNative
of the layer , and wake up the rendering thread to perform rendering tasks;RenderThread
OpenGL
8.1 Build the drawing command tree
Let's first take a look at the code simplification process for building and drawing the command tree in the first stage:
/*frameworks/base/core/java/android/view/ThreadedRenderer.java*/
private void updateRootDisplayList(View view, DrawCallbacks callbacks) {
// 原生标记构建View绘制操作命令树过程的systrace tag
Trace.traceBegin(Trace.TRACE_TAG_VIEW, "Record View#draw()");
// 递归子View的updateDisplayListIfDirty实现构建DisplayListOp
updateViewTreeDisplayList(view);
...
if (mRootNodeNeedsUpdate || !mRootNode.hasDisplayList()) {
// 获取根View的SkiaRecordingCanvas
RecordingCanvas canvas = mRootNode.beginRecording(mSurfaceWidth, mSurfaceHeight);
try {
...
// 利用canvas缓存DisplayListOp绘制命令
canvas.drawRenderNode(view.updateDisplayListIfDirty());
...
} finally {
// 将所有DisplayListOp绘制命令填充到RootRenderNode中
mRootNode.endRecording();
}
}
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
private void updateViewTreeDisplayList(View view) {
...
// 从DecorView根节点出发,开始递归调用每个View树节点的updateDisplayListIfDirty函数
view.updateDisplayListIfDirty();
...
}
/*frameworks/base/core/java/android/view/View.java*/
public RenderNode updateDisplayListIfDirty() {
...
// 1.利用`View`对象构造时创建的`RenderNode`获取一个`SkiaRecordingCanvas`“画布”;
final RecordingCanvas canvas = renderNode.beginRecording(width, height);
try {
...
if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
// 如果仅仅是ViewGroup,并且自身不用绘制,直接递归子View
dispatchDraw(canvas);
...
} else {
// 2.利用SkiaRecordingCanvas,在每个子View控件的onDraw绘制函数中调用drawLine、drawRect等绘制操作时,创建对应的DisplayListOp绘制命令,并缓存记录到其内部的SkiaDisplayList持有的DisplayListData中;
draw(canvas);
}
} finally {
// 3.将包含有`DisplayListOp`绘制命令缓存的`SkiaDisplayList`对象设置填充到`RenderNode`中;
renderNode.endRecording();
...
}
...
}
public void draw(Canvas canvas) {
...
// draw the content(View自己实现的onDraw绘制,由应用开发者自己实现)
onDraw(canvas);
...
// draw the children
dispatchDraw(canvas);
...
}
/*frameworks/base/graphics/java/android/graphics/RenderNode.java*/
public void endRecording() {
...
// 从SkiaRecordingCanvas中获取SkiaDisplayList对象
long displayList = canvas.finishRecording();
// 将SkiaDisplayList对象填充到RenderNode中
nSetDisplayList(mNativeRenderNode, displayList);
canvas.recycle();
}
As can be seen from the above code, the process of building the drawing command tree is triggered from View
the root node of the control tree DecorView
, recursively calls the function View
of each child node updateDisplayListIfDirty
, and finally completes the creation of the drawing tree. The brief process is as follows :
- Get a "canvas"
View
created when the object is constructed ;RenderNode
SkiaRecordingCanvas
- Use
SkiaRecordingCanvas
, when calling and other drawing operations in the drawing function of each sub- control , create the corresponding drawing command, and cache and record it in its internal holdingView
onDraw
drawLine
drawRect
DisplayListOp
SkiaDisplayList
DisplayListData
; - Fill in the object settings containing
DisplayListOp
the drawing command buffer ;SkiaDisplayList
RenderNode
- Finally, set the root
View
cache to , and complete the build.DisplayListOp
RootRenderNode
The entire process of building and drawing the command tree above can be represented by the following flow chart:
The View tree structure of the entire interface under hardware acceleration is shown in the following figure:
Finally, look at the process from systrace as shown in the figure below:
8.2 Execute rendering and drawing tasks
After the analysis in the previous section, the application starts UI
from the root node in the thread DecorView
, recursively traverses each child View
node, collects its drawXXX
drawing actions and converts them into DisplayListOp
commands, records them DisplayListData
and fills them in RenderNode
, and finally completes View
the construction of the entire drawing command tree. From then on, the drawing task of the UI thread is completed. In the next step UI
, the thread will wake up RenderThread
the rendering thread and trigger it to execute OpenGL
the rendering task of the interface. In this section, we will focus on analyzing this process. Let's take a look at the simplified process of this code first:
/*frameworks/base/graphics/java/android/graphics/HardwareRenderer.java*/
public int syncAndDrawFrame(@NonNull FrameInfo frameInfo) {
// JNI调用native层的相关函数
return nSyncAndDrawFrame(mNativeProxy, frameInfo.frameInfo, frameInfo.frameInfo.length);
}
/*frameworks/base/libs/hwui/jni/android_graphics_HardwareRenderer.cpp*/
static int android_view_ThreadedRenderer_syncAndDrawFrame(JNIEnv* env, jobject clazz,
jlong proxyPtr, jlongArray frameInfo, jint frameInfoSize) {
...
RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr);
env->GetLongArrayRegion(frameInfo, 0, frameInfoSize, proxy->frameInfo());
return proxy->syncAndDrawFrame();
}
/*frameworks/base/libs/hwui/renderthread/RenderProxy.cpp*/
int RenderProxy::syncAndDrawFrame() {
// 唤醒RenderThread渲染线程,执行DrawFrame绘制任务
return mDrawFrameTask.drawFrame();
}
/*frameworks/base/libs/hwui/renderthread/DrawFrameTask.cpp*/
int DrawFrameTask::drawFrame() {
...
postAndWait();
...
}
void DrawFrameTask::postAndWait() {
AutoMutex _lock(mLock);
// 向RenderThread渲染线程的MessageQueue消息队列放入一个待执行任务,以将其唤醒执行run函数
mRenderThread->queue().post([this]() {
run(); });
// UI线程暂时进入wait等待状态
mSignal.wait(mLock);
}
void DrawFrameTask::run() {
// 原生标识一帧渲染绘制任务的systrace tag
ATRACE_NAME("DrawFrame");
...
{
TreeInfo info(TreeInfo::MODE_FULL, *mContext);
//1.将UI线程构建的DisplayListOp绘制命令树同步到RenderThread渲染线程
canUnblockUiThread = syncFrameState(info);
...
}
...
// 同步完成后则可以唤醒UI线程
if (canUnblockUiThread) {
unblockUiThread();
}
...
if (CC_LIKELY(canDrawThisFrame)) {
// 2.执行draw渲染绘制动作
context->draw();
} else {
...
}
...
}
bool DrawFrameTask::syncFrameState(TreeInfo& info) {
ATRACE_CALL();
...
// 调用CanvasContext的prepareTree函数实现绘制命令树同步的流程
mContext->prepareTree(info, mFrameInfo, mSyncQueued, mTargetNode);
...
}
/*frameworks/base/libs/hwui/renderthread/CanvasContext.cpp*/
void CanvasContext::prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued,
RenderNode* target) {
...
for (const sp<RenderNode>& node : mRenderNodes) {
...
// 递归调用各个子View对应的RenderNode执行prepareTree动作
node->prepareTree(info);
...
}
...
}
/*frameworks/base/libs/hwui/RenderNode.cpp*/
void RenderNode::prepareTree(TreeInfo& info) {
ATRACE_CALL();
...
prepareTreeImpl(observer, info, false);
...
}
void RenderNode::prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer) {
...
if (info.mode == TreeInfo::MODE_FULL) {
// 同步绘制命令树
pushStagingDisplayListChanges(observer, info);
}
if (mDisplayList) {
// 遍历调用各个子View对应的RenderNode的prepareTreeImpl
bool isDirty = mDisplayList->prepareListAndChildren(
observer, info, childFunctorsNeedLayer,
[](RenderNode* child, TreeObserver& observer, TreeInfo& info,
bool functorsNeedLayer) {
child->prepareTreeImpl(observer, info, functorsNeedLayer);
});
...
}
...
}
void RenderNode::pushStagingDisplayListChanges(TreeObserver& observer, TreeInfo& info) {
...
syncDisplayList(observer, &info);
...
}
void RenderNode::syncDisplayList(TreeObserver& observer, TreeInfo* info) {
...
// 完成赋值同步DisplayList对象
mDisplayList = mStagingDisplayList;
mStagingDisplayList = nullptr;
...
}
void CanvasContext::draw() {
...
// 1.调用OpenGL库使用GPU,按照构建好的绘制命令完成界面的渲染
bool drew = mRenderPipeline->draw(frame, windowDirty, dirty, mLightGeometry, &mLayerUpdateQueue,
mContentDrawBounds, mOpaque, mLightInfo, mRenderNodes,
&(profiler()));
...
// 2.将前面已经绘制渲染好的图形缓冲区Binder上帧给SurfaceFlinger合成和显示
bool didSwap =
mRenderPipeline->swapBuffers(frame, drew, windowDirty, mCurrentFrameInfo, &requireSwap);
...
}
It can be seen from the above code that UI
the thread utilizes to send a task request RenderProxy
to the thread, wakes up, and starts rendering. The general process is as follows :RenderThread
DrawFrameTask
RenderThread
syncFrameState
TraversingView
each one on the treeRenderNode
, executingprepareTreeImpl
the function, and realizing the operation of synchronously drawing the command tree;- Call
OpenGL
the libraryAPI
to useGPU
, and complete the rendering of the interface according to the built drawing command (the specific process, due to the limited space of this article, will not be analyzed for the time being); - Frame the previously drawn and rendered graphics buffer
Binder
forSurfaceFlinger
synthesis and display;
The whole process can be represented by the following flowchart:
This process from systrace is shown in the following figure:
9. SurfaceFlinger synthetic display
SurfaceFlinger
The synthetic display part belongs to the graphic display content in the Android
system completely , and the logical structure is relatively complicated, but it does not belong to the focus of this article. GUI
Therefore, this section only introduces its working principle and ideas in general, and does not analyze the source code in detail. Interested readers can follow the author's follow-up articles for detailed analysis and explanation. Simply put, SurfaceFlinger
as a process that runs independently in the system Native
, ** borrows Android
the description from the official website, and its responsibility is to accept data buffers from multiple sources, synthesize them, and then send them to the display device. **As shown below:
As can be seen from the above figure, it actually plays a connecting roleSurfaceFlinger
in the entire graphic display system of the system :Android
- For the above : establish contact with different application processes through Surface, receive the drawing buffer data written by them in Surface, and synthesize them in a unified manner.
- To the bottom : establish a connection with the screen through the back buffer area of the screen, and send the synthesized data to the screen display device.
The transmission of graphics is to be further encapsulated Buffer
as a carrier , that is to say, there are multiple internally for the upper layer to use. How to manage these ? The answer is , here's how it works:Surface
Buffer
Surface
Buffer
Buffer
BufferQueue
BufferQueue
9.1 BufferQueue mechanism
Borrow a classic picture to describe BufferQueue
the working principle:
BufferQueue
is a typical producer-consumer data structure . In Android
the rendering process of the application, the application plays the role of "producer" and SurfaceFlinger
the role of "consumer". The working process is as follows :
- Before starting the drawing and rendering of the interface in the application process, it is necessary to apply for an available state from the managed in the process by
Binder
calling the interface . If it is not available at this time, it will block and wait;dequeueBuffer
SurfaceFlinger
BufferQueue
free
Buffer
Buffer
- After getting this available in the application process
Buffer
, choose to useCPU
software rendering orGPU
hardware accelerated rendering. After the rendering is completed, the cached data will be returned to the corresponding application process byBinder
calling the interface (if it is rendering, there is also a processing process, so this will not be available immediately, you need to wait for the rendering completion signal), and apply for the type to wake up the "consumer" for consumption;queueBuffer
BufferQueue
GPU
GPU
Buffer
GPU
Fence
sf
Vsync
SurfaceFlinger
SurfaceFlinger
After receivingVsync
the signal, start to prepare for synthesis, use toacquireBuffer
obtain the correspondingBufferQueue
in the applicationBuffer
and perform the synthesis operation;- After the composition is completed, it will be set to the available state
SurfaceFlinger
by calling and return to the corresponding in the application .releaseBuffer
Buffer
free
BufferQueue
9.2 Vsync synchronization mechanism
Vysnc
Vertical synchronization is Android
an important mechanism introduced in the "butter plan", which is essentially for the purpose of coordinating the BufferQueue
UI data generation action of the application producer and SurfaceFlinger
the synthetic consumption action of the consumer, so as to avoid Tearing
the phenomenon of screen tearing. Vysnc
Signals are of two types:
app
TypeVsync
:app
The type of signal is registered and receivedVysnc
by the upper-layer applicationChoreographer
according to the drawing requirements, and is used to control the production rhythm of the application UI drawing frame . According to the analysis in the 7th summary: when the application calls invalidate in the UI thread to refresh the interface drawing, it needs to apply to theChoreographer
system to registerVsync
the signal of the app type. AfterVsync
the signal arrives, it can put the task to be drawn in the message queue of the main thread. Perform real UI drawing actions;sf
TypeVsync
:sf
TypeVsync
is used to controlSurfaceFlinger
the rhythm of the composition consumption . After the application completes the drawing and rendering of the interface, when returning the cached data to the corresponding application byBinder
calling the interface , it will apply for the type , and after receiving the signal in its UI thread , the interface synthesis operation will start.queueBuffer
BufferQueue
sf
Vsync
SurfaceFlinger
Vsync
Vsync
The generation of the signal refers to the refresh cycle of the screen hardware, and its architecture is shown in the following figure:
The process described in this section, from the perspective of systrace, SurfaceFlinger
the process of processing application frames is shown in the following figure:
10. Write at the end
So far, this article combines the source code and systrace to analyze the complete process from the user's finger clicking the application icon on the desktop to the first frame of the main interface of the application displayed on the screen, Activity
which involves a series App
of applications, system_server
frameworks, Art
virtual machines, etc. The mutual cooperation of the core modules of the system has many details and cannot be fully analyzed due to space limitations. Interested readers can continue to analyze in depth in combination with the AOSP source code. And optimizing the speed of app startup and opening, which is the core user experience index of the system, is also the direction that Google, chip manufacturers, mobile phone manufacturers and various application developers have worked together to optimize for many years:surfaceflinger
Android
SOC
ODM
- For
SOC
chip manufacturers : continuous upgradesCPU
andGPU
advanced hardware computing power are required; - For
Android
the system maintainer Google : During the upgrade process of the major version of the Android system, it continuously optimizes the various system processes in the application startup process, such as the speed optimization of process creation, theArt
introduction and performance optimization of virtual machines, and the simplification of the View drawing process. , The introduction of the hardware drawing acceleration mechanism, the lock optimization of the system core AMS, WMS and other core services; - For each
ODM
mobile phone manufacturer : it will develop and identify the scene where the application starts, and carry out targeted CPU frequency increase adjustment, touch response speed optimization and other mechanisms; - For each application developer : they will optimize the application startup scenario based on their own business, such as minimizing or postponing the initialization logic
Application
inActivity
life cycle functions, removing over-drawing of interface layout, asynchronous layout fileXML
parsing, etc. mechanism.
This article only analyzes the general process of application startup. As for how to optimize the speed of application startup, you can pay attention to the update of the author's subsequent articles, and this article can be used as a basic understanding of the application startup optimization topic. Finally, use a flow chart to outline the overall picture of the application startup process:
If you haven't mastered the Framework yet, and want to get a thorough understanding of it in the shortest time, you can refer to "Android Framework Core Knowledge Points" , which includes: Init, Zygote, SystemServer, Binder, Handler, AMS, PMS, Launcher... ... and other knowledge point records.
"Framework Core Knowledge Point Summary Manual" :https://qr18.cn/AQpN4J
Part of the implementation principle of the Handler mechanism:
1. Macro-theoretical analysis and Message source code analysis
2. MessageQueue source code analysis
3. Looper source code analysis
4. Handler source code analysis
5. Summary
Binder principle:
1. Knowledge points that must be understood before learning Binder
2. Binder mechanism in ServiceManager
3. System service registration process
4. ServiceManager startup process
5. System service acquisition process
6. Java Binder initialization
7. Java The registration process of system services in Binder
Zygote :
- The startup process of the Android system and the startup process of Zygote
- The startup process of the application process
AMS source code analysis:
- Activity life cycle management
- onActivityResult execution process
- Detailed Explanation of Activity Stack Management in AMS
In-depth PMS source code:
1. PMS startup process and execution process
2. APK installation and uninstallation source code analysis
3. Intent-filter matching structure in PMS
WMS:
1. The birth of WMS
2. The important members of WMS and the addition process of Window
3. The deletion process of Window
"Android Framework Study Manual":https://qr18.cn/AQpN4J
- Boot Init process
- Start the Zygote process at boot
- Start the SystemServer process at boot
- Binder driver
- AMS startup process
- The startup process of the PMS
- Launcher's startup process
- The four major components of Android
- Android system service - distribution process of Input event
- Android underlying rendering-screen refresh mechanism source code analysis
- Android source code analysis in practice