<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                AMS的main函數將返回一個Context類型的對象,該對象在SystemServer中被其他服務大量使用。Context,顧名思義,代表了一種上下文環境(筆者覺得其意義和JNIEnv類似),有了這個環境,我們就可以做很多事情(例如獲取該環境中的資源、Java類信息等)。那么AMS的main將返回一個怎樣的上下文環境呢?來看以下代碼: **ActivityManagerService.java::main** ~~~ publicstatic final Context main(int factoryTest) { AThreadthr = new AThread();//①創建一個AThread線程對象 thr.start(); ......//等待thr創建成功 ActivityManagerServicem = thr.mService; mSelf =m; //②調用ActivityThread的systemMain函數 ActivityThreadat = ActivityThread.systemMain(); mSystemThread= at; //③得到一個Context對象,注意調用的函數名為getSystemContext,何為System Context Contextcontext = at.getSystemContext(); context.setTheme(android.R.style.Theme_Holo); m.mContext= context; m.mFactoryTest= factoryTest; //ActivtyStack是AMS中用來管理Activity的啟動和調度的核心類,以后再分析它 m.mMainStack = new ActivityStack(m, context,true); //調用BSS的publish函數,我們在第5章的BSS知識中介紹過了 m.mBatteryStatsService.publish(context); //另外一個service:UsageStatsService。后續再分析該服務 m.mUsageStatsService.publish(context); synchronized (thr) { thr.mReady = true; thr.notifyAll();//通知thr線程,本線程工作完成 } //④調用AMS的startRunning函數 m.startRunning(null, null, null, null); returncontext; } ~~~ 在main函數中,我們又列出了4個關鍵函數,分別是: - 創建AThread線程。雖然AMS的main函數由ServerThread線程調用,但是AMS自己的工作并沒有放在ServerThread中去做,而是新創建了一個線程,即AThread線程。 - ActivityThread.systemMain函數。初始化ActivityThread對象。 - ActivityThread.getSystemContext函數。用于獲取一個Context對象,從函數名上看,該Context代表了System的上下文環境。 - AMS的startRunning函數。 注意,main函數中有一處等待(wait)及一處通知(notifyAll),原因是: - main函數首先需要等待AThread所在線程啟動并完成一部分工作。 - AThread完成那一部分工作后,將等待main函數完成后續的工作。 這種雙線程互相等待的情況,在Android代碼中比較少見,讀者只需了解它們的目的即可。下邊來分析以上代碼中的第一個關鍵點。 1. AThread分析 (1) AThread分析 AThread的代碼如下: **ActivityManagerService.java::AThread** ~~~ static class AThread extends Thread {//AThread從Thread類派生 ActivityManagerServicemService; booleanmReady = false; publicAThread() { super("ActivityManager");//線程名就叫“ActivityManager” } publicvoid run() { Looper.prepare();//看來,AThread線程將支持消息循環及處理功能 android.os.Process.setThreadPriority(//設置線程優先級 android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); //創建AMS對象 ActivityManagerService m = new ActivityManagerService(); synchronized (this) { mService= m;//賦值AThread內部成員變量mService,指向AMS notifyAll(); //通知main函數所在線程 } synchronized (this) { while (!mReady) { try{ wait();//等待main函數所在線程的notifyAll }...... } }...... Looper.loop();//進入消息循環 } } ~~~ 從本質上說,AThread是一個支持消息循環及處理的線程,其主要工作就是創建AMS對象,然后通知AMS的main函數。這樣看來,main函數等待的就是這個AMS對象。 (2) AMS的構造函數分析 AMS的構造函數的代碼如下: **ActivityManagerService.java::ActivityManagerService構造** ~~~ private ActivityManagerService() { FiledataDir = Environment.getDataDirectory();//指向/data/目錄 FilesystemDir = new File(dataDir, "system");//指向/data/system/目錄 systemDir.mkdirs();//創建/data/system/目錄 //創建BatteryStatsService(以后簡稱BSS)和UsageStatsService(以后簡稱USS) //我們在分析PowerManageService時已經見過BSS了 mBatteryStatsService = new BatteryStatsService(new File( systemDir, "batterystats.bin").toString()); mBatteryStatsService.getActiveStatistics().readLocked(); mBatteryStatsService.getActiveStatistics().writeAsyncLocked(); mOnBattery = DEBUG_POWER ? true : mBatteryStatsService.getActiveStatistics().getIsOnBattery(); mBatteryStatsService.getActiveStatistics().setCallback(this); //創建USS mUsageStatsService= new UsageStatsService(new File( systemDir, "usagestats").toString()); //獲取OpenGl版本 GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version", ConfigurationInfo.GL_ES_VERSION_UNDEFINED); //mConfiguration類型為Configuration,用于描述資源文件的配置屬性,例如 //字體、語言等。后文再討論這方面的內容 mConfiguration.setToDefaults(); mConfiguration.locale = Locale.getDefault(); //mProcessStats為ProcessStats類型,用于統計CPU、內存等信息。其內部工作原理就是 //讀取并解析/proc/stat文件的內容。該文件由內核生成,用于記錄kernel及system //一些運行時的統計信息。讀者可在Linux系統上通過man proc命令查詢詳細信息 mProcessStats.init(); //解析/data/system/packages-compat.xml文件,該文件用于存儲那些需要考慮屏幕尺寸 //的APK的一些信息。讀者可參考AndroidManifest.xml中compatible-screens相關說明。 //當APK所運行的設備不滿足要求時,AMS會根據設置的參數以采用屏幕兼容的方式去運行它 mCompatModePackages = new CompatModePackages(this, systemDir); Watchdog.getInstance().addMonitor(this); //創建一個新線程,用于定時更新系統信息(和mProcessStats交互) mProcessStatsThread = new Thread("ProcessStats") {...//先略去該段代碼} mProcessStatsThread.start(); } ~~~ AMS的構造函數比想象得要簡單些,下面回顧一下它的工作: - 創建BSS、USS、mProcessStats (ProcessStats類型)、mProcessStatsThread線程,這些都與系統運行狀況統計相關。 - 創建/data/system目錄,為mCompatModePackages(CompatModePackages類型)和mConfiguration(Configuration類型)等成員變量賦值。 AMS main函數的第一個關鍵點就分析到此,再來分析它的第二個關鍵點。 2. ActivityThread.systemMain函數分析 ActivityThread是Android Framework中一個非常重要的類,它代表一個應用進程的主線程(對于應用進程來說,ActivityThread的main函數確實是由該進程的主線程執行),其職責就是調度及執行在該線程中運行的四大組件。 >[info] **注意**:應用進程指那些運行APK的進程,它們由Zyote 派生(fork)而來,上面運行了dalvik虛擬機。與應用進程相對的就是系統進程(包括Zygote和SystemServer)。 >另外,讀者須將“應用進程和系統進程”與“應用APK和系統APK”的概念區分開來。APK的判別依賴其文件所在位置(如果apk文件在/data/app目錄下,則為應用APK)。 該函數代碼如下: **ActivityThread.java::systemMain** ~~~ public static final ActivityThread systemMain() { HardwareRenderer.disable(true);//禁止硬件渲染加速 //創建一個ActivityThread對象,其構造函數非常簡單 ActivityThread thread = new ActivityThread(); thread.attach(true);//調用它的attach函數,注意傳遞的參數為true returnthread; } ~~~ 在分析ActivityThread的attach函數之前,先提一個問題供讀者思考:前面所說的ActivityThread代表應用進程(其上運行了APK)的主線程,而SystemServer并非一個應用進程,那么為什么此處也需要ActivityThread呢? - 還記得在PackageManagerService分析中提到的framework-res.apk嗎?這個APK除了包含資源文件外,還包含一些Activity(如關機對話框),這些Activity實際上運行在SystemServer進程中[^①]。從這個角度看,SystemServer是一個特殊的應用進程。 - 另外,通過ActivityThread可以把Android系統提供的組件之間的交互機制和交互接口(如利用Context提供的API)也拓展到SystemServer中使用。 * * * * * **提示**:解答這個問題,對于理解SystemServer中各服務的交互方式是尤其重要的。 * * * * * 下面來看ActivityThread的attach函數。 (1) attach函數分析 **ActivityThread.java::attach** ~~~ private void attach(boolean system) { sThreadLocal.set(this); mSystemThread= system;//判斷是否為系統進程 if(!system) { ......//應用進程的處理流程 } else {//系統進程的處理流程,該情況只在SystemServer中處理 //設置DDMS時看到的systemserver進程名為system_process android.ddm.DdmHandleAppName.setAppName("system_process"); try { //ActivityThread的幾員大將出場,見后文的分析 mInstrumentation = new Instrumentation(); ContextImpl context = new ContextImpl(); //初始化context,注意第一個參數值為getSystemContext context.init(getSystemContext().mPackageInfo, null, this); Application app = //利用Instrumentation創建一個Application對象 Instrumentation.newApplication(Application.class,context); //一個進程支持多個Application,mAllApplications用于保存該進程中 //的Application對象 mAllApplications.add(app); mInitialApplication = app;//設置mInitialApplication app.onCreate();//調用Application的onCreate函數 }......//try/catch結束 }//if(!system)判斷結束 //注冊Configuration變化的回調通知 ViewRootImpl.addConfigCallback(newComponentCallbacks2() { publicvoid onConfigurationChanged(Configuration newConfig) { ......//當系統配置發生變化(如語言切換等)時,需要調用該回調 } public void onLowMemory() {} public void onTrimMemory(int level) {} }); } ~~~ attach函數中出現了幾個重要成員,其類型分別是Instrumentation類、Application類及Context類,它們的作用如下(為了保證準確,這里先引用Android的官方說明)。 - Instrumentation:Base class for implementingapplication instrumentation code. When running with instrumentation turned on,this class will be instantiated for you before any of the application code,allowing you to monitor all of the interaction the system has with the application.An Instrumentation implementation is described to the system through anAndroidManifest.xml's <instrumentation> tag。大意是:Instrumentaion是一個工具類。當它被啟用時,系統先創建它,再通過它來創建其他組件。另外,系統和組件之間的交互也將通過Instrumentation來傳遞,這樣,Instrumentation就能監測系統和這些組件的交互情況了。在實際使用中,我們可以創建Instrumentation的派生類來進行相應的處理。讀者可查詢Android中Junit的使用來了解Intrstrumentation的作用。本書不討論Intrstrumentation方面的內容。 - Application:Base class for those who need tomaintain global application state. You can provide your own implementation byspecifying its name in your AndroidManifest.xml's <application> tag,which will cause that class to be instantiated for you when the process foryour application/package is created.大意是:Application類保存了一個全局的application狀態。Application由AndroidManifest.xml中的<application>標簽聲明。在實際使用時需定義Application的派生類。 - Context:Interface to global informationabout an application environment. This is an abstract class whoseimplementation is provided by the Android system. It allows access toapplication-specific resources and classes, as well as up-calls forapplication-level operations such as launching activities, broadcasting andreceiving intents, etc.大意是:Context是一個接口,通過它可以獲取并操作Application對應的資源、類,甚至包含于Application中的四大組件。 >[info] **提示**:此處的Application是Android中的一個概念,可理解為一種容器,它內部包含四大組件。另外,一個進程可以運行多個Application。 Context是一個抽象類,而由AMS創建的將是它的子類ContextImpl。如前所述,Context提供了Application的上下文信息,這些信息是如何傳遞給Context的呢?此問題包括兩個方面: - Context本身是什么? - Context背后所包含的上下文信息又是什么? 下面來關注上邊代碼中調用的getSystemContext函數。 (2) getSystemContext函數分析 **ActivityThread.java::getSystemContext** ~~~ public ContextImpl getSystemContext() { synchronized(this) { if(mSystemContext == null) {//單例模式 ContextImplcontext = ContextImpl.createSystemContext(this); //LoadedApk是2.3引入的一個新類,代表一個加載到系統中的APK LoadedApkinfo = new LoadedApk(this, "android", context, null, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO); //初始化該ContextImpl對象 context.init(info, null, this); //初始化資源信息 context.getResources().updateConfiguration( getConfiguration(),getDisplayMetricsLocked( CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, false)); mSystemContext = context;//保存這個特殊的ContextImpl對象 } } returnmSystemContext; } ~~~ 以上代碼無非是先創建一個ContextImpl,然后再將其初始化(調用init函數)。為什么函數名是getSystemContext呢?因為在初始化ContextImp時使用了一個LoadedApk對象。如注釋中所說,LoadedApk是Android 2.3引入的一個類,該類用于保存一些和APK相關的信息(如資源文件位置、JNI庫位置等)。在getSystemContext函數中初始化ContextImpl的這個LoadedApk所代表的package名為“android”,其實就是framework-res.apk,由于該APK僅供SystemServer使用,所以此處叫getSystemContext。 上面這些類的關系比較復雜,可通過圖6-2展示它們之間的關系。 :-: ![](http://img.blog.csdn.net/20150803122554489?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖6-2 ContextImpl和它的“兄弟”們 由圖6-2可知: - 先來看派生關系, ApplicationContentResolver從ConentResolver派生,它主要用于和ContentProvider打交道。ContextImpl和ContextWrapper均從Context繼承,而Application則從ContextWrapper派生。 - 從社會關系角度看,ContextImpl交際面最廣。它通過mResources指向Resources,mPackageInfo指向LoadedApk,mMainThread指向ActivityThread,mContentResolver指向ApplicationContentResolver。 - ActivityThread代表主線程,它通過mInstrumentation指向Instrumentation。另外,它還保存多個Application對象。 * * * * * **注意**:在函數中有些成員變量的類型為基類類型,而在圖6-2中直接指向了實際類型。 * * * * * (3) systemMain函數總結 調用systemMain函數結束后,我們得到了什么? - 得到一個ActivityThread對象,它代表應用進程的主線程。 - 得到一個Context對象,它背后所指向的Application環境與framework-res.apk有關。 費了如此大的功夫,systemMain函數的目的到底是什么?一針見血地說: systemMain函數將為SystemServer進程搭建一個和應用進程一樣的Android運行環境。這句話涉及兩個概念。 - 進程:來源于操作系統,是在OS中看到的運行體。我們編寫的代碼一定要運行在一個進程中。 - Android運行環境:Android努力構筑了一個自己的運行環境。在這個環境中,進程的概念被模糊化了。組件的運行及它們之間的交互均在該環境中實現。 Android運行環境是構建在進程之上的。有Android開發經驗的讀者可能會發現,在應用程序中,一般只和Android運行環境交互。基于同樣的道理,SystemServer希望它內部的那些Service也通過Android運行環境交互,因此也需為它創建一個運行環境。由于SystemServer的特殊性,此處調用了systemMain函數,而普通的應用進程將在主線程中調用ActivityThread的main函數來創建Android運行環境。 另外,ActivityThread雖然本意是代表進程的主線程,但是作為一個Java類,它的實例到底由什么線程創建,恐怕不是ActivityThread自己能做主的,所以在SystemServer中可以發現,ActivityThread對象由其他線程創建,而在應用進程中,ActivityThread將由主線程來創建。 3. ActivityThread.getSystemContext函數分析 該函數在上一節已經見過了。調用該函數后,將得到一個代表系統進程的Context對象。到底什么是Context?先來看如圖6-3所示的Context家族圖譜。 * * * * * **注意**:該族譜成員并不完全。另外,Activity、Service和Application所實現的接口也未畫出。 * * * * * :-: ![](http://img.blog.csdn.net/20150803122622508?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖6-3 Context家族圖譜 由圖6-3可知: - ContextWrapper比較有意思,其在SDK中的說明為“Proxying implementation ofContext that simply delegates all of its calls to another Context. Can besubclassed to modify behavior without changing the original Context.”大概意思是:ContextWrapper是一個代理類,被代理的對象是另外一個Context。在圖6-3中,被代理的類其實是ContextImpl,由ContextWrapper通過mBase成員變量指定。讀者可查看ContextWrapper.java,其內部函數功能的實現最終都由mBase完成。這樣設計的目的是想把ContextImpl隱藏起來。 - Application從ContextWrapper派生,并實現了ComponentCallbacks2接口。Application中有一個LoadedApk類型的成員變量mLoadedApk。LoadedApk代表一個APK文件。由于一個AndroidManifest.xml文件只能聲明一個Application標簽,所以一個Application必然會和一個LoadedApk綁定。 - Service從ContextWrapper派生,其中Service內部成員變量mApplication指向Application(在AndroidManifest.xml中,Service只能作為Application的子標簽,所以在代碼中Service必然會和一個Application綁定)。 - ContextThemeWrapper重載了和Theme(主題)相關的兩個函數。這些和界面有關,所以Activity作為Android系統中的UI容器,必然也會從ContextThemeWrapper派生。與Service一樣,Activity內部也通過mApplication成員變量指向Application。 對Context的分析先到這里,再來分析第三個關鍵函數startRunning。 4. AMS的startRunning函數分析 **ActivityManagerService.java::startRunning** ~~~ //注意調用該函數時所傳遞的4個參數全為null public final void startRunning(String pkg, Stringcls, String action, String data) { synchronized(this) { if (mStartRunning) return; //如果已經調用過該函數,則直接返回 mStartRunning = true; //mTopComponent最終賦值為null mTopComponent = pkg != null && cls != null ? new ComponentName(pkg, cls) : null; mTopAction = action != null ? action : Intent.ACTION_MAIN; mTopData = data; //mTopData最終為null if(!mSystemReady) return; //此時mSystemReady為false,所以直接返回 } systemReady(null);//這個函數很重要,可惜不在本次startRunning中調用 } ~~~ startRunning函數很簡單,此處不贅述。 至此,ASM 的main函數所涉及的4個知識點已全部分析完。下面回顧一下AMS 的main函數的工作。 5. ActivityManagerService的main函數總結 AMS的main函數的目的有兩個: - 首先也是最容易想到的目的是創建AMS對象。 - 另外一個目的比較隱晦,但是非常重要,那就是創建一個供SystemServer進程使用的Android運行環境。 根據目前所分析的代碼,Android運行環境將包括兩個成員:ActivityThread和ContextImpl(一般用它的基類Context)。 圖6-4展示了在這兩個類中定義的一些成員變量,通過它們可看出ActivityThread及ContextImpl的作用。 :-: ![](http://img.blog.csdn.net/20150803122653459?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center) 圖6-4 ActivityThread和ContextImpl的部分成員變量 由圖6-4可知: - ActivityThread中有一個mLooper成員,它代表一個消息循環。這恐怕是ActivityThread被稱做“Thread”的一個直接證據。另外,mServices用于保存Service,Activities用于保存ActivityClientRecord,mAllApplications用于保存Application。關于這些變量的具體作用,以后遇到時再說。 - 對于ContextImpl,其成員變量表明它和資源、APK文件有關。 AMS的main函數先分析到此,至于其創建的Android運行環境將在下節分析中派上用場。 接下來分析AMS的第三個調用函數setSystemProcess。 [^①]:實際上,SettingsProvider.apk也運行于system_server進程中。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看