声明:原创文章,转载请备注来源: 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虚拟机执行流程详解
标签:03,启动,APP,ActivityThread,public,Application,app,data,final From: https://www.cnblogs.com/domefy/p/16866473.html