Android application startup whole process analysis (source code depth analysis)

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

AndroidThe system is event-driven, and inputit is one of the most common events. The user's click, slide, long press and other operations are all inputevent-driven, and the core is InputReaderand InputDispatcher. InputReaderand InputDispatcherare SystemServertwo nativeloop threads running in the process, responsible for reading and dispatching Inputevents. The whole processing process is roughly as follows:

  1. InputReaderResponsible for reading the event from EventHubit Input, and then handing it over to InputDispatcherthe event distribution;
  2. InputDispatcherAfter getting InputReaderthe acquired event, after wrapping the event, find and distribute it to the target window;
  3. InboundQueueThe queue ("iq") holds the events received InputDispatcherfrom it ;InputReaderinput
  4. OutboundQueue("oq") queue contains events that will be dispatched to each target window App;
  5. WaitQueueThe records in the queue are events that have been dispatched to App("wq"), but Appare still being processed and have not been returned successfully;
  6. PendingInputEventQueueThe events that the application needs to process are recorded in the queue ("aq") Input, where you can see that inputthe events have been delivered to the application process;
  7. deliverInputEventThe flag App UI Threadis Inputawakened by the event;
  8. InputResponseIdentify Inputthe event area, where you can see that the processing stages of one Input_Downevent + several Input_Moveevents + one Input_Upevent are counted here;
  9. AppIn response to processing Inputevents, Viewprocessing 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_serverThe nativethread InputReaderis first responsible EventHubfor monitoring the mechanism linuxused epolleand reading the reported touch events from the screen driver, and then wakes up another native thread InputDispatcherto be responsible for further event distribution. InputDispatcherIt will first put the event into InboundQueuethe "iq" queue, then find the target application window that specifically handles inputthe event, and put the event into the corresponding target window, OutboundQueuewhich is the "oq" queue, waiting to SocketPairbe 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_serverAn ANR exception event will be reported to the application . The above whole process Androidhas 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 inputthe touch event is delivered to the desktop application process, the event is put into the "aq" local pending queue through the function Inputafter 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.enqueueInputEventdeliverInputEventinputWindowViewRootImpl#setViewInputStageImeInputStageViewPostImeInputStageViewDecorViewViewViewViewGroupfinishInputEventJNInativeInputConsumersendFinishedSignalInputDispatcherANR

In the desktop application interface View, one touch event and multiple touch events are processed continuously ACTION_DOWN, TouchEventuntil the last event ACTION_MOVEoccurs , 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_UPTouchEventonClickActivityManager BinderAMSstartActivity

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 bindercalls the interface AMSof 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 startActivityInnerthe startup application logic, the stack management logic AMSin 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:ActivityResumeActivityActivityPaused

/*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 pausemessage , 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:ActivityonPausebinderAMSactivityPausedactivitypause

  @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();
        }
    }

AMSAfter receiving the application activityPausedcall here, continue to execute the logic of starting the application, and judge that Activitythe process of the application to be started does not exist, so startProcessAsyncthe 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:

  1. Notify the pause desktop application:


2. activityPausedAfter 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 Androidthe startup of the application process is passive . When clicking the icon on the desktop to start an application component such as Activity, if Activitythe process does not exist, the process will be created and started. ** AndroidThe creation of general application processes in the system is uniformly created by zygotethe 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:forkAMSsocketzygotesocketzygotefork

Let's continue the analysis in the previous section, continue to AMS#startProcessAsyncstart 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#startViaZygotethe logic that finally creates the application process:

  1. openZygoteSocketIfNeededThe function opens the local socketclient to connect to the server zygoteof the processsocket ;
  2. zygoteSendArgsAndGetResultSend socketthe request parameters with the created application process parameter information ;
  3. returnThe returned data structure will have fields ProcessStartResultfor 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, zygotewhen the process is created, ZygoteInit#mainthe 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#runSelectLoophow 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, zygotethe process listens to the received AMSrequest, forkcreates a sub-application process, and then pidenters the sub-process space when it is 0, and then ZygoteInit#zygoteInitcompletes 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:

  1. The default javaexception handling mechanism of the application process (can realize Java crashthe logic of monitoring and intercepting all the application process);
  2. JNICall the thread pool of the starting process binder(note that the thread pool resource of the application process binderis created by itself and not zygoteinherited from the parent process);
  3. Create an object through reflection ActivityThreadand call its " main" entry method.

Let's continue to look at RuntimeInit#applicationInitthe 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#mainfunction initialization is:

  1. Create and start loopthe message loop of the main thread;
  2. Register yourself in by bindercalling AMSthe interface .attachApplicationattachAMS

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 ActivityThreadand its mainfunctions 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 Handlerthis time , including the life cycle functions of components such as , , , , etc., in the form of , which will be processed in the main thread in orderActivityThreadHandlerMessageApplicationActivityContentProviderServiceBroadcastMessage , which is AppThe initialization and operation principle of the main thread, part of the processing Messageis 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. MessageOnce a Messagemessage is sent, the main thread will be woken up and Messageprocessed. After the processing is completed, if there is no other Messageneed to be processed, the main thread will enter the dormant blocking state to continue wait. It can be said that Androidthe 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. MessageQueueIts Messageoperating principle is shown in the following figure:

  1. Handler: HandlerMainly used for processing Message, the application can be created in any thread Handler, as long as the corresponding is specified at the time of creation Looper, if not specified, the default is Threadcorresponding to the current Looper.
  2. Looper: Looper It can be regarded as a circulator. After its loopmethod is opened, it continuously obtains MessageQueuefromMessage , Messagesums Deliverywith Dispatch, and finally sends it to the corresponding Handlerfor processing.
  3. **MessageQueue**:MessageQueueIt is a Messagemanager. In the queue Message, when there is no Message, MessageQueuewith the help Linuxof ePollthe mechanism, it blocks and waits for sleep until there is Messagea queuing to wake it up .
  4. **Message**:MessageIt is the object to transmit the message, which contains the content to be transmitted, the most commonly used ones include what, arg, and callbackso on.

6. Application Application and Activity component creation and initialization

6.1 Application creation and initialization

ActivityThread#mainFrom 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 , loopbefore starting the main thread message loop, it will register itself in the system by calling the interface of Binderthe 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:AMSattachApplicationAMSAMSattachApplication

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 AMSof 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 applicationattachApplicationonewaybinderActivityThread#IApplicationThreadbindApplicationbindApplicationBIND_APPLICATIONhandleBindApplication . 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#**handleBindApplicationthe initialization process, the following events are mainly completed in the main thread of the application**:

  1. ApplicationInfoCreate the object APKcorresponding to the application according to the information passed in by the framework LoadedApk;
  2. Create application Applicationobjects Context;
  3. Create a class loader ClassLoaderobject and trigger Artthe virtual machine to execute OpenDexFilesFromOatan action to load the APKapplication Dexfile ;
  4. By LoadedApkloading the application APK's Resourceresources ;
  5. LoadedApkThe function called makeApplicationto create the application Applicationobject;
  6. Execute the application Application#onCreatelifecycle function ( APPthe first line of code that the application developer can control);

Let's focus on APK Dexthe loading of files and Resourcethe 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, Applicationit Contextwill try to load the resource immediately APK, Resourcebut before that, it needs to LoadedApkcreate a class loader ClassLoaderobject, and this process will eventually trigger Artthe virtual machine to load the application APKfile 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 APKfile resources by the system is actually the process of creating resource objects in the application process , in which the parsing of resource files Resourcesis 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:APKI/OAssetManagerNativeC

6.2 Activity creation and initialization

Let's go back to the 6.1 summary and see that AMSafter receiving the registration request of the application process , first call the # interface attachApplicationof 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:IApplicationThreadbindApplicationhandleBindeApplicationActivityActivity

/*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_serverprocess 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 ActivityStackSupervisorcode realStartActivityLockedflow :LaunchActivityItemResumeActivityItemActivity

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 :

  1. Created ; Activity_Context
  2. Create Activityobjects through reflection;
  3. ActivityThe action performed attach, in which the object of the application window is created PhoneWindowand setWindowManage ;
  4. Execute the life cycle function Activityof the application onCreateand setContentViewcreate a window DecorViewobject 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 :

  1. Execute application Activitylifecycle onResumefunctions ;
  2. WindowManagerThe action performed addViewstarts the view drawing logic;
  3. Activitythe created ViewRootImplobject;
  4. ViewRootImplThe executed setViewfunction 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 ViewRootImpland 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, WindowManagerthe 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:

  • WindowIt is an abstract class that provides some standard UI solutions through controlDecorView背景、标题、虚拟按键等 , for example, the only implementation class of PhoneWindowbut , which is created in the attach process after creation, and the content displayed by the application is loaded into its internal ( );WindowActivitymDecorDecorView
  • DecorViewIt 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;
  • WindowManagerIt is an interface, which inherits from ViewManagerthe interface and provides Viewbasic operation methods; WindowManagerImpimplements WindowManagerthe interface, and 组合holds it internally WindowManagerGlobalfor operation View; WindowManagerGlobalit is a global singleton, which can be ViewRootImpladded Viewto it 窗口internally ;
  • ViewRootImplIt is all View, Parentused for overall management Viewdrawing and WMSIPC interaction with the system window management service to achieve development 窗口; it ViewRootImplis the engine of the application process running, you can see that ViewRootImplit contains mView(that is DecorView), mSurface, Choregrapher, mViewrepresenting the entire control tree, mSurfaccerepresenting the canvas, The UI rendering of the application will be directly placed mSurfacein the middle, Choregorapherso that the application requests vsyncthe signal and starts the rendering process after receiving the signal;
    we ViewRootImplcontinue 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, ViewRootImplthe key internal process of setView is as follows:

  1. requestLayout() triggers interface drawing (measure, layout, draw) actions through a series of calls , which will be analyzed in detail below;
  2. 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 can Viewdisplay it on the screen. . The internal WMSimplementation process is also very complicated. Due to the limited space, this article will not analyze it in detail.
  3. Create a WindowInputEventReceiver object to encapsulate the logic for the application window to receive system touch events;
  4. Execute view.assignParent(this), and set DecorViewmParent to ViewRootImpl. So, while ViewRootImplnot one View, it's Viewthe top layer of all Parent.

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);
         ...
     }
}

ChoreographerThe introduction is mainly to cooperate with Vsyncthe 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 SurfaceFlingersynthesized images, and avoids tearing of the tearing screen), and provides a stable rendering for the upper-layer App. MessageThe timing of processing, that is, Vsyncthe arrival of , the system Vsynccontrols the timing of each frame drawing operation by adjusting the signal cycle. ChoreographerPlay the role of linking up and down in the Android rendering chain :

  1. Inheritance : Responsible for receiving and processing various update messages and callbacks of the App, and Vsyncprocessing them uniformly when the App arrives. For example, centralized processing of Input (mainly the processing of Input events), Animation (related to animation), Traversal (including measure、layout、drawoperations such as ), judging frame drops and recording CallBack time-consuming, etc.;
  2. Qixia : Responsible for requesting and receiving Vsync signals. Receive Vsync event callback (via FrameDisplayEventReceiver. onVsync), request Vsync( FrameDisplayEventReceiver. scheduleVsync).

ChoreographerAfter receiving CALLBACK_TRAVERSALa 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 ViewRootImplwill 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:ChoreographerpostCallbackChoreographerAPPvsyncvsyncViewRootImpldoTraversal

The simplified code flow of our next ViewRootImplfunction 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, ViewRootImplthe main flow of drawing the entire application interface in charge of is as follows :

  1. Starting from the root node of the interface View control tree DecorView, recursively traverse the entire View control tree, and complete the measurement operation Viewof the entire control tree measure. Due to space limitations, this article will not analyze the detailed process of this piece;
  2. When the interface executes the drawing task for the first time, it will Binder IPCaccess 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 creating SurfaceFlingerthe application interface object , and pass the address reference back to the application process through WMS BufferQueueLayerthrough memory sharingBinder ), due to space limitations, this article will not analyze the detailed process of this piece;
  3. Starting from the root node of the interface View control tree DecorView, recursively traverse the entire View control tree to complete the measurement operation Viewof the entire control tree layout;
  4. Start from the root node of the interface View control tree DecorView, recursively traverse the entire control tree, and complete the measurement operation Viewon the entire Viewcontrol 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 ;drawGPUCPU

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, ViewRootImplafter 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 Androidof the UI thread mentioned above. In addition, the interface also needs to be RenderThreadrendered by threads. After the rendering is completed, it needs to be handed Binderover to the process by calling "upframe" surfaceflingerfor synthesis and then sent to display before it can be finally displayed on the screen. ViewRootImplIn this section, we will follow the last draw process in the previous section and continue to analyze RenderThreadthe 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 :

  1. Starting from DecorViewthe root node, recursively traverse Viewthe control tree, record the drawing operation command Viewof each node , and complete the construction of the drawing operation command tree;drawOp
  2. JNICall Javathe drawing command tree built by the synchronization layer to the rendering thread Nativeof the layer , and wake up the rendering thread to perform rendering tasks;RenderThreadOpenGL

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 Viewthe root node of the control tree DecorView, recursively calls the function Viewof each child node updateDisplayListIfDirty, and finally completes the creation of the drawing tree. The brief process is as follows :

  1. Get a "canvas" Viewcreated when the object is constructed ;RenderNodeSkiaRecordingCanvas
  2. 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 holdingViewonDrawdrawLinedrawRectDisplayListOpSkiaDisplayListDisplayListData ;
  3. Fill in the object settings containing DisplayListOpthe drawing command buffer ;SkiaDisplayListRenderNode
  4. Finally, set the root Viewcache to , and complete the build.DisplayListOpRootRenderNode

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 UIfrom the root node in the thread DecorView, recursively traverses each child Viewnode, collects its drawXXXdrawing actions and converts them into DisplayListOpcommands, records them DisplayListDataand fills them in RenderNode, and finally completes Viewthe 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 RenderThreadthe rendering thread and trigger it to execute OpenGLthe 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 UIthe thread utilizes to send a task request RenderProxyto the thread, wakes up, and starts rendering. The general process is as follows :RenderThreadDrawFrameTaskRenderThread

  1. syncFrameStateTraversing Vieweach one on the tree RenderNode, executing prepareTreeImplthe function, and realizing the operation of synchronously drawing the command tree;
  2. Call OpenGLthe library APIto use GPU, 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);
  3. Frame the previously drawn and rendered graphics buffer Binderfor SurfaceFlingersynthesis 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

SurfaceFlingerThe synthetic display part belongs to the graphic display content in the Androidsystem completely , and the logical structure is relatively complicated, but it does not belong to the focus of this article. GUITherefore, 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, SurfaceFlingeras a process that runs independently in the system Native, ** borrows Androidthe 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 Bufferas 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:SurfaceBufferSurfaceBufferBufferBufferQueueBufferQueue

9.1 BufferQueue mechanism

Borrow a classic picture to describe BufferQueuethe working principle:

BufferQueueis a typical producer-consumer data structure . In Androidthe rendering process of the application, the application plays the role of "producer" and SurfaceFlingerthe role of "consumer". The working process is as follows :

  1. 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 Bindercalling the interface . If it is not available at this time, it will block and wait;dequeueBufferSurfaceFlingerBufferQueuefreeBufferBuffer
  2. After getting this available in the application process Buffer, choose to use CPUsoftware rendering or GPUhardware accelerated rendering. After the rendering is completed, the cached data will be returned to the corresponding application process by Bindercalling 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;queueBufferBufferQueueGPUGPUBufferGPUFencesfVsyncSurfaceFlinger
  3. SurfaceFlingerAfter receiving Vsyncthe signal, start to prepare for synthesis, use to acquireBufferobtain the corresponding BufferQueuein the application Bufferand perform the synthesis operation;
  4. After the composition is completed, it will be set to the available state SurfaceFlingerby calling and return to the corresponding in the application .releaseBufferBufferfreeBufferQueue

9.2 Vsync synchronization mechanism

VysncVertical synchronization is Androidan important mechanism introduced in the "butter plan", which is essentially for the purpose of coordinating the BufferQueueUI data generation action of the application producer and SurfaceFlingerthe synthetic consumption action of the consumer, so as to avoid Tearingthe phenomenon of screen tearing. VysncSignals are of two types:

  1. appType Vsync: appThe type of signal is registered and received Vysncby 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 the Choreographersystem to register Vsyncthe signal of the app type. After Vsyncthe signal arrives, it can put the task to be drawn in the message queue of the main thread. Perform real UI drawing actions;
  2. sfType Vsync: sfType Vsyncis used to control SurfaceFlingerthe 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 by Bindercalling the interface , it will apply for the type , and after receiving the signal in its UI thread , the interface synthesis operation will start.queueBufferBufferQueuesfVsyncSurfaceFlingerVsync

VsyncThe 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, SurfaceFlingerthe 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, Activitywhich involves a series Appof applications, system_serverframeworks, Artvirtual 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:surfaceflingerAndroidSOCODM

  • For SOCchip manufacturers : continuous upgrades CPUand GPUadvanced hardware computing power are required;
  • For Androidthe 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, the Artintroduction 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 ODMmobile 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 Applicationin Activitylife cycle functions, removing over-drawing of interface layout, asynchronous layout file XMLparsing, 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 :

  1. The startup process of the Android system and the startup process of Zygote
  2. The startup process of the application process

AMS source code analysis:

  1. Activity life cycle management
  2. onActivityResult execution process
  3. 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

  1. Boot Init process
  2. Start the Zygote process at boot
  3. Start the SystemServer process at boot
  4. Binder driver
  5. AMS startup process
  6. The startup process of the PMS
  7. Launcher's startup process
  8. The four major components of Android
  9. Android system service - distribution process of Input event
  10. Android underlying rendering-screen refresh mechanism source code analysis
  11. Android source code analysis in practice

Guess you like

Origin blog.csdn.net/weixin_61845324/article/details/131818078