摘要:加載流程定義在從上面可以看到,真正的是在中繼承,處理的等操作,和卡交互完成后,將數(shù)據(jù)改變信息通知給然后將數(shù)據(jù)變化的發(fā)送給注冊(cè)監(jiān)聽(tīng)的應(yīng)用,應(yīng)用做相應(yīng)的同步動(dòng)作。
ADN加載流程:
IccProvider.java
IccProvider定義在/packages/services/Telephony/AndroidManifest.xml
public class IccProvider extends com.android.internal.telephony.IccProvider { public IccProvider() { super(); } }
從上面可以看到,真正的ICCProvider是在framework中繼承ContentProvider,處理ADN/FDN/SDN的query/insert/update/delete等操作,和SIM卡交互完成后,將數(shù)據(jù)改變信息通知給ContentObserver,然后ContentObserver將數(shù)據(jù)變化的發(fā)送給注冊(cè)監(jiān)聽(tīng)的應(yīng)用,Contacts應(yīng)用做相應(yīng)的同步動(dòng)作。
Contacts數(shù)據(jù)庫(kù)和SIM卡聯(lián)系的同步后面繼續(xù)分析。
關(guān)于ContentProvider和ContentResolver以及ContentObserver的介紹,可以參考:
http://blog.csdn.net/dmk877/a...
IccProvider重寫(xiě)ContentProvider的方法:
UiccPhoneBookController.java
UiccPhoneBookController在ProxyController的構(gòu)造方法中初始化。
mUiccPhoneBookController = new UiccPhoneBookController(mPhones);
UiccPhoneBookController的構(gòu)造方法:
public class UiccPhoneBookController extends IIccPhoneBook.Stub { private static final String TAG = "UiccPhoneBookController"; private Phone[] mPhone; /* only one UiccPhoneBookController exists */ public UiccPhoneBookController(Phone[] phone) { if (ServiceManager.getService("simphonebook") == null) { ServiceManager.addService("simphonebook", this); } mPhone = phone;
IccProvider通過(guò)AIDL調(diào)用UiccPhoneBookController:
try { IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface( ServiceManager.getService("simphonebook")); if (iccIpb != null) { success = iccIpb.updateAdnRecordsInEfBySearchForSubscriber(subId, efType, "", "", name, number, pin2); } } catch (RemoteException ex) { // ignore it } catch (SecurityException ex) { if (DBG) log(ex.toString()); }
關(guān)于AIDL的實(shí)現(xiàn)后面詳細(xì)學(xué)習(xí)
IccPhoneBookInterfaceManager.java
IccPhoneBookInterfaceManager是在Phone的初始化時(shí)完成實(shí)例化:
在GsmCdmaPhone構(gòu)造方法initOnce()中: mIccPhoneBookIntManager = mTelephonyComponentFactory.makeIccPhoneBookInterfaceManager(this);
SimPhoneBookAdnRecordCache.java
SimPhoneBookAdnRecordCache在IccPhoneBookInterfaceManager構(gòu)造方法中完成初始化:
public IccPhoneBookInterfaceManager(Phone phone) {
this.mPhone = phone; IccRecords r = phone.getIccRecords(); if (r != null) { mAdnCache = r.getAdnCache(); } if(isSimPhoneBookEnabled()){ if(mSimPbAdnCache == null) { mSimPbAdnCache = new SimPhoneBookAdnRecordCache( phone.getContext(), phone.getPhoneId(), phone.mCi); } } }
查詢(xún)SIM卡聯(lián)系人流程
1 IccProvider
private static final UriMatcher URL_MATCHER = new UriMatcher(UriMatcher.NO_MATCH); static { URL_MATCHER.addURI("icc", "adn", ADN); URL_MATCHER.addURI("icc", "adn/subId/#", ADN_SUB); URL_MATCHER.addURI("icc", "fdn", FDN); URL_MATCHER.addURI("icc", "fdn/subId/#", FDN_SUB); URL_MATCHER.addURI("icc", "sdn", SDN); URL_MATCHER.addURI("icc", "sdn/subId/#", SDN_SUB); } 支持ADN/FDN/SDN的URL private MatrixCursor loadFromEf(int efType, int subId) { if (DBG) log("loadFromEf: efType=0x" + Integer.toHexString(efType).toUpperCase() + ", subscription=" + subId); ListadnRecords = null; try { IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface( ServiceManager.getService("simphonebook")); if (iccIpb != null) { adnRecords = iccIpb.getAdnRecordsInEfForSubscriber(subId, efType); } } catch (RemoteException ex) { // ignore it } catch (SecurityException ex) { if (DBG) log(ex.toString()); } //獲取adn list轉(zhuǎn)換成cursor if (adnRecords != null) { // Load the results final int N = adnRecords.size(); final MatrixCursor cursor = new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES, N); if (DBG) log("adnRecords.size=" + N); for (int i = 0; i < N ; i++) { loadRecord(adnRecords.get(i), cursor, i); } return cursor; } else { // No results to load Rlog.w(TAG, "Cannot load ADN records"); return new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES); } }
UiccPhoneBookController時(shí)一個(gè)Binder服務(wù)類(lèi),接口是IIccPhoneBook,服務(wù)名"simphonebook"
2.UiccPhoneBookController
getAdnRecordsInEfForSubscriber方法:
@Override public ListgetAdnRecordsInEfForSubscriber(int subId, int efid) throws android.os.RemoteException { //獲取實(shí)例,實(shí)例在文章開(kāi)始Phone初始化時(shí)設(shè)置 IccPhoneBookInterfaceManager iccPbkIntMgr = getIccPhoneBookInterfaceManager(subId); if (iccPbkIntMgr != null) { //調(diào)用getAdnRecordsInEf方法 return iccPbkIntMgr.getAdnRecordsInEf(efid); } else { Rlog.e(TAG,"getAdnRecordsInEf iccPbkIntMgr is" + "null for Subscription:"+subId); return null; } }
3.IccPhoneBookInterfaceManager
/** * Loads the AdnRecords in efid and returns them as a * List of AdnRecords * * throws SecurityException if no READ_CONTACTS permission * * @param efid the EF id of a ADN-like ICC * @return List of AdnRecord */ public ListgetAdnRecordsInEf(int efid) { //檢查權(quán)限 if (mPhone.getContext().checkCallingOrSelfPermission( android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException( "Requires android.permission.READ_CONTACTS permission"); } //根據(jù)SIM卡類(lèi)型設(shè)定EF_ID efid = updateEfForIccType(efid); if (DBG) logd("getAdnRecordsInEF: efid=0x" + Integer.toHexString(efid).toUpperCase()); //線(xiàn)程同步 synchronized(mLock) { checkThread(); AtomicBoolean status = new AtomicBoolean(false); //回調(diào)message Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE, status); if (isSimPhoneBookEnabled() && (efid == IccConstants.EF_PBR || efid == IccConstants.EF_ADN)) { if (mSimPbAdnCache != null) { //查詢(xún)聯(lián)系人,通過(guò)message返回 mSimPbAdnCache.requestLoadAllAdnLike(response); //此處線(xiàn)程wait(),mBaseHandler 獲取mRecords后notifyPending(),代碼才能繼續(xù)往下執(zhí)行 waitForResult(status); } else { loge("Failure while trying to load from SIM due to uninit sim pb adncache"); } } else { if (mAdnCache != null) { mAdnCache.requestLoadAllAdnLike( efid, mAdnCache.extensionEfForEf(efid), response); waitForResult(status); } else { loge("Failure while trying to load from SIM due to uninitialised adncache"); } } } return mRecords; }
看看Handler的處理:
protected class IccPbHandler extends Handler {
public IccPbHandler(Looper looper) { super(looper); } @Override public void handleMessage(Message msg) { AsyncResult ar; switch (msg.what) { case EVENT_GET_SIZE_DONE: ar = (AsyncResult) msg.obj; synchronized (mLock) { if (ar.exception == null) { mRecordSize = (int[])ar.result; // recordSize[0] is the record length // recordSize[1] is the total length of the EF file // recordSize[2] is the number of records in the EF file logd("GET_RECORD_SIZE Size " + mRecordSize[0] + " total " + mRecordSize[1] + " #record " + mRecordSize[2]); } notifyPending(ar); } break; case EVENT_UPDATE_DONE: ar = (AsyncResult) msg.obj; if(ar.exception != null) { if(DBG) logd("exception of EVENT_UPDATE_DONE is" + ar.exception ); } synchronized (mLock) { mSuccess = (ar.exception == null); notifyPending(ar); } break; case EVENT_LOAD_DONE://查詢(xún)完成 ar = (AsyncResult)msg.obj; synchronized (mLock) { if (ar.exception == null) { if(DBG) logd("Load ADN records done"); //返回adn list mRecords = (List) ar.result; } else { if(DBG) logd("Cannot load ADN records"); mRecords = null; } //notify()喚醒 notifyPending(ar); } break; } }
4.SimPhoneBookAdnRecordCache查詢(xún),requestLoadAllAdnLike()方法
public void requestLoadAllAdnLike(Message response) { //加入message list if (mAdnLoadingWaiters != null) { mAdnLoadingWaiters.add(response); } //線(xiàn)程同步 synchronized (mLock) { if (!mSimPbRecords.isEmpty()) { log("ADN cache has already filled in"); if (mRefreshAdnCache) { mRefreshAdnCache = false; refreshAdnCache(); } else { notifyAndClearWaiters(); } return; } //查詢(xún)adn queryAdnRecord(); } }
queryAdnRecord方法:
public void queryAdnRecord () {
mRecCount = 0; mAdnCount = 0; mValidAdnCount = 0; mEmailCount = 0; mAddNumCount = 0; log("start to queryAdnRecord"); //查詢(xún)ADN record,返回容量 mCi.getAdnRecord(obtainMessage(EVENT_QUERY_ADN_RECORD_DONE)); //向RIL注冊(cè)ADN records info監(jiān)聽(tīng) mCi.registerForAdnRecordsInfo(this, EVENT_LOAD_ADN_RECORD_DONE, null); try { //線(xiàn)程等待,EVENT_LOAD_ADN_RECORD_DONE消息處理完(實(shí)際是EVENT_LOAD_ALL_ADN_LIKE_DONE)后notify喚醒 mLock.wait(); } catch (InterruptedException e) { Rlog.e(LOG_TAG, "Interrupted Exception in queryAdnRecord"); } //取消監(jiān)聽(tīng) mCi.unregisterForAdnRecordsInfo(this);
}
handlerMessage中的處理:
case EVENT_QUERY_ADN_RECORD_DONE: log("Querying ADN record done"); if (ar.exception != null) { synchronized (mLock) { mLock.notify(); } for (Message response : mAdnLoadingWaiters) { sendErrorResponse(response, "Query adn record failed" + ar.exception); } mAdnLoadingWaiters.clear(); break; } mAdnCount = ((int[]) (ar.result))[0]; mValidAdnCount = ((int[]) (ar.result))[1]; mEmailCount = ((int[]) (ar.result))[2]; mValidEmailCount = ((int[]) (ar.result))[3]; mAddNumCount = ((int[]) (ar.result))[4]; mValidAddNumCount = ((int[]) (ar.result))[5]; log("Max ADN count is: " + mAdnCount + ", Valid ADN count is: " + mValidAdnCount + ", Email count is: " + mEmailCount + ", Valid Email count is: " + mValidEmailCount + ", Add number count is: " + mAddNumCount + ", Valid Add number count is: " + mValidAddNumCount); if(mValidAdnCount == 0 || mRecCount == mValidAdnCount) { sendMessage(obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE)); } break; case EVENT_LOAD_ADN_RECORD_DONE: log("Loading ADN record done"); if (ar.exception != null) { break; } SimPhoneBookAdnRecord[] AdnRecordsGroup = (SimPhoneBookAdnRecord[])(ar.result); for (int i = 0 ; i < AdnRecordsGroup.length ; i++) { if (AdnRecordsGroup[i] != null) { mSimPbRecords.add(new AdnRecord(0, AdnRecordsGroup[i].getRecordIndex(), AdnRecordsGroup[i].getAlphaTag(), AdnRecordsGroup[i].getNumber(), AdnRecordsGroup[i].getEmails(), AdnRecordsGroup[i].getAdNumbers())); mRecCount ++; } } if(mRecCount == mValidAdnCount) { sendMessage(obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE)); } break; case EVENT_LOAD_ALL_ADN_LIKE_DONE: log("Loading all ADN records done"); synchronized (mLock) { mLock.notify(); } notifyAndClearWaiters(); break;
RIL先返回RIL_UNSOL_RESPONSE_ADN_RECORDS,在EVENT_LOAD_ADN_RECORD_DONE事件中處理,更新mSimPbRecords和MRecount;
然后RIL返回getAdnRecord的請(qǐng)求RIL_REQUEST_GET_ADN_RECORD,在EVENT_QUERY_ADN_RECORD_DONE消息處理,獲得Max ADN count/Valid ADN count等數(shù)據(jù);
然后發(fā)送EVENT_LOAD_ALL_ADN_LIKE_DONE消息,在該消息中mLock.notify()(queryAdnRecord 方法繼續(xù)執(zhí)行解除注冊(cè));
notifyAndClearWaiters方法將之前requestLoadAllAdnLike方法中記錄的messaage消息發(fā)出去,發(fā)給IccPhoneBookInterfaceManager處理;
IccPhoneBookInterfaceManager的getAdnRecordsInEf方法此時(shí)走到waitForResult(),線(xiàn)程wait,在mBaseHandler處理完 message后獲取mRecords,然后喚醒等待線(xiàn)程,getAdnRecordsInEf方法執(zhí)行完畢獲得返回and list。
開(kāi)機(jī)加載ADN log解析:
//通過(guò)ContentResolver調(diào)用provider查詢(xún) 3793:09-22 15:52:44.114 2230 2311 D IccProvider: [IccProvider] query //查詢(xún)URL 3800:09-22 15:52:44.115 2230 2311 D IccProvider: [IccProvider] getRequestSubId url: content://icc/adn/subId/1 3801:09-22 15:52:44.115 2230 2311 D IccProvider: [IccProvider] loadFromEf: efType=0x6F3A, subscription=1 //調(diào)用IccPbInterfaceManager getAdnRecordsInEF方法查詢(xún) 3802:09-22 15:52:44.116 2230 2311 D IccPhoneBookIM: [IccPbInterfaceManager] getAdnRecordsInEF: efid=0x4F30 //調(diào)用SimPhoneBookAdnRecordCache requestLoadAllAdnLike方法 3803:09-22 15:52:44.116 2230 2311 D SimPhoneBookAdnRecordCache: start to queryAdnRecord //queryAdnRecord方法通過(guò)RIL查詢(xún) 3804:09-22 15:52:44.117 2230 2311 D RILJ : [3884]> RIL_REQUEST_GET_ADN_RECORD [SUB1] //此處queryAdnRecord方法wait //RIL查詢(xún) 3806:09-22 15:52:44.135 2230 2293 D RILJ : Unsol response received for RIL_UNSOL_RESPONSE_ADN_RECORDS Sending ack to ril.cpp [SUB1] 3807:09-22 15:52:44.136 2230 2293 D RILJ : [SimPhoneBookAdnRecord{index =1, name = Bbbbbbbbb, number = 123456789, email count = 1, email = [zzzzz@huaqin.com], ad number count = 0, ad number = null}] [SUB1] 3808:09-22 15:52:44.136 2230 2293 D RILJ : [UNSL]< RIL_UNSOL_RESPONSE_ADN_RECORDS [SUB1] //RIL先返回RIL_UNSOL_RESPONSE_ADN_RECORDS 3809:09-22 15:52:44.136 2230 2230 D SimPhoneBookAdnRecordCache: Loading ADN record done 3810:09-22 15:52:44.136 2230 2293 D RILJ : [3884]< RIL_REQUEST_GET_ADN_RECORD {500, 1, 100, 1, 500, 0} [SUB1] //RIL然后返回RIL_REQUEST_GET_ADN_RECORD 3811:09-22 15:52:44.137 2230 2230 D SimPhoneBookAdnRecordCache: Querying ADN record done 3812:09-22 15:52:44.137 2230 2230 D SimPhoneBookAdnRecordCache: Max ADN count is: 500, Valid ADN count is: 1, Email count is: 100, Valid Email count is: 1, Add number count is: 500, Valid Add number count is: 0 //sendMessage(obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE)) 3817:09-22 15:52:44.147 2230 2230 D SimPhoneBookAdnRecordCache: Loading all ADN records done //此處notify 3818:09-22 15:52:44.147 2230 2230 D SimPhoneBookAdnRecordCache: Loading all ADN records done mLock.notify //此處解除注冊(cè) 3819:09-22 15:52:44.147 2230 2311 D SimPhoneBookAdnRecordCache: unregisterForAdnRecordsInfo //此處getAdnRecordsInEF方法wait 3820:09-22 15:52:44.147 2230 2311 D IccPhoneBookIM: [IccPbInterfaceManager] getAdnRecordsInEF: start wait 3821:09-22 15:52:44.148 2230 2311 D IccPhoneBookIM: [IccPbInterfaceManager] mLock.wait() //IccPbInterfaceManager處理EVENT_LOAD_DONE消息 3822:09-22 15:52:44.148 2230 2303 D IccPhoneBookIM: [IccPbInterfaceManager] Load ADN records done //處理完消息后喚醒 3823:09-22 15:52:44.148 2230 2303 D IccPhoneBookIM: [IccPbInterfaceManager] mLock.notifyAll //查詢(xún)執(zhí)行結(jié)束 3824:09-22 15:52:44.148 2230 2311 D IccPhoneBookIM: [IccPbInterfaceManager] getAdnRecordsInEF: end 3825:09-22 15:52:44.149 2230 2311 D IccProvider: [IccProvider] adnRecords.size=1 3826:09-22 15:52:44.149 2230 2311 D IccProvider: [IccProvider] loadRecord: Bbbbbbbbb, [98O8HYCOBHMq32eZZczDTKeuNEE] 3827:09-22 15:52:44.149 2230 2311 D IccProvider: [IccProvider] Adding email:[27d4JpidP9pzDQRt2hPJU82D-UA]
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/70529.html
摘要:幸運(yùn)的是,你可以透過(guò)撰寫(xiě)一個(gè)函數(shù)很輕易的去覆寫(xiě)選擇集,選中原本構(gòu)件的父節(jié)點(diǎn),而且你只要去監(jiān)聽(tīng)事件就可以達(dá)成了透過(guò)上面的修改,現(xiàn)在透過(guò)點(diǎn)擊構(gòu)件就可以選中構(gòu)件的父節(jié)點(diǎn),就可以看到所有我們想要的屬性數(shù)據(jù)。 showImg(https://segmentfault.com/img/bVVaYM?w=2478&h=1800); 這篇文章的原著是 Autodesk ADN 的 Adam Nagy。...
摘要:本文章的原作是的在版的里引入了一個(gè)重大的變革,開(kāi)始支持載入外部擴(kuò)展,細(xì)節(jié)可以參考這篇文章重大變更。這個(gè)函數(shù)自此刻起的函數(shù)回傳值不在是布林值,取而代之的是一個(gè)實(shí)例,這表示開(kāi)始支持使用非同步的方法在載入擴(kuò)展。 本文章的原作是 Autodesk ADN 的 Philippe Leefsma 在 v2.15 版的 Forge Viewer API 里引入了一個(gè)重大的變革,Viewer開(kāi)始支持載...
摘要:給大家推薦一個(gè)基于的右鍵彈出菜單插件,支持單一頁(yè)面以及可以在循環(huán)綁定中使用。項(xiàng)目地址為在原有基礎(chǔ)上進(jìn)行了重構(gòu),支持節(jié)子菜單。效果圖如下配置簡(jiǎn)單,可以像那樣去配置一個(gè)來(lái)設(shè)置選項(xiàng)。例如圖的配置項(xiàng)為選項(xiàng)選項(xiàng)選項(xiàng)選項(xiàng)選項(xiàng)選項(xiàng)選項(xiàng)選項(xiàng) 給大家推薦一個(gè)基于Vue2的右鍵彈出菜單插件,支持單一SPA頁(yè)面以及可以在循環(huán)綁定中使用。 項(xiàng)目地址為:https://github.com/chiic/vue-...
閱讀 1953·2021-11-19 09:40
閱讀 2677·2021-08-30 09:46
閱讀 2243·2021-08-03 14:01
閱讀 2695·2019-08-30 10:54
閱讀 1265·2019-08-29 16:38
閱讀 1497·2019-08-29 11:02
閱讀 2599·2019-08-28 18:16
閱讀 1766·2019-08-28 18:09