在看ActivityThread
源碼的時候,看到有博客提到它承擔着整個應用的運轉以及生命週期。於是很好奇想一探究竟,跟着跟着大概就把應用啓動過程過程瞭解了一下。這篇文章主要是介紹ActivityThread
中有關於應用啓動過程以及Activity
啓動部分。有關Binder的機制或者其他部分內容太多了,以後專門看看。
Activity有且只有一個ActivityThread
對象,他是每一個應用程序所在進程的主線程,。先看看主入口方法main
,整個應用的loop死循環是從這邊啓動的。貼上代碼:
public static void main(String[] args) {
...
ActivityThread thread = new ActivityThread();
thread.attach(false);
...
Looper.loop();
throw new RuntimeException("Main thread loop unexpectedly exited");
}
第一部分是ActivityThread
對象執行attach方法。這個是本文要分析的部分,就是他來啓動應用。
第二部分是啓動Looper,這個是整個應用程序的心臟。下一篇文章將分析。
OK!先跟進attach方法看下。貼上代碼:
private void attach(boolean system) {
if (!system) {
final IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
} else {
...
}
...
}
傳入system
值爲false,那麼這裏會進入判斷爲true的代碼塊裏面。其中attachApplication
是啓動Application的方法,也是作爲本文分析流程的入口。
1、ActivityThread
把mAppThread
對象傳給AMS
上面介紹到了attachApplication
方法,那麼接下來看下mAppThread
怎麼傳給AMS的。貼上時序圖:
可以看到Activity通過ActivityManagerProxy
代理來和AMS通信的。
那麼先看下ActivityManagerNative.getDefault()
是怎麼獲取對象的。先進入ActivityManagerNative
的getDefault
方法,貼上代碼:
/**
* Retrieve the system's default/global activity manager.
*/
static public IActivityManager getDefault() {
return gDefault.get();
}
注意到是gDefault
對象的方法,跟進去:
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
IBinder b = ServiceManager.getService("activity");
if (false) {
Log.v("ActivityManager", "default service binder = " + b);
}
IActivityManager am = asInterface(b);
if (false) {
Log.v("ActivityManager", "default service = " + am);
}
return am;
}
};
public abstract class Singleton<T> {
private T mInstance;
protected abstract T create();
public final T get() {
synchronized (this) {
if (mInstance == null) {
mInstance = create();
}
return mInstance;
}
}
}
首先Singleton是一個獲取單例對象的方法。首次調用get()方法就會執行create(),那麼回到gDefault
對象的create()方法看看。
首先是ServiceManager.getService("activity")
。跟進ServiceManager
類源碼看一下:
private static IServiceManager getIServiceManager() {
if (sServiceManager != null) {
return sServiceManager;
} // Find the service manager
sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
return sServiceManager;
}
/**
* Returns a reference to a service with the given name.
*
* @param name the name of the service to get
* @return a reference to the service, or <code>null</code> if the service doesn't exist
*/
public static IBinder getService(String name) {
try {
IBinder service = sCache.get(name);
if (service != null) {
return service;
} else {
return getIServiceManager().getService(name);
}
} catch (RemoteException e) {
Log.e(TAG, "error in getService", e);
}
return null;
}
先看下getIServiceManager()
方法,他返回的sServiceManager
對象(ServiceManagerService
的代理)。ServiceManagerService
不是真實存在的,而是存在於C++層的一個單獨的進程。
那麼getService
就是通過代理獲取String爲activity
的服務的IBinder
對象,其實也就是AMS的IBinder
對象。
現在回到gDefault
方法中。看下asInterface(b)
方法,其中b也就是上面從ServiceManagerService
獲取的IBinder
對象。
現在看下asInterface
方法,貼上代碼:
static public IActivityManager asInterface(IBinder obj) {
if (obj == null) {
return null;
}
IActivityManager in =
(IActivityManager)obj.queryLocalInterface(descriptor);
if (in != null) {
return in;
}
return new ActivityManagerProxy(obj);
}
queryLocalInterface
方法用於檢查obj是否位於本地進程,很明顯前面獲取AMS的IBinder
對象位於另一個進程。那麼asInterface
返回的就是new出來的ActivityManagerProxy
對象了。
到這一步返回到上面的getDefault()
方法,可以知道他實際上返回的是AMS的ActivityManagerProxy
代理對象。也就是說attach方法中的mgr對象其實也就是AMS的代理了。
那麼看下attach方法中的mgr.attachApplication(mAppThread)
,也就是通過代理把mAppThread
參數傳給了AMS。
那到底是傳什麼東西呢?
看看ActivityManagerProxy
源碼:
class ActivityManagerProxy implements IActivityManager
{
...
public void attachApplication(IApplicationThread app) throws RemoteException
{
Parcel data = Parcel.obtain();
Parcel reply = Parcel.obtain();
data.writeInterfaceToken(IActivityManager.descriptor);
data.writeStrongBinder(app.asBinder());
mRemote.transact(ATTACH_APPLICATION_TRANSACTION, data, reply, 0);
reply.readException();
data.recycle();
reply.recycle();
}
}
先是把app
寫入data數據,然後傳給遠程的AMS。然後看下AMS那邊的接收代碼:
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
throws RemoteException{
...
case ATTACH_APPLICATION_TRANSACTION: {
data.enforceInterface(IActivityManager.descriptor);
IApplicationThread app = ApplicationThreadNative.asInterface(
data.readStrongBinder());
if (app != null) {
attachApplication(app);
}
reply.writeNoException();
return true;
}
}
注意到ApplicationThreadNative.asInterface(data.readStrongBinder())
,返回的是ApplicationThread
的代理對象。然後再看下attachApplication(app)
,也就是說AMS這邊其實獲取到的是傳進來的ApplicationThread
參數對象的代理。
2、AMS
通過mAppThread
參數對象創建Application
上面說到mAppThread
作爲傳給了AMS,那麼AMS持有該對象並回調bindApplication
方法。先看下時序圖:
上面講到ActivityThread
通過代理調用了AMS的attachApplication
方法。那麼AMS這邊的attachApplication
方法是怎麼樣的呢?看下源碼:
@Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);
Binder.restoreCallingIdentity(origId);
}
}
thread也就是上面提到的ApplicationThread
的代理對象applicationThread
。重點看下attachApplicationLocked
方法,貼上代碼:
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid){
...
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass,
profilerInfo, app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode,
mBinderTransactionTrackingEnabled, enableTrackAllocation,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat,
getCommonServicesLocked(app.isolated),
mCoreSettingsObserver.getCoreSettingsLocked());
}
也就是說通過這個代理對象執行了bindApplication
方法。那麼ApplicationThreadProxy
是怎麼個邏輯呢?
@Override
public final void bindApplication(String packageName, ApplicationInfo info,
List<ProviderInfo> providers, ComponentName testName, ProfilerInfo profilerInfo,
Bundle testArgs, IInstrumentationWatcher testWatcher,
IUiAutomationConnection uiAutomationConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation, boolean restrictedBackupMode,
boolean persistent, Configuration config, CompatibilityInfo compatInfo,
Map<String, IBinder> services, Bundle coreSettings) throws RemoteException {
Parcel data = Parcel.obtain();
data.writeInterfaceToken(IApplicationThread.descriptor);
...
mRemote.transact(BIND_APPLICATION_TRANSACTION, data, null,
IBinder.FLAG_ONEWAY);
data.recycle();
}
這個是在AMS裏面執行的,也就是把那麼一大堆參數存入data中。再調用mRemote.transact
傳給ActivityThread
。那現在看下ActivityThread
怎麼處理接收到的數據。
case BIND_APPLICATION_TRANSACTION:
{
data.enforceInterface(IApplicationThread.descriptor);
...
bindApplication(packageName, info, providers, testName, profilerInfo, testArgs,testWatcher, uiAutomationConnection, testMode, enableBinderTracking,trackAllocation, restrictedBackupMode, persistent, config, compatInfo, services,coreSettings);
return true;
}
在ActivityThread
中回調bindApplication
方法。因爲傳過去的是ApplicationThread
對象,也就是說調用ApplicationThread
中該方法的實現。貼上代碼:
public final void bindApplication(String processName, ApplicationInfo appInfo,
List<ProviderInfo> providers, ComponentName instrumentationName,
ProfilerInfo profilerInfo, Bundle instrumentationArgs,
IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableBinderTracking, boolean trackAllocation,
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);
}
setCoreSettings(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.enableBinderTracking = enableBinderTracking;
data.trackAllocation = trackAllocation;
data.restrictedBackupMode = isRestrictedBackupMode;
data.persistent = persistent;
data.config = config;
data.compatInfo = compatInfo;
data.initProfilerInfo = profilerInfo;
sendMessage(H.BIND_APPLICATION, data);
}
OK!那就是接收到數據之後,給系統發個Message。系統的Looper接收到信息之後會跳轉到handleBindApplication
方法中。那麼到這邊,ActivityThread
就開始根據AMS返回回來的信息開始創建應用了。
3、Application的創建以及Activity創建
那麼先看下handleBindApplication方法,貼上該方法:
private void handleBindApplication(AppBindData data) {
...
mInstrumentation = (Instrumentation)
cl.loadClass(data.instrumentationName.getClassName())
.newInstance();
...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
...
mInstrumentation.callApplicationOnCreate(app);
...
}
首先是利用反射初始化一個mInstrumentation
對象出來,後續會經常用到。
data.info是AMS傳過來的LoadedApk
對象,那麼下面看下data.info.makeApplication
做了些什麼:
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
if (mApplication != null) {
return mApplication;
}
...
String appClass = mApplicationInfo.className;
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication( cl, appClass, appContext);
...
}
看下newApplication
這個方法:
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;
}
可以看到執行了兩個步驟:
1、通過反射新建了一個Application
對象
2、app
調用attach方法,將app
與context
綁定
回到handleBindApplication
的mInstrumentation.callApplicationOnCreate(app)
方法:
public void callApplicationOnCreate(Application app) {
app.onCreate();
}
OK!mInstrumentation
可以說是一個代理層,最終Apllication
的創建,Activity的創建,以及生命週期都會經過這個對象去執行。個人理解這是代理模式的一個典型例子。
當Application初始化完成後,系統會根據Manifests中的配置的來啓動對應的Activity。本文對這個過程不做介紹,先說下處於ActicityThread
部分。當啓動Activity之後,ActivityThred
的H就收到了一條LAUNCH_ACTIVITY。接收到該Message之後,便會調用到handleLaunchActivity
方法:
private void handleLaunchActivity(ActivityClientRecord r
, Intent customIntent
, String reason) {
...
Activity a = performLaunchActivity(r, customIntent);
...
if (a != null) {
...
handleResumeActivity(r.token
, false
, r.isForward
,!r.activity.mFinished && !r.startsNotResumed
, r.lastProcessedSeq, reason);
...
}
}
首先看下performLaunchActivity
代碼:
private Activity performLaunchActivity(ActivityClientRecord r
, Intent customIntent) {
...
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
...
Application app = r.packageInfo.makeApplication(false, mInstrumentation);
...
activity.attach(appContext
, this
, getInstrumentation()
, r.token
,.ident
, app
, r.intent
, r.activityInfo
, title
, r.parent
, r.embeddedID
, r.lastNonConfigurationInstances
, config
,r.referrer
, r.voiceInteractor
, window);
...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
...
}
先看下mInstrumentation.newActivity
。可以看到Activity也交由mInstrumentation
代理了,下面是代碼。
public Activity newActivity(ClassLoader cl, String className,Intent intent)
throws InstantiationException, IllegalAccessException,ClassNotFoundException {
return (Activity)cl.loadClass(className).newInstance();
}
創建Activity其實也是通過反射直接new出來的。
再看下callActivityOnCreate
方法,也是交給mInstrumentation
處理。他最終會調用Activity的兩個方法:
final void performCreate(Bundle icicle) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
final void performCreate(Bundle icicle, PersistableBundle persistentState) {
restoreHasCurrentPermissionRequest(icicle);
onCreate(icicle, persistentState);
mActivityTransitionState.readState(icicle);
performCreateCommon();
}
這也就是Activity的oncreate
生命週期,至此Activity也跑起來了。
1、應用的啓動過程還涉及到很多東西,比如說Manifest解析,Binder機制等等。可以逐漸瞭解。