文章出处:http://blog.csdn.net/shift_wwx
接着之前三篇
ActivityManagerService (一)
ActivityManagerService (二)
ActivityManagerService (三)
SystemServer中的ActivityManagerService.self().setWindowManager(wm);暂时不总结了,需要结合WMS。
接着总结:
ActivityManagerService.self().systemReady(new Runnable() { public void run() { Slog.i(TAG, "Making services ready"); try { ActivityManagerService.self().startObservingNativeCrashes(); } catch (Throwable e) { reportWtf("observing native crashes", e); } if (!headless) { startSystemUi(contextF); } try { if (mountServiceF != null) mountServiceF.systemReady(); } catch (Throwable e) { reportWtf("making Mount Service ready", e); } ...... ...... } };这里systemReady的参数是一个Runnable的对象,并且实现了run,可以看到run里面都是AMS之后的一些准备工作。
例如startSystemUi、mountServiceF(MountService)、batteryF(BatteryService)、networkManagementF(NetworkManagementService)等等。
这些后续补充,来看一下systemReady的source code,由于systemReady的source code太长了,所以就分开来分析:
1、
// Check to see if there are any update receivers to run. if (!mDidUpdate) { if (mWaitingUpdate) { return; } Intent intent = new Intent(Intent.ACTION_PRE_BOOT_COMPLETED); List<ResolveInfo> ris = null; try { ris = AppGlobals.getPackageManager().queryIntentReceivers( intent, null, 0, 0); } catch (RemoteException e) { } if (ris != null) { for (int i=ris.size()-1; i>=0; i--) { if ((ris.get(i).activityInfo.applicationInfo.flags &ApplicationInfo.FLAG_SYSTEM) == 0) { ris.remove(i); } } intent.addFlags(Intent.FLAG_RECEIVER_BOOT_UPGRADE); ArrayList<ComponentName> lastDoneReceivers = readLastDonePreBootReceivers(); final ArrayList<ComponentName> doneReceivers = new ArrayList<ComponentName>(); for (int i=0; i<ris.size(); i++) { ActivityInfo ai = ris.get(i).activityInfo; ComponentName comp = new ComponentName(ai.packageName, ai.name); if (lastDoneReceivers.contains(comp)) { ris.remove(i); i--; } } final int[] users = getUsersLocked(); for (int i=0; i<ris.size(); i++) { ActivityInfo ai = ris.get(i).activityInfo; ComponentName comp = new ComponentName(ai.packageName, ai.name); doneReceivers.add(comp); intent.setComponent(comp); for (int j=0; j<users.length; j++) { IIntentReceiver finisher = null; if (i == ris.size()-1 && j == users.length-1) { finisher = new IIntentReceiver.Stub() { public void performReceive(Intent intent, int resultCode, String data, Bundle extras, boolean ordered, boolean sticky, int sendingUser) { // The raw IIntentReceiver interface is called // with the AM lock held, so redispatch to // execute our code without the lock. mHandler.post(new Runnable() { public void run() { synchronized (ActivityManagerService.this) { mDidUpdate = true; } writeLastDonePreBootReceivers(doneReceivers); showBootMessage(mContext.getText( R.string.android_upgrading_complete), false); systemReady(goingCallback); } }); } }; } Slog.i(TAG, "Sending system update to " + intent.getComponent() + " for user " + users[j]); broadcastIntentLocked(null, null, intent, null, finisher, 0, null, null, null, AppOpsManager.OP_NONE, true, false, MY_PID, Process.SYSTEM_UID, users[j]); if (finisher != null) { mWaitingUpdate = true; } } } } if (mWaitingUpdate) { return; } mDidUpdate = true; }主要用来处理OTA升级后database有改变的状况,这里会从PMS中获取所有接收ACTION_PRE_BOOT_COMPLETED的Receivers,并发送广播给它们,最后会记录这些已经发送广播的Receivers到/data/system/called_pre_boots.dat文件中。关于OTA升级这部分我们先不关注了。
接着来看systemReady后面的代码:
2、
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; }上面的代码主要是杀死在AMS systemReady之前启动的启动process,且这些process没有设置FLAG_PERSISTENT(例如update进程),然后调用removeProcessLocked去结束进程并释放资源,这部分代码我们后面再来介绍。
3、retrieveSettings();
private void retrieveSettings() { final ContentResolver resolver = mContext.getContentResolver(); String debugApp = Settings.Global.getString( resolver, Settings.Global.DEBUG_APP); boolean waitForDebugger = Settings.Global.getInt( resolver, Settings.Global.WAIT_FOR_DEBUGGER, 0) != 0; boolean alwaysFinishActivities = Settings.Global.getInt( resolver, Settings.Global.ALWAYS_FINISH_ACTIVITIES, 0) != 0; boolean forceRtl = Settings.Global.getInt( resolver, Settings.Global.DEVELOPMENT_FORCE_RTL, 0) != 0; // Transfer any global setting for forcing RTL layout, into a System Property SystemProperties.set(Settings.Global.DEVELOPMENT_FORCE_RTL, forceRtl ? "1":"0"); Configuration configuration = new Configuration(); Settings.System.getConfiguration(resolver, configuration); if (forceRtl) { // This will take care of setting the correct layout direction flags configuration.setLayoutDirection(configuration.locale); } synchronized (this) { mDebugApp = mOrigDebugApp = debugApp; mWaitForDebugger = mOrigWaitForDebugger = waitForDebugger; mAlwaysFinishActivities = alwaysFinishActivities; // This happens before any activities are started, so we can // change mConfiguration in-place. updateConfigurationLocked(configuration, null, false, true); if (DEBUG_CONFIGURATION) Slog.v(TAG, "Initial config: " + mConfiguration); } }从SettingsProvider中获取DEBUG_APP、WAIT_FOR_DEBUGGER、ALWAYS_FINISH_ACTIVITIES和DEVELOPMENT_FORCE_RTL四个配置项。
4、readGrantedUriPermissionsLocked
readGrantedUriPermissionsLocked从/data/system/urigrants.xml中读取Uri权限,并构造UriPermission保存在AMS全局的mGrantedUriPermissions中,这部分我们以后遇到的时候再来介绍。
5、if (goingCallback != null) goingCallback.run();
这里就是刚开始说到的,在systemServer中调用systemReady的时候同时注册的callback。
主要就是其他一些service 的systemReady、startSystemUi、软件启动Watchdog等。
6、mBooting = true;
7、mStackSupervisor.resumeTopActivitiesLocked();
boolean resumeTopActivitiesLocked() { return resumeTopActivitiesLocked(null, null, null); }
boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target, Bundle targetOptions) { if (targetStack == null) { targetStack = getFocusedStack(); } boolean result = false; for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = mStacks.get(stackNdx); if (isFrontStack(stack)) { if (stack == targetStack) { result = stack.resumeTopActivityLocked(target, targetOptions); } else { stack.resumeTopActivityLocked(null); } } } return result; }targetStack传进来的是null,所以,重新赋值为mHomeStack。记得ActivityStackSupervisor这个类吧?在AMS.main的时候实例化的。
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) { if (ActivityManagerService.DEBUG_LOCKSCREEN) mService.logLockScreen(""); // Find the first activity that is not finishing. ActivityRecord next = topRunningActivityLocked(null); // Remember how we'll process this pause/resume situation, and ensure // that the state is reset however we wind up proceeding. final boolean userLeaving = mStackSupervisor.mUserLeaving; mStackSupervisor.mUserLeaving = false; if (next == null) { // There are no more activities! Let's just start up the // Launcher... ActivityOptions.abort(options); if (DEBUG_STATES) Slog.d(TAG, "resumeTopActivityLocked: No more activities go home"); if (DEBUG_STACK) mStackSupervisor.validateTopActivitiesLocked(); return mStackSupervisor.resumeHomeActivity(prev); }首先要获取next:
final ActivityRecord topRunningActivityLocked(ActivityRecord notTop) { for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) { ActivityRecord r = mTaskHistory.get(taskNdx).topRunningActivityLocked(notTop); if (r != null) { return r; } } return null; }刚启动的时候mTaskHistory应该是空,所以,返回后next应该是null。
最终会调用return mStackSupervisor.resumeHomeActivity(prev);
boolean resumeHomeActivity(ActivityRecord prev) { moveHomeToTop(); if (prev != null) { prev.task.mOnTopOfHome = false; } ActivityRecord r = mHomeStack.topRunningActivityLocked(null); if (r != null && r.isHomeActivity()) { mService.setFocusedActivityLocked(r); return resumeTopActivitiesLocked(mHomeStack, prev, null); } return mService.startHomeActivityLocked(mCurrentUser, false); }r还是null,直接调用AMS的startHomeActivityLocked:
boolean startHomeActivityLocked(int userId, boolean preStart) { if (mHeadless) { // Added because none of the other calls to ensureBootCompleted seem to fire // when running headless. ensureBootCompleted(); return false; } if(preStart){ ensureBootCompleted(); } if (mFactoryTest == SystemServer.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; } Intent intent = getHomeIntent(); try { //check if mount data fail Boolean bMountFail = SystemProperties.getBoolean("ro.init.mountdatafail", false); //Log.i( TAG, "bMountFail:" + bMountFail ); ComponentName name = new ComponentName("com.amlogic.promptuser", "com.amlogic.promptuser.BootActivity"); //PackageManager pm = mContext.getPackageManager(); //pm.setComponentEnabledSetting(name, bMountFail ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP); final IPackageManager pm = AppGlobals.getPackageManager(); pm.setComponentEnabledSetting(name, bMountFail ? PackageManager.COMPONENT_ENABLED_STATE_ENABLED : PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP, userId); } catch (Exception e) { Log.w( TAG, "setComponentEnabledSetting with com.amlogic.promptuser boot activity fail" ); e.printStackTrace(); } 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); mStackSupervisor.startHomeActivity(intent, aInfo); } } return true; }1)getHomeIntent
Intent getHomeIntent() { Intent intent = new Intent(mTopAction, mTopData != null ? Uri.parse(mTopData) : null); intent.setComponent(mTopComponent); if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { intent.addCategory(Intent.CATEGORY_HOME); } return intent; }mTopAction、mTopData、mTopComponent都是在AMS.main中调用的startRunning(null,null,null,null)中初始值的。
public final void startRunning(String pkg, String cls, String action, String data) { synchronized(this) { if (mStartRunning) { return; } mStartRunning = true; mTopComponent = pkg != null && cls != null ? new ComponentName(pkg, cls) : null; mTopAction = action != null ? action : Intent.ACTION_MAIN; mTopData = data; if (!mSystemReady) { return; } } systemReady(null); }可以看出mTopAction是Intent.ACTION_MAIN,mTopComponent是null。
那么综合看来getHomeIntent的目的就是实例化一个ACTION 是Intent.ACTION_MAIN、category是Intent.CATEGORY_HOME的一个intent。
2)通过之前获得的intent来解析ActivityInfo:
resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
private ActivityInfo resolveActivityInfo(Intent intent, int flags, int userId) { ActivityInfo ai = null; ComponentName comp = intent.getComponent(); try { if (comp != null) { ai = AppGlobals.getPackageManager().getActivityInfo(comp, flags, userId); } else { ResolveInfo info = AppGlobals.getPackageManager().resolveIntent( intent, intent.resolveTypeIfNeeded(mContext.getContentResolver()), flags, userId); if (info != null) { ai = info.activityInfo; } } } catch (RemoteException e) { // ignore } return ai; }
@Override public ResolveInfo resolveIntent(Intent intent, String resolvedType, int flags, int userId) { if (!sUserManager.exists(userId)) return null; enforceCrossUserPermission(Binder.getCallingUid(), userId, false, "resolve intent"); List<ResolveInfo> query = queryIntentActivities(intent, resolvedType, flags, userId); return chooseBestActivity(intent, resolvedType, flags, query, userId); }
可能存在多个ACTION_MAIN,category是home的 intent,queryIntentActivities就是筛选,最开始的时候如果没有选择过会进入ResolverActivity (frameworks/base/core/java/com/android/internal/app) 让用户选择,至于怎么解析出ResolverActivity,我也是跟了一半,后期需要研究一下。如果有选择过了,就会通过chooseBestActivity函数来筛选:
private ResolveInfo chooseBestActivity(Intent intent, String resolvedType, int flags, List<ResolveInfo> query, int userId) { if (query != null) { final int N = query.size(); if (N == 1) { return query.get(0); } else if (N > 1) { final boolean debug = ((intent.getFlags() & Intent.FLAG_DEBUG_LOG_RESOLUTION) != 0); // If there is more than one activity with the same priority, // then let the user decide between them. ResolveInfo r0 = query.get(0); ResolveInfo r1 = query.get(1); if (DEBUG_INTENT_MATCHING || debug) { Slog.v(TAG, r0.activityInfo.name + "=" + r0.priority + " vs " + r1.activityInfo.name + "=" + r1.priority); } // If the first activity has a higher priority, or a different // default, then it is always desireable to pick it. if (r0.priority != r1.priority || r0.preferredOrder != r1.preferredOrder || r0.isDefault != r1.isDefault) { return query.get(0); } // If we have saved a preference for a preferred activity for // this Intent, use that. ResolveInfo ri = findPreferredActivity(intent, resolvedType, flags, query, r0.priority, true, false, debug, userId); if (ri != null) { return ri; } if (userId != 0) { ri = new ResolveInfo(mResolveInfo); ri.activityInfo = new ActivityInfo(ri.activityInfo); ri.activityInfo.applicationInfo = new ApplicationInfo( ri.activityInfo.applicationInfo); ri.activityInfo.applicationInfo.uid = UserHandle.getUid(userId, UserHandle.getAppId(ri.activityInfo.applicationInfo.uid)); return ri; } return mResolveInfo; } } return null; }通过code可以看到,如果就一个home activity的话,就直接返回了。如果是多个的话就需要比较,例如priority、preferredOrder、isDefault等。
ProcessRecord app = getProcessRecordLocked(aInfo.processName, aInfo.applicationInfo.uid, true);
这里app显然null,于是进入:
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); mStackSupervisor.startHomeActivity(intent, aInfo);Home 是一个新的task,最终看到了启动Home Activity的地方了。
接下来详细分析一下启动Home Activity的过程,以后单纯的启动一个activity也会有很多相似的地方。这里以android 的Launcher2为例。
void startHomeActivity(Intent intent, ActivityInfo aInfo) { moveHomeToTop();//mTaskHistory 现在是空,这里没有做处理 startActivityLocked(null, intent, null, aInfo, null, null, 0, 0, 0, null, 0, null, false, null); } final int startActivityLocked(IApplicationThread caller, Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo, String resultWho, int requestCode, int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options, boolean componentSpecified, ActivityRecord[] outActivity) { int err = ActivityManager.START_SUCCESS; ProcessRecord callerApp = null; PackageManager mPm = mContext.getPackageManager(); if (caller != null) {//传进来参数为null ...... } if (err == ActivityManager.START_SUCCESS) { final int userId = aInfo != null ? UserHandle.getUserId(aInfo.applicationInfo.uid) : 0; Slog.i(TAG, "START u" + userId + " {" + intent.toShortString(true, true, true, false) + "} from pid " + (callerApp != null ? callerApp.pid : callingPid)); } ActivityRecord sourceRecord = null; ActivityRecord resultRecord = null; if (resultTo != null) {//传进来参数为null ...... } ActivityStack resultStack = resultRecord == null ? null : resultRecord.task.stack; int launchFlags = intent.getFlags(); if ((launchFlags&Intent.FLAG_ACTIVITY_FORWARD_RESULT) != 0 && sourceRecord != null) {//sourceRecord 为null ...... } if (err == ActivityManager.START_SUCCESS && intent.getComponent() == null) {//component 不为null ...... } if (err == ActivityManager.START_SUCCESS && aInfo == null) {//aInfo不为null ...... } ResolveInfo info = mPm.resolveActivity(intent, PackageManager.GET_DISABLED_COMPONENTS); //ResolveInfo info = mPm.resolveActivity(intent, PackageManager.GET_DISABLED_COMPONENTS|PackageManager.GET_INTENT_FILTERS); String packageName = (info != null) ? info.activityInfo.applicationInfo.packageName : null; String className = (info != null) ? info.activityInfo.name : null; Slog.i(TAG, "start package name is " + packageName + ", class name is " + className + ", error code is " + err);//打印: //I/ActivityManager( 506): start package name is com.android.launcher, //class name is com.android.launcher2.Launcher, error code is 0 if (err != ActivityManager.START_SUCCESS) { ...... } final int startAnyPerm = mService.checkPermission( START_ANY_ACTIVITY, callingPid, callingUid);//返回值是PERMISSION_GRANTED final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid, callingUid, aInfo.applicationInfo.uid, aInfo.exported); if (startAnyPerm != PERMISSION_GRANTED && componentPerm != PERMISSION_GRANTED) { ...... } boolean abort = !mService.mIntentFirewall.checkStartActivity(intent, callingUid, callingPid, resolvedType, aInfo.applicationInfo); if (mService.mController != null) { ...... } if (abort) { ...... } ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified, this); if (outActivity != null) {//传进来的参数是null ...... } final ActivityStack stack = getFocusedStack();//mHomeStack if (stack.mResumedActivity == null || stack.mResumedActivity.info.applicationInfo.uid != callingUid) { if (!mService.checkAppSwitchAllowedLocked(callingPid, callingUid, "Activity start")) { ...... } } if (mService.mDidAppSwitch) { // This is the second allowed switch since we stopped switches, // so now just generally allow switches. Use case: user presses // home (switches disabled, switch to home, mDidAppSwitch now true); // user taps a home icon (coming from home so allowed, we hit here // and now allow anyone to switch again). mService.mAppSwitchesAllowedTime = 0; } else { mService.mDidAppSwitch = true; } mService.doPendingActivityLaunchesLocked(false); err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options); if (allPausedActivitiesComplete()) { // If someone asked to have the keyguard dismissed on the next // activity start, but we are not actually doing an activity // switch... just dismiss the keyguard now, because we // probably want to see whatever is behind it. dismissKeyguard(); } return err; }
看一下code中添加的注释。
针对home来分析一下startActivityLocked 如果不是home activity,过程是不一样的。
1)r
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage, intent, resolvedType, aInfo, mService.mConfiguration, resultRecord, resultWho, requestCode, componentSpecified, this);