安卓应用启动流程

227 阅读6分钟

对于安卓开发者来说,理清安卓应用的启动流程实在很有帮助,可以在这个流程中把一些重要的概念都串起来,包括AMS, WMS,IMS, SurfaceFlinger, AIDL通信机制,Lopper机制等,也可以帮助我们解决各种应用启动问题,还可以帮助我们更好地理解启各种动优化技术,知道哪种启动优化技术是作用于哪个阶段的。 这篇文章会结合安卓源码介绍用户在Launcher上点击启动图标到应用的第一帧被渲染出来的流程。

1 一图总览全流程

start.png

2 结合源码介绍具体流程

2.1 根据需要创建进程

在主页点击应用的图标之后,主页会调用startActivity函数,这个函数其实会最终调用到ATMS的启动activity方法

launcehr会调用这个方法启动应用, 这个方法经过层层调用最终会调用ATMS的方法startActivityAsUser
public void startActivity(Intent intent) {
    this.startActivity(intent, null);
}

ATMS是服务中专门负责Activity启动和管理的服务,原理这块工作是交由AMS负责,现在专门独立出一个ATMS来负责这块,startActivityAsUser方法最终会调用到ActivityTaskSupervisor.startSpecificActivity方法,在这个方法中会判断目标引用进程是否存在,如果不存在就通过socket发送消息给zygote进程去创建一个新的引用进程。

void startSpecificActivity(ActivityRecord r, boolean andResume, boolean checkConfig) {
    final WindowProcessController wpc =
            mService.getProcessController(r.processName, r.info.applicationInfo.uid);

    boolean knownToBeDead = false;
    // 应用进程存在,直接启动activity
    if (wpc != null && wpc.hasThread()) {
        try {
            realStartActivityLocked(r, wpc, andResume, checkConfig);
            return;
        }
    }
    
    // 应用进程不存在, 创建新的进程, 这里调用了ATMS的startProcessAsync方法,
    // 但最终会发闪送消息给zygote进程,由zygote进程去创建进程
    mService.startProcessAsync(r, knownToBeDead, isTop,
            isTop ? HostingRecord.HOSTING_TYPE_TOP_ACTIVITY
                    : HostingRecord.HOSTING_TYPE_ACTIVITY);
}

新的应用进程创建之后,会自动继承zygote进程的一些资源,包括ART虚拟机和一些公共的库。然后新进程会执行预定义的程序入口点即ActivityThread.main()方法

2.2 进程启动后,准备环境,启动application

应用进程创建之后,应用进程会告诉AMS新进程已经好了,AMS因为还负责进程管理的职责,所以需要更新一下新进程的信息,像优先级。然后应用进程启动Looper,开启消息循环处理机制,等待AMS下一步启动Applicaiton和Activity的消息并处理。 接下来结合源码看看这个流程 在ActivityThread.main中,一方面会准备looper机制,以便处理应用内主线程的消息。不熟悉looper机制的可以参考之前的文章。另一方里面调用MAS.attachApplication方法告诉AMS当前应用进程已经准备好了。

public static void main(String[] args) {
...
    // 初始化looper机制, 先调用prepareMainLooper方法,再调用下面的loop方法
    Looper.prepareMainLooper();

    // 这里attach到AMS
    ActivityThread thread = new ActivityThread();
    thread.attach(false, startSeq);

    Looper.loop();
}


private void attach(boolean system, long startSeq) {
        ...
        final IActivityManager mgr = ActivityManager.getService();
        try {
        // 调用AMS.attachApplication方法
            mgr.attachApplication(mAppThread, startSeq);
        }
 }
  1. attch到AMS,因为AMS负责管理应用进程,所以首先更新下这个进程的一些信息,像进程优先级。 然后通过binder调用ApplicationThread.bindApplication方法继续之后启动流程
public final void attachApplication(IApplicationThread thread, long startSeq) {
    synchronized (this) {
        attachApplicationLocked(thread, callingPid, callingUid, startSeq);
    }
}

private void attachApplicationLocked(@NonNull IApplicationThread thread,
        int pid, int callingUid, long startSeq) {
        // 更新进程的一些信息
        ...

// 调用ApplicationThread.bindApplication方法通知应用进程继续下一步的动作
thread.bindApplication(processName, appInfo,
        app.sdkSandboxClientAppVolumeUuid, app.sdkSandboxClientAppPackage,
        providerList, null, profilerInfo, null, null, null, testMode,
        mBinderTransactionTrackingEnabled, enableTrackAllocation,
        isRestrictedBackupMode || !normalMode, app.isPersistent(),
        new Configuration(app.getWindowProcessController().getConfiguration()),
        app.getCompat(), getCommonServicesLocked(app.isolated),
        mCoreSettingsObserver.getCoreSettingsLocked(),
        buildSerial, autofillOptions, contentCaptureOptions,
        app.getDisabledCompatChanges(), serializedSystemFontMap,
        app.getStartElapsedTime(), app.getStartUptime());
        
       
       // 这个方法里面会继续启动需要的activity, service和接受广播
finishAttachApplicationInner(startSeq, callingUid, pid);
}


private void finishAttachApplicationInner(long startSeq, int uid, int pid) {
  
    // 启动activity
    didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
   
     
    // 启动service
   didSomething |= mServices.attachApplicationLocked(app, processName);
   
   // 接受一些广播并处理
   for (BroadcastQueue queue : mBroadcastQueues) {
       didSomething |= queue.onApplicationAttachedLocked(app);
   }
}


  1. ApplicationThread.bindApplication方法中,应用进程会通过Looper机制发送一个BIND_APPLICATION消息,然后由Handler的继承类H来处理, H会加载应用包,然后执行Application.onCreate()
// ActivityThread.java
public final void bindApplication(...) {

AppBindData data = new AppBindData();
...
// 发送BIND_APPLICATION消息
sendMessage(H.BIND_APPLICATION, data);


public void handleMessage(Message msg) {
    switch (msg.what) {
        case BIND_APPLICATION:
            AppBindData data = (AppBindData)msg.obj;
            handleBindApplication(data);
            break;
    }
}


private void handleBindApplication(AppBindData data) {
// 构造LoadedApk对象,这里负责加载apk, 包括dex文件和资源文件
data.info = getPackageInfo(data.appInfo, mCompatibilityInfo, null /* baseLoader */,
        false /* securityViolation */, true /* includeCode */,
        false /* registerPackage */, isSdkSandbox);


try {
// 执行Application.onCreate函数
    mInstrumentation.onCreate(data.instrumentationArgs);
}


2.2 启动Activity

上面讲过应用进程启动之后会通知AMS,然后AMS再通过binder让应用进程启动Application后会通过ATMS.attachApplication方法启动Activity。当然后面还会启动service和接受广播,这部分不展开介绍。

在启动Activity的过程中

boolean realStartActivityLocked(ActivityRecord r, WindowProcessController proc,
        boolean andResume, boolean checkConfig) throws RemoteException {
        // 这里最终会执行到ApplicationThread.handleLaunchActivity方法
        clientTransaction.addCallback(LaunchActivityItem.obtain(...));
        final ActivityLifecycleItem lifecycleItem =       ResumeActivityItem.obtain(isTransitionForward, r.shouldSendCompatFakeFocus());
        // 这里最终会执行到Application.handleResumeActivity方法
        clientTransaction.setLifecycleStateRequest(lifecycleItem);
        
        mService.getLifecycleManager().scheduleTransaction(clientTransaction);

handleLaunchActivity方法中会创建Activity,然后执行onCreate生命周期方法,在onCreate中,开发者会调用setContentView方法,这个方法中会创建DecorView

public Activity handleLaunchActivity(ActivityClientRecord r,
        PendingTransactionActions pendingActions, int deviceId, Intent customIntent) {
        final Activity a = performLaunchActivity(r, customIntent);
        
}

private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
    //  创建Activity
    Activity activity = null;
    java.lang.ClassLoader cl = appContext.getClassLoader();
    activity = mInstrumentation.newActivity(
                    cl, component.getClassName(), r.intent);
    //这里会创建PhoneWindow对象
    activity.attach(...);

    // 这里会调用Activity.onCreate函数
    mInstrumentation.callActivityOnCreate(activity, r.state);
}

handleResumeActivity方法中会执行Activity.onResume方法,然后创建DecorView并通过调用addView方法通知surface创建surface用于后期的界面绘制和渲染。

public void handleResumeActivity(ActivityClientRecord r, boolean finalStateRequest,
        boolean isForward, boolean shouldSendCompatFakeFocus, String reason) {
        
        // 这里会执行Activity.onResume方法
if (!performResumeActivity(r, finalStateRequest, reason)) {
    return;
}
// 这里创建DecorView并通过调用addView方法通知surface创建surface用于后期的界面绘制和渲染, addView中会
View decor = r.window.getDecorView();
// 这个方法中会创建ViewRootImpl对象, 并调用setview
wm.addView(decor, l);

setView方法中完成了这些工作之后会向SurfacceFlinger请求vsync信号,然后再vsync信号到来的时候进行第一帧的渲染。

public void addView(View view, ViewGroup.LayoutParams params,
        Display display, Window parentWindow, int userId) {
                    if (windowlessSession == null) {
                root = new ViewRootImpl(view.getContext(), display);
            } else {
                root = new ViewRootImpl(view.getContext(), display,
                        windowlessSession, new WindowlessWindowLayout());
            }
            // 这个方法最终会调用Choreographer.postCallback去请求vsync信号
            root.setView(view, wparams, panelParentView, userId);
}

接受到vsync信号之后就会开始第一帧的渲染工作

2.3 第一帧的渲染

安卓应用通过Choreographer类去请求和接受Vsync信号,接受到vsync信号之后会完成第一帧的绘制。 Choreographer类在FrameDisplayEventReceiver.onVsync(...)方法中接受vsync信号,然后构造一个消息丢到主线程的消息队列中等待处理。

public void onVsync(long timestampNanos, long physicalDisplayId, int frame,
      VsyncEventData vsyncEventData) {
      // 构造一个异步消息,这个消息的callback绑定的就是FrameDisplayEventReceiver对象,这个类继承自runable
      Message msg = Message.obtain(mHandler, this);
      msg.setAsynchronous(true);
      // 放进消息队列,处理消息的之后时候会执行FrameDisplayEventReceiver.run方法
      mHandler.sendMessageAtTime(msg, timestampNanos / TimeUtils.NANOS_PER_MS);
 }

FrameDisplayEventReceiver.run方法里面最终会调用ViewRootImlp.doTraversal方法完成绘制

        public void run() {
            mHavePendingVsync = false;
            doFrame(mTimestampNanos, mFrame, mLastVsyncEventData);
        }

ViewRootImlp.doTraversal方法里面会经过measure, layout,draw完成一帧的绘制

    void doTraversal() {
        if (mTraversalScheduled) {
            mTraversalScheduled = false;
            mHandler.getLooper().getQueue().removeSyncBarrier(mTraversalBarrier);

            if (mProfile) {
                Debug.startMethodTracing("ViewAncestor");
            }
            // 
            performTraversals();

            if (mProfile) {
                Debug.stopMethodTracing();
                mProfile = false;
            }
        }
    }

参考

安卓14源码