💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
作为核心服务,AMS的systemReady会做什么呢?由于该函数内容较多,我们将它分为三段。首先看第一段的工作。 1. systemReady第一阶段的工作 **ActivityManagerService.java::systemReady** ~~~ public void systemReady(final RunnablegoingCallback) { synchronized(this){ ...... if(!mDidUpdate) {//判断是否为升级 if(mWaitingUpdate) return; //升级未完成,直接返回 //准备PRE_BOOT_COMPLETED广播 Intent intent = newIntent(Intent.ACTION_PRE_BOOT_COMPLETED); List<ResolveInfo> ris = null; //向PKMS查询该广播的接收者 ris= AppGlobals.getPackageManager().queryIntentReceivers( intent, null,0); ......//从返回的结果中删除那些非系统APK的广播接收者 intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE); //读取/data/system/called_pre_boots.dat文件,这里存储了上次启动时候已经 //接收并处理PRE_BOOT_COMPLETED广播的组件。鉴于该广播的特殊性,系统希望 //该广播仅被这些接收者处理一次 ArrayList<ComponentName>lastDoneReceivers = readLastDonePreBootReceivers(); final ArrayList<ComponentName> doneReceivers= newArrayList<ComponentName>(); ......//从PKMS返回的接收者中删除那些已经处理过该广播的对象 for (int i=0; i<ris.size(); i++) { ActivityInfo ai = ris.get(i).activityInfo; ComponentName comp = newComponentName(ai.packageName, ai.name); doneReceivers.add(comp); intent.setComponent(comp); IIntentReceiver finisher = null; if (i == ris.size()-1) { //为最后一个广播接收者注册一个回调通知,当该接收者处理完广播后,将调用该 //回调 finisher = new IIntentReceiver.Stub() { public voidperformReceive(Intent intent, int resultCode, Stringdata, Bundle extras, boolean ordered, booleansticky) { mHandler.post(newRunnable() { public void run(){ synchronized(ActivityManagerService.this) { mDidUpdate = true; } //保存那些处理过该广播的接收者信息 writeLastDonePreBootReceivers(doneReceivers); showBootMessage(mContext.getText( R.string.android_upgrading_complete), false); systemReady(goingCallback); }//run结束 });// new Runnable结束 }//performReceive结束 };//finisher创建结束 }// if (i == ris.size()-1)判断结束 //发送广播给指定的接收者 broadcastIntentLocked(null, null, intent,null, finisher, 0, null, null, null, true, false, MY_PID, Process.SYSTEM_UID); if (finisher != null) mWaitingUpdate = true; } if(mWaitingUpdate) return; mDidUpdate= true; } mSystemReady = true; if(!mStartRunning) return; }//synchronized(this)结束 ~~~ 由以上代码可知,systemReady第一阶段的工作并不轻松,其主要职责是发送并处理与PRE_BOOT_COMPLETED广播相关的事情。目前代码中还没有接收该广播的地方,不过从代码中的注释中可猜测到,该广播接收者的工作似乎和系统升级有关。 建议如有哪位读者了解与此相关的知识,不妨和大家分享。 下面来介绍systemReady第二阶段的工作。 2. systemReady第二阶段的工作 **ActivityManagerService.java::systemReady** ~~~ ArrayList<ProcessRecord>procsToKill = null; synchronized(mPidsSelfLocked) { for(int i=mPidsSelfLocked.size()-1; i>=0; i--) { ProcessRecord proc = mPidsSelfLocked.valueAt(i); //从mPidsSelfLocked中找到那些先于AMS启动的进程,哪些进程有如此能耐, //在AMS还未启动完毕就启动完了呢?对,那些声明了persistent为true的进程有可能 if(!isAllowedWhileBooting(proc.info)){ if (procsToKill == null) procsToKill = new ArrayList<ProcessRecord>(); procsToKill.add(proc); } }//for结束 }// synchronized结束 synchronized(this){ if(procsToKill != null) { for (int i=procsToKill.size()-1; i>=0; i--) { ProcessRecord proc = procsToKill.get(i); //把这些进程关闭,removeProcessLocked函数比较复杂,以后再分析 removeProcessLocked(proc, true, false); } } //至此,系统已经准备完毕 mProcessesReady = true; } synchronized(this) { if(mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL) { }//和工厂测试有关,不对此进行讨论 } //查询Settings数据,获取一些配置参数 retrieveSettings(); ~~~ systemReady第二阶段的工作包括: - 杀死那些竟然在AMS还未启动完毕就先启动的应用进程。注意,这些应用进程一定是APK所在的Java进程,因为只有应用进程才会向AMS注册,而一般Native(例如mediaserver)进程是不会向AMS注册的。 - 从Settings数据库中获取配置信息,目前只取4个配置参数,分别是:"debug_app"(设置需要debug的app的名称)、"wait_for_debugger"(如果为1,则等待调试器,否则正常启动debug_app)、"always_finish_activities"(当一个activity不再有地方使用时,是否立即对它执行destroy)、"font_scale"(用于控制字体放大倍数,这是Android 4.0新增的功能)。以上配置项由Settings数据库的System表提供。 3. systemReady第三阶段的工作 **ActivityManagerService.java::systemReady** ~~~ //调用systemReady传入的参数,它是一个Runnable对象,下节将分析此函数 if (goingCallback != null) goingCallback.run(); synchronized (this) { if(mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { try{ //从PKMS中查询那些persistent为1的ApplicationInfo List apps = AppGlobals.getPackageManager(). getPersistentApplications(STOCK_PM_FLAGS); if (apps != null) { int N = apps.size(); int i; for (i=0; i<N; i++) { ApplicationInfo info = (ApplicationInfo)apps.get(i); //由于framework-res.apk已经由系统启动,所以这里需要把它去除 //framework-res.apk的packageName为"android" if (info != null && !info.packageName.equals("android")) addAppLocked(info);//启动该Application所在的进程 } } }...... } mBooting= true; //设置mBooting变量为true,其作用后面会介绍 try { if(AppGlobals.getPackageManager().hasSystemUidErrors()) { ......//处理那些Uid有错误的Application }...... //启动全系统第一个Activity,即Home mMainStack.resumeTopActivityLocked(null); }// synchronized结束 } ~~~ systemReady第三阶段的工作有3项: - 调用systemReady设置的回调对象goingCallback的run函数。 - 启动那些声明了persistent的APK。 - 启动桌面。 先看回调对象goingCallback的run函数的工作。 (1) goingCallback的run函数分析 **SystemServer.java::ServerThread.run** ~~~ ActivityManagerService.self().systemReady(newRunnable() { publicvoid run() { startSystemUi(contextF);//启动SystemUi //调用其他服务的systemReady函数 if(batteryF != null) batteryF.systemReady(); if(networkManagementF != null) networkManagementF.systemReady(); ...... Watchdog.getInstance().start();//启动Watchdog ......//调用其他服务的systemReady函数 } ~~~ run函数比较简单,执行的工作如下: - 执行startSystemUi,在该函数内部启动SystemUIService,该Service和状态栏有关。 - 调用一些服务的systemReady函数。 - 启动Watchdog。 startSystemUi的代码如下: `SystemServer.java::startSystemUi` ~~~ static final void startSystemUi(Context context) { Intentintent = new Intent(); intent.setComponent(new ComponentName("com.android.systemui", "com.android.systemui.SystemUIService")); context.startService(intent); } ~~~ SystemUIService由SystemUi.apk提供,它实现了系统的状态栏。 * * * * * **注意**:在精简ROM时,也不能删除SystemUi.apk。 * * * * * (2) 启动Home界面 如前所述,resumeTopActivityLocked将启动Home界面,此函数非常重要也比较复杂,故以后再详细分析。我们提取了resumeTopActivityLocked启动Home界面时的相关代码,如下所示: **ActivityStack.java::resumeTopActivityLocked** ~~~ final booleanresumeTopActivityLocked(ActivityRecord prev) { //找到下一个要启动的Activity ActivityRecord next = topRunningActivityLocked(null); finalboolean userLeaving = mUserLeaving; mUserLeaving = false; if (next== null) { //如果下一个要启动的ActivityRecord为空,则启动Home if(mMainStack) {//全系统就一个ActivityStack,所以mMainStack永远为true //mService指向AMS return mService.startHomeActivityLocked();//mService指向AMS } } ......//以后再详细分析 } ~~~ 下面来看AMS的startHomeActivityLocked函数,代码如下: **ActivityManagerService.java::startHomeActivityLocked** ~~~ boolean startHomeActivityLocked() { Intentintent = new Intent( mTopAction, mTopData != null ? Uri.parse(mTopData) :null); intent.setComponent(mTopComponent); if(mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) intent.addCategory(Intent.CATEGORY_HOME);//添加Category为HOME类别 //向PKMS查询满足条件的ActivityInfo ActivityInfo aInfo = intent.resolveActivityInfo(mContext.getPackageManager(), STOCK_PM_FLAGS); if(aInfo != null) { intent.setComponent(new ComponentName( aInfo.applicationInfo.packageName,aInfo.name)); ProcessRecordapp = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid); //在正常情况下,app应该为null,因为刚开机,Home进程肯定还没启动 if(app == null || app.instrumentationClass == null) { intent.setFlags(intent.getFlags()| Intent.FLAG_ACTIVITY_NEW_TASK); //启动Home mMainStack.startActivityLocked(null, intent, null, null, 0, aInfo, null, null, 0, 0, 0, false, false,null); } }//if(aInfo != null)判断结束 return true; } ~~~ 至此,AMS携诸位Service都启动完毕,Home也靓丽登场,整个系统就准备完毕,只等待用户的检验了。不过在分析逻辑上还有一点没涉及,那会是什么呢? (3) 发送ACTION_BOOT_COMPLETED广播 由前面的代码可知,AMS发送了ACTION_PRE_BOOT_COMPLETED广播,可系统中没有地方处理它。在前面的章节中,还碰到一个ACTION_BOOT_COMPLETED广播,该广播广受欢迎,却不知道它是在哪里发送的。 当Home Activity启动后,ActivityStack的activityIdleInternal函数将被调用,其中有一句代码颇值得注意: **ActivityStack.java::activityIdleInternal** ~~~ final ActivityRecord activityIdleInternal(IBindertoken, boolean fromTimeout, Configuration config) { booleanbooting = false; ...... if(mMainStack) { booting = mService.mBooting; //在systemReady的第三阶段工作中设置该值为true mService.mBooting = false; } ...... if(booting) mService.finishBooting();//调用AMS的finishBooting函数 } ~~~ **ActivityManagerService.java::finishBooting** ~~~ final void finishBooting() { IntentFilter pkgFilter = new IntentFilter(); pkgFilter.addAction(Intent.ACTION_QUERY_PACKAGE_RESTART); pkgFilter.addDataScheme("package"); mContext.registerReceiver(new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { ......//处理Package重启的广播 } }, pkgFilter); synchronized (this) { finalint NP = mProcessesOnHold.size(); if (NP> 0) { ArrayList<ProcessRecord> procs = new ArrayList<ProcessRecord>(mProcessesOnHold); for(int ip=0; ip<NP; ip++)//启动那些等待启动的进程 startProcessLocked(procs.get(ip), "on-hold", null); } if(mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { //每15钟检查系统各应用进程使用电量的情况,如果某进程使用WakeLock时间 //过长,AMS将关闭该进程 Message nmsg = mHandler.obtainMessage(CHECK_EXCESSIVE_WAKE_LOCKS_MSG); mHandler.sendMessageDelayed(nmsg, POWER_CHECK_DELAY); //设置系统属性sys.boot_completed的值为1 SystemProperties.set("sys.boot_completed","1"); //发送ACTION_BOOT_COMPLETED广播 broadcastIntentLocked(null, null, newIntent(Intent.ACTION_BOOT_COMPLETED, null), null, null, 0, null,null, android.Manifest.permission.RECEIVE_BOOT_COMPLETED, false, false, MY_PID,Process.SYSTEM_UID); } } } ~~~ 原来,在Home启动成功后,AMS才发送ACTION_BOOT_COMPLETED广播。 4. ASM的 systemReady总结 systemReady函数完成了系统就绪的必要工作,然后它将启动Home Activity。至此,Android系统就全部启动了。