摘要:加載流程定義在從上面可以看到,真正的是在中繼承,處理的等操作,和卡交互完成后,將數據改變信息通知給然后將數據變化的發送給注冊監聽的應用,應用做相應的同步動作。
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卡交互完成后,將數據改變信息通知給ContentObserver,然后ContentObserver將數據變化的發送給注冊監聽的應用,Contacts應用做相應的同步動作。
Contacts數據庫和SIM卡聯系的同步后面繼續分析。
關于ContentProvider和ContentResolver以及ContentObserver的介紹,可以參考:
http://blog.csdn.net/dmk877/a...
IccProvider重寫ContentProvider的方法:
UiccPhoneBookController.java
UiccPhoneBookController在ProxyController的構造方法中初始化。
mUiccPhoneBookController = new UiccPhoneBookController(mPhones);
UiccPhoneBookController的構造方法:
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通過AIDL調用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()); }
關于AIDL的實現后面詳細學習
IccPhoneBookInterfaceManager.java
IccPhoneBookInterfaceManager是在Phone的初始化時完成實例化:
在GsmCdmaPhone構造方法initOnce()中: mIccPhoneBookIntManager = mTelephonyComponentFactory.makeIccPhoneBookInterfaceManager(this);
SimPhoneBookAdnRecordCache.java
SimPhoneBookAdnRecordCache在IccPhoneBookInterfaceManager構造方法中完成初始化:
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); } } }
查詢SIM卡聯系人流程
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轉換成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時一個Binder服務類,接口是IIccPhoneBook,服務名"simphonebook"
2.UiccPhoneBookController
getAdnRecordsInEfForSubscriber方法:
@Override public ListgetAdnRecordsInEfForSubscriber(int subId, int efid) throws android.os.RemoteException { //獲取實例,實例在文章開始Phone初始化時設置 IccPhoneBookInterfaceManager iccPbkIntMgr = getIccPhoneBookInterfaceManager(subId); if (iccPbkIntMgr != null) { //調用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) { //檢查權限 if (mPhone.getContext().checkCallingOrSelfPermission( android.Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { throw new SecurityException( "Requires android.permission.READ_CONTACTS permission"); } //根據SIM卡類型設定EF_ID efid = updateEfForIccType(efid); if (DBG) logd("getAdnRecordsInEF: efid=0x" + Integer.toHexString(efid).toUpperCase()); //線程同步 synchronized(mLock) { checkThread(); AtomicBoolean status = new AtomicBoolean(false); //回調message Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE, status); if (isSimPhoneBookEnabled() && (efid == IccConstants.EF_PBR || efid == IccConstants.EF_ADN)) { if (mSimPbAdnCache != null) { //查詢聯系人,通過message返回 mSimPbAdnCache.requestLoadAllAdnLike(response); //此處線程wait(),mBaseHandler 獲取mRecords后notifyPending(),代碼才能繼續往下執行 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://查詢完成 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查詢,requestLoadAllAdnLike()方法
public void requestLoadAllAdnLike(Message response) { //加入message list if (mAdnLoadingWaiters != null) { mAdnLoadingWaiters.add(response); } //線程同步 synchronized (mLock) { if (!mSimPbRecords.isEmpty()) { log("ADN cache has already filled in"); if (mRefreshAdnCache) { mRefreshAdnCache = false; refreshAdnCache(); } else { notifyAndClearWaiters(); } return; } //查詢adn queryAdnRecord(); } }
queryAdnRecord方法:
public void queryAdnRecord () {
mRecCount = 0; mAdnCount = 0; mValidAdnCount = 0; mEmailCount = 0; mAddNumCount = 0; log("start to queryAdnRecord"); //查詢ADN record,返回容量 mCi.getAdnRecord(obtainMessage(EVENT_QUERY_ADN_RECORD_DONE)); //向RIL注冊ADN records info監聽 mCi.registerForAdnRecordsInfo(this, EVENT_LOAD_ADN_RECORD_DONE, null); try { //線程等待,EVENT_LOAD_ADN_RECORD_DONE消息處理完(實際是EVENT_LOAD_ALL_ADN_LIKE_DONE)后notify喚醒 mLock.wait(); } catch (InterruptedException e) { Rlog.e(LOG_TAG, "Interrupted Exception in queryAdnRecord"); } //取消監聽 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的請求RIL_REQUEST_GET_ADN_RECORD,在EVENT_QUERY_ADN_RECORD_DONE消息處理,獲得Max ADN count/Valid ADN count等數據;
然后發送EVENT_LOAD_ALL_ADN_LIKE_DONE消息,在該消息中mLock.notify()(queryAdnRecord 方法繼續執行解除注冊);
notifyAndClearWaiters方法將之前requestLoadAllAdnLike方法中記錄的messaage消息發出去,發給IccPhoneBookInterfaceManager處理;
IccPhoneBookInterfaceManager的getAdnRecordsInEf方法此時走到waitForResult(),線程wait,在mBaseHandler處理完 message后獲取mRecords,然后喚醒等待線程,getAdnRecordsInEf方法執行完畢獲得返回and list。
開機加載ADN log解析:
//通過ContentResolver調用provider查詢 3793:09-22 15:52:44.114 2230 2311 D IccProvider: [IccProvider] query //查詢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 //調用IccPbInterfaceManager getAdnRecordsInEF方法查詢 3802:09-22 15:52:44.116 2230 2311 D IccPhoneBookIM: [IccPbInterfaceManager] getAdnRecordsInEF: efid=0x4F30 //調用SimPhoneBookAdnRecordCache requestLoadAllAdnLike方法 3803:09-22 15:52:44.116 2230 2311 D SimPhoneBookAdnRecordCache: start to queryAdnRecord //queryAdnRecord方法通過RIL查詢 3804:09-22 15:52:44.117 2230 2311 D RILJ : [3884]> RIL_REQUEST_GET_ADN_RECORD [SUB1] //此處queryAdnRecord方法wait //RIL查詢 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 //此處解除注冊 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 //查詢執行結束 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]
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70529.html
摘要:本文章的原作是的在版的里引入了一個重大的變革,開始支持載入外部擴展,細節可以參考這篇文章重大變更。這個函數自此刻起的函數回傳值不在是布林值,取而代之的是一個實例,這表示開始支持使用非同步的方法在載入擴展。 本文章的原作是 Autodesk ADN 的 Philippe Leefsma 在 v2.15 版的 Forge Viewer API 里引入了一個重大的變革,Viewer開始支持載...
摘要:給大家推薦一個基于的右鍵彈出菜單插件,支持單一頁面以及可以在循環綁定中使用。項目地址為在原有基礎上進行了重構,支持節子菜單。效果圖如下配置簡單,可以像那樣去配置一個來設置選項。例如圖的配置項為選項選項選項選項選項選項選項選項 給大家推薦一個基于Vue2的右鍵彈出菜單插件,支持單一SPA頁面以及可以在循環綁定中使用。 項目地址為:https://github.com/chiic/vue-...
閱讀 1877·2021-11-19 09:40
閱讀 2594·2021-08-30 09:46
閱讀 2177·2021-08-03 14:01
閱讀 2648·2019-08-30 10:54
閱讀 1197·2019-08-29 16:38
閱讀 1440·2019-08-29 11:02
閱讀 2536·2019-08-28 18:16
閱讀 1679·2019-08-28 18:09