SystemServer程序在啟動的過程中會啟動PackageManagerService,PackageManagerService啟動後會将系統中的應用程式安裝完成。在此前已經啟動的AMS會将Launcher啟動起來。
Launcher的入口為AMS的systemReady方法
1
ActivityManagerDebugConfig frameworks/base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
這裡首先分享一個技巧 可以把這個類裡面的這個屬性設定為true這樣就可以把ActivityManager相關的log打開了
// Enable all debug log categories.
// static final boolean DEBUG_ALL = false;
static final boolean DEBUG_ALL = true;
2
startOtherServices() frameworks/base/services/java/com/android/server/SystemServer.java
此處是一個Lambda表達式省略的部分是一個回調方法
mActivityManagerService.systemReady(
...
)
3
systemReady() frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
這裡關于EventLog分享一個檢視log的連結https://www.jianshu.com/p/1c9106dd8284
android日志主要分為 kernel、radio、event、main
adb logcat -b xxx
130|generic_x86_64:/ # logcat -b events | grep "3040"
06-02 00:18:02.017 1541 1556 I am_pss : [2069,10015,com.android.launcher,31063040,17305600,0]
06-02 00:22:02.033 1541 1556 I am_pss : [2069,10015,com.android.launcher,31063040,17305600,0]
06-02 04:48:12.311 1541 1556 I am_pss : [2069,10015,com.android.launcher,32285696,18903040,0]
06-02 09:19:17.510 1541 1556 I am_pss : [2069,10015,com.android.launcher,33040384,19652608,0]
06-02 17:51:00.018 1541 1556 I am_pss : [1710,1001,com.android.phone,31703040,20111360,0]
06-02 19:26:00.039 1541 1556 I am_pss : [2069,10015,com.android.launcher,34850816,21463040,0]
public void systemReady(final Runnable goingCallback, TimingsTraceLog traceLog) {
traceLog.traceBegin("PhaseActivityManagerReady");
...
Slog.i(TAG, "System now ready");
EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_AMS_READY,
SystemClock.uptimeMillis());
...
}
關于工廠模式FactoryTest可參考這篇文章 https://blog.csdn.net/thl789/article/details/8053574 這裡是正常模式
...
//判斷工廠模式
synchronized(this) {
// Make sure we have no pre-ready processes sitting around.
if (mFactoryTest == FactoryTest.FACTORY_TEST_LOW_LEVEL)
...
startPersistentApps 隻啟動加密感覺的持久應用程式;一旦使用者被解鎖,我們将傳回并啟動不知情的應用程式可參考這篇文章
https://blog.csdn.net/yaobao888/article/details/77824950
https://www.jianshu.com/p/c9e43905e6b6
https://www.jianshu.com/p/3db7809f231e
...
synchronized (this) {
// Only start up encryption-aware persistent apps; once user is
// unlocked we'll come back around and start unaware apps
startPersistentApps(PackageManager.MATCH_DIRECT_BOOT_AWARE);
...
啟動Launcher
startHomeActivityLocked(currentUserId, "systemReady");
4
startHomeActivityLocked() frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
這裡介紹來自這篇 https://blog.csdn.net/learnframework?spm=1001.2014.3001.5509
這裡看到了startHomeActivityLocked(currentUserId, “systemReady”);被調用,從名字既可以看得出他是要啟動Home類型的Activtiy,常見的Launcher就是一種Home類型的Activity,但這裡其實并不是Launcher,而是設定中的FallbackHome類型的,它也是一個Home類型的Activity,這裡FallbackHome是google新加入的,主要就是因為涉及整個android系統的加密等原因,系統在還沒有完全解鎖前,不可以啟動Launcher,因為Launcher中明顯和各個第三方應用耦合較多(比如桌面可能顯示着一堆的各個應用的Widget),如果直接Launcher作為FallbackHome啟動,相對就會要求Launcher依賴的應用也是支援直接解密類型,那就肯定不現實。是以就先啟動了FallbackHome一個什麼也不顯示的界面來作為啟動真正Launcher的一個過度。
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;
}
Intent intent = getHomeIntent();
...
}
5
getHomeIntent() frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
在這個方法中建立了Intent 并将mTopAction、mTopData傳入,
String mTopAction = Intent.ACTION_MAIN;
和若是系統運作模式不是低級工廠模式則将Intent的Category設定為Intent.CATEGORY_HOME後傳回。
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;
}
6
startHomeActivityLocked() frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
繼續來分析startHomeActivityLocked方法
resolveActivityInfo 此前已經說過,系統在還沒有完全解鎖前,不可以啟動Launcher。是以這裡其實并不是Launcher,而是設定中的FallbackHome類型的,它也是一個Home類型的Activity
ProcessRecord Android系統中用于描述程序的資料結構是ProcessRecord對象,AMS便是管理程序的核心子產品 可以參考https://www.cnblogs.com/mingfeng002/p/10573298.html
此處的ProcessRecord app 應該是設定的包名 此時調用getProcessRecordLocked擷取的就是設定的程序,因為目前android程式還沒有啟動是以這是擷取不到的 app就傳回為null再調用後面的啟動
boolean startHomeActivityLocked(int userId, String reason) {
...
Intent intent = getHomeIntent();
ActivityInfo aInfo = resolveActivityInfo(intent, STOCK_PM_FLAGS, userId);
if (aInfo != null) {
...
ProcessRecord app = getProcessRecordLocked(aInfo.processName,
aInfo.applicationInfo.uid, true);
if (app == null || app.instr == null) {
intent.setFlags(intent.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
final int resolvedUserId = UserHandle.getUserId(aInfo.applicationInfo.uid);
// For ANR debugging to verify if the user activity is the one that actually
// launched.
final String myReason = reason + ":" + userId + ":" + resolvedUserId;
mActivityStarter.startHomeActivityLocked(intent, aInfo, myReason);
}
} else {
Slog.wtf(TAG, "No home screen found for " + intent, new Throwable());
}
return true;
}
7
mActivityStarter.startHomeActivityLocked() frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
這裡目前就調用了startActivityLocked()
void startHomeActivityLocked(Intent intent, ActivityInfo aInfo, String reason) {
mSupervisor.moveHomeStackTaskToTop(reason);
mLastHomeActivityStartResult = 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*/, mLastHomeActivityStartRecord /*outActivity*/,
null /*inTask*/, "startHomeActivity: " + reason);
...
}
}
8
startActivityLocked() frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
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, TaskRecord inTask, String reason) {
...
mLastStartActivityResult = startActivity(caller, intent, ephemeralIntent, resolvedType,
aInfo, rInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode,
callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags,
options, ignoreTargetSecurity, componentSpecified, mLastStartActivityRecord,
inTask);
...
}
9
startActivity() frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
這裡更新一個知識點,frameworks/base/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java的
// Enable all debug log categories.
static final boolean DEBUG_ALL = false; 打開debuglog
ActivityRecord Activity的資訊記錄在ActivityRecord對象, 并通過通過成員變量task指向TaskRecord 可以參考https://blog.csdn.net/b1480521874/article/details/84637592
注意這塊最後調用startActivity的第六個參數為 true
/** DO NOT call this method directly. Use {@link #startActivityLocked} instead. */
private int startActivity(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, TaskRecord inTask) {
...
ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, intent, resolvedType, aInfo, mService.getGlobalConfiguration(),
resultRecord, resultWho, requestCode, componentSpecified, voiceSession != null,
mSupervisor, options, sourceRecord);
if (outActivity != null) {
outActivity[0] = r;
}
...
return startActivity(r, sourceRecord, voiceSession, voiceInteractor, startFlags, true,
options, inTask, outActivity);
}
10
startActivity() frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
顯然這個doResume參數為true 繼續調用startActivityUnchecked
private int startActivity(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
...
result = startActivityUnchecked(r, sourceRecord, voiceSession, voiceInteractor,
startFlags, doResume, options, inTask, outActivity);
...
}
11
startActivityUnchecked() frameworks/base/services/core/java/com/android/server/am/ActivityStarter.java
這裡面調用的setInitialState會将mDoResume這個字段置為 true
接下來調用了mSupervisor.resumeFocusedStackTopActivityLocked
// Note: This method should only be called from {@link startActivity}.
private int startActivityUnchecked(final ActivityRecord r, ActivityRecord sourceRecord,
IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor,
int startFlags, boolean doResume, ActivityOptions options, TaskRecord inTask,
ActivityRecord[] outActivity) {
...
setInitialState(r, options, inTask, doResume, startFlags, sourceRecord, voiceSession,
voiceInteractor);
...
if (mDoResume) {
final ActivityRecord topTaskActivity =
mStartActivity.getTask().topRunningActivityLocked();
if (!mTargetStack.isFocusable()
|| (topTaskActivity != null && topTaskActivity.mTaskOverlay
&& mStartActivity != topTaskActivity)) {
...
} else {
// If the target stack was not previously focusable (previous top running activity
// on that stack was not visible) then any prior calls to move the stack to the
// will not update the focused stack. If starting the new activity now allows the
// task stack to be focusable, then ensure that we now update the focused stack
// accordingly.
if (mTargetStack.isFocusable() && !mSupervisor.isFocusedStack(mTargetStack)) {
mTargetStack.moveToFront("startActivityUnchecked");
}
mSupervisor.resumeFocusedStackTopActivityLocked(mTargetStack, mStartActivity,
mOptions);
}
} else {
...
}
}
12
resumeFocusedStackTopActivityLocked() frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
這塊調用到了targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
boolean resumeFocusedStackTopActivityLocked(
ActivityStack targetStack, ActivityRecord target, ActivityOptions targetOptions) {
...
if (targetStack != null && isFocusedStack(targetStack)) {
return targetStack.resumeTopActivityUncheckedLocked(target, targetOptions);
}
...
return false;
}
13
resumeTopActivityUncheckedLocked() frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
這塊調用到了result = resumeTopActivityInnerLocked(prev, options);
boolean resumeTopActivityUncheckedLocked(ActivityRecord prev, ActivityOptions options) {
...
try {
// Protect against recursion.
mStackSupervisor.inResumeTopActivity = true;
result = resumeTopActivityInnerLocked(prev, options);
} finally {
mStackSupervisor.inResumeTopActivity = false;
}
...
return result;
}
14
resumeTopActivityInnerLocked() frameworks/base/services/core/java/com/android/server/am/ActivityStack.java
由于這塊代碼實在是太多太複雜了 這裡隻給出結論,無論這中間代碼是如何調用的在這個方法的最後打出了一個log
“resumeTopActivityLocked: Restarting” 顯然這裡面最後調用了 mStackSupervisor.startSpecificActivityLocked(next, true, true);
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
...
} else {
// Whoops, need to restart this activity!
if (!next.hasBeenLaunched) {
next.hasBeenLaunched = true;
} else {
if (SHOW_APP_STARTING_PREVIEW) {
next.showStartingWindow(null /* prev */, false /* newTask */,
false /* taskSwich */);
}
if (DEBUG_SWITCH) Slog.v(TAG_SWITCH, "Restarting: " + next);
}
if (DEBUG_STATES) Slog.d(TAG_STATES, "resumeTopActivityLocked: Restarting " + next);
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
}
15
startSpecificActivityLocked() frameworks/base/services/core/java/com/android/server/am/ActivityStackSupervisor.java
此部分代碼程序為空 接下來調用 mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,"activity", r.intent.getComponent(), false, false, true);
注意這個地方倒數第二個參數 isolated 傳遞的為 false
void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
r.getStack().setLaunchTime(r);
if (app != null && app.thread != null) {
...
}
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);
}
16
startProcessLocked() frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
調用自己的重載方法
此時 isolated 為 false
entryPoint 為 null
startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType, hostingName, allowWhileBooting, isolated, 0 , keepIfLarge, null , null , null , null );
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
String hostingType, ComponentName hostingName, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return startProcessLocked(processName, info, knownToBeDead, intentFlags, hostingType,
hostingName, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
17
startProcessLocked() frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
這個方法主要接下來建立程序
isolated 為 false
entryPoint 為 null
最後調用了startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
if (!isolated) {
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
//這裡app還是為null
checkTime(startTime, "startProcess: after getProcessRecord");
if ((intentFlags & Intent.FLAG_FROM_BACKGROUND) != 0) {
...//不走
} else {
// When the user is explicitly starting a process, then clear its
// crash count so that we won't make it bad until they see at
// least one crash dialog again, and make the process good again
// if it had been bad.
if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid
+ "/" + info.processName);
mAppErrors.resetProcessCrashTimeLocked(info);
if (mAppErrors.isBadProcessLocked(info)) {
EventLog.writeEvent(EventLogTags.AM_PROC_GOOD,
UserHandle.getUserId(info.uid), info.uid,
info.processName);
mAppErrors.clearBadProcessLocked(info);
if (app != null) {
app.bad = false;
}
}
}
} else {
...
}
...
if (app == null) {
checkTime(startTime, "startProcess: creating new process record");
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
if (app == null) {
...//不走
}
app.crashHandler = crashHandler;
checkTime(startTime, "startProcess: done creating new process record");
} else {
...//不走
}
...
startProcessLocked(
app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
checkTime(startTime, "startProcess: done starting proc!");
return (app.pid != 0) ? app : null;
}
18
startProcessLocked() frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
entryPoint 為 null
if (entryPoint == null) entryPoint = "android.app.ActivityThread"; 建構啟動參數 這個參數是最後剩下的在Zygote中用來反射調用main函數的
最後調用了這個 Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, entryPointArgs);
注意這個時候把新new出來的ProcessRecord放到mPidsSelfLocked中 this.mPidsSelfLocked.put(startResult.pid, app);
private final void startProcessLocked(ProcessRecord app, String hostingType,
String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
...
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Start proc: " +
app.processName);
checkTime(startTime, "startProcess: asking zygote to start proc");
ProcessStartResult startResult;
if (hostingType.equals("webview_service")) {
...//不走
} else {
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, entryPointArgs);
}
...
synchronized (mPidsSelfLocked) {
this.mPidsSelfLocked.put(startResult.pid, app);
if (isActivityProcess) {
Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);
msg.obj = app;
mHandler.sendMessageDelayed(msg, startResult.usingWrapper
? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);
}
}
}
19
Process.start() frameworks/base/core/java/android/os/Process.java
一眼望去 zygoteProcess.start(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
public static final ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
return zygoteProcess.start(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
}
20
start() frameworks/base/core/java/android/os/ZygoteProcess.java
public final Process.ProcessStartResult start(final String processClass,
final String niceName,
int uid, int gid, int[] gids,
int debugFlags, int mountExternal,
int targetSdkVersion,
String seInfo,
String abi,
String instructionSet,
String appDataDir,
String invokeWith,
String[] zygoteArgs) {
try {
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, zygoteArgs);
} catch (ZygoteStartFailedEx ex) {
Log.e(LOG_TAG,
"Starting VM process through Zygote failed");
throw new RuntimeException(
"Starting VM process through Zygote failed", ex);
}
}