简单易懂(六)之Launcher启动过程

前言

根据前几篇文章,我们学习了Android系统启动流程相关的init进程、Zygote进程、SystemServer进程,这篇文章我们将来学习Launcher启动过程。

我们的android系统启动后,最终会显示在桌面界面,这个桌面就是我们今天要讲的Launcher,它也是一个应用程序。Launcher启动后,它会去找PKMS拿系统里已经安装过的应用程序信息,然后把这些应用程序的快捷图标一个个显示在系统屏幕上,这样我们就可以通过点击这些快捷图标来启动对应的应用。

Launcher启动过程介绍

在上一篇文章中提到过,在SystemServer里的run()方法中,会去调用startOtherServices()方法,去启动一些系统服务,在startOtherServices()方法里,我们可以看到调用到了AMS的systemReady()方法,记住这个方法,启动Launcher的入口,就是从这个方法开始的:

java 复制代码
//代码文件位置:frmework/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() { 

    *****省略部分代码*****
    
    //记住这个systemReady()
    mActivityManagerService.systemReady(() -> { 
    Slog.i(TAG, "Making services ready"); 
    traceBeginAndSlog("StartActivityManagerReadyPhase"); 
    mSystemServiceManager.startBootPhase( SystemService.PHASE_ACTIVITY_MANAGER_READY);
    
    *****省略部分代码*****
}

下面来查看下AMS的systemReady()方法做了什么:

java 复制代码
//代码文件位置:frmework/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void systemReady(final Runnable goingCallback, BootTimingsTraceLog traceLog) {

    *****省略部分代码*****
    
    mStackSupervisor.resumeFocusedStackTopActivityLocked();
    
    *****省略部分代码*****
}

systemReady方法里,调用了ActivityStackSupervisor的resumeFocusedStackTopActivityLocked方法:

java 复制代码
//代码文件位置:frmework/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeFocusedStackTopActivityLocked( ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {

    if (targetStack != null && isFocusedStack(targetStack)) { 
            return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions); 
        }
    
    *****省略部分代码*****
}

接着调用了ActivityStack的resumeTopActivityUncheckedLocked方法,ActivityStack对象是用来描述Activity堆栈的,resumeTopActivityUncheckedLocked方法源码如下:

java 复制代码
//代码文件位置:frmework/base/services/core/java/com/android/server/am/ActivityStack.java
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {

    result = resumeTopActivityInnerLocked(prev, options);
    
    *****省略部分代码*****
}

接着看resumeTopActivityInnerLocked():

java 复制代码
//代码文件位置:frmework/base/services/core/java/com/android/server/am/ActivityStack.java
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {

    *****省略部分代码*****
    
    return isOnHomeDisplay() && mStackSupervisor.resumeHomeStackTask(prev, "prevFinished");
    
    *****省略部分代码*****
}

resumeTopActivityInnerLocked()里的代码非常多,我们只分析最关键的一部分,调用了mStackSupervisor的resumeHomeStackTask方法,mStackSupervisor是一个ActivityStackSupervisor对象:

java 复制代码
//代码文件位置:frmework/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
boolean resumeHomeStackTask(ActivityRecord prev, String reason) {

    *****省略部分代码*****
    
    return mService.startHomeActivityLocked(mCurrentUser, myReason);
}

这里的mService指的是AMS,可以看到在这里调用了AMS的startHomeActivityLocked方法:

java 复制代码
//代码文件位置:frmework/base/services/core/java/com/android/server/am/ActivityManagerService.java
boolean startHomeActivityLocked(int userId, String reason) {

    *****省略部分代码*****
    
    //在这里创建 Launcher启动所需的Intent
    Intent intent = getHomeIntent();
    
    *****省略部分代码*****
    
    //如果Launcher还没被创建的话
    if (app == null || app.instr == null) {
    
        //在这里 启动Launcher
        mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
    }
    
}

首先会去调用getHomeIntent()方法,去创建Launcher启动所需的Intent,其中包括action设置为Intent.ACTION_MAIN,以及intent的Category设置为Intent.CATEGORY_HOME。

这里为什么要设置Intent.ACTION_MAIN和Intent.CATEGORY_HOME,其实我们可以去看Launcher的源码里,在它的AndroidManifest文件中,intent-filter标签就匹配了Action为Intent.ACTION_MAIN,Category为Intent.CATEGORY_HOME,这样我们这个Launcher应用就可正常被找到并启动啦

创建完Launcher所需的Intent后,就判断如果Launcher没有启动的话,就会去调用mActivityStarter.startHomeActivityLocked()去启动Launcher:

java 复制代码
//代码文件位置:frmework/base/services/core/java/com/android/server/am/ActivityStarter.java
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
    //讲Launcher放入HomeStack中
    mSupervisor.moveHomeStackTaskToTop(reason);
    mLastHomeActivityStartResult = startActivityLocked(null /*caller*/, intent, null 
    /*ephemeralIntent*/, null /*resolvedType*/, aInfo, null /*rInfo*/, null /*voiceSession*/, 
    null /*voiceInteractor*/, null /*resultTo*/, null /*resultWho*/, 0 /*requestCode*/, 0 
    /*callingPid*/, 0 /*callingUid*/, null /*callingPackage*/, 0 /*realCallingPid*/, 0 
    /*realCallingUid*/, 0 /*startFlags*/, null /*options*/, false /*ignoreTargetSecurity*/, 
    false /*componentSpecified*/, mLastHomeActivityStartRecord /*outActivity*/, null 
    /*container*/, null /*inTask*/, "startHomeActivity: " + reason);
    }

在startHomeActivityLocked()里,先把Launcher放入HomeStack中,HomeStack是在ActivityStackSupervisor中定义的,用来存储Launcher的变量,接着调用startActivityLocked()方法来启动Launcher。

调用startActivityLocked()方法后面的源码,就涉及到Activity的启动流程了,我们后面会讲。

到此,最终就进入到Launcher的onCreate方法,Launcher启动完成。

时序图

系列文章

简单易懂系列文章
有所收获的朋友,请多多关注、点赞,谢谢大家!

相关推荐
雨白1 小时前
深入理解协程的运作机制 —— 调度、挂起与性能
android·kotlin
沐怡旸1 小时前
【Android】Android系统体系结构
android
namehu1 小时前
React Native 应用性能分析与优化不完全指南
android·react native·ios
xqlily2 小时前
Kotlin:现代编程语言的革新者
android·开发语言·kotlin
HelloBan2 小时前
如何正确去掉SeekBar的Thumb和按压效果
android
木易 士心2 小时前
Android EventBus 源码解析:设计模式、原理与实现
android
ClassOps2 小时前
源码阅读 LeakCanary
android
用户2018792831672 小时前
为啥现在 Android App 不用手动搞 MultiDex 了?
android
fouryears_234173 小时前
如何将Vue 项目转换为 Android App(使用Capacitor)
android·前端·vue.js
消失的旧时光-19433 小时前
人脸跟随 ( Channel 实现(缓存5条数据 + 2度过滤 + 平滑移动))
android·java·开发语言·kotlin