Android应用程序组件Content Provider的启动过程源代码分析(3)
Step 7.ActivityManagerService.getContentProviderImpl 这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中: publicfinalclassActivityManagerServiceextendsActivityManagerNative implementsWatchdog.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(cpi.name); 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(cpi.processName, cpr.appInfo,false,0,"contentprovider", newComponentName(cpi.applicationInfo.packageName, cpi.name),false); ...... mLaunchingProviders.add(cpr); ...... } //Makesuretheproviderispublished(thesameproviderclass //maybepublishedundermultiplenames). if(firstClass){ mProvidersByClass.put(cpi.name,cpr); } cpr.launchingApp=proc; mProvidersByName.put(name,cpr); ...... } //Waitfortheprovidertobepublished... synchronized(cpr){ while(cpr.provider==null){ ...... try{ cpr.wait(); }catch(InterruptedExceptionex){ } } } returncpr; } ...... } 这个函数比较长,我们一步一步地分析。 函数首先是获取调用者的进程记录块信息: ProcessRecordr=null; if(caller!=null){ r=getRecordForAppLocked(caller); ...... } 在我们这个情景中,要获取的就是应用程序Article的进程记录块信息了,后面会用到。 在ActivityManagerService中,有两个成员变量是用来保存系统中的Content Provider信息的,一个是mProvidersByName,一个是mProvidersByClass,前者是以Content Provider的authoriry值为键值来保存的,后者是以Content Provider的类名为键值来保存的。一个Content Provider可以有多个authority,而只有一个类来和它对应,因此,这里要用两个Map来保存,这里为了方便根据不同条件来快速查找而设计的。下面的代码就是用来检查要获取的Content Provider是否已经加存在的了: //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(cpi.name); finalbooleanfirstClass=cpr==null; if(firstClass){ try{ ApplicationInfoai= AppGlobals.getPackageManager(). getApplicationInfo( cpi.applicationInfo.packageName, STOCK_PM_FLAGS); ...... cpr=newContentProviderRecord(cpi,ai); }catch(RemoteExceptionex){ //pmisinsameprocess,thiswillneverhappen. } } 在我们这个情景中,由于是第一次调用ArticlesProvider接口,因此,在mProvidersByName和mProvidersByClass两个Map中都不存在ArticlesProvider的相关信息,因此,这里会通过AppGlobals.getPackageManager函数来获得PackageManagerService服务接口,然后分别通过它的resolveContentProvider和getApplicationInfo函数来分别获取ArticlesProvider应用程序的相关信息,分别保存在cpi和cpr这两个本地变量中。这些信息都是在安装应用程序的过程中保存下来的,具体可以参考 Android应用程序安装过程源代码分析 一文。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966983,如需转载请自行联系原作者