Android O
SubId,即SIM卡id,此id为数据库中的"_id"字段,从1开始。
每当我们向手机插入一张SIM卡,此卡的相关记录就会被保存到数据库,而其记录的"_id"字段则被用作SubId。
若SIM卡之前已插入过手机,则再次插入时就会直接从数据库中去读取原来的SubId。
DummySubId:当无卡或卡未加载完成时,我们无法获得真正的SubId,只能得到一个Dummy值,为"-2 - SlotId"。
SubId的添加:
当SIM LOADED后,会发送android.intent.action.internal_sim_state_changed的广播,
SubscriptionInfoUpdater.sReceiver会收到并进行处理。
private final BroadcastReceiver sReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
......
logd("Action: " + action);
......
} else if (IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(simStatus)) {
sendMessage(obtainMessage(EVENT_SIM_LOADED, slotIndex, -1));
} else {
......
}
public void handleMessage(Message msg) {
......
case EVENT_SIM_LOADED:
handleSimLoaded(msg.arg1);
break;
......
}
protected void handleSimLoaded(int slotId) {
logd("handleSimLoaded: slotId: " + slotId);
......
if (isAllIccIdQueryDone()) {
updateSubscriptionInfoByIccId();
......
}
synchronized private void updateSubscriptionInfoByIccId() {
logd("updateSubscriptionInfoByIccId:+ Start");
......
// We only clear the slot-to-sub map when one/some SIM was removed. Note this is a
// workaround for some race conditions that the empty map was accessed while we are
// rebuilding the map.
if (SubscriptionController.getInstance().getActiveSubIdList().length > insertedSimCount) {
SubscriptionController.getInstance().clearSubInfo();
}
......
//check if the inserted SIM is new SIM
int nNewCardCount = 0;
int nNewSimStatus = 0;
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);
}
......
......
}
SubscriptionManager.java
public Uri addSubscriptionInfoRecord(String iccId, int slotIndex) {
......
ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
if (iSub != null) {
// FIXME: This returns 1 on success, 0 on error should should we return it?
iSub.addSubInfoRecord(iccId, slotIndex);
......
}
SubscriptionController.java
public int addSubInfoRecord(String iccId, int slotIndex) {
if (DBG) logdl("[addSubInfoRecord]+ iccId:" + SubscriptionInfo.givePrintableIccid(iccId) +
" slotIndex:" + slotIndex);
......
// 根据iccId从数据库读取SIM卡信息
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()) {
// 此SIM卡之前未插入过,然后我们就会先插入一条新的空记录
setDisplayName = true;
Uri uri = insertEmptySubInfoRecord(iccId, slotIndex);
if (DBG) logdl("[addSubInfoRecord] New record created: " + uri);
} else {
// 此SIM卡之前插入过,就直接读取其SubId
int subId = cursor.getInt(0);
......
if (value.size() > 0) {
resolver.update(SubscriptionManager.CONTENT_URI, value,
SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID +
"=" + Long.toString(subId), null);
// Refresh the Cache of Active Subscription Info List
refreshCachedActiveSubscriptionInfoList();
......
}
// 然后再将SubId加入sSlotIndexToSubId中
cursor = resolver.query(SubscriptionManager.CONTENT_URI, null,
SubscriptionManager.SIM_SLOT_INDEX + "=?",
new String[] {String.valueOf(slotIndex)}, null);
try {
......
sSlotIndexToSubId.put(slotIndex, subId);
......
}
......
}
public int clearSubInfo() {
......
sSlotIndexToSubId.clear();
......
}
SubId的删除:
流程类似,也会走到updateSubscriptionInfoByIccId(),然后clearSubInfo。