Android5.0開始支持雙卡了。另外贱呐,對(duì)于雙卡的卡信息的管理丧诺,也有了實(shí)現(xiàn),盡管還不是完全徹底完整奄薇,如卡的slot id驳阎,display name,iccid惕艳,color等搞隐,其設(shè)計(jì)思路竟然跟之前接觸到的一個(gè)平臺(tái)是一樣的,都是同不同顏色來(lái)標(biāo)識(shí)不同的卡远搪,讓用戶一目了然劣纲,只是5.0的實(shí)現(xiàn)目前還局限在FW框架里,應(yīng)用層的實(shí)現(xiàn)還沒(méi)有谁鳍,相信癞季,等到5.1或者再之后的版本中,我們就可以在setting里看到對(duì)卡表示顏色倘潜、名稱等進(jìn)行設(shè)置的功能菜單啦绷柒。
下面進(jìn)入正題,來(lái)分析Android5.0的雙卡信息是如何來(lái)維護(hù)的:
1卡信息的存儲(chǔ)
先說(shuō)結(jié)論涮因,5.0是將所有卡信息通過(guò)數(shù)據(jù)庫(kù)進(jìn)行保存的废睦。數(shù)據(jù)庫(kù)表URL:content://telephony/siminfo,對(duì)應(yīng)到的數(shù)據(jù)庫(kù)為telephony.db中的siminfo表养泡,代碼文件在TelephonyProvider.java嗜湃,在這里可以看到createTable的詳情,來(lái)看看這個(gè)表都包含哪些字段澜掩。
總共設(shè)計(jì)了11個(gè)字段购披,下面這張圖是從5.0模擬器上拉出來(lái)的telephony.db里截取到的,可以用來(lái)做示例:
表名:
表數(shù)據(jù)示例:
下面分別介紹一下這些字段的含義肩榕。
1.1 _id
這個(gè)自不必說(shuō)刚陡,android里的每個(gè)db都有的,是數(shù)據(jù)庫(kù)里的數(shù)據(jù)主key株汉,這里的_id值也是以后代碼里看到的subId筐乳,是在數(shù)據(jù)庫(kù)中保存時(shí)所在的條目的唯一標(biāo)識(shí)。有多少條數(shù)據(jù)郎逃,就說(shuō)明保存了多少個(gè)sim卡的信息哥童;
1.2 icc_id
從卡上讀取得到,是卡的唯一身份標(biāo)識(shí)褒翰,世界上的所有sim卡贮懈,每個(gè)卡都有不同的iccid匀泊,就像身份證一樣;如上面圖中的16進(jìn)制串89014103211118510720朵你;
1.3 sim_id
分配給卡的id序號(hào)各聘,android設(shè)計(jì)從0開始,最大為卡槽個(gè)數(shù)抡医,比如如果是雙卡終端躲因,那么只有可能是0或者1;當(dāng)然無(wú)卡時(shí)其值為-1忌傻,所以這里其實(shí)是與卡槽固定對(duì)應(yīng)的大脉,卡槽如果有卡就取對(duì)應(yīng)id,如果無(wú)卡水孩,就設(shè)為-1镰矿;
1.4 display_name
分配給卡的顯示名字,從代碼上來(lái)看開機(jī)后會(huì)嘗試使用運(yùn)營(yíng)商名字俘种,如果取不到秤标,就使用簡(jiǎn)單的SUB 01這樣的字串表示,等拿到運(yùn)營(yíng)商名字之后重新set宙刘,另外從下面的name_source字段的設(shè)計(jì)來(lái)看苍姜,android是允許用戶來(lái)自己指定這個(gè)顯示名的;
1.5 name_source
表明display_name字段的來(lái)源悬包,有兩種來(lái)源衙猪,一是系統(tǒng)自動(dòng),name_source取值為0布近,另一種就是來(lái)自用戶指定屈嗤,取值為1;
1/**
2 *The name_source is the default
3 *@hide
4 */
5publicstaticfinalint NAME_SOURCE_DEFAULT_SOURCE =0;
6
7/**
8 *The name_source is from the SIM
9 *@hide
10 */
11 publicstaticfinalintNAME_SOURCE_SIM_SOURCE =1;
12
13 /**
14 * The name_source is from the user
15 * @hide
16 */
17 publicstaticfinalintNAME_SOURCE_USER_INPUT =2;
1.6 color
顯示顏色吊输,將使用顏色在UI上明顯區(qū)分卡1和卡2;android設(shè)定每個(gè)卡都只能從固定的幾個(gè)顏色中取铁追,如下:
1/** @hide */
2publicstaticfinal String COLOR ="color";
3
4/** @hide */
5publicstaticfinalint COLOR_1 =0;
6
7/** @hide */
8publicstaticfinalint COLOR_2 =1;
9
10 /** @hide */
11 publicstaticfinalint COLOR_3 =2;
12
13 /** @hide */
14 publicstaticfinalint COLOR_4 =3;
15
16 /** @hide */
17 publicstaticfinalint COLOR_DEFAULT =COLOR_1;
這四種顏色根據(jù)主題是dark還是light分別對(duì)應(yīng)4種顏色季蚂,這些顏色其實(shí)并非是色值,而是固定顏色的背景9.png圖片琅束,都定義在資源drawable里扭屁,看來(lái)是用來(lái)做backgroud用的。如
sim_dark_bluesim_light_purple
其他幾種顏色可以參考SubscriptionController. setSimResource函數(shù)里去color資源數(shù)組的初始化涩禀。
1.7 number
該卡對(duì)應(yīng)的號(hào)碼料滥,phone number。//TODO:研究一下這個(gè)是怎么獲取到呢艾船?
1.8 display_number_format
標(biāo)識(shí)number字段的格式葵腹,總共有固定的3種高每,取其一。
/** @hide */
publicstaticfinalint DISPLAY_NUMBER_NONE=0;
/** @hide */
publicstaticfinalint DISPLAY_NUMBER_FIRST=1;
/** @hide */
publicstaticfinalint DISPLAY_NUMBER_LAST=2;
/** @hide */
publicstaticfinalint DISLPAY_NUMBER_DEFAULT= DISPLAY_NUMBER_FIRST;
從SubscriptionController. setDisplayNumberFormat()函數(shù)的注釋可以看出點(diǎn)門道践宴,
*Set number display format. 0: none, 1:?the first four digits,2:?the last four digits
但搜了一下鲸匿,對(duì)應(yīng)的setDisplayNumber()函數(shù)并沒(méi)有跟這個(gè)format有關(guān)聯(lián),直接保存?zhèn)魅氲膎umber到數(shù)據(jù)庫(kù)了阻肩。所以還不太清楚the first four digits和the last four digits的具體含義带欢,等以后android應(yīng)用層完善后應(yīng)該能看到具體的使用方式。
1.9 data_roaming
是否允許這張卡進(jìn)行數(shù)據(jù)漫游烤惊,默認(rèn)禁止漫游乔煞。
1 /** @hide */
2 publicstaticfinalint DATA_ROAMING_ENABLE=1;
3
4 /** @hide */
5 publicstaticfinalint DATA_ROAMING_DISABLE=0;
6
7 /** @hide */
8 publicstaticfinalint DATA_ROAMING_DEFAULT= DATA_ROAMING_DISABLE;
1.10 mcc
移動(dòng)國(guó)家碼,從卡上讀取得到柒室,卡的mcc碼渡贾;
1.11 mnc
移動(dòng)網(wǎng)絡(luò)碼,從卡上讀取得到伦泥,卡的mnc碼剥啤。度娘到對(duì)于mcc和mnc的解釋:
MCC是Mobile Country Code的縮寫,譯為移動(dòng)國(guó)家代碼不脯。它由三位數(shù)字組成府怯。用于標(biāo)識(shí)一個(gè)國(guó)家,但一個(gè)國(guó)家可以被分配多個(gè)MCC防楷。比如美國(guó)的MCC有310牺丙,311,和316复局。中國(guó)的MCC只有460冲簿。MNC是Mobile Network Code的縮寫,譯為移動(dòng)網(wǎng)絡(luò)代碼亿昏。它由二到三位數(shù)字組成峦剔。MNC和MCC合在一起唯一標(biāo)識(shí)一個(gè)移動(dòng)網(wǎng)絡(luò)提供者。比如中國(guó)移動(dòng)的MNC是00角钩,中國(guó)聯(lián)通的MNC是01吝沫,中國(guó)聯(lián)通CDMA的MNC是03,中國(guó)衛(wèi)星全球星網(wǎng)的MNC是04递礼。因此惨险,460 00就唯一標(biāo)識(shí)了中國(guó)移動(dòng)。
所以卡的displayname應(yīng)該也是通過(guò)mcc+mnc得到的脊髓。
2主要工作類
上面介紹了卡信息的數(shù)據(jù)設(shè)計(jì)辫愉,接下來(lái)看看有哪些類圍繞著這些數(shù)據(jù)來(lái)對(duì)外提供接口和功能。
類
功能介紹
TelephonyProvider
siminfo數(shù)據(jù)庫(kù)provider将硝,直接操作DB恭朗,實(shí)現(xiàn)siminfo表的增刪改查屏镊。
SubscriptionController
實(shí)現(xiàn)為遠(yuǎn)程service,在phone初始化時(shí)被創(chuàng)建冀墨,作為數(shù)據(jù)庫(kù)的對(duì)外接口提供功能闸衫,其內(nèi)部維護(hù)從數(shù)據(jù)庫(kù)讀取到的siminfo list,并實(shí)現(xiàn)了大量的如getSubId
getDisplayName setDisplayName等getter和setter方法诽嘉,這些方法維護(hù)siminfo
list以及通過(guò)URL訪問(wèn)數(shù)據(jù)庫(kù)來(lái)實(shí)現(xiàn)功能蔚出。
SubscriptionManager
該類所有的內(nèi)部接口都實(shí)現(xiàn)為了static,也就是該類是一個(gè)純粹提供接口的靜態(tài)類虫腋,其內(nèi)部并不實(shí)現(xiàn)具體的邏輯骄酗,只是通過(guò)調(diào)用SubscriptionController這個(gè)service的對(duì)應(yīng)接口來(lái)完成工作,所以該類是一個(gè)對(duì)外接口的封裝悦冀,APP可以直接通過(guò)SubscriptionManager.getSubId等來(lái)實(shí)現(xiàn)功能趋翻,不需要直接操作service。目前還是Hide的盒蟆,估計(jì)以后會(huì)開放給SDK踏烙。這種設(shè)計(jì)模式,android FW層用的很多历等,如SmsMnager讨惩、TelephonyManager等。
SubInfoRecordUpdater
卡信息變化的監(jiān)聽者和更新者寒屯,其在PhoneFactory中創(chuàng)建完phones之后被創(chuàng)建荐捻,起來(lái)之后會(huì)注冊(cè)對(duì)ACTION_SIM_STATE_CHANGED的監(jiān)聽,收到監(jiān)聽之后更新對(duì)應(yīng)siminfo的信息寡夹,如iccid处面、displayname(運(yùn)營(yíng)商名)、phonenumber菩掏。并且在自己內(nèi)部維護(hù)了每個(gè)卡的卡狀態(tài)魂角,這里的卡狀態(tài)區(qū)別與ACTION_SIM_STATE_CHANGED所攜帶的卡狀態(tài),ACTION_SIM_STATE_CHANGED的卡狀態(tài)有LOCKED智绸、READY或颊、NOT READY、ABSENT等传于,是指的卡的具體狀態(tài),而這里的卡狀態(tài)是指有沒(méi)有插卡醉顽、該卡槽的卡是不是變過(guò)了(換了一張卡)沼溜、卡槽的卡是一張沒(méi)見過(guò)的新卡、卡槽的卡是位置互換啦游添、卡槽的卡沒(méi)變化系草⊥ㄏǎ【狀態(tài)還真有點(diǎn)繞,管的挺多的啊找都。唇辨。∧艹埽】這些狀態(tài)是在收到ACTION_SIM_STATE_CHANGED之后赏枚,根據(jù)卡狀態(tài)以及卡的iccid等一些信息算出來(lái)的,如果發(fā)現(xiàn)有新卡插入會(huì)進(jìn)行廣播晓猛。
SubInfoRecord
subinfo的可序列化實(shí)現(xiàn)饿幅,封裝數(shù)據(jù)庫(kù)數(shù)據(jù)。
另外戒职,在代碼中還可以看到Subscription和SubscriptionData這兩個(gè)類栗恩,這兩個(gè)其實(shí)只是數(shù)據(jù)封裝,并不直接跟卡信息管理相關(guān)洪燥,其只是保存了一些卡的數(shù)據(jù)來(lái)提供給phone等使用磕秤,目前還找不到組織他們的接口,全局搜索會(huì)發(fā)現(xiàn)捧韵,好多地方google都注釋掉了市咆,邏輯還沒(méi)完整。SubscriptionData是Subscription list纫版,目前從代碼來(lái)看床绪,這兩個(gè)還沒(méi)有真正用起來(lái),所以可以先無(wú)視了其弊,不過(guò)要吐槽下google的代碼癞己,起名咋這么繞啊。另外還有個(gè)CdmaSubscriptionSourceManager的類梭伐,這個(gè)是跟CDMA的卡提供者信息有關(guān)的痹雅,會(huì)影響到具體的網(wǎng)絡(luò)行為,也跟本文的雙卡信息管理無(wú)關(guān)糊识。
3工作流程
通過(guò)上面主要類的介紹绩社,基本上整個(gè)雙卡信息管理的框架就出來(lái)了,畫了一個(gè)圖方便理解赂苗。
4總結(jié)
5.0通過(guò)DB來(lái)保存和維護(hù)雙卡信息愉耙,SubInfoRecordUpdater通過(guò)監(jiān)聽卡的變化動(dòng)態(tài)更新數(shù)據(jù)庫(kù)里的卡數(shù)據(jù);SubscriptionController和SubscriptionManager通過(guò)各種接口來(lái)向外提供卡信息的查詢和修改拌滋,這樣看來(lái)邏輯還是比較清晰明了的