共计 30270 个字符,预计需要花费 76 分钟才能阅读完成。
ActivityManagerService,简称 AMS,具备治理 Activity 行为、管制 activity 的生命周期、派发音讯事件、内存治理等性能,AMS 的另外两个重要概念是两大外围性能是 WindowManagerService.java 和 View.java。
剖析 ActivityManagerService 的流程之前须要先下载 Android 的零碎源码,相干下载能够参照上面的文章:中国大陆如何下载 Android 源码
用户从 Launcher 程序点击利用图标可启动利用的入口 Activity,Activity 启动时须要多个过程之间的交互,如下图所示。
其中,AMS 过程实际上是 SystemServer 过程,因为 AMS 只是 SystemServer 启动的一个服务而已,运行在 SystemServer 的某个线程中。
具体的,用户在 Launcher 程序里点击利用图标时,会告诉 ActivityManagerService 启动利用的主 Activity,ActivityManagerService 发现这个利用还未启动,则会告诉 Zygote 过程执行 ActivityThread 的 main 办法。利用过程接下来告诉 ActivityManagerService 利用过程已启动,ActivityManagerService 保留利用过程的一个代理对象,这样 ActivityManagerService 能够通过这个代理对象管制利用过程,而后 ActivityManagerService 告诉利用过程创立主 Activity 的实例,并执行它的生命周期办法,也就是诸如 OnCreadte() 等办法。
Launcher 启动
当点击应用程序图标后,Launcher 应用一个带有 Intent.FLAG_ACTIVITY_NEW_TASK flag 的 Intent,调用 startActivity 办法来启动 App。相干源码如下:
public static Intent makeLaunchIntent(Context context, LauncherActivityInfoCompat info,
UserHandleCompat user) {long serialNumber = UserManagerCompat.getInstance(context).getSerialNumberForUser(user);
return new Intent(Intent.ACTION_MAIN)
.addCategory(Intent.CATEGORY_LAUNCHER)
.setComponent(info.getComponentName())
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
.putExtra(EXTRA_PROFILE, serialNumber);
}
当点击 app 的图标时会执行如下的代码调用流程。
public void onClick(View v) {
...
Object tag = v.getTag();
if (tag instanceof ShortcutInfo) {onClickAppShortcut(v);
}
...
}
protected void onClickAppShortcut(final View v) {
...
// Start activities
startAppShortcutOrInfoActivity(v);
...
}
void startAppShortcutOrInfoActivity(View v) {
...
// 失去 launcher 提供的启动这个 app 主 activity 的 intent
intent = shortcut.intent;
...
boolean success = startActivitySafely(v, intent, tag);
...
}
boolean startActivitySafely(View v, Intent intent, Object tag) {
...
success = startActivity(v, intent, tag);
...
}
private boolean startActivity(View v, Intent intent, Object tag) {intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
...
startActivity(intent, optsBundle);
...
}
从以上代码流程可知当 Launcher 启动一个 app 时,会在本人的 startActivity() 办法中为 Intent 中增加一个 FLAG_ACTIVITY_NEW_TASK flag,而后调用继承自 Activity 的 startActivity() 办法来进一步启动 app。
Activity 向 AMS 发动申请启动 App
Activity 启动 Activity 的流程如下,具体能够查看相干的源码,须要留神的是 Android 6.0 的实现和 8.0 版本实现有稍微的区别。
上面咱们看一下 ActivityThread 类,ActivityThread 类是 Android 利用过程的外围类,这个类蕴含了利用框架中其余重要的类。其源码如下:
public final class ActivityThread {
........
private ContextImpl mSystemContext;
static IPackageManager sPackageManager;
// 保留该 app 中所有的 Activity
final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>();
// 保留该 app 中所有的 service
final ArrayMap<IBinder, Service> mServices = new ArrayMap<>();
// 保留该 app 中所有的 provider
final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap
= new ArrayMap<ProviderKey, ProviderClientRecord>();
// 治理利用的资源
private final ResourcesManager mResourcesManager;
// 存储蕴含代码,即 dex 文件的 apk 文件保留在该变量中
final ArrayMap<String, WeakReference<LoadedApk>> mPackages
= new ArrayMap<String, WeakReference<LoadedApk>>();
// 不蕴含代码,紧紧蕴含资源的 apk 放在该变量中
final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages
// 如果 app 中本人实现了 Application 的子类,并在清单文件中申明了,那么该变量就指向本人实现的那个子类对象
Application mInitialApplication;
AppBindData mBoundApplication;
// 用于 binder 通信,AMS 通过它来调用利用的接口
final ApplicationThread mAppThread = new ApplicationThread();
// 主线程中的 Handler
static Handler sMainThreadHandler; // set once in main()
final Looper mLooper = Looper.myLooper();
// H 继承自 Handler,mH 用来发送和解决 ApplicationThread 通过 binder 承受的 AMS 申请
final H mH = new H();
.........
}
ActivityThread 类中没有定义数据结构来存储 BroadcastReceiver 对象,因为 BroadcastReceiver 对象生命周期很短暂,属于调用一次运行一次的类型,因而不须要保留其对象。AppBindData 类为 ActivityThread 的外部类,定义如下,记录了与之绑定的 app 的相干数据。
static final class AppBindData {
LoadedApk info;
String processName;
ApplicationInfo appInfo;
List<ProviderInfo> providers;
ComponentName instrumentationName;
Bundle instrumentationArgs;
IInstrumentationWatcher instrumentationWatcher;
IUiAutomationConnection instrumentationUiAutomationConnection;
int debugMode;
boolean enableOpenGlTrace;
boolean restrictedBackupMode;
boolean persistent;
Configuration config;
CompatibilityInfo compatInfo;
/** Initial values for {@link Profiler}. */
ProfilerInfo initProfilerInfo;
public String toString() {return "AppBindData{appInfo=" + appInfo + "}";
}
}
其中 ApplicationThread 类型的变量 mAppThread 用于 AMS 所在 app 的接口,利用过程须要调用 AMS 提供的性能,而 AMS 也须要被动调用利用过程以管制利用过程并实现指定操作。ApplicationThread 的运作流程如下图:
如上图可知,AMS 通过 IApplicationThread 接口治理利用过程,ApplicationThread 类实现了 IApplicationThread 接口,实现了治理利用的操作,ApplicationThread 对象运行在利用过程里。ApplicationThreadProxy 对象是 ApplicationThread 对象在 AMS 线程 (AMS 线程运行在 system_server 过程) 内的代理对象,AMS 通过 ApplicationThreadProxy 对象调用 ApplicationThread 提供的性能,比方让利用过程启动某个 Activity。ApplicationThread 中的 scheduleDestroyActivity 的源码如下:
public final void scheduleDestroyActivity(IBinder token, boolean finishing,
int configChanges) {
sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0,
configChanges);
}
而 Binder 服务端的最终调用的是 ActivityThread 的 sendMessage 函数。
private void sendMessage(int what, Object obj, int arg1, int arg2) {sendMessage(what, obj, arg1, arg2, false);
}
private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) {if (DEBUG_MESSAGES) Slog.v(TAG, "SCHEDULE" + what + " " + mH.codeToString(what)
+ ":" + arg1 + "/" + obj);
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
if (async) {msg.setAsynchronous(true);
}
mH.sendMessage(msg);
}
而 ActivityThread 类中外部类 H(继承自 Handler,mH 就是 H 的对象)中则定义了解决音讯的办法,该函数用来解决接管到的数据。
AMS 启动 Activity
后面讲到 AMS 应用 startActivity 启动 APP,为了加深印象在来看一下 startActivity 函数(须要留神的是,6.0 和 8.0 的代码有轻微的区别)。
public final int startActivity(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode, startFlags, profilerInfo, options,
UserHandle.getCallingUserId());
}
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode,
int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) {
// 如果是隔离的利用的话,不容许其关上其余 app 的 activity
// appid 是 99000-99999 之间的属于隔离 app
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,
false, ALLOW_FULL_ONLY, "startActivity", null);
// TODO: Switch to user app stacks here.
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent,
resolvedType, null, null, resultTo, resultWho, requestCode, startFlags,
profilerInfo, null, null, options, false, userId, null, null);
}
判断发起者是否是隔离的 app,不容许隔离的 app 调用其余 app。而后调用 ActivityStackSupervisor 类中的 startActivityMayWait 办法。
final int startActivityMayWait(
IApplicationThread caller,//AMS 通过这个参数能够和发起者进行交互
int callingUid,// 发起者 uid
String callingPackage,// 发起者包名
Intent intent, // 启动 activity 的 intent
String resolvedType, // intent 的类型, 也就是 MIME type
IVoiceInteractionSession voiceSession,
IVoiceInteractor voiceInteractor,
IBinder resultTo,// 用于接管 startActivityForResult 的后果,launcher 启动 app 这种情景下没有用, 为 null
String resultWho,
int requestCode,// 这个是调用者来定义其意义,若值大于等于 0,则 AMS 外部保留该值并通过 onActivityResult 返回调用者, 这里为 -1
int startFlags,// 传入的为 0
ProfilerInfo profilerInfo,
WaitResult outResult,
Configuration config,
Bundle options,
boolean ignoreTargetSecurity,
int userId,
IActivityContainer iContainer, // 传入的为 null
TaskRecord inTask)/ // 传入为 null
{
// Refuse possible leaked file descriptors
if (intent != null && intent.hasFileDescriptors()) {throw new IllegalArgumentException("File descriptors passed in Intent");
}
// 当启动一个 app 时,launcher 会结构一个 intent,后面曾经介绍了,是一个显示的 intent
// 所以这里为 true,boolean componentSpecified = intent.getComponent() != null;
// Don't modify the client's object!
// 创立一个新的 intent,不便改变
intent = new Intent(intent);
// 收集 要启动的 app 的主 activity 的信息
ActivityInfo aInfo =
resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId);
// 传入的该参数为 null
ActivityContainer container = (ActivityContainer)iContainer;
synchronized (mService) {
if (container != null && container.mParentActivity != null &&
container.mParentActivity.state != RESUMED) {
// Cannot start a child activity if the parent is not resumed.
return ActivityManager.START_CANCELED;
}
....................................
final ActivityStack stack;
if (container == null || container.mStack.isOnHomeDisplay()) {stack = mFocusedStack;} else {stack = container.mStack;}
// 传入的 config 为 null
stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0;
if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION,
"Starting activity when config will change =" + stack.mConfigWillChange);
final long origId = Binder.clearCallingIdentity();
if (aInfo != null &&
(aInfo.applicationInfo.privateFlags
&ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) {.......................}
int res = startActivityLocked(caller, intent, resolvedType, aInfo,
voiceSession, voiceInteractor, resultTo, resultWho,
requestCode, callingPid, callingUid, callingPackage,
realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity,
componentSpecified, null, container, inTask);
Binder.restoreCallingIdentity(origId);
if (stack.mConfigWillChange) {.............}
// 传入的为 null
if (outResult != null) {
.......................
mService.wait(); // 期待利用过程的 activity 启动实现
...........
}
.............
}
return res;
}
}
startActivityAsUser() 办法最次要的目地是进行权限查看,查看发起者是否被隔离,是的话,是不容许调用别的 app 的 activity 的。startActivityMayWait() 办法次要是利用传入的 intent 去向 PMS 收集要启动的 APP 的信息,贮存到 aInfo 中.。名字中有 wait 字眼,预示着该办法可能导致线程期待,不过在咱们这个场景中不会呈现这种状况,因为 wait 呈现在对后果的解决中, 咱们这个场景中是不须要处理结果的。
ActivityThread.main
Android APP 的入口类在 ActivityThread 中,有一个 Main 函数,该函数的源码如下:
public static void main(String[] args) {Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
SamplingProfilerIntegration.start();
CloseGuard.setEnabled(false);
// 环境初始化,次要是 app 运行过程中须要应用到的零碎门路
// 比方内部存储门路等等
Environment.initForCurrentUser();
// Set the reporter for event logging in libcore
EventLogger.setReporter(new EventLoggingReporter());
// 减少一个保留 key 的 provider
AndroidKeyStoreProvider.install();
// 为利用社会以后用户的 CA 证书保留的地位
final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
TrustedCertificateStore.setDefaultUserDirectory(configDir);
// 设置 app 过程的名字
// 通过后面的剖析可知,后面的过程中曾经设置过名字了,这里又改为了“pre-initialized”, 不晓得为啥,// 因为前面还要在调用该办法,从新设置过程名字为 app 包名或者 app 指定的名字。Process.setArgV0("<pre-initialized>");
// 创立主线程 looper
Looper.prepareMainLooper();
// 创立 ActivityThread 对象。ActivityThread thread = new ActivityThread();
// 将创立的 ActivityThread 附加到 AMS 中,这样
// AMS 就能够管制这个 app 中组件的生命周期了
thread.attach(false);
if (sMainThreadHandler == null) {sMainThreadHandler = thread.getHandler();
}
if (false) {Looper.myLooper().setMessageLogging(new
LogPrinter(Log.DEBUG, "ActivityThread"));
}
// End of event ActivityThreadMain.
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
//App 主线程开始执行音讯解决循环
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
}
当 ActivityThread 对象创立之后,就开始调用其 attach() 办法,这是一个很重要的办法, 参数为 false 表明是一般 app 过程。
private void attach(boolean system)
{
sCurrentActivityThread = this;
mSystemThread = system;
// app 过程传入 fasle
if (!system) {ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
// mAppThread 是 ApplicationThread 对象;// 上面这个办法会把 mAppThread 放到 RuntimeInit 类中的动态变量 mApplicationObject 中
RuntimeInit.setApplicationObject(mAppThread.asBinder());
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
// 执行 AMS 的 attachApplication 办法
// 将 mAppThread 传入 AMS,这样 AMS 就能够通过它来管制 app 了
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {// Ignore}
// Watch for getting close to heap limit.
BinderInternal.addGcWatcher(new Runnable() {............});
} else {..............}
// add dropbox logging to libcore
DropBox.setReporter(new DropBoxReporter());
ViewRootImpl.addConfigCallback(new ComponentCallbacks2() {.......});
}
其中,RuntimeInit.setApplicationObject 办法源码如下:
public static final void setApplicationObject(IBinder app) {mApplicationObject = app;}
AMS 的 attachApplication 办法
attachApplication 办法次要负责 APP 与 AMS 的绑定操作,该办法的源码如下:
public final void attachApplication(IApplicationThread thread) {synchronized (this) {int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
该办法最终调用了 attachApplicationLocked() 办法。
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {synchronized (mPidsSelfLocked) {// 在创立 startProcessLocked() 办法中调用 Process.start() 办法创立过程后
// 会以接管传递过去的过程号为索引, 将 ProcessRecord 退出到 AMS 的 mPidsSelfLocked 中
// 这里能够以过程号从 mPidsSelfLocked 中拿到 ProcessRecord
app = mPidsSelfLocked.get(pid);
}
} else {app = null;}
if (app == null) {
........
return false;
}
if (app.thread != null) {handleAppDiedLocked(app, true, true);
}
// 注册 app 过程死亡告诉解决机制, 也就是创立监听 app 死亡的对象
// App 过程死亡后, 会调用 AppDeathRecipient.binderDied() 办法
final String processName = app.processName;
try {
AppDeathRecipient adr = new AppDeathRecipient(app, pid, thread);
thread.asBinder().linkToDeath(adr, 0);
app.deathRecipient = adr;
} catch (RemoteException e) {app.resetPackageList(mProcessStats);
startProcessLocked(app, "link fail", processName);
return false;
}
// 调用 ProcessStatsService 开始记录 process 的状态
// 该办法中将 thread 赋值给 app.thread
app.makeActive(thread, mProcessStats);
// 初始化 App 过程优先级等信息
app.curAdj = app.setAdj = -100;
app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
// 移除 PROC_START_TIMEOUT_MSG 音讯
// 后面在 AMS.startProcessLocked 办法中会在调用 Process.start() 办法之后, 将这个音讯放入音讯队列中
// 如果没有在规定的工夫内将该音讯移除音讯队列, 那么会导致过程启动超时
mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);
// mProcessesReady 为 true
boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info);
// 拿到 App 的 provider
List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null;
........
// If the app is being launched for restore or full backup, set it up specially
boolean isRestrictedBackupMode = false;
if (mBackupTarget != null && mBackupAppName.equals(processName)) {isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE)
|| (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL)
|| (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL);
}
// 判断是否须要执行 dex2oat 命令
// 在 app 装置的时候, 会执行一次 dex2oat
// 当生成的 oat 文件被破外或者删除的时候, 须要从新执行 dex2oat
ensurePackageDexOpt(app.instrumentationInfo != null
? app.instrumentationInfo.packageName
: app.info.packageName);
// instrument app 技术先关
// 比方 Android studio 开发时, 批改某些代码时, 没必要重新安装 apk, 即可查看之后的后果
// 后续独自在剖析 instrument 技术
if (app.instrumentationClass != null) {ensurePackageDexOpt(app.instrumentationClass.getPackageName());
}
....
// 调用 ApplicationThread 的 bindApplication 接口
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();} catch (Exception e) {
............
return false;
}
....
boolean badApp = false;
boolean didSomething = false;
// See if the top visible activity is waiting to run in this process...
// 为 true
if (normalMode) {
try {
// 执行 ActivityStackSupervisor.attachApplicationLocked
if (mStackSupervisor.attachApplicationLocked(app)) {didSomething = true;}
} catch (Exception e) {Slog.wtf(TAG, "Exception thrown launching activities in" + app, e);
badApp = true;
}
}
// Find any services that should be running in this process...
if (!badApp) {
try {
// 解决要运行这个过程中的 service
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {Slog.wtf(TAG, "Exception thrown starting services in" + app, e);
badApp = true;
}
}
// Check if a next-broadcast receiver is in this process...
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
// 解决播送
didSomething |= sendPendingBroadcastsLocked(app);
} catch (Exception e) {
// If the app died trying to launch the receiver we declare it 'bad'
Slog.wtf(TAG, "Exception thrown dispatching broadcasts in" + app, e);
badApp = true;
}
}
........
if (!didSomething) {updateOomAdjLocked();
}
return true;
}
attachApplicationLocked 函数比拟长,首先以传入的 app 过程号为索引从 AMS 的 mPidsSelfLocked 中取出 app 过程的 ProcessRecord 对象。而后调用 ProcessRecord 对象的 makeActive 办法调用 ProcessStatsService 开始记录 process 的状态,接着将 PROC_START_TIMEOUT_MSG 音讯, 从音讯循环中移除, 查看是否从新执行 dex2oat 生成 app 的 oat 文件。
该办法次要做了一下四件事件:
- 调用 ActivityThread 的 bindApplication 办法去启动 Application;
- 是调用 ActivityStackSupervisor 的 attachApplicationLocked() 办法去启动 ActivityStack 栈顶的 Activity;
- 是 ActiveServices 调用的 attachApplicationLocked() 办法启动在以后 App 过程中的 service;
- 是查看是否有播送 broadcast 到这个 application,如果有则播送。
其执行的流程图如下图所示:
ApplicationThread.bindApplication 办法
接下来重点剖析下 bindApplication() 办法,这个办法最终成果是调用了 App 的 Application 对象的 onCreate 办法。其源码如下:
public final void bindApplication(
String processName, //ProcessRecord 中记录的过程名字
ApplicationInfo appInfo,
List<ProviderInfo> providers, // app 中的 providers
ComponentName instrumentationName,
ProfilerInfo profilerInfo,
Bundle instrumentationArgs, // 测试相干
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) {if (services != null) {
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
// 发送 SET_CORE_SETTINGS 音讯
// 获取零碎的设定并设置到 ActivityThread 中
setCoreSettings(coreSettings);
// 拿到 PMS
IPackageManager pm = getPackageManager();
android.content.pm.PackageInfo pi = null;
try {
// 以包名从 PMS 中取得 PackageInfo
pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId());
} catch (RemoteException e) { }
if (pi != null) {
// 该 app 是否设置了共享 uid
boolean sharedUserIdSet = (pi.sharedUserId != null);
// app 过程名字是否被设定为与包名不统一
// 默认状况下,app 过程名字就是其包名
// 当显示设置 process name 的时候能够执行过程的名字
boolean processNameNotDefault =
(pi.applicationInfo != null &&
!appInfo.packageName.equals(pi.applicationInfo.processName));
// 如果设置了共享 uid 或者过程名字设置为了其余名字,
// 这就导致该 app 可能运行在一个曾经运行的过程中
boolean sharable = (sharedUserIdSet || processNameNotDefault);
// 如果 app 是独自的过程, 那么要想 VM 注册相干信息
// 是就上就在 /data/dalvik-cache/profiles/ 创立一个以包名为名字的空文件, 另外两个参数没用到
if (!sharable) {
VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir,
appInfo.processName);
}
}
// 创立兵初始化 AppBindData 对象
// 在这里设置了过程名字,app 的 provider,ApplicationInfo
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
// 测试相干
data.instrumentationName = instrumentationName;
data.instrumentationArgs = instrumentationArgs;
data.instrumentationWatcher = instrumentationWatcher;
data.instrumentationUiAutomationConnection = instrumentationUiConnection;
data.debugMode = debugMode;
data.enableOpenGlTrace = enableOpenGlTrace;
// 是否容许 adb backup
data.restrictedBackupMode = isRestrictedBackupMode;
// 过程是否常驻内存, 杀掉后, 会被重启
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
// 发送 BIND_APPLICATION 音讯
sendMessage(H.BIND_APPLICATION, data);
}
bindApplication() 办法要通过 PMS 查看启动的 app 是否设置了共享 uid,以及查看以后 app 过程的名字是否设定的与包名不统一,合乎两者中的任一种状况下, 则阐明该 app 过程可能运行在另一个曾经存在的过程中。
bindApplication() 办法次要是创立和初始化了 AppBindData 对象,并发送两个音讯:一个是 SET_CORE_SETTINGS;另一个是 BIND_APPLICATION。SET_CORE_SETTINGS 次要是获取零碎的设定并设置到 ActivityThread 中。BIND_APPLICATION 用于启动 App 并装置所有的 provider,并回调 App 的 oncreate 办法 BIND_APPLICATION 音讯。
ActivityThread 中解决 BIND_APPLICATION 音讯的办法是 handleBindApplication(),其源码如下:
private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
.......
// 设置过程的名字, 因为后面 ActivityThread.main 将其设置为了 "<pre-initialized>"
Process.setArgV0(data.processName);
// 设置 app 在 ddms 中显示的过程名字
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
// 一般 app 过程, 个别状况下为 false
// 除非 xml 设置 persistent 为 true
// 带有 persistent 标记的过程在低内存设施中部反对应用硬件加速
if (data.persistent) {if (!ActivityManager.isHighEndGfx()) {HardwareRenderer.disable(false);
}
}
if (mProfiler.profileFd != null) {mProfiler.startProfiling();
}
// 依据 app 编译时指定的 sdk 版本与以后零碎 sdk 版本设置 AsyncTask
if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
Message.updateCheckRecycle(data.appInfo.targetSdkVersion);
// 复原时区和地位信息
TimeZone.setDefault(null);
Locale.setDefault(data.config.locale);
// 资源管理初始化设置
mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
mCurDefaultDisplayDpi = data.config.densityDpi;
applyCompatConfiguration(mCurDefaultDisplayDpi);
// 设置 AppBindData 中 LoadedApk info 属性字段
// 这里会依据传入 app 的 ActivityInfo 和 CompatibilityInfo 创立一个 LoadedApk 对象
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
// 如果利用没有指定应用设施的 density, 那么默认应用 mdpi
if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
== 0) {
mDensityCompatMode = true;
Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
}
updateDefaultDensity();
// 创立 ContextImpl 上下文, 外面也设计到了资源管理相干的内容 , 如从 LoadedApk 中提取资源
// 后续还需对其进行初始化
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
// 一般 app 启动时,isIsolated 为 false
if (!Process.isIsolated()) {
// 在沙箱目录中创立 cache 文件夹
final File cacheDir = appContext.getCacheDir();
if (cacheDir != null) {
// 将创立的 cache 文件夹与属性 "java.io.tmpdir" 关联
System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath());
} else {Log.v(TAG, "Unable to initialize \"java.io.tmpdir\"property due to missing cache directory");
}
// Use codeCacheDir to store generated/compiled graphics code
// 在沙箱目录创立 code-cache 文件夹
final File codeCacheDir = appContext.getCodeCacheDir();
if (codeCacheDir != null) {setupGraphicsSupport(data.info, codeCacheDir);
} else {Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory");
}
}
// 设置工夫格局
final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24));
DateFormat.set24HourTimePref(is24Hr);
View.mDebugViewAttributes =
mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0;
// 调试相干
if ((data.appInfo.flags &
(ApplicationInfo.FLAG_SYSTEM |
ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) {StrictMode.conditionallyEnableDebugLogging();
}
if (data.appInfo.targetSdkVersion > 9) {StrictMode.enableDeathOnNetwork();
}
NetworkSecurityPolicy.getInstance().setCleartextTrafficPermitted((data.appInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0);
if (data.debugMode != IApplicationThread.DEBUG_OFF) {............}
// Enable OpenGL tracing if required
if (data.enableOpenGlTrace) {GLUtils.setTracingLevel(1);
}
// Allow application-generated systrace messages if we're debuggable.
boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(appTracingAllowed);
/**
* Initialize the default http proxy in this process for the reasons we set the time zone.
*/
IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
// 设置网络代理
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
} catch (RemoteException e) {}}
// 为 null
if (data.instrumentationName != null) {..........} else {
// 创立 Instrumentation 对象
mInstrumentation = new Instrumentation();}
if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();} else {dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();}
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
try {
// 创立 app 的 Application 对象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
// don't bring up providers in restricted mode; they may depend on the
// app's custom Application class
if (!data.restrictedBackupMode) {
List<ProviderInfo> providers = data.providers;
if (providers != null) {installContentProviders(app, providers);
// For process that contains content providers, we want to
// ensure that the JIT is enabled "at some point".
mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000);
}
}
// Do this after providers, since instrumentation tests generally start their
// test thread at this point, and we don't want that racing.
try {// 执行 instrumentation 的 onCreate() 办法
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {................}
// 执行 Application 的 onCreate 生命周期办法
try {mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {...............}
} finally {StrictMode.setThreadPolicy(savedPolicy);
}
}
handleBindApplication 函数次要实现了如下的一些操作:
- 确定了过程的最终名字, 以及其在 ddms 中显示的过程名字;
- 复原过程的时区和地位信息;
- 调用 getPackageInfoNoCheck() 创立 LoadApk 对象;
- 创立 ContextImpl 对象, 是 AppContext;
- 设置网络代理;
- 创立 Instrumentation 对象。
LoadedApk
LoadedApk 类用来记录形容一个被加载运行的 APK, 的代码、资源等信息。
public final class LoadedApk {
private static final String TAG = "LoadedApk";
private final ActivityThread mActivityThread; // App 的 ActivityThread 对象
private ApplicationInfo mApplicationInfo; // 形容 App 信息的 ApplicationInfo, 如果 App 中重载了 Application 类, 那么其类名会被记录在 ApplicationInfo 中
final String mPackageName;// app 的包名
private final String mAppDir;// app 在 /data/app/< 包名 > 门路
private final String mResDir;// 资源门路
private final String[] mSplitAppDirs;
private final String[] mSplitResDirs;
private final String[] mOverlayDirs;
private final String[] mSharedLibraries;// 共享 java 库
private final String mDataDir;// 数据沙箱目录
private final String mLibDir;// native so 库地位
private final File mDataDirFile;
private final ClassLoader mBaseClassLoader;//getPackageInfoNoCheck() 创立的 LoadedApk 对象中该字段初始化为 null
private final boolean mSecurityViolation;
private final boolean mIncludeCode;// 这个 apk 是否蕴含 dex
private final boolean mRegisterPackage;
private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments();
Resources mResources;
private ClassLoader mClassLoader;//
private Application mApplication;// 这个 app 的 Application 对象, 如果 App 继承了 Application, 那么为其子类对象
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers
= new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers
= new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>();
private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices
= new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices
= new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>();
int mClientCount = 0;
Application getApplication() {return mApplication;}
通过剖析可知,在 handleBindApplication() 办法中通过调用 getPackageInfoNoCheck() 办法创立 LoadedApk 对象。getPackageInfoNoCheck() 的源码如下:
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {return getPackageInfo(ai, compatInfo, null, false, true, false);
}
getPackageInfoNoCheck() 又调用了 getPackageInfo()。
private LoadedApk getPackageInfo(
ApplicationInfo aInfo, // app 的 Application 信息
CompatibilityInfo compatInfo, // 兼容性
ClassLoader baseLoader,// 传入 null
boolean securityViolation,// 传入 false
boolean includeCode,// 传入 true
boolean registerPackage // 传入 false
) {
// 要启动 app 的拥有者与以后零碎用户不统一
final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid));
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (differentUser) {ref = null;} else if (includeCode) {
// 如果蕴含了 dex, 那么从 ActivityThread.mPackages 中先查找是否曾经有了 apk 对应的 LoadedApk
ref = mPackages.get(aInfo.packageName);
} else {
// 如果没有蕴含了 dex, 那么从 ActivityThread.mResourcePackages 中先查找是否曾经有了 apk 对应的 LoadedApk
ref = mResourcePackages.get(aInfo.packageName);
}
// 如果后面曾经从 mPackages 或者 mResourcePackages 中找到了 apk 对应的 LoadedApk, 那么就能够间接返回了
// 没有找到的话, 就要创立 LoadedApk 对象了
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
// 创立 LoadedApk 对象
packageInfo =
new LoadedApk(this, aInfo, compatInfo, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage);
if (mSystemThread && "android".equals(aInfo.packageName)) {
packageInfo.installSystemApplicationInfo(aInfo,
getSystemContext().mPackageInfo.getClassLoader());
}
// 创立 LoadedApk 对象之后, 将其退出对应的缓存列表中
if (differentUser) {// Caching not supported across users} else if (includeCode) {
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
}
}
由以上代码可知,当要获取一个 LoadedApk 对象时,先从 ActivityThread 的两个缓存列表:mPackages 和 mResourcePackages 中寻找,没找到的话才会新建 LoadedApk 对象,而后将其退出对应的缓存列表中。当找到 apk 对应的 LoadedApk 对象后,以此为参数创立 Application 的 Context 对象。
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
return new ContextImpl(null, mainThread,
packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY);
}
private ContextImpl(
ContextImpl container, // 传入 null
ActivityThread mainThread,// app 的 ActivityThread 对象
LoadedApk packageInfo, // apk 对应的 LoadedApk 对象
IBinder activityToken, // 传入为 null
UserHandle user, boolean restricted,
Display display, Configuration overrideConfiguration, int createDisplayWithId) {
mOuterContext = this;
mMainThread = mainThread;
mActivityToken = activityToken;
mRestricted = restricted;
if (user == null) {user = Process.myUserHandle();
}
mUser = user;
// context 中会记录 apk 对应的 LoadedApk 对象
mPackageInfo = packageInfo;
// 资源管理相干, 后续独自开篇介绍
mResourcesManager = ResourcesManager.getInstance();
..............
Resources resources = packageInfo.getResources(mainThread);
if (resources != null) {
if (displayId != Display.DEFAULT_DISPLAY
|| overrideConfiguration != null
|| (compatInfo != null && compatInfo.applicationScale
!= resources.getCompatibilityInfo().applicationScale)) {resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(),
packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(),
packageInfo.getApplicationInfo().sharedLibraryFiles, displayId,
overrideConfiguration, compatInfo);
}
}
mResources = resources;
if (container != null) {
mBasePackageName = container.mBasePackageName;
mOpPackageName = container.mOpPackageName;
} else {
// 记录 app 包名
mBasePackageName = packageInfo.mPackageName;
ApplicationInfo ainfo = packageInfo.getApplicationInfo();
if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) {mOpPackageName = ActivityThread.currentPackageName();
} else {mOpPackageName = mBasePackageName;}
}
// 内容提供者相干
mContentResolver = new ApplicationContentResolver(this, mainThread, user);
}
bindApplication() 办法要害时序图如下:
在这个办法中创立了 Classloader, 以及 Application 对象。而后执行 Application 对象的 attach 办法,这个办法中又会调用 attachBaseContext() 办法。也就是说 Application 对象首先被执行的办法不是 onCreate() 办法,而是 attach() 办法。
attachApplicationLocked
由 ActivityThread.main 的整体执行时序图中可知,启动 activity 的最终是 attachApplicationLocked() 办法。
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
final String processName = app.processName;
boolean didSomething = false;
for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) {ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks;
for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) {final ActivityStack stack = stacks.get(stackNdx);
// 从 如何启动 app 中篇之 Task 的治理 可知, 此时 mFocusedStack 指向行将要运行的 activity 所在的 ActivityStack
// 上面这个办法就是为了从泛滥 ActivityStack 找到这个 ActivityStack
if (!isFrontStack(stack)) {continue;}
// 找到了所需的 ActivityStack
// 而后找到其栈顶的 Activity, 理论就是 mTaskHistory 数组末端的 Task 的顶端 Activity
ActivityRecord hr = stack.topRunningActivityLocked(null);
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {if (realStartActivityLocked(hr, app, true, true)) {didSomething = true;}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity"
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
}
if (!didSomething) {ensureActivitiesVisibleLocked(null, 0);
}
return didSomething;
}
ActivityStackSupervisor 的流程调用关系能够用上面的流程图示意。