最近看腾讯开源的插件化框架shadow,发现宿主的Activity容器配置了
android:multiprocess="true" 这个属性有什么作用?
<activity
android:name="com.tencent.shadow.sample.plugin.runtime.PluginDefaultProxyActivity"
android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation|screenSize|smallestScreenSize|layoutDirection"
android:hardwareAccelerated="true"
android:launchMode="standard"
android:multiprocess="true"
android:screenOrientation="portrait"
android:theme="@style/troop_Transparent" />
让我们看一下系统源码:
系统在安装APK时会扫描解析AndroidManifest.解析组件,PackageParser.parseActivity 方法解析逻辑,得到一个标记位,保存在ActivityInfo的flags标记位里。如果android:multiprocess=true,那么对应标志位就置为1
if (sa.getBoolean(
R.styleable.AndroidManifestActivity_multiprocess, false)) {
a.info.flags |= ActivityInfo.FLAG_MULTIPROCESS;
}
Activity启动流程ActivityTaskManagerService.startActivity=> ActivityTaskManagerService.startActivityAsUser
=>ActivityStarter.execute => ActivityStarter.executeRequest
此方法内部通过PMS的resolveIntent得到 ResolveInfo,进而得到安装扫描好的ActivityInfo
并传入ActivityInfo为新启动的Activity创建系统侧的ActivityRecord
final ActivityRecord r = new ActivityRecord(mService, callerApp, callingPid, callingUid,
callingPackage, callingFeatureId, intent, resolvedType, aInfo,
mService.getGlobalConfiguration(), resultRecord, resultWho, requestCode,
request.componentSpecified, voiceSession != null, mSupervisor, checkedOptions,
sourceRecord);
mLastStartActivityRecord = r;
ActivityRecord 构造函数关键代码,这里就是android:multiprocess=true的起作用地方了,
如果ActivityInfo的flag存在FLAG_MULTIPROCESS标记位,也是android:multiprocess=true,并且
调用进程存在,并且调用进程uid和组件的uid相同,那么这个activity就归属于调用进程。
反之则属于 android:process="xxxxx" 这个属性声明的进程,如果未声明则是默认使用包名为进程名。
ActivityRecord(ActivityTaskManagerService _service, WindowProcessController _caller,
int _launchedFromPid, int _launchedFromUid, String _launchedFromPackage,
@Nullable String _launchedFromFeature, Intent _intent, String _resolvedType,
ActivityInfo aInfo, Configuration _configuration, ActivityRecord _resultTo,
String _resultWho, int _reqCode, boolean _componentSpecified,
boolean _rootVoiceInteraction, ActivityStackSupervisor supervisor,
ActivityOptions options, ActivityRecord sourceRecord) {
..........................
if ((aInfo.flags & FLAG_MULTIPROCESS) != 0 && _caller != null
&& (aInfo.applicationInfo.uid == SYSTEM_UID
|| aInfo.applicationInfo.uid == _caller.mInfo.uid)) {
processName = _caller.mName;
} else {
processName = aInfo.processName;
}
..........................
}
在创建ActvitiyRecord后,加入任务栈中,然后执行ActivityStack.resumeTopActivityInnerLocked
ActivityStack
private boolean resumeTopActivityInnerLocked(ActivityRecord prev, ActivityOptions options) {
if (next.attachedToProcess()) {
...
...
} 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.startSpecificActivity(next, true, true);
}
ActivityStackSupervisor执行启动应用进程activity创建和生命周期逻辑,这里关键代码根据ActivityRecord的processName取到对应的进程WindowProcessController,其内部有IApplicationThread mThread,应用的binder,用于去执行应用端的相关组件操作。
ActivityStackSupervisor类中方法
void startSpecificActivity(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 {
realStartActivityLocked(r, wpc, andResume, checkConfig);
return;
} catch (RemoteException e) {
Slog.w(TAG, "Exception when starting activity "
+ r.intent.getComponent().flattenToShortString(), e);
}
// If a dead object exception was thrown -- fall through to
// restart the application.
knownToBeDead = true;
}
r.notifyUnknownVisibilityLaunchedForKeyguardTransition();
final boolean isTop = andResume && r.isTopRunningActivity();
mService.startProcessAsync(r, knownToBeDead, isTop, isTop ? "top-activity" : "activity");
}
综上:multiprocess 这个属性决定了ActivityRecord.processName的是那个,processName则对应了WindowProcessController里面的IApplicationThread是那个,这个IApplicationThread是一个binder,属于客户端应用进程发布给ActivityMangerService管理,用来远程操作应用进程执行组件的创建,生命周期回调。
总结:
1、Activity配置android:multiprocess="true" ,调用进程uid和组件的uid相同(一个应用的不同进程uid是相同的)则Activity跑在调用进程里面,调用进程是谁,他就跑在那个进程里,换句话说 Activity 可以跑在不同进程里面
2、Activity配置android:multiprocess="false" ,另外不配置也是false,则Activity跑在清单文件配置的进程里(android:process="xxxx"),如果没有指定process,则跑在应用包名进程也就是应用的主进程里,换句话说 Activity 只能跑在一个进程里,因为进程名限定死了,没配置进程名则是包名。