クマは森で用を足しますか?

アウトプットは重要です。

Google Pixel 4 がデュアル SIM 端末になるとき

Google Pixel 4 は出荷時はシングル SIM 端末ですが、その後の UI 操作によってデュアル SIM 端末へ動的に変化します。Google Pixel 4 に IIJ さんの eSIM をダウンロードしてデュアル SIM 端末にしましたので、そのときに観測できたことをメモしておこうと思います。

f:id:cheerio-the-bear:20200613223945p:plain:w360f:id:cheerio-the-bear:20200613224033p:plain:w360
デュアル SIM 端末になる際のユーザー確認

1. シングル SIM 動作時の端末コンフィギュレーション

1-1. FEATURE

Google Pixel 4 が eSIM を取り扱う能力がある端末であることを示す FEATURE_TELEPHONY_EUICC は、最初から表示されています。

$ pm list features
...
feature:android.hardware.telephony
feature:android.hardware.telephony.carrierlock
feature:android.hardware.telephony.cdma
feature:android.hardware.telephony.euicc // これ
feature:android.hardware.telephony.gsm
feature:android.hardware.telephony.ims
...

その他の FEATURE 一覧はこちら。

cheerio-the-bear.hatenablog.com

1-1. コンフィギュレーション用リソース

Android フレームワークが持っているリソースを、幾つか読んでみました。

f:id:cheerio-the-bear:20200613221310p:plain
各リソースの値

config_telephonyEuiccDeviceCapabilities は概ね Google/AOSP にある下記の例の通りですが、contactlessSupportedRelease と rspCrlSupportedVersion の指定はありません。3GPP 系がリリース 11 になっているのは、どうしてでしょうか。

    <!-- An array of device capabilities defined by GSMA SGP.22 v2.0.
         The first item is the capability name that the device supports. The second item is the
         major version. The minor and revision versions are default to 0s.
         The device capabilities and their definition in the spec are:
             gsm : gsmSupportedRelease
             utran : utranSupportedRelease
             cdma1x : cdma2000onexSupportedRelease
             hrpd : cdma2000hrpdSupportedRelease
             ehrpd : cdma2000ehrpdSupportedRelease
             eutran : eutranSupportedRelease
             nfc : contactlessSupportedRelease
             crl : rspCrlSupportedVersion
    -->
    <string-array translatable="false" name="config_telephonyEuiccDeviceCapabilities">
        <item>"gsm,11"</item>
        <item>"utran,11"</item>
        <item>"cdma1x,1"</item>
        <item>"hrpd,3"</item>
        <item>"ehrpd,12"</item>
        <item>"eutran,11"</item>
    </string-array>

二番目の物理スロットが端末に実装されている eSIM なので、non_removable_euicc_slots の配列には 1 だけが設定されています。

    <!-- Device-specific array of SIM slot indexes which are are embedded eUICCs.
         e.g. If a device has two physical slots with indexes 0, 1, and slot 1 is an
         eUICC, then the value of this array should be:
             <integer-array name="non_removable_euicc_slots">
                 <item>1</item>
             </integer-array>
         If a device has three physical slots and slot 1 and 2 are eUICCs, then the value of
         this array should be:
             <integer-array name="non_removable_euicc_slots">
                <item>1</item>
                <item>2</item>
             </integer-array>
         This is used to differentiate between removable eUICCs and built in eUICCs, and should
         be set by OEMs for devices which use eUICCs. -->
    <integer-array name="non_removable_euicc_slots">
       <item>1</item>
    </integer-array>

この時点ではシングル SIM 端末ですが、Google Pixel 4 はデュアル SIM 端末になれる子です。config_num_physical_slots は 2 になっています。

    <!-- Number of physical SIM slots on the device. This includes both eSIM and pSIM slots, and
         is not necessarily the same as the number of phones/logical modems supported by the device.
         For example, a multi-sim device can have 2 phones/logical modems, but 3 physical slots,
         or a single SIM device can have 1 phones/logical modems, but 2 physical slots (one eSIM
         and one pSIM) -->
    <integer name="config_num_physical_slots">2</integer>
1-3. テレフォニー API が返す値

テレフォニー API が返す値が、複数の SIM を取り扱うこと能力があることを示していることがわかります。Google Pixel 4 がデュアル SIM 端末になるときに端末の再起動を求められるのは、doesSwitchMultiSimConfigTriggerReboot() が true を返しているからですね。

API 返値
doesSwitchMultiSimConfigTriggerReboot() true
getActiveModemCount() (Android Q にはまだない)
getSupportedModemCount() (Android Q にはまだない)
getMaxNumberOfSimultaneouslyActiveSims() (Android Q にはまだない)
getMultiSimConfiguration() UNKNOWN
getSimCount() 1
isMultiSimEnabled() false
isMultiSimSupported() 0 (MULTISIM_ALLOWED)
1-4. システムプロパティ

システムプロパティも確認してみましたが、シングル SIM 端末として動作している時点では "persist.radio.multisim.config" が見当たりません。

cheerio-the-bear.hatenablog.com

2. デュアル SIM 端末へ変更

2-1. 物理スロットの状態

物理スロットの状態を示す下記のログは、まだシングル SIM 端末として動作しているときにとった radio ログから抜き出したものです。物理スロット 2 にある eSIM だけがアクティブで、論理スロット 1 にマッピングされているようです。端末をアンロックしていないので、TelephonyManager.getLogicalToPhysicalSlotMapping() の返値は確認できていません。

D/RadioConfigResponse( 2047): [0009]< GET_SLOT_STATUS [
    IccSlotStatus {CARDSTATE_ABSENT,SLOTSTATE_INACTIVE,logicalSlotIndex=0,atr=,iccid=,eid=},
    IccSlotStatus {CARDSTATE_PRESENT,SLOTSTATE_ACTIVE,logicalSlotIndex=0,atr=3b9f96803fc6a28031e073f62157574a4d021060500002,
    ...
]

その状態から物理スロット 1 に SIM カードを装着すると、本投稿の冒頭に貼ったスクリーンショットのダイアログ群が表示されます。デュアル SIM 端末になること、それには再起動が必要なことに同意すると、端末の再起動の後にデュアル SIM 端末へと切り替わります。SWITCH_DUAL_SIM_CONFIG がそのために送信されるメッセージのようです。

D/PhoneCfgMgr( 2048): switchMultiSimConfig: with numOfSims = 2
D/PhoneCfgMgr( 2048): switchMultiSimConfig: sending the request for switching
D/RadioConfig( 2048): [0352]> SWITCH_DUAL_SIM_CONFIG, numOfLiveModems = 2

デュアル SIM 端末になったところで、物理スロットの状態をもう一度見てみましょう。両方の物理スロットがアクティブになり、また物理・論理スロットのマッピングもストレートになっていることがわかります。

D/RadioConfigResponse( 2103): [0017]< GET_SLOT_STATUS [
    IccSlotStatus {CARDSTATE_PRESENT,SLOTSTATE_ACTIVE,logicalSlotIndex=0,atr=3b9f96c00a1fc68031e073fe211f65d00233131b810ffa,iccid=898109001[****],eid=},
    IccSlotStatus {CARDSTATE_PRESENT,SLOTSTATE_ACTIVE,logicalSlotIndex=1,atr=3b9f96803fc6a28031e073f62157574a4d021060500002,iccid=898103039[****],
    ...
]
2-2. テレフォニー API が返す値

getMultiSimConfiguration() と getSimCount()、isMultiSimEnabled() の返値が変わり、デュアル SIM 端末っぽくなっています。

API 返値
doesSwitchMultiSimConfigTriggerReboot() true
getActiveModemCount() (Android Q にはまだない)
getSupportedModemCount() (Android Q にはまだない)
getMaxNumberOfSimultaneouslyActiveSims() (Android Q にはまだない)
getMultiSimConfiguration() DSDS
getSimCount() 2
isMultiSimEnabled() true
isMultiSimSupported() 0 (MULTISIM_ALLOWED)
2-3. システムプロパティ

元々は存在しなかったプロパティ、"persist.radio.multisim.config" が動的に追加されているのがわかります。

...
[persist.mm.enable.prefetch]: [true]
[persist.radio.multisim.config]: [dsds]  // これ
[persist.rcs.supported]: [1]
...