AMS和客户进程间的交互之Application的创建过程
Android应用程序的启动入口在ActivityThread的main()函数,在main()函数中创建了ActivityThread的实例对象,并且调用它的attach()去执行应用程序的启动流程,attach()中的工作就是调用ApplicationThread的attachApplication()去创建application,那么就来看看其中具体的过程:
整个过程大致如图:
attachApplication过程
当应用程序启动后,就会报告给AMS,自己已经启动完毕可以启动activity了,这个实际上是通过IPC调用AMS的attachApplication()方法完成的,该方法具体如下:
public final void attachApplication(IApplicationThread thread, long startSeq) {
synchronized (this) {
//1.获取客户进程pid、uid等相关信息
int callingPid = Binder.getCallingPid();
final int callingUid = Binder.getCallingUid();
final long origId = Binder.clearCallingIdentity();
//2.将以上参数传入下面的attachApplicationLocked()方法中
attachApplicationLocked(thread, callingPid, callingUid, startSeq);
Binder.restoreCallingIdentity(origId);
}
}
再来看看具体的attachApplicationLocked()过程;
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid, int callingUid, long startSeq) {
//1.根据客户端进程pid找到ProcessRecord
ProcessRecord app;
long startTime = SystemClock.uptimeMillis();
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
if (app == null && startSeq > 0) {
final ProcessRecord pending = mPendingStarts.get(startSeq);
if (pending != null && pending.startUid == callingUid
&& handleProcessStartedLocked(pending, pid, pending.usingWrapper,
startSeq, true)) {
app = pending;
}
}
/**
* 2.如果上面找不到对应的processRecord对象,那么说明该pid客户进程是一个没有经过AMS
* 允许的“野进程”,因为AMS在启动任何客户端进程前,都已经在内部为未来的进程创建相应的
* ProcessRecord对象,并且在调用Process.startProcess()返回时,将客户进程的pid
* 赋值到了app.pid变量,如果找不到的话,说明它肯定是一个“野进程”。那么就kill了该进
* 程。
**/
if (app == null) {
EventLog.writeEvent(EventLogTags.AM_DROP_PROCESS, pid);
if (pid > 0 && pid != MY_PID) {
killProcessQuiet(pid);
//TODO: killProcessGroup(app.info.uid, pid);
} else {
try {
thread.scheduleExit();
} catch (Exception e) {
// Ignore exceptions.
}
}
return false;
}
// If this application record is still attached to a previous
// process, clean it up now.
if (app.thread != null) {
handleAppDiedLocked(app, true, true);
}
/**
* 3.给app设置binder的死亡代理
**/
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;
}
/**
* 4.给app对象内部的其他相应变量赋值,比如app.thread = thread等。
**/
...
app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj = app.verifiedAdj = ProcessList.INVALID_ADJ;
app.curSchedGroup = app.setSchedGroup = ProcessList.SCHED_GROUP_DEFAULT;
app.forcingToImportant = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
app.killed = false;
....
/**
* 5.确保目标程序APK文件已经被转换成了odex文件,APK文件实际上是一个zip文件,它在安
* 装时辉自动在/data/app目录下产生一个dex文件,这个dex文件是从zip文件中提取的,而
* 为了提高效率,该dex文件在运行前一般都会被系统转换成odex文件,即所谓的Optimized
* dex文件,如果检查到还没有生成odex文件,则先要生成odex文件。
*
**/
//设置是否是debug模式
try {
int testMode = ApplicationThreadConstants.DEBUG_OFF;
if (mDebugApp != null && mDebugApp.equals(processName)) {
testMode = mWaitForDebugger
? ApplicationThreadConstants.DEBUG_WAIT
: ApplicationThreadConstants.DEBUG_ON;
app.debugging = true;
if (mDebugTransient) {
mDebugApp = mOrigDebugApp;
mWaitForDebugger = mOrigWaitForDebugger;
}
}
boolean enableTrackAllocation = false;
if (mTrackAllocationApp != null && mTrackAllocationApp.equals(processName)) {
enableTrackAllocation = true;
mTrackAllocationApp = null;
}
...
/**
* 6.调用thread.bindApplication()方法通知客户进程运行指定的Activity所在的
* APK文件,这个“指定的activity“被包含在了参数app.info中,这个appinfo来源
* 于调用者intent从系统中查询到的Applicationinfo信息
** /
checkTime(startTime, "attachApplicationLocked: immediately before bindApplication");
mStackSupervisor.getActivityMetricsLogger().notifyBindApplication(app);
if (app.isolatedEntryPoint != null) {
thread.runIsolatedEntryPoint(app.isolatedEntryPoint, app.isolatedEntryPointArgs);
} else if (app.instr != null) {
thread.bindApplication(.....);
} else {
thread.bindApplication(....);
}
if (profilerInfo != null) {
profilerInfo.closeFd();
profilerInfo = null;
}
checkTime(startTime, "attachApplicationLocked: immediately after bindApplication");
/**
* 7.通知完毕后,调用updateLruProcess()更新“最新调用的进程列表”。
**/
updateLruProcessLocked(app, false, null);
checkTime(startTime, "attachApplicationLocked: after updateLruProcessLocked");
app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis();
} catch (Exception e) {
app.resetPackageList(mProcessStats);
app.unlinkDeathRecipient();
startProcessLocked(app, "bind fail", processName);
return false;
}
// Remove this record from the list of starting applications.
mPersistentStartingProcesses.remove(app);
mProcessesOnHold.remove(app);
boolean badApp = false;
boolean didSomething = false;
if (normalMode) {
try {
/**
* 8.通过attachApplicationLock()调用realStartActivityLock()通知客
* 户进程运行指定的activity,上一步只是通知目标进程从APK文件中加载
* Application类并运行,但是没有真正的启动指定的Activity,而在这一步才
* 是真正的启动了目标activity。
**/
, if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
badApp = true;
}
}
/**
* 8.查询是否有依赖于目标进程的pendingService或者pendingBroadcast服务,如果有
* 的话,就通知目标进程执行。
*
**/
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
checkTime(startTime, "attachApplicationLocked: after mServices.attachApplicationLocked");
} catch (Exception e) {
badApp = true;
}
}
if (!badApp && isPendingBroadcastProcessLocked(pid)) {
try {
didSomething |= sendPendingBroadcastsLocked(app);
checkTime(startTime, "attachApplicationLocked: after sendPendingBroadcastsLocked");
} catch (Exception e) {
badApp = true;
}
}
.....
return true;
}
应用进程launch指定的Activity
上面attachApplication()执行完,客户进程已经启动,但是它包含的程序文件只是Framework中的ActivityThread基类,这个过程还没有涉及到应用程序本身的任何文件,这个过程类似于LInux程序的启动过程,即首先由操作系统产生一个空进程,然后再通知它去加载具体的要执行程序文件。
那么现在客户进程(空进程)就要根据AMS提供的ApplicationInfo去加载具体的activity了, 注意了,ApplicationInfo是实现了Parcelable的,所以可以在进程间传递数据。上一步中,客户进程向AMS报告自己已经启动,AMS会执行attachApplication(),在这个方法中调用了ActivityThread.ApplicationThread的bindApplication()方法,ApplicationThread本身是一个Binder对象,看看这个方法的具体实现:
public final void bindApplication(String processName, ApplicationInfo appInfo....) {
if (services != null) {
i...
// Setup the service cache in the ServiceManager
ServiceManager.initServiceCache(services);
}
setCoreSettings(coreSettings);
//将待启动的程序信息设置给AppBindData,通过handler发送BIND_APPLICATION信息,接下来handler去处理这个信息。
AppBindData data = new AppBindData();
data.processName = processName;
data.appInfo = appInfo;
data.providers = providers;
data.instrumentationName = instrumentationName;
...
sendMessage(H.BIND_APPLICATION, data);
}
ActivityThread的H(即handler)收到了“BIND_APPLICATION”时,则调用handleBindApplication()去处理这个消息,先看一下大致的流程图:
具体代码如下,这部分代码也是非常长,这里还是选择主干部分代码进行分析:
private void handleBindApplication(AppBindData data) {
... //获取data信息并且设置给profiler
Process.setArgV0(data.processName);
android.ddm.DdmHandleAppName.setAppName(data.processName,
UserHandle.myUserId());
VMRuntime.setProcessPackageName(data.appInfo.packageName);
if (mProfiler.profileFd != null) {
mProfiler.startProfiling();
}
...
//进行版本判断,指定合适的线程池或者图片解码方式
/**
* 1. 重设客户进程时区为系统时区,这个是有必要的, 因为系统时区可能在客户进程启动后
* 改变了,所以需要对进程时区进行重设,否则客户进程有可能不正确。
**/
TimeZone.setDefault(null);
/**
* 重设区域列表,由于所有的应用进程都是从zygote进程复制出来的,zygote本身已经装载
* 了系统资源,不同的区域代表不同的资源内容,而在zygote装在系统资源时,系统区域是默
* 认的,而此时用户有可能已经改变了系统区域,
* 因此需要重新设置区域,当然内部会判断当前区域和默认区域是否一样才决定是否要重新装
* 载。
**/
LocaleList.setDefault(data.config.getLocales());
synchronized (mResourcesManager) {
//因为系统配置是预加载的,如果配置发生了变化就不得知了,所以这里需要更新系统配置。
mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
mCurDefaultDisplayDpi = data.config.densityDpi;
// This calls mResourcesManager so keep it within the synchronized block.
applyCompatConfiguration(mCurDefaultDisplayDpi);
}
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
if (agent != null) {
handleAttachAgent(agent, data.info);
}
.....
//设置像素密度值
//设置时间格式,12小时制或者24小时制
/**
* 2.判断是否是debug模式,那么就show一个debug的弹窗等待用户确认,且允许systrace
* messages文件,可见其实调试时的"waiting for debugger"对话框其实是应用程序本
* 身的一部分,而不是调试时才会有的。
*
if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
// XXX should have option to change the port.
Debug.changeDebugPort(8100);
if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
Slog.w(TAG, "Application " + data.info.getPackageName()
+ " is waiting for the debugger on port 8100...");
IActivityManager mgr = ActivityManager.getService();
try {
mgr.showWaitingForDebugger(mAppThread, true);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
Debug.waitForDebugger();
try {
mgr.showWaitingForDebugger(mAppThread, false);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} else {
Slog.w(TAG, "Application " + data.info.getPackageName()
+ " can be debugged on port 8100...");
}
}
boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
Trace.setAppTracingAllowed(isAppDebuggable);
ThreadedRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
if (isAppDebuggable && data.enableBinderTracking) {
Binder.enableTracing();
}
//接下来给该客户进程初始化默认的http代理。
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies");
final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
if (b != null) {
final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
try {
final ProxyInfo proxyInfo = service.getProxyForNetwork(null);
Proxy.setHttpProxySystemProperty(proxyInfo);
} catch (RemoteException e) {
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
throw e.rethrowFromSystemServer();
}
}
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
// Instrumentation info affects the class loader, so load it before
// setting up the app context.
/**
* 3.这一步的工作主要如下:
* 判断是否应用程序是否存在自定义的Instrumentation,如果存在,则获取类加载器并且加
* 载Instrumentation类,创建实例mInstrumentation;
* 如果没有,则使用默认的Instrumentation去创建实例mInstrumentation。
* 说明:一般情况下应用程序都不会有自定义的Instrumentation类,除非是单元测试
* (UnitTest)模块,Android提供的这个单元测试框架,允许产生一个专门测试应用程序的
* 单元测试APK,这个框架正是利用了自定义的Instrumentation类。使得真正的应用程序
* 在单元测试的“容器”中启动。
*
* 具体如下面代码所示:
**/
final InstrumentationInfo ii;
//首先判断应用程序是否存在data.instrumentationName
if (data.instrumentationName != null) {
try {
ii = new ApplicationPackageManager(null, getPackageManager())
.getInstrumentationInfo(data.instrumentationName, 0);
} catch (PackageManager.NameNotFoundException e) {
throw new RuntimeException(
"Unable to find instrumentation info for: " + data.instrumentationName);
}
.... //检验ABI是否匹配
}
mInstrumentationPackageName = ii.packageName;
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationSplitAppDirs = ii.splitSourceDirs;
mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
mInstrumentedAppDir = data.info.getAppDir();
mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
mInstrumentedLibDir = data.info.getLibDir();
} else {
ii = null;
}
//接着创建了Application的Context实例
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
.....//这里会创建网络安全配置provider,并且更新LocalList等一些相关信息
//然后这里根据是否有自定义的Instrumentation来决定用哪种方式生成instrumentation的实例
if (ii != null) {
//当存在着自定义的nstrumentation时;
ApplicationInfo instrApp;
try {
//从上面的InstrumentationInfo获取ApplicationInfo对象
instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
UserHandle.myUserId());
} catch (RemoteException e) {
instrApp = null;
}
if (instrApp == null) {
instrApp = new ApplicationInfo();
}
ii.copyTo(instrApp);
instrApp.initForUser(UserHandle.myUserId());
final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
final ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
try {
//获取类加载器
final ClassLoader cl = instrContext.getClassLoader();
//加载Instrumentation类并且获取实例mInstrumentation.
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName()).newInstance();
} catch (Exception e) {
throw new RuntimeException(
"Unable to instantiate instrumentation "
+ data.instrumentationName + ": " + e.toString(), e);
}
final ComponentName component = new ComponentName(ii.packageName, ii.name);
//初始化mInstrumentation的成员变量
mInstrumentation.init(this, instrContext, appContext, component,
data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
....
} else {
//当应用程序没有自定义的Instrumentation,那么直接实例化系统默认的就可以了。
mInstrumentation = new Instrumentation();
mInstrumentation.basicInit(this);
}
.....
Application app;
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
try {
/**
* 4.调用LoadApk的makeApplication去创建Application的实例,到这里,我们终
* 于获取到了Application的实例了,同时会创建全局的ApplicationContext对象,
* 可见,Application是应用程序被加载后运行的第一个类,而且在应用程序中唯一。
**/
app = data.info.makeApplication(data.restrictedBackupMode, null);
// Propagate autofill compat state
app.setAutofillCompatibilityEnabled(data.autofillCompatibilityEnabled);
mInitialApplication = app;
/**
* 5.如果应用程序存在着Provider,那么此刻就可以创建并且启动他们了,可见,
* provider会先于activity运行,这时activity还没有创建呢。
**/
....
/**
* 6.此刻,可以通过mInstrumentation去调用Application实例的onCreate()方
* 法了,对Application进行初始化,并真正的开始运行我们的app程序。
**/
try {
mInstrumentation.onCreate(data.instrumentationArgs);
}
catch (Exception e) {
throw new RuntimeException(
"Exception thrown in onCreate() of "
+ data.instrumentationName + ": " + e.toString(), e);
}
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
// If the app targets < O-MR1, or doesn't change the thread policy
// during startup, clobber the policy to maintain behavior of b/36951662
if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
|| StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
StrictMode.setThreadPolicy(savedPolicy);
}
}
.....
}
加载Activity的过程
上面完成了创建Application的工作,接下来,就会调用handleLaunchActivity()来加载指定的activity并且运行,具体代码如下:
public Activity handleLaunchActivity(ActivityClientRecord r,
PendingTransactionActions pendingActions, Intent customIntent) {
/**
* 1.暂停背景运行的内存回收器,该回收器实际上是一个Handler对象,该对象会在系统空闲
* 时接收回收信息,并执行相应的回收函数。
**/
unscheduleGcIdler();
mSomeActivitiesChanged = true;
if (r.profilerInfo != null) {
mProfiler.setProfiler(r.profilerInfo);
mProfiler.startProfiling();
}
// Make sure we are running with the most recent config.
handleConfigurationChanged(null, null);
// Initialize before creating the activity
if (!ThreadedRenderer.sRendererDisabled) {
GraphicsEnvironment.earlyInitEGL();
}
//初始化WMS对象,它也是在Android中交互非常重要的一个对象。
WindowManagerGlobal.initialize();
/**
* 2.调用performLaunchActivity()去加载Activity,也就是说,加载Activity的过程
* 移到了这个方法下面。
**/
final Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
reportSizeConfigurations(r);
if (!r.activity.mFinished && pendingActions != null) {
pendingActions.setOldState(r.state);
pendingActions.setRestoreInstanceState(true);
pendingActions.setCallOnPostCreate(true);
}
} else {
// If there was an error, for any reason, tell the activity manager to stop us.
try {
ActivityManager.getService()
.finishActivity(r.token, Activity.RESULT_CANCELED, null,
Activity.DONT_FINISH_TASK_WITH_ACTIVITY);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
return a;
}
接下来具体看看activity是如何加载的;
![](/qrcode.jpg)
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
ActivityInfo aInfo = r.activityInfo;
if (r.packageInfo == null) {
r.packageInfo = getPackageInfo(aInfo.applicationInfo, r.compatInfo,
Context.CONTEXT_INCLUDE_CODE);
}
/**
* 1.根据传入参数生成一个ComponentName对象,它是application四大组件(Activity、
* Service、BroadcastReceiver、ContentProvider)的标识符,主要包含两个信息:包
* 名和该组件的类名
**/
ComponentName component = r.intent.getComponent();
if (component == null) {
component = r.intent.resolveActivity(
mInitialApplication.getPackageManager());
r.intent.setComponent(component);
}
if (r.activityInfo.targetActivity != null) {
component = new ComponentName(r.activityInfo.packageName,
r.activityInfo.targetActivity);
}
/**
* 2.创建Activity所需的context对象,每一个Activity都包含一个Context对象,
**/
ContextImpl appContext = createBaseContextForActivity(r);
//3.通过类加载器去生成目标activity的实例对象
Activity activity = null;
try {
java.lang.ClassLoader cl = appContext.getClassLoader();
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
r.intent.prepareToEnterProcess();
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to instantiate activity " + component
+ ": " + e.toString(), e);
}
}
try {
//4.获取已经创建好的Application 对象
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
if (activity != null) {
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
if (r.overrideConfig != null) {
config.updateFrom(r.overrideConfig);
}
Window window = null;
if (r.mPendingRemoveWindow != null && r.mPreserveWindow) {
window = r.mPendingRemoveWindow;
r.mPendingRemoveWindow = null;
r.mPendingRemoveWindowManager = null;
}
appContext.setOuterContext(activity);
/**
* 5.调用Activity的attach()方法将context对象赋给Activity 的mBase,
* 同时实例化PhoneWindow,设置各类监听,给各种成员变量例如mToken、
* mApplication、mUiThread等进行赋值
**/
activity.attach(appContext, this, getInstrumentation(), r.token,
r.ident, app, r.intent, r.activityInfo, title, r.parent,
r.embeddedID, r.lastNonConfigurationInstances, config,
r.referrer, r.voiceInteractor, window, r.configCallback);
if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
checkAndBlockForNetworkAccess();
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
/**
* 6.从AndroidManifest.xml中定义的theme中获取主题模式,如果没有的则使
* 用默认的主题模式,再调用setTheme()设置给Activity
**/
if (theme != 0) {
activity.setTheme(theme);
}
activity.mCalled = false;
/**
* 7. 判断是否是Persistable模式(5.0之后的一种更强的保存数据模式,例如
* power off时)然后这里,终于开始回调Activity的onCreate()生命周期
* 了;同时activity中也会调用fragment的生命周期。
**/
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
}
r.setState(ON_CREATE);
/**
* 8.这里要将当前启动的Activity放入 Activity Thread的mActivities存储,注
* 意了,保存的对象是ActivityClientRecord,而不是直接的Activity。
**/
mActivities.put(r.token, r);
} catch (SuperNotCalledException e) {
throw e;
} catch (Exception e) {
if (!mInstrumentation.onException(activity, e)) {
throw new RuntimeException(
"Unable to start activity " + component
+ ": " + e.toString(), e);
}
}
return activity;
}
上面的performLaunchActivity()方法返回之后,继续执行handleResumeActivity(),那么再来看看这个方法内部是如何回调activity的onResume()生命周期的;
Activity的resume()过程
public void handleResumeActivity(IBinder token, boolean finalStateRequest, boolean isForward,
String reason) {
...
/**
* 1.内部调用了performResumeActivity(),这个方法内部就是改变activity的生命周
* 期状态,并且调用activity的onResume()方法,并改变了ActivityRecord的一些
* pause、stopped的状态变量
**/
final ActivityClientRecord r = performResumeActivity(token, finalStateRequest, reason);
if (r == null) {
// We didn't actually resume the activity, so skipping any follow-up actions.
return;
}
final Activity a = r.activity;
....
/**
* 2. 尽管前面所有的步骤中,创建了Application、Activity、并且调用了Activity的
* onCreate()、onResume()方法,但是都还没有通知到WMS,没有完成真正的显示工作,
* 这一步就会去获取activity的window对象,且添加给WMS。
**/
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
l.softInputMode |= forwardBit;
if (r.mPreserveWindow) {
a.mWindowAdded = true;
r.mPreserveWindow = false;
ViewRootImpl impl = decor.getViewRootImpl();
if (impl != null) {
impl.notifyChildRebuilt();
}
}
if (a.mVisibleFromClient) {
if (!a.mWindowAdded) {
a.mWindowAdded = true;
wm.addView(decor, l); //将Activity的DecorView添加到WMS中
} else {
a.onWindowAttributesChanged(l);
}
}
} else if (!willBeVisible) {
if (localLOGV) Slog.v(TAG, "Launch " + r + " mStartedActivity set");
r.hideForNow = true;
}
cleanUpPendingRemoveWindows(r, false /* force */);
if (!r.activity.mFinished && willBeVisible && r.activity.mDecor != null && !r.hideForNow) {
if (r.newConfig != null) {
performConfigurationChangedForActivity(r, r.newConfig);
r.newConfig = null;
}
WindowManager.LayoutParams l = r.window.getAttributes();
if ((l.softInputMode
& WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION)
!= forwardBit) {
l.softInputMode = (l.softInputMode
& (~WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION))
| forwardBit;
if (r.activity.mVisibleFromClient) {
ViewManager wm = a.getWindowManager();
View decor = r.window.getDecorView();
wm.updateViewLayout(decor, l); //调用ViewManager去更新viewLayout.
}
}
r.activity.mVisibleFromServer = true;
mNumVisibleActivities++;
if (r.activity.mVisibleFromClient) {
/**
* 3.这一步调用activity的makeVisible(),内部其实是将DecorView设成
* 可见,到了这一步,用户终于能够看到了Activity的内容了。
**/
r.activity.makeVisible();
}
}
r.nextIdle = mNewActivities;
mNewActivities = r;
/**
* 4.添加一个IdleHandler对象,一般情况下,activity执行完上面步骤后,就进入了空闲
* 状态,所以可以进行内存回收。
**/
Looper.myQueue().addIdleHandler(new Idler());
}
以上就是整个application的创建以及activity的创建和显示过程。