android8.1启动过程 SystemServer启动FallbackHome
Posted we1less
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android8.1启动过程 SystemServer启动FallbackHome相关的知识,希望对你有一定的参考价值。
SystemServer进程在启动的过程中会启动PackageManagerService,PackageManagerService启动后会将系统中的应用程序安装完成。在此前已经启动的AMS会将Launcher启动起来。
Launcher的入口为AMS的systemReady方法
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;
startOtherServices() frameworks/base/services/java/com/android/server/SystemServer.java
此处是一个Lambda表达式省略的部分是一个回调方法
mActivityManagerService.systemReady(
...
)
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");
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();
...
}
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;
}
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;
}
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);
...
}
}
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);
...
}
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);
}
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);
...
}
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 {
...
}
}
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;
}
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;
}
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);
}
}
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);
}
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 /* isolatedUid */, keepIfLarge, null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */, null /* crashHandler */);
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 */);
}
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;
}
startProcessLocked() frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
entryPoint 为 null
最后调用了这个 Process.start(entryPoint, app.processName, uid, uid, gids, debugFlags, mountExternal, app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet, app.info.dataDir, invokeWith, entryPointArgs);
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);
}
...
}
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);
}
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);
}
}
以上是关于android8.1启动过程 SystemServer启动FallbackHome的主要内容,如果未能解决你的问题,请参考以下文章