Telephony之subscription介绍

sim卡初始化流程

整体流程是在SIMRecords加载完所有的文件之后,通知IccCardProxy把sim卡相关的信息更新到数据库(telephony.db)中,并且完成slotid、subid、phoneid的映射。

telephony.db data/user_de/0/com.android.providers.telephony/databases

SubscriptionInfoUpdater

初始化

@PhoneFactory.java
sSubInfoRecordUpdater = telephonyComponentFactory.makeSubscriptionInfoUpdater(
        BackgroundThread.get().getLooper(), context, sPhones, sCommandsInterfaces);
public SubscriptionInfoUpdater(
        Looper looper, Context context, Phone[] phone, CommandsInterface[] ci) {
    super(looper);
    ...
    IntentFilter intentFilter = new IntentFilter(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
    intentFilter.addAction(IccCardProxy.ACTION_INTERNAL_SIM_STATE_CHANGED);
    mContext.registerReceiver(sReceiver, intentFilter);
}

添加到数据库

如果手机插入了两张卡,会等两张卡都加载完之后,才回去添加到数据库。

@SubscriptionInfoUpdater.java
synchronized protected void updateSubscriptionInfoByIccId() {
    ...
    ContentResolver contentResolver = mContext.getContentResolver();
    String[] oldIccId = new String[PROJECT_SIM_NUM];
    for (int i = 0; i < PROJECT_SIM_NUM; i++) {
        oldIccId[i] = null;
        List<SubscriptionInfo> oldSubInfo =
                SubscriptionController.getInstance().getSubInfoUsingSlotIndexWithCheck(i, false,
                mContext.getOpPackageName());
        if (oldSubInfo != null && oldSubInfo.size() > 0) {
            oldIccId[i] = oldSubInfo.get(0).getIccId();
            logd("updateSubscriptionInfoByIccId: oldSubId = "
                    + oldSubInfo.get(0).getSubscriptionId());
            if (mInsertSimState[i] == SIM_NOT_CHANGE && !mIccId[i].equals(oldIccId[i])) {
                mInsertSimState[i] = SIM_CHANGED;
            }   
            if (mInsertSimState[i] != SIM_NOT_CHANGE) {
                ContentValues value = new ContentValues(1);
                value.put(SubscriptionManager.SIM_SLOT_INDEX,
                        SubscriptionManager.INVALID_SIM_SLOT_INDEX);
                contentResolver.update(SubscriptionManager.CONTENT_URI, value,
                        SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + "="
                        + Integer.toString(oldSubInfo.get(0).getSubscriptionId()), null);

                // refresh Cached Active Subscription Info List
                SubscriptionController.getInstance().refreshCachedActiveSubscriptionInfoList();
            }
        } else {
            if (mInsertSimState[i] == SIM_NOT_CHANGE) {
                // no SIM inserted last time, but there is one SIM inserted now
                mInsertSimState[i] = SIM_CHANGED;
            }
            oldIccId[i] = ICCID_STRING_FOR_NO_SIM;
            logd("updateSubscriptionInfoByIccId: No SIM in slot " + i + " last time");
        }
    }
    ...
    for (int i = 0; i < PROJECT_SIM_NUM; i++) {
        if (mInsertSimState[i] == SIM_NOT_INSERT) {
            logd("updateSubscriptionInfoByIccId: No SIM inserted in slot " + i + " this time");
        } else {
            if (mInsertSimState[i] > 0) {
                //some special SIMs may have the same IccIds, add suffix to distinguish them
                //FIXME: addSubInfoRecord can return an error.
                mSubscriptionManager.addSubscriptionInfoRecord(mIccId[i]
                        + Integer.toString(mInsertSimState[i]), i);
                logd("SUB" + (i + 1) + " has invalid IccId");
            } else /*if (sInsertSimState[i] != SIM_NOT_INSERT)*/ {
                mSubscriptionManager.addSubscriptionInfoRecord(mIccId[i], i);
            }
    }
}   

接下来看针对slot_id不存在的卡处理,这种情况发生在之前数据库中没有信息,或者有一条信息,这次插入了两张卡的情况。也就说下面三种情况会到这里来:

@SubscriptionController.java
public int addSubInfoRecord(String iccId, int slotIndex) {
    try {
        if (iccId == null) {
            if (DBG) logdl("[addSubInfoRecord]- null iccId");
            return -1;
        }

        ContentResolver resolver = mContext.getContentResolver();
        Cursor cursor = resolver.query(SubscriptionManager.CONTENT_URI,
                new String[]{SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID,
                        SubscriptionManager.SIM_SLOT_INDEX, SubscriptionManager.NAME_SOURCE},
                SubscriptionManager.ICC_ID + "=?", new String[]{iccId}, null);

        boolean setDisplayName = false;
        try {
            if (cursor == null || !cursor.moveToFirst()) {
                setDisplayName = true;
                Uri uri = insertEmptySubInfoRecord(iccId, slotIndex);
                if (DBG) logdl("[addSubInfoRecord] New record created: " + uri);
            } else {
                ContentValues value = new ContentValues();

                if (slotIndex != oldSimInfoId) {
                    value.put(SubscriptionManager.SIM_SLOT_INDEX, slotIndex);
                }
                if (nameSource != SubscriptionManager.NAME_SOURCE_USER_INPUT) {
                    setDisplayName = true;
                }
                if (value.size() > 0) {
                    resolver.update(SubscriptionManager.CONTENT_URI, value,
                            SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID +
                                    "=" + Long.toString(subId), null);
                    refreshCachedActiveSubscriptionInfoList();
                }
            }
        }
        sPhones[slotIndex].updateDataConnectionTracker();
}

接下来再返回到updateSubscriptionInfoByIccId,把手机号码加入到数据库,设置默认的数据卡。最后通知注册监听的客户端,并且发送广播ACTION_SUBINFO_CONTENT_CHANGE

SubscriptionController.getInstance().notifySubscriptionInfoChanged();

继续更新

再次回到handleSimLoaded方法中,接着进行处理。

总结

这篇主要介绍了SIMRecords中加载完sim卡信息之后,把信息更新到数据库的过程。主要涉及到SubscriptionInfoUpdater、SubscriptionController、SubscriptionManager。