03-APP的启动过程
声明:原创文章,转载请备注来源: https://shuwoom.com/?p=142
备注:本文的Android源码版版本都是基于Android4.4.3
为了更好地理解APK加壳加固原理,我们需要对APP的启动流程进行分析,同时,我们整理提炼几个关键的问题,解决了下面的几个问题,对APP的启动过程理解和后面实战APK加固都很有帮助。
- APP启动的大概流程?
- 该过程中涉及到的比较重要的类、函数,及其之间的关系?
- 在哪里创建LoadedApk?
- 在哪里创建类加载器?
- 哪里加载dex文件
- 在哪里创建Application对象?
3.1 Android系统启动流程
在讲APP启动过程之前,我们先快速的了解下Android系统的启动流程。Android底层是基于Linux内核的,跟大多数Linux内核系统一样,系统启动时,bootloader先启动加载内核和执行init进程。init进程是系统启动后运行在用户控件的首个进程,如下图所示,init进程的PPID为1。
init进程启动完系统所需的各种守护线程后,接着根据init.rc文件中的配置创建启动Zygote进程。Zygote进程是Android系统中一个相当重要的进程,所有运行应用程序的Dalvik虚拟机都是由Zygote进程创建的,Zygote本身也是一个虚拟机进程。我们可以看到下图中zygote的PPID为52,PPID为1,也就是父进程为init进程。其他一些应用程序,如phone、email、sms、calendar等PPID都是52,也就是他们的父进程都是同一个zygote进程。
Zygote进程会开启一个Socket接口来监听请求,然后通过复制自身快速提供Dalvik虚拟机实例来执行应用程序。在Android中,每一个应用程序都运行着一个Dalvik虚拟机实例,每个Dalvik虚拟机实例都是一个独立的进程空间,这样可以很好的确保应用程序运行的独立性和安全性。
同时,Zygote会启动一个系统服务System Server管理进程,该进程会启动Android所有系统核心服务,包括Activity Manager Service、Package Manager Service等service。到这里,系统就准备好启动第一个APP进程-Home进程,也就是我们常说的Launcher进程。
TODO:参考《Android Dalvik虚拟机结构及机制剖析》第一卷第六章
3.2 几个关键类的关系和用途
在开始分析APP启动流程之前,我们事先了解下述几个在启动过程中比较关键的类:
- ActivityThread
- Application
- Instrumentation
- LoadedApk
- ApplicationLoaders
3.2.1 ActivityThread类
(1) 用途:
一个App启动时会创建一个ActivityThread,它管理着app进程中主线程的执行,其main方法作为app启动的入口。它根据Activity Manager发送的请求,对activities、broadcasts和其他操作进行调度、执行。
(2)关键的成员和方法:
public final class ActivityThread {
//关键成员
final ApplicationThread mAppThread = new ApplicationThread();
final H mH = new H();
Application mInitialApplication;
private static ActivityThread sCurrentActivityThread;
Instrumentation mInstrumentation;
final ArrayMap<String, WeakReference<LoadedApk>> mPackages
= new ArrayMap<String, WeakReference<LoadedApk>>();
…
//关键方法
public static void main(String[] args) { … }
private void attach(boolean system) { … }
public final void bindApplication(String processName,
ApplicationInfo appInfo, List<ProviderInfo> providers,
ComponentName instrumentationName, String profileFile,
ParcelFileDescriptor profileFd, boolean autoStopProfiler,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) { .. }
private void handleBindApplication(AppBindData data) {…}
…
}
3.2.2 Application类
(1) 用途:
通过ActivityThread类的定义我们知道,ActivityThread是单例模式,而且是应用程序的主线程。其中,Application对象mInitialApplication是该类的成员。可见,应用程序中有且仅有一个Application组件,它是全局的单例的。而且Application对象的生命周期跟应用程序的生命周期一样长,从应用启动开始到应用退出结束。
Application跟Activity、Service一样,是Android系统的一个组件,当Android程序启动时会创建一个Application对象,用来存储系统的一些信息。默认情况下,系统会帮我们自动创建一个Application对象,我们也可以在AndroidManifest.xml中指定并创建自己的Application做一些全局初始化的工作。
(2) 关键的成员和方法:
public class Application extends ContextWrapper implements ComponentCallbacks2 {
//关键成员
public LoadedApk mLoadedApk;
…
//关键方法
public void onCreate(){ … }
protected void attachBaseContext(Context base) { ... }
…
}
3.2.3 Instrumentation类
(1) 用途:
同样,通过上面ActivityThread类的源码,我们知道在ActivityThread静态单例模式类中,有一个Instrumentation实例成员mInstrumentation。可见,Instrumentation同样也是全局的单例的。
Instrumentation主要是用来监控系统和应用的交互,并为ActivityThread创建Activity、Application等组件。
(2) 关键的成员和方法:
public class Instrumentation {
//关键成员
private ActivityThread mThread = null;
private Context mInstrContext;
private Context mAppContext;
…
//关键方法
public void callApplicationOnCreate(Application app){ … }
public Application newApplication(ClassLoader cl, String className, Context context){ … }
static public Application newApplication(Class<?> clazz, Context context){ … }
…
}
3.2.4 LoadedApk类
(1)用途:
一个应用程序对应一个LoadedApk对象。它用来保存当前加载的APK包的各种信息,包括app安装路径、资源路径、用户数据保存路径、使用的类加载器、Application信息等。
(2)关键的成员和方法:
public final class LoadedApk {
//关键成员
private final ActivityThread mActivityThread;
private final ClassLoader mBaseClassLoader;
private ClassLoader mClassLoader;
private Application mApplication;
…
//关键方法
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation){…} …
}
3.2.5 ApplicationLoaders类
(1)用途:
获取当前应用程序的类加载器,通过LoadedApk类的getClassLoader方法获取。
(2)关键的成员和方法:
class ApplicationLoaders{
//关键成员
private final ArrayMap<String, ClassLoader> mLoaders =
new ArrayMap<String, ClassLoader>();
private static final ApplicationLoaders gApplicationLoaders =
new ApplicationLoaders(); …
//关键方法
public static ApplicationLoaders getDefault() { … }
public ClassLoader getClassLoader(String zip, String libPath,
ClassLoader parent) { … } …
}
3.3APP启动流程
这里,我们讲解最常见的一种触发启动方式—用户点击启动。
当用户点击桌面上一个APP图标时,这个APP的启动流程大致如下:
(1)点击APP图标,产生Click Event事件;
(2)Launcher程序接收到Click Event事件,调用startActivity(Intent),通过Binder IPC机制调用Activity Manager Service的服务;
(3)Activity Manager Service会调用startProcessLocked方法来创建新的进程;
(4)startProcessLocked方法调用Process类的静态成员函数start来创建这个APP的进程,并指定APP进程的入口函数为android.app.ActivityThread类的静态成员函数main;
(5)main方法成功创建ActivityThread对象后,再调用attach方法完成初始化,然后进入消息循环,直到进程退出;
接下来,我们就通过源码一步步分析上述流程。
3.3.1 指定app的入口方法
我们从startProcessLocked方法开始分析,其关键代码如下:
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
…
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr) {
…
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, null);
…
}
}
可以看到,startProcessLocked方法调用Process类的start方法创建应用程序的进程,并指定android.app.ActivityThread类的main方法为入口函数。
下面我们看ActivityThread类的main方法的定义:
public final class ActivityThread {
… public static void main(String[] args) {
…
Looper.prepareMainLooper();
ActivityThread thread = new ActivityThread();
thread.attach(false);
…
Looper.loop();
… } …
}
main方法首先创建ActivityThread类对象,并调用attach方法完成初始化,然后调用Looper.loop()方法进入消息循环。这里我们看下attach()方法做了哪些初始化工作。
public final class ActivityThread {
…
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
ViewRootImpl.addFirstDrawHandler(new Runnable() {
@Override
public void run() {
ensureJitEnabled();
}
});
android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
UserHandle.myUserId());
RuntimeInit.setApplicationObject(mAppThread.asBinder());
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
}
…
}
…
}
通过上面thread.attach(false)函数调用,我们知道这里传递过来的参数是false,也就是非系统应用。ActivityManagerNative.getDefault()获取的是ActivityManagerService实例,这里,ActivityManagerService对象通过attachApplication绑定ApplicationThread对象mAppThread。这里,我们观察下ApplicationThread类。
ApplicationThread是ActivityThread的内部类,其定义如下:
public final class ActivityThread {
… private class ApplicationThread extends ApplicationThreadNative{ … } …
}
ApplicationThread继承了ApplicationThreadNative抽象类,再看下ApplicationThreadNative的定义:
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread {
…
}
而ApplicationThreadNative抽象类继承了Binder类并实现了IApplicationThread接口。
所以,传递给attach参数的是ApplicationThread类型的Binder对象,它主要的作用是用来进行进程间的通信。
下面进入ActivityManagerService,查看attachApplication方法:
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback { … public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
} …
}
attachApplication调用attachApplicationLocked方法,继续分析:
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
…
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
//创建app对象
ProcessRecord app;
if (pid != MY_PID && pid >= 0) {
synchronized (mPidsSelfLocked) {
app = mPidsSelfLocked.get(pid);
}
} else {
app = null;
}
…
//优化odex文件
ensurePackageDexOpt(app.instrumentationInfo != null =? app.instrumentationInfo.packageName :
app.info.packageName);
…
thread.bindApplication(processName, appInfo, providers,
app.instrumentationClass, profileFile, profileFd, profileAutoStop,
app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());
updateLruProcessLocked(app, false, null);
…
//启动Activity
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app, mHeadless)) {
didSomething = true;
}
} catch (Exception e) {
badApp = true;
}
}
//启动Service
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
badApp = true;
}
}
… } …
}
TODO:新加了内容
通过上面分析,我们知道,传递过来的thread对象是ApplicationThread类型的Binder对象,通过该Binder对象,跨进程调用ActivityThread的bindApplication方法,下面我们回到ActivityThread类。
public final class ActivityThread {
…
public final void bindApplication(String processName,
ApplicationInfo appInfo, List<ProviderInfo> providers,
ComponentName instrumentationName, String profileFile,
ParcelFileDescriptor profileFd, boolean autoStopProfiler,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) {
…
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;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfileFile = profileFile;
data.initProfileFd = profileFd;
data.initAutoStopProfiler = false;
queueOrSendMessage(H.BIND_APPLICATION, data); } …
}
3.3.2 发送BIND_APPLICATION消息并处理
bindApplication方法调用queueOrSendMessage函数发送H.BIND_APPLICATION消息和data数据。queueOrSendMessage方法定义如下:
public final class ActivityThread {
… private void queueOrSendMessage(int what, Object obj) {
queueOrSendMessage(what, obj, 0, 0);
}
private void queueOrSendMessage(int what, Object obj, int arg1) {
queueOrSendMessage(what, obj, arg1, 0);
}
private void queueOrSendMessage(int what, Object obj, int arg1, int arg2) {
synchronized (this) {
…
Message msg = Message.obtain();
msg.what = what;
msg.obj = obj;
msg.arg1 = arg1;
msg.arg2 = arg2;
mH.sendMessage(msg);
} } …
}
queueOrSendMessage最终调用queueOrSendMessage(int what, Object obj, int arg1, int arg2)方法,并调用mH对象发送消息,这里msg.what = H.BIND_APPLICATION。我们调到ActivityThread的内部类H:
public final class ActivityThread {
…
private class H extends Handler {
public static final int LAUNCH_ACTIVITY = 100;
public static final int PAUSE_ACTIVITY = 101;
public static final int PAUSE_ACTIVITY_FINISHING= 102;
public static final int STOP_ACTIVITY_SHOW = 103;
public static final int STOP_ACTIVITY_HIDE = 104;
public static final int SHOW_WINDOW = 105;
public static final int HIDE_WINDOW = 106;
public static final int RESUME_ACTIVITY = 107;
public static final int SEND_RESULT = 108;
public static final int DESTROY_ACTIVITY = 109;
public static final int BIND_APPLICATION = 110;
…
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY : {…} break;
case RELAUNCH_ACTIVITY : {…} break;
…
case BIND_APPLICATION:
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "bindApplication");
AppBindData data = (AppBindData)msg.obj;
handleBindApplication(data);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
break;
…
}
}
…
}
…
}
我们可以看到,H对象接收并处理各种消息,包括启动、暂停、关闭各个组件等操作。
上面,我们知道mH发送的是BIND_APPLICATION的消息,mH对象收到消息后,调用handleBindApplication对象处理传递过来的data对象数据。这个是app启动过程中最关键的方法。在这个方法里,有几个比较重要的操作跟加固相关:
- 创建LoadedApk对象
- 获取类加载器加载apk
- 创建Application对象
我们看下handleBindApplication方法具体做了些什么。
public final class ActivityThread {
…
private void handleBindApplication(AppBindData data) {
mBoundApplication = data;
…
//创建LoadedApk对象
data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
…
final ContextImpl appContext = new ContextImpl();
appContext.init(data.info, null, this);
…
//创建Application对象
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
…
//启动app
mInstrumentation.callApplicationOnCreate(app);
…
}
…
}
3.3.3 创建LoadedApk对象
handleBindApplication方法首先通过getPackageInfoNoCheck函数创建,而getPackageInfoNoCheck内部又调用getPackageInfo完成实际的LoadedApk创建工作。
public final class ActivityThread {
…
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai,
CompatibilityInfo compatInfo) {
return getPackageInfo(ai, compatInfo, null, false, true);
}
…
private LoadedApk getPackageInfo(ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, boolean includeCode) {
synchronized (mResourcesManager) {
WeakReference<LoadedApk> ref;
if (includeCode) {
ref = mPackages.get(aInfo.packageName);
} else {
ref = mResourcePackages.get(aInfo.packageName);
}
LoadedApk packageInfo = ref != null ? ref.get() : null;
if (packageInfo == null || (packageInfo.mResources != null
&& !packageInfo.mResources.getAssets().isUpToDate())) {
…
//创建LoadedApk对象
packageInfo = new LoadedApk(this, aInfo, compatInfo, this, baseLoader,
securityViolation, includeCode &&
(aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0);
if (includeCode) {
//添加到mPackages列表中
mPackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
} else {
mResourcePackages.put(aInfo.packageName,
new WeakReference<LoadedApk>(packageInfo));
}
}
return packageInfo;
}
}
…
}
这里,由于LoadedApk是第一次创建,所以ref为空,需要创建LoadedApk对象并添加到mPackages列表中。最后,通过getPackageInfoNoCheck方法,返回LoadedApk对象。我们接着看data.info.makeApplication方法。这里data.info就是getPackageInfoNoCheck返回的LoadedApk对象。
public final class LoadedApk {
…
public Application makeApplication(boolean forceDefaultAppClass, Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
Application app = null;
//Application类的完整包名
String appClass = mApplicationInfo.className;
if (forceDefaultAppClass || (appClass == null)) {
appClass = "android.app.Application";
}
try {
//获取类加载器
java.lang.ClassLoader cl = getClassLoader();
ContextImpl appContext = new ContextImpl();
appContext.init(this, null, mActivityThread);
//创建Application对象
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
appContext.setOuterContext(app);
} catch (Exception e) {
…
}
mActivityThread.mAllApplications.add(app);
mApplication = app;
…
return app;
}…
}
3.3.4 创建PathClassLoader加载dex
makeApplication调用getClassLoader给应用程序创建类加载器.
public final class LoadedApk{
public ClassLoader getClassLoader() {
synchronized (this) {
if (mClassLoader != null) {
return mClassLoader;
}
//第三方应用程序
if (mIncludeCode && !mPackageName.equals("android")) {
String zip = mAppDir;
String libraryPath = mLibDir;
String instrumentationAppDir = mActivityThread.mInstrumentationAppDir;
String instrumentationAppLibraryDir = mActivityThread.mInstrumentationAppLibraryDir;
String instrumentationAppPackage = mActivityThread.mInstrumentationAppPackage;
String instrumentedAppDir = mActivityThread.mInstrumentedAppDir;
String instrumentedAppLibraryDir = mActivityThread.mInstrumentedAppLibraryDir;
String[] instrumentationLibs = null;
if (mAppDir.equals(instrumentationAppDir)
|| mAppDir.equals(instrumentedAppDir)) {
zip = instrumentationAppDir + ":" + instrumentedAppDir;
libraryPath = instrumentationAppLibraryDir + ":" + instrumentedAppLibraryDir;
if (! instrumentedAppDir.equals(instrumentationAppDir)) {
instrumentationLibs =
getLibrariesFor(instrumentationAppPackage);
}
}
if ((mSharedLibraries != null) || (instrumentationLibs != null)) {
zip = combineLibs(mSharedLibraries, instrumentationLibs) + ':' + zip;
}
…
mClassLoader = ApplicationLoaders.getDefault().getClassLoader(
zip, libraryPath, mBaseClassLoader);
…
} else {
//系统应用程序
if (mBaseClassLoader == null) {
mClassLoader = ClassLoader.getSystemClassLoader();
} else {
mClassLoader = mBaseClassLoader;
}
}
return mClassLoader;
}
}
}
这里,由于我们是第一次调用getClassLoader方法,所以,mClassLoader为null。同时,我们的包名是属于第三方应用的包,且mIncludeCode为true。此时进入第一个if条件。所以,这里,调用ApplicationLoaders.getDefault().getClassLoader获取。我们看下ApplicationLoaders下的getClassLoader方法:
class ApplicationLoaders{
public ClassLoader getClassLoader(String zip, String libPath, ClassLoader parent){
//父类加载器为BootClassLoader
ClassLoader baseParent = ClassLoader.getSystemClassLoader().getParent();
synchronized (mLoaders) {
if (parent == null) {
parent = baseParent;
}
if (parent == baseParent) {
ClassLoader loader = mLoaders.get(zip);
if (loader != null) {
return loader;
}
…
PathClassLoader pathClassloader = new PathClassLoader(zip, libPath, parent);
…
mLoaders.put(zip, pathClassloader);
return pathClassloader;
}
…
PathClassLoader pathClassloader = new PathClassLoader(zip, parent);
…
return pathClassloader;
}
}
}
也就是说,当parent 为null时,设置parent为BootClassLoader,即设置父类加载器为BootClassLoader。否则,当parent==baseParent,如果mLoaders列表中已存在该类的类加载器,则返回,否则就调用下面的代码创建一个给该apk创建新的PathClassLoader加载器,并将app的目录名和对应的类加载器添加到mLoaders列表中。
PathClassLoader pathClassloader = new PathClassLoader(zip, libPath, parent);
我们知道Android加载Dex文件有两个方法,分别是DexClassLoader和PathClassLoader类加载器。
两者的区别是,DexClassLoader可以加载外部的Dex文件,而PathClassLoader只能加载已经安装了的apk的dex文件。到这里,我们就知道,dex文件的加载解析工作就发生在PathClassLoader类加载其中。我们会在第五章“Dalvik加载和解析dex过程”详细分析这一过程。
我们可以创建一个Android工程验证一下上面的结论:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.v("loader", getClassLoader().toString());
Log.v("loader", getClassLoader().getParent().toString());
}
}
可以看到输出日志为:
也就是说应用程序的类加载器是PathClassLoader类型,其父加载器是BootClassLoader,跟我们上面分析的一样。
通过这一节内容,我们就知道了解了Android应用程序的类加载器的来源和流程,以及应用程序的类是如加载进来的。
3.3.5 创建Application对象
我们接着回到makeApplication方法中,当获取到应用程序的类加载器后,接着就是调用mActivityThread.mInstrumentation.newApplication方法创建Application对象。也就是说,实际的Application创建工作时交给Instrumentation对象完成。
public class Instrumentation {
…
public Application newApplication(ClassLoader cl, String className, Context context)
throws InstantiationException,
IllegalAccessException,
ClassNotFoundException {
return newApplication(cl.loadClass(className), context);
}
static public Application newApplication(Class<?> clazz, Context context)
throws InstantiationException,
IllegalAccessException,
ClassNotFoundException {
Application app = (Application)clazz.newInstance();
app.attach(context);
return app;
} …
}
newApplication用我们上一步获取的类加载器PathClassLoader来加载Application类(没有指明Application,则加载系统默认的Appli类,否则加载自定义的的Application类),并调用另一个版本的newApplication。
在该方法中,通过上一步加载获取的字节码创建Application类的实例对象,并调用attach方法绑定context,到这里我们就完成了Application类对象的创建。
3.3.6 启动Activity
完成Application对象的创建后,我们回到ActivityManagerService类中的attachApplicationLocked方法中。最后,程序通过调用mStackSupervisor类对象的attachApplicationLocked方法启动Activity。
位置:Android源码/framework/base/services/java/com/android/server/am/ActivityStackSupervisor.java
boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
boolean didSomething = false;
final String processName = app.processName;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
if (!isFrontStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked(null);
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (headless) {
…
} else if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (Exception e) {
…
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0);
}
return didSomething;
}
这里调用了realStartActivityLocked方法:
位置:Android源码/framework/base/services/java/com/android/server/am/ActivityStackSupervisor.java
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)throws RemoteException {
r.startFreezingScreenLocked(app, 0);
if (false) Slog.d(TAG, "realStartActivity: setting app visibility true");
mWindowManager.setAppVisibility(r.appToken, true);
…
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new Configuration(mService.mConfiguration), r.compat,
app.repProcState, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
…
}
TODO:补充说明
app.thread调用schedulelaunchActivity方法通过Binder机制进入到ApplicationThread类的schedulelaunchActivity方法。
位置:Android源码\frameworks\base\core\java\android\app\ActivityThread.java
public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,
ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,
int procState, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,
String profileName, ParcelFileDescriptor profileFd, boolean autoStopProfiler) {
updateProcessState(procState, false);
ActivityClientRecord r = new ActivityClientRecord();
…
queueOrSendMessage(H.LAUNCH_ACTIVITY, r);
}
这里跟3.3.2一样调用queueOrSendMessage方法发送LAUNCH_ACTIVITY的消息。我们回到handleMessage方法怎么处理。
public void handleMessage(Message msg) {
switch (msg.what) {
case LAUNCH_ACTIVITY: {
Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "activityStart");
ActivityClientRecord r = (ActivityClientRecord)msg.obj;
r.packageInfo = getPackageInfoNoCheck(
r.activityInfo.applicationInfo, r.compatInfo);
handleLaunchActivity(r, null);
Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
} break;
…
}
}
…
}
这里最终调用了handleLaunchActivity方法完成Activity的启动。
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
…
Activity a = performLaunchActivity(r, customIntent);
…
handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed);
…
}
handleLaunchActivity方法调用performLaunchActivity创建Activity对象并调用OnCreate方法。完成对象创建后,调用handleResumeActivity调用OnResume方法,跟Activity生命周期一致,如下图。
我们进入performLaunchActivity方法:
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
…
Activity activity = null;
try {
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity( cl, component.getClassName(), r.intent);
StrictMode.incrementExpectedActivityCount(activity.getClass());
r.intent.setExtrasClassLoader(cl);
if (r.state != null) {
r.state.setClassLoader(cl);
}
} catch (Exception e) {
…
}
…
mInstrumentation.callActivityOnCreate(activity, r.state);
…
}
可以最终创建Activity的是Instrumentation类对象,它调用newActivity方法创建并返回Activity对象。
在创建完Activity对象后,调用callActivityOnCreate方法启动Activity。到此完成了Activity的启动。
我们看下newActivity方法做了些什么。
位置:
public Activity newActivity(ClassLoader cl, String className,Intent intent)
throws InstantiationException, IllegalAccessException,ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
我们看到newActivity方法是通过调用类加载器加载具体的类的。关于Dalvik加载类方法的过程我们会在第六章详细讲解。
参考:
[1]《Android系统源代码情景分析》第12章 Android应用程序进程的启动过程。罗升阳著。.
[2] [Android Application启动流程分析http://www.jianshu.com/p/a5532ecc8377
[3] Android应用的启动过程分析(强烈推荐) http://www.jianshu.com/p/a1f40b39b3de
[4] Android Context是什么?http://blog.csdn.net/feiduclear_up/article/details/47356289
[5] Android ActivityThread(主线程或UI线程)简介 http://blog.csdn.net/myarrow/article/details/14223493
[6] Android Application介绍 http://www.ctolib.com/topics/73986.html
[7] App’s ClassLoader的来源 http://whataa.github.io/2016/10/31/App's%20ClassLoader%E7%9A%84%E6%9D%A5%E6%BA%90/
[8] Android中Hook Instrumentation的一些思考 http://blog.csdn.net/shifuhetudi/article/details/52078445
[9]【Android源码-AMS】(一)Instrumentation类解析 http://blog.csdn.net/nemo__/article/details/50528249
[10] Android应用程序启动过程源代码分析 http://blog.csdn.net/luoshengyang/article/details/6689748
[11] Android应用程序进程启动过程的源代码分析http://blog.csdn.net/luoshengyang/article/details/6747696
[12] Android Application启动流程分析 http://www.jianshu.com/p/a5532ecc8377
[13]《Android Dalvik虚拟机结构及机制剖析》-第一卷 第六章Dalvik虚拟机执行流程详解

浙公网安备 33010602011771号