简单易懂(六)之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启动完成。

时序图

系列文章

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

相关推荐
安卓开发者5 小时前
Android RxJava 组合操作符实战:优雅处理多数据源
android·rxjava
阿华的代码王国5 小时前
【Android】RecyclerView复用CheckBox的异常状态
android·xml·java·前端·后端
一条上岸小咸鱼5 小时前
Kotlin 基本数据类型(三):Booleans、Characters
android·前端·kotlin
Jerry说前后端6 小时前
RecyclerView 性能优化:从原理到实践的深度优化方案
android·前端·性能优化
alexhilton6 小时前
深入浅出着色器:极坐标系与炫酷环形进度条
android·kotlin·android jetpack
一条上岸小咸鱼12 小时前
Kotlin 基本数据类型(一):Numbers
android·前端·kotlin
Huntto13 小时前
最小二乘法计算触摸事件速度
android·最小二乘法·触摸事件·速度估计
一笑的小酒馆13 小时前
Android中使用Compose实现各种样式Dialog
android
红橙Darren13 小时前
手写操作系统 - 编译链接与运行
android·ios·客户端
鹏多多.17 小时前
flutter-使用device_info_plus获取手机设备信息完整指南
android·前端·flutter·ios·数据分析·前端框架