摘要:加载流程定义在从上面可以看到,真正的是在中继承,处理的等操作,和卡交互完成后,将数据改变信息通知给然后将数据变化的发送给注册监听的应用,应用做相应的同步动作。
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]
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/70529.html
摘要:本文章的原作是的在版的里引入了一个重大的变革,开始支持载入外部扩展,细节可以参考这篇文章重大变更。这个函数自此刻起的函数回传值不在是布林值,取而代之的是一个实例,这表示开始支持使用非同步的方法在载入扩展。 本文章的原作是 Autodesk ADN 的 Philippe Leefsma 在 v2.15 版的 Forge Viewer API 里引入了一个重大的变革,Viewer开始支持载...
摘要:给大家推荐一个基于的右键弹出菜单插件,支持单一页面以及可以在循环绑定中使用。项目地址为在原有基础上进行了重构,支持节子菜单。效果图如下配置简单,可以像那样去配置一个来设置选项。例如图的配置项为选项选项选项选项选项选项选项选项 给大家推荐一个基于Vue2的右键弹出菜单插件,支持单一SPA页面以及可以在循环绑定中使用。 项目地址为:https://github.com/chiic/vue-...
阅读 1879·2021-11-19 09:40
阅读 2596·2021-08-30 09:46
阅读 2179·2021-08-03 14:01
阅读 2650·2019-08-30 10:54
阅读 1201·2019-08-29 16:38
阅读 1441·2019-08-29 11:02
阅读 2539·2019-08-28 18:16
阅读 1685·2019-08-28 18:09