




版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
Telephony框架設(shè)計(jì)解析version:1.2author:***目錄一、RIL3二、Telephony中多卡及多運(yùn)營(yíng)商設(shè)計(jì)區(qū)分8〔.telephony中的多卡9AP區(qū)分多卡9modem區(qū)分多卡142.telephony中的多運(yùn)營(yíng)商設(shè)計(jì)15三、Telephony中AID1模式設(shè)計(jì)16四、Telephony中觀察者模式設(shè)計(jì)17五、TelephonyRegistry監(jiān)昕模式設(shè)計(jì)21概述21以狀態(tài)欄信號(hào)更新為例分析注冊(cè)和更新過(guò)程【YETIM-1107J22.注冊(cè)過(guò)程22.RIL上報(bào)監(jiān)聽(tīng)回調(diào)更新過(guò)程25六、ServiceStateTracker/DcTracker/CallTracke28七、Telephony分析案例之檢測(cè)不到SIM卡29八、手機(jī)駐網(wǎng)過(guò)程modemlog32
本篇文檔將從如下六個(gè)方面講述telephony框架設(shè)計(jì):RIL、多卡及多運(yùn)營(yíng)商設(shè)計(jì)區(qū)分、不同運(yùn)營(yíng)商的extends繼承實(shí)現(xiàn)、IDEL的設(shè)計(jì)、觀察者模式設(shè)計(jì)、TelephonyRegistry監(jiān)昕模式設(shè)計(jì)、ServiceStateTracker/DcTracker/CallTracker。附上AndroidTelephony框架圖代冷」七項(xiàng)]低:必Audit*DrifTPackageMin咿tTelephonyMnnajwrWiruJEYNolificaEiunH.cM}iartc峋口獎(jiǎng)靖「PowerManjtjeinctnlC:山物L(fēng)it里MMSJav;i|LranicxvorksUserLibrariesSVLitcWchKitQpcnti].IlAHJiUrd^nreA書(shū)銳節(jié)。KmiWi-FiRABKXWIl-iLinuxKerntI代冷」七項(xiàng)]低:必Audit*DrifTPackageMin咿tTelephonyMnnajwrWiruJEYNolificaEiunH.cM}iartc峋口獎(jiǎng)靖「PowerManjtjeinctnlC:山物L(fēng)it里MMSJav;i|LranicxvorksUserLibrariesSVLitcWchKitQpcnti].IlAHJiUrd^nreA書(shū)銳節(jié)。KmiWi-FiRABKXWIl-iLinuxKerntIICI>L:I>PIPUSLiOri^cr\<'i4'i-DiivtrConttnll^ovidcrs■AdiiityM:im鄴tC:iine?;iDriverIjtspifiyDriverMedia.FmmgvrkSiLrlhuGKeypad[3ri舛rHinder^EPQUriverMemoryDriverI)4ltEiCciincictionAidrnidRurritiuConeLLbraricsDalvikVirtiKilMil匚h小匚VicM15wioniLuC;>t]DTlMw呻邸PS:共跨越了4層:AndroidTelephony采用了分層結(jié)構(gòu),共跨越了4層:1.Telephony應(yīng)用,包括了Phone、MMS和STK等應(yīng)用程序2.Telephony框架,提供TelephonyManager,包含數(shù)據(jù)連接、通話、信息和SIM相關(guān)的API3夙線通信接口層(RIL),主要位于UserLibraries層中的HAL層,提供入?(ApplicationProcessor)和BP(BasebandProcessor)之間的通信功能4.Modem,位于BP,主要負(fù)責(zé)實(shí)際的無(wú)線通信能力處理一、RILRIL有RILJ和RILC,RILJ是我們所熟悉的java側(cè)RIL.java代碼,RILC是hardware/ril目錄下C代碼,此處我們簡(jiǎn)單介紹下RILC模塊的初始化和運(yùn)行機(jī)理。Android的RIL驅(qū)動(dòng)模塊,在hardware/ril目錄下,一共分rild,libril.so以及l(fā)ibrefrence_ril.so三個(gè)部分,另有一radiooptions可供自動(dòng)或手動(dòng)調(diào)試使用。都依賴于include目錄中ril.h頭文件。目前cupcake分支上帶的是gsm的支持,另有一cdma分支,這里分析的是gsm驅(qū)動(dòng)。GSM模塊,由于Modem的歷史原B,AP-直是通過(guò)基于串口的AT命令與88交互。包括到了目前的一些edge或3。模塊,或像。map這類(lèi)ap,bp集成的芯片,已經(jīng)使用了USB或其他等高速總線通信,但大多仍然使用模擬串口機(jī)制來(lái)使用AT命令。這里的RIL(RadioInterfaceLayer)層,主要也就是基于AT命令的操作,加發(fā)命令,response解析等。首先介紹一下rild與libril.so以及l(fā)ibrefrence_ril.so的關(guān)系:rild:僅實(shí)現(xiàn)一main函數(shù)作為整個(gè)ril層的入口點(diǎn),負(fù)責(zé)完成初始化。libril.so:與rild結(jié)合相當(dāng)緊密,是其共享庫(kù),編譯時(shí)就已經(jīng)建立了這一關(guān)系。組成部分為ril.cpp,ril_event.cppolibril.so駐留在rild這一守護(hù)進(jìn)程中,主要完成同上層通信的工作,接受ril請(qǐng)求并傳遞給librefrence_ril.so,同時(shí)把來(lái)自librefrence_ril.so的反饋回傳給調(diào)用進(jìn)程。librefrence_ril.so:rild通過(guò)手動(dòng)的dlopen方式加載,結(jié)合稍微松散,這也是因?yàn)閘ibrefrence.so主要負(fù)責(zé)跟Modem硬件通信的緣故。這樣做更方便替換成修改以適配更多的Modem種類(lèi)。它轉(zhuǎn)換來(lái)自libril.so的請(qǐng)求為AT命令,同時(shí)監(jiān)控Modem的反饋信息,并傳遞回libril.so。在初始化時(shí),rild通過(guò)符號(hào)RIL_Init獲取一組函數(shù)指針并以此與之建立聯(lián)系。radiooptions:radiooptiongs通過(guò)獲取啟動(dòng)參數(shù),利用socket與rild通信,可供調(diào)試時(shí)配置Modem參數(shù)。接下來(lái)分析初始化流程:主入口是rild.c中的main函數(shù),主要完成三個(gè)任務(wù):1.開(kāi)啟libril.so中的event機(jī)制,在RIL_startEventLoop中,是最核心的由多路I/O驅(qū)動(dòng)的消息循環(huán)。
初始化librefrence_ril.so,也就是跟硬件或模擬硬件modem通信的部分(后面統(tǒng)一稱硬件),通過(guò)RIL_Init函數(shù)完成。通過(guò)RIL_Init獲取一組函數(shù)指針RIL_RadioFunctions,并通過(guò)RIL_register完成注冊(cè),并打開(kāi)接受上層命令的socket通道。第一個(gè)任務(wù)流程圖:rild.c中白勺main()ril_event_add()在ril_event.cpp中將新ril_event加入隊(duì)列之中add會(huì)把隊(duì)列里所有ril_event的fd,放入一個(gè)fd集合readFds中ril_event_loop(),ril_event.cpp中
建立超消息(event)隊(duì)列機(jī)制ril_event_loop能通過(guò)—多路復(fù)用I/O的機(jī)鬧(select)來(lái)等待這些fd
如果任何一個(gè)fd有數(shù)據(jù)寫(xiě)入,則進(jìn)入分析流程
processTimeouts(),processReadReadies(&rfds,n),
ril_event_loop(),ril_event.cpp中
建立超消息(event)隊(duì)列機(jī)制ril_event.cpp中包含的方法
voidril_event_init();voidril_event_set(structril_event*ev,intfd...);voidril_event_add(structril_event*ev);voidril_timer_add(structril_event*ev,structtimeval*tv);voidril_event_del(structril_event*ev);voidril_event_loop();
至此第一個(gè)初始化任務(wù)分析完畢,
這樣便建立起了基于event隊(duì)列的消息循環(huán),
稍后便可以接受上層發(fā)來(lái)的的請(qǐng)求了(上層請(qǐng)求的event對(duì)象建立,在第三個(gè)任務(wù)中)。圖一(RIL_startEventLoop消息循環(huán)初始化)第二個(gè)任務(wù)流程圖:main(),ril.c中
為ril層的入口點(diǎn)艮口mainLoop艮口mainLoop(..)主要任務(wù)是建立起與硬read方法阻塞等待硬彳在reference_ril.c中M牛的通信一,然后通過(guò)件的主動(dòng)上報(bào)或響應(yīng)RIL_Init(..)在reference_ril.c中首先通過(guò)參數(shù)獲取硬件接口色設(shè)備文件或模擬硬件接口的socket.接下來(lái)便新開(kāi)一個(gè)線程繼續(xù)初始化RIL_requestTimedCallback(initializeCallback,NULL,&TIMEVAL_0),跑到initializeCallback中,執(zhí)行
一些Modem的初始化命令,主要都是AT命令的方式。at_open(..)在atchannel.cat_open(..)在atchannel.c中
建立起這一設(shè)備文件上的reader等待循環(huán),
這也是通過(guò)新建一個(gè)線程完成ret=pthread_create(&s_tid_reader,&attr,readerLpop,&attr),注冊(cè)一些基礎(chǔ)回調(diào)(timeout,readerclose)
后,mainLoop首先打開(kāi)硬件設(shè)備文件,建立起
與硬件的通信,s_device_path和s_port是前
面獲取的設(shè)備路徑參■數(shù),將其打開(kāi)圖二(RIL_Init硬件modem通信部分初始化)第三個(gè)任務(wù)流程圖:圖三(RIL_RadioFunctions接受上層命令的socket通道初始化)二、Telephony中多卡及多運(yùn)營(yíng)商設(shè)計(jì)區(qū)分以雙卡為例,上層是如何區(qū)分卡1和卡2在telephony模塊中運(yùn)行,AP發(fā)送AT命令后?modem如何區(qū)分去執(zhí)行卡1還是卡2的操作?
I.telephony中的多卡1)AP區(qū)分多卡要區(qū)分多卡,就必須要為每卡都給其屬于其自己的變量。.android.phone是開(kāi)機(jī)自啟動(dòng)進(jìn)程,有關(guān)telephony的很多初始化都是在這個(gè)進(jìn)程中完成的。下面我們來(lái)詳細(xì)解析此進(jìn)程:packages/services/Telephony/AndroidManifest.xml<applicationandroid:name="PhoneApp"http://phone進(jìn)程定義了此屬性,開(kāi)機(jī)AMS啟動(dòng)后就會(huì)檢測(cè)帶有此屬性的進(jìn)程然后將其啟動(dòng)android:persistent="true"PhoneApp.javapublicvoidonCreate(){if(UserHandle.myUserId()==0){〃啟動(dòng)了PhoneGlobalsmPhoneGlobals=newPhoneGlobals(this);mPhoneGlobals.onCreate();mTelephonyGlobals=newTelephonyGlobals(this);mTelephonyGlobals.onCreate();PhoneGlobals.javapublicvoidonCreate(){〃從這開(kāi)始就要做很多有關(guān)telephony相關(guān)的初始化操作//1.Initializethetelephonyframework,這里很重要,創(chuàng)建phone類(lèi)型,區(qū)分多sim卡,接下來(lái)重點(diǎn)將此流程PhoneFactory.makeDefaultPhones(this);//2.CreatetheNotificationMgrsingleton,whichisusedtodisplay//statusbariconsandcontrolotherstatusbarbehavior.notificationMgr=NotificationMgr.init(this);//3.call相關(guān)初始化mCM=CallManager.getInstance();CallLoggercallLogger=newCallLogger(this,newCallLogAsync());callController=CallController.init(this,callLogger,callGatewayManager);//4.ap側(cè)經(jīng)常使用的PhoneInterfaceManager初始化phoneMgr=PhoneInterfaceManager.init(this,PhoneFactory.getDefaultPhone());//5.registerforMMI/USSDmCM.registerForMmiplete(mHandler,MMI_PLETE,null);//.....等等PhoneFactory.java〃接下來(lái)分析此方法的眾多初始化信息publicstaticvoidmakeDefaultPhone(Contextcontext^synchronized(sLockProxyPhonesKif(!sMadeDefaults){sContext=context;//createthetelephonydevicecontroller.TelephonyDevController.create();intretryCount=0;for(;;){booleanhasException=false;retryCount++;try{//useUNIXdomainsocketto//preventsubsequentinitializationnewLocalServerSocket(".ernal.telephony");}catch(java.io.IOExceptionex){hasException=true;}if(!hasException){break;}elseif(retryCount>SOCKET_OPEN_MAX_RETRY){thrownewRuntimeException("PhoneFactoryprobablyalreadyrunning");}else{try{Thread.sleep(SOCKET_OPEN_RETRY_MILLIS);}catch(InterruptedExceptioner){}}}//1.初始化DefaultPhoneNotifier,第五章就是會(huì)用到此DefaultPhoneNotifier的一個(gè)例子sPhoneNotifier=newDefaultPhoneNotifier();intcdmaSubscription=CdmaSubscriptionSourceManager.getDefault(context);Rlog.i(LOG_TAG,"CdmaSubscriptionsetto"+cdmaSubscription);/*IncaseofmultiSIMmodetwoinstancesofPhoneProxy,RILarecreated,whereasinsingleSIMmodeonlyinstance.isMultiSimEnabled()functioncheckswhetheritissingleSIMormultiSIMmode*/intnumPhones=TelephonyManager.getDefault().getPhoneCount();int[]networkModes=newint[numPhones];sProxyPhones=newPhoneProxy[numPhones];smandsInterfaces=newRIL[numPhones];//2.此循環(huán)是開(kāi)機(jī)時(shí)給卡槽獲取設(shè)置網(wǎng)絡(luò)模式(例如是GSMONLY還是LTE...),telephony中有關(guān)網(wǎng)絡(luò)模式此處不做詳細(xì)講述,后面再單獨(dú)講解for(inti=0;i<numPhones;i++){//readsthesystempropertiesandmakesmandsinterface//GworkModes[i]=RILConstants.PREFERRED_NETWORK_MODE;Stringvalue=TelephonyManager.getTelephonyProperty(i,"ro.telephony.default_network",null);if(value!=null&&!value.isEmpty()){try{networkModes[i]=Integer.parseInt(value);}catch(NumberFormatExceptionex){Rlog.i(LOG_TAG,"NumberFormatExceptioninparsingnetworkMode");}}Rlog.i(LOG_TAG,"NetworkModesetto"+Integer.toString(networkModes[i]));//2.此smandsInterfaces很重要,會(huì)一直關(guān)聯(lián)到RILsmandsInterfaces[i]=newRIL(context,networkModes[i],cdmaSubscription,i);}Rlog.i(LOG_TAG,"CreatingSubscriptionController");//3.初始化SubscriptionController,一般我們獲取telephony.db數(shù)據(jù)庫(kù)中siminfo表里的有關(guān)sim卡信息都會(huì)用此類(lèi)去獲取SubscriptionController.init(context,smandsInterfaces);//InstantiateUiccControllersothatallotherclassescanjust//callgetInstance()//4.初始化UiccController,framework中對(duì)sim卡的處理,讀寫(xiě)等等操作mUiccController=UiccController.make(context,smandsInterfaces);//5.這個(gè)for循環(huán)就是區(qū)分sim卡的重點(diǎn),位每個(gè)卡槽的sim創(chuàng)建一個(gè)phone類(lèi)型,在整個(gè)telephony運(yùn)行過(guò)程中,和卡槽始終對(duì)應(yīng)//6.ap側(cè)想對(duì)某卡進(jìn)行操作時(shí)都會(huì)獲取此處的phone類(lèi)型變量,然后就可以進(jìn)行相關(guān)設(shè)置,此處使用了代理模式for(inti=0;i<numPhones;i++){PhoneBasephone=null;intphoneType=TelephonyManager.getPhoneType(networkModes[i]);if(phoneType==PhoneConstants.PHONE_TYPE_GSM){phone=(PhoneBase)getGsmPhone(i);}elseif(phoneType==PhoneConstants.PHONE_TYPE_CDMA){phone=newCDMALTEPhone(context,smandsInterfaces[i],sPhoneNotifier,i);}Rlog.i(LOG_TAG,"CreatingPhonewithtype="+phoneType+"sub="+i);sProxyPhones[i]=newPhoneProxy(phone);}mProxyController=ProxyController.getInstance(context,sProxyPhones,mUiccController,smandsInterfaces);//Setthedefaultphoneinbaseclass.//FIXME:Thisisafirstbestguessatwhatthedefaultswillbe.It//FIXME:needstobedoneinamorecontrolledmannerinthefuture.sProxyPhone=sProxyPhones[0];smandsInterface=smandslnterfaces[0];//EnsurethatwehaveadefaultSMSapp.Requestingtheappwith//updateIfNeededsettotrueisenoughtoconfigureadefaultSMSapp.ponentNameponentName=SmsApplication.getDefaultSmsApplication(context,true/*updateIfNeeded*/);StringpackageName="NONE";if(ponentName!=null){packageName=ponentName.getPackageName();}Rlog.i(LOG_TAG,"defaultSmsApplication:"+packageName);//SetupmonitortowatchforchangestoSMSpackages//7.初始化一個(gè)默認(rèn)信息應(yīng)用SmsApplication.initSmsPackageMonitor(context);sMadeDefaults=true;Rlog.i(LOG_TAG,"CreatingSubInfoRecordUpdater");sSubInfoRecordUpdater=newSubscriptionInfoUpdater(context,sProxyPhones,smandsInterfaces);SubscriptionController.getInstance().updatePhonesAvailability(sProxyPhones);//Startmonitoringafterdefaultshavebeenmade.//DefaultphonemustbereadybeforeImsPhoneiscreated//becauseImsServicemightneeditwhenitisbeingopened.//8.Imsphone,與VoLTE:4G通話,相關(guān)for(inti=0;i<numPhones;i++){sProxyPhones[i].startMonitoringImsService();}}}}此時(shí)的phone類(lèi)型就出來(lái)了,AP側(cè)可以通過(guò)PhoneFactory.java中的getPhone方法獲取對(duì)應(yīng)卡的phone。2)modem區(qū)分多卡此處創(chuàng)建了phone類(lèi)型,用構(gòu)造函數(shù)new出了GSMPhon。或者CDMAPhone,然后會(huì)進(jìn)入這兩個(gè)phone類(lèi)型中進(jìn)行初始化。GSMPhone.javapublicGSMPhone(Contextcontext,mandsInterfaceci,PhoneNotifiernotifier,booleanunitTestMode,intphoneId){super("GSM",notifier,context,ci,unitTestMode,phoneId);〃調(diào)用父類(lèi)的構(gòu)造函數(shù),見(jiàn)下面的解析if(ciinstanceofSimulatedRadioControl){mSimulatedRadioControl=(SimulatedRadioControl)ci;}〃這個(gè)mCi就是就連接RIL的經(jīng)過(guò)RIL往modem發(fā)送指令〃每卡對(duì)應(yīng)一個(gè)phone對(duì)應(yīng)一個(gè)mCi對(duì)應(yīng)modem處理相應(yīng)的sim卡//下面這四個(gè)變量都是對(duì)應(yīng)卡對(duì)應(yīng)變量mCi.setPhoneType(PhoneConstants.PHONE_TYPE_GSM);//telephony中處理RIL上報(bào)的call相關(guān)初始化mCT=newGsmCallTracker(this);//telephony中處理注冊(cè)狀態(tài),信號(hào)等相關(guān)初始化mSST=newGsmServiceStateTracker(this);//telephony中處理數(shù)據(jù)業(yè)務(wù)的初始化mDcTracker=newDcTracker(this);〃以上三個(gè)是telephony中非常重要的三個(gè)tracker,此處不做詳細(xì)流程分析if(!unitTestMode){mSimPhoneBookIntManager=newSimPhoneBookInterfaceManager(this);mSubInfo=newPhoneSubInfo(this);}mCi.registerForAvailable(this,EVENT_RADIO_AVAILABLE,null);mCi.registerForOffOrNotAvailable(this,EVENT_RADIO_OFF_OR_NOT_AVAILABLE,null);mCi.registerForOn(this,EVENT_RADIO_ON,null);mCi.setOnUSSD(this,EVENT_USSD,null);mCi.setOnSuppServiceNotification(this,EVENT_SSN,null);mSST.registerForNetworkAttached(this,EVENT_REGISTERED_TO_NETWORK,null);mCi.setOnSs(this,EVENT_SS,null);setProperties();log("GSMPhone:constructor:sub="+mPhoneld);setProperties();}PhoneBase.javaprotectedPhoneBase(Stringname,PhoneNotifiernotifier,Contextcontext,mandsInterfaceci,booleanunitTestMode,intphoneId){mPhoneId=phoneId;mName=name;mNotifier=notifier;mContext=context;mLooper=Looper.myLooper();〃初始化相關(guān)變量mCi=ci;telephony中的多運(yùn)營(yíng)商設(shè)計(jì)區(qū)分運(yùn)營(yíng)商的類(lèi)一般如下GSMPhone和CDMAPhone繼承自PhoneBaseGsmServiceStateTracker和CdmaServiceStateTracker繼承自ServiceStateTrackerGsmCallTracker和CdmaCallTracker繼承自CallTracker第二種和第三種在第一種的類(lèi)的部初始化,所以有第一種決定,只需要關(guān)心第一種phone類(lèi)型是如何來(lái)確定的,之前在PhoneFactory.java申我們?cè)岬?/2.此循環(huán)是開(kāi)機(jī)時(shí)給卡槽獲取設(shè)置網(wǎng)絡(luò)模式(例如是GSMONLY還是LTE...),telephony中有關(guān)網(wǎng)絡(luò)模式此處不做詳細(xì)講述,后面再單獨(dú)講解for(inti=0;i<numPhones;i++){//readsthesystempropertiesandmakesmandsinterface//GworkModes[i]=RILConstants.PREFERRED_NETWORK_MODE;Stringvalue=TelephonyManager.getTelephonyProperty(i,"ro.telephony.default_network",null);if(value!=null&&!value.isEmpty()){try{networkModes[i]=Integer.parseInt(value);}catch(NumberFormatExceptionex){Rlog.i(LOG_TAG,"NumberFormatExceptioninparsingnetworkMode");//在這里我們可以發(fā)現(xiàn)phone類(lèi)型是由網(wǎng)絡(luò)模式?jīng)Q定的//5.這個(gè)for循環(huán)就是區(qū)分sim卡的重點(diǎn),位每個(gè)卡槽的sim創(chuàng)建一個(gè)phone類(lèi)型,在整個(gè)telephony運(yùn)行過(guò)程中,和卡槽始終對(duì)應(yīng)//6.ap側(cè)想對(duì)某卡進(jìn)行操作時(shí)都會(huì)獲取此處的phone類(lèi)型變量,然后就可以進(jìn)行相關(guān)設(shè)置,此處使用了代理模式for(inti=0;i<numPhones;i++){PhoneBasephone=null;intphoneType=TelephonyManager.getPhoneType(networkModes[i]);if(phoneType==PhoneConstants.PHONE_TYPE_GSM){phone=(PhoneBase)getGsmPhone(i);}elseif(phoneType==PhoneConstants.PHONE_TYPE_CDMA){phone=newCDMALTEPhone(context,smandsInterfaces[i],sPhoneNotifier,i);}Rlog.i(LOG_TAG,"CreatingPhonewithtype="+phoneType+"sub="+i);sProxyPhones[i]=newPhoneProxy(phone);}三、Telephony中AIDL模式設(shè)計(jì)Telephony中有很多地方在使用跨進(jìn)程數(shù)據(jù)調(diào)用維持手機(jī)的整體運(yùn)行,所以有些服務(wù)died之后可能會(huì)導(dǎo)致phone進(jìn)程crash。下面是常用的一些服務(wù)://第五章是使用此服務(wù)的一個(gè)例子。在TelephonyRegistry.java實(shí)現(xiàn)privateITelephonyRegistrygetTelephonyRegistry(){returnITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));}//很多手機(jī)狀態(tài)信息是通過(guò)此服務(wù)調(diào)用。在PhoneInterfaceManager.java實(shí)現(xiàn)privateITelephonygetITelephony(){returnITelephony.Stub.asInterface(ServiceManager.getService(Context.TELEPHONY_SERVICE));}〃通話call相關(guān)信息科通過(guò)此服務(wù)獲取privateITeleServicegetTeleService(){returnITeleService.Stub.asInterface(ServiceManager.getService(Context.TELE_SERVICE));}//sim信息卡相關(guān)獲取服務(wù)privateIPhoneSubInfogetSubscriberInfo(){returnIPhoneSubInfo.Stub.asInterface(ServiceManager.getService("iphonesubinfo"));}〃數(shù)據(jù)庫(kù)和sim相關(guān)服務(wù)privateISubgetISub(){returnISub.Stub.asInterface(ServiceManager.getService("isub"));四、Telephony中觀察者模式設(shè)計(jì)ServiceStateTracker、DcTracker、CallTracker以及其繼承類(lèi)都是使用觀察者模式進(jìn)行監(jiān)聽(tīng)回調(diào)執(zhí)行,下面我們舉例來(lái)分析觀察者模式中重要的參數(shù)問(wèn)題。
//我們以RIL中的RIL_UNSOL_RESTRICTED_STATE_CHANGED為例RlL.javacaseRIL_UNSOL_RESTRICTED_STATE_CHANGED:if(RILJ_LOGD)unsljLogvRet(response,ret);if(mRestrictedStateRegistrant!=null){//ret的定義是Objectret;這個(gè)參數(shù)就是modem返回的數(shù)據(jù)//protectedRegistrantmRestrictedStateRegistrant;定義類(lèi)型是Registrant,后面分析有用mRestrictedStateRegistrant.notifyRegistrant(newAsyncResult(null,ret,null));}break;〃上面的new個(gè)對(duì)象newAsyncResult(null,ret,null),進(jìn)入AsyncResult類(lèi)中查看此構(gòu)造函數(shù)〃由構(gòu)造函數(shù)可只modem返回的參數(shù)ret傳給了AsyncResult的result參數(shù)AsyncResult.javapublicAsyncResult(Objectuo,Objectr,Throwableex){userObj=uo;result=r;exception=ex;}//然后我們跟進(jìn)mRestrictedStateRegistrant.notifyRegistrant的notifyRegistrant方法〃此時(shí)我們可以發(fā)現(xiàn)上面的ret給result參數(shù)后,在此處又new了一個(gè)AsyncResult,到這里我們就要分析msg.what=what;這里的what是哪里來(lái)的,這樣或許我們就可以知道此處是如何通知觀察者的了Registrant.javapublicvoidnotifyRegistrant(AsyncResultar){internalNotifyRegistrant(ar.result,ar.exception);}/*package*/voidinternalNotifyRegistrant(Objectresult,Throwableexception){Handlerh=getHandler();if(h==null){clear();}else{Messagemsg=Message.obtain();msg.what=what;msg.obj=newAsyncResult(userObj,result,exception);h.sendMessage(msg);}}〃接下來(lái)我們開(kāi)始分析注冊(cè)的地方GsmServiceStateTracker.java〃此觀察者注冊(cè)的第一個(gè)參數(shù)是這個(gè)類(lèi)里的handler,第二個(gè)是回調(diào)what參數(shù)類(lèi)型,第三個(gè)是null,如果我們想傳遞一些我們自己設(shè)計(jì)的相關(guān)參數(shù)也可以利用這個(gè)沒(méi)有使用的參數(shù)mCi.setOnRestrictedStateChanged(this,EVENT_RESTRICTED_STATE_CHANGED,null);Basemands.java//PS:此處我們可以看下RlL.java的繼承關(guān)系://publicfinalclassRILextendsBasemandsimplementsmandslnterfacepublicvoidsetOnRestrictedStateChanged(Handlerh,intwhat,Objectobj){mRestrictedStateRegistrant=newRegistrant(h,what,obj);}//進(jìn)入Registrant.java的構(gòu)造函數(shù)Registrant.javapublicRegistrant(Handlerh,intwhat,Objectobj){refH=newWeakReference(h);this.what=what;userObj=obj;}〃現(xiàn)在我們?cè)倩氐絼倓倧腞IL.java開(kāi)始通知回調(diào)的流程中/*package*/voidinternalNotifyRegistrant(Objectresult,Throwableexception){//此處的handler就是注冊(cè)時(shí)的handlerHandlerh=getHandler();if(h==null){clear();}else{Messagemsg=Message.obtain();〃這個(gè)what就是注冊(cè)時(shí)的what,回調(diào)時(shí)執(zhí)行哪個(gè)case中的代碼msg.what=what;〃這個(gè)就是modem回調(diào)的參數(shù),具體怎么使用,等會(huì)我們分析回調(diào)流程的代碼時(shí),看此參數(shù)有何作用msg.obj=newAsyncResult(userObj,result,exception);〃發(fā)送message給注冊(cè)時(shí)的那個(gè)handler執(zhí)行回調(diào)操作h.sendMessage(msg);}}此時(shí)觀察者的回調(diào)已經(jīng)清楚,下面我們繼續(xù)流程,RIL上報(bào)后,通過(guò)觀察者執(zhí)行到GsmServiceStateTracker.javacaseEVENT_RESTRICTED_STATE_CHANGED://Thisisanotificationfrom//mandsInterface.setOnRestrictedStateChangedif(DBG)log("EVENT_RESTRICTED_STATE_CHANGED");〃此處我們就可以很容易看出下面這個(gè)代碼為何可以得到AsyncResult//Registrant.java里internalNotifyRegistrant方法中msg.obj=newAsyncResult(userObj,result,exception);〃這個(gè)msg.obj就是等于在RIL.java中new的那個(gè)ar=(AsyncResult)msg.obj;onRestrictedStateChanged(ar);break;//進(jìn)入onRestrictedStateChanged方法privatevoidonRestrictedStateChanged(AsyncResultar){RestrictedStatenewRs=newRestrictedState();if(DBG)log("onRestrictedStateChanged:Ers"+mRestrictedState);if(ar.exception==nullX//這里的ar.result就是modem上報(bào)的ret參數(shù)值,到這里,modem參數(shù)就被完整的解析出來(lái),上層可以正常取值分析流程int[]ints=(int[])ar.result;intstate=ints[0];五、TelephonyRegistry監(jiān)聽(tīng)模式設(shè)計(jì)1.概述這是一個(gè)系統(tǒng)服務(wù),主要完成兩方面的通知任務(wù):1、監(jiān)昕Phone狀態(tài),當(dāng)有新的狀態(tài)時(shí),對(duì)注冊(cè)該服務(wù)的客戶端進(jìn)行通知。比如:notifyCallState:通知通話狀態(tài)的改變。notifySignalStrength:通知信號(hào)的改變。notifyCallForwardingChanged:通知呼叫轉(zhuǎn)移狀態(tài)的改變。notifyDataConnection:通知數(shù)據(jù)連接的改變。.等等2、監(jiān)昕Phone狀態(tài),當(dāng)有新的狀態(tài)時(shí),發(fā)送相應(yīng)的廣播到系統(tǒng)中。比如:broadcastServiceStateChanged:廣播服務(wù)狀態(tài)的改變。broadcastSignalStrengthChanged:廣播信號(hào)的改變。broadcastDataConnectionStateChanged:廣播數(shù)據(jù)連接狀態(tài)的改等等變。等等客戶端在得到這個(gè)服務(wù)后,可以通過(guò)統(tǒng)一的listen方法將自己注冊(cè)為狀態(tài)的監(jiān)昕器,如果Phone狀態(tài)發(fā)生了改變,系統(tǒng)就會(huì)遍歷所有的監(jiān)聽(tīng)器,主動(dòng)向他們發(fā)消息,調(diào)用相應(yīng)的回調(diào)函數(shù)。既然他是一個(gè)服務(wù),就需要去向ServiceManager注冊(cè)自己。我們?cè)赟ystemServer初始化線程中找到了他的注冊(cè)過(guò)程:TelephonyRegistrysRegistry=ITelephonyRegistry.Stub.asInterface(ServiceManager.getService("telephony.registry"));由此可見(jiàn),這個(gè)服務(wù)被加載為“telephony.registry”的服務(wù)。如果需要獲取該服務(wù),就需要通過(guò)“telephony.registry”的名字向ServiceManager查詢。2.以狀態(tài)欄信號(hào)更新為例分析注冊(cè)和更新過(guò)程[YETIM-1107J【YETIM-1107】[FT][Yeti-M][SH]4GiconisdisplayedonDUT,butSIMcardsignalisempty.[Once]1).注冊(cè)過(guò)程在SystemUI中,注冊(cè)狀態(tài)欄上的監(jiān)聽(tīng)。
上糧目日的時(shí)IS#回能或是將主帝網(wǎng)豪,■.的一至boSFtuiM質(zhì)QRXdB的功聶有上糧目日的時(shí)IS#回能或是將主帝網(wǎng)豪,■.的一至boSFtuiM質(zhì)QRXdB的功聶有i專乾典Dtfr茶就底后,:戒/代河!之“毗ry臺(tái)右EBwEKordm中的莒戶i京月他叮豈If垃U的SiBIlft'//^Saaiid^EzSJiiTiSi:'■JS^EH3IGWM.霹巷fcJSTH待都;U.^HegEd中卜7eLwLcciiiSaiiager.j-ita際Gtolluvoid.liffECDLFbaneiSrsazCLJi.BC?ier.iFtc!?z.i*events!■{jHa>rlfl,u:y.llj^!e'ZiFDrSL±i9CEItri-xIlLFcez*sJL=^Z,iQe~^p£acj[ay±2l3H*I;iili5zen*-^:Bllt4ck|.e-5-en.T-Siriotiri/Wc*).:pzlTDbtwoidli容此玖StdziRQAllLnc'PacEac%,IPhcn?3>:ia.E&Lidi.4n4-rc-sllbact,inxeveriTa,匕二JL左B二ZlEEJ.xli'ZiE'^-RI-Fjhld^|E!^2i?toid.liffteDFnr^ubsGriierfuh-Zdi■■cxLJi^^k^Fcirl^b'jg.ZPhd.a£Lac?LLr'i:azjfiZcallteaalr.inLevenTS,tDOle-mZKic:i73c?-|(寫(xiě)wiBgE匚二MEw.^±Llbiz^.wh二jiGtafylflawpfjfcld);第一步:MobileSignalController.javafinalPhoneStateListenermPhoneStateListener;mPhoneStateListener=newMobilePhoneStateListener(info.getSubscriptionId(),receiverLooper);〃這里new-個(gè)對(duì)象是一個(gè)部類(lèi),此處的第一個(gè)subid參數(shù)很重要,可以用于區(qū)分modem上報(bào)的是哪卡狀態(tài)更新,從而使UI界面正確顯示classMobilePhoneStateListenerextendsPhoneStateListener{publicMobilePhoneStateListener(intsubid,Looperlooper){super(subId,looper);//這個(gè)構(gòu)造函數(shù),使用了其父類(lèi)PhoneStateListener的構(gòu)造函數(shù)初始化}PhoneStateListener.javapublicPhoneStateListener(intsubid,Looperlooper){if(DBG)log("ctor:subid="+subid+"looper="+looper);mSubid=subid;第二步:MobileSignalController.javapublicvoidregisterListener(){//如下設(shè)置監(jiān)聽(tīng)的類(lèi)型,如此例號(hào)欄狀態(tài)LISTEN_SIGNAL_STRENGTHS//這里的mPhone是TelephonyManager的對(duì)象mPhone.listen(mPhoneStateListener,PhoneStateListener.LISTEN_SERVICE_STATE|PhoneStateListener.LISTEN_SIGNAL_STRENGTHS|PhoneStateListener.LISTEN_CALL_STATE|PhoneStateListener.LISTEN_DATA_CONNECTION_STATE|PhoneStateListener.LISTEN_DATA_ACTIVITY|PhoneStateListener.LISTEN_CARRIER_NETWORK_CHANGE);}Goto-->TelephonyManager.javapublicvoidlisten(PhoneStateListenerlistener,intevents){if(mContext==null)return;try{BooleannotifyNow=(getITelephony()!=null);//sRegistry是ITelephonyRegistry對(duì)象,是一個(gè)aidl跨進(jìn)程服務(wù),并在TelephonyRegistry繼承實(shí)現(xiàn)//如下參數(shù)listener.mSubId,就是上面所說(shuō)的重要的subid值sRegistry.listenForSubscriber(listener.mSubId,getOpPackageName(),listener.callback,events,notifyNow);}catch(RemoteExceptionex){}catch(NullPointerExceptionex){}}Goto-->TelephonyRegistry.javapublicvoidlistenForSubscriber(intsubId,StringpkgForDebug,IPhoneStateListenercallback,intevents,booleannotifyNow){listen(pkgForDebug,callback,events,notifyNow,subId);}privatevoidlisten(StringcallingPackage,IPhoneStateListenercallback,intevents,booleannotifyNow,intsubId){//此函數(shù)就是將注冊(cè)時(shí)帶入的一些參數(shù)添加到一個(gè)叫做mRecords的列表中,當(dāng)Phone狀態(tài)改變后,TelephonyRegistry會(huì)遍歷mRecords中的客戶端,分別調(diào)用他們當(dāng)初注冊(cè)的回調(diào)函數(shù)。//會(huì)添加subid以及之前監(jiān)聽(tīng)類(lèi)型LISTEN_SIGNAL_STRENGTHS等都加入mRecord中,等特匹配回調(diào)
到這里監(jiān)聽(tīng)的注冊(cè)過(guò)程就已經(jīng)走完,接下來(lái)是要處理modem上報(bào)信號(hào)改變后通知UI改變的流程2).RIL上報(bào)監(jiān)昕回調(diào)更新過(guò)程nodemfl■始回>?tdJif洋斛McteileSLirnalCcat-ioLleiij-svBpublicToldufasz-eiel-spjizGiy(F;『*_!*;:Yaid.口3二3匕TM匚nodemfl■始回>?tdJif洋斛McteileSLirnalCcat-ioLleiij-svBpublicToldufasz-eiel-spjizGiy(F;『*_!*;:Yaid.口3二3匕TM匚gtt.fl'h口B33由H){In匚j-ubldaiin.lex.c-*LS'ubld(|<f¥fi^!;i3Ct^aDGil!l!Si(niaL3DieD3DJirGr&-dbac;ritier(fubldj5KidErige^3^gE.HJ.Stre35,th(j-);publmt--dnatitj5ignal3trenifftiFarSjbaczilserijint-js'_tZ^.ZL^4U"Zitn.acli3^57i415"reiig"ii]{魚(yú)m美嫁-有迎里epa=n±.iifa£if-tg-■言安術(shù)用牌聽(tīng)符會(huì)技回調(diào)|蓮專皿四1:BrelranSrsr.java〃建個(gè)?女中注ffi了田畏者監(jiān)項(xiàng)住號(hào)uE,i.3±ci^nSLC7iE.lSc,Ewnc,^iD5daxe削3虬£:紋L_STkE頰叮pry□UXllFSanServ^wStaterEiiGlrzciva。七此國(guó)由瞻瀏S中也行t-EC?_3La距—斐EZWGI禮謳D1K□cnSigTL52Sz.r*EgTrtRwjlrl-ar.tne|i;kILjBIVH.ua_se:ELILT3SCL5IGM&LSISEHGIBi厄3Lqn£.13i:Eengc2iE.ec:iJC^tnx.n.QC.irySefllatrincI□ew(dliIL.z-2t4mil)FPTtoneBa-BajaTap:.±Lie^oidnot^31'jn.aLStren.flth(]■{z3Dui2^K:JLC?~j.f75i.aEJLErr-EE.irE!:rth■曲1prcrtcTaflEOcLaaEgeSLjrnal3tre:igtjiEveffu2.tCA3iTL-sF.e-sid.t―弓Tn二二3二二日SsiJ■[jr?三uEnnj匚七三誓三1.0^日!§匚匚三m匹化【I"P^OMcrelbaoleazi-ziif>-5x3DaJ.StrKicth.(|{TsFtca&HiS'SJio^SzrsrLgTtL0:RIL.java〃經(jīng)過(guò)modem主動(dòng)上報(bào)信號(hào)改變,processUnsolicited開(kāi)始處理caseRIL_UNSOL_SIGNAL_STRENGTH://Notethisissetto"verbose"becauseithappens//frequentlyif(RILJ_LOGV)unsljLogvRet(response,ret);if(mSignalStrengthRegistrant!=null){〃此處是觀察者模式,見(jiàn)第四章觀察者模式詳解mSignalStrengthRegistrant.notifyRegistrant(newAsyncResult(null,ret,null));}break;ServiceStateTracker.java〃這個(gè)類(lèi)中注冊(cè)了觀察者監(jiān)聽(tīng)信號(hào)狀態(tài)改變mCi.setOnSignalStrengthUpdate(this,EVENT_SIGNAL_STRENGTH_UPDATE,null);〃收到RIL上報(bào)后會(huì)執(zhí)行handle中此EVENT_SIGNAL_STRENGTH_UPDATE操作,會(huì)在如下類(lèi)中執(zhí)行(以GSM為例)〃此處涉及第三章中不同運(yùn)營(yíng)商的繼承,詳細(xì)可參照此章節(jié)GsmServiceStateTracker.java〃在此handle線程中執(zhí)行caseEVENT_SIGNAL_STRENGTH_UPDATE://Thisisanotificationfrom//mandsInterface.setOnSignalStrengthUpdatear=(AsyncResult)msg.obj;//Theradioistellingusaboutsignalstrengthchanges//wedon'thavetoaskitmDontPollSignalStrength=true;onSignalStrengthResult(ar,true);break;//AsyncResult這個(gè)參數(shù)再RIL中很重要,詳細(xì)說(shuō)明在第四章中protectedbooleanonSignalStrengthResult(AsyncResultar,booleanisGsm){SignalStrengtholdSignalStrength=mSignalStrength;//Thissignalisusedforbothvoiceanddataradiosignalsoparse//allfieldsif((ar.exception==null)&&(ar.result!=null)){mSignalStrength=(SignalStrength)ar.result;mSignalStrength.validateInput();mSignalStrength.setGsm(isGsm);}else{log("onSignalStrengthResult()ExceptionfromRIL:"+ar.exception);mSignalStrength=newSignalStrength(isGsm);}//BLADEIIIBA-1380,renfy120150626,notnotifysignalupdatewhensametolastif((oldSignalStrength.getGsmDbm()==mSignalStrength.getGsmDbm())&&(oldSignalStrength.getLteRsrp()==mSignalStrength.getLteRsrp())){returntrue;}else{returnnotifySignalStrength();}protectedbooleannotifySignalStrength(Kbooleannotified=false;synchronized(mCellInfo){if(!mSignalStrength.equals(mLastSignalStrength)){try(〃此處向PhoneBase發(fā)出通知,telephony和phone是密切相關(guān)的mPhoneBase.notifySignalStrength();notified=true;}catch(NullPointerExceptionex){loge("updateSignalStrength()Phonealreadydestroyed:"+ex+"SignalStrengthnotnotified");}}}returnnotified;}PhoneBase.javapublicvoidnotifySignalStrength(){mNotifier.notifySignalStrength(this);}DefaultPhoneNotifier.javapublicvoidnotifySignalStrength(Phonesender){intsubId=sender.getSubId();Rlog.d(LOG_TAG,"notifySignalStrength:mRegistry="+mRegistry+"ss="+sender.getSignalStrength()+"sender="+sender);〃這行l(wèi)og就是此處的log,打印出信號(hào)量的具體容SignalStrength,信號(hào)強(qiáng)度也可以在這個(gè)log中讀到//SignalStrength具體log含義,可以參見(jiàn)SignalStrength.java中tostring()方法,此處的99就是相當(dāng)于無(wú)信號(hào)的信號(hào)強(qiáng)度//04-1813:31:17.97439183918DDefaultPhoneNotifier:notifySignalStrength:mRegistry=.ernal.telephony.ITelephonyRegistry$Stub$Proxy7bb4143ss=SignalStrength:9999-120-160-120-1-199-122-115021474836472147483647gsm|ltesender=Handler(.ernal.telephony.gsm.GSMPhone){3218a66}try{if(mRegistry!=null){//這里是發(fā)送回調(diào)的關(guān)鍵,此處傳入了subid和信號(hào)量SignalStrength//從這里進(jìn)入關(guān)鍵類(lèi)TelephonyRegistry.javamRegistry.notifySignalStrengthForSubscriber(subId,sender.getSignalStrength());}}catch(RemoteExceptionex){}}TelephonyRegistry.javapublicvoidnotifySignalStrengthForSubscriber(intsubId,SignalStrengthsignalStrength)(〃通知關(guān)鍵,在這里匹配subid和監(jiān)聽(tīng)類(lèi)型,符合要求的監(jiān)聽(tīng)將會(huì)被回調(diào)MobileSignalController.javaclassMobilePhoneStateListenerextendsPhoneStateListener{publicMobilePhoneStateListener(intsubId,Looperlooper){super(subId,looper);}OverridepublicvoidonSignalStrengthsChanged(SignalStrengthsignalStrength){if(DEBUG){Log.d(mTag,"onSignalStrengthsChangedsignalStrength="+signalStrength+((signalStrength==null)?"":("level="+signalStrength.getLevel())));}mSignalStrength=signalStrength;//UI界面將會(huì)被執(zhí)行更新updateTelephony();}大、ServiceStateTracker/DcTracker/CallTracke之前在phone初始化中介紹過(guò)很重要的三個(gè)tracker,這三個(gè)是telephony的重點(diǎn)流程,繼承自handler,在線程中完成telephony相關(guān)操作。由于此三個(gè)流程復(fù)雜且重要,不在此框架文檔中重點(diǎn)敘述,后續(xù)文章再分別講述。//telephony中處理RIL上報(bào)的call相關(guān)初始化mCT=newGsmCallTracker(this);//telephony中處理注冊(cè)狀態(tài),信號(hào)等相關(guān)初始化mSST=newGsmServiceStateTracker(this);//telephony中處理數(shù)據(jù)業(yè)務(wù)的初始化mDcTracker=newDcTracker(this);七、Telephony分析案例之檢測(cè)不到SIM卡//modem的radio此時(shí)是off的,所以ss=33是飛行模式的狀態(tài)04-2910:24:10.26541724279DRILJ:[3649]>RADIO_POWERoff[SUB0]04-2910:24:10.27441724279DRILJ:[UNSL]<UNSOL_RESPONSE_RADIO_STATE_CHANGEDRADIO_OFF[SUB0]04-2910:24:10.37241724279DRILJ:[3649]<RADIO_POWER[SUB0]04-2910:24:10.27641724279DRILJ:[UNSL]<UNSOL_RESPONSE_SIMSTATUSCHANGED[SUB0]//此時(shí)回通知IccCardProxy.java發(fā)送sim卡motready狀態(tài)04-2910:24:10.93941724172DIccCardProxy:broadcastIccStateChangedIntentintentACTION_SIM_STATE_CHANGEDvalue=NOT_READYreason=nullformPhoneId=004-2910:24:11.75141724172DDefaultPhoneNotifier:nofityServiceState:mRegistry=.ernal.telephony.ITelephonyRegistry$Stub$Proxyb04bd3ess=33voicehomedatahomenullnullnullnullnullnullUnknownUnknownCSSnotsupported-1-1RoamInd=-1DefRoamInd=-1EmergOnly=falseIsDataRoamingFromRegistration=falsesender=Handler(.ernal.telephony.gsm.GSMPhone){d3d9b54}phondId=0subId=-2//打開(kāi)radio04-2910:24:11.72741724172DRILJ:[3656]>RADIO_POWERon[SUB0]04-2910:24:11.80541724279DRILJ:[UNSL]<UNSOL_RESPONSE_RADIO_STATE_CHANGEDRADIO_ON[SUB0]04-2910:24:11.80641724279DRILJ:[3656]<RADIO_POWER[SUB0]04-2910:24:13.09141724172DRILJ:[3671]>GET_SIM_STATUS[SUB0]04-2910:24:13RILJ:[3671]<GET_SIM_STATUSIccCardState{CARDSTATE_PRESENT,PINSTATE_UNKNOWN,num_apps=1,gsm_id=0{APPTYPE_USIM,APPSTATE_DETECTED,pin1=PINSTATE_UNKNOWN,pin2=PINSTATE_UNKNOWN},cdma_id=-1,ims_id=-1}[SUB0]//此時(shí)modem的radio是on,駐網(wǎng)狀態(tài)ss=11,是outofservices04-2910:24:13.41441724172DDefaultPhoneNotifier:nofityServiceState:mRegistry=.ernal.telephony.ITelephonyRegistry$Stub$Proxyb04bd3ess=11voicehomedatahomenullnullnullnullnullnullUnknownUnknownCSSnotsupported-1-1RoamInd=-1DefRoamInd=-1EmergOnly=falseIsDataRoamingFromRegistration=falsesender=Handler(.ernal.telephony.gsm.GSMPhone){d3
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 山東省百師聯(lián)盟2024-2025學(xué)年高二下學(xué)期6月聯(lián)考地理試題(解析版)
- 遼寧省重點(diǎn)高中沈陽(yáng)市郊聯(lián)體2024-2025學(xué)年高三上學(xué)期10月月考地理試題(解析版)
- 2025年合肥市口腔醫(yī)院引進(jìn)高層次人才10人模擬試卷及一套完整答案詳解
- 倡導(dǎo)健康生活行為規(guī)范承諾書(shū)(8篇)
- 員工培訓(xùn)課程表
- 2025國(guó)家自然科學(xué)基金委員會(huì)公開(kāi)選聘流動(dòng)編制10人模擬試卷及完整答案詳解
- 2025年廈門(mén)市供電服務(wù)有限公司招聘12人考前自測(cè)高頻考點(diǎn)模擬試題及完整答案詳解一套
- 2025年浙江大學(xué)醫(yī)學(xué)院附屬第二醫(yī)院招聘心電圖室工作人員若干人考前自測(cè)高頻考點(diǎn)模擬試題及答案詳解(名師系列)
- 2025遼寧錦州醫(yī)科大學(xué)開(kāi)展“錦醫(yī)英才計(jì)劃”醫(yī)學(xué)名家遴選考前自測(cè)高頻考點(diǎn)模擬試題參考答案詳解
- 2025年上海奉賢區(qū)教育系統(tǒng)事業(yè)單位編外用工招聘143名模擬試卷含答案詳解
- 2022智慧園區(qū)設(shè)計(jì)、建設(shè)與驗(yàn)收技術(shù)規(guī)范
- 自備車(chē)補(bǔ)貼申請(qǐng)表
- 信息論與編碼(第4版)完整全套課件
- 汽修廠安全風(fēng)險(xiǎn)分級(jí)管控清單
- GB/T 2679.7-2005紙板戳穿強(qiáng)度的測(cè)定
- GB/T 25840-2010規(guī)定電氣設(shè)備部件(特別是接線端子)允許溫升的導(dǎo)則
- GB/T 25146-2010工業(yè)設(shè)備化學(xué)清洗質(zhì)量驗(yàn)收規(guī)范
- 參考資深同傳
- 多功能注氧儀說(shuō)明書(shū)課件
- 科隆電磁流量計(jì)培訓(xùn)課件
- 全集舉一反三課件奧數(shù)五年級(jí)(數(shù)學(xué))
評(píng)論
0/150
提交評(píng)論