ActivityThread解析之Application與Activity啓動

  • 前言

在看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、ActivityThreadmAppThread對象傳給AMS

上面介紹到了attachApplication方法,那麼接下來看下mAppThread怎麼傳給AMS的。貼上時序圖:

在這裏插入圖片描述

可以看到Activity通過ActivityManagerProxy代理來和AMS通信的。

那麼先看下ActivityManagerNative.getDefault()是怎麼獲取對象的。先進入ActivityManagerNativegetDefault方法,貼上代碼:

	/**
     * 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方法,將appcontext綁定

回到handleBindApplicationmInstrumentation.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機制等等。可以逐漸瞭解。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章