Android P之Launcher启动

Android  源码分析  2023年11月6日 pm6:55发布11个月前更新 91es.com站长
60 0 0

前言

记录下一下Launcher是啥时候启动,至于启动中所有步骤这里不细写。

记录于此,主要是方便自己的。

PS : 分析源码 Android 9.0(P)

正文

正常情况下,Launcher是Android中第一个启动的应用。Launcher是Android系统的桌面,也是提供进入其他应用的启动程序。

Launcher很重要,因此今天记录一下Launcher的启动过程。

进入正题。

SystemServer.java

frameworks\base\services\java\com\android\server\SystemServer.java

SystemServer是Zygote启动时fork出来的,而SystemServer中主要的工作是:

初始化环境,比如时间,时区,语言等
准备主线程Looper
加载libandroid_servers.so库
初始化系统Context
创建SystemServiceManager
启动服务(引导服务,核心服务,其他服务)
进入Looper循环

之前大概介绍过(《SystenServer的启动之一》),如果需要的可以回归看看。(其实我也忘了,,尴尬)

今天介绍的Launcher启动是在启动服务(引导服务,核心服务,其他服务)中的[其他服务]中启动的。

startOtherServices()

差不多最后,有调用mActivityManagerService.systemReady()

//略[内容很多省略]
mActivityManagerService.systemReady(() -> {
    //略 
    mSystemServiceManager.startBootPhase(
            SystemService.PHASE_ACTIVITY_MANAGER_READY);
    //略             
});

ActivityManagerService.java

frameworks\base\services\core\java\com\android\server\am\ActivityManagerService.java

public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
    synchronized(this) {
        //mSystemReady = false,
        if (mSystemReady) {
            //略
        }
        //略[初始化]
        mSystemReady = true;
    }
    //略
    final PowerManagerInternal pmi = LocalServices.getService(PowerManagerInternal.class);
    //pmi不为null
    if (pmi != null) {
        pmi.registerLowPowerModeObserver(ServiceType.FORCE_BACKGROUND_CHECK,
                state -> updateForceBackgroundCheck(state.batterySaverEnabled));
        updateForceBackgroundCheck(
                pmi.getLowPowerState(ServiceType.FORCE_BACKGROUND_CHECK).batterySaverEnabled);
    }
    //略
    synchronized (this) {
        //为true
        if (!android.os.Bolt.BOLT_PERSIST_APP) {
            startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
        }
        mBooting = true;
        //略
        //BOLT_EARLY_HOME为false,进入
        if (!android.os.Bolt.BOLT_EARLY_HOME) {
            //进入这里
            startHomeActivityLocked(currentUserId, "systemReady");
        }
        //略
    }
}
startHomeActivityLocked
boolean startHomeActivityLocked(int userId, String reason) {
    //略[下面部分也省略]
    //这里没有获取到Launcher的启动包名
    Intent intent = getHomeIntent();
    //根据getHomeIntent()中的intent进行获取Launcher包名信息
    ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
    //aInfo不为null
    if (aInfo != null) {
        //设置启动包名和启动Activity
        intent.setComponent(new ComponentName(aInfo.applicationInfo.packageName, aInfo.name));
        aInfo = new ActivityInfo(aInfo);
        aInfo.applicationInfo = getAppInfoForUser(aInfo.applicationInfo, userId);
        ProcessRecord app = getProcessRecordLocked(aInfo.processName,
                aInfo.applicationInfo.uid, true);
        //app == null
        if (app == null || app.instr == null) {
            intent.setFlags(intent.getFlags() | FLAG_ACTIVITY_NEW_TASK);
            //正式启动Launcher的Activity
            mActivityStartController.startHomeActivity(intent, aInfo, myReason);
        }
    }
    return true;
}
getHomeIntent()
Intent getHomeIntent() {
    Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null);
    //mTopComponent为null
    intent.setComponent(mTopComponent);
    intent.addFlags(Intent.FLAG_DEBUG_TRIAGED_MISSING);
    //添加CATEGORY_HOME属性
    if (mFactoryTest != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
        intent.addCategory(Intent.CATEGORY_HOME);
    }
    return intent;
}

这里获取的intent并没有Launcher的启动包名信息,而是:

Intent { act=android.intent.action.MAIN cat=[android.intent.category.HOME] flg=0x100 }
resolveActivityInfo()
private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) {
    ActivityInfo ai = null;
    ComponentName comp = intent.getComponent();
    try {
		//comp为null,因为之前没有获取到
        if (comp为null != null) {
            // Factory test.
            ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId);
        } else {
            //进入这里,根据[android.intent.category.HOME]进行获取
            ResolveInfo info = AppGlobals.getPackageManager().resolveIntent(
                    intent,
                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
                    flags, userId);
            if (info != null) {
                ai = info.activityInfo;
            }
        }
        //ai= ActivityInfo{4bb04fb com.biumall.launcher.MainActivity}
    } catch (RemoteException e) {
    }
    return ai;
}
startHomeActivity
void startHomeActivity(Intent intent, ActivityInfo aInfo, String reason) {
    mSupervisor.moveHomeStackTaskToTop(reason);
    //build模式
    //obtainStarter()返回ActivityStarter
    //最后执行的ActivityStarter..execute()
    mLastHomeActivityStartResult = obtainStarter(intent, "startHomeActivity: " + reason)
            .setOutActivity(tmpOutRecord)
            .setCallingUid(0)
            .setActivityInfo(aInfo)
            .execute();
    mLastHomeActivityStartRecord = tmpOutRecord[0];
    //inResumeTopActivity=false
    if (mSupervisor.inResumeTopActivity) {
        mSupervisor.scheduleResumeTopActivities();
    }
}
obtainStarter
//关注点是返回ActivityStarter
ActivityStarter obtainStarter(Intent intent, String reason) {
    return mFactory.obtain().setIntent(intent).setReason(reason);
}

这里返回ActivityStarter,跟Launcher启动Activity的一样流程。

ActivityStarter.java

frameworks\base\services\core\java\com\android\server\am\ActivityStarter.java

这里的mRequest.mayWait为false,也就是走else

int execute() {
    try {
        //如果有调用.setMayWait(userId),这里会设置过true
        if (mRequest.mayWait) {
			return startActivityMayWait(mRequest.caller, mRequest.callingUid,
                    mRequest.callingPackage, mRequest.intent, mRequest.resolvedType,
                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                    mRequest.resultWho, mRequest.requestCode, mRequest.startFlags,
                    mRequest.profilerInfo, mRequest.waitResult, mRequest.globalConfig,
                    mRequest.activityOptions, mRequest.ignoreTargetSecurity, mRequest.userId,
                    mRequest.inTask, mRequest.reason,
                    mRequest.allowPendingRemoteAnimationRegistryLookup);
        } else {
			return startActivity(mRequest.caller, mRequest.intent, mRequest.ephemeralIntent,
                    mRequest.resolvedType, mRequest.activityInfo, mRequest.resolveInfo,
                    mRequest.voiceSession, mRequest.voiceInteractor, mRequest.resultTo,
                    mRequest.resultWho, mRequest.requestCode, mRequest.callingPid,
                    mRequest.callingUid, mRequest.callingPackage, mRequest.realCallingPid,
                    mRequest.realCallingUid, mRequest.startFlags, mRequest.activityOptions,
                    mRequest.ignoreTargetSecurity, mRequest.componentSpecified,
                    mRequest.outActivity, mRequest.inTask, mRequest.reason,
                    mRequest.allowPendingRemoteAnimationRegistryLookup);
        }
    } finally {
        onExecutionComplete();
    }
}

这里不继续跟了,就是startActivity的启动过程。后续会单独分析Activity的启动。

参考文章

太久了,忘记具体参考的文章,可以谷歌一下。

 历史上的今天

  1. 2021: 周国平:享受智力活动的快乐(0条评论)
  2. 2019: 汪曾祺:豆腐(0条评论)
版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站内容: 部分来源于网络,仅供学习和参考,若侵权请留言
3、 本站申明: 个人流水账日记,内容并不保证有效

暂无评论

暂无评论...

随机推荐

启动startService()分析(2)

接上一篇《Android 6.0 启动startService()源码分析(1)》,依旧分析startService()启动过程。由于篇幅过长,分开记录,便于阅读。10.4 ActivityManagerProxy.attachApplication在上一篇中的代码中 【获取的又是Activi...

Android机型适配相关摘抄

前言由于Android分辨多样,在做适配时总感觉困惑,怎么配置?(哈哈哈,之前项目一直都是一个分辨率的,不用做兼容,不同客户需求不一样)6个主流分辨率:800480、480320、1280720、854480、960540、19201080因此,摘抄如下内容。正文屏幕相关概念屏幕尺寸、...

尼采:孩子和婚姻

兄弟,我单独问你一个问题,这个问题就如探测之铅坠,我可据此了解你的灵魂。你年轻,渴望孩子与婚姻,但我问你,你有资格渴求孩子吗?你是胜利者吗?你战胜自己了吗?你能控制感情吗?你可以主宰你的美德吗?你的渴望是动物般的需要呢,还是孤独或内心冲突的表现?我希望你拥有胜利和自由后再渴望孩子,你应当为自己的...

西贝:路人

不知为何,明明想和你说话。却骗你说,风雨正好,该去写点诗句。 不必嘲讽我,你笑出声来,我也当是天籁。 不必怀有敌意,你所有心计,我都当是你对我的心意。 我的宿命分两段,未遇见你时,和遇见你以后。你治好我的忧郁,而后赐我悲伤。 忧郁和悲...

sendBroadcast静态广播源码分析

前言本次分析一下Android P开机后发送静态广播源码分析,记录一下,方便自己查阅。部分流程跟前面的源码分析《startActivity源码分析》和《startService源码分析》都比较类似,所以重复的步骤就省略。PS:启动startActivity的比较复杂,流程多,但搞懂了这个,...

Android startActivity去掉自带的动画效果

Android中startActivity系统自带动画效果,如果需要取消动效,可以考虑如下两种方式。使用overridePendingTransition在启动Activity后添加此代码Intent intent = new Intent(mContext, MainActivity.cl...