天天看點

【Android架構Telephony篇】Subscription和SubscriptionManager

【Android架構Telephony篇】Subscription和SubscriptionManager

一台裝置可以有多張SIM卡,最典型的例子就是眼下流行的“雙卡雙待”。每一張SIM卡都對應一個Subscription,找不到對應的中文術語,我們求助下翻譯軟體。

Subscription:谷歌翻譯為“訂閱”,依舊不明覺厲;繼續翻譯:

訂閱(Subscription):定義了請求者與業務或業務操作之間的關聯關系。隻有定義了訂閱關系,才能通過業務政策,控制請求者對某個業務的通路行為。

我們用誰家的SIM卡就相當于訂閱(Subscription)誰家的業務,對應的SIM卡的資訊就是Subscription Information,比如營運商名稱、MNC、MCC等,多張SIM卡就有多個Subscription Information。

在Android中,針對上述功能的實作、管理就是SubscriptionManager,表現到軟體上就是:

【Android架構Telephony篇】Subscription和SubscriptionManager

各個類的實作比較簡單自行參看源碼。

SubscriptionManager作用有三個:

  • 擷取Subscription資訊
  • 更改Subscription某些資訊
  • 提供OnSubscriptionsChangedListener監聽器,友善其他應用監聽Subscription的狀态改變

是時候看下Subscription了。

Subscription内容:

public class SubscriptionInfo implements Parcelable {
    /**
     * Subscription Identifier, this is a device unique number
     * and not an index into an array
     */
    private int mId;

    /**
     * The GID for a SIM that maybe associated with this subscription, empty if unknown
     */
    private String mIccId;

    /**
     * The index of the slot that currently contains the subscription
     * and not necessarily unique and maybe INVALID_SLOT_ID if unknown
     */
    private int mSimSlotIndex;

    /**
     * The name displayed to the user that identifies this subscription
     */
    private CharSequence mDisplayName;

    /**
     * String that identifies SPN/PLMN
     * TODO : Add a new field that identifies only SPN for a sim
     */
    private CharSequence mCarrierName;

    /**
     * The source of the name, NAME_SOURCE_UNDEFINED, NAME_SOURCE_DEFAULT_SOURCE,
     * NAME_SOURCE_SIM_SOURCE or NAME_SOURCE_USER_INPUT.
     */
    private int mNameSource;

    /**
     * A number presented to the user identify this subscription
     */
    private String mNumber;

    /**
     * Data roaming state, DATA_RAOMING_ENABLE, DATA_RAOMING_DISABLE
     */
    private int mDataRoaming;

    /**
     * Mobile Country Code
     */
    private int mMcc;

    /**
     * Mobile Network Code
     */
    private int mMnc;

    /**
     * ISO Country code for the subscription's provider
     */
    private String mCountryIso;
}
           

一條Log:

SubscriptionController: [getSubInfoRecord] id:2 iccid:898600020XXXXXXXXXXX simSlotIndex:0 displayName:中國移動 carrierName:No service. nameSource:0 iconTint:-16746133 dataRoaming:0 mcc:460 mnc:2 countIso:cn
           

看下對應的術語:

ICCID:Integrate circuit card identity 內建電路卡識别碼(固化在手機SIM卡中)。ICCID為IC卡的唯一識别号碼,共有20位數字組成:

【Android架構Telephony篇】Subscription和SubscriptionManager

PLMN:Public Land Mobile Network 公共陸地移動網,一般某個國家的一個營運商對應一個PLMN

SPN:Service Provider Name 營運商名稱

MCC:Mobile Country Code,移動國家碼,MCC的資源由國際電聯(ITU)統一配置設定和管理,唯一識别移動使用者所屬的國家,共3位,中國為460

MNC:Mobile Network Code 移動網絡号碼,用于識别移動使用者所歸屬的移動通信網,2~3位數字組成,如中國移動系統使用00、02、04、07,中國聯通GSM系統使用01、06、09

ISO country code: 國際上不同國家的ISO編碼,比如我們國家:

【Android架構Telephony篇】Subscription和SubscriptionManager

那麼問題來了,這些資訊從哪來?

對于SubscriptionController來說,它是從資料庫telephony.db的siminfo表中讀取:

/data/data/com.android.providers.telephony/databases

【Android架構Telephony篇】Subscription和SubscriptionManager

siminfo表的建立:

TelephonyProvider.java (g:\rk3288-android6.0f\packages\providers\telephonyprovider\src\com\android\providers\telephony)	105530	2017-04-24
private void createSimInfoTable(SQLiteDatabase db) {
	db.execSQL("CREATE TABLE " + SIMINFO_TABLE + "("
			+ SubscriptionManager.UNIQUE_KEY_SUBSCRIPTION_ID + " INTEGER PRIMARY KEY AUTOINCREMENT,"
			+ SubscriptionManager.ICC_ID + " TEXT NOT NULL,"
			+ SubscriptionManager.SIM_SLOT_INDEX + " INTEGER DEFAULT " + SubscriptionManager.SIM_NOT_INSERTED + ","
			+ SubscriptionManager.DISPLAY_NAME + " TEXT,"
			+ SubscriptionManager.CARRIER_NAME + " TEXT,"
			+ SubscriptionManager.NAME_SOURCE + " INTEGER DEFAULT " + SubscriptionManager.NAME_SOURCE_DEFAULT_SOURCE + ","
			+ SubscriptionManager.COLOR + " INTEGER DEFAULT " + SubscriptionManager.COLOR_DEFAULT + ","
			+ SubscriptionManager.NUMBER + " TEXT,"
			+ SubscriptionManager.DISPLAY_NUMBER_FORMAT + " INTEGER NOT NULL DEFAULT " + SubscriptionManager.DISPLAY_NUMBER_DEFAULT + ","
			+ SubscriptionManager.DATA_ROAMING + " INTEGER DEFAULT " + SubscriptionManager.DATA_ROAMING_DEFAULT + ","
			+ SubscriptionManager.MCC + " INTEGER DEFAULT 0,"
			+ SubscriptionManager.MNC + " INTEGER DEFAULT 0,"
			+ SubscriptionManager.CB_EXTREME_THREAT_ALERT + " INTEGER DEFAULT 1,"
			+ SubscriptionManager.CB_SEVERE_THREAT_ALERT + " INTEGER DEFAULT 1,"
			+ SubscriptionManager.CB_AMBER_ALERT + " INTEGER DEFAULT 1,"
			+ SubscriptionManager.CB_EMERGENCY_ALERT + " INTEGER DEFAULT 1,"
			+ SubscriptionManager.CB_ALERT_SOUND_DURATION + " INTEGER DEFAULT 4,"
			+ SubscriptionManager.CB_ALERT_REMINDER_INTERVAL + " INTEGER DEFAULT 0,"
			+ SubscriptionManager.CB_ALERT_VIBRATE + " INTEGER DEFAULT 1,"
			+ SubscriptionManager.CB_ALERT_SPEECH + " INTEGER DEFAULT 1,"
			+ SubscriptionManager.CB_ETWS_TEST_ALERT + " INTEGER DEFAULT 0,"
			+ SubscriptionManager.CB_CHANNEL_50_ALERT + " INTEGER DEFAULT 1,"
			+ SubscriptionManager.CB_CMAS_TEST_ALERT + " INTEGER DEFAULT 0,"
			+ SubscriptionManager.CB_OPT_OUT_DIALOG + " INTEGER DEFAULT 1"
			+ ");");
	if (DBG) log("dbh.createSimInfoTable:-");
}
           

那麼又要問了,資料庫的資料從哪來?自然從SIM中讀取的了。

怎麼讀?通過AT指令讀!

怎麼通過AT指令讀?說過了。

繼續閱讀