Launcher界面的启动流程

AMS做了一系列初始化操作之后,会进入AMS.systemReady()方法,Launcher的启动就是由这个方法开始的。

frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
/**
 * Ready. Set. Go!
 */
public void systemReady(final Runnable goingCallback, @NonNull TimingsTraceAndSlog t) {
    t.traceBegin("PhaseActivityManagerReady");
    mSystemServiceManager.preSystemReady();
    synchronized(this) {
        ......
        if (bootingSystemUser) {
            t.traceBegin("startHomeOnAllDisplays");
            mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");//需要启动界面,肯定要AMS启动完成。
            t.traceEnd();
        }
        ......
    }
}
 
 
mAtmInternal = LocalServices.getService(ActivityTaskManagerInternal.class);

可以看到调用了mAtmInternel.startHomeOnAllDisplays()方法来启动launcher。而mAtmInternel是一个ActivityTaskManagerInternal的对象,ActivityTaskManagerInternal是一个抽象类,里面定义了一些抽象方法。这些抽象方法实际上是在ActivityTaskManagerService.java的内部类LocalService.java中实现的。(源码里面一般类似xxxInternal的抽象类,实现类往往是xxxService里面的LocalService)

所以它实际上调用的是ActivityTaskManagerService.java的startHomeOnAllDisplays()方法

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
final class LocalService extends ActivityTaskManagerInternal {
         ......
         @Override
         public boolean startHomeOnAllDisplays(int userId, String reason) {
             synchronized (mGlobalLock) {
                 return mRootWindowContainer.startHomeOnAllDisplays(userId, reason);
             }
         }
        ......
     }

调用了RootWindowContainer.java里的startHomeOnAllDisplays()方法。

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;
     }

对每一个显示器进行遍历,在每个display上显示其对应的Home界面,调用了同文件里的startHomeOnDisplay()方法。

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean startHomeOnDisplay(int userId, String reason, int displayId) {
    return startHomeOnDisplay(userId, reason, displayId, false /* allowInstrumenting */,
            false /* fromHomeKey */);
}
 
 
boolean startHomeOnDisplay(int userId, String reason, int displayId, boolean allowInstrumenting,
        boolean fromHomeKey) {
    // Fallback to top focused display or default display if the displayId is invalid.
    if (displayId == INVALID_DISPLAY) {//判断diaplay id是否有效,如果无效,则回退到top焦点显示,或者默认显示
        final Task rootTask = getTopDisplayFocusedRootTask();
        displayId = rootTask != null ? rootTask.getDisplayId() : DEFAULT_DISPLAY;
    }
 
    final DisplayContent display = getDisplayContent(displayId);//获取display信息
    return display.reduceOnAllTaskDisplayAreas((taskDisplayArea, result) ->
                    result | startHomeOnTaskDisplayArea(userId, reason, taskDisplayArea,
                            allowInstrumenting, fromHomeKey),
            false /* initValue */);
}

后面继续调用startHomeOnTaskDisplayArea()方法

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
boolean startHomeOnTaskDisplayArea(int userId, String reason, TaskDisplayArea taskDisplayArea,
        boolean allowInstrumenting, boolean fromHomeKey) {
    // Fallback to top focused display area if the provided one is invalid.
    if (taskDisplayArea == null) {//如果taskDisplayArea为null,回退到当前顶部焦点显示
        final Task rootTask = getTopDisplayFocusedRootTask();
        taskDisplayArea = rootTask != null ? rootTask.getDisplayArea()
                : getDefaultTaskDisplayArea();
    }
 
    Intent homeIntent = null;//要启动的launcher中的home intent
    ActivityInfo aInfo = null;//要启动的launcher中的activity info
    if (taskDisplayArea == getDefaultTaskDisplayArea()) {//判断传入的taskDisplayArea是否是默认的taskDisplayArea
        homeIntent = mService.getHomeIntent();//1.调用了ActivityTaskManagerService里的getHomeIntent()方法获取默认屏幕的home intent
        aInfo = resolveHomeActivity(userId, homeIntent);//2.获取home activity的信息
    } else if (shouldPlaceSecondaryHomeOnDisplayArea(taskDisplayArea)) {// 如果需要加载第二个屏幕home intent的activity
        Pair<ActivityInfo, Intent> info = resolveSecondaryHomeActivity(userId, taskDisplayArea);
        aInfo = info.first;
        homeIntent = info.second;
    }
    if (aInfo == null || homeIntent == null) {
        return false;
    }
 
    if (!canStartHomeOnDisplayArea(aInfo, taskDisplayArea, allowInstrumenting)) {//检查是否允许在屏幕上开始显示home activity
        return false;
    }
 
    // Updates the home component of the intent.
    //设置homeintent的一些属性
    homeIntent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
    homeIntent.setFlags(homeIntent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
    // Updates the extra information of the intent.
    if (fromHomeKey) {//表示是否是由于按了home按键导致的启动home intent
        homeIntent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, true);
        if (mWindowManager.getRecentsAnimationController() != null) {
            mWindowManager.getRecentsAnimationController().cancelAnimationForHomeStart();
        }
    }
    homeIntent.putExtra(WindowManagerPolicy.EXTRA_START_REASON, reason);
 
    // Update the reason for ANR debugging to verify if the user activity is the one that
    // actually launched.
    final String myReason = reason + ":" + userId + ":" + UserHandle.getUserId(
            aInfo.applicationInfo.uid) + ":" + taskDisplayArea.getDisplayId();//获取启动home activity的reason
    mService.getActivityStartController().startHomeActivity(homeIntent, aInfo, myReason,
            taskDisplayArea);//3.启动home activity
    return true;
}

startHomeOnTaskDisplayArea()方法里主要是设置了一些home intent的属性,封装进homeIntent中,然后通过startHomeActivity()方法来启动对应的activity。首先是通过mService.getHomeIntent()方法获取需要启动的intent信息:

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
RootWindowContainer(WindowManagerService service) {
    super(service);
    ......
    mService = service.mAtmService;
    ......
}
 
 
frameworks/base/services/core/java/com/android/server/wm/WindowManagerService.java
final ActivityTaskManagerService mAtmService;

所以实际上调用的是ActivityTaskManagerService里的getHomeIntent()方法获取需要启动的intent信息,主要是添加一个category为CATEGORY_HOME的Intent,表明是Home Activity

frameworks/base/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
Intent getHomeIntent() {
    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    intent.setComponent(mTopComponent);
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        intent.addCategory(Intent.CATEGORY_HOME);
    }
    return intent;
}

getHomeIntent()函数中创建了Intent,并将mTopAction和mTopData传入。mTopAction的值为Intent.ACTION_MAIN,如果系统运行模式不是低级工厂模式则将intent的Category设置为Intent.CATEGORY_HOME。Launcher的Intent对象中添加了Intent.CATEGORY_HOME常量,这个其实是一个launcher的标志,一般系统的启动页面Activity都会在AndroidManifest.xml中配置这个标志。

然后是调用resolveHomeActivity()方法从PKMS中查询Category类型为HOME的Activity。

这里只有系统自带的Launcher应用程序注册了HOME类型的Activity

frameworks/base/services/core/java/com/android/server/wm/RootWindowContainer.java
@VisibleForTesting
ActivityInfo resolveHomeActivity(int userId, Intent homeIntent) {
    final int flags = ActivityManagerService.STOCK_PM_FLAGS;
    final ComponentName comp = homeIntent.getComponent();
    ActivityInfo aInfo = null;
    try {
        if (comp != null) {
            // Factory test.
            aInfo = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
        } else {//系统正常启动,走该流程
            final String resolvedType =
                    homeIntent.resolveTypeIfNeeded(mService.mContext.getContentResolver());
            final ResolveInfo info = AppGlobals.getPackageManager()
                    .resolveIntent(homeIntent, resolvedType, flags, userId);//查找符合home intent的activities,然后找出最符合的那个activity
            if (info != null) {
                aInfo = info.activityInfo;
            }
        }
    } catch (RemoteException e) {
        // ignore
    }
 
    if (aInfo == null) {
        Slog.wtf(TAG, "No home screen found for " + homeIntent, new Throwable());
        return null;
    }
 
    aInfo = new ActivityInfo(aInfo);
    aInfo.applicationInfo = mService.getAppInfoForUser(aInfo.applicationInfo, userId);
    return aInfo;
}

获取好了需要启动的activity信息之后,通过ActivityStartController里的startHomeActivity()方法来启动对应的activity

frameworks/base/services/core/java/com/android/server/wm/ActivityStartController.java
    void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason,
            TaskDisplayArea taskDisplayArea) {
        ......
        mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
                .setOutActivity(tmpOutRecord)
                .setCallingUid(0)
                .setActivityInfo(aInfo)
                .setActivityOptions(options.toBundle())
                .execute();
        ......
    }
 
ActivityStarter obtainStarter(Intent intent, String reason) {
        return mFactory.obtain().setIntent(intent).setReason(reason);
   }

在这个方法中主要是传入启动所需的各种参数,然后就是启动了一个异步任务去开始启动activity。可以看到obtainStarter()方法返回了一个ActivityStarter对象,所以调用了ActivityStarter的execute()方法。

frameworks/base/services/core/java/com/android/server/wm/ActivityStarter.java
int execute() {
    try {
        ......
            res = executeRequest(mRequest);
        ......
}

调用了executeRequest()方法,在这个方法中首先根据Request获取要启动activity的一些属性,检查activity权限、后台启动activity及判断是否可以启动这个activity,然后调用startActivityUnchecked()->startActivityInner()来启动home activity。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android系统在启动过程中,会依次启动各个系统服务,其中也包括Launcher服务。Launcher是Android系统的桌面显示服务,它负责管理并显示设备的主屏幕和应用程序列表。Launcher服务在Android系统的最后阶段启动,即在主界面启动之前。 当设备完成各个系统服务的启动,并且系统进入正常运行状态时,Launcher服务会被启动。系统启动时,先启动底层服务如Zygote进程、SystemServer进程等,然后再启动Android应用进程。Launcher服务作为最基本的应用程序之一,需要在其他应用程序之前加载,以确保用户可以正常使用设备的主屏幕。 Launcher服务的启动主要通过系统服务管理器来实现。系统服务管理器负责管理Android系统的各项服务,并按照事先定义好的优先级顺序启动服务。在启动Launcher服务时,系统服务管理器会调用相应的启动函数,加载Launcher相关的资源和配置文件,并开始监控用户对桌面的操作。 一旦Launcher服务启动成功,就会显示设备的主屏幕,并加载应用程序列表。通过Launcher服务,用户可以查看和管理设备上已安装的应用程序,并快捷地启动它们。同时,Launcher服务还提供了桌面小部件、壁纸等个性化设置,使用户可以自定义设备的外观和功能。 总而言之,Android系统的Launcher服务在启动过程的最后阶段启动,它管理和显示设备的主屏幕和应用程序列表,为用户提供方便的桌面操作和个性化设置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值