HomeActivity启动流程(launcher)

本文详细分析了Android系统中HomeActivity的启动流程,从启动到展示在屏幕上的各个步骤,涉及 AMS、Binder 机制、进程通信等多个关键环节。通过对源码的解读,阐述了如何从到启动新的进程,再到ActivityThread的main方法执行,以及后续的Activity生命周期管理。
摘要由CSDN通过智能技术生成

0. 写在前面的话

上一篇讲了各种Service是在何时启动的,最后提到了关于HomeActivity的启动。HomeActivity作为Android系统启动后第一个加载的Activity,今天就来分析下其启动流程。
其实还有个时序图的,但是太大了,截图也不全,等下次直接上传,方便自己查看。
暂时的规划先是Activity的启动流程,通过这个又会涉及到进程间通信——Binder机制,接着Activity启动后,布局是如何绘制到屏幕上,View的事件是如何分发的?通过这条线来慢慢整理这两年多我对Android的理解,加深自己的印象。


1. ActivityManagerService.systemReady(new Runnable())做了什么?

我们先来看下这个方法的代码:

public void systemReady(final Runnable goingCallback) {
    synchronized(this) {
        //mSystemReady默认为false,所以第一次调用这个方法时不会执行goingCallback.run()
        if (mSystemReady) {
            if (goingCallback != null) {
                goingCallback.run();
            }
            return;
        }
        ......
    }
    //要杀掉的进程(启动时不允许启动的进程)
    ArrayList<ProcessRecord> procsToKill = null;
    synchronized(mPidsSelfLocked) {
        for (int i=mPidsSelfLocked.size()-1; i>=0; i--) {
            ProcessRecord proc = mPidsSelfLocked.valueAt(i);
            if (!isAllowedWhileBooting(proc.info)){
                if (procsToKill == null) {
                    procsToKill = new ArrayList<ProcessRecord>();
                }
                procsToKill.add(proc);
            }
        }
    }
    //杀掉这些进程
    synchronized(this) {
        if (procsToKill != null) {
            for (int i=procsToKill.size()-1; i>=0; i--) {
                ProcessRecord proc = procsToKill.get(i);
                Slog.i(TAG, "Removing system update proc: " + proc);
                removeProcessLocked(proc, true, false, "system update done");
            }
        }

        // Now that we have cleaned up any update processes, we
        // are ready to start launching real processes and know that
        // we won't trample on them any more.
        mProcessesReady = true;
    }
    ......
    //这里会调用Runnable的run()方法
    if (goingCallback != null) goingCallback.run();
    ......
    synchronized (this) {
        //启动常驻的应用
        startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
        mBooting = true;
        if (UserManager.isSplitSystemUser()) {
            ComponentName cName = new ComponentName(mContext, SystemUserHomeActivity.class);
            try {
                //解禁SystemUserHomeActivity
                AppGlobals.getPackageManager().setComponentEnabledSetting(cName,
                        PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0,
                        UserHandle.USER_SYSTEM);
            } catch (RemoteException e) {
                throw e.rethrowAsRuntimeException();
            }
        }
        //开始启动HomeActivity
        startHomeActivityLocked(currentUserId, "systemReady");
        ......
    }
}

这个方法内容挺多的,首次进入是设置的Runnable不会执行,后面通过查找启动时系统不允许启动的进程,并将其kill掉。接下来启动了系统常驻应用startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE),通过使用AppGlobals.getPackageManager().setComponentEnabledSetting方法解禁SystemUserHomeActivity,其flag为PackageManager.COMPONENT_ENABLED_STATE_ENABLED,最后通过startHomeActivityLocked(currentUserId, "systemReady")来启动HomeActivity


2. startHomeActivityLocked开始启动HomeActivity

这里的代码不多,也很好理解:

boolean startHomeActivityLocked(int userId, String reason) {
    //测试模式下不用管
    if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL
            && mTopAction == null) {
        // We are running in factory test mode, but unable to find
        // the factory test app, so just sit around displaying the
        // error message and don't try to start anything.
        return false;
    }
    //得到要启动Activity的Intent
    Intent intent = getHomeIntent();
    //将Intent解析成ActivityInfo
    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);
            //启动Activity
            mActivityStarter.startHomeActivityLocked(intent, aInfo, reason);
        }
    } else {
        Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
    }

    return true;
}

Intent getHomeIntent() {
    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    intent.setComponent(mTopComponent);
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    //不是测试情况下则设置Category为Intent.CATEGORY_HOME
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        intent.addCategory(Intent.CATEGORY_HOME);
    }
    return intent;
}

首先是判断当前系统是否处于测试环境,接着去获取(创建)HomeIntent,并将其解析成ActivityInfo,接下来调用ActivityStarter中的startHomeActivityLocked(intent, aInfo, reason)方法去启动HomeActivity


3. startHomeActivityLockedstartActivityLocked

我们进入ActivityStarter中可以看到startHomeActivityLocked调用了startActivityLocked方法,其中传入的参数只有IntentActivityInfo不为空,其他的都为null或者0或者false,由于大部分参数都为nullstartActivityLocked中真正执行的代码并不是很多。

void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
    mSupervisor.moveHomeStackTaskToTop(HOME_ACTIVITY_TYPE, reason);
    //调用了参数居多的方法
    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*/, null /*outActivity*/,
            null /*container*/, null /*inTask*/);
    if (mSupervisor.inResumeTopActivity) {
        // If we are in resume section already, home activity will be initialized, but not
        // resumed (to avoid recursive resume) and will stay that way until something pokes it
        // again. We need to schedule another resume.
        mSupervisor.scheduleResumeTopActivities();
    }
}
//这个参数是真TM的多啊
final int startActivityLocked(IApplicationThread caller, Intent intent, Intent ephemeralIntent,
        String resolvedType, ActivityInfo aInfo, ResolveInfo rInfo,
        IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
        IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid,
        String callingPackage, int realCallingPid, int realCallingUid, int startFlags,
        ActivityOptions options, boolean ignoreTargetSecurity, boolean componentSpecified,
        ActivityRecord[] outActivity, ActivityStackSupervisor.ActivityContainer container,
        TaskRecord inTask) {
    //启动结果代码
    int err = ActivityManager.START_SUCCESS;
    
    ProcessRecord callerApp = null;
    //caller == null
    if (caller != null) {
        ......
    }
    
    final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0;

    if (err == ActivityManager.START_SUCCESS) {
        ..Log..
    }

    ActivityRecord sourceRecord = null;
    ActivityRecord resultRecord = null;
    //resultTo == null
    if (resultTo != null) {
        ......
    }

    final int launchFlags = intent.getFlags();
    //Activity启动是设置的flags
    if ((launchFlags & Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {
        ......
    }

    ......
    
    //检查启动Activity的权限
    boolean abort = !mSupervisor.checkStartAnyActivityPermission(intent, aInfo, resultWho,
          
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值