目录

一,背景介绍

二,源码分析


一,背景介绍

        在Android的中,桌面应用Launcher由Launcher演变到Launcher2,再到现在的Launcher3,Google也做了很多改动。

    Launcher不支持桌面小工具动画效果,Launcher2添加了动画效果和3D初步效果支持,从Android 4.4 (KK)开始Launcher默认使用Launcher3,    Launcher3加入了透明状态栏,增加overview模式,可以调整workspace上页面的前后顺序,可以动态管理屏幕数量,widget列表与app list分开显示等功能。

  我们主要研究android11的Launcher3的启动过程。

二,源码分析

  路径:/frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java

public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
       //......
      if (bootingSystemUser) {
                t.traceBegin("startHomeOnAllDisplays");
                mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");
                t.traceEnd();
            }
    //......
}

        ActivityTaskManagerInternal是 ActivityTaskManagerService的一个抽象类,正在的实现是在ActivityTaskManagerService中,

路径:/frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java

@Override
        public boolean startHomeOnAllDisplays(int userId, String reason) {
            synchronized (mGlobalLock) {
                return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
            }
        }

路径:/frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java

boolean startHomeOnAllDisplays(int userId, String reason) {
        boolean homeStarted = false;
        for (int i = getChildCount() - 1; i >= 0; i--) {
            final int displayId = getChildAt(i).mDisplayId;
            homeStarted |= startHomeOnDisplay(userId, reason, displayId);
        }
        return homeStarted;
    }

这里要重点讲解下窗口结构层级,

Android launcher3 apk替换_java

 1,RootWindowContainer:根窗口容器,树的根是它。通过它遍历寻找,可以找到窗口树上的窗口。它的孩子是DisplayContent。
2,DisplayContent:该类是对应着显示屏幕的,Android是支持多屏幕的,所以可能存在多个3,DisplayContent对象。上图只画了一个对象的结构,其他对象的结构也是和画的对象的结构是相似的。
4,TaskDisplayArea:它为DisplayContent的孩子,对应着窗口层次的第2层。第2层作为应用层,看它的定义:int APPLICATION_LAYER = 2,应用层的窗口是处于第2层。TaskDisplayArea的孩子是Task类,其实它的孩子类型也可以是TaskDisplayArea。而Task的孩子则可以是5,ActivityRecord,也可以是Task。
6,Tokens:它为DisplayContent的孩子,它的孩子是WindowToken。而WindowToken的孩子则为7,WindowState对象。WindowState是对应着一个窗口的。结构图中,DisplayContent不止包含一个Tokens,还有两个。其实ImeContainer也是继承自Tokens。
8,ImeContainer:它也为DisplayContent的孩子,它是输入法窗口的容器,它的孩子是WindowToken类型。WindowToken的孩子为WindowState类型,而WindowState类型则对应着输入法窗口。
9,Task:任务,它的孩子可以是Task,也可以是ActivityRecord类型。
10,ActivityRecord:是对应着应用进程中的Activity的。ActivityRecord是继承WindowToken的,它的孩子类型为WindowState。
11,WindowState:WindowState是对应着一个窗口的。
        结构图中,DisplayContent有5个孩子。图中从上到下,第一个是Tokens,对应着窗口图层0、1。第二个是TaskDisplayArea,对应着窗口图层2。第三个是Tokens,对应着窗口图层3到14。第四个是ImeContainer,对应着窗口图层15到16。第五个是Tokens,对应着窗口图层17到36。

        回到代码里面,startHomeOnDisplay(userId, reason, displayId) 按照物理显示屏幕情况来启动launcher桌面,也就是说android本身支持多屏幕显示。

boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
            boolean allowInstrumenting, boolean fromHomeKey) {

    if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, allowInstrumenting)) {
            return false;
        }

     mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,taskDisplayArea);
}

canStartHomeOnDisplayArea检测home activity是否支持在多屏上显示,真正执行启动home activity的为startHomeActivity

void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason, int displayId) {
    ....
    //返回一个 ActivityStarter 对象,它负责 Activity 的启动
    //一系列 setXXX() 方法传入启动所需的各种参数,最后的 execute() 是真正的启动逻辑
    //最后执行 ActivityStarter的execute方法
    mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
            .setOutActivity(tmpOutRecord)
            .setCallingUid(0)
            .setActivityInfo(aInfo)
            .setActivityOptions(options.toBundle())
            .execute();  //参考[4.3.1]
    mLastHomeActivityStartRecord = tmpOutRecord[0];
    final ActivityDisplay display =
            mService.mRootActivityContainer.getActivityDisplay(displayId);
    final ActivityStack homeStack = display != null ? display.getHomeStack() : null;
 
    if (homeStack != null && homeStack.mInResumeTopActivity) {
        //如果home activity 处于顶层的resume activity中,则Home Activity 将被初始化,但不会被恢复(以避免递归恢复),
        //并将保持这种状态,直到有东西再次触发它。我们需要进行另一次恢复。
        mSupervisor.scheduleResumeTopActivities();
    }
}

execute为真正的启动逻辑,

路径:/frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java