ActivityManagerService,簡稱AMS,具備管理Activity行爲、控制activity的生命週期、派發消息事件、內存管理等功能,AMS的另外兩個重要概念是兩大核心功能是WindowManagerService.java和View.java。
分析ActivityManagerService的流程以前須要先下載Android的系統源碼,相關下載能夠參照下面的文章:中國大陸如何下載 Android 源碼java
用戶從Launcher程序點擊應用圖標可啓動應用的入口Activity,Activity啓動時須要多個進程之間的交互,以下圖所示。
android
其中,AMS進程其實是SystemServer進程,由於AMS只是SystemServer啓動的一個服務而已,運行在SystemServer的某個線程中。數組
具體的,用戶在Launcher程序裏點擊應用圖標時,會通知ActivityManagerService啓動應用的主Activity,ActivityManagerService發現這個應用還未啓動,則會通知Zygote進程執行ActivityThread的main方法。應用進程接下來通知ActivityManagerService應用進程已啓動,ActivityManagerService保存應用進程的一個代理對象,這樣ActivityManagerService能夠經過這個代理對象控制應用進程,而後ActivityManagerService通知應用進程建立主Activity的實例,並執行它的生命週期方法,也就是諸如OnCreadte()等方法。緩存
當點擊應用程序圖標後,Launcher 使用一個帶有 Intent.FLAG_ACTIVITY_NEW_TASK flag 的 Intent,調用 startActivity 方法來啓動App。相關源碼以下:網絡
public static Intent makeLaunchIntent(Context context, LauncherActivityInfoCompat info, UserHandleCompat user) { long serialNumber = UserManagerCompat.getInstance(context).getSerialNumberForUser(user); return new Intent(Intent.ACTION_MAIN) .addCategory(Intent.CATEGORY_LAUNCHER) .setComponent(info.getComponentName()) .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) .putExtra(EXTRA_PROFILE, serialNumber); }
當點擊app的圖標時會執行以下的代碼調用流程。數據結構
public void onClick(View v) { ... Object tag = v.getTag(); if (tag instanceof ShortcutInfo) { onClickAppShortcut(v); } ... } protected void onClickAppShortcut(final View v) { ... // Start activities startAppShortcutOrInfoActivity(v); ... } void startAppShortcutOrInfoActivity(View v) { ... // 獲得launcher提供的啓動這個app主activity的intent intent = shortcut.intent; ... boolean success = startActivitySafely(v, intent, tag); ... } boolean startActivitySafely(View v, Intent intent, Object tag) { ... success = startActivity(v, intent, tag); ... } private boolean startActivity(View v, Intent intent, Object tag) { intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); ... startActivity(intent, optsBundle); ... }
從以上代碼流程可知當Launcher啓動一個app時,會在本身的startActivity()方法中爲Intent中添加一個FLAG_ACTIVITY_NEW_TASK flag,而後調用繼承自Activity的startActivity()方法來進一步啓動app。併發
Activity啓動Activity的流程以下,具體能夠查看相關的源碼,須要注意的是Android 6.0的實現和8.0版本實現有略微的區別。app
下面咱們看一下ActivityThread類,ActivityThread類是Android應用進程的核心類,這個類包含了應用框架中其餘重要的類。其源碼以下:框架
public final class ActivityThread { ........ private ContextImpl mSystemContext; static IPackageManager sPackageManager; // 保存該app中全部的Activity final ArrayMap<IBinder, ActivityClientRecord> mActivities = new ArrayMap<>(); // 保存該app中全部的service final ArrayMap<IBinder, Service> mServices = new ArrayMap<>(); // 保存該app中全部的provider final ArrayMap<ProviderKey, ProviderClientRecord> mProviderMap = new ArrayMap<ProviderKey, ProviderClientRecord>(); //管理應用的資源 private final ResourcesManager mResourcesManager; // 存儲包含代碼,即dex文件的apk文件保存在該變量中 final ArrayMap<String, WeakReference<LoadedApk>> mPackages = new ArrayMap<String, WeakReference<LoadedApk>>(); // 不包含代碼,牢牢包含資源的apk放在該變量中 final ArrayMap<String, WeakReference<LoadedApk>> mResourcePackages // 若是app中本身實現了Application的子類,並在清單文件中聲明瞭,那麼該變量就指向本身實現的那個子類對象 Application mInitialApplication; AppBindData mBoundApplication; // 用於binder通訊,AMS經過它來調用應用的接口 final ApplicationThread mAppThread = new ApplicationThread(); // 主線程中的Handler static Handler sMainThreadHandler; // set once in main() final Looper mLooper = Looper.myLooper(); // H繼承自Handler,mH用來發送和處理ApplicationThread經過binder接受的AMS請求 final H mH = new H(); ......... }
ActivityThread類中沒有定義數據結構來存儲BroadcastReceiver對象,由於BroadcastReceiver對象生命週期很短暫,屬於調用一次運行一次的類型,所以不須要保存其對象。AppBindData類爲ActivityThread的內部類,定義以下,記錄了與之綁定的app的相關數據。async
static final class AppBindData { LoadedApk info; String processName; ApplicationInfo appInfo; List<ProviderInfo> providers; ComponentName instrumentationName; Bundle instrumentationArgs; IInstrumentationWatcher instrumentationWatcher; IUiAutomationConnection instrumentationUiAutomationConnection; int debugMode; boolean enableOpenGlTrace; boolean restrictedBackupMode; boolean persistent; Configuration config; CompatibilityInfo compatInfo; /** Initial values for {@link Profiler}. */ ProfilerInfo initProfilerInfo; public String toString() { return "AppBindData{appInfo=" + appInfo + "}"; } }
其中 ApplicationThread類型的變量mAppThread用於AMS所在app的接口,應用進程須要調用AMS提供的功能,而AMS也須要主動調用應用進程以控制應用進程並完成指定操做。ApplicationThread的運做流程以下圖:
如上圖可知,AMS經過IApplicationThread接口管理應用進程,ApplicationThread類實現了IApplicationThread接口,實現了管理應用的操做,ApplicationThread對象運行在應用進程裏。ApplicationThreadProxy對象是ApplicationThread對象在AMS線程 (AMS線程運行在system_server進程)內的代理對象,AMS經過ApplicationThreadProxy對象調用ApplicationThread提供的功能,好比讓應用進程啓動某個Activity。ApplicationThread中的scheduleDestroyActivity的源碼以下:
public final void scheduleDestroyActivity(IBinder token, boolean finishing, int configChanges) { sendMessage(H.DESTROY_ACTIVITY, token, finishing ? 1 : 0, configChanges); }
而Binder服務端的最終調用的是ActivityThread的sendMessage函數。
private void sendMessage(int what, Object obj, int arg1, int arg2) { sendMessage(what, obj, arg1, arg2, false); } private void sendMessage(int what, Object obj, int arg1, int arg2, boolean async) { if (DEBUG_MESSAGES) Slog.v( TAG, "SCHEDULE " + what + " " + mH.codeToString(what) + ": " + arg1 + " / " + obj); Message msg = Message.obtain(); msg.what = what; msg.obj = obj; msg.arg1 = arg1; msg.arg2 = arg2; if (async) { msg.setAsynchronous(true); } mH.sendMessage(msg); }
而ActivityThread類中內部類H(繼承自Handler,mH就是H的對象)中則定義了處理消息的方法,該函數用來處理接收到的數據。
前面講到AMS使用startActivity啓動APP,爲了加深印象在來看一下startActivity函數(須要注意的是,6.0和8.0的代碼有細微的區別)。
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()); } public final int startActivityAsUser(IApplicationThread caller, String callingPackage, Intent intent, String resolvedType, IBinder resultTo, String resultWho, int requestCode, int startFlags, ProfilerInfo profilerInfo, Bundle options, int userId) { // 若是是隔離的應用的話,不容許其打開其餘app的activity // appid是99000-99999之間的屬於隔離app enforceNotIsolatedCaller("startActivity"); userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId, false, ALLOW_FULL_ONLY, "startActivity", null); // TODO: Switch to user app stacks here. return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType, null, null, resultTo, resultWho, requestCode, startFlags, profilerInfo, null, null, options, false, userId, null, null); }
判斷髮起者是不是隔離的app,不容許隔離的app調用其餘app。而後調用ActivityStackSupervisor類中的startActivityMayWait方法。
final int startActivityMayWait( IApplicationThread caller,//AMS經過這個參數能夠和發起者進行交互 int callingUid,//發起者uid String callingPackage,//發起者包名 Intent intent, // 啓動activity的intent String resolvedType, // intent的類型,也就是MIME type IVoiceInteractionSession voiceSession, IVoiceInteractor voiceInteractor, IBinder resultTo,//用於接收startActivityForResult的結果,launcher啓動app這種情景下沒有用,爲null String resultWho, int requestCode,//這個是調用者來定義其意義,若值大於等於0,則AMS內部保存該值並經過onActivityResult返回調用者,這裏爲-1 int startFlags,// 傳入的爲0 ProfilerInfo profilerInfo, WaitResult outResult, Configuration config, Bundle options, boolean ignoreTargetSecurity, int userId, IActivityContainer iContainer, // 傳入的爲null TaskRecord inTask)/ // 傳入爲null { // Refuse possible leaked file descriptors if (intent != null && intent.hasFileDescriptors()) { throw new IllegalArgumentException("File descriptors passed in Intent"); } // 當啓動一個app時 ,launcher會構造一個intent,前面已經介紹了,是一個顯示的intent // 因此這裏爲true, boolean componentSpecified = intent.getComponent() != null; // Don't modify the client's object! // 建立一個新的intent,方便改動 intent = new Intent(intent); // 收集 要啓動的app的主activity的信息 ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags, profilerInfo, userId); // 傳入的該參數爲null ActivityContainer container = (ActivityContainer)iContainer; synchronized (mService) { if (container != null && container.mParentActivity != null && container.mParentActivity.state != RESUMED) { // Cannot start a child activity if the parent is not resumed. return ActivityManager.START_CANCELED; } .................................... final ActivityStack stack; if (container == null || container.mStack.isOnHomeDisplay()) { stack = mFocusedStack; } else { stack = container.mStack; } // 傳入的config爲null stack.mConfigWillChange = config != null && mService.mConfiguration.diff(config) != 0; if (DEBUG_CONFIGURATION) Slog.v(TAG_CONFIGURATION, "Starting activity when config will change = " + stack.mConfigWillChange); final long origId = Binder.clearCallingIdentity(); if (aInfo != null && (aInfo.applicationInfo.privateFlags &ApplicationInfo.PRIVATE_FLAG_CANT_SAVE_STATE) != 0) { ....................... } int res = startActivityLocked(caller, intent, resolvedType, aInfo, voiceSession, voiceInteractor, resultTo, resultWho, requestCode, callingPid, callingUid, callingPackage, realCallingPid, realCallingUid, startFlags, options, ignoreTargetSecurity, componentSpecified, null, container, inTask); Binder.restoreCallingIdentity(origId); if (stack.mConfigWillChange) { ............. } // 傳入的爲null if (outResult != null) { ....................... mService.wait(); //等待應用進程的activity啓動完成 ........... } ............. } return res; } }
startActivityAsUser()方法最主要的目地是進行權限檢查,檢查發起者是否被隔離,是的話,是不容許調用別的app的activity的。startActivityMayWait()方法主要是利用傳入的intent去向PMS蒐集要啓動的APP的信息,儲存到aInfo中.。名字中有wait字眼,預示着該方法可能致使線程等待,不過在咱們這個場景中不會出現這種狀況,由於wait出如今對結果的處理中,咱們這個場景中是不須要處理結果的。
Android APP的入口類在ActivityThread中,有一個Main函數,該函數的源碼以下:
public static void main(String[] args) { Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain"); SamplingProfilerIntegration.start(); CloseGuard.setEnabled(false); // 環境初始化,主要是app運行過程當中須要使用到的系統路徑 // 好比外部存儲路徑等等 Environment.initForCurrentUser(); // Set the reporter for event logging in libcore EventLogger.setReporter(new EventLoggingReporter()); //增長一個保存key的provider AndroidKeyStoreProvider.install(); // 爲應用社會當前用戶的CA證書保存的位置 final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId()); TrustedCertificateStore.setDefaultUserDirectory(configDir); // 設置app進程的名字 // 經過前面的分析可知,前面的過程當中已經設置過名字了,這裏又改成了「pre-initialized」,不知道爲啥, // 由於後面還要在調用該方法,從新設置進程名字爲app 包名或者app指定的名字。 Process.setArgV0("<pre-initialized>"); // 建立主線程looper Looper.prepareMainLooper(); // 建立ActivityThread對象。 ActivityThread thread = new ActivityThread(); // 將建立的ActivityThread附加到AMS中,這樣 // AMS就能夠控制這個app中組件的生命週期了 thread.attach(false); if (sMainThreadHandler == null) { sMainThreadHandler = thread.getHandler(); } if (false) { Looper.myLooper().setMessageLogging(new LogPrinter(Log.DEBUG, "ActivityThread")); } // End of event ActivityThreadMain. Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); //App主線程開始執行消息處理循環 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); } }
當ActivityThread對象建立以後,就開始調用其attach()方法,這是一個很重要的方法,參數爲false代表是普通app進程。
private void attach(boolean system) { sCurrentActivityThread = this; mSystemThread = system; // app進程傳入fasle if (!system) { ViewRootImpl.addFirstDrawHandler(new Runnable() { @Override public void run() { ensureJitEnabled(); } }); android.ddm.DdmHandleAppName.setAppName("<pre-initialized>", UserHandle.myUserId()); // mAppThread是ApplicationThread對象; // 下面這個方法會把mAppThread放到RuntimeInit類中的靜態變量mApplicationObject中 RuntimeInit.setApplicationObject(mAppThread.asBinder()); final IActivityManager mgr = ActivityManagerNative.getDefault(); try { // 執行AMS的attachApplication方法 // 將mAppThread傳入AMS,這樣AMS就能夠經過它來控制app了 mgr.attachApplication(mAppThread); } catch (RemoteException ex) { // Ignore } // Watch for getting close to heap limit. BinderInternal.addGcWatcher(new Runnable() { ............ }); } else { .............. } // add dropbox logging to libcore DropBox.setReporter(new DropBoxReporter()); ViewRootImpl.addConfigCallback(new ComponentCallbacks2() { ....... }); }
其中,RuntimeInit.setApplicationObject方法源碼以下:
public static final void setApplicationObject(IBinder app) { mApplicationObject = app; }
attachApplication方法主要負責APP與AMS的綁定操做,該方法的源碼以下:
public final void attachApplication(IApplicationThread thread) { synchronized (this) { int callingPid = Binder.getCallingPid(); final long origId = Binder.clearCallingIdentity(); attachApplicationLocked(thread, callingPid); Binder.restoreCallingIdentity(origId); } }
該方法最終調用了attachApplicationLocked()方法。
private final boolean attachApplicationLocked(IApplicationThread thread, int pid) { ProcessRecord app; if (pid != MY_PID && pid >= 0) { synchronized (mPidsSelfLocked) { // 在建立startProcessLocked()方法中調用Process.start()方法建立進程後 // 會以接收傳遞過來的進程號爲索引,將ProcessRecord加入到AMS的mPidsSelfLocked中 // 這裏能夠以進程號從mPidsSelfLocked中拿到ProcessRecord app = mPidsSelfLocked.get(pid); } } else { app = null; } if (app == null) { ........ return false; } if (app.thread != null) { handleAppDiedLocked(app, true, true); } // 註冊app進程死亡通知處理機制,也就是建立監聽app死亡的對象 // App進程死亡後,會調用AppDeathRecipient.binderDied()方法 final String processName = app.processName; try { AppDeathRecipient adr = new AppDeathRecipient( app, pid, thread); thread.asBinder().linkToDeath(adr, 0); app.deathRecipient = adr; } catch (RemoteException e) { app.resetPackageList(mProcessStats); startProcessLocked(app, "link fail", processName); return false; } //調用ProcessStatsService開始記錄process的狀態 //該方法中將thread賦值給app.thread app.makeActive(thread, mProcessStats); // 初始化App進程優先級等信息 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; // 移除PROC_START_TIMEOUT_MSG消息 // 前面在AMS.startProcessLocked方法中會在調用Process.start()方法以後,將這個消息放入消息隊列中 // 若是沒有在規定的時間內將該消息移除消息隊列,那麼會致使進程啓動超時 mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app); // mProcessesReady爲true boolean normalMode = mProcessesReady || isAllowedWhileBooting(app.info); // 拿到App的provider List<ProviderInfo> providers = normalMode ? generateApplicationProvidersLocked(app) : null; ........ // If the app is being launched for restore or full backup, set it up specially boolean isRestrictedBackupMode = false; if (mBackupTarget != null && mBackupAppName.equals(processName)) { isRestrictedBackupMode = (mBackupTarget.backupMode == BackupRecord.RESTORE) || (mBackupTarget.backupMode == BackupRecord.RESTORE_FULL) || (mBackupTarget.backupMode == BackupRecord.BACKUP_FULL); } // 判斷是否須要執行dex2oat命令 // 在app安裝的時候,會執行一次dex2oat // 當生成的oat文件被破外或者刪除的時候,須要從新執行dex2oat ensurePackageDexOpt(app.instrumentationInfo != null ? app.instrumentationInfo.packageName : app.info.packageName); // instrument app 技術先關 // 好比Android studio 開發時,修改某些代碼時,不必從新安裝apk,便可查看以後的結果 // 後續單獨在分析instrument技術 if (app.instrumentationClass != null) { ensurePackageDexOpt(app.instrumentationClass.getPackageName()); } .... // 調用ApplicationThread的bindApplication接口 thread.bindApplication(processName, appInfo, providers, app.instrumentationClass, profilerInfo, app.instrumentationArguments, app.instrumentationWatcher, app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace, isRestrictedBackupMode || !normalMode, app.persistent, new Configuration(mConfiguration), app.compat, getCommonServicesLocked(app.isolated), mCoreSettingsObserver.getCoreSettingsLocked()); updateLruProcessLocked(app, false, null); app.lastRequestedGc = app.lastLowMemory = SystemClock.uptimeMillis(); } catch (Exception e) { ............ return false; } .... boolean badApp = false; boolean didSomething = false; // See if the top visible activity is waiting to run in this process... // 爲true if (normalMode) { try { // 執行ActivityStackSupervisor.attachApplicationLocked if (mStackSupervisor.attachApplicationLocked(app)) { didSomething = true; } } catch (Exception e) { Slog.wtf(TAG, "Exception thrown launching activities in " + app, e); badApp = true; } } // Find any services that should be running in this process... if (!badApp) { try { // 處理要運行這個進程中的service didSomething |= mServices.attachApplicationLocked(app, processName); } catch (Exception e) { Slog.wtf(TAG, "Exception thrown starting services in " + app, e); badApp = true; } } // Check if a next-broadcast receiver is in this process... if (!badApp && isPendingBroadcastProcessLocked(pid)) { try { // 處理廣播 didSomething |= sendPendingBroadcastsLocked(app); } catch (Exception e) { // If the app died trying to launch the receiver we declare it 'bad' Slog.wtf(TAG, "Exception thrown dispatching broadcasts in " + app, e); badApp = true; } } ........ if (!didSomething) { updateOomAdjLocked(); } return true; }
attachApplicationLocked函數比較長,首先以傳入的app進程號爲索引從AMS的mPidsSelfLocked中取出app進程的ProcessRecord對象。而後調用ProcessRecord對象的makeActive方法調用ProcessStatsService開始記錄process的狀態,接着將PROC_START_TIMEOUT_MSG消息,從消息循環中移除,檢查是否從新執行dex2oat生成app的oat文件。
該方法主要作了一下四件事情:
其執行的流程圖以下圖所示:
接下來重點分析下bindApplication()方法,這個方法最終效果是調用了App的Application對象的onCreate方法。其源碼以下:
public final void bindApplication( String processName, //ProcessRecord中記錄的進程名字 ApplicationInfo appInfo, List<ProviderInfo> providers, // app中的providers ComponentName instrumentationName, ProfilerInfo profilerInfo, Bundle instrumentationArgs, //測試相關 IInstrumentationWatcher instrumentationWatcher, IUiAutomationConnection instrumentationUiConnection, int debugMode, boolean enableOpenGlTrace, 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); } // 發送SET_CORE_SETTINGS消息 // 獲取系統的設定並設置到ActivityThread中 setCoreSettings(coreSettings); // 拿到PMS IPackageManager pm = getPackageManager(); android.content.pm.PackageInfo pi = null; try { // 以包名從PMS中得到PackageInfo pi = pm.getPackageInfo(appInfo.packageName, 0, UserHandle.myUserId()); } catch (RemoteException e) { } if (pi != null) { // 該app是否設置了共享uid boolean sharedUserIdSet = (pi.sharedUserId != null); // app進程名字是否被設定爲與包名不一致 // 默認狀況下,app進程名字就是其包名 // 當顯示設置process name 的時候能夠執行進程的名字 boolean processNameNotDefault = (pi.applicationInfo != null && !appInfo.packageName.equals(pi.applicationInfo.processName)); // 若是設置了共享uid或者進程名字設置爲了其餘名字, // 這就致使該app可能運行在一個已經運行的進程中 boolean sharable = (sharedUserIdSet || processNameNotDefault); // 若是app是單獨的進程,那麼要想VM註冊相關信息 // 是就上就在/data/dalvik-cache/profiles/建立一個以包名爲名字的空文件,另外兩個參數沒用到 if (!sharable) { VMRuntime.registerAppInfo(appInfo.packageName, appInfo.dataDir, appInfo.processName); } } // 建立兵初始化AppBindData對象 // 在這裏設置了進程名字,app的provider,ApplicationInfo 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; // 是否容許adb backup data.restrictedBackupMode = isRestrictedBackupMode; // 進程是否常駐內存,殺掉後,會被重啓 data.persistent = persistent; data.config = config; data.compatInfo = compatInfo; data.initProfilerInfo = profilerInfo; // 發送BIND_APPLICATION消息 sendMessage(H.BIND_APPLICATION, data); }
bindApplication()方法要經過PMS檢查啓動的app是否設置了共享uid,以及檢查當前app進程的名字是否設定的與包名不一致,符合二者中的任一種狀況下,則說明該app進程可能運行在另外一個已經存在的進程中。
bindApplication()方法主要是建立和初始化了AppBindData對象,併發送兩個消息:一個是SET_CORE_SETTINGS;另外一個是BIND_APPLICATION。SET_CORE_SETTINGS主要是獲取系統的設定並設置到ActivityThread中。BIND_APPLICATION用於啓動App並安裝全部的provider,並回調App的oncreate方法BIND_APPLICATION消息。
ActivityThread中處理BIND_APPLICATION消息的方法是handleBindApplication(),其源碼以下:
private void handleBindApplication(AppBindData data) { mBoundApplication = data; ....... // 設置進程的名字,由於前面ActivityThread.main將其設置爲了"<pre-initialized>" Process.setArgV0(data.processName); // 設置app在ddms中顯示的進程名字 android.ddm.DdmHandleAppName.setAppName(data.processName, UserHandle.myUserId()); // 普通app進程,通常狀況下爲false // 除非xml設置persistent爲true // 帶有persistent標記的進程在低內存設備中部支持使用硬件加速 if (data.persistent) { if (!ActivityManager.isHighEndGfx()) { HardwareRenderer.disable(false); } } if (mProfiler.profileFd != null) { mProfiler.startProfiling(); } // 根據app編譯時指定的sdk版本與當前系統sdk版本設置AsyncTask if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) { AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } Message.updateCheckRecycle(data.appInfo.targetSdkVersion); // 恢復時區和位置信息 TimeZone.setDefault(null); Locale.setDefault(data.config.locale); // 資源管理初始化設置 mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo); mCurDefaultDisplayDpi = data.config.densityDpi; applyCompatConfiguration(mCurDefaultDisplayDpi); // 設置AppBindData中LoadedApk info屬性字段 // 這裏會根據傳入app的ActivityInfo和CompatibilityInfo建立一個LoadedApk對象 data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo); // 若是應用沒有指定使用設備的density,那麼默認使用mdpi if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) == 0) { mDensityCompatMode = true; Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT); } updateDefaultDensity(); // 建立ContextImpl上下文,裏面也設計到了資源管理相關的內容 ,如從LoadedApk中提取資源 // 後續還需對其進行初始化 final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); // 普通app啓動時,isIsolated爲false if (!Process.isIsolated()) { //在沙箱目錄中建立cache文件夾 final File cacheDir = appContext.getCacheDir(); if (cacheDir != null) { //將建立的cache文件夾與屬性"java.io.tmpdir"關聯 System.setProperty("java.io.tmpdir", cacheDir.getAbsolutePath()); } else { Log.v(TAG, "Unable to initialize \"java.io.tmpdir\" property due to missing cache directory"); } // Use codeCacheDir to store generated/compiled graphics code // 在沙箱目錄建立code-cache文件夾 final File codeCacheDir = appContext.getCodeCacheDir(); if (codeCacheDir != null) { setupGraphicsSupport(data.info, codeCacheDir); } else { Log.e(TAG, "Unable to setupGraphicsSupport due to missing code-cache directory"); } } // 設置時間格式 final boolean is24Hr = "24".equals(mCoreSettings.getString(Settings.System.TIME_12_24)); DateFormat.set24HourTimePref(is24Hr); View.mDebugViewAttributes = mCoreSettings.getInt(Settings.Global.DEBUG_VIEW_ATTRIBUTES, 0) != 0; // 調試相關 if ((data.appInfo.flags & (ApplicationInfo.FLAG_SYSTEM | ApplicationInfo.FLAG_UPDATED_SYSTEM_APP)) != 0) { StrictMode.conditionallyEnableDebugLogging(); } if (data.appInfo.targetSdkVersion > 9) { StrictMode.enableDeathOnNetwork(); } NetworkSecurityPolicy.getInstance().setCleartextTrafficPermitted( (data.appInfo.flags & ApplicationInfo.FLAG_USES_CLEARTEXT_TRAFFIC) != 0); if (data.debugMode != IApplicationThread.DEBUG_OFF) { ............ } // Enable OpenGL tracing if required if (data.enableOpenGlTrace) { GLUtils.setTracingLevel(1); } // Allow application-generated systrace messages if we're debuggable. boolean appTracingAllowed = (data.appInfo.flags&ApplicationInfo.FLAG_DEBUGGABLE) != 0; Trace.setAppTracingAllowed(appTracingAllowed); /** * Initialize the default http proxy in this process for the reasons we set the time zone. */ IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE); if (b != null) { IConnectivityManager service = IConnectivityManager.Stub.asInterface(b); try { // 設置網絡代理 final ProxyInfo proxyInfo = service.getProxyForNetwork(null); Proxy.setHttpProxySystemProperty(proxyInfo); } catch (RemoteException e) {} } // 爲null if (data.instrumentationName != null) { .......... } else { // 建立Instrumentation對象 mInstrumentation = new Instrumentation(); } if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) { dalvik.system.VMRuntime.getRuntime().clearGrowthLimit(); } else { dalvik.system.VMRuntime.getRuntime().clampGrowthLimit(); } final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites(); try { // 建立app的Application對象 Application app = data.info.makeApplication(data.restrictedBackupMode, null); mInitialApplication = app; // don't bring up providers in restricted mode; they may depend on the // app's custom Application class if (!data.restrictedBackupMode) { List<ProviderInfo> providers = data.providers; if (providers != null) { installContentProviders(app, providers); // For process that contains content providers, we want to // ensure that the JIT is enabled "at some point". mH.sendEmptyMessageDelayed(H.ENABLE_JIT, 10*1000); } } // Do this after providers, since instrumentation tests generally start their // test thread at this point, and we don't want that racing. try { // 執行instrumentation的onCreate()方法 mInstrumentation.onCreate(data.instrumentationArgs); } catch (Exception e) { ................ } // 執行Application的onCreate生命週期方法 try { mInstrumentation.callApplicationOnCreate(app); } catch (Exception e) { ............... } } finally { StrictMode.setThreadPolicy(savedPolicy); } }
handleBindApplication函數主要完成了以下的一些操做:
LoadedApk類用來記錄描述一個被加載運行的APK,的代碼、資源等信息。
public final class LoadedApk { private static final String TAG = "LoadedApk"; private final ActivityThread mActivityThread; // App的ActivityThread對象 private ApplicationInfo mApplicationInfo; // 描述App信息的ApplicationInfo,若是App中重載了Application類,那麼其類名會被記錄在ApplicationInfo中 final String mPackageName;// app的包名 private final String mAppDir;// app在/data/app/<包名>路徑 private final String mResDir;// 資源路徑 private final String[] mSplitAppDirs; private final String[] mSplitResDirs; private final String[] mOverlayDirs; private final String[] mSharedLibraries;// 共享java庫 private final String mDataDir;//數據沙箱目錄 private final String mLibDir;// native so庫位置 private final File mDataDirFile; private final ClassLoader mBaseClassLoader;//getPackageInfoNoCheck()建立的LoadedApk對象中該字段初始化爲null private final boolean mSecurityViolation; private final boolean mIncludeCode;// 這個apk是否包含dex private final boolean mRegisterPackage; private final DisplayAdjustments mDisplayAdjustments = new DisplayAdjustments(); Resources mResources; private ClassLoader mClassLoader;// private Application mApplication;// 這個app的Application對象,若是App繼承了Application,那麼爲其子類對象 private final ArrayMap<Context, ArrayMap<BroadcastReceiver, ReceiverDispatcher>> mReceivers = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>(); private final ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>> mUnregisteredReceivers = new ArrayMap<Context, ArrayMap<BroadcastReceiver, LoadedApk.ReceiverDispatcher>>(); private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mServices = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>(); private final ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>> mUnboundServices = new ArrayMap<Context, ArrayMap<ServiceConnection, LoadedApk.ServiceDispatcher>>(); int mClientCount = 0; Application getApplication() { return mApplication; }
經過分析可知,在handleBindApplication()方法中經過調用getPackageInfoNoCheck()方法建立LoadedApk對象。getPackageInfoNoCheck()的源碼以下:
public final LoadedApk getPackageInfoNoCheck(ApplicationInfo ai, CompatibilityInfo compatInfo) { return getPackageInfo(ai, compatInfo, null, false, true, false); }
getPackageInfoNoCheck()又調用了getPackageInfo()。
private LoadedApk getPackageInfo( ApplicationInfo aInfo, // app的Application信息 CompatibilityInfo compatInfo, // 兼容性 ClassLoader baseLoader,// 傳入null boolean securityViolation,// 傳入false boolean includeCode,// 傳入true boolean registerPackage // 傳入false ) { // 要啓動app的擁有者與當前系統用戶不一致 final boolean differentUser = (UserHandle.myUserId() != UserHandle.getUserId(aInfo.uid)); synchronized (mResourcesManager) { WeakReference<LoadedApk> ref; if (differentUser) { ref = null; } else if (includeCode) { // 若是包含了dex,那麼從ActivityThread.mPackages中先查找是否已經有了apk對應的LoadedApk ref = mPackages.get(aInfo.packageName); } else { // 若是沒有包含了dex,那麼從ActivityThread.mResourcePackages中先查找是否已經有了apk對應的LoadedApk ref = mResourcePackages.get(aInfo.packageName); } // 若是前面已經從mPackages或者mResourcePackages中找到了apk對應的LoadedApk,那麼就能夠直接返回了 // 沒有找到的話,就要建立LoadedApk對象了 if (packageInfo == null || (packageInfo.mResources != null && !packageInfo.mResources.getAssets().isUpToDate())) { // 建立LoadedApk對象 packageInfo = new LoadedApk(this, aInfo, compatInfo, baseLoader, securityViolation, includeCode && (aInfo.flags&ApplicationInfo.FLAG_HAS_CODE) != 0, registerPackage); if (mSystemThread && "android".equals(aInfo.packageName)) { packageInfo.installSystemApplicationInfo(aInfo, getSystemContext().mPackageInfo.getClassLoader()); } // 建立LoadedApk對象以後,將其加入對應的緩存列表中 if (differentUser) { // Caching not supported across users } else if (includeCode) { mPackages.put(aInfo.packageName, new WeakReference<LoadedApk>(packageInfo)); } else { mResourcePackages.put(aInfo.packageName, new WeakReference<LoadedApk>(packageInfo)); } } return packageInfo; } }
由以上代碼可知,當要獲取一個LoadedApk對象時,先從ActivityThread的兩個緩存列表:mPackages和mResourcePackages中尋找,沒找到的話纔會新建LoadedApk對象,而後將其加入對應的緩存列表中。當找到apk對應的LoadedApk對象後,以此爲參數建立Application的Context對象。
final ContextImpl appContext = ContextImpl.createAppContext(this, data.info); static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) { if (packageInfo == null) throw new IllegalArgumentException("packageInfo"); return new ContextImpl(null, mainThread, packageInfo, null, null, false, null, null, Display.INVALID_DISPLAY); } private ContextImpl( ContextImpl container, // 傳入null ActivityThread mainThread,// app的ActivityThread對象 LoadedApk packageInfo, // apk對應的LoadedApk對象 IBinder activityToken, // 傳入爲null UserHandle user, boolean restricted, Display display, Configuration overrideConfiguration, int createDisplayWithId) { mOuterContext = this; mMainThread = mainThread; mActivityToken = activityToken; mRestricted = restricted; if (user == null) { user = Process.myUserHandle(); } mUser = user; // context中會記錄apk對應的LoadedApk對象 mPackageInfo = packageInfo; // 資源管理相關,後續單獨開篇介紹 mResourcesManager = ResourcesManager.getInstance(); .............. Resources resources = packageInfo.getResources(mainThread); if (resources != null) { if (displayId != Display.DEFAULT_DISPLAY || overrideConfiguration != null || (compatInfo != null && compatInfo.applicationScale != resources.getCompatibilityInfo().applicationScale)) { resources = mResourcesManager.getTopLevelResources(packageInfo.getResDir(), packageInfo.getSplitResDirs(), packageInfo.getOverlayDirs(), packageInfo.getApplicationInfo().sharedLibraryFiles, displayId, overrideConfiguration, compatInfo); } } mResources = resources; if (container != null) { mBasePackageName = container.mBasePackageName; mOpPackageName = container.mOpPackageName; } else { // 記錄app包名 mBasePackageName = packageInfo.mPackageName; ApplicationInfo ainfo = packageInfo.getApplicationInfo(); if (ainfo.uid == Process.SYSTEM_UID && ainfo.uid != Process.myUid()) { mOpPackageName = ActivityThread.currentPackageName(); } else { mOpPackageName = mBasePackageName; } } // 內容提供者相關 mContentResolver = new ApplicationContentResolver(this, mainThread, user); }
bindApplication()方法關鍵時序圖以下:
在這個方法中建立了Classloader,以及Application對象。而後執行Application對象的attach方法,這個方法中又會調用attachBaseContext()方法。也就是說Application對象首先被執行的方法不是onCreate()方法,而是attach()方法。
由ActivityThread.main的總體執行時序圖中可知,啓動activity的最終是attachApplicationLocked()方法。
boolean attachApplicationLocked(ProcessRecord app) throws RemoteException { final String processName = app.processName; boolean didSomething = false; for (int displayNdx = mActivityDisplays.size() - 1; displayNdx >= 0; --displayNdx) { ArrayList<ActivityStack> stacks = mActivityDisplays.valueAt(displayNdx).mStacks; for (int stackNdx = stacks.size() - 1; stackNdx >= 0; --stackNdx) { final ActivityStack stack = stacks.get(stackNdx); // 從 如何啓動app中篇之Task的管理 可知,此時mFocusedStack指向即將要運行的activity所在的ActivityStack // 下面這個方法就是爲了從衆多ActivityStack找到這個ActivityStack if (!isFrontStack(stack)) { continue; } // 找到了所需的ActivityStack // 而後找到其棧頂的Activity,實際就是mTaskHistory數組末端的Task的頂端Activity ActivityRecord hr = stack.topRunningActivityLocked(null); if (hr != null) { if (hr.app == null && app.uid == hr.info.applicationInfo.uid && processName.equals(hr.processName)) { try { if (realStartActivityLocked(hr, app, true, true)) { didSomething = true; } } catch (RemoteException e) { Slog.w(TAG, "Exception in new application when starting activity " + hr.intent.getComponent().flattenToShortString(), e); throw e; } } } } } if (!didSomething) { ensureActivitiesVisibleLocked(null, 0); } return didSomething; }
ActivityStackSupervisor的流程調用關係能夠用下面的流程圖表示。