SubscriptionManager(sim卡的一些必要信息。)

来源:互联网 发布:php上传图片到数据库 编辑:程序博客网 时间:2024/05/20 12:24

SubscriptionManager

Subscription可以理解为卡上的一个信息单元,里面包含了卡的一些必要信息。

SubscriptionDataSubscription的一个集合。

SubscriptionManager总体上是一个Handler,主要以消息驱动。


维护几个信息:

1.用户指定的Subscription

         2.当前激活的Subscription

         3.准备好的Subscription ,依赖于卡状态的主动上报

         4.当前的数据Subscription

         5.设置Subscription模式?

 

提供两个功能:

1.       激活或去激活Subscription

2.       设置数据Subscription

3.       Modem修改了卡状态以后会同步做出反应

 

内部类:

1.       SetUiccSubsParams 设定两个值:subIdSubscriptionStatus

2.       PhoneSubscriptionInfo 维护SubscriptionManager中管理的Subscription信息

 

/**

     * Subscription Id

     */

    private enum SubscriptionId {

        SUB1,

        SUB2

}

这里固定了subId的叫法,与习惯不一样。

 

SubscriptionManager使用单例模式,但是使用getInstance()有可能得到null

 

在构造SubscriptionManager的时候,会先调用getUserPreferredSubs()来把存在数据库里的卡的Subscription信息还原回mUserPrefSubs(一个SubscriptionData),如果没有就设定无效的值进去,且保存回数据库。


实例化一个CardSubscriptionManager对象,向这个对象注册三个事件:

registerForCardInfoAvailable——EVENT_CARD_INFO_AVAILABLE

registerForCardInfoUnavailable——EVENT_CARD_INFO_NOT_AVAILABLE

registerForAllCardsInfoAvailable——EVENT_ALL_CARD_INFO_AVAILABLE

 

向每一个Ril实例,注册三个事件:

registerForSubscriptionStatusChanged——EVENT_SUBSCRIPTION_STATUS_CHANGED

registerForOffOrNotAvailable——EVENT_RADIO_OFF_OR_NOT_AVAILABLE

registerForOn——EVENT_RADIO_ON

 

实例化两个激活/去激活注册器列表:

mSubDeactivatedRegistrants

mSubActivatedRegistrants

 

实例化两个激活/去激活队列:

mActivatePending

mDeactivatePending

 

MSimPhoneFactory.getDataSubscription()获取当前数据通道使用的是哪一个Subscription

 

实例化mCurrentSubscriptions队列

 

private void updateSubPreferences() { int activeSubCount = 0; Subscription activeSub = null; for (SubscriptionId sub: SubscriptionId.values()) { 看有几个激活的sub if (getCurrentSubscriptionStatus(sub) == SubscriptionStatus.SUB_ACTIVATED) { activeSubCount++; activeSub = getCurrentSubscription(sub); } } // If there is only one active subscription, set user preferred settings // for voice/sms/data subscription to this subscription. 只有一个卡激活 if (activeSubCount == 1) { if (MSimPhoneFactory.getDefaultSubscription() != activeSub.subId) { 设置这个卡为voice/sms/data的默认 MSimPhoneFactory.setDefaultSubscription(activeSub.subId); } 如果当前的数据通道不是这张激活的卡,设置这张卡为默认数据通道。 if (mCurrentDds != activeSub.subId) { Log.i(LOG_TAG,"mCurrentDds != activeSub.subId "); Log.i(LOG_TAG,"activeSub = "+activeSub); // Currently selected DDS subscription is not in activated state. // So set the DDS to the only active subscription available now. // Directly set the Data Subscription Source to the only activeSub if it // is READY. If the SUBSCRIPTION_READY event is not yet received on this // subscription, wait for the event to set the Data Subscription Source. SubscriptionId subId = SubscriptionId.values()[activeSub.subId]; 这张卡的状态要ready if (getCurrentSubscriptionReadiness(subId)) { mQueuedDds = activeSub.subId; Message callback = Message.obtain(this, EVENT_SET_DATA_SUBSCRIPTION_DONE, Integer.toString(activeSub.subId)); logd("update setDataSubscription to " + activeSub.subId); mCi[activeSub.subId].setDataSubscription(callback); mSetDdsRequired = false; } else { 如果不ready,就置一个标志位,等ready了再设置,在别的函数里 Log.i(LOG_TAG,"mQueuedDds = activeSub.subId"); // Set the flag and update the mCurrentDds, so that when subscription // ready event receives, it will set the dds properly. mSetDdsRequired = true; mCurrentDds = activeSub.subId; //MSimPhoneFactory.setDataSubscription(mCurrentDds); } } }else if (activeSubCount > 1){ 两张卡都激活了 int preferredDataSub = MSimPhoneFactory.getUserPreferredDDS(); 如果现在的数据通道不是用户选择的那个,处理方式同上 if (mCurrentDds != preferredDataSub){ logd("current dds is "+mCurrentDds+",preferred one is "+preferredDataSub); if (getCurrentSubscriptionReadiness(SubscriptionId.values()[preferredDataSub])){ mQueuedDds = preferredDataSub; Message callback = Message.obtain(this,EVENT_SET_DATA_SUBSCRIPTION_DONE, Integer.toString(preferredDataSub)); logd("update dds to "+preferredDataSub); mCi[preferredDataSub].setDataSubscription(callback); }else{ logd("updata dds later"); mSetDdsRequired = true; mCurrentDds = preferredDataSub; } } }}


/** * Start one deactivate from the pending deactivate request queue. * If the deactivate is required for the DDS SUB, then initiate * clean up the data connection and deactivate later. * @return true if deactivate is started. */ private boolean startNextPendingDeactivateRequests() { printPendingDeactivateRequests(); 遍历两张卡,对每张卡上的去激活请求进行处理 for (SubscriptionId sub: SubscriptionId.values()) { Subscription newSub = mDeactivatePending.get(sub); if (newSub != null && newSub.subStatus == SubscriptionStatus.SUB_DEACTIVATE) { if (!validateDeactivationRequest(newSub)) { // Not a valid entry. Clear the deactivate pending entry mDeactivatePending.put(sub, null); continue; } logd("startNextPendingDeactivateRequests: Need to deactivating SUB : " + newSub); if (mCurrentDds == newSub.subId && mDataActive) { 如果是当前正在用的数据通道所在的sub,先关数据 // This is the DDS. // Tear down all the data calls on this subscription. Once the // clean up completed, the set uicc subscription request with // deactivate will be sent to deactivate this subscription. logd("Deactivate all the data calls if there is any"); Message allDataCleanedUpMsg = Message.obtain(this, EVENT_CLEANUP_DATA_CONNECTION_DONE, mCurrentDds); MSimProxyManager.getInstance().disableDataConnectivity(mCurrentDds, allDataCleanedUpMsg); mSetDdsRequired = true; } else { 如果不是就可以直接去激活,通过RIL的setUiccSubscription logd("startNextPendingDeactivateRequests: Deactivating now"); SetUiccSubsParams setSubParam = new SetUiccSubsParams(newSub.subId, newSub.subStatus); Message msgSetUiccSubDone = Message.obtain(this, EVENT_SET_UICC_SUBSCRIPTION_DONE, setSubParam); mCi[newSub.subId].setUiccSubscription(newSub.slotId, newSub.getAppIndex(), newSub.subId, newSub.subStatus.ordinal(), msgSetUiccSubDone); } // process one request at a time!! return true; } } return false;}


/** * Start one activate request from the pending activate request queue. * @return true if activate request is started. */ private boolean startNextPendingActivateRequests() { printPendingActivateRequests(); 遍历两张卡,对每张卡上的激活请求进行处理 for (SubscriptionId sub: SubscriptionId.values()) { Subscription newSub = mActivatePending.get(sub); if (newSub != null && newSub.subStatus == SubscriptionStatus.SUB_ACTIVATE) { if (!validateActivationRequest(newSub)) { // Not a valid entry. Clear the pending activate request list mActivatePending.put(sub, null); continue; } // We need to update the phone object for the new subscription. MSimProxyManager.getInstance().checkAndUpdatePhoneObject(newSub); logd("startNextPendingActivateRequests: Activating SUB : " + newSub); SetUiccSubsParams setSubParam = new SetUiccSubsParams(newSub.subId, newSub.subStatus); Message msgSetUiccSubDone = Message.obtain(this, EVENT_SET_UICC_SUBSCRIPTION_DONE, setSubParam); mCi[newSub.subId].setUiccSubscription(newSub.slotId, newSub.getAppIndex(), newSub.subId, newSub.subStatus.ordinal(), msgSetUiccSubDone); // process one request at a time!! return true; } } return false; }


/** * Set Uicc Subscriptions * Algorithm: * 1. Process the set subscription request if not in progress, return false if * already in progress. * 2. Read each requested SUB * 3. If user selected a different app for a SUB and previous status of SUB is * ACTIVATED, then need to deactivate it. * Add to the pending Deactivate request Queue. * 4. If user selected an app for SUB to ACTIVATE * Add to the pending Activate request Queue. * 5. Start deactivate requests * 6. If no deactivate requests, start activate requests. * In case of deactivate requests started, the pending activate requests with * be processed after finishing the deactivate. * 7. If any set uicc subscription started, return true. * * @param subData - Contains the required SUB1 and SUB2 subscription information. * To activate a SUB, set the subStatus to ACTIVATE * To deactivate, set the subStatus to DEACTIVATE * To keep the subscription with out any change, set the sub to current sub. * @return true if the requested set subscriptions are started. * false if there is no request to update the subscriptions * or if already a set subscription is in progress. */ 如果有去激活的请求先执行去激活的操作,再执行激活的操作 public boolean setSubscription(SubscriptionData subData) { boolean ret = false; // Return failure if the set uicc subscription is already in progress. // Ideally the setSubscription should not be called when there is a // activate/deactivate in undergoing. Whoever calling should aware of // set subscription status. if (mSetSubscriptionInProgress) { 如果正在执行激活/去激活操作,直接返回false return false; } mSubResult[0] = SUB_NOT_CHANGED; mSubResult[1] = SUB_NOT_CHANGED; // Check what are the user preferred subscriptions. for (SubscriptionId subId: SubscriptionId.values()) { // If previous subscription is not same as the requested subscription // (ie., the user must have marked this subscription as deactivate or // selected a new sim app for this subscription), then deactivate the // previous subscription. 如果当前的Subscription和参数给的不一样,且当前的是激活态,就把当前的这个去激活 if (!getCurrentSubscription(subId).equals(subData.subscription[subId.ordinal()])) { if (getCurrentSubscriptionStatus(subId) == SubscriptionStatus.SUB_ACTIVATED) { logd("Need to deactivate current SUB :" + subId); Subscription newSub = new Subscription(); newSub.copyFrom(getCurrentSubscription(subId)); newSub.subStatus = SubscriptionStatus.SUB_DEACTIVATE; mDeactivatePending.put(subId, newSub); } else if (getCurrentSubscriptionStatus(subId) == SubscriptionStatus.SUB_DEACTIVATED && subData.subscription[subId.ordinal()].subStatus == SubscriptionStatus.SUB_DEACTIVATE) { // This subscription is already in deactivated state! } } 如果参数里有要激活的,就放到激活队列里 if (subData.subscription[subId.ordinal()].subStatus == SubscriptionStatus.SUB_ACTIVATE) { logd("Need to activate new SUB : " + subId); Subscription newSub = new Subscription(); newSub.copyFrom(subData.subscription[subId.ordinal()]); mActivatePending.put(subId, newSub); } } 先执行去激活,再激活 // Start the set uicc subscription only if if (!mSetSubscriptionInProgress) { boolean deactivateInProgress = startNextPendingDeactivateRequests(); if (deactivateInProgress) { mSetSubscriptionInProgress = true; } else { processActivateRequests(); } } if (mSetSubscriptionInProgress) { // No set uicc request to process. ret = true; } return ret;}


/** * Sets the designated data subscription source(DDS). * @param subscription * @param onCompleteMsg */ 设置数据通道,这个是逻辑上设置,最后还要通过MsimPhoneFactory的setDataSubscription去把设置的值写到数据库里去。 public void setDataSubscription(int subscription, Message onCompleteMsg) { logd("setDataSubscription: mCurrentDds = " + mCurrentDds + " new subscription = " + subscription); if (!getCurrentSubscriptionReadiness(SubscriptionId.values()[subscription])) { loge("setDataSubscription: requested SUB:" + subscription + " is not yet activated, returning failure"); if(onCompleteMsg != null){ AsyncResult.forMessage(onCompleteMsg, false, new RuntimeException("Subscription not active")); onCompleteMsg.sendToTarget(); } return; } mSetDdsCompleteMsg = onCompleteMsg; // If there is no set dds in progress disable the current // active dds. Once all data connections is teared down, the data // connections on mQueuedDds will be enabled. // Call the MSimPhoneFactory setDataSubscription API only after disconnecting // the current dds. 要先断开当前的数据连接,然后通过RIL的setDataSubscription去设置数据通道 mQueuedDds = subscription; if (!mDisableDdsInProgress) { Message allDataDisabledMsg = obtainMessage(EVENT_DISABLE_DATA_CONNECTION_DONE); MSimProxyManager.getInstance().disableDataConnectivity(mCurrentDds, allDataDisabledMsg); mDisableDdsInProgress = true; }}

0 0
原创粉丝点击