ADN加载流程:

IccProvider.java

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

android:authorities="icc"

android:multiprocess="true"

android:exported="true"

android:readPermission="android.permission.READ_CONTACTS"

android:writePermission="android.permission.WRITE_CONTACTS" />

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);

List adnRecords = 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 List getAdnRecordsInEfForSubscriber(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 List getAdnRecordsInEf(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]

adn进程JAVA_ADN加载流程相关推荐

  1. iOS进阶之底层原理-应用程序加载(dyld加载流程、类与分类的加载)

    iOS应用程序的入口是main函数,那么main函数之前系统做了什么呢? 我们定义一个类方法load,打断点,查看栈进程,我们发现dyld做了很多事,接下来就来探究到底dyld做了什么. 什么是dyl ...

  2. Android 系统(169)---Android 7.0 插卡后APN信息的加载流程

    Android 7.0 插卡后APN信息的加载流程.UI界面编辑APN的流程及Android中APN配置相关的漏洞 终端中有一个apns-config.xml文件,负责定义各个运营商规定的默认APN参 ...

  3. Android SIM卡识别加载流程

    文章目录 总述 代码路径 UICC框架 SIM卡识别加载流程 日志分析举例 总述 本文基于Android N(Android 7) 首先要知道SIM卡一般是挂载在CP侧(MODEM侧)的,由MODEM ...

  4. linux驱动加载流程分析

    linux驱动加载流程分析 内核是如何加载驱动的,有些是编译到内核里面,有些事编译成ko,让系统自动加载.总的说来,在Linux下可以通过两种方式加载驱动程序:静态加载和动态加载. 静态加载就是把驱动 ...

  5. Launcher启动流程加载流程学习

     声明: 图片本来是有的 涉及到有些代码不能示人没有贴上,不过仅文字说也足够了,请广大老爷们自行下载源码参看流程分析阅读. 目录 一.认识Launcher: 1 1.功能 1 2.样式 2 3.And ...

  6. Pinpoint Agent加载流程分析

    pinpoint 版本:2.0.3-SNAPSHOT pinpoint利用java agent 特性,提供了一个agent jar包,此jar包会在应用运行之前先运行,agent和应用在同一个进程.p ...

  7. 打卡学习Gradle深度解析 - kts脚本加载流程

    kts脚本加载流程 和groovy脚本一样,kts脚本也分为2个阶段 stage 1 执行buildscript和plugins部分,执行结果会对stage2 program的classpath有影响 ...

  8. QT程序启动加载流程简介

    1. QT应用程序启动加载流程简介 1.1      QWS与QPA启动客户端程序区别 1.1.1   QWS(Qt Window System)介绍 QWS(Qt Windows System)是Q ...

  9. AngularJS 初始化加载流程

    一.AngularJS 初始化加载流程 1.浏览器载入HTML,然后把它解析成DOM. 2.浏览器载入angular.js脚本. 3.AngularJS等到DOMContentLoaded事件触发. ...

最新文章

  1. 集成学习之Bagging
  2. vim文本编辑器使用技巧
  3. java对象的强引用,软引用,弱引用和虚引用
  4. Python语言的有限状态机实现样例
  5. React Native之函数作为参数传递给另外一个函数去调用
  6. 344. 反转字符串 golang
  7. tensorflow eager 模式下打印dataset中的数据
  8. kong 网关教程入门
  9. win10 查看系统开机历史记录
  10. instantclient 配置 链接oracle,PLSQL与InstantClient的配置
  11. 前端html5 css3 教案,Web前端开发任务驱动式教程(HTML5+CSS3+JavaScript)
  12. 登顶多国免费榜,Zynga能否依靠超休闲游戏重回巨头行列
  13. usb-OTG-ADP-HNP-SRP
  14. 一图看尽APP各推广渠道“超级用户浓度”| 互联网行业公会
  15. 基于Springboot中小餐厅点餐管理系统设计
  16. C++ 实用趣味小程序
  17. 那些年, 你读错过的IT名词
  18. 远场(far-field)语音识别的主流技术有哪些
  19. WSL2设置局域网网访问
  20. 【JavaScript】移动端扫描二维码检测浏览器(微信、支付宝、Safari、其他浏览器)

热门文章

  1. Python pandas导excel数据量太大报错问题
  2. 用c语言输出一个月的月历
  3. 单目vo中的深度确定方法--三角测量
  4. Guitar Pro8吉他软件主要功能详解及安装教程
  5. python 字符串和十六进制的相互转化
  6. 修复Premiere Pro 2022 V22.5 意外退出 fix Premier Pro quit unexpectedly
  7. python制作快递查询小软件
  8. eis电子防抖好还是光学防抖好_【玩码】OPPO Reno2 搭载超级视频防抖技术,视频拍摄稳得很...
  9. 使用阿里云优惠券轻松享受超强性能大数据型实例
  10. 华为数通笔记-ISIS高级特性