资讯专栏INFORMATION COLUMN

ADN加载流程

A Loity / 2802人阅读

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

ADN加载流程:

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

  

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]

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

转载请注明本文地址: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元查看
<