Android應(yīng)用程序組件Content Provider的啟動(dòng)過(guò)程源代碼分析_第1頁(yè)
Android應(yīng)用程序組件Content Provider的啟動(dòng)過(guò)程源代碼分析_第2頁(yè)
Android應(yīng)用程序組件Content Provider的啟動(dòng)過(guò)程源代碼分析_第3頁(yè)
Android應(yīng)用程序組件Content Provider的啟動(dòng)過(guò)程源代碼分析_第4頁(yè)
Android應(yīng)用程序組件Content Provider的啟動(dòng)過(guò)程源代碼分析_第5頁(yè)
已閱讀5頁(yè),還剩21頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

Android應(yīng)用程序組件ContentProvider的啟動(dòng)過(guò)程源代碼分析通過(guò)前面的學(xué)習(xí),我們知道在Android系統(tǒng)中,ContentProvider可以為不同的應(yīng)用程序訪問(wèn)相同的數(shù)據(jù)提供統(tǒng)一的入口。ContentProvider一般是運(yùn)行在獨(dú)立的進(jìn)程中的,每一個(gè)ContentProvider在系統(tǒng)中只有一個(gè)實(shí)例存在,其它應(yīng)用程序首先要找到這個(gè)實(shí)例,然后才能訪問(wèn)它的數(shù)據(jù)。那么,系統(tǒng)中的ContentProvider實(shí)例是由誰(shuí)來(lái)負(fù)責(zé)啟動(dòng)的呢?本文將回答這個(gè)問(wèn)題。ContentProvider和應(yīng)用程序組件Activity、Service一樣,需要在AndroidManifest.xml文件中配置之后才能使用。系統(tǒng)在安裝包含ContentProvider的應(yīng)用程序的時(shí)候,會(huì)把這些ContentProvider的描述信息保存起來(lái),其中最重要的就是ContentProvider的Authority信息,Android應(yīng)用程序的安裝過(guò)程具體可以參考一文。注意,安裝應(yīng)用程序的時(shí)候,并不會(huì)把相應(yīng)的ContentProvider加載到內(nèi)存中來(lái),系統(tǒng)采取的是懶加載的機(jī)制,等到第一次要使用這個(gè)ContentProvider的時(shí)候,系統(tǒng)才會(huì)把它加載到內(nèi)存中來(lái),下次再要使用這個(gè)ContentProvider的時(shí)候,就可以直接返回了。本文以前面一篇文章中的例子來(lái)詳細(xì)分析ContentProvider的啟動(dòng)過(guò)程。在這篇文章介紹的應(yīng)用程序Article中,第一次使用ArticlesProvider這個(gè)ContentProvider的地方是ArticlesAdapter類的getArticleCount函數(shù),因?yàn)镸ainActivity要在ListView中顯示文章信息列表時(shí),首先要知道ArticlesProvider中的文章信息的數(shù)量。從ArticlesAdapter類的getArticleCount函數(shù)調(diào)用開始,一直到ArticlesProvider類的onCreate函數(shù)被調(diào)用,就是ArticlesProvider的完整啟動(dòng)過(guò)程,下面我們就先看看這個(gè)過(guò)程的序列圖,然后再詳細(xì)分析每一個(gè)步驟:這個(gè)函數(shù)定義在前面一篇文章介紹的應(yīng)用程序Artilce源代碼工程目錄下,在文件為packages/experimental/Article/src/shy/luo/article/ArticlesAdapter.Java中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicclassArticlesAdapter{......privateContentResolverresolver=null;publicArticlesAdapter(Contextcontext){resolver=context.getContentResolver();}......publicintgetArticleCount(){intcount=0;try{IContentProviderprovider=resolver.acquireProvider(Articles.CONTENT_URI);Bundlebundle=provider.call(Articles.METHOD_GET_ITEM_COUNT,null,null);count=bundle.getInt(Articles.KEY_ITEM_COUNT,0);}catch(RemoteExceptione){e.printStackTrace();}returncount;}......}這個(gè)函數(shù)通過(guò)應(yīng)用程序上下文的ContentResolver接口resolver的acquireProvider函數(shù)來(lái)獲得與Articles.CONTENT_URI對(duì)應(yīng)的ContentProvider對(duì)象的IContentProvider接口。常量Articles.CONTENT_URI是在應(yīng)用程序ArticlesProvider中定義的,它的值為“content://viders.articles/item”,對(duì)應(yīng)的ContentProvider就是ArticlesProvider了。Step2.ContentResolver.acqireProvider這個(gè)函數(shù)定義在frameworks/base/core/java/android/content/ContentResolver.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicabstractclassContentResolver{......publicfinalIContentProvideracquireProvider(Uriuri){if(!SCHEME_CONTENT.equals(uri.getScheme())){returnnull;}Stringauth=uri.getAuthority();if(auth!=null){returnacquireProvider(mContext,uri.getAuthority());}returnnull;}......}函數(shù)首先驗(yàn)證參數(shù)uri的scheme是否正確,即是否是以content://開頭,然后取出它的authority部分,最后調(diào)用另外一個(gè)成員函數(shù)acquireProvider執(zhí)行獲取ContentProvider接口的操作。在我們這個(gè)情景中,參數(shù)uri的authority的內(nèi)容便是“viders.articles”了。從ContentResolver類的定義我們可以看出,它是一個(gè)抽象類,兩個(gè)參數(shù)版本的acquireProvider函數(shù)是由它的子類來(lái)實(shí)現(xiàn)的?;氐絊tep1中,這個(gè)ContentResolver接口是通過(guò)應(yīng)用程序上下文Context對(duì)象的getContentResolver函數(shù)來(lái)獲得的,而應(yīng)用程序上下文Context是由ContextImpl類來(lái)實(shí)現(xiàn)的,它定義在frameworks/base/core/java/android/app/ContextImpl.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片classContextImplextendsContext{......privateApplicationContentResolvermContentResolver;......finalvoidinit(LoadedApkpackageInfo,IBinderactivityToken,ActivityThreadmainThread,Resourcescontainer){......mContentResolver=newApplicationContentResolver(this,mainThread);......}......@OverridepublicContentResolvergetContentResolver(){returnmContentResolver;}......}ContextImpl類的init函數(shù)是在應(yīng)用程序啟動(dòng)的時(shí)候調(diào)用的,具體可以參考一文中的Step34。因此,在上面的ContentResolver類的acquireProvider函數(shù)里面接下來(lái)要調(diào)用的ApplicationContentResolver類的acquireProvider函數(shù)。Step3.ApplicationContentResolve.acquireProvider這個(gè)函數(shù)定義在frameworks/base/core/java/android/app/ContextImpl.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片classContextImplextendsContext{......privatestaticfinalclassApplicationContentResolverextendsContentResolver{......@OverrideprotectedIContentProvideracquireProvider(Contextcontext,Stringname){returnmMainThread.acquireProvider(context,name);}......privatefinalActivityThreadmMainThread;}......}它調(diào)用ActivityThread類的acquireProvider函數(shù)進(jìn)一步執(zhí)行獲取ContentProvider接口的操作。Step4.ActivityThread.acquireProvider這個(gè)函數(shù)定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityThread{......publicfinalIContentProvideracquireProvider(Contextc,Stringname){IContentProviderprovider=getProvider(c,name);if(provider==null)returnnull;......returnprovider;}......}它又是調(diào)用了另外一個(gè)成員函數(shù)getProvider來(lái)進(jìn)一步執(zhí)行獲取ContentProvider接口的操作。Step5.ActivityThread.getProvider這個(gè)函數(shù)定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityThread{......privatefinalIContentProvidergetExistingProvider(Contextcontext,Stringname){synchronized(mProviderMap){finalProviderClientRecordpr=mProviderMap.get(name);if(pr!=null){returnpr.mProvider;}returnnull;}}......privatefinalIContentProvidergetProvider(Contextcontext,Stringname){IContentProviderexisting=getExistingProvider(context,name);if(existing!=null){returnexisting;}IActivityManager.ContentProviderHolderholder=null;try{holder=ActivityManagerNative.getDefault().getContentProvider(getApplicationThread(),name);}catch(RemoteExceptionex){}IContentProviderprov=installProvider(context,vider,,true);......returnprov;}......}這個(gè)函數(shù)首先會(huì)通過(guò)getExistingProvider函數(shù)來(lái)檢查本地是否已經(jīng)存在這個(gè)要獲取的ContentProvider接口,如果存在,就直接返回了。本地已經(jīng)存在的ContextProvider接口保存在ActivityThread類的mProviderMap成員變量中,以ContentProvider對(duì)應(yīng)的URI的authority為鍵值保存。在我們這個(gè)情景中,因?yàn)槭堑谝淮握{(diào)用ArticlesProvider接口,因此,這時(shí)候通過(guò)getExistingProvider函數(shù)得到的IContentProvider接口為null,于是下面就會(huì)調(diào)用ActivityManagerService服務(wù)的getContentProvider接口來(lái)獲取一個(gè)ContentProviderHolder對(duì)象holder,這個(gè)對(duì)象就包含了我們所要獲取的ArticlesProvider接口,在將這個(gè)接口返回給調(diào)用者之后,還會(huì)調(diào)用installProvider函數(shù)來(lái)把這個(gè)接口保存在本地中,以便下次要使用這個(gè)ContentProvider接口時(shí),直接就可以通過(guò)getExistingProvider函數(shù)獲取了。我們先進(jìn)入到ActivityManagerService服務(wù)的getContentProvider函數(shù)中看看它是如何獲取我們所需要的ArticlesProvider接口的,然后再返回來(lái)看看installProvider函數(shù)的實(shí)現(xiàn)。Step6.ActivityManagerService.getContentProvider這個(gè)函數(shù)定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityManagerServiceextendsActivityManagerNativeimplementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback{......publicfinalContentProviderHoldergetContentProvider(IApplicationThreadcaller,Stringname){......returngetContentProviderImpl(caller,name);}......}它調(diào)用getContentProviderImpl函數(shù)來(lái)進(jìn)一步執(zhí)行操作。Step7.ActivityManagerService.getContentProviderImpl這個(gè)函數(shù)定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityManagerServiceextendsActivityManagerNativeimplementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback{......privatefinalContentProviderHoldergetContentProviderImpl(IApplicationThreadcaller,Stringname){ContentProviderRecordcpr;ProviderInfocpi=null;synchronized(this){ProcessRecordr=null;if(caller!=null){r=getRecordForAppLocked(caller);......}//Firstcheckifthiscontentproviderhasbeenpublished...cpr=mProvidersByName.get(name);if(cpr!=null){......}else{try{cpi=AppGlobals.getPackageManager().resolveContentProvider(name,STOCK_PM_FLAGS|PackageManager.GET_URI_PERMISSION_PATTERNS);}catch(RemoteExceptionex){}......}cpr=mProvidersByClass.get();finalbooleanfirstClass=cpr==null;if(firstClass){try{ApplicationInfoai=AppGlobals.getPackageManager().getApplicationInfo(cpi.applicationInfo.packageName,STOCK_PM_FLAGS);......cpr=newContentProviderRecord(cpi,ai);}catch(RemoteExceptionex){//pmisinsameprocess,thiswillneverhappen.}}if(r!=null&&cpr.canRunHere(r)){//Ifthisisamultiprocessprovider,thenjustreturnits//infoandallowthecallertoinstantiateit.Onlydo//thisiftheprovideristhesameuserasthecaller's//process,orcanrunasroot(socanbeinanyprocess).returncpr;}......//Thisissingleprocess,andourappisnowconnectingtoit.//Seeifwearealreadyintheprocessoflaunchingthis//provider.finalintN=mLaunchingProviders.size();inti;for(i=0;i<N;i++){if(mLaunchingProviders.get(i)==cpr){break;}}//Iftheproviderisnotalreadybeinglaunched,thengetit//started.if(i>=N){finallongorigId=Binder.clearCallingIdentity();ProcessRecordproc=startProcessLocked(cessName,cpr.appInfo,false,0,"contentprovider",newComponentName(cpi.applicationInfo.packageName,),false);......mLaunchingProviders.add(cpr);......}//Makesuretheproviderispublished(thesameproviderclass//maybepublishedundermultiplenames).if(firstClass){mProvidersByClass.put(,cpr);}cpr.launchingApp=proc;mProvidersByName.put(name,cpr);......}//Waitfortheprovidertobepublished...synchronized(cpr){while(vider==null){......try{cpr.wait();}catch(InterruptedExceptionex){}}}returncpr;}......}這個(gè)函數(shù)比較長(zhǎng),我們一步一步地分析。函數(shù)首先是獲取調(diào)用者的進(jìn)程記錄塊信息:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片ProcessRecordr=null;if(caller!=null){r=getRecordForAppLocked(caller);......}在我們這個(gè)情景中,要獲取的就是應(yīng)用程序Article的進(jìn)程記錄塊信息了,后面會(huì)用到。在ActivityManagerService中,有兩個(gè)成員變量是用來(lái)保存系統(tǒng)中的ContentProvider信息的,一個(gè)是mProvidersByName,一個(gè)是mProvidersByClass,前者是以ContentProvider的authoriry值為鍵值來(lái)保存的,后者是以ContentProvider的類名為鍵值來(lái)保存的。一個(gè)ContentProvider可以有多個(gè)authority,而只有一個(gè)類來(lái)和它對(duì)應(yīng),因此,這里要用兩個(gè)Map來(lái)保存,這里為了方便根據(jù)不同條件來(lái)快速查找而設(shè)計(jì)的。下面的代碼就是用來(lái)檢查要獲取的ContentProvider是否已經(jīng)加存在的了:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片//Firstcheckifthiscontentproviderhasbeenpublished...cpr=mProvidersByName.get(name);if(cpr!=null){......}else{try{cpi=AppGlobals.getPackageManager().resolveContentProvider(name,STOCK_PM_FLAGS|PackageManager.GET_URI_PERMISSION_PATTERNS);}catch(RemoteExceptionex){}......}cpr=mProvidersByClass.get();finalbooleanfirstClass=cpr==null;if(firstClass){try{ApplicationInfoai=AppGlobals.getPackageManager().getApplicationInfo(cpi.applicationInfo.packageName,STOCK_PM_FLAGS);......cpr=newContentProviderRecord(cpi,ai);}catch(RemoteExceptionex){//pmisinsameprocess,thiswillneverhappen.}}在我們這個(gè)情景中,由于是第一次調(diào)用ArticlesProvider接口,因此,在mProvidersByName和mProvidersByClass兩個(gè)Map中都不存在ArticlesProvider的相關(guān)信息,因此,這里會(huì)通過(guò)AppGlobals.getPackageManager函數(shù)來(lái)獲得PackageManagerService服務(wù)接口,然后分別通過(guò)它的resolveContentProvider和getApplicationInfo函數(shù)來(lái)分別獲取ArticlesProvider應(yīng)用程序的相關(guān)信息,分別保存在cpi和cpr這兩個(gè)本地變量中。這些信息都是在安裝應(yīng)用程序的過(guò)程中保存下來(lái)的,具體可以參考一文。接下去這個(gè)代碼判斷當(dāng)前要獲取的ContentProvider是否允許在客戶進(jìn)程中加載,即查看一個(gè)這個(gè)ContentProvider否配置了multiprocess屬性為true,如果允許在客戶進(jìn)程中加載,就直接返回了這個(gè)ContentProvider的信息了:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片if(r!=null&&cpr.canRunHere(r)){//Ifthisisamultiprocessprovider,thenjustreturnits//infoandallowthecallertoinstantiateit.Onlydo//thisiftheprovideristhesameuserasthecaller's//process,orcanrunasroot(socanbeinanyprocess).returncpr;}在我們這個(gè)情景中,要獲取的ArticlesProvider設(shè)置了要在獨(dú)立的進(jìn)程中運(yùn)行,因此,繼續(xù)往下執(zhí)行:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片//Thisissingleprocess,andourappisnowconnectingtoit.//Seeifwearealreadyintheprocessoflaunchingthis//provider.finalintN=mLaunchingProviders.size();inti;for(i=0;i<N;i++){if(mLaunchingProviders.get(i)==cpr){break;}}系統(tǒng)中所有正在加載的ContentProvider都保存在mLaunchingProviders成員變量中。在加載相應(yīng)的ContentProvider之前,首先要判斷一下它是可否正在被其它應(yīng)用程序加載,如果是的話,就不用重復(fù)加載了。在我們這個(gè)情景中,沒(méi)有其它應(yīng)用程序也正在加載ArticlesProvider這個(gè)ContentProvider,繼續(xù)往前執(zhí)行:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片//Iftheproviderisnotalreadybeinglaunched,thengetit//started.if(i>=N){finallongorigId=Binder.clearCallingIdentity();ProcessRecordproc=startProcessLocked(cessName,cpr.appInfo,false,0,"contentprovider",newComponentName(cpi.applicationInfo.packageName,),false);......mLaunchingProviders.add(cpr);......}這里的條件i>=N為true,就表明沒(méi)有其它應(yīng)用程序正在加載這個(gè)ContentProvider,因此,就要調(diào)用startProcessLocked函數(shù)來(lái)啟動(dòng)一個(gè)新的進(jìn)程來(lái)加載這個(gè)ContentProvider對(duì)應(yīng)的類了,然后把這個(gè)正在加載的信息增加到mLaunchingProviders中去。我們先接著分析這個(gè)函數(shù),然后再來(lái)看在新進(jìn)程中加載ContentProvider的過(guò)程,繼續(xù)往下執(zhí)行:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片//Makesuretheproviderispublished(thesameproviderclass//maybepublishedundermultiplenames).if(firstClass){mProvidersByClass.put(,cpr);}cpr.launchingApp=proc;mProvidersByName.put(name,cpr);這段代碼把這個(gè)ContentProvider的信息分別保存到mProvidersByName和mProviderByCalss兩個(gè)Map中去,以方便后續(xù)查詢。因?yàn)槲覀冃枰@取的ContentProvider是在新的進(jìn)程中加載的,而getContentProviderImpl這個(gè)函數(shù)是在系統(tǒng)進(jìn)程中執(zhí)行的,它必須要等到要獲取的ContentProvider是在新的進(jìn)程中加載完成后才能返回,這樣就涉及到進(jìn)程同步的問(wèn)題了。這里使用的同步方法是不斷地去檢查變量cpr的provider域是否被設(shè)置了。當(dāng)要獲取的ContentProvider在新的進(jìn)程加載完成之后,它會(huì)通過(guò)Binder進(jìn)程間通信機(jī)制調(diào)用到系統(tǒng)進(jìn)程中,把這個(gè)cpr變量的provider域設(shè)置為已經(jīng)加載好的ContentProvider接口,這時(shí)候,函數(shù)getContentProviderImpl就可以返回了。下面的代碼就是用來(lái)等待要獲取的ContentProvider是在新的進(jìn)程中加載完成的:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片//Waitfortheprovidertobepublished...synchronized(cpr){while(vider==null){......try{cpr.wait();}catch(InterruptedExceptionex){}}}下面我們?cè)俜治鲈谛逻M(jìn)程中加載ArticlesProvider這個(gè)ContentProvider的過(guò)程。Step8.ActivityManagerService.startProcessLockedStep9.Process.startStep10.ActivityThread.mainStep11.ActivityThread.attachStep12.ActivityManagerService.attachApplication這五步是標(biāo)準(zhǔn)的Android應(yīng)用程序啟動(dòng)步驟,具體可以參考一文中的Step23到Step27,或者一文中的Step4到Step9,這里就不再詳細(xì)描述了。Step13.ActivityManagerService.attachApplicationLocked這個(gè)函數(shù)定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityManagerServiceextendsActivityManagerNativeimplementsWatchdog.Monitor,BatteryStatsImpl.BatteryCallback{......privatefinalbooleanattachApplicationLocked(IApplicationThreadthread,intpid){//Findtheapplicationrecordthatisbeingattached...eithervia//thepidifwearerunninginmultipleprocesses,orjustpullthe//nextapprecordifweareemulatingprocesswithanonymousthreads.ProcessRecordapp;if(pid!=MY_PID&&pid>=0){synchronized(mPidsSelfLocked){app=mPidsSelfLocked.get(pid);}}elseif(mStartingProcesses.size()>0){......}else{......}......app.thread=thread;app.curAdj=app.setAdj=-100;app.curSchedGroup=Process.THREAD_GROUP_DEFAULT;app.setSchedGroup=Process.THREAD_GROUP_BG_NONINTERACTIVE;app.forcingToForeground=null;app.foregroundServices=false;app.debugging=false;......booleannormalMode=mProcessesReady||isAllowedWhileBooting();Listproviders=normalMode?generateApplicationProvidersLocked(app):null;try{......thread.bindApplication(processName,app.instrumentationInfo!=null?app.instrumentationInfo:,providers,app.instrumentationClass,app.instrumentationProfileFile,app.instrumentationArguments,app.instrumentationWatcher,testMode,isRestrictedBackupMode||!normalMode,mConfiguration,getCommonServicesLocked());......}catch(Exceptione){......}......returntrue;}......privatefinalListgenerateApplicationProvidersLocked(ProcessRecordapp){Listproviders=null;try{providers=AppGlobals.getPackageManager().queryContentProviders(cessName,.uid,STOCK_PM_FLAGS|PackageManager.GET_URI_PERMISSION_PATTERNS);}catch(RemoteExceptionex){}if(providers!=null){finalintN=providers.size();for(inti=0;i<N;i++){ProviderInfocpi=(ProviderInfo)providers.get(i);ContentProviderRecordcpr=mProvidersByClass.get();if(cpr==null){cpr=newContentProviderRecord(cpi,);mProvidersByClass.put(,cpr);}app.pubProviders.put(,cpr);app.addPackage(cpi.applicationInfo.packageName);ensurePackageDexOpt(cpi.applicationInfo.packageName);}}returnproviders;}......}這個(gè)函數(shù)首先是根據(jù)傳進(jìn)來(lái)的進(jìn)程ID找到相應(yīng)的進(jìn)程記錄塊,注意,這個(gè)進(jìn)程ID是應(yīng)用程序ArticlesProvider的ID,然后對(duì)這個(gè)進(jìn)程記錄塊做一些初傾始化的工作。再接下來(lái)通過(guò)調(diào)用generateApplicationProvidersLocked獲得需要在這個(gè)過(guò)程中加載的ContentProvider列表,在我們這個(gè)情景中,就只有ArticlesProvider這個(gè)ContentProvider了。最后調(diào)用從參數(shù)傳進(jìn)來(lái)的IApplicationThread對(duì)象thread的bindApplication函數(shù)來(lái)執(zhí)行一些應(yīng)用程序初始化工作。從一文中我們知道,在Android系統(tǒng)中,每一個(gè)應(yīng)用程序進(jìn)程都加載了一個(gè)ActivityThread實(shí)例,在這個(gè)ActivityThread實(shí)例里面,有一個(gè)成員變量mAppThread,它是一個(gè)Binder對(duì)象,類型為ApplicationThread,實(shí)現(xiàn)了IApplicationThread接口,它是專門用來(lái)和ActivityManagerService服務(wù)進(jìn)行通信的。因此,調(diào)用下面語(yǔ)句:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片thread.bindApplication(processName,app.instrumentationInfo!=null?app.instrumentationInfo:,providers,app.instrumentationClass,app.instrumentationProfileFile,app.instrumentationArguments,app.instrumentationWatcher,testMode,isRestrictedBackupMode||!normalMode,mConfiguration,getCommonServicesLocked());就會(huì)進(jìn)入到應(yīng)用程序ArticlesProvider進(jìn)程中的ApplicationThread對(duì)象的bindApplication函數(shù)中去。在我們這個(gè)情景場(chǎng),這個(gè)函數(shù)調(diào)用中最重要的參數(shù)便是第三個(gè)參數(shù)providers了,它是我們要處理的對(duì)象。Step14.ApplicationThread.bindApplication這個(gè)函數(shù)定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityThread{......privatefinalclassApplicationThreadextendsApplicationThreadNative{......publicfinalvoidbindApplication(StringprocessName,ApplicationInfoappInfo,List<ProviderInfo>providers,ComponentNameinstrumentationName,StringprofileFile,BundleinstrumentationArgs,IInstrumentationWatcherinstrumentationWatcher,intdebugMode,booleanisRestrictedBackupMode,Configurationconfig,Map<String,IBinder>services){if(services!=null){//SetuptheservicecacheintheServiceManagerServiceManager.initServiceCache(services);}AppBindDatadata=newAppBindData();cessName=processName;data.appInfo=appInfo;viders=providers;data.instrumentationName=instrumentationName;fileFile=profileFile;data.instrumentationArgs=instrumentationArgs;data.instrumentationWatcher=instrumentationWatcher;data.debugMode=debugMode;data.restrictedBackupMode=isRestrictedBackupMode;data.config=config;queueOrSendMessage(H.BIND_APPLICATION,data);}......}......}這個(gè)函數(shù)把相關(guān)的信息都封裝成一個(gè)AppBindData對(duì)象,然后以一個(gè)消息的形式發(fā)送到主線程的消息隊(duì)列中去等等待處理。這個(gè)消息最終是是在ActivityThread類的handleBindApplication函數(shù)中進(jìn)行處理的。Step15.ActivityThread.handleBindApplication這個(gè)函數(shù)定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityThread{......privatefinalvoidhandleBindApplication(AppBindDatadata){......List<ProviderInfo>providers=viders;if(providers!=null){installContentProviders(app,providers);......}......}......}這個(gè)函數(shù)的內(nèi)容比較多,我們忽略了其它無(wú)關(guān)的部分,只關(guān)注和ContentProvider有關(guān)的邏輯,這里主要就是調(diào)用installContentProviders函數(shù)來(lái)在本地安裝ContentProviders信息。Step16.ActivityThread.installContentProviders這個(gè)函數(shù)定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityThread{......privatefinalvoidinstallContentProviders(Contextcontext,List<ProviderInfo>providers){finalArrayList<IActivityManager.ContentProviderHolder>results=newArrayList<IActivityManager.ContentProviderHolder>();Iterator<ProviderInfo>i=providers.iterator();while(i.hasNext()){ProviderInfocpi=i.next();StringBuilderbuf=newStringBuilder(128);buf.append("Pub");buf.append(cpi.authority);buf.append(":");buf.append();Log.i(TAG,buf.toString());IContentProvidercp=installProvider(context,null,cpi,false);if(cp!=null){IActivityManager.ContentProviderHoldercph=newIActivityManager.ContentProviderHolder(cpi);vider=cp;results.add(cph);//Don'teverunloadthisproviderfromtheprocess.synchronized(mProviderMap){mProviderRefCountMap.put(cp.asBinder(),newProviderRefCount(10000));}}}try{ActivityManagerNative.getDefault().publishContentProviders(getApplicationThread(),results);}catch(RemoteExceptionex){}}......}這個(gè)函數(shù)主要是做了兩件事情,一是調(diào)用installProvider來(lái)在本地安裝每一個(gè)ContentProivder的信息,并且為每一個(gè)ContentProvider創(chuàng)建一個(gè)ContentProviderHolder對(duì)象來(lái)保存相關(guān)的信息。ContentProviderHolder對(duì)象是一個(gè)Binder對(duì)象,是用來(lái)把ContentProvider的信息傳遞給ActivityManagerService服務(wù)的。當(dāng)這些ContentProvider都處理好了以后,還要調(diào)用ActivityManagerService服務(wù)的publishContentProviders函數(shù)來(lái)通知ActivityManagerService服務(wù),這個(gè)進(jìn)程中所要加載的ContentProvider,都已經(jīng)準(zhǔn)備完畢了,而ActivityManagerService服務(wù)的publishContentProviders函數(shù)的作用就是用來(lái)喚醒在前面Step7等待的線程的了。我們先來(lái)看installProvider的實(shí)現(xiàn),然后再來(lái)看ActivityManagerService服務(wù)的publishContentProviders函數(shù)的實(shí)現(xiàn)。Step17.ActivityThread.installProvider這個(gè)函數(shù)定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:[java]viewplaincopy在CODE上查看代碼片派生到我的代碼片publicfinalclassActivityThread{......privatefinalIContentProviderinstallProvider(Contextcontext,IContentProviderprovider,ProviderInfoinfo,booleannoisy){ContentProviderlocalProvider=null;if(provider==null){......Contextc=null;ApplicationInfoai=info.applicationInfo;if(context.getPackageName().equals(ai.packageName)){c=context;}elseif(mInitialApplication!=null&&mInitialApplication.getPackageName().equals(ai.packageName)){c=mInitialApplication;}else{try{c=context.createPackageContext(ai.packageName,Context.CONTEXT_INCLUDE_CODE);}catch(PackageManager.NameNotFoundExceptione){}}......try{finaljava.lang.ClassLoadercl=c.getClassLoader();localProvider=(ContentProvider)cl.loadClass().newInstance();provider=localProvider.getIContentProvider();......//XXXNeedtocreatethecorrectcontextforthisprovider.localProvider.attachInfo(c,info);}catch(java.lang.Exceptione){......}}elseif(localLOGV){......}synchronized(mProviderMap){//Cachethepointerfortheremoteprovider.Stringnames[]=PATTERN_SEMICOLON.split(info.authority);for(inti=0;i<names.length;i++){ProviderClientRecordpr=newProviderClientRecord(names[i],provider,localProvider);try{provider.asBinder().linkToDeath(pr,0);mProvi

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論