开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第32天,点击查看活动详情
Android系统的桌面叫Launcher,它本身也是一个应用程序,当它被启动时会调用PackageManagerService(系统的包管理服务)返回系统中已经安装的APP,并将启动图标展示在桌面上,用户可以通过点击图标启动应用程序。
1.应用进程的启动
当用户在桌面上点击APP的图标后Launcher会调用startActivitySafely,然后startActivitySafely会进入到startActivity中,接下来的部分就是通过IPC进入到ATMS中,然后在分析启动普通Activity时的ActivityStackSupervisor的startSpecificActivityLocked方法中判断应用程序的进程是否存在
//ActivityStackSupvervisor#startSpecificActivityLocked
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
final WindowProcessController wpc =
mService.getProcessController(r.processName, r.info.applicationInfo.uid);
boolean knownToBeDead = false;
if (wpc != null && wpc.hasThread()) {
try {
//有应用进程就启动activity
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
knownToBeDead = true;
}
...
try {
if (Trace.isTagEnabled(TRACE_TAG_ACTIVITY_MANAGER)) {
Trace.traceBegin(TRACE_TAG_ACTIVITY_MANAGER, "dispatchingStartProcess:"
+ r.processName);
}
// Post message to start process to avoid possible deadlock of calling into AMS with the
// ATMS lock held.
// 上面的wpc != null && wpc.hasThread()不满足的话,说明没有进程,就会去创建进程
final Message msg = PooledLambda.obtainMessage(
ActivityManagerInternal::startProcess, mService.mAmInternal, r.processName,
r.info.applicationInfo, knownToBeDead, "activity", r.intent.getComponent());
mService.mH.sendMessage(msg);
} finally {
Trace.traceEnd(TRACE_TAG_ACTIVITY_MANAGER);
}
}
判断进程是否存在的语句就是if(wpc != null && wpc.hasThread())条件为false时就先创建进程然后再启动Activity,看一下hasThread()的源码
//WindowProcessController
private IApplicationThread mThread;
boolean hasThread() {
return mThread != null;
}
这里的IApplicationThread是ApplicationThread在系统进程中的代理,如果它不为空就说明应用程序已经被启动了。
进程是如何被创建的?
回过头再看ActivityStackSupervisor.startSpecificActivityLocked方法的实现,方法中通过startProcessAsync中的
ActivityTaskManagerService的mH.sendMessage(msg)发送了一条消息。其中这个mH是Handler的子类,发送的msg是ActivityManagerInternal::startProcess,ActivityManagerInternal的实现类是LocalService,在LocalService的startProcess中调用了startProcessLocked,这个方法是AMS的,那么AMS中的startProcessLocked做了什么呢
//ActivityManagerService#startProcessLocked
@GuardedBy("this")
final ProcessRecord startProcessLocked(String processName,
ApplicationInfo info, boolean knownToBeDead, int intentFlags,
HostingRecord hostingRecord, boolean allowWhileBooting,
boolean isolated, boolean keepIfLarge) {
return mProcessList.startProcessLocked(processName, info, knownToBeDead, intentFlags,
hostingRecord, allowWhileBooting, isolated, 0 /* isolatedUid */, keepIfLarge,
null /* ABI override */, null /* entryPoint */, null /* entryPointArgs */,
null /* crashHandler */);
}
然后又调用了ProcessList的startProcessLocked方法,然后内部又调用了startProcessLocked方法并进行了多次重载最终进入到了startProcess
//Processlist#startProcessLocked
@GuardedBy("mService")
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info,
boolean knownToBeDead, int intentFlags, HostingRecord hostingRecord,
boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge,
String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
...
final boolean success = startProcessLocked(app, hostingRecord, abiOverride);
...
return success ? app : null;
}
//Processlist#startProcessLocked
@GuardedBy("mService")
final boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
String abiOverride) {
return startProcessLocked(app, hostingRecord,
false /* disableHiddenApiChecks */, false /* mountExtStorageFull */, abiOverride);
}
//Processlist#startProcessLocked
@GuardedBy("mService")
boolean startProcessLocked(ProcessRecord app, HostingRecord hostingRecord,
boolean disableHiddenApiChecks, boolean mountExtStorageFull,
String abiOverride) {
...
return startProcessLocked(hostingRecord, entryPoint, app, uid, gids,
runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet, invokeWith,
startTime);
...
}
//Processlist#startProcessLocked
//这里最终进入到了startProcess
@GuardedBy("mService")
boolean startProcessLocked(HostingRecord hostingRecord,
String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
if (mService.mConstants.FLAG_PROCESS_START_ASYNC) {
...
final Process.ProcessStartResult startResult = startProcess(app.hostingRecord,
entryPoint, app, app.startUid, gids, runtimeFlags, mountExternal,
app.seInfo, requiredAbi, instructionSet, invokeWith, app.startTime);
...
} else {
...
final Process.ProcessStartResult startResult = startProcess(hostingRecord,
entryPoint, app,
uid, gids, runtimeFlags, mountExternal, seInfo, requiredAbi, instructionSet,
invokeWith, startTime);
...
}
}
//ProcessList# startProcess
private Process.ProcessStartResult startProcess(HostingRecord hostingRecord, String entryPoint,
ProcessRecord app, int uid, int[] gids, int runtimeFlags, int mountExternal,
String seInfo, String requiredAbi, String instructionSet, String invokeWith,
long startTime) {
try {
...
startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, runtimeFlags, mountExternal,
app.info.targetSdkVersion, seInfo, requiredAbi, instructionSet,
app.info.dataDir, invokeWith, app.info.packageName,
new String[] {PROC_START_SEQ_IDENT + app.startSeq});
checkSlow(startTime, "startProcess: returned from zygote!");
return startResult;
} finally {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
}
}
在ProcessList中经过了多次重载的startProcessLocked最终进入了startProcess方法中,而在startProcess方法中最终调用了Process.start方法,源码如下:
//Process#start
public static ProcessStartResult start(@NonNull final String processClass,
@Nullable final String niceName,
int uid, int gid, @Nullable int[] gids,
int runtimeFlags,
int mountExternal,
int targetSdkVersion,
@Nullable String seInfo,
@NonNull String abi,
@Nullable String instructionSet,
@Nullable String appDataDir,
@Nullable String invokeWith,
@Nullable String packageName,
@Nullable String[] zygoteArgs) {
return ZYGOTE_PROCESS.start(processClass, niceName, uid, gid, gids,
runtimeFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, invokeWith, packageName,
/*useUsapPool=*/ true, zygoteArgs);
}
返回值ZYGOTE_PROCESS是用于保持与Zygote进程的通信状态,发送socket请求与Zygote进程通信。Zygote进程是进程孵化器,主要用于创建进程。ZYGOTE_PROCESS.start主要做了以下几件事:
-
- Zygote通过fork创建了一个进程
- 在新建的进程中创建Binder线程池(此进程就支持了Binder IPC)
- 最终是通过反射获取到了ActivityThread类并执行了main方法
(这里要分析《Android进阶解密》第二、三章内容)
2.根Activity的启动
从Android消息机制中可以知道ActivityThread的main方法主要就是开启了主线程的消息循环
final H mH = new H();
public static void main(String[] args) {
...
//1、准备主线程的Looper
Looper.prepareMainLooper();
long startSeq = 0;
if (args != null) {
for (int i = args.length - 1; i >= 0; --i) {
if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
startSeq = Long.parseLong(
args[i].substring(PROC_START_SEQ_IDENT.length()));
}
}
}
//这里实例化ActivityThread,也就实例化了上面的mH,就是handler。
ActivityThread thread = new ActivityThread();
thread.attach(false, startSeq);
//获取handler
if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}
...
//主线程looper开启
Looper.loop();
//因为主线程的Looper是不能退出的,退出就无法接受事件了。一旦意外退出,会抛出异常
throw new RuntimeException("Main thread loop unexpectedly exited");
}
在ActivityThread的main方法中创建了ActivityThread的实例,因为已经知道ApplicationThread是ActivityThread的实例的属性,因此也会创建ApplicationThread的实例,然后调用了attach方法
//ActivityThread#attach
private void attach(boolean system, long startSeq) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManager.getService();
try {
//把ApplicationThread实例关联到AMS中
mgr.attachApplication(mAppThread, startSeq);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
...
}
...
}
这里调用了mgr.attachApplication,其中mgr就是AMS在客户端的代理,所以mgr的attachApplication方法就是IPC走到AMS的attachApplication方法了
//ActivityManagerService#attachApplication
@Override
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
//ActivityManagerService#attachApplicationLocked
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
...
//1、IPC操作,创建绑定Application
thread.bindApplication(processName, appInfo, providers, null, profilerInfo,
null, null, null, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.isPersistent(),
new Configuration(app.getWindowProcessController().getConfiguration()),
app.compat, getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked(),
buildSerial, autofillOptions, contentCaptureOptions);
...
// 2、赋值IApplicationThread
app.makeActive(thread, mProcessStats);
...
// See if the top visible activity is waiting to run in this process...
if (normalMode) {
try {
//3、通过ATMS启动 根activity
didSomething = mAtmInternal.attachApplication(app.getWindowProcessController());
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
...
}
AMS的attachApplicationLocked做了三件事:
-
- 调用IApplicationThread的bindApplication方法,IPC操作,创建并绑定Application
- 给通过makeActive给IApplicationThread赋值
- 通过ATMS启动根Activity
//ProcessRecord#makeActive
public void makeActive(IApplicationThread _thread, ProcessStatsService tracker) {
if (thread == null) {
final ProcessState origBase = baseProcessTracker;
if (origBase != null) {
origBase.setState(ProcessStats.STATE_NOTHING,
tracker.getMemFactorLocked(), SystemClock.uptimeMillis(), pkgList.mPkgList);
for (int ipkg = pkgList.size() - 1; ipkg >= 0; ipkg--) {
StatsLog.write(StatsLog.PROCESS_STATE_CHANGED,
uid, processName, pkgList.keyAt(ipkg),
ActivityManager.processStateAmToProto(ProcessStats.STATE_NOTHING),
pkgList.valueAt(ipkg).appVersion);
}
origBase.makeInactive();
}
baseProcessTracker = tracker.getProcessStateLocked(info.packageName, info.uid,
info.longVersionCode, processName);
baseProcessTracker.makeActive();
for (int i=0; i<pkgList.size(); i++) {
ProcessStats.ProcessStateHolder holder = pkgList.valueAt(i);
if (holder.state != null && holder.state != origBase) {
holder.state.makeInactive();
}
tracker.updateProcessStateHolderLocked(holder, pkgList.keyAt(i), info.uid,
info.longVersionCode, processName);
if (holder.state != baseProcessTracker) {
holder.state.makeActive();
}
}
}
thread = _thread;
mWindowProcessController.setThread(thread);
}
使用mWindowProcessController.setThread(thread)进行了赋值,这样就可以依据IApplicationThread是否为空来判断进程是否已经存在了。
再看一下绑定Application的过程。绑定操作是通过thread.bindApplication完成,IApplicationThread的bindApplication实现的是ApplicationThread的bindApplication方法,然后在ApplicationThread的的bindApplication方法中通过sendMessage(H.BIND_APPLICATION)转移到了ActivityThread的handBindApplication
//ActivityThread#ApplicationThread#bindApplication
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
boolean isRestrictedBackupMode, boolean persistent, Configuration config,
CompatibilityInfo compatInfo, Map services, Bundle coreSettings,
String buildSerial, AutofillOptions autofillOptions,
ContentCaptureOptions contentCaptureOptions) {
...
sendMessage(H.BIND_APPLICATION, data);
}
再进入handlerBindApplication看一下实现
//ActivityThread#handleBindApplication
private void handleBindApplication(AppBindData data) {
...
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi,
appContext.getOpPackageName());
try {
//创建Instrumentation
final ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
}
...
final ComponentName component = new ComponentName(ii.packageName, ii.name);
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
...
//创建Application
app = data.info.makeApplication(data.restrictedBackupMode, null);
...
mInitialApplication = app;
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
...
try {
//内部调用Application的onCreate方法
mInstrumentation.callApplicationOnCreate(app);
}
...
}
这里主要做了一个操作就是创建Application并调用onCreate方法。在前面介绍的ActivityThread的performLaunchActivity方法中,也有同样的操作,只不过会先判断Application是否已存在。也就是说,正常情况下Application的初始化是在handleBindApplication完成的并且是在创建进程后才会调用,在performLauncherActivity中只是做了一个检测,异常情况Application不存在时才会创建。
这里注意一点,创建Application后,内部会attach方法,attach内部会调用attachBaseContext方法,attachBaseContext方法是我们能接触到的一个方法,接着才是onCreate方法。
再回到启动根Activity的逻辑上,在attachApplicationLocked方法中启动根Activity的实现是mAtmInternal.attachApplication方法,mAtmInternal是ActivityManagerInternal的实例,它的具体实现是在ActivityTaskManagerService的LocalService中
@HotPath(caller = HotPath.PROCESS_CHANGE)
@Override
public boolean attachApplication(WindowProcessController wpc) throws RemoteException {
synchronized (mGlobalLockWithoutBoost) {
return mRootActivityContainer.attachApplication(wpc);
}
}
mRootActivityContainer是RootActivityContainer的实例,再看一下attachApplication的方法实现
//RootActivityContainer#attachApplication
boolean attachApplication(WindowProcessController app) throws RemoteException {
final String processName = app.mName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {
final ActivityDisplay display = mActivityDisplays.get(displayNdx);
final ActivityStack stack = display.getFocusedStack();
if (stack != null) {
stack.getAllRunningVisibleActivitiesLocked(mTmpActivityList);
final ActivityRecord top = stack.topRunningActivityLocked();
final int size = mTmpActivityList.size();
for (int i = 0; i < size; i++) {
final ActivityRecord activity = mTmpActivityList.get(i);
if (activity.app == null && app.mUid == activity.info.applicationInfo.uid
&& processName.equals(activity.processName)) {
try {
if (mStackSupervisor.realStartActivityLocked(activity, app,
top == activity /* andResume */, true /* checkConfig */)) {
didSomething = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ top.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {
ensureActivitiesVisible(null, 0, false /* preserve_windows */);
}
return didSomething;
}
遍历Activity栈,理论上这时只有一个Activity,然后调用mStackSupervisor.realStartActivityLocked方法接下来就是进入启动普通Activity的的流程了,即切换线程及消息处理和Activity启动的核心实现。
到此为止启动根Activity的流程也就分析完毕了,启动根Activity和启动普通Activity的流程是一致的,只不过在启动根Activity的流程之前要先创建应用进程然后在ActivityThread的main方法中开启主线程循环,初始化并绑定Application,给IApplicationThread赋值