Android Applicaion組件創建的源代碼(Android 9,含代碼註釋)

1. 序列圖

1.1 簡化版序列圖

簡化版序列圖

1.2 完整版序列圖

完整版序列圖

2. Application創建過程源代碼

2.1 ActivityThread初始化

public static void main(String[] args) {
	Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ActivityThreadMain");
	
	// Install selective syscall interception
	// 安裝選擇性的系統調用攔截
	AndroidOs.install();
	
	// CloseGuard defaults to true and can be quite spammy.  We
	// disable it here, but selectively enable it later (via
	// StrictMode) on debug builds, but using DropBox, not logs.
	/*
	CloseGuard(工具類,用來記錄資源泄露的場景,比如使用完的資源(比如cursor/fd)沒有正常關閉),默認爲true,
	並且可能是垃圾郵件。 我們在這裏禁用它,可以在調試版本中有選擇地啓用它(通過StrictMode),使用DropBox而不是日誌。
	*/
	CloseGuard.setEnabled(false);
	
	Environment.initForCurrentUser();
	
	// Make sure TrustedCertificateStore looks in the right place for CA certificates
	// 確保TrustedCertificateStore可以正確查找到CA證書(數字證書)
	final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
	TrustedCertificateStore.setDefaultUserDirectory(configDir);
	
	Process.setArgV0("<pre-initialized>");
	
	Looper.prepareMainLooper();
	
	// Find the value for {@link #PROC_START_SEQ_IDENT} if provided on the command line.
	// It will be in the format "seq=114"
	/*
	找到命令行中的值{@link #PROC_START_SEQ_IDENT},值的格式爲"seq=114"
	*/
	long startSeq = 0;
	if (args != null) {
	    for (int i = args.length - 1; i >= 0; --i) {
	        if (args[i] != null && args[i].startsWith(PROC_START_SEQ_IDENT)) {
	            startSeq = Long.parseLong(
	                    args[i].substring(PROC_START_SEQ_IDENT.length()));
	        }
	    }
	}
	//實例化ActivityThread
	ActivityThread thread = new ActivityThread();
	//調用attach()
	thread.attach(false, startSeq);
	//創建主線程Handler
	if (sMainThreadHandler == null) {
	    sMainThreadHandler = thread.getHandler();
	}
	
	if (false) {
	    Looper.myLooper().setMessageLogging(new
	            LogPrinter(Log.DEBUG, "ActivityThread"));
	}
	
	// End of event ActivityThreadMain.
	// ActivityThreadMain事件結束
	Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
	//循環的從消息隊列中通過MessageQueue的next方法獲取Message
	//UI顯示刷新通過Handler處理,Looper會阻塞但不會卡死
	Looper.loop();
	
	throw new RuntimeException("Main thread loop unexpectedly exited");
}

2.2 ActivityThread的attach(…)函數

private void attach(boolean system, long startSeq) {
	sCurrentActivityThread = this;
	mSystemThread = system;
	if (!system) {
	    android.ddm.DdmHandleAppName.setAppName("<pre-initialized>",
	                                            UserHandle.myUserId());
	
	    RuntimeInit.setApplicationObject(mAppThread.asBinder());
	    //獲取ActivityManager Service代理對象
	final IActivityManager mgr = ActivityManager.getService();
	    try {
	//通知AMS(Android中系統服務,可統一調度所有應用的Activity)進行application的初始化
	        mgr.attachApplication(mAppThread, startSeq);
	    } catch (RemoteException ex) {
	        throw ex.rethrowFromSystemServer();
	    }
	    // Watch for getting close to heap limit.
	// 注意接近堆限制
	    BinderInternal.addGcWatcher(new Runnable() {
	        @Override public void run() {
	            if (!mSomeActivitiesChanged) {
	                return;
	            }
	            Runtime runtime = Runtime.getRuntime();
	            long dalvikMax = runtime.maxMemory();
	            long dalvikUsed = runtime.totalMemory() - runtime.freeMemory();
	            if (dalvikUsed > ((3*dalvikMax)/4)) {
	                if (DEBUG_MEMORY_TRIM) Slog.d(TAG, "Dalvik max=" + (dalvikMax/1024)
	                        + " total=" + (runtime.totalMemory()/1024)
	                        + " used=" + (dalvikUsed/1024));
	                mSomeActivitiesChanged = false;
	                try {
	                    ActivityTaskManager.getService().releaseSomeActivities(mAppThread);
	                } catch (RemoteException e) {
	                    throw e.rethrowFromSystemServer();
	                }
	            }
	        }
	    });
	} else {
	    // Don't set application object here -- if the system crashes,
	    // we can't display an alert, we just want to die die die.
	/*
	不要在這裏設置應用程序對象-如果系統崩潰,我們將無法顯示提醒,我們只是想關閉。
	*/
	    android.ddm.DdmHandleAppName.setAppName("system_process",
	            UserHandle.myUserId());
	    try {
	//創建Instrumentation,負責跟蹤Application在Activity的生命週期
	        mInstrumentation = new Instrumentation();
	        mInstrumentation.basicInit(this);
	        ContextImpl context = ContextImpl.createAppContext(
	                this, getSystemContext().mPackageInfo);
	        mInitialApplication = context.mPackageInfo.makeApplication(true, null);
	        mInitialApplication.onCreate();
	    } catch (Exception e) {
	        throw new RuntimeException(
	                "Unable to instantiate Application():" + e.toString(), e);
	    }
	}
	
	ViewRootImpl.ConfigChangedCallback configChangedCallback
	        = (Configuration globalConfig) -> {
	    synchronized (mResourcesManager) {
	        // We need to apply this change to the resources immediately, because upon returning
	        // the view hierarchy will be informed about it.
	/*
	我們需要立即將此更改應用於資源,因爲返回後,視圖層次結構將被提示
	*/
	        if (mResourcesManager.applyConfigurationToResourcesLocked(globalConfig,
	                null /* compat */)) {
	            updateLocaleListFromAppContext(mInitialApplication.getApplicationContext(),
	                    mResourcesManager.getConfiguration().getLocales());
	
	            // This actually changed the resources! Tell everyone about it.
	// 改變了資源
	            if (mPendingConfiguration == null
	                    || mPendingConfiguration.isOtherSeqNewer(globalConfig)) {
	                mPendingConfiguration = globalConfig;
	                sendMessage(H.CONFIGURATION_CHANGED, globalConfig);
	            }
	        }
	    }
	};
	ViewRootImpl.addConfigCallback(configChangedCallback);
}

2.3 ActivityManagerService的attachApplication函數

public final void attachApplication(IApplicationThread thread, long startSeq) {
	synchronized (this) {
	//獲取遠程Binder調用端的Pid,Uid
	    int callingPid = Binder.getCallingPid();
	    final int callingUid = Binder.getCallingUid();
	//清空遠程調用端的Uid和Pid,用當前本地進程的Uid和Pid替代
	    final long origId = Binder.clearCallingIdentity();
	//調用attachApplicationLocked()
	    attachApplicationLocked(thread, callingPid, callingUid, startSeq);
	//通過origId變量,還原遠程Binder調用端的Uid和Pid信息
	    Binder.restoreCallingIdentity(origId);
	}
}

2.4 ActivityManagerService的attachApplicationLocked函數

private final boolean attachApplicationLocked(IApplicationThread thread, int pid, int callingUid, long startSeq) {
	//...
	//ActivityThread啓動application
	thread.bindApplication(processName, appInfo, providers,
			instr2.mClass,
			profilerInfo, instr2.mArguments,
			instr2.mWatcher,
			instr2.mUiAutomationConnection, testMode,
			mBinderTransactionTrackingEnabled, enableTrackAllocation,
			isRestrictedBackupMode || !normalMode, app.isPersistent(),
			new Configuration(app.getWindowProcessController().getConfiguration()),
			app.compat, getCommonServicesLocked(app.isolated),
			mCoreSettingsObserver.getCoreSettingsLocked(),
			buildSerial, autofillOptions, contentCaptureOptions);
	//...
}

2.5 ActivityThread的handleBindApplication函數

private void handleBindApplication(AppBindData data) {
	// Register the UI Thread as a sensitive thread to the runtime.
	// 將UI線程註冊爲虛擬機(VMRuntime)
	VMRuntime.registerSensitiveThread();
	// In the case the stack depth property exists, pass it down to the runtime.
	// 如果存在堆棧深度屬性,則將其傳遞給虛擬機
	String property = SystemProperties.get("debug.allocTracker.stackDepth");
	if (property.length() != 0) {
	    VMDebug.setAllocTrackerStackDepth(Integer.parseInt(property));
	}
	if (data.trackAllocation) {
	    DdmVmInternal.enableRecentAllocations(true);
	}
	// Note when this process has started.
	// 注意進程開始時間
	Process.setStartTimes(SystemClock.elapsedRealtime(), SystemClock.uptimeMillis());
	mBoundApplication = data;
	mConfiguration = new Configuration(data.config);
	mCompatConfiguration = new Configuration(data.config);
	mProfiler = new Profiler();
	String agent = null;
	if (data.initProfilerInfo != null) {
	    mProfiler.profileFile = data.initProfilerInfo.profileFile;
	    mProfiler.profileFd = data.initProfilerInfo.profileFd;
	    mProfiler.samplingInterval = data.initProfilerInfo.samplingInterval;
	    mProfiler.autoStopProfiler = data.initProfilerInfo.autoStopProfiler;
	    mProfiler.streamingOutput = data.initProfilerInfo.streamingOutput;
	    if (data.initProfilerInfo.attachAgentDuringBind) {
	        agent = data.initProfilerInfo.agent;
	    }
	}
	// send up app name; do this *before* waiting for debugger
	// 發送app名稱;在此之前等待調試器(debugger)
	Process.setArgV0(data.processName);
	android.ddm.DdmHandleAppName.setAppName(data.processName,
	                                        UserHandle.myUserId());
	VMRuntime.setProcessPackageName(data.appInfo.packageName);
	// Pass data directory path to ART. This is used for caching information and
	// should be set before any application code is loaded.
	// 將數據目錄路徑傳遞到ART(Android Runtime)。用於緩存信息,應在加載任何應用程序代碼之前進行設置。
	// Android 4.4中可選擇性開啓ART,Android 5.0後完全替代Dalvik虛擬機
	VMRuntime.setProcessDataDirectory(data.appInfo.dataDir);
	if (mProfiler.profileFd != null) {
	    mProfiler.startProfiling();
	}
	// If the app is Honeycomb MR1 or earlier, switch its AsyncTask
	// implementation to use the pool executor.  Normally, we use the
	// serialized executor as the default. This has to happen in the
	// main thread so the main looper is set right.
	/*
	如果應用程序是Honeycomb MR1或更早版本,需切換其AsyncTask實現以使用池執行程序。
	通常,我們使用序列化的執行程序作爲默認值。這必須在主線程中發生,因此主Looper需設置正確。
	*/
	if (data.appInfo.targetSdkVersion <= android.os.Build.VERSION_CODES.HONEYCOMB_MR1) {
	    AsyncTask.setDefaultExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
	}
	// Let the util.*Array classes maintain "undefined" for apps targeting Pie or earlier.
	// 讓util.*Array中的類文件維護Android Q或者更早版本的未定義App
	UtilConfig.setThrowExceptionForUpperArrayOutOfBounds(
	        data.appInfo.targetSdkVersion >= Build.VERSION_CODES.Q);
	Message.updateCheckRecycle(data.appInfo.targetSdkVersion);
	// Prior to P, internal calls to decode Bitmaps used BitmapFactory,
	// which may scale up to account for density. In P, we switched to
	// ImageDecoder, which skips the upscale to save memory. ImageDecoder
	// needs to still scale up in older apps, in case they rely on the
	// size of the Bitmap without considering its density.
	/*
	在P之前,對Bitmap進行內部解碼的調用使用了BitmapFactory,它可以擴展以解決密度問題。 
	在P中,我們切換到ImageDecoder,它跳過了消耗高的代碼以節省內存。 如果舊版本的應用程序
	依賴於位圖的大小而不考慮其密度,則ImageDecoder仍需要在舊版應用程序中進行擴展
	*/
	ImageDecoder.sApiLevel = data.appInfo.targetSdkVersion;
	/*
	 * Before spawning a new process, reset the time zone to be the system time zone.
	 * This needs to be done because the system time zone could have changed after the
	 * the spawning of this process. Without doing this this process would have the incorrect
	 * system time zone.
	 */
	/*
	在產生新進程之前,需將時區重置爲系統時區,因爲系統時區可能在該進程產生後已更改。
	如果不這樣做,此過程可能會有不正確的系統時區。
	*/
	TimeZone.setDefault(null);
	/*
	 * Set the LocaleList. This may change once we create the App Context.
	 */
	/*
	設置LocaleList。 一旦創建了應用上下文,LocaleList可能會改變
	*/
	LocaleList.setDefault(data.config.getLocales());
	synchronized (mResourcesManager) {
	    /*
	     * Update the system configuration since its preloaded and might not
	     * reflect configuration changes. The configuration object passed
	     * in AppBindData can be safely assumed to be up to date
	     */
	/*
	由於系統配置已預先加載,因此可能會更新,因此可能無法反映配置更改。 
	可以安全地假定AppBindData中傳遞的配置對象是最新的
	*/
	mResourcesManager.applyConfigurationToResourcesLocked(data.config, data.compatInfo);
	    mCurDefaultDisplayDpi = data.config.densityDpi;
	
	    // This calls mResourcesManager so keep it within the synchronized block.
	// 調用mResourcesManager,並將其保留在同步塊中
	    applyCompatConfiguration(mCurDefaultDisplayDpi);
	}
	data.info = getPackageInfoNoCheck(data.appInfo, data.compatInfo);
	if (agent != null) {
	    handleAttachAgent(agent, data.info);
	}
	/**
	 * Switch this process to density compatibility mode if needed.
	 */
	if ((data.appInfo.flags&ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES)
	        == 0) {
	    mDensityCompatMode = true;
	    Bitmap.setDefaultDensity(DisplayMetrics.DENSITY_DEFAULT);
	}
	updateDefaultDensity();
	final String use24HourSetting = mCoreSettings.getString(Settings.System.TIME_12_24);
	Boolean is24Hr = null;
	if (use24HourSetting != null) {
	    is24Hr = "24".equals(use24HourSetting) ? Boolean.TRUE : Boolean.FALSE;
	}
	// null : use locale default for 12/24 hour formatting,
	// false : use 12 hour format,
	// true : use 24 hour format.
	/*
	null:使用默認環境下的12/24小時格式,
	false:使用12小時格式,
	true:使用24小時格式。
	*/
	DateFormat.set24HourTimePref(is24Hr);
	updateDebugViewAttributeState();
	StrictMode.initThreadDefaults(data.appInfo);
	StrictMode.initVmDefaults(data.appInfo);
	if (data.debugMode != ApplicationThreadConstants.DEBUG_OFF) {
	    // XXX should have option to change the port.
	// XXX應該可以選擇更改端口
	    Debug.changeDebugPort(8100);
	    if (data.debugMode == ApplicationThreadConstants.DEBUG_WAIT) {
	        Slog.w(TAG, "Application " + data.info.getPackageName()
	              + " is waiting for the debugger on port 8100...");
	        IActivityManager mgr = ActivityManager.getService();
	        try {
	            mgr.showWaitingForDebugger(mAppThread, true);
	        } catch (RemoteException ex) {
	            throw ex.rethrowFromSystemServer();
	        }
	        Debug.waitForDebugger();
	        try {
	            mgr.showWaitingForDebugger(mAppThread, false);
	        } catch (RemoteException ex) {
	            throw ex.rethrowFromSystemServer();
	        }
	    } else {
	        Slog.w(TAG, "Application " + data.info.getPackageName()
	              + " can be debugged on port 8100...");
	    }
	}
	// Allow binder tracing, and application-generated systrace messages if we're profileable.
	// 允許Binder(進程間通信機制)跟蹤,則允許綁定程序跟蹤和應用程序生成的系統跟蹤消息
	boolean isAppProfileable = data.appInfo.isProfileableByShell();
	Trace.setAppTracingAllowed(isAppProfileable);
	if (isAppProfileable && data.enableBinderTracking) {
	    Binder.enableTracing();
	}
	// Initialize heap profiling.
	// 初始化堆分析
	if (isAppProfileable || Build.IS_DEBUGGABLE) {
	    nInitZygoteChildHeapProfiling();
	}
	// Allow renderer debugging features if we're debuggable.
	// 如果我們是可調試的,則允許渲染器調試功能
	boolean isAppDebuggable = (data.appInfo.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
	HardwareRenderer.setDebuggingEnabled(isAppDebuggable || Build.IS_DEBUGGABLE);
	HardwareRenderer.setPackageName(data.appInfo.packageName);
	/**
	 * Initialize the default http proxy in this process for the reasons we set the time zone.
	 */
	//由於我們設置時區的原因,在此過程中初始化默認的http代理。
	Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Setup proxies");
	final IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
	if (b != null) {
	    // In pre-boot mode (doing initial launch to collect password), not
	    // all system is up.  This includes the connectivity service, so don't
	    // crash if we can't get it.
	/*
	在預引導模式下(進行初始啓動以收集密碼),並非所有系統都已啓動。 這包括連接服務,因此如果我們無法獲得連接,請不要崩潰
	*/
	    final IConnectivityManager service = IConnectivityManager.Stub.asInterface(b);
	    try { 		   	    	    	                         Proxy.setHttpProxySystemProperty(service.getProxyForNetwork(null));
	    } catch (RemoteException e) {
	        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
	        throw e.rethrowFromSystemServer();
	    }
	}
	Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
	
	// Instrumentation info affects the class loader, so load it before
	// setting up the app context.
	/*
	Instrumentation信息會影響類加載器,所以需要在設置應用程序上下文之前加載它。
	*/
	final InstrumentationInfo ii;
	if (data.instrumentationName != null) {
	    try {
	        ii = new ApplicationPackageManager(null, getPackageManager())
	                .getInstrumentationInfo(data.instrumentationName, 0);
	    } catch (PackageManager.NameNotFoundException e) {
	        throw new RuntimeException(
	                "Unable to find instrumentation info for: " + data.instrumentationName);
	    }
	    // Warn of potential ABI mismatches.
	// 警告潛在的ABI(Application Binary Interface,應用程序提供應用程序二進制接口,
	// 包含一系列的系統調用和使用這些系統調用的方法)不匹配。
	    if (!Objects.equals(data.appInfo.primaryCpuAbi, ii.primaryCpuAbi)
	            || !Objects.equals(data.appInfo.secondaryCpuAbi, ii.secondaryCpuAbi)) {
	        Slog.w(TAG, "Package uses different ABI(s) than its instrumentation: "
	                + "package[" + data.appInfo.packageName + "]: "
	                + data.appInfo.primaryCpuAbi + ", " + data.appInfo.secondaryCpuAbi
	                + " instrumentation[" + ii.packageName + "]: "
	                + ii.primaryCpuAbi + ", " + ii.secondaryCpuAbi);
	    }
	    mInstrumentationPackageName = ii.packageName;
	    mInstrumentationAppDir = ii.sourceDir;
	    mInstrumentationSplitAppDirs = ii.splitSourceDirs;
	    mInstrumentationLibDir = getInstrumentationLibrary(data.appInfo, ii);
	    mInstrumentedAppDir = data.info.getAppDir();
	    mInstrumentedSplitAppDirs = data.info.getSplitAppDirs();
	    mInstrumentedLibDir = data.info.getLibDir();
	} else {
	    ii = null;
	}
	//創建上下文對象
	final ContextImpl appContext = ContextImpl.createAppContext(this, data.info);
	updateLocaleListFromAppContext(appContext,
	        mResourcesManager.getConfiguration().getLocales());
	if (!Process.isIsolated()) {
	    final int oldMask = StrictMode.allowThreadDiskWritesMask();
	    try {
	        setupGraphicsSupport(appContext);
	    } finally {
	        StrictMode.setThreadPolicyMask(oldMask);
	    }
	} else {
	    HardwareRenderer.setIsolatedProcess(true);
	}
	// Install the Network Security Config Provider. This must happen before the application
	// code is loaded to prevent issues with instances of TLS objects being created before
	// the provider is installed.
	/*
	安裝網絡安全配置Provider。必須在加載應用代碼之前完成,以防止在安裝provider之前
	創建傳輸層安全協議(Transport Layer Security,TLS)對象實例的問題
	*/
	Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "NetworkSecurityConfigProvider.install");
	NetworkSecurityConfigProvider.install(appContext);
	Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
	// Continue loading instrumentation.
	// 繼續加載instrumentation(Android系統裏面的一套控制方法或者”鉤子“,用於在正常的生命週期之外控制控件的運行)
	if (ii != null) {
	    ApplicationInfo instrApp;
	    try {
	        instrApp = getPackageManager().getApplicationInfo(ii.packageName, 0,
	                UserHandle.myUserId());
	    } catch (RemoteException e) {
	        instrApp = null;
	    }
	    if (instrApp == null) {
	        instrApp = new ApplicationInfo();
	    }
	    ii.copyTo(instrApp);
	    instrApp.initForUser(UserHandle.myUserId());
	    final LoadedApk pi = getPackageInfo(instrApp, data.compatInfo,
	            appContext.getClassLoader(), false, true, false);
	    // The test context's op package name == the target app's op package name, because
	    // the app ops manager checks the op package name against the real calling UID,
	    // which is what the target package name is associated with.
	/*
	測試上下文的包名==目標應用程序的包名,因爲應用程序操作管理器會根據
	真實的調用UID(即目標程序包名稱與之關聯)來檢查包名。
	*/
	    final ContextImpl instrContext = ContextImpl.createAppContext(this, pi,
	            appContext.getOpPackageName());
	    try {
	        final ClassLoader cl = instrContext.getClassLoader();
	        mInstrumentation = (Instrumentation)
	            cl.loadClass(data.instrumentationName.getClassName()).newInstance();
	    } catch (Exception e) {
	        throw new RuntimeException(
	            "Unable to instantiate instrumentation "
	            + data.instrumentationName + ": " + e.toString(), e);
	    }
	    final ComponentName component = new ComponentName(ii.packageName, ii.name);
	    mInstrumentation.init(this, instrContext, appContext, component,
	            data.instrumentationWatcher, data.instrumentationUiAutomationConnection);
	    if (mProfiler.profileFile != null && !ii.handleProfiling
	            && mProfiler.profileFd == null) {
	        mProfiler.handlingProfiling = true;
	        final File file = new File(mProfiler.profileFile);
	        file.getParentFile().mkdirs();
	        Debug.startMethodTracing(file.toString(), 8 * 1024 * 1024);
	    }
	} else {
	//創建Instrumentation,負責跟蹤Application在Activity的生命週期
	    mInstrumentation = new Instrumentation();
	    mInstrumentation.basicInit(this);
	}
	if ((data.appInfo.flags&ApplicationInfo.FLAG_LARGE_HEAP) != 0) {
	    dalvik.system.VMRuntime.getRuntime().clearGrowthLimit();
	} else {
	    // Small heap, clamp to the current growth limit and let the heap release
	    // pages after the growth limit to the non growth limit capacity. b/18387825
	/*
	小堆,將其限制在當前的增長限制之內,然後讓堆在增長限制達到非增長限制容量之後釋放頁面
	*/
	    dalvik.system.VMRuntime.getRuntime().clampGrowthLimit();
	}
	// Allow disk access during application and provider setup. This could
	// block processing ordered broadcasts, but later processing would
	// probably end up doing the same disk access.
	/*
	在應用程序和provider程序設置期間允許磁盤訪問。這可能會阻止處理有序廣播,
	但是以後的處理可能最終會進行相同的磁盤訪問。
	*/
	Application app;
	final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskWrites();
	final StrictMode.ThreadPolicy writesAllowedPolicy = StrictMode.getThreadPolicy();
	try {
	    // If the app is being launched for full backup or restore, bring it up in
	    // a restricted environment with the base application class.
	// 如果運行app進行完全備份或還原,則需要在受限環境中通過基本application類將其啓動
	// 創建Application對象
	    app = data.info.makeApplication(data.restrictedBackupMode, null);
	    // Propagate autofill compat state
	// 傳播自動填充兼容狀態
	    app.setAutofillOptions(data.autofillOptions);
	    // Propagate Content Capture options
	// 傳播內容捕獲選項
	    app.setContentCaptureOptions(data.contentCaptureOptions);
	    mInitialApplication = app;
	    // don't bring up providers in restricted mode; they may depend on the
	    // app's custom Application class
	/*
	不要以受限模式啓動providers;它們可能取決於應用程序的自定義Application類
	*/
	    if (!data.restrictedBackupMode) {
	        if (!ArrayUtils.isEmpty(data.providers)) {
	            installContentProviders(app, data.providers);
	        }
	    }
	    // Do this after providers, since instrumentation tests generally start their
	    // test thread at this point, and we don't want that racing.
	/*
	在providers(Content Providers,用於共享數據給訪問者)之後執行此操作,通常情況下instrumentation測試會開始其測試線程,並且我們不希望它開啓
	*/
	    try {
	//調用Instrumentation的onCreate(),內部是空實現
	        mInstrumentation.onCreate(data.instrumentationArgs);
	    }
	    catch (Exception e) {
	        throw new RuntimeException(
	            "Exception thrown in onCreate() of "
	            + data.instrumentationName + ": " + e.toString(), e);
	    }
	    try {
	//調用Instrumentation的callApplicationOnCreate(),內部是調用Application的onCreate
	/*
	public class Instrumentation {
	public void callApplicationOnCreate(Application app) {
	app.onCreate();
	}
	}
	*/
	        mInstrumentation.callApplicationOnCreate(app);
	    } catch (Exception e) {
	        if (!mInstrumentation.onException(app, e)) {
	            throw new RuntimeException(
	              "Unable to create application " + app.getClass().getName()
	              + ": " + e.toString(), e);
	        }
	    }
	} finally {
	    // If the app targets < O-MR1, or doesn't change the thread policy
	    // during startup, clobber the policy to maintain behavior of b/36951662
	// 沒看懂
	    if (data.appInfo.targetSdkVersion < Build.VERSION_CODES.O_MR1
	            || StrictMode.getThreadPolicy().equals(writesAllowedPolicy)) {
	        StrictMode.setThreadPolicy(savedPolicy);
	    }
	}
	// Preload fonts resources
	// 預加載字體資源
	FontsContract.setApplicationContextForResources(appContext);
	if (!Process.isIsolated()) {
	    try {
	        final ApplicationInfo info =
	                getPackageManager().getApplicationInfo(
	                        data.appInfo.packageName,
	                        PackageManager.GET_META_DATA /*flags*/,
	                        UserHandle.myUserId());
	        if (info.metaData != null) {
	            final int preloadedFontsResource = info.metaData.getInt(
	                    ApplicationInfo.METADATA_PRELOADED_FONTS, 0);
	            if (preloadedFontsResource != 0) {
	                data.info.getResources().preloadFonts(preloadedFontsResource);
	            }
	        }
	    } catch (RemoteException e) {
	        throw e.rethrowFromSystemServer();
	    }
	}
   }

2.6 Instrumentation 的callApplicationOnCreate函數和newApplication函數

public void callApplicationOnCreate(Application app) {
	app.onCreate();
}
public Application newApplication(ClassLoader cl, String className, Context context)
	throws InstantiationException, IllegalAccessException, 
	ClassNotFoundException {
	Application app = getFactory(context.getPackageName())
	    .instantiateApplication(cl, className);
	//調用Application的attach
	app.attach(context);
	return app;
}

3. 另附兩篇Application源碼分析過程中的文章

  1. Android源代碼分析之類方法與組件名詞解釋https://blog.csdn.net/qq_26906345/article/details/103694786。
  2. Android Applicaion組件創建的源代碼流程分析
    https://blog.csdn.net/qq_26906345/article/details/103693846。

4. 參考文章

[1]: Android的Handler的簡單理解和使用. https://blog.csdn.net/weixin_43548748/article/details/91128791.
[2]: Android消息處理機制:Handler中sendMessage()方法的幾種重載方法. https://blog.csdn.net/fansl410k/article/details/79425765.
[3]: Android系統服務 —— WMS與AMS. https://www.jianshu.com/p/47eca41428d6.
[4]: Android源碼的Binder權限控制. https://blog.csdn.net/bbmcdull/article/details/52046690.
[5]: Binder進程間通信系統. Android系統源代碼情景分析.
[6]: Android進階(三):Application啓動過程(最詳細&最簡單). https://www.jianshu.com/p/4a8f44b6eecb.
[7]: Application初始化過程,基於android10. https://juejin.im/post/5ddb6b0de51d4523307fca86.
[8]: Android內存優化:DVM和ART原理初探. https://blog.csdn.net/weixin_42336002/article/details/80610555.
[9]: Content Provider組件的實現原理. Android系統源代碼情景分析.
[10]: Android HTTPS、TLS版本支持相關解決方案. https://blog.csdn.net/devrecord/article/details/88580235.
[11]: 不同版本的TLS在Android中的支持情況. https://blog.csdn.net/yanzhenjie1003/article/details/80202476.
[12]: 加密傳輸纔是王道!谷歌在 Android P 上默認啓用 TLS. https://www.oschina.net/news/95202/dns-over-tls-support-in-android-p.
[13]: Android instrumentation原理. https://blog.csdn.net/a19891024/article/details/54342799.
[14]: Instrumentation的理解. https://www.jianshu.com/p/5a7768f22b36.
[15]: Android ABI的淺析. https://www.jianshu.com/p/d2119b3880d8.
[16]: 關於BOOT_COMPLETED廣播-自啓動. https://www.jianshu.com/p/679dc03ee650.
[17]: PackageManagerService原理分析文章合集. https://www.douban.com/note/726553288/.
[18]: PackageManagerService服務框架詳解. https://www.jianshu.com/p/ef058fcfcd30.
[19]: Android 插件化原理解析——Hook機制之AMS&PMS.https://www.jianshu.com/p/8632fdc86009.
[20]: 一篇文章看明白 Android PackageManagerService 工作流程.https://blog.csdn.net/freekiteyu/article/details/82774947.

發佈了37 篇原創文章 · 獲贊 63 · 訪問量 11萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章