添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

Launcher的启动过程

Launcher即桌面,是Android智能设备的窗口,用户使用最频繁的软件之一。Launhcer是Android所有应用的入口,也提供窗口小部件等功能。如下图:

当然,Launcher本身就是一个APP,一个提供桌面的APP,我们也可以开发一款Launcher APP作为手机的桌面。Laucher有很多和普通APP不同的地方。

  • Launcher是顶部APP,即任何应用返回后都是到Launcher,不能再继续返回;
  • Launcher是所有应用的入口,可以管理应用;
  • Launcher是Android系统启动后就要显示给用户的应用。

我们的手机一开机第一眼看见的就是Launcher,也就是说Launcher在开机的过程中就已经启动完成,下文,我们就来看看

  1. Launcher的在开机时的启动过程;
  2. 每次按Home键的启动过程(上图中底部中间圆圈的按钮);
  3. 以及Launcher发生强退等应用退出等意外情况的启动过程。

开机Launcher的启动

手机开机时,会启动ActivityManagerService,在这个系统服务启动完成后,便会启动Launcher。关于ActivityManagerService启动过程的详细过程,读者可以参阅文章《 Android系统之System Server大纲 》。

启动时序图

ActivityManagerService启动完成后,会调用systemReady()方法,如下:

public void systemReady(final Runnable goingCallback) {
    synchronized(this) {
        .....
        startHomeActivityLocked(currentUserId, "systemReady");
    ......

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。

如上面的代码,ActivityManagerService启动完成后调用systemReady()方法,然后调用startHomeActivityLocked()方法,启动HomeActivity,即Launcher应用的桌面Activity。继续看这个方法

boolean startHomeActivityLocked(int userId, String reason) {
    Intent intent = getHomeIntent();
    ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
    if (aInfo != null) {
        intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
        // Don't do this if the home app is currently being
        // instrumented.
        aInfo = new ActivityInfo(aInfo);
        aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
        ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                aInfo.applicationInfo.uid, true);
        if (app == null || app.instrumentationClass == null) {
            intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
            mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
    return true;

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。

上面的代码首先是调用了getHomeIntent()方法取得HomeActivity的Intent,看这个方法的实现

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;

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。

上面的代码,new一个Intent对象,mTopAction的值是Intent.ACTION_MAIN,我们重点关注intent.addCategory(Intent.CATEGORY_HOME)这条语句,给HomeActvity 的 intent 对象添加Category Intent.CATEGORY_HOME=android.intent.category.HOME,也就是说Launcher的Activity必须声明Category android.intent.category.HOME,即表明这个Actiivty是一个Home Activity。

取得Intent返回startHomeActivityLocked()方法,通过方法resolveActivityInfo()遍历手机中所有安装包含Category Intent.CATEGORY_HOME=android.intent.category.HOME的Activity,然后把Activity的信息作为Component通过intent.setComponent()方法传输给intent对象。如果是Android原生的手机,此时aInfo.applicationInfo.packageName的值是:com.android.launcher3,aInfo.name的值是:com.android.launcher3.Launcher,即com.android.launcher3.Launcher(Android 7.0)是Home Activity。

然后调用mActivityStarter.startHomeActivityLocked()继续启动Home Activity。

void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
    mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
    startActivityLocked(null /*caller*/, intent, ......);
    if (mSupervisor.inResumeTopActivity) {
        mSupervisor.scheduleResumeTopActivities();

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java中。

首先通过mSupervisor.moveHomeStackTaskToTop()方法把Launcher的堆栈移到顶部,这也是为什么Launcher总是在所有APP的顶部的原因。然后接着调用startActivityLocked()继续启动Home Activity。startActivityLocked()是Android系统启动所有Activity的入口,本文就不再阐述Activity的启动过程了。

按Home键的Launcher启动过程

既然是按Home键,那么就涉及到输入系统,Home是一个按键,当被按下时,底层会上报事件到InputManagerService,如下

// Native callback.
private long interceptKeyBeforeDispatching(InputWindowHandle focus,
        KeyEvent event, int policyFlags) {
    return mWindowManagerCallbacks.interceptKeyBeforeDispatching(focus, event, policyFlags);

这个方法定义在文件frameworks/base/services/core/java/com/android/server/input/InputManagerService.java中。

参数event封装了这次按键事件,接着调用了WindowManagerCallbacks即InputMonitor的interceptKeyBeforeDispatching方法

public long interceptKeyBeforeDispatching(
        InputWindowHandle focus, KeyEvent event, int policyFlags) {
    WindowState windowState = focus != null ? (WindowState) focus.windowState : null;
    return mService.mPolicy.interceptKeyBeforeDispatching(windowState, event, policyFlags);

这个方法定义在文件frameworks/base/services/core/java/com/android/server/wm/InputMonitor.java中。

没有做任何处理,直接调用了mService.mPolicy.interceptKeyBeforeDispatching(),mPolicy实质是PhoneWindowManager对象

public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
    ......
    if (keyCode == KeyEvent.KEYCODE_HOME) {
        ......
        handleShortPressOnHome();
        return -1;

这个方法定义在文件frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java中。

如上面的代码,keyCode是KeyEvent.KEYCODE_HOME时,调用处理短按home键handleShortPressOnHome()的方法

private void handleShortPressOnHome() {
    ......
    // Go home!
    launchHomeFromHotKey();

这个方法定义在文件frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java中。

继续往下执行launchHomeFromHotKey()

void launchHomeFromHotKey(final boolean awakenFromDreams, final boolean respectKeyguard) {
    ......
    sendCloseSystemWindows(SYSTEM_DIALOG_REASON_HOME_KEY);
    startDockOrHome(true /*fromHomeKey*/, awakenFromDreams);

这个方法定义在文件frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java中。

首先调用sendCloseSystemWindows()关闭系统弹窗,调用startDockOrHome()启动Dock或者Home,本文要论述的是如何启动Home。

void startDockOrHome(boolean fromHomeKey, boolean awakenFromDreams) {
    ......
    if (fromHomeKey) {
        intent = new Intent(mHomeIntent);
        intent.putExtra(WindowManagerPolicy.EXTRA_FROM_HOME_KEY, fromHomeKey);
    } else {
        intent = mHomeIntent;
    startActivityAsUser(intent, UserHandle.CURRENT);

这个方法定义在文件frameworks/base/services/core/java/com/android/server/policy/PhoneWindowManager.java中。

创建Home Activity的Intent,mHomeIntent详情如下

mHomeIntent =  new Intent(Intent.ACTION_MAIN, null);
mHomeIntent.addCategory(Intent.CATEGORY_HOME);
mHomeIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);

如上文中提到,Home Activity的必须是一个携带Category为Intent.CATEGORY_HOME的Activity。在启动Activity之前,往Intent中设置WindowManagerPolicy.EXTRA_FROM_HOME_KEY/fromHomeKey的键值对,表明从Home按键启动Launcher。然后调用startActivityAsUser()方法,把Home Activity启动起来。

意外情况启动Launcher

所谓意外情况,比如Launcher强退等异常。Launcher也是一个普通的应用,当发生异常导致强退时,也就是说Launcher死掉了,那么由Launcher显示的桌面也没有了。但是,如果桌面都没有了,用户还怎么使用Launcher呢?所以,当Launcher发生异常等导致强退时,系统需要自动重新把Launcher启动起来。

以强退为例,我们知道Android的Activity由ActivityManagerService管理和维护者,当一个应用发生强退,会调用到ActivityManagerService的forceStopPackage()方法。

当应用强退时,调用ActivityManagerService的forceStopPackage()方法

public void forceStopPackage(final String packageName, int userId) {
    if (isUserRunningLocked(user, false)) {
        forceStopPackageLocked(packageName, pkgUid, "from pid " + callingPid);

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java中。

如上面的代码,继续调用forceStopPackageLocked()方法,最终会调用scheduleIdleLocked()方法处理强退。

final ActivityRecord activityIdleInternalLocked(final IBinder token, boolean fromTimeout,
            Configuration config) {
    ......
    if (activityRemoved) {
        resumeTopActivitiesLocked();
    return r;

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java中。

如上面的方法,从scheduleIdleLocked()一直到activityIdleInternalLocked(),再往下处理Activity挂掉的动作。

private boolean resumeTopActivityInnerLocked(ActivityRecord prev, Bundle options) {
    return isOnHomeDisplay() &&
                    mStackSupervisor.resumeHomeStackTask(returnTaskType, prev, reason);

这个方法定义在文件frameworks/base/services/core/java/com/android/server/am/ActivityStack.java中。

如上面的方法,如果挂掉的Activity是Home Activity,那么调用resumeHomeStackTask()重新启动Launcher。最后调用ActivityManagerService的startHomeActivityLocked()方法,这里和开机启动的Launcher的过程一样了。更详细的流程请查看时序图。

Launcher的启动过程前言Launcher即桌面,是Android智能设备的窗口,用户使用最频繁的软件之一。Launhcer是Android所有应用的入口,也提供窗口小部件等功能。
launcher是安卓系统中的桌面启动器,安卓系统的桌面UI统称为LauncherLauncher是安卓系统中的主要程序组件之一,安卓系统中如果没有Launcher就无法启动安卓桌面,Launcher出错的时候,安卓系统会出现“进程 com.android.launcher 意外停止”的提示窗口。这时需要重新启动Launcher。 对于大部分Android开发来说不用改变Andro...
此前的文章我们学习了init进程、Zygote进程和SyetemServer进程的启动过程,这一篇文章我们就来学习Android系统启动流程的最后一步:Launcher启动流程,并结合本系列的前三篇文章的内容来讲解Android系统启动流程。建议读这篇文章前要通读本系列的前三篇文章,否则你可能不会理解我在讲什么。 1.Launcher概述 Android系统启动的最后一步是启动一个Home应用程序,这个应用程序用来显示系统中已经安装的应用程序,这个Home应用程序就叫做Launcher。...
Launcher即桌面,是Android智能设备的窗口,用户使用最频繁的软件之一。Launhcer是Android所有应用的入口,也提供窗口小部件等功能 当然,Launcher本身就是一个APP,一个提供桌面的APP,我们也可以开发一款Launcher APP作为手机的桌面。Laucher有很多和普通APP不同的地方。 Launcher是顶部APP,即任何应用返回后都是到Launcher,不能再继续返回; Launcher是所有应用的入口,可以管理应用; Launcher是Android系统启动后就要显示
开机作为使用手机的第一步操作,在长按电源键之后到我们可视化可操作的界面中间包含了很多任务,诸如文件系统挂载、native service启动、zygote启动launcher启动等,而这些任务是怎么执行的,又是在哪个阶段执行的? 我们先来看下当我们按下电源键之后,我们的手机执行这些任务的流程图: 从上图中我们可以看到,当按下开机键的时候,手机开始从固化在ROM的预设代码开始执行,加载Bootlo..
### 回答1: Galaxy Launcher是一款非常受欢迎的安卓手机桌面替换应用程序。它可以提供许多个性化的功能,帮助用户将他们的手机变得更加独特和个性化。 要下载Galaxy Launcher,您可以按照以下步骤进行操作: 首先,打开您的手机应用商店,可以是Google Play商店或者其他第三方应用商店。 然后,在搜索栏中输入“Galaxy Launcher”,然后点击搜索按钮。 接下来,您应该会看到一系列与Galaxy Launcher相关的搜索结果。请仔细浏览这些结果,并选择与您的需求最匹配的一个。您可以通过查看评论和评分来了解其他用户对该应用程序的满意程度。 接下来,找到一个适合的应用,点击进入详细页面。在此页面上,您将看到有关应用程序的更多信息,例如功能介绍、更新日志和用户评论。 然后,点击“下载”按钮,等待应用程序下载完成。请确保您的手机连接到互联网,以便下载过程顺利进行。 完成下载后,您可以在手机上找到安装文件并点击打开。按照屏幕上的指示完成应用程序的安装。 最后,您可以回到手机的主屏幕,将Galaxy Launcher设置为默认的桌面应用程序。您可以通过长按屏幕上的空白区域,然后选择“桌面设置”来完成此操作。 现在,您可以开始个性化您的手机,并享受Galaxy Launcher提供的各种功能了。 此外,还应提醒您下载和安装应用程序时要注意以下事项:确保您的手机有足够的存储空间;只从信任的来源下载应用程序;及时更新应用程序以获取更好的体验;定期清理手机内存以保持良好的运行速度。希望这些说明能够帮助您下载Galaxy Launcher并解决您的问题。 ### 回答2: Galaxy Launcher是一款可以让你的手机界面更像三星Galaxy系列手机的应用程序。它提供了一系列的个性化设置和功能,让你能够自定义手机的外观和操作方式。 首先,你可以在Galaxy Launcher中选择你喜欢的主题和壁纸,让你的手机界面看起来更加炫酷和个性化。无论是喜欢简约风格还是华丽风格的用户,都能够找到适合自己的主题。 其次,Galaxy Launcher还支持自定义图标和文件夹的样式。你可以根据自己的喜好,选择不同风格的图标和文件夹,让你的应用程序和文件更加整齐和易于管理。 除了外观设置,Galaxy Launcher还提供了一些实用的功能。比如,你可以通过手势操作来快速启动应用程序或执行特定的操作。你可以设置双击屏幕打开相机,或者滑动手势打开通知栏。 此外,Galaxy Launcher还提供了一些小工具,如天气插件、日历插件等,方便你随时查看天气和日程安排。 总而言之,Galaxy Launcher是一款功能强大的个性化应用程序,可以让你的手机界面更加炫酷和易于使用。不管你是想要简约风格还是华丽风格,Galaxy Launcher都能满足你的需求。赶快去下载Galaxy Launcher,让你的手机焕然一新吧! ### 回答3: Galaxy Launcher是一款用于安卓设备的桌面启动器应用程序,它可以为用户提供更好的桌面界面体验。通过使用Galaxy Launcher,用户可以为自己的设备选择不同的主题、图标样式、壁纸等,以使设备界面更加个性化和符合自己的喜好。 要下载Galaxy Launcher,用户可以前往Google Play商店或其他安卓应用市场。在应用市场搜索栏中输入“Galaxy Launcher”,并点击搜索按钮。搜索结果中将会显示Galaxy Launcher应用程序的相关信息和下载选项。用户可以点击下载按钮开始安装,系统会自动下载并安装应用程序到设备中。安装完成后,用户可以通过桌面图标或应用抽屉中找到Galaxy Launcher,并点击它来打开应用程序。 下载和安装Galaxy Launcher后,用户可以进入设置界面进行个性化设置。在设置界面中,用户可以选择不同的主题、图标包、壁纸等,以满足自己的需求和喜好。用户还可以调整桌面的布局和图标大小,以使界面更加符合自己的使用习惯。 总之,Galaxy Launcher是一款能够为安卓设备提供更好桌面体验的应用程序。通过下载和使用该应用程序,用户可以实现个性化的桌面设置,使设备界面更加符合自己的喜好。用户可以通过前往应用市场并搜索“Galaxy Launcher”来下载和安装该应用程序,并通过设置界面进行个性化设置。
卑微小城: [code=csharp] 10-27 16:51:26.352 1 1 I init : starting service 'compress-daemon'... 10-27 16:51:26.364 3946 3946 F init : cannot setexeccon('u:r:compress-daemon:s0') for compress-daemon: Invalid argument 10-27 16:51:26.370 1 1 I init : Service 'compress-daemon' (pid 3946) exited with status 6 10-27 16:51:26.370 1 1 I init : Sending signal 9 to service 'compress-daemon' (pid 3946) process group... 10-27 16:51:26.371 1 1 E init : updatable process 'compress-daemon' exited 4 times in 4 minutes [/code] 博主,我按照你的这个方法,开启启动提示以上问题,能指点一下吗,环境时linux系统20.04.03,Android_11_0_0_r32