ADN加载流程:
IccProvider.java
IccProvider定义在/packages/services/Telephony/AndroidManifest.xml
<provider android:name="IccProvider"
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<AdnRecord> 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<AdnRecord> 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<AdnRecord> 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<AdnRecord>) 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]