以下內容為原創,歡迎轉載,轉載請注明
來自天天博客:http://www.cnblogs.com/tiantianbyconan/p/5017056.html
從Launcher開始啟動App流程源碼分析
com.android.launcher.Launcher
就是我們的Launcher頁面了,可以看到Launcher其實也是一個Activity
:
public final class Launcher extends Activity implements View.OnClickListener, OnLongClickListener {
// ...
}
既然是Activity
,那當然也會有onCreate
、onResume
等生命周期了,按照邏輯,應該會去加載所有App,以網格的布局顯示在頁面上,果然,在onResume
看到了這個方法:
@Override
protected void onResume() {
super.onResume();
if (mRestoring) {
startLoaders();
}
// ...
}
看方法名就可以猜到這個方法就是用來加載所有App信息的,進入這個方法:
private void startLoaders() {
boolean loadApplications = sModel.loadApplications(true, this, mLocaleChanged);
sModel.loadUserItems(!mLocaleChanged, this, mLocaleChanged, loadApplications);
mRestoring = false;
}
這里調用sModel
(LauncherModel
類型)的loadUserItems
方法去加載數據了,sModel
明顯屬於Model
層,進入loadUserItems
方法:
void loadUserItems(boolean isLaunching, Launcher launcher, boolean localeChanged,
boolean loadApplications) {
// ...
mDesktopItemsLoaded = false;
mDesktopItemsLoader = new DesktopItemsLoader(launcher, localeChanged, loadApplications,
isLaunching);
mDesktopLoaderThread = new Thread(mDesktopItemsLoader, "Desktop Items Loader");
mDesktopLoaderThread.start();
// ...
}
然后使用DesktopItemsLoader
在mDesktopLoaderThread
線程中加載,:
private class DesktopItemsLoader implements Runnable {
// ...
public void run() {
// ...
final Cursor c = contentResolver.query(LauncherSettings.Favorites.CONTENT_URI, null, null, null, null);
// ...
final int idIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites._ID);
final int intentIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.INTENT);
final int titleIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.TITLE);
final int iconTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_TYPE);
final int iconIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON);
final int iconPackageIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_PACKAGE);
final int iconResourceIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ICON_RESOURCE);
final int containerIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CONTAINER);
final int itemTypeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.ITEM_TYPE);
final int appWidgetIdIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.APPWIDGET_ID);
final int screenIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SCREEN);
final int cellXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLX);
final int cellYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.CELLY);
final int spanXIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANX);
final int spanYIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.SPANY);
final int uriIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.URI);
final int displayModeIndex = c.getColumnIndexOrThrow(LauncherSettings.Favorites.DISPLAY_MODE);
// ...
// 通過launcher回調返回數據
launcher.onDesktopItemsLoaded(uiDesktopItems, uiDesktopWidgets);
// ...
}
// ...
}
然后我們回到Launcher
的onDesktopItemsLoaded
方法:
void onDesktopItemsLoaded(ArrayList<ItemInfo> shortcuts, ArrayList<LauncherAppWidgetInfo> appWidgets) {
// ...
bindDesktopItems(shortcuts, appWidgets);
}
繼續進入bindDesktopItems
方法:
private void bindDesktopItems(ArrayList<ItemInfo> shortcuts, ArrayList<LauncherAppWidgetInfo> appWidgets) {
// ...
mBinder = new DesktopBinder(this, shortcuts, appWidgets, drawerAdapter);
mBinder.startBindingItems();
}
進入startBindingItems
方法:
public void startBindingItems() {
// ...
obtainMessage(MESSAGE_BIND_ITEMS, 0, mShortcuts.size()).sendToTarget();
}
這里使用了Handler
發送消息,進入Handler
的handleMessage
方法:
@Override
public void handleMessage(Message msg) {
// ...
switch (msg.what) {
// ...
case MESSAGE_BIND_ITEMS: {
launcher.bindItems(this, mShortcuts, msg.arg1, msg.arg2);
break;
}
// ...
}
}
接收到消息之后調用bindItems
方法:
private void bindItems(Launcher.DesktopBinder binder, ArrayList<ItemInfo> shortcuts, int start, int count) {
// ...
case LauncherSettings.Favorites.ITEM_TYPE_APPLICATION:
case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
final View shortcut = createShortcut((ApplicationInfo) item);
workspace.addInScreen(shortcut, item.screen, item.cellX, item.cellY, 1, 1, !desktopLocked);
// ...
}
這里我們只考慮app或者app快捷方式的情況,文件夾和widgets暫時不考慮。app或者app快捷方式實質上都是進入了這個邏輯中,調用createShortcut
方法:
// 重載方法,最終都會調用這個方法
View createShortcut(int layoutResId, ViewGroup parent, ApplicationInfo info) {
// ...
TextView favorite = (TextView) mInflater.inflate(layoutResId, parent, false);
// ...
favorite.setCompoundDrawablesWithIntrinsicBounds(null, info.icon, null, null);
favorite.setText(info.title);
favorite.setTag(info);
favorite.setOnClickListener(this);
// ...
}
這里首先inflater出item的布局,然后設置text
和OnClickListener
,還有tag,這個tag是ApplicationInfo
,里面包含了各種App信息,是從App的AndroidManifest.xml
的<application>
標簽中解析出來的。既然設置了點擊事件,顯然,點擊后應該會打開對應的App才對。所以繼續看onClick
方法:
public void onClick(View v) {
Object tag = v.getTag();
if (tag instanceof ApplicationInfo) {
// Open shortcut
final Intent intent = ((ApplicationInfo) tag).intent;
startActivitySafely(intent);
} else if (tag instanceof FolderInfo) {
handleFolderClick((FolderInfo) tag);
}
}
點擊App就會通過startActivitySafely
方法使用剛才設置的tag,也就是ApplicationInfo
中的intent進行跳轉:
void startActivitySafely(Intent intent) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// ...
startActivity(intent);
// ...
}
然后我們來看看打開某個app的時候整個流程是怎么走的。接着上面的的startActivity()
方法走:
public void startActivity(Intent intent, @Nullable Bundle options) {
// ...
if (options != null) {
startActivityForResult(intent, -1, options);
} else {
startActivityForResult(intent, -1);
}
// ...
}
可以看到,不管你是調用了startActivity
還是startActivityForResult
方法,startActivityForResult
方法,並且如果是調用的startActivity
,則默認requestCode
就是-1,所以如果你想調用startActivityForResult
的時候,注意不能把requestCode
設置為-1,否則它的效果就跟startActivity
一樣了,不會再回調onActivityResult
!,再看看startActivityForResult
的實現:
public void startActivityForResult(Intent intent, int requestCode, @Nullable Bundle options) {
Instrumentation.ActivityResult ar = mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,
intent, requestCode, options);
// ...
}
可以看到,Activity內部是使用mInstrumentation
(Instrumentation
類型)執行execStartActivity
方法來實現Activity
跳轉的,執行完畢后會返回一個Instrumentation.ActivityResult
。
然后查看Instrumentation::execStartActivity
:
public ActivityResult execStartActivity(
// ...
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, options);
// ...
}
首先通過ActivityManagerNative.getDefault()
獲得一個IActivityManager
的實現類:
static public IActivityManager getDefault() {
return gDefault.get();
}
private static final Singleton<IActivityManager> gDefault = new Singleton<IActivityManager>() {
protected IActivityManager create() {
// 通過Binder IPC獲取ActivityManager(IBinder)
IBinder b = ServiceManager.getService("activity");
// ...
IActivityManager am = asInterface(b);
// ...
return am;
}
};
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);
}
先通過Binder IPC的方式從服務端獲取一個Activity Manager
,然后通過ActivityManagernative
封裝成一個代理ActivityManagerProxy
對象,然后調用startActivity
也是使用了Binder IPC進行與服務器端的通信,(整個Android系統的通信機制使用了大量的Binder IPC,這個以后再專門討論這個吧),接着,我們進入到了com.android.server.am.ActivityManagerService
的startActivity
方法:
@Override
public final int startActivity(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options) {
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo, resultWho, requestCode, startFlags, profilerInfo, options, UserHandle.getCallingUserId());
}
接下來的調用鏈:
-> startActivityAsUser
-> startActivityMayWait
-> startActivityLocked
-> startActivityUncheckedLocked
-> targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options)
-> mStackSupervisor.resumeTopActivitiesLocked(this, r, options)
-> resumeTopActivityInnerLocked(prev, options);
-> mStackSupervisor.startSpecificActivityLocked(next, true, true)
startSpecificActivityLocked
方法如下:
void startSpecificActivityLocked(ActivityRecord r, boolean andResume, boolean checkConfig) {
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
// ...
if (app != null && app.thread != null) {
// ...
realStartActivityLocked(r, app, andResume, checkConfig);
return;
}
// ...
mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0, "activity", r.intent.getComponent(), false, false, true);
}
首先從mService
找出對應需要啟動Activity的進程(通過進程名字和uid,進程名字可以在AndroidManifest.xml
中配置)如果可以獲取到,說明這個Activity所屬的進程已經存在了,也就是說app已經在運行了,那就會調用realStartActivityLocked
,否則,如果該Activity所在的App是第一次啟動,則會調用mService.startProcessLocked
方法:
final ProcessRecord startProcessLocked(/*...*/){
// ...
startProcessLocked(app, hostingType, hostingNameStr, abiOverride, entryPoint, entryPointArgs);
// ...
}
final ProcessRecord startProcessLocked(String processName, ApplicationInfo info, boolean knownToBeDead, int intentFlags, String hostingType, ComponentName hostingName, boolean allowWhileBooting, boolean isolated, int isolatedUid, boolean keepIfLarge, String abiOverride, String entryPoint, String[] entryPointArgs, Runnable crashHandler) {
// ...
app = getProcessRecordLocked(processName, info.uid, keepIfLarge);
// ...
if (app == null) {
app = newProcessRecordLocked(info, processName, isolated, isolatedUid);
}
// ...
}
private final void startProcessLocked(ProcessRecord app, String hostingType, String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
// ...
// entryPoint表示一個類,它用來作為新創建的進程的主入口,會調用這個類的靜態main方法,這個參數在startProcessLocked方法中會被檢查重置,如果是null的話,就默認是android.app.ActivityThread。
if (entryPoint == null) entryPoint = "android.app.ActivityThread";
// ...
Process.ProcessStartResult startResult = Process.start(entryPoint,
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, requiredAbi,
instructionSet, app.info.dataDir, entryPointArgs);
// ...
}
這3個重載方法做的事情就是,先根據進程名字調用getProcessRecordLocked()
獲取ProcessRecord
,如果ProcessRecord
不存在,則調用newProcessRecordLocked()
方法建立一個ProcessRecord
,並且新的ProcessRecord
綁定了ApplicationInfo
,uid
等信息,但后進入第三個重載方法,執行新建、啟動進程。
再看Process::start
的實現:
public static final ProcessStartResult start(/*...*/){
// ...
return startViaZygote(processClass, niceName, uid, gid, gids,
debugFlags, mountExternal, targetSdkVersion, seInfo,
abi, instructionSet, appDataDir, zygoteArgs);
// ...
}
接下來就是通過Zygote
進程fork
一個新的進程作為app的進程。這里要需要講的一個參數是processClass
,這個參數表示一個類,它用來作為新創建的進程的主入口,會調用這個類的靜態main
方法,這個參數在startProcessLocked
方法中會被檢查重置,如果是null的話,就默認是android.app.ActivityThread
。
現在App的進程也創建成功了,就會進入android.app.ActivityThread
的靜態的main
中:
public static void main(String[] args) {
// ...
// 初始化主線程Looper
Looper.prepareMainLooper();
// ...
ActivityThread thread = new ActivityThread();
thread.attach(false);
// ...
// 啟動消息循環
Looper.loop()
// ...
}
然后創建了一個ActivityThread
,說明每當一個新的app進程被創建,都會對應一個新的ActivityThread
實例,然后調用它的attach
方法:
private void attach(boolean system) {
// ...
if (!system) {
// ...
final IActivityManager mgr = ActivityManagerNative.getDefault();
// ...
mgr.attachApplication(mAppThread);
// ...
}else{
// ...
}
// ...
}
然后再次通過Binder IPC調用ActivityManagerProxy
的attachApplication
,傳入的ApplicationThread
(Binder)參數用於在服務端進行回調通信。最后進入ActivityManagerService::attachApplication
,再調用attachApplicationLocked(thread, callingPid)
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) {
// ...
app = mPidsSelfLocked.get(pid);
// ...
app.makeActive(thread, mProcessStats);
app.curAdj = app.setAdj= -100;
app.curSchedGroup = app.setSchedGroup = Process.THREAD_GROUP_DEFAULT;
app.forcingToForeground = null;
updateProcessForegroundLocked(app, false, false);
app.hasShownUi = false;
app.debugging = false;
app.cached = false;
app.killedByAm = false;
// ...
thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, enableTrackAllocation, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked());
// ...
if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app)) {
didSomething = true;
}
} catch (Exception e) {
Slog.wtf(TAG, "Exception thrown launching activities in " + app, e);
badApp = true;
}
}
// ...
}
首先,通過pid獲取剛剛創建的進程,然后對app進行一些初始化工作,然后調用bindApplication
遠程調用客戶端ActivityThread::bindApplication
,再通過Handler
調用到ActivityThread::handleBindApplication
方法:
private void handleBindApplication(AppBindData data) {
// ...
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
if (data.instrumentationName != null) {
// ...
mInstrumentationPackageName = ii.packageName;
mInstrumentationAppDir = ii.sourceDir;
mInstrumentationSplitAppDirs = ii.splitSourceDirs;
mInstrumentationLibDir = ii.nativeLibraryDir;
mInstrumentedAppDir = data.info.getAppDir();
mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
mInstrumentedLibDir = data.info.getLibDir();
ApplicationInfo instrApp = new ApplicationInfo();
instrApp.packageName = ii.packageName;
instrApp.sourceDir = ii.sourceDir;
instrApp.publicSourceDir = ii.publicSourceDir;
instrApp.splitSourceDirs = ii.splitSourceDirs;
instrApp.splitPublicSourceDirs = ii.splitPublicSourceDirs;
instrApp.dataDir = ii.dataDir;
instrApp.nativeLibraryDir = ii.nativeLibraryDir;
LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
appContext.getClassLoader(), false, true, false);
ContextImpl instrContext = ContextImpl.createAppContext(this, pi);
// ...
java.lang.ClassLoader cl = instrContext.getClassLoader();
mInstrumentation = (Instrumentation) cl.loadClass(data.instrumentationName.getClassName()).newInstance();
mInstrumentation.init(this, instrContext, appContext, new ComponentName(ii.packageName, ii.name), data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
// ...
}else{
mInstrumentation = new Instrumentation();
}
// ...
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
// ...
mInstrumentation.callApplicationOnCreate(app);
// ...
}
首先,創建一個當前App的Context
,然后如果data.instrumentationName != null
,則初始化Instrumentation
相關的變量,並創建Instrumentation
的ApplicationInfo
等對象來創建Instrumentation
的Context
,然后創建Instrumentation
對象,並調用它的init
方法進行初始化。如果data.instrumentationName == null
,則new一個Instrumentation
(在一個進程中只會有一個Instrumentation
實例)然后創建Application
對象,並調用它的onCreate
方法,這樣Application
就會被回調了。
然后我們回到ActivityManagerService::attachApplicationLocked
方法,遠程執行完thread.bindApplication
方法之后,接下來會調用mStackSupervisor.attachApplicationLocked(app)
方法:
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException {
// ...
ActivityRecord hr = stack.topRunningActivityLocked(null);
// ...
realStartActivityLocked(hr, app, true, true)
// ...
}
先通過topRunningActivityLocked
從堆棧頂端獲取要啟動的Activity,然后realStartActivityLocked(hr, app, true, true)
:
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
// ...
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken, System.identityHashCode(r), r.info, new Configuration(mService.mConfiguration), new Configuration(stack.mOverrideConfig), r.compat, r.launchedFromPackage, task.voiceInteractor, app.repProcState, r.icicle, r.persistentState, results, newIntents, !andResume, mService.isNextTransitionForward(), profilerInfo);
// ...
}
繼續通過Binder IPC遠程調用scheduleLaunchActivity
方法,然后進入ActivityThread
的scheduleLaunchActivity
方法中,然后通過Handler
進入handleLaunchActivity
方法:
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent){
// ...
Activity a = performLaunchActivity(r, customIntent);
handleResumeActivity(r.token, false, r.isForward, !r.activity.mFinished && !r.startsNotResumed);
// ...
}
先調用performLaunchActivity
方法返回一個Activity
,然后調用handleResumeActivity
方法讓該Activity
進入onResume
狀態。所以很顯然在performLaunchActivity
中肯定是生成了Activity
實例,並調用了onCreate
方法了,來看下代碼:
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);
}
// ...
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent);
// ...
Context appContext = createBaseContextForActivity(r, activity);
// ...
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);
// ...
if (r.isPersistable()) {
mInstrumentation.callActivityOnCreate(activity, r.state, r.persistentState);
} else {
mInstrumentation.callActivityOnCreate(activity, r.state);
}
// ...
mInstrumentation.callActivityOnRestoreInstanceState(activity, r.state, r.persistentState);
// ...
mInstrumentation.callActivityOnPostCreate(activity, r.state, r.persistentState);
// ...
}
首先,初始化LoadedApk
,然后通過Instrumentation
來創建一個Activity
實例,通過createBaseContextForActivity
方法創建一個Activity Context
,調用activity
的attach
方法,然后依次觸發該Activity
的onCreate
、onRestoreInstanceState
、onPostCreate
等生命周期方法。
createBaseContextForActivity
方法如下:
private Context createBaseContextForActivity(ActivityClientRecord r, final Activity activity) {
// ...
ContextImpl appContext = ContextImpl.createActivityContext(this, r.packageInfo, displayId, r.overrideConfig);
appContext.setOuterContext(activity);
Context baseContext = appContext;
// ...
}
通過ContextImpl::createActivityContext
創建的Context
對象,可以發現,不論是System Context/App Context/Activity Context
,這些Context
都是通過ContextImpl
生成的,具體這里再挖個坑先。
再繼續進入Activity::attach
方法:
final void attach(Context context, ActivityThread aThread,
Instrumentation instr, IBinder token, int ident,
Application application, Intent intent, ActivityInfo info,
CharSequence title, Activity parent, String id,
NonConfigurationInstances lastNonConfigurationInstances,
Configuration config, String referrer, IVoiceInteractor voiceInteractor) {
// ...
mMainThread = aThread;
mInstrumentation = instr;
mToken = token;
mIdent = ident;
mApplication = application;
mIntent = intent;
mReferrer = referrer;
mComponent = intent.getComponent();
mActivityInfo = info;
mTitle = title;
mParent = parent;
mEmbeddedID = id;
mLastNonConfigurationInstances = lastNonConfigurationInstances;
// ...
}
上面對Activity
與ActivityThread
、Instrumentation
等進行了綁定,所以說每個Activity
都含有一個ActivityThread
引用和一個Instrumentation
引用,而ActivityThread
實例和Instrumentation
實例在一個進程中都只有一個實例,因為ActivityThread
是在進程被創建成功后,進入ActivityThread
的static main()
時才會被創建,而Instrumentation
則是在ActivityThread
被創建后進行attach
的之后被創建。
### 啟動應用流程所有方法鏈調用總結:
-
Activity::startActivity
-
Activity::startActivityForResult
-
Instrumentation::execStartActivity
:
攜帶參數:
who
:from的ContextcontextThread
:from的ActivityThread
的ApplicationThread
,ApplicationThread
中可以通過Binder IPC提供給服務端回調Activity
生命周期等操作(from的主線程)。mToken
:Binder
類型,用來標識from的Activity,可能為null。target
:from的Activity(所以是用來接收跳轉結果的),如果不是從Activity跳轉則為null。intent
:跳轉Intent。requestCode
:如果是startActivity
,則為-1。options
:額外Bundle數據。
ActivityManagerProxy::startActivity()
:
攜帶參數:
caller
:上面的contextThread
,from主線程。callingPackage
:from的Context包名。intent
:跳轉Intent。resolvedType
:跳轉Intent的MIME類型。resultTo
:上面的token
,Binder
類型,用來標識from的Activity。resultWho
:from的Activity的mEmbeddedID(唯一標示字符串)requestCode
:如果是startActivity
,則為-1。startFlags
:默認傳入為0。profilerInfo
:默認傳入為null。options
:額外Bundle數據。
-
ActivityManagerService::startActivity()
(通過Binder IPC調用):
攜帶參數跟上面一樣。 -
ActivityManagerService::startActivityAsUser
攜帶參數包括ActivityManagerService::startActivity()
所有的參數,最再加一個:
userId
:userId,根據給當前進程分配的Linux UID(這個UID可以用來讓上層系統服務進行身份識別和權限檢查)得到一個userId(如果不是多用戶,則直接返回0)。
ActivityStackSupervisor::startActivityMayWait()
參數:
caller
:上面的caller/contextThread
,from主線程。callingUid
:調用用戶uid。callingPackage
:from的Context包名。intent
:跳轉Intent。resolvedType
:跳轉Intent的MIME類型。voiceSession
:傳null。voiceInteractor
:傳null。resultTo
:上面的resultTo/token
,Binder
類型,用來標識from的Activity。resultWho
:from的Activity的mEmbeddedID(唯一標示字符串)requestCode
:如果是startActivity
,則為-1。startFlags
:傳null。profilerInfo
:傳null。outResult
:傳null。config
:傳null。options
:額外數據。ignoreTargetSecurity
:false。userId
:上面的userId
,根據給當前進程分配的Linux UID(這個UID可以用來讓上層系統服務進行身份識別和權限檢查)得到一個userId(如果不是多用戶,則直接返回0)。iContainer
:傳null。inTask
:null。
ActivityStackSupervisor::startActivityLocked()
:
參數:
caller
:上面的caller/contextThread
,from主線程。intent
:跳轉Intent。resolvedType
:跳轉Intent的MIME類型。aInfo
:ActivityInfo
類型,解析from的Activity的Intent信息。voiceSession
:傳null。voiceInteractor
:傳null。resultTo
:上面的resultTo/token
,Binder
類型,用來標識from的Activity。resultWho
:from的Activity的mEmbeddedID(唯一標示字符串)requestCode
:如果是startActivity
,則為-1。callingPackage
:from的Context包名。startFlags
:傳null。options
:額外數據。ignoreTargetSecurity
:false。componentSpecified
:是否顯示指定了component
。outActivity
:傳null。container
:上面的iContainer
,轉型成了ActivityContainer
,還是null。inTask
:null。
在這個方法中,通過ProcessRecord callerApp = mService.getRecordForAppLocked(caller);
獲取到之前創建的ProcessRecord
,然后從Activity
棧中根據resultTo/token
獲取到對應from Activity的ActivityRecord
(sourceRecord),然后__創建將要跳轉的Activity的ActivityRecord對象__(Token
也是在這個時候生成的)。
ActivityStackSupervisor::startActivityUncheckedLocked()
:
參數:
r
:ActivityRecord
類型,就是ActivityStackSupervisor::startActivityLocked()
中創建的將要跳轉的Activity的ActivityRecord對象。sourceRecord
:就是ActivityStackSupervisor::startActivityLocked()
方法獲取的from Activity的sourceRecord
。voiceSession
:傳null。voiceInteractor
:傳null。startFlags
:傳null。doResume
:傳true。options
:額外數據。inTask
:null。
這個方法中有大量的代碼來處理task/stack
等方面的邏輯,以后再仔細深入這個方法。
ActivityStrack::startActivityLocked()
:
方法調用者:ActivityStack
類型,
targetStack
:在ActivityStackSupervisor::startActivityUncheckedLocked()
中確定的需要添加到的ActivityStack
。
參數:
r
:ActivityRecord
類型,就是ActivityStackSupervisor::startActivityLocked()
中創建的跳轉的Activity的ActivityRecord對象。newTask
:是否Intent
是否設置了Intent.FLAG_ACTIVITY_NEW_TASK
。doResume
:傳true。keepCurTransition
:這個具體后面再研究,跟Intent
的flag有關。options
:額外數據。
同樣,這個方法中有大量的代碼來處理task/stack
等方面的邏輯,以后再仔細深入這個方法__(執行完這個方法后,ActivityRecord
就會被真正加入到ActivityStack
中)__。
ActivityStackSupervisor::resumeTopActivitiesLocked()
:
參數:
targetStack
:在ActivityStackSupervisor::startActivityUncheckedLocked()
中確定的需要添加到的ActivityStack
。target
:ActivityRecord
類型,就是ActivityStackSupervisor::startActivityLocked()
中創建的跳轉的Activity的ActivityRecord對象。targetOptions
:額外數據。
ActivityStack::resumeTopActivityLocked()
:
參數:
prev
:ActivityRecord
類型,就是ActivityStackSupervisor::startActivityLocked()
中創建的跳轉的Activity的ActivityRecord對象。options
:額外數據。
ActivityStack::resumeTopActivityInnerLocked()
:
參數:
prev
:ActivityRecord
類型,就是ActivityStackSupervisor::startActivityLocked()
中創建的跳轉的Activity的ActivityRecord對象。options
:額外數據。
ActivityStackSupervisor::startSpecificActivityLocked()
:
參數:
r
:最頂部沒有處於finishing的Activity,就是剛剛在startActivityLocked
中加入的將要跳轉的ActivityRecord
,通過topRunningActivityLocked(null)
查找andResume
:傳truecheckConfig
:傳true
ActivityManagerService::startProcessLocked()
:
參數:
processName
:創建進程的名稱,就是ActivityStack::startSpecificActivityLocked()
中的r.processName
info
:ApplicationInfo
,也是r.info.applicaitonInfo
,具體可以查看ActivityStackSupervisor::startActivityLocked()
中創建ActivityRecord
的代碼。knownToBeDead
:傳true。intentFlags
:傳0。hostingType
:傳字符串“activity”。hostingName
:ComponentName
類型,intent
中的Componentname
allowWhileBooting
:傳false。isolated
:傳falsekeepIfLarge
傳true
ActivityManagerService::startProcessLocked()
(重載方法):
參數包含上面所有,多了以下幾個:
isolatedUid
:傳0abiOverride
:傳nullentryPoint
:傳nullentryPointArgs
傳nullcrashHandler
傳null
注意:在這個方法中,會創建新進程的ProcessRecord
對象,並綁定ApplicationInfo
等信息,這樣,啟動進程后進行bindApplicaiton
的時候就可以根據進程PID獲取到所有的ApplicationInfo
信息了。
ActivityManagerService::startProcessLocked()
(重載方法):
參數:
app
:ProcessRecord
類型,創建的進程。hostingType
:傳字符串“activity”。hostingNameStr
:通過hostingName
生成的字符串(包名 + "/" + 類的簡單類名)abiOverride
:傳nullentryPoint
:傳nullentryPointArgs
傳null
Process.start()
參數(省略部分參數):
processClass
:上面的entryPoint
,但是並不是null了,而是android.app.ActivityThread
,因為在ActivityManagerService::startProcessLocked()
中被設置默認值了,它表示一個類,用來作為新創建的進程的主入口,會調用這個類的靜態main方法。所以啟動完這個進程就會進入ActivityThread
的static main()
方法。zygoteArgs
:fork zygote進程時的參數。
-
ActivityThread::main()
-
ActivityThread::attach()
-
ActivityManagerProxy::attachApplication()
:
參數:
mAppThread
:ApplicationThread()
類型,Binder,用來提供給AMS調用。
ActivityManagerService::attachApplication()
:
參數:
mAppThread
:ApplicationThread()
類型,Binder,用來提供給AMS調用。
ActivityManagerService::attachApplicationLocked()
:
參數:
thread
:ApplicationThread()
類型,Binder,用來提供給AMS調用。上面的mAppThread
。pid
:當前調用的進程PID。
IApplicationThread::bindApplication()
:
方法調用調用者:上面的thread/mAppThread
,Binder,用來提供給AMS調用。
參數(省略部分參數):
packageName
:用的進程名字processName
info
:ApplicationInfo
類型,從ProcessRecord
中的instrumentationInfo或者info
,這個ApplicationInfo
是在建立ProcessRecord
時就保存了。
-
ActivityThread::bindApplication()
:
參數:同上 -
ActivityThread::handleBindApplication()
:
通過Handler調用。
參數:
data
:AppBindData
類型,里面包含的類型processName
,providers
,instrumentationName
,instrumentationArgs
,instrumentationWatcher
,instrumentationUiAutomationConnection
,config
等數據。
- `ActivityManagerService`中的`ActivityThread::bindApplication()`執行完畢之后
ActivityStackSupervisor::attachApplicationLocked()
:
參數:
app
:新建的進程綁定的ProcessRecord
。
ActivityStackSupervisor::realStartActivityLocked()
:
參數:
r
:ActivityRecord
類型,topRunningActivityLocked從堆棧頂端獲取要啟動的Activity。app
:新建的進程綁定的ProcessRecord
。andResume
:傳入truecheckConfig
:傳入true
IApplicationThread::scheduleLaunchActivity()
:
參數(部分):
intent
:將要啟動的ActivityRecord
中的intent
。token
:將要啟動的ActivityRecord
中的token
。info
:將要啟動的ActivityRecord
中的ApplicationInfo
。
-
ActivityThread::scheduleLaunchActivity()
:
Binder IPC調用,參數與IApplicationThread::scheduleLaunchActivity()
相同。 -
ActivityThread::handleLaunchActivity()
:
該方法通過Handler調用,參數同上。
r
:ActivityClientRecord
類型,在ActivityThread::scheduleLaunchActivity()
中封裝,包括的數據有token
,ident
,intent
,activityInfo
等等,但是LoadedApk
是這時根據包名從ActivityThread
中弱引用緩存中獲取的的。customIntent
:null
-
ActivityThread::performLaunchActivity()
:
參數與ActivityThread::handleLaunchActivity()
相同。 -
Activity::attach()
:
參數(部分):
context
:ActivityThread::performLaunchActivity()
中創建的Activity Context
。aThread
:ActivityThread
類型,主線程,一個進程都共用一個。token
:構建ActivityRecord
時生成的token
。application
:Application
第一次的時候創建一遍。intent
:將要啟動的ActivityRecord中的intent。info
:ActivityInfo
類型,將要啟動的ActivityRecord中的ActivityInfo
。
Instrumentation::callActivityOnCreate()
:
參數(部分):
activity
:ActivityThread::performLaunchActivity()
中創建的Activity
。
-
Activity::performCreate()
-
Activity::onCreate()