开机后将sim/uim卡上的联系人写入数据库
tyle="margin:20px 0px 0px; font-size:14px; line-height:26px; font-family:Arial; color:rgb(51,51,51)">
1. 類SyncSimContactsReceiver:
這個(gè)類是一個(gè)廣播接收器(broadcastReceiver),主要看它的onReceive()方法: 在接收到android.intent.action.BOOT_COMPLETED這個(gè)intent的時(shí)候,會(huì)執(zhí)行startService(),service對(duì)應(yīng)的類是SyncSimContactsService
2. 類SyncSimContactsService:
這個(gè)類是一個(gè)服務(wù)(service),service被啟動(dòng)后,
2.1 先執(zhí)行onCreate(),在onCreate()中會(huì)創(chuàng)建一個(gè)handler(mServiceHandler),
mServiceHandler = new ServiceHandler();
ServiceHandler是一個(gè)SyncSimContactsService的內(nèi)部類,這個(gè)類實(shí)現(xiàn)了一個(gè)handleMessage方法.
創(chuàng)建Handler時(shí)默認(rèn)沒(méi)有傳入?yún)?shù),那么系統(tǒng)就會(huì)默認(rèn)將當(dāng)前線程的looper綁定到handler上,looper對(duì)象中維護(hù)著一個(gè)消息隊(duì)列,handler發(fā)送的消息都會(huì)存儲(chǔ)在這個(gè)消息隊(duì)列中,looper不斷的遍歷這個(gè)消息隊(duì)列,取出消息交給handleMessage()來(lái)處理,因?yàn)閘ooper屬于當(dāng)前線程,所以handleMessage()就會(huì)在當(dāng)前線程中執(zhí)行。
2.2 再執(zhí)行onStartCommand(),在onStartCommand()中主要執(zhí)行doServicehandler(),在doServicehandler()中,mServiceHandler會(huì)發(fā)送兩個(gè)MESSAGE_INIT消息,消息中的arg2參數(shù)會(huì)記錄sim卡的index,表示要對(duì)兩個(gè)sim卡都行初始化。
2.3 由于mServiceHandler綁定的是當(dāng)前線程的消息隊(duì)列,因此當(dāng)前線程的消息隊(duì)列收到MESSAGE_INIT后會(huì)執(zhí)行handleMessage方法,handleMessage對(duì)消息進(jìn)行解析,消息中有4個(gè)主要參數(shù):
1. what: 存儲(chǔ)的值是messageId,在這里就是MESSAGE_INIT。
2?arg1: 存儲(chǔ)的值是startId, 這個(gè)參數(shù)是service在執(zhí)行onStartCommand方法時(shí),作為形參傳入的,表示是由誰(shuí)啟動(dòng)的service
3. arg2: 存儲(chǔ)的值是phoneId, 表明是哪個(gè)sim卡。
4. obj:? 存儲(chǔ)的值是intent, 這個(gè)值也是service在執(zhí)行onStartCommand方法時(shí),作為形參傳入的,表示是哪個(gè)intent來(lái)啟動(dòng)的service。
接下來(lái)就是具體處理MESSAGE_INIT這個(gè)消息了,先要根據(jù)phoneId獲取到對(duì)應(yīng)的TelephonyManager的對(duì)象,然后通過(guò)調(diào)用getSimOperator方法來(lái)獲取sim_oper_num(MCC+MNC),如果這個(gè)值有效,則執(zhí)行importDualSimAction方法來(lái)導(dǎo)入sim卡聯(lián)系人的數(shù)據(jù)了。
在importDualSimAction中會(huì)創(chuàng)建一個(gè)線程,并啟動(dòng)這個(gè)線程:
DualSimcardImportThread simImport = new DualSimcardImportThread(serviceId,new ContactsAccount(accountName, Account.SIM_ACCOUNT_TYPE, uri), phoneId);
simImport.start();
DualSimcardImportThread是一個(gè)內(nèi)部類, 它的構(gòu)造函數(shù)的形參有3個(gè):
1. serviceId:即前面提到的startId,
2. ContactsAccount:這個(gè)對(duì)象里面攜帶了訪問(wèn)sim卡的URI數(shù)據(jù),如果是sim1,則對(duì)應(yīng)的URI是"content://icc0/adn",如果是sim2,對(duì)應(yīng)的URI是"content://icc1/adn"
3. phoneId: 前面已經(jīng)提到過(guò)。
這個(gè)線程類最主要的當(dāng)然是實(shí)現(xiàn)了run方法,
在run方法中,先執(zhí)行deleteSimAction方法,刪除本地?cái)?shù)據(jù)庫(kù)"content://com.android.contacts/raw_contacts"中account_name=sim1 or sim2的數(shù)據(jù),這些聯(lián)系人不是本地聯(lián)系人,所以開(kāi)機(jī)后需要?jiǎng)h除后重新加載。
接下來(lái)就是訪問(wèn)sim卡數(shù)據(jù)庫(kù)了“content://icc0/adn”:
simCursor = mResolver.query(mAccount.getContactsAccountUri(),SIM_COLUMN, null, null, null);
在phone.apk的manifest.xml中:
???? <provider android:name="MsmsIccProvider"
????????????????????? android:authorities="icc"
????????????????????? android:multiprocess="true"
????????????????????? android:readPermission="android.permission.READ_CONTACTS"
????????????????????? android:writePermission="android.permission.WRITE_CONTACTS" />
?? <provider android:name="MsmsIccProvider"
????????????????????? android:authorities="icc0"
????????????????????? android:multiprocess="true"
????????????????????? android:readPermission="android.permission.READ_CONTACTS"
????????????????????? android:writePermission="android.permission.WRITE_CONTACTS" />
?? <provider android:name="MsmsIccProvider"
????????????????????? android:authorities="icc1"
????????????????????? android:multiprocess="true"
????????????????????? android:readPermission="android.permission.READ_CONTACTS"
????????????????????? android:writePermission="android.permission.WRITE_CONTACTS" />
因此通過(guò)URI的匹配,我們可以訪問(wèn)到MsmsIccProvider這個(gè)類的Query方法
3. 類MsmsIccProvider
MsmsIccProvider的繼續(xù)關(guān)系是MsmsIccProvider-》IccProvider-》ContentProvider,它是一個(gè)contentProvider,
這里先看它實(shí)現(xiàn)的Query方法,
在Query方法中,會(huì)執(zhí)行l(wèi)oadFromEf方法,入口參數(shù)是根據(jù)URI匹配得到的ADN/FDN/SDN,?
ADN: Abbreviated dialing number, 就是常規(guī)的用戶號(hào)碼,用戶可以存儲(chǔ)/刪除
FDN:Fixed dialer number,固定撥號(hào),固定撥號(hào)功能讓您設(shè)置話機(jī)的使用限制,當(dāng)您開(kāi)啟固定撥號(hào)功能后,您只可以撥打存儲(chǔ)的固定撥號(hào)列表中的號(hào)碼。固定號(hào)碼表存放在SIM卡中。能否使用固定撥號(hào)功能取決于SIM卡類型以及網(wǎng)絡(luò)商是否提供此功能。
SDN:Service dialing number,系統(tǒng)撥叫號(hào)碼,網(wǎng)絡(luò)服務(wù)撥號(hào),固化的用戶不能編輯。
從以上的描述,我們可以看到,一般情況下都是訪問(wèn)ADN。
在loadFromEf中,要先得到一個(gè)IIccPhoneBook對(duì)象:
IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(ServiceManager.getService(PhoneFactory.getServiceName("simphonebook", phoneId)));
這個(gè)對(duì)象是用AIDL接口來(lái)獲取到的,然后調(diào)用getAdnRecordsInEf方法:
adnRecords = iccIpb.getAdnRecordsInEf(efType);
這是通過(guò)AIDL接口實(shí)現(xiàn)的方法調(diào)用,所以先要找到Stub的實(shí)體類,因?yàn)樽罱K是調(diào)用到了Stub實(shí)體類的getAdnRecordsInEf方法.這個(gè)實(shí)體類的對(duì)象是通過(guò)ServiceManager.getService來(lái)獲取的,那么找到addService的地方就可以發(fā)現(xiàn)它了。
4. 類IccPhoneBookInterfaceManagerProxy
IccPhoneBookInterfaceManagerProxy這是stub的實(shí)體類,繼承了IIccPhoneBook.Stub,在它的構(gòu)造函數(shù)中執(zhí)行了addService方法:
? String serviceName = PhoneFactory.getServiceName("simphonebook", phoneId);
? if(ServiceManager.getService(serviceName) == null) {
????? ServiceManager.addService(serviceName, this);
? }
addService方法傳入?yún)?shù)為當(dāng)前類的對(duì)象,因此,在PhoneFactory.getServiceName("simphonebook", phoneId)是獲得的就是IccPhoneBookInterfaceManagerProxy類的對(duì)象。
那么在前面(3)中提到的MsmsIccProvider類中iccIpb.getAdnRecordsInEf方法實(shí)際就調(diào)用到了IccPhoneBookInterfaceManagerProxy類的getAdnRecordsInEf方法。
在getAdnRecordsInEf方法中,執(zhí)行:
mIccPhoneBookInterfaceManager.getAdnRecordsInEf(efid);
mIccPhoneBookInterfaceManager是IccPhoneBookInterfaceManagerProxy的一個(gè)成員對(duì)象,它是何時(shí)被賦值的呢,注意在IccPhoneBookInterfaceManagerProxy的構(gòu)造函數(shù)中:
mIccPhoneBookInterfaceManager = iccPhoneBookInterfaceManager;
iccPhoneBookInterfaceManager是構(gòu)造函數(shù)傳入的形參,這么看來(lái),還要看IccPhoneBookInterfaceManagerProxy這個(gè)類是何時(shí)被實(shí)例化的?
5. 類PhoneProxy
在PhoneProxy的構(gòu)造函數(shù)中,執(zhí)行:
mIccPhoneBookInterfaceManagerProxy = new IccPhoneBookInterfaceManagerProxy(phone.getIccPhoneBookInterfaceManager());
mIccPhoneBookInterfaceManagerProxy是PhoneProxy的一個(gè)成員,在這里類IccPhoneBookInterfaceManagerProxy被實(shí)例化,之前我們提到,我們需要找到在實(shí)例化這個(gè)類時(shí)傳入的形參,在這里我們看到這個(gè)形參是
通過(guò)phone.getIccPhoneBookInterfaceManager()來(lái)會(huì)獲取的。這個(gè)獲取到的對(duì)象就是(4)中的mIccPhoneBookInterfaceManager。
而phone是PhoneProxy的構(gòu)造函數(shù)的形參傳入的一個(gè)對(duì)象,要找到這個(gè)對(duì)象的出處,就要看類PhoneProxy是何時(shí)被實(shí)例化的?
6.PhoneFactory
在類PhoneFactory中有一個(gè)makeDefaultPhone方法,里面執(zhí)行了:
sCommandsInterface[phone_index] = new SprdRIL(context, networkMode, cdmaSubscription, phone_index);
sProxyPhone[phone_index] = new SprdPhoneProxy(new TDPhone(context,sCommandsInterface[phone_index], sPhoneNotifier[phone_index]));
先看類SprdPhoneProxy的繼承關(guān)系: SprdPhoneProxy-》PhoneProxy-》Handler
也就是說(shuō),在這里,類PhoneProxy被實(shí)例化,當(dāng)然實(shí)際上是它的子類SprdPhoneProxy被實(shí)例化,構(gòu)造函數(shù)傳入的形參是一個(gè)類TDPhone的對(duì)象,
類TDPhone的繼承關(guān)系: TDPhone->GSMPhone->PhoneBase->Handler
前面(5)中要找的phone.getIccPhoneBookInterfaceManager方法的返回值就是類TDPhone的getIccPhoneBookInterfaceManager方法的返回值,getIccPhoneBookInterfaceManager方法在類TDPhone中沒(méi)有實(shí)現(xiàn),而是在它的父類GSMPhone中實(shí)現(xiàn)的。
7.GSMPhone
在類GSMPhone中實(shí)現(xiàn)了getIccPhoneBookInterfaceManager方法
public IccPhoneBookInterfaceManager getIccPhoneBookInterfaceManager(){
??????? return mSimPhoneBookIntManager;
}
mSimPhoneBookIntManager是一個(gè)成員,它在類GSMPhone的構(gòu)造函數(shù)中被賦值:
public GSMPhone (Context context, CommandsInterface ci, PhoneNotifier notifier, boolean unitTestMode) {
。。。。
mSimPhoneBookIntManager = new SimPhoneBookInterfaceManager(this);
。。。。
}
mSimPhoneBookIntManager就是(6)中的類TDPhone的getIccPhoneBookInterfaceManager方法返回值
8. SimPhoneBookInterfaceManager
類SimPhoneBookInterfaceManager的繼承關(guān)系:SimPhoneBookInterfaceManager-》IccPhoneBookInterfaceManager
(4)中的mIccPhoneBookInterfaceManager.getAdnRecordsInEf方法實(shí)際上就是類SimPhoneBookInterfaceManager的getAdnRecordsInEf方法,
而getAdnRecordsInEf在類SimPhoneBookInterfaceManager中沒(méi)有實(shí)現(xiàn),而是在它的父類IccPhoneBookInterfaceManager中實(shí)現(xiàn)的,
(3)中的iccIpb.getAdnRecordsInEf方法執(zhí)行調(diào)用的就是IccPhoneBookInterfaceManager.getAdnRecordsInEf方法
9. IccPhoneBookInterfaceManager
類IccPhoneBookInterfaceManager中實(shí)現(xiàn)了getAdnRecordsInEf方法
在getAdnRecordsInEf方法中,執(zhí)行:
adnCache.requestLoadAllAdnLike(efid, adnCache.extensionEfForEf(efid), response);
adnCache是類AdnRecordCache的對(duì)象
10. AdnRecordCache
在類AdnRecordCache中實(shí)現(xiàn)了requestLoadAllAdnLike方法,
在requestLoadAllAdnLike中,執(zhí)行:
new AdnRecordLoader(mFh).loadAllFromEF(efid, extensionEf,obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE, efid, 0))
這里實(shí)例化一個(gè)類AdnRecordLoader的對(duì)象,并且調(diào)用該對(duì)象的loadAllFromEF方法
11. AdnRecordLoader
在類AdnRecordLoader中實(shí)現(xiàn)了loadAllFromEF方法,
在loadAllFromEF方法中,執(zhí)行:
mFh.loadEFLinearFixedAll(ef, obtainMessage(EVENT_ADN_LOAD_ALL_DONE));
mFh是類IccFileHandler的對(duì)象,實(shí)際上是它的子類TDUSIMFileHandler的對(duì)象,繼承關(guān)系是:TDUSIMFileHandler-》SIMFileHandler-》IccFileHandler
12. IccFileHandler
在類IccFileHandler中實(shí)現(xiàn)了loadEFLinearFixedAll方法,
在loadEFLinearFixedAll方法中,執(zhí)行:
phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
mCM是類SprdRIL的對(duì)象,SprdRIL的繼承關(guān)系是:SprdRIL-》RIL
13. RIL
在類RIL中實(shí)現(xiàn)了iccIO方法,
在iccIO方法中,執(zhí)行:
RILRequest rr = RILRequest.obtain(RIL_REQUEST_SIM_IO, result);
創(chuàng)建一個(gè)RILRequest對(duì)象,requestId=RIL_REQUEST_SIM_IO
然后把這個(gè)對(duì)象當(dāng)作一個(gè)obj,放到message中,
msg = mSender.obtainMessage(EVENT_SEND, rr);
messageId=EVENT_SEND
mSender是一個(gè)handler對(duì)象,它是如何生成的呢,在RIL的構(gòu)造函數(shù)中可以看到:
mSenderThread = new HandlerThread("RILSender");
mSenderThread.start();
Looper looper = mSenderThread.getLooper();
mSender = new RILSender(looper);
mSender在實(shí)例化時(shí)傳入的looper是發(fā)送子線程的looper,因此,mSender發(fā)出的消息會(huì)發(fā)送到這個(gè)子線程的消息隊(duì)列中,也就是mSenderThread這個(gè)線程中,handleMessage也會(huì)在這個(gè)子線程中執(zhí)行。
接下來(lái)看類RILSender的handleMessage方法,
在handleMessage中,解析出來(lái)msg.what=EVENT_SEND,從msg.obj中取出數(shù)據(jù),寫入socket
s = mSocket;
s.getOutputStream().write(dataLength);
s.getOutputStream().write(data);
mSocket是在另外一個(gè)子線程,即接收子線程中創(chuàng)建的,
s = new LocalSocket();
l = new LocalSocketAddress(SOCKET_NAME_RIL,LocalSocketAddress.Namespace.RESERVED);
s.connect(l);
mSocket = s;
至此,數(shù)據(jù)請(qǐng)求已經(jīng)通過(guò)socket發(fā)送給rild了,rild會(huì)解析這些數(shù)據(jù),再組裝成AT命令,通過(guò)串口發(fā)送給modem,modem會(huì)返回AT數(shù)據(jù)給rild,rild再解析AT數(shù)據(jù),然后打包通過(guò)socket發(fā)揮給RIL.java來(lái)接收。
實(shí)際上,前面這一句描述有些含糊,從(1)中我們可以看到,從SyncSimContactsReceiver接收到intent開(kāi)始,一直到(13)整個(gè)代碼執(zhí)行都工作在Contacts.apk(android.process.acore)這個(gè)進(jìn)程中,只不過(guò)有的是在主線程中,有的是在子線程中,這個(gè)應(yīng)用進(jìn)程通過(guò)socket與rild這個(gè)守護(hù)進(jìn)程通信,將數(shù)據(jù)傳送到rild這個(gè)進(jìn)程中,rild得到串口返回的數(shù)據(jù)后,再通過(guò)socket發(fā)送給應(yīng)用層進(jìn)程Contacts.apk(android.process.acore).
這里,我們假設(shè)數(shù)據(jù)已經(jīng)通過(guò)socket返回給應(yīng)用層進(jìn)程Conatacts.apk(android.process.acore),那么RIL.java是怎么接收的呢?
在類RIL的構(gòu)造函數(shù)中可以看到:
mReceiver = new RILReceiver();
mReceiverThread = new Thread(mReceiver, "RILReceiver");
mReceiverThread.start();
這里創(chuàng)建了一個(gè)接收子線程,這個(gè)線程用來(lái)接收rild進(jìn)程通過(guò)socket返回來(lái)的數(shù)據(jù),
我們看一下接收子線程的run方法,
在run方法中,執(zhí)行:
InputStream is = mSocket.getInputStream();
length = readRilMessage(is, buffer);
p = Parcel.obtain();
p.unmarshall(buffer, offset, length - offset);
p.setDataPosition(0);
processResponse(p);
從socket接收到的數(shù)據(jù)進(jìn)行解析,主要在processResponse方法中執(zhí)行,
ret =? responseICC_IO(p);
AsyncResult.forMessage(rr.mResult, ret, null);
rr.mResult.sendToTarget();
將數(shù)據(jù)解析出來(lái)后,打包到message中,發(fā)送出去,那么發(fā)送到哪個(gè)消息隊(duì)列中了呢?
rr.mResult存儲(chǔ)的message對(duì)象是iccIO方法的形參傳入的,而iccIO方法是(12)中的類IccFileHandler的loadEFLinearFixedAll方法調(diào)用的,
14. IccFileHandler
在IccFileHandler中實(shí)現(xiàn)了loadEFLinearFixedAll方法,
? public void loadEFLinearFixedAll(int fileid, Message onLoaded) {
??????? Message response = obtainMessage(EVENT_GET_RECORD_SIZE_DONE,
??????????????????????? new LoadLinearFixedContext(fileid,onLoaded));
??????? phone.mCM.iccIO(COMMAND_GET_RESPONSE, fileid, getEFPath(fileid),
??????????????????????? 0, 0, GET_RESPONSE_EF_SIZE_BYTES, null, null, response);
??? }
這里的response就是(13)中的rr.mResult,
IccFileHandler的繼承關(guān)系:IccFileHandler-》Handler
這里我們也看一下IccFileHandler的構(gòu)造函數(shù),
??? protected IccFileHandler(PhoneBase phone) {
??????? super();
??????? this.phone = phone;
??? }
在調(diào)用父類構(gòu)造函數(shù)時(shí),沒(méi)有傳入?yún)?shù),意味著這個(gè)handler是與主線程的消息隊(duì)列綁定的,handleMessage方法就在主線程中執(zhí)行,
那么(13)中的rr.mResult.sendToTarget()發(fā)送到了主線程中,主線程會(huì)調(diào)用IccFileHandler的handleMessage方法進(jìn)行處理,
public void handleMessage(Message msg) {
。。。。。。。
?case EVENT_GET_RECORD_SIZE_DONE:
。。。。。。。。
lc.countRecords = size / lc.recordSize;
?phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid),
???????????????????????? lc.recordNum,
???????????????????????? READ_RECORD_MODE_ABSOLUTE,
???????????????????????? lc.recordSize, null, null,
???????????????????????? obtainMessage(EVENT_READ_RECORD_DONE, lc));
。。。。。。。。。
根據(jù)socket返回的數(shù)據(jù),計(jì)算出聯(lián)系人record的totalNumber,然后再一次通過(guò)調(diào)用類RIL的iccIO方法向socket發(fā)送數(shù)據(jù)請(qǐng)求讀取第一個(gè)聯(lián)系人record的具體內(nèi)容,然后socket接收到返回?cái)?shù)據(jù)后,發(fā)送message給消息隊(duì)列,繼續(xù)由類IccFileHandler的handleMessage方法處理,
case EVENT_READ_RECORD_DONE:
。。。。。。
lc.results.add(result.payload);
lc.recordNum++;
。。。。。。
phone.mCM.iccIO(COMMAND_READ_RECORD, lc.efid, getEFPath(lc.efid),lc.recordNum,READ_RECORD_MODE_ABSOLUTE,lc.recordSize, null, null,obtainMessage(EVENT_READ_RECORD_DONE,0,pathNum,lc));
。。。。。。
把讀取到record內(nèi)容保存起來(lái),然后num++,繼續(xù)讀取下一條record,依此類推,逐條的來(lái)發(fā)送請(qǐng)求和接收數(shù)據(jù),sim的容量是250,則要發(fā)送250個(gè)數(shù)據(jù)請(qǐng)求給rild。
當(dāng)最后一個(gè)數(shù)據(jù)接收到之后, 就要發(fā)送message給上層的消息隊(duì)列了,
response = lc.onLoaded;
response.sendToTarget();
這里的lc.onLoaded是在(11)中的mFh.loadEFLinearFixedAll(ef, obtainMessage(EVENT_ADN_LOAD_ALL_DONE))傳入的,因此發(fā)送消息的handler是類AdnRecordLoader的對(duì)象,消息隊(duì)列中接收到消息后
就要調(diào)用類AdnRecordLoader的handleMessage方法了
15. AdnRecordLoader
類AdnRecordLoader的繼承關(guān)系:AdnRecordLoader-》Handler
在類AdnRecordLoader中實(shí)現(xiàn)了handleMessage方法,
case EVENT_ADN_LOAD_ALL_DONE:
。。。
for (int i = 0, s = datas.size(); i < s; i++) {
adn = new AdnRecord(ef, 1 + i, datas.get(i));
adns.add(adn);
}
userResponse.sendToTarget();
....
將數(shù)據(jù)打包到消息中,發(fā)送到消息隊(duì)列中,那么userResponse這個(gè)消息又是和哪個(gè)handler關(guān)聯(lián)的呢??
public void loadAllFromEF(int ef, int extensionEF, Message response) {
this.ef = ef;
this.extensionEF = extensionEF;
this.userResponse = response;
。。。
mFh.loadEFLinearFixedAll(ef, obtainMessage(EVENT_ADN_LOAD_ALL_DONE));
}
可以看到userResponse是loadAllFromEF方法的形參傳入的,這是由(10)中的
new AdnRecordLoader(mFh).loadAllFromEF(efid, extensionEf,obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE, efid, 0))調(diào)用的
這個(gè)message(EVENT_LOAD_ALL_ADN_LIKE_DONE)是類AdnRecordCache的對(duì)象發(fā)出的,那么發(fā)出這個(gè)消息后,由類AdnRecordCache的handleMessage方法調(diào)用的
16. AdnRecordCache
類AdnRecordCache實(shí)現(xiàn)了HandleMessage方法,
case EVENT_LOAD_ALL_ADN_LIKE_DONE:
waiters = adnLikeWaiters.get(efid);
adnLikeWaiters.delete(efid);
notifyWaiters(waiters, ar);
在notifyWaiters方法中,
Message waiter = waiters.get(i);
AsyncResult.forMessage(waiter, ar.result, ar.exception);
waiter.sendToTarget();
這里還是發(fā)送一個(gè)消息到消息隊(duì)列中,這個(gè)消息是什么呢? waiter消息是在requestLoadAllAdnLike方法中被賦值的,
public void requestLoadAllAdnLike(int efid, int extensionEf,Message response) {
。。。
waiters.add(response);
。。。
}
這個(gè)response是形參帶入的,就是(9)中的adnCache.requestLoadAllAdnLike(efid, adnCache.extensionEfForEf(efid), response)調(diào)用的,
即類IccPhoneBookInterfaceManager的getAdnRecordsInEf方法調(diào)用的,
17.IccPhoneBookInterfaceManager
在類IccPhoneBookInterfaceManager中實(shí)現(xiàn)了getAdnRecordsInEf方法,
public synchronized List<AdnRecord> getAdnRecordsInEf(int efid) {
...
Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE, status);
adnCache.requestLoadAllAdnLike(efid, adnCache.extensionEfForEf(efid), response);
waitForResult(status);
...
}
這里可以看到message是mBaseHandler發(fā)出的,由mBaseHandler的handleMessage方法處理,
case EVENT_LOAD_DONE:
notifyPending(ar);
這里執(zhí)行解鎖,那么getAdnRecordsInEf方法中的waitForResult就可以返回了,
至此,getAdnRecordsInEf方法才執(zhí)行完畢,而這是個(gè)AIDL接口調(diào)用,它是由(3)中的iccIpb.getAdnRecordsInEf(efType)發(fā)起的,現(xiàn)在執(zhí)行到了類MsmsIccProvider的loadFromEf方法中,
18. MsmsIccProvider
在類MsmsIccProvider中,實(shí)現(xiàn)了loadFromEf方法,
?private ArrayList<ArrayList> loadFromEf(int efType, int phoneId) {
。。。
adnRecords = iccIpb.getAdnRecordsInEf(efType);
?int N = adnRecords.size();
??? for (int i = 0; i < N ; i++) {
??????????????? loadRecord(adnRecords.get(i), results);
??? }
這個(gè)方法執(zhí)行完畢之后,走回到類MsmsIccProvider的query方法中,將results轉(zhuǎn)換成cursor對(duì)象返回。
query方法執(zhí)行完畢后,(2)中的mResolver.query(mAccount.getContactsAccountUri(),SIM_COLUMN, null, null, null);也就返回了
19. SyncSimContactsService
類SyncSimContactsService的DualSimcardImportThread這個(gè)線程的run方法中,query語(yǔ)句就執(zhí)行完畢了
至此,從sim卡上就讀取到全部的聯(lián)系人數(shù)據(jù)了,接下來(lái)就是將這些數(shù)據(jù)存儲(chǔ)到本地?cái)?shù)據(jù)庫(kù)中了,當(dāng)然要做一下標(biāo)記,account_name=sim1 or sim2。
?
總結(jié)
以上是生活随笔為你收集整理的开机后将sim/uim卡上的联系人写入数据库的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: php 声明字符串的三种方式
- 下一篇: [转]ORACLE日期时间函数大全