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

时序图

系列文章

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

相关推荐
三少爷的鞋2 小时前
Java 线程自上而下,Kotlin 协程自下而上
android
好的佩奇3 小时前
Dart 之增强枚举
android·flutter·dart
梦影_4 小时前
MySQL进阶教程(五)—— SQL调优(下)
android·大数据·数据库·后端·sql·mysql·database
好的佩奇6 小时前
蓝牙之无线电与通信距离
android·flutter·蓝牙
vilya7 小时前
我把一套完整的 Python Agent 运行时塞进手机 APK:依赖闭包、Rust 轮子和三个真机坑
android
呆呆敲代码的小Y9 小时前
【实战精选面试题】C# 面试题详细解答,按难易程度排序
android·java·游戏·c#·游戏开发·unity面试题·c#面试题
思想觉悟10 小时前
SEAndroid实战
android·linux·c++
思想觉悟11 小时前
Aosp开发磨刀石之ADB速查
android·c++
应用市场13 小时前
用本机跑的开源音乐模型,给安卓小游戏做 20 秒无缝循环背景音乐
android·python·游戏开发·soundpool·音频处理
企业数字化笔记13 小时前
表单发布前怎么验收?版本引用、字段兼容和历史数据回归
android·数据挖掘·回归