资讯专栏INFORMATION COLUMN

ADN加载流程

A Loity / 2910人阅读

摘要:加载流程定义在从上面可以看到,真正的是在中继承,处理的等操作,和卡交互完成后,将数据改变信息通知给然后将数据变化的发送给注册监听的应用,应用做相应的同步动作。

ADN加载流程:

IccProvider.java
IccProvider定义在/packages/services/Telephony/AndroidManifest.xml

</>复制代码

  1. public class IccProvider extends com.android.internal.telephony.IccProvider {
  2. public IccProvider() {
  3. super();
  4. }
  5. }

从上面可以看到,真正的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的构造方法:

</>复制代码

  1. public class UiccPhoneBookController extends IIccPhoneBook.Stub {
  2. private static final String TAG = "UiccPhoneBookController";
  3. private Phone[] mPhone;
  4. /* only one UiccPhoneBookController exists */
  5. public UiccPhoneBookController(Phone[] phone) {
  6. if (ServiceManager.getService("simphonebook") == null) {
  7. ServiceManager.addService("simphonebook", this);
  8. }
  9. mPhone = phone;

IccProvider通过AIDL调用UiccPhoneBookController:

</>复制代码

  1. try {
  2. IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
  3. ServiceManager.getService("simphonebook"));
  4. if (iccIpb != null) {
  5. success = iccIpb.updateAdnRecordsInEfBySearchForSubscriber(subId, efType,
  6. "", "", name, number, pin2);
  7. }
  8. } catch (RemoteException ex) {
  9. // ignore it
  10. } catch (SecurityException ex) {
  11. if (DBG) log(ex.toString());
  12. }

关于AIDL的实现后面详细学习
IccPhoneBookInterfaceManager.java
IccPhoneBookInterfaceManager是在Phone的初始化时完成实例化:

</>复制代码

  1. 在GsmCdmaPhone构造方法initOnce()中:
  2. mIccPhoneBookIntManager = mTelephonyComponentFactory.makeIccPhoneBookInterfaceManager(this);

SimPhoneBookAdnRecordCache.java
SimPhoneBookAdnRecordCache在IccPhoneBookInterfaceManager构造方法中完成初始化:
public IccPhoneBookInterfaceManager(Phone phone) {

</>复制代码

  1. this.mPhone = phone;
  2. IccRecords r = phone.getIccRecords();
  3. if (r != null) {
  4. mAdnCache = r.getAdnCache();
  5. }
  6. if(isSimPhoneBookEnabled()){
  7. if(mSimPbAdnCache == null) {
  8. mSimPbAdnCache = new SimPhoneBookAdnRecordCache(
  9. phone.getContext(), phone.getPhoneId(), phone.mCi);
  10. }
  11. }
  12. }

查询SIM卡联系人流程
1 IccProvider

</>复制代码

  1. private static final UriMatcher URL_MATCHER =
  2. new UriMatcher(UriMatcher.NO_MATCH);
  3. static {
  4. URL_MATCHER.addURI("icc", "adn", ADN);
  5. URL_MATCHER.addURI("icc", "adn/subId/#", ADN_SUB);
  6. URL_MATCHER.addURI("icc", "fdn", FDN);
  7. URL_MATCHER.addURI("icc", "fdn/subId/#", FDN_SUB);
  8. URL_MATCHER.addURI("icc", "sdn", SDN);
  9. URL_MATCHER.addURI("icc", "sdn/subId/#", SDN_SUB);
  10. }
  11. 支持ADN/FDN/SDN的URL
  12. private MatrixCursor loadFromEf(int efType, int subId) {
  13. if (DBG) log("loadFromEf: efType=0x" +
  14. Integer.toHexString(efType).toUpperCase() + ", subscription=" + subId);
  15. List adnRecords = null;
  16. try {
  17. IIccPhoneBook iccIpb = IIccPhoneBook.Stub.asInterface(
  18. ServiceManager.getService("simphonebook"));
  19. if (iccIpb != null) {
  20. adnRecords = iccIpb.getAdnRecordsInEfForSubscriber(subId, efType);
  21. }
  22. } catch (RemoteException ex) {
  23. // ignore it
  24. } catch (SecurityException ex) {
  25. if (DBG) log(ex.toString());
  26. }
  27. //获取adn list转换成cursor
  28. if (adnRecords != null) {
  29. // Load the results
  30. final int N = adnRecords.size();
  31. final MatrixCursor cursor = new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES, N);
  32. if (DBG) log("adnRecords.size=" + N);
  33. for (int i = 0; i < N ; i++) {
  34. loadRecord(adnRecords.get(i), cursor, i);
  35. }
  36. return cursor;
  37. } else {
  38. // No results to load
  39. Rlog.w(TAG, "Cannot load ADN records");
  40. return new MatrixCursor(ADDRESS_BOOK_COLUMN_NAMES);
  41. }
  42. }

UiccPhoneBookController时一个Binder服务类,接口是IIccPhoneBook,服务名"simphonebook"

2.UiccPhoneBookController
getAdnRecordsInEfForSubscriber方法:

</>复制代码

  1. @Override
  2. public List getAdnRecordsInEfForSubscriber(int subId, int efid)
  3. throws android.os.RemoteException {
  4. //获取实例,实例在文章开始Phone初始化时设置
  5. IccPhoneBookInterfaceManager iccPbkIntMgr =
  6. getIccPhoneBookInterfaceManager(subId);
  7. if (iccPbkIntMgr != null) {
  8. //调用getAdnRecordsInEf方法
  9. return iccPbkIntMgr.getAdnRecordsInEf(efid);
  10. } else {
  11. Rlog.e(TAG,"getAdnRecordsInEf iccPbkIntMgr is" +
  12. "null for Subscription:"+subId);
  13. return null;
  14. }
  15. }

3.IccPhoneBookInterfaceManager

</>复制代码

  1. /**
  2. * Loads the AdnRecords in efid and returns them as a
  3. * List of AdnRecords
  4. *
  5. * throws SecurityException if no READ_CONTACTS permission
  6. *
  7. * @param efid the EF id of a ADN-like ICC
  8. * @return List of AdnRecord
  9. */
  10. public List getAdnRecordsInEf(int efid) {
  11. //检查权限
  12. if (mPhone.getContext().checkCallingOrSelfPermission(
  13. android.Manifest.permission.READ_CONTACTS)
  14. != PackageManager.PERMISSION_GRANTED) {
  15. throw new SecurityException(
  16. "Requires android.permission.READ_CONTACTS permission");
  17. }
  18. //根据SIM卡类型设定EF_ID
  19. efid = updateEfForIccType(efid);
  20. if (DBG) logd("getAdnRecordsInEF: efid=0x" + Integer.toHexString(efid).toUpperCase());
  21. //线程同步
  22. synchronized(mLock) {
  23. checkThread();
  24. AtomicBoolean status = new AtomicBoolean(false);
  25. //回调message
  26. Message response = mBaseHandler.obtainMessage(EVENT_LOAD_DONE, status);
  27. if (isSimPhoneBookEnabled() &&
  28. (efid == IccConstants.EF_PBR || efid == IccConstants.EF_ADN)) {
  29. if (mSimPbAdnCache != null) {
  30. //查询联系人,通过message返回
  31. mSimPbAdnCache.requestLoadAllAdnLike(response);
  32. //此处线程wait(),mBaseHandler 获取mRecords后notifyPending(),代码才能继续往下执行
  33. waitForResult(status);
  34. } else {
  35. loge("Failure while trying to load from SIM due to uninit sim pb adncache");
  36. }
  37. } else {
  38. if (mAdnCache != null) {
  39. mAdnCache.requestLoadAllAdnLike(
  40. efid, mAdnCache.extensionEfForEf(efid), response);
  41. waitForResult(status);
  42. } else {
  43. loge("Failure while trying to load from SIM due to uninitialised adncache");
  44. }
  45. }
  46. }
  47. return mRecords;
  48. }

看看Handler的处理:
protected class IccPbHandler extends Handler {

</>复制代码

  1. public IccPbHandler(Looper looper) {
  2. super(looper);
  3. }
  4. @Override
  5. public void handleMessage(Message msg) {
  6. AsyncResult ar;
  7. switch (msg.what) {
  8. case EVENT_GET_SIZE_DONE:
  9. ar = (AsyncResult) msg.obj;
  10. synchronized (mLock) {
  11. if (ar.exception == null) {
  12. mRecordSize = (int[])ar.result;
  13. // recordSize[0] is the record length
  14. // recordSize[1] is the total length of the EF file
  15. // recordSize[2] is the number of records in the EF file
  16. logd("GET_RECORD_SIZE Size " + mRecordSize[0] +
  17. " total " + mRecordSize[1] +
  18. " #record " + mRecordSize[2]);
  19. }
  20. notifyPending(ar);
  21. }
  22. break;
  23. case EVENT_UPDATE_DONE:
  24. ar = (AsyncResult) msg.obj;
  25. if(ar.exception != null) {
  26. if(DBG) logd("exception of EVENT_UPDATE_DONE is" + ar.exception );
  27. }
  28. synchronized (mLock) {
  29. mSuccess = (ar.exception == null);
  30. notifyPending(ar);
  31. }
  32. break;
  33. case EVENT_LOAD_DONE://查询完成
  34. ar = (AsyncResult)msg.obj;
  35. synchronized (mLock) {
  36. if (ar.exception == null) {
  37. if(DBG) logd("Load ADN records done");
  38. //返回adn list
  39. mRecords = (List) ar.result;
  40. } else {
  41. if(DBG) logd("Cannot load ADN records");
  42. mRecords = null;
  43. }
  44. //notify()唤醒
  45. notifyPending(ar);
  46. }
  47. break;
  48. }
  49. }

4.SimPhoneBookAdnRecordCache查询,requestLoadAllAdnLike()方法

</>复制代码

  1. public void requestLoadAllAdnLike(Message response) {
  2. //加入message list
  3. if (mAdnLoadingWaiters != null) {
  4. mAdnLoadingWaiters.add(response);
  5. }
  6. //线程同步
  7. synchronized (mLock) {
  8. if (!mSimPbRecords.isEmpty()) {
  9. log("ADN cache has already filled in");
  10. if (mRefreshAdnCache) {
  11. mRefreshAdnCache = false;
  12. refreshAdnCache();
  13. } else {
  14. notifyAndClearWaiters();
  15. }
  16. return;
  17. }
  18. //查询adn
  19. queryAdnRecord();
  20. }
  21. }

queryAdnRecord方法:

public void queryAdnRecord () {

</>复制代码

  1. mRecCount = 0;
  2. mAdnCount = 0;
  3. mValidAdnCount = 0;
  4. mEmailCount = 0;
  5. mAddNumCount = 0;
  6. log("start to queryAdnRecord");
  7. //查询ADN record,返回容量
  8. mCi.getAdnRecord(obtainMessage(EVENT_QUERY_ADN_RECORD_DONE));
  9. //向RIL注册ADN records info监听
  10. mCi.registerForAdnRecordsInfo(this, EVENT_LOAD_ADN_RECORD_DONE, null);
  11. try {
  12. //线程等待,EVENT_LOAD_ADN_RECORD_DONE消息处理完(实际是EVENT_LOAD_ALL_ADN_LIKE_DONE)后notify唤醒
  13. mLock.wait();
  14. } catch (InterruptedException e) {
  15. Rlog.e(LOG_TAG, "Interrupted Exception in queryAdnRecord");
  16. }
  17. //取消监听
  18. mCi.unregisterForAdnRecordsInfo(this);

}
handlerMessage中的处理:

</>复制代码

  1. case EVENT_QUERY_ADN_RECORD_DONE:
  2. log("Querying ADN record done");
  3. if (ar.exception != null) {
  4. synchronized (mLock) {
  5. mLock.notify();
  6. }
  7. for (Message response : mAdnLoadingWaiters) {
  8. sendErrorResponse(response, "Query adn record failed" + ar.exception);
  9. }
  10. mAdnLoadingWaiters.clear();
  11. break;
  12. }
  13. mAdnCount = ((int[]) (ar.result))[0];
  14. mValidAdnCount = ((int[]) (ar.result))[1];
  15. mEmailCount = ((int[]) (ar.result))[2];
  16. mValidEmailCount = ((int[]) (ar.result))[3];
  17. mAddNumCount = ((int[]) (ar.result))[4];
  18. mValidAddNumCount = ((int[]) (ar.result))[5];
  19. log("Max ADN count is: " + mAdnCount
  20. + ", Valid ADN count is: " + mValidAdnCount
  21. + ", Email count is: " + mEmailCount
  22. + ", Valid Email count is: " + mValidEmailCount
  23. + ", Add number count is: " + mAddNumCount
  24. + ", Valid Add number count is: " + mValidAddNumCount);
  25. if(mValidAdnCount == 0 || mRecCount == mValidAdnCount) {
  26. sendMessage(obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE));
  27. }
  28. break;
  29. case EVENT_LOAD_ADN_RECORD_DONE:
  30. log("Loading ADN record done");
  31. if (ar.exception != null) {
  32. break;
  33. }
  34. SimPhoneBookAdnRecord[] AdnRecordsGroup = (SimPhoneBookAdnRecord[])(ar.result);
  35. for (int i = 0 ; i < AdnRecordsGroup.length ; i++) {
  36. if (AdnRecordsGroup[i] != null) {
  37. mSimPbRecords.add(new AdnRecord(0,
  38. AdnRecordsGroup[i].getRecordIndex(),
  39. AdnRecordsGroup[i].getAlphaTag(),
  40. AdnRecordsGroup[i].getNumber(),
  41. AdnRecordsGroup[i].getEmails(),
  42. AdnRecordsGroup[i].getAdNumbers()));
  43. mRecCount ++;
  44. }
  45. }
  46. if(mRecCount == mValidAdnCount) {
  47. sendMessage(obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE));
  48. }
  49. break;
  50. case EVENT_LOAD_ALL_ADN_LIKE_DONE:
  51. log("Loading all ADN records done");
  52. synchronized (mLock) {
  53. mLock.notify();
  54. }
  55. notifyAndClearWaiters();
  56. 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解析:

</>复制代码

  1. //通过ContentResolver调用provider查询
  2. 3793:09-22 15:52:44.114 2230 2311 D IccProvider: [IccProvider] query
  3. //查询URL
  4. 3800:09-22 15:52:44.115 2230 2311 D IccProvider: [IccProvider] getRequestSubId url: content://icc/adn/subId/1
  5. 3801:09-22 15:52:44.115 2230 2311 D IccProvider: [IccProvider] loadFromEf: efType=0x6F3A, subscription=1
  6. //调用IccPbInterfaceManager getAdnRecordsInEF方法查询
  7. 3802:09-22 15:52:44.116 2230 2311 D IccPhoneBookIM: [IccPbInterfaceManager] getAdnRecordsInEF: efid=0x4F30
  8. //调用SimPhoneBookAdnRecordCache requestLoadAllAdnLike方法
  9. 3803:09-22 15:52:44.116 2230 2311 D SimPhoneBookAdnRecordCache: start to queryAdnRecord
  10. //queryAdnRecord方法通过RIL查询
  11. 3804:09-22 15:52:44.117 2230 2311 D RILJ : [3884]> RIL_REQUEST_GET_ADN_RECORD [SUB1]
  12. //此处queryAdnRecord方法wait
  13. //RIL查询
  14. 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]
  15. 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]
  16. 3808:09-22 15:52:44.136 2230 2293 D RILJ : [UNSL]< RIL_UNSOL_RESPONSE_ADN_RECORDS [SUB1]
  17. //RIL先返回RIL_UNSOL_RESPONSE_ADN_RECORDS
  18. 3809:09-22 15:52:44.136 2230 2230 D SimPhoneBookAdnRecordCache: Loading ADN record done
  19. 3810:09-22 15:52:44.136 2230 2293 D RILJ : [3884]< RIL_REQUEST_GET_ADN_RECORD {500, 1, 100, 1, 500, 0} [SUB1]
  20. //RIL然后返回RIL_REQUEST_GET_ADN_RECORD
  21. 3811:09-22 15:52:44.137 2230 2230 D SimPhoneBookAdnRecordCache: Querying ADN record done
  22. 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
  23. //sendMessage(obtainMessage(EVENT_LOAD_ALL_ADN_LIKE_DONE))
  24. 3817:09-22 15:52:44.147 2230 2230 D SimPhoneBookAdnRecordCache: Loading all ADN records done
  25. //此处notify
  26. 3818:09-22 15:52:44.147 2230 2230 D SimPhoneBookAdnRecordCache: Loading all ADN records done mLock.notify
  27. //此处解除注册
  28. 3819:09-22 15:52:44.147 2230 2311 D SimPhoneBookAdnRecordCache: unregisterForAdnRecordsInfo
  29. //此处getAdnRecordsInEF方法wait
  30. 3820:09-22 15:52:44.147 2230 2311 D IccPhoneBookIM: [IccPbInterfaceManager] getAdnRecordsInEF: start wait
  31. 3821:09-22 15:52:44.148 2230 2311 D IccPhoneBookIM: [IccPbInterfaceManager] mLock.wait()
  32. //IccPbInterfaceManager处理EVENT_LOAD_DONE消息
  33. 3822:09-22 15:52:44.148 2230 2303 D IccPhoneBookIM: [IccPbInterfaceManager] Load ADN records done
  34. //处理完消息后唤醒
  35. 3823:09-22 15:52:44.148 2230 2303 D IccPhoneBookIM: [IccPbInterfaceManager] mLock.notifyAll
  36. //查询执行结束
  37. 3824:09-22 15:52:44.148 2230 2311 D IccPhoneBookIM: [IccPbInterfaceManager] getAdnRecordsInEF: end
  38. 3825:09-22 15:52:44.149 2230 2311 D IccProvider: [IccProvider] adnRecords.size=1
  39. 3826:09-22 15:52:44.149 2230 2311 D IccProvider: [IccProvider] loadRecord: Bbbbbbbbb, [98O8HYCOBHMq32eZZczDTKeuNEE]
  40. 3827:09-22 15:52:44.149 2230 2311 D IccProvider: [IccProvider] Adding email:[27d4JpidP9pzDQRt2hPJU82D-UA]

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/70529.html

相关文章

  • 选择集覆写

    摘要:幸运的是,你可以透过撰写一个函数很轻易的去覆写选择集,选中原本构件的父节点,而且你只要去监听事件就可以达成了透过上面的修改,现在透过点击构件就可以选中构件的父节点,就可以看到所有我们想要的属性数据。 showImg(https://segmentfault.com/img/bVVaYM?w=2478&h=1800); 这篇文章的原著是 Autodesk ADN 的 Adam Nagy。...

    princekin 评论0 收藏0
  • 在 Forge Viewer 载入外部扩展

    摘要:本文章的原作是的在版的里引入了一个重大的变革,开始支持载入外部扩展,细节可以参考这篇文章重大变更。这个函数自此刻起的函数回传值不在是布林值,取而代之的是一个实例,这表示开始支持使用非同步的方法在载入扩展。 本文章的原作是 Autodesk ADN 的 Philippe Leefsma 在 v2.15 版的 Forge Viewer API 里引入了一个重大的变革,Viewer开始支持载...

    LinkedME2016 评论0 收藏0
  • Vue2的右键弹出菜单(vue-contextmenu)

    摘要:给大家推荐一个基于的右键弹出菜单插件,支持单一页面以及可以在循环绑定中使用。项目地址为在原有基础上进行了重构,支持节子菜单。效果图如下配置简单,可以像那样去配置一个来设置选项。例如图的配置项为选项选项选项选项选项选项选项选项 给大家推荐一个基于Vue2的右键弹出菜单插件,支持单一SPA页面以及可以在循环绑定中使用。 项目地址为:https://github.com/chiic/vue-...

    wangym 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<