adn进程JAVA_ADN加载流程
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加载流程相关推荐
- iOS进阶之底层原理-应用程序加载(dyld加载流程、类与分类的加载)
iOS应用程序的入口是main函数,那么main函数之前系统做了什么呢? 我们定义一个类方法load,打断点,查看栈进程,我们发现dyld做了很多事,接下来就来探究到底dyld做了什么. 什么是dyl ...
- Android 系统(169)---Android 7.0 插卡后APN信息的加载流程
Android 7.0 插卡后APN信息的加载流程.UI界面编辑APN的流程及Android中APN配置相关的漏洞 终端中有一个apns-config.xml文件,负责定义各个运营商规定的默认APN参 ...
- Android SIM卡识别加载流程
文章目录 总述 代码路径 UICC框架 SIM卡识别加载流程 日志分析举例 总述 本文基于Android N(Android 7) 首先要知道SIM卡一般是挂载在CP侧(MODEM侧)的,由MODEM ...
- linux驱动加载流程分析
linux驱动加载流程分析 内核是如何加载驱动的,有些是编译到内核里面,有些事编译成ko,让系统自动加载.总的说来,在Linux下可以通过两种方式加载驱动程序:静态加载和动态加载. 静态加载就是把驱动 ...
- Launcher启动流程加载流程学习
声明: 图片本来是有的 涉及到有些代码不能示人没有贴上,不过仅文字说也足够了,请广大老爷们自行下载源码参看流程分析阅读. 目录 一.认识Launcher: 1 1.功能 1 2.样式 2 3.And ...
- Pinpoint Agent加载流程分析
pinpoint 版本:2.0.3-SNAPSHOT pinpoint利用java agent 特性,提供了一个agent jar包,此jar包会在应用运行之前先运行,agent和应用在同一个进程.p ...
- 打卡学习Gradle深度解析 - kts脚本加载流程
kts脚本加载流程 和groovy脚本一样,kts脚本也分为2个阶段 stage 1 执行buildscript和plugins部分,执行结果会对stage2 program的classpath有影响 ...
- QT程序启动加载流程简介
1. QT应用程序启动加载流程简介 1.1 QWS与QPA启动客户端程序区别 1.1.1 QWS(Qt Window System)介绍 QWS(Qt Windows System)是Q ...
- AngularJS 初始化加载流程
一.AngularJS 初始化加载流程 1.浏览器载入HTML,然后把它解析成DOM. 2.浏览器载入angular.js脚本. 3.AngularJS等到DOMContentLoaded事件触发. ...
最新文章
- 集成学习之Bagging
- vim文本编辑器使用技巧
- java对象的强引用,软引用,弱引用和虚引用
- Python语言的有限状态机实现样例
- React Native之函数作为参数传递给另外一个函数去调用
- 344. 反转字符串 golang
- tensorflow eager 模式下打印dataset中的数据
- kong 网关教程入门
- win10 查看系统开机历史记录
- instantclient 配置 链接oracle,PLSQL与InstantClient的配置
- 前端html5 css3 教案,Web前端开发任务驱动式教程(HTML5+CSS3+JavaScript)
- 登顶多国免费榜,Zynga能否依靠超休闲游戏重回巨头行列
- usb-OTG-ADP-HNP-SRP
- 一图看尽APP各推广渠道“超级用户浓度”| 互联网行业公会
- 基于Springboot中小餐厅点餐管理系统设计
- C++ 实用趣味小程序
- 那些年, 你读错过的IT名词
- 远场(far-field)语音识别的主流技术有哪些
- WSL2设置局域网网访问
- 【JavaScript】移动端扫描二维码检测浏览器(微信、支付宝、Safari、其他浏览器)
热门文章
- Python pandas导excel数据量太大报错问题
- 用c语言输出一个月的月历
- 单目vo中的深度确定方法--三角测量
- Guitar Pro8吉他软件主要功能详解及安装教程
- python 字符串和十六进制的相互转化
- 修复Premiere Pro 2022 V22.5 意外退出 fix Premier Pro quit unexpectedly
- python制作快递查询小软件
- eis电子防抖好还是光学防抖好_【玩码】OPPO Reno2 搭载超级视频防抖技术,视频拍摄稳得很...
- 使用阿里云优惠券轻松享受超强性能大数据型实例
- 华为数通笔记-ISIS高级特性