首页 热点专区 小学知识 中学知识 出国留学 考研考公
您的当前位置:首页正文

高通平台Sim卡联系人是怎么读取的?

2024-12-09 来源:要发发知识网

高通平台Sim卡联系人是怎么读取的?

App端Query Uri
=》IccProvider.loadFromEf(IccConstants.EF_ADN, subId)

=》UiccPhoneBookController(extends IIccPhoneBook.Stub).getAdnRecordsInEfForSubscriber

=》QtiIccPhoneBookInterfaceManager(As a member in GsmCdmaPhone).getAdnRecordsInEf
(
这里设计的很巧妙:
1 通过mBaseHandler构建EVENT_LOAD_DONE事件的Message, 将AtomicBoolean作为obj塞进去
2 检测AtomicBoolean的状态,不为true就一致wait
3 Message放入QtiSimPhoneBookAdnRecordCache的对列中等待notify
4 QtiSimPhoneBookAdnRecordCache查询完毕后将result和对列中的Message重新构建成AsyncResult 发送给Message的Handler处理
5 AsyncResult中有两个Object: userObj是原始的Message Object即AtomicBoolean, result是查询的sim卡联系人
6 mBaseHandler处理返回来的EVENT_LOAD_DONE事件,取出AsyncResult中的result赋值给成员变量mRecords,即要返回给上层App的
7 同时取出AsyncResult中的result的userObj赋值为true
8 步骤2中发现为true就不再wait, 此时mRecords也已经赋值,将此结果层层返回给上层App.
从这里可以看出ADN SIM卡联系人的查询是阻塞式的
)

=》efType为IccConstants.EF_PBR和IccConstants.EF_ADN类型走 QtiSimPhoneBookAdnRecordCache.requestLoadAllAdnLike
其他类型走AdnRecordCache.requestLoadAllAdnLike
EF文件是指Elementary File,顾名思义:包含了基本信息的文件
加载Sim卡联系人走的就是EF_ADN类型,调用QtiSimPhoneBookAdnRecordCache.requestLoadAllAdnLike

=》QtiSimPhoneBookAdnRecordCache.queryAdnRecord
(
AAA : QtiRilInterface.getAdnRecord(obtainMessage(EVENT_QUERY_ADN_RECORD_DONE), mPhoneId);
【这里是通过QcRilHook来下发请求的, 目的就是查询ADN中联系人的相关信息,最大电话个数,Email个数等】

  BBB : QtiRilInterface.registerForAdnRecordsInfo(this, EVENT_LOAD_ADN_RECORD_DONE, null);
  【这里注册到RegistrantList中,当QtiRilInterface中的mBroadcastReceiver接收ACTION_ADN_RECORDS_IND广播
    的时候将结果封装成AsyncResult,notify RegistrantList中的注册者,回调到上面步骤4中】
   

   ACTION_ADN_RECORDS_IND广播是这样发送的:
   RILD
   =》
   HIDL Service Of QtiOemHookIndication (extends IQtiOemHookIndication.Stub, 作为QcrilOemhookMsgTunnel的内部类)
   =》QtiOemHookIndication.oemHookRawIndication
   =》QcrilOemhookMsgTunnel.processOemHookIndication
   =》QcrilOemhookMsgTunnel.processUnsolOemhookResponse
   =》QcrilOemhookMsgTunnel.broadcastAdnRecordsInd

   ?????? 疑问一: 如果广播在注册之前已经接收到,后续该广播没有再发,后面再来注册的岂不无法notify ??????
   ?????? 疑问一: 在该广播发送完毕后才去请求Sim卡联系人是有时候加载不出来的原因吗               ??????

)

QtiSimPhoneBookAdnRecordCache顾名思义就是有Cache功能的,每次读取到ADN Sim卡联系人的结果都会缓存到mSimPbRecords列表中,
每次查询Call到requestLoadAllAdnLike的时候都会先检测缓存列表mSimPbRecords是否Empty,
不Empty且不需要更新则直接返回缓存结果;
不Empty需要更新则清除缓存并重新调用queryAdnRecord查询;
Empty则直接调用queryAdnRecord查询;
是否更新的逻辑:QtiSimPhoneBookAdnRecordCache监听SIM_STATE_CHANGED广播来确定更新标志

简化上面查询流程,重点在下面两个步骤:

CCC: QtiSimPhoneBookAdnRecordCache.requestLoadAllAdnLike 【synchronized (mLock)】
DDD: QtiSimPhoneBookAdnRecordCache.queryAdnRecord【mLock.wait】
上面AAA步骤中如果请求发生异常会mLock.notify():发生异常了读不到了,不需要等了;
上面AAA步骤中如果查询到的有效ADN个数为0最终也会mLock.notify():没有sim卡联系人,也不需要等了;
上面BBB步骤中如果请求发生异常不会mLock.notify();
上面BBB步骤中只有返回结果的个数和AAA步骤中查询到的有效个数相同才会mLock.notify();

Question: 当发起多个线程同时查询Sim卡ADN联系人的时候会怎么样?
首先走到上面CCC的时候因为同步锁,会一个一个等待,
无异常的情况下,第一次查询完毕,后续的查询通过缓存会很快返回;
DDD中出现异常就会造成死锁,mLock一直无法释放,如果后面继续有新的访问请求,就会导致binder_thread耗尽。

所以BBB中的notify逻辑需要讨论下是否更改,BBB很容易导致死锁,处于一直wait状态。
修改建议:
1 DDD中出现异常执行mLock.notify()
2 wait设置超时时间

显示全文