การใช้งาน eSIM

เทคโนโลยี SIM แบบฝัง (eSIM หรือ eUICC) ช่วยให้ผู้ใช้อุปกรณ์เคลื่อนที่สามารถดาวน์โหลดโปรไฟล์ผู้ให้บริการและเปิดใช้งานบริการของผู้ให้บริการได้โดยไม่ต้องมีซิมการ์ดจริง เป็นข้อกำหนดระดับโลกที่ขับเคลื่อนโดย GSMA ซึ่งเปิดใช้งานการจัดเตรียม SIM ระยะไกล (RSP) ของอุปกรณ์เคลื่อนที่ใดๆ เริ่มต้นด้วย Android 9 เฟรมเวิร์ก Android มอบ API มาตรฐานสำหรับการเข้าถึง eSIM และจัดการโปรไฟล์การสมัครรับข้อมูลบน eSIM eUICC API เหล่านี้ช่วยให้บุคคลที่สามสามารถพัฒนาแอปของผู้ให้บริการและ Local Profile Assistant (LPA) ของตนเองบนอุปกรณ์ Android ที่รองรับ eSIM

LPA เป็นแอประบบแบบสแตนด์อโลนที่ควรรวมอยู่ในอิมเมจบิลด์ Android โดยทั่วไปการจัดการโปรไฟล์บน eSIM จะดำเนินการโดย LPA เนื่องจากทำหน้าที่เป็นสะพานเชื่อมระหว่าง SM-DP+ (บริการระยะไกลที่จัดเตรียม จัดเก็บ และจัดส่งแพ็คเกจโปรไฟล์ไปยังอุปกรณ์) และชิป eUICC LPA APK สามารถเลือกรวมองค์ประกอบ UI ที่เรียกว่า LPA UI หรือ LUI เพื่อเป็นพื้นที่ส่วนกลางสำหรับผู้ใช้ในการจัดการโปรไฟล์การสมัครรับข้อมูลแบบฝังทั้งหมด กรอบงาน Android จะค้นพบและเชื่อมต่อกับ LPA ที่ดีที่สุดที่มีอยู่โดยอัตโนมัติ และกำหนดเส้นทางการดำเนินการ eUICC ทั้งหมดผ่านอินสแตนซ์ LPA

สถาปัตยกรรม Remote SIM Provisioning (RSP) แบบง่าย

รูปที่ 1 สถาปัตยกรรม RSP แบบง่าย

ผู้ให้บริการเครือข่ายมือถือที่สนใจสร้าง แอปผู้ให้บริการ ควรดู API ใน EuiccManager ซึ่งมีการดำเนินการจัดการโปรไฟล์ระดับสูง เช่น downloadSubscription() , switchToSubscription() และ deleteSubscription()

หากคุณเป็น OEM อุปกรณ์ที่สนใจสร้างแอประบบ LPA ของคุณเอง คุณต้องขยาย EuiccService สำหรับเฟรมเวิร์ก Android เพื่อเชื่อมต่อกับบริการ LPA ของคุณ นอกจากนี้ คุณควรใช้ API ใน EuiccCardManager ซึ่งมีฟังก์ชัน ES10x ตาม GSMA RSP v2.0 ฟังก์ชันเหล่านี้ใช้เพื่อออกคำสั่งไปยังชิป eUICC เช่น prepareDownload() , loadBoundProfilePackage() , retrieveNotificationList() และ resetMemory()

API ใน EuiccManager จำเป็นต้องมีแอป LPA ที่ใช้งานอย่างเหมาะสมจึงจะทำงานได้ และผู้เรียก EuiccCardManager API ต้องเป็น LPA สิ่งนี้บังคับใช้โดยกรอบงาน Android

อุปกรณ์ที่ใช้ Android 10 ขึ้นไปสามารถรองรับอุปกรณ์ที่มี eSIM หลายอันได้ สำหรับข้อมูลเพิ่มเติม โปรดดู การรองรับ eSIM หลายอัน

การสร้างแอปผู้ให้บริการ

eUICC APIs ใน Android 9 ช่วยให้ผู้ให้บริการเครือข่ายมือถือสามารถสร้างแอปที่มีตราสินค้าของผู้ให้บริการเพื่อจัดการโปรไฟล์ของตนได้โดยตรง ซึ่งรวมถึงการดาวน์โหลดและการลบโปรไฟล์การสมัครสมาชิกของผู้ให้บริการ รวมถึงการสลับไปใช้โปรไฟล์ของผู้ให้บริการ

Euicผู้จัดการ

EuiccManager เป็นจุดเริ่มต้นหลักสำหรับแอปในการโต้ตอบกับ LPA ซึ่งรวมถึงแอพของผู้ให้บริการที่ดาวน์โหลด ลบ และสลับไปใช้การสมัครรับของผู้ให้บริการ นอกจากนี้ยังรวมถึงแอประบบ LUI ซึ่งมีตำแหน่งส่วนกลาง/UI สำหรับจัดการการสมัครสมาชิกแบบฝัง ทั้งหมด และสามารถเป็นแอปแยกต่างหากจากแอปที่ให้บริการ EuiccService

หากต้องการใช้ API สาธารณะ แอปผู้ให้บริการจะต้องได้รับอินสแตนซ์ของ EuiccManager ผ่าน Context#getSystemService ก่อน

EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);

คุณควรตรวจสอบว่าอุปกรณ์รองรับ eSIM หรือไม่ก่อนดำเนินการใดๆ กับ eSIM โดยทั่วไป EuiccManager#isEnabled() จะคืน true หากมีการกำหนดคุณลักษณะ android.hardware.telephony.euicc และมีแพ็คเกจ LPA อยู่

if (mgr == null || !mgr.isEnabled()) {
    return;
}

วิธีรับข้อมูลเกี่ยวกับฮาร์ดแวร์ eUICC และเวอร์ชัน eSIM OS:

EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();

API จำนวนมาก เช่น downloadSubscription() และ switchToSubscription() ใช้การเรียกกลับ PendingIntent เนื่องจากอาจใช้เวลาไม่กี่วินาทีหรือหลายนาทีจึงจะเสร็จสมบูรณ์ PendingIntent จะถูกส่งไปพร้อมกับโค้ดผลลัพธ์ในพื้นที่ EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_ ซึ่งจัดเตรียมโค้ดข้อผิดพลาดที่เฟรมเวิร์กกำหนด เช่นเดียวกับโค้ดผลลัพธ์โดยละเอียดตามอำเภอใจที่เผยแพร่จาก LPA เป็น EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE ช่วยให้แอปผู้ให้บริการสามารถติดตามเพื่อวัตถุประสงค์ในการบันทึก/แก้ไขจุดบกพร่อง การเรียกกลับ PendingIntent จะต้องเป็น BroadcastReceiver

หากต้องการดาวน์โหลดการสมัครสมาชิกที่ดาวน์โหลดได้ (สร้างจาก รหัสเปิดใช้งาน หรือรหัส QR):

// Register receiver.
static final String ACTION_DOWNLOAD_SUBSCRIPTION = "download_subscription";
static final String LPA_DECLARED_PERMISSION
    = "com.your.company.lpa.permission.BROADCAST";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);

                // If the result code is a resolvable error, call startResolutionActivity
                if (resultCode == EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR) {
                    PendingIntent callbackIntent = PendingIntent.getBroadcast(
                        getContext(), 0 /* requestCode */, intent,
                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
                    mgr.startResolutionActivity(
                        activity,
                        0 /* requestCode */,
                        intent,
                        callbackIntent);
                }

                resultIntent = intent;
            }
        };
context.registerReceiver(receiver,
        new IntentFilter(ACTION_DOWNLOAD_SUBSCRIPTION),
        LPA_DECLARED_PERMISSION /* broadcastPermission*/,
        null /* handler */);

// Download subscription asynchronously.
DownloadableSubscription sub = DownloadableSubscription
        .forActivationCode(code /* encodedActivationCode*/);
Intent intent = new Intent(action).setPackage(context.getPackageName());
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent,
        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
mgr.downloadSubscription(sub, true /* switchAfterDownload */,
        callbackIntent);

กำหนดและใช้การอนุญาตใน AndroidManifest.xml :

    <permission android:protectionLevel="signature" android:name="com.your.company.lpa.permission.BROADCAST" />
    <uses-permission android:name="com.your.company.lpa.permission.BROADCAST"/>

หากต้องการเปลี่ยนไปใช้การสมัครสมาชิกตามรหัสการสมัครสมาชิก:

// Register receiver.
static final String ACTION_SWITCH_TO_SUBSCRIPTION = "switch_to_subscription";
static final String LPA_DECLARED_PERMISSION
    = "com.your.company.lpa.permission.BROADCAST";
BroadcastReceiver receiver =
        new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                if (!action.equals(intent.getAction())) {
                    return;
                }
                resultCode = getResultCode();
                detailedCode = intent.getIntExtra(
                    EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
                    0 /* defaultValue*/);
                resultIntent = intent;
            }
        };
context.registerReceiver(receiver,
        new IntentFilter(ACTION_SWITCH_TO_SUBSCRIPTION),
        LPA_DECLARED_PERMISSION /* broadcastPermission*/,
        null /* handler */);

// Switch to a subscription asynchronously.
Intent intent = new Intent(action).setPackage(context.getPackageName());
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent,
        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);

หากต้องการดูรายการ EuiccManager API และตัวอย่างโค้ดทั้งหมด โปรดดูที่ eUICC API

ข้อผิดพลาดที่แก้ไขได้

มีบางกรณีที่ระบบไม่สามารถดำเนินการ eSIM ให้เสร็จสิ้นได้ แต่ผู้ใช้สามารถแก้ไขได้ ตัวอย่างเช่น downloadSubscription อาจล้มเหลวหากข้อมูลเมตาของโปรไฟล์ระบุว่าจำเป็นต้องใช้ รหัสยืนยันจากผู้ให้บริการ หรือ switchToSubscription อาจล้มเหลวหากแอปของผู้ให้บริการมีสิทธิ์ของผู้ให้บริการผ่านโปรไฟล์ปลายทาง (นั่นคือ ผู้ให้บริการเป็นเจ้าของโปรไฟล์) แต่ไม่มีสิทธิ์ของผู้ให้บริการผ่านโปรไฟล์ที่เปิดใช้งานในปัจจุบัน และด้วยเหตุนี้จึงต้องได้รับความยินยอมจากผู้ใช้

ในกรณีเหล่านี้ การโทรกลับของผู้โทรจะถูกเรียกด้วย EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR Intent ของการโทรกลับมีสิ่งพิเศษภายใน เช่น เมื่อผู้โทรส่งต่อไปยัง EuiccManager#startResolutionActivity จะสามารถขอการแก้ไขผ่าน LUI ได้ ตัวอย่างเช่น การใช้รหัสยืนยันอีกครั้ง EuiccManager#startResolutionActivity จะทริกเกอร์หน้าจอ LUI ที่อนุญาตให้ผู้ใช้ป้อนรหัสยืนยัน หลังจากป้อนรหัสแล้ว การดาวน์โหลดจะกลับมาทำงานต่อ วิธีการนี้ทำให้แอปของผู้ให้บริการสามารถควบคุมได้อย่างเต็มที่ว่าจะแสดง UI เมื่อใด แต่ให้ LPA/LUI มีวิธีที่สามารถขยายได้สำหรับการเพิ่มการจัดการใหม่ของปัญหาที่ผู้ใช้กู้คืนได้ในอนาคตโดยไม่จำเป็นต้องเปลี่ยนแอปไคลเอ็นต์

Android 9 กำหนดข้อผิดพลาดที่แก้ไขได้เหล่านี้ใน EuiccService ซึ่ง LUI ควรจัดการ:

/**
 * Alert the user that this action will result in an active SIM being
 * deactivated. To implement the LUI triggered by the system, you need to define
 * this in AndroidManifest.xml.
 */
public static final String ACTION_RESOLVE_DEACTIVATE_SIM =
        "android.service.euicc.action.RESOLVE_DEACTIVATE_SIM";
/**
 * Alert the user about a download/switch being done for an app that doesn't
 * currently have carrier privileges.
 */
public static final String ACTION_RESOLVE_NO_PRIVILEGES =
        "android.service.euicc.action.RESOLVE_NO_PRIVILEGES";

/** Ask the user to resolve all the resolvable errors. */
public static final String ACTION_RESOLVE_RESOLVABLE_ERRORS =
        "android.service.euicc.action.RESOLVE_RESOLVABLE_ERRORS";

สิทธิพิเศษของผู้ให้บริการ

หากคุณเป็นผู้ให้บริการที่พัฒนาแอปผู้ให้บริการของคุณเองที่เรียก EuiccManager เพื่อดาวน์โหลดโปรไฟล์ลงในอุปกรณ์ โปรไฟล์ของคุณควรรวมกฎสิทธิ์ของผู้ให้บริการที่สอดคล้องกับแอปผู้ให้บริการของคุณไว้ในข้อมูลเมตา เนื่องจากโปรไฟล์การสมัครสมาชิกของผู้ให้บริการแต่ละรายสามารถอยู่ร่วมกันใน eUICC ของอุปกรณ์ได้ และแอปของผู้ให้บริการแต่ละรายควรได้รับอนุญาตให้เข้าถึงเฉพาะโปรไฟล์ของผู้ให้บริการรายนั้นเท่านั้น ตัวอย่างเช่น ผู้ให้บริการ A ไม่ควรสามารถดาวน์โหลด เปิดใช้งาน หรือปิดใช้งานโปรไฟล์ที่เป็นของผู้ให้บริการ B

เพื่อให้แน่ใจว่ามีเพียงเจ้าของเท่านั้นที่สามารถเข้าถึงโปรไฟล์ได้ Android จะใช้กลไกในการให้สิทธิพิเศษแก่แอปของเจ้าของโปรไฟล์ (นั่นคือ แอปของผู้ให้บริการ) แพลตฟอร์ม Android โหลดใบรับรองที่จัดเก็บไว้ในไฟล์กฎการเข้าถึง (ARF) ของโปรไฟล์ และให้สิทธิ์แก่แอปที่ลงนามโดยใบรับรองเหล่านี้เพื่อทำการเรียกไปยัง EuiccManager API กระบวนการระดับสูงอธิบายไว้ด้านล่าง:

  1. ผู้ดำเนินการลงนามในแอปผู้ให้บริการ APK; เครื่องมือ apksigner จะแนบใบรับรองคีย์สาธารณะเข้ากับ APK
  2. ผู้ปฏิบัติงาน/SM-DP+ เตรียมโปรไฟล์และข้อมูลเมตา ซึ่งรวมถึง ARF ที่ประกอบด้วย:

    1. ลายเซ็น (SHA-1 หรือ SHA-256) ของใบรับรองคีย์สาธารณะของแอปผู้ให้บริการ (จำเป็น)
    2. ชื่อแพ็กเกจของแอปผู้ให้บริการ (แนะนำอย่างยิ่ง)
  3. แอปผู้ให้บริการพยายามดำเนินการ eUICC ผ่าน EuiccManager API

  4. แพลตฟอร์ม Android ตรวจสอบแฮช SHA-1 หรือ SHA-256 ของใบรับรองของแอปผู้โทรตรงกับลายเซ็นของใบรับรองที่ได้รับจาก ARF ของโปรไฟล์เป้าหมาย หากชื่อแพ็กเกจของแอปผู้ให้บริการรวมอยู่ใน ARF ชื่อแพ็กเกจนั้นจะต้องตรงกับชื่อแพ็กเกจของแอปผู้โทรด้วย

  5. หลังจากตรวจสอบลายเซ็นและชื่อแพ็กเกจ (หากรวมไว้ด้วย) แล้ว แอปผู้โทรจะมอบสิทธิ์ของผู้ให้บริการผ่านโปรไฟล์เป้าหมาย

เนื่องจากข้อมูลเมตาของโปรไฟล์สามารถใช้ได้ภายนอกโปรไฟล์ (เพื่อให้ LPA สามารถดึงข้อมูลเมตาของโปรไฟล์จาก SM-DP+ ก่อนที่จะดาวน์โหลดโปรไฟล์ หรือจาก ISD-R เมื่อโปรไฟล์ถูกปิดใช้งาน) จึงควรมีกฎสิทธิ์ของผู้ให้บริการเดียวกัน เช่นเดียวกับในโปรไฟล์

eUICC OS และ SM-DP+ ต้องรองรับแท็กที่เป็นกรรมสิทธิ์ BF76 ในข้อมูลเมตาของโปรไฟล์ เนื้อหาแท็กควรเป็นกฎสิทธิ์ของผู้ให้บริการเดียวกันกับที่ส่งคืนโดยแอปเพล็ตกฎการเข้าถึง (ARA) ที่กำหนดใน UICC Carrier Privileges :

RefArDo ::= [PRIVATE 2] SEQUENCE {  -- Tag E2
    refDo [PRIVATE 1] SEQUENCE {  -- Tag E1
        deviceAppIdRefDo [PRIVATE 1] OCTET STRING (SIZE(20|32)),  -- Tag C1
        pkgRefDo [PRIVATE 10] OCTET STRING (SIZE(0..127)) OPTIONAL  -- Tag CA
    },
    arDo [PRIVATE 3] SEQUENCE {  -- Tag E3
        permArDo [PRIVATE 27] OCTET STRING (SIZE(8))  -- Tag DB
    }
}

สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับการลงนามแอป โปรดดูที่ ลงนามแอปของคุณ สำหรับรายละเอียดเกี่ยวกับสิทธิ์ของผู้ให้บริการ โปรดดู ที่ สิทธิ์ของผู้ให้บริการ UICC

การสร้างแอปผู้ช่วยโปรไฟล์ในเครื่อง

ผู้ผลิตอุปกรณ์สามารถใช้ Local Profile Assistant (LPA) ของตนเองได้ ซึ่งจะต้องเชื่อมต่อกับ Android Euicc API ส่วนต่อไปนี้จะให้ภาพรวมโดยย่อของการสร้างแอป LPA และบูรณาการเข้ากับระบบ Android

ข้อกำหนดด้านฮาร์ดแวร์/โมเด็ม

LPA และ eSIM OS บนชิป eUICC ต้องรองรับอย่างน้อย GSMA RSP (Remote SIM Provisioning) v2.0 หรือ v2.2 คุณควรวางแผนที่จะใช้เซิร์ฟเวอร์ SM-DP+ และ SM-DS ที่มีเวอร์ชัน RSP ที่ตรงกัน สำหรับสถาปัตยกรรม RSP โดยละเอียด โปรดดู ข้อกำหนดสถาปัตยกรรม RSP ของ GSMA SGP.21

นอกจากนี้ หากต้องการรวมเข้ากับ eUICC API ใน Android 9 โมเด็มอุปกรณ์ควรส่งความสามารถของเทอร์มินัลพร้อมรองรับการเข้ารหัสความสามารถของ eUICC (การจัดการโปรไฟล์ในตัวเครื่องและการดาวน์โหลดโปรไฟล์) นอกจากนี้ยังจำเป็นต้องใช้วิธีการต่อไปนี้:

  • IRadio HAL v1.1: setSimPower
  • IRadio HAL v1.2: getIccCardStatus

  • IRadioConfig HAL v1.0: getSimSlotsStatus

  • IRadioConfig AIDL v1.0: getAllowedCarriers

    Google LPA จำเป็นต้องทราบสถานะการล็อกของผู้ให้บริการเพื่อให้สามารถอนุญาตให้ดาวน์โหลดหรือโอน eSIM สำหรับผู้ให้บริการที่ได้รับอนุญาตเท่านั้น มิฉะนั้นผู้ใช้อาจดาวน์โหลดและถ่ายโอน SIM และทราบในภายหลังว่าอุปกรณ์นั้นถูกล็อคโดยผู้ให้บริการรายอื่น

    • ผู้จำหน่ายหรือ OEM ต้องใช้ IRadioSim.getAllowedCarriers()HAL API

    • ผู้ขาย RIL / โมเด็มจะต้องเติมสถานะการล็อคและรหัสผู้ให้บริการของผู้ให้บริการที่อุปกรณ์ถูกล็อคโดยเป็นส่วนหนึ่งของ IRadioSimResponse.getAllowedCarriersResponse()HAL API

โมเด็มควรจดจำ eSIM โดยเปิดใช้งานโปรไฟล์การบูตเริ่มต้นเป็นซิมที่ถูกต้อง และเปิดซิมไว้

สำหรับอุปกรณ์ที่ใช้ Android 10 จะต้องกำหนดอาร์เรย์ ID สล็อต eUICC ที่ไม่สามารถถอดออกได้ ตัวอย่างเช่น ดูที่ arrays.xml

<resources>
   <!-- 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>
</resources>

ดูรายการข้อกำหนดของโมเด็มทั้งหมด โปรดดู ข้อกำหนดของโมเด็มสำหรับการรองรับ eSIM

ยูอิคเซอร์วิส

LPA ประกอบด้วยองค์ประกอบ 2 ส่วนแยกกัน (อาจใช้งานทั้งคู่ใน APK เดียวกัน): แบ็กเอนด์ LPA และ LPA UI หรือ LUI

หากต้องการใช้แบ็กเอนด์ LPA คุณต้องขยาย EuiccService และประกาศบริการนี้ในไฟล์ Manifest ของคุณ บริการจะต้องได้รับอนุญาตจากระบบ android.permission.BIND_EUICC_SERVICE เพื่อให้แน่ใจว่ามีเพียงระบบเท่านั้นที่สามารถเชื่อมโยงได้ บริการนี้ยังต้องมีตัวกรองเจตนาพร้อมกับการดำเนินการ android.service.euicc.EuiccService ลำดับความสำคัญของตัวกรอง Intent ควรตั้งค่าเป็นค่าที่ไม่ใช่ศูนย์ ในกรณีที่มีการใช้งานหลายอย่างบนอุปกรณ์ ตัวอย่างเช่น:

<service
    android:name=".EuiccServiceImpl"
    android:permission="android.permission.BIND_EUICC_SERVICE">
    <intent-filter android:priority="100">
        <action android:name="android.service.euicc.EuiccService" />
    </intent-filter>
</service>

ภายใน เฟรมเวิร์ก Android จะกำหนด LPA ที่ใช้งานอยู่และโต้ตอบกับเฟรมเวิร์กดังกล่าวตามความจำเป็นเพื่อรองรับ Android eUICC API PackageManager ได้รับการสอบถามสำหรับแอปทั้งหมดที่มีสิทธิ์ android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS ซึ่งระบุบริการสำหรับการดำเนินการ android.service.euicc.EuiccService เลือกบริการที่มีลำดับความสำคัญสูงสุด หากไม่พบบริการ การสนับสนุน LPA จะถูกปิดใช้งาน

หากต้องการนำ LUI ไปใช้ คุณต้องจัดเตรียมกิจกรรมสำหรับการดำเนินการต่อไปนี้:

  • android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS
  • android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION

เช่นเดียวกับบริการ แต่ละกิจกรรมจะต้องได้รับอนุญาตจากระบบ android.permission.BIND_EUICC_SERVICE แต่ละรายการควรมีตัวกรอง Intent พร้อมการดำเนินการที่เหมาะสม หมวดหมู่ android.service.euicc.category.EUICC_UI และลำดับความสำคัญที่ไม่เป็นศูนย์ ตรรกะที่คล้ายกันใช้ในการเลือกการใช้งานสำหรับกิจกรรมเหล่านี้ เช่นเดียวกับการเลือกการใช้งาน EuiccService ตัวอย่างเช่น:

<activity android:name=".MyLuiActivity"
          android:exported="true"
          android:permission="android.permission.BIND_EUICC_SERVICE">
    <intent-filter android:priority="100">
        <action android:name="android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS" />
        <action android:name="android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.service.euicc.category.EUICC_UI" />
    </intent-filter>
</activity>

นี่หมายความว่า UI ที่ใช้งานหน้าจอเหล่านี้อาจมาจาก APK ที่แตกต่างจาก APK ที่ใช้ EuiccService ไม่ว่าจะมี APK เดียวหรือหลาย APK (เช่น หนึ่งที่ใช้ EuiccService และอีกหนึ่งที่มีกิจกรรม LUI) ก็เป็นทางเลือกในการออกแบบ

EuicCardManager

EuiccCardManager เป็นอินเทอร์เฟซสำหรับการสื่อสารกับชิป eSIM โดยมีฟังก์ชัน ES10 (ตามที่อธิบายไว้ในข้อกำหนด GSMA RSP) และจัดการคำสั่งคำขอ/ตอบกลับ APDU ระดับต่ำ ตลอดจนการแยกวิเคราะห์ ASN.1 EuiccCardManager เป็น API ของระบบและสามารถเรียกได้โดยแอปที่มีสิทธิ์ของระบบเท่านั้น

แอปของผู้ให้บริการ, LPA และ Euicc API

รูปที่ 2 ทั้งแอปผู้ให้บริการและ LPA ใช้ Euicc API

API การดำเนินการโปรไฟล์ผ่าน EuiccCardManager กำหนดให้ผู้เรียกเป็น LPA สิ่งนี้บังคับใช้โดยกรอบงาน Android ซึ่งหมายความว่าผู้เรียกจะต้องขยาย EuiccService และได้รับการประกาศในไฟล์ Manifest ของคุณ ตามที่อธิบายไว้ในส่วนก่อนหน้า

เช่นเดียวกับ EuiccManager หากต้องการใช้ EuiccCardManager API นั้น LPA ของคุณจะต้องได้รับอินสแตนซ์ของ EuiccCardManager ผ่าน Context#getSystemService ก่อน

EuiccCardManager cardMgr = (EuiccCardManager) context.getSystemService(Context.EUICC_CARD_SERVICE);

จากนั้น หากต้องการรับโปรไฟล์ทั้งหมดบน eUICC:

ResultCallback<EuiccProfileInfo[]> callback =
       new ResultCallback<EuiccProfileInfo[]>() {
           @Override
           public void onComplete(int resultCode,
                   EuiccProfileInfo[] result) {
               if (resultCode == EuiccCardManagerReflector.RESULT_OK) {
                   // handle result
               } else {
                   // handle error
               }
           }
       };

cardMgr.requestAllProfiles(eid, AsyncTask.THREAD_POOL_EXECUTOR, callback);

ภายใน EuiccCardManager เชื่อมโยงกับ EuiccCardController (ซึ่งทำงานในกระบวนการโทรศัพท์) ผ่านอินเทอร์เฟซ AIDL และแต่ละวิธี EuiccCardManager ได้รับการติดต่อกลับจากกระบวนการโทรศัพท์ผ่านอินเทอร์เฟซ AIDL เฉพาะที่แตกต่างกัน เมื่อใช้ EuiccCardManager API ผู้เรียก (LPA) จะต้องจัดเตรียมออบเจ็ Executor เพื่อใช้เรียกกลับ ออบเจ็กต์ Executor นี้อาจทำงานบนเธรดเดียวหรือบนพูลเธรดที่คุณเลือก

EuiccCardManager API ส่วนใหญ่มีรูปแบบการใช้งานเหมือนกัน ตัวอย่างเช่น หากต้องการโหลดแพ็คเกจโปรไฟล์ที่ถูกผูกไว้บน eUICC:

...
cardMgr.loadBoundProfilePackage(eid, boundProfilePackage,
        AsyncTask.THREAD_POOL_EXECUTOR, callback);

หากต้องการเปลี่ยนไปใช้โปรไฟล์อื่นด้วย ICCID ที่กำหนด:

...
cardMgr.switchToProfile(eid, iccid, true /* refresh */,
        AsyncTask.THREAD_POOL_EXECUTOR, callback);

วิธีรับที่อยู่ SM-DP+ เริ่มต้นจากชิป eUICC:

...
cardMgr.requestDefaultSmdpAddress(eid, AsyncTask.THREAD_POOL_EXECUTOR,
        callback);

หากต้องการดึงรายการการแจ้งเตือนของเหตุการณ์การแจ้งเตือนที่กำหนด:

...
cardMgr.listNotifications(eid,
        EuiccNotification.Event.INSTALL
              | EuiccNotification.Event.DELETE /* events */,
        AsyncTask.THREAD_POOL_EXECUTOR, callback);

การเปิดใช้งานโปรไฟล์ eSIM ผ่านแอพของผู้ให้บริการ

บนอุปกรณ์ที่ใช้ Android 9 ขึ้นไป คุณสามารถใช้แอปของผู้ให้บริการเพื่อเปิดใช้งาน eSIM และดาวน์โหลดโปรไฟล์ได้ แอพของผู้ให้บริการสามารถดาวน์โหลดโปรไฟล์ได้โดยการเรียก downloadSubscription โดยตรงหรือโดยการให้รหัสเปิดใช้งานแก่ LPA

เมื่อแอปของผู้ให้บริการดาวน์โหลดโปรไฟล์โดยการเรียก downloadSubscription การโทรจะบังคับให้แอปสามารถจัดการโปรไฟล์ผ่าน แท็กข้อมูลเมตา BF76 ที่เข้ารหัส กฎสิทธิ์ของผู้ให้บริการ สำหรับโปรไฟล์นั้น หากโปรไฟล์ไม่มีแท็ก BF76 หรือหากแท็ก BF76 ไม่ตรงกับลายเซ็นของแอพผู้ให้บริการโทรศัพท์ การดาวน์โหลดจะถูกปฏิเสธ

ส่วนด้านล่างอธิบายการเปิดใช้งาน eSIM ผ่านแอพของผู้ให้บริการเครือข่ายโดยใช้รหัสเปิดใช้งาน

การเปิดใช้งาน eSIM โดยใช้รหัสเปิดใช้งาน

เมื่อใช้รหัสเปิดใช้งานเพื่อเปิดใช้งานโปรไฟล์ eSIM LPA จะดึงรหัสเปิดใช้งานจากแอพของผู้ให้บริการและดาวน์โหลดโปรไฟล์ LPA สามารถริเริ่มโฟลว์นี้ได้ และ LPA สามารถควบคุมโฟลว์ UI ทั้งหมดได้ ซึ่งหมายความว่าจะไม่มีการแสดง UI ของแอปผู้ให้บริการ วิธีการนี้จะข้ามการตรวจสอบแท็ก BF76 และผู้ให้บริการเครือข่ายไม่จำเป็นต้องใช้โฟลว์การเปิดใช้งาน eSIM UI ทั้งหมด รวมถึงการดาวน์โหลดโปรไฟล์ eSIM และการจัดการข้อผิดพลาด

การกำหนดบริการจัดเตรียม eUICC ของผู้ให้บริการ

แอป LPA และผู้ให้บริการสื่อสารผ่านอินเทอร์เฟซ AIDL สองอินเทอร์เฟซ: ICarrierEuiccProvisioningService และ IGetActivationCodeCallback แอปผู้ให้บริการต้องใช้อินเทอร์เฟซ ICarrierEuiccProvisioningService และเปิดเผยใน การประกาศรายการ LPA ต้องเชื่อมโยงกับ ICarrierEuiccProvisioningService และใช้ IGetActivationCodeCallback สำหรับข้อมูลเพิ่มเติมเกี่ยวกับวิธีการนำไปใช้และเปิดเผยอินเทอร์เฟซ AIDL โปรดดูที่ การกำหนดและอินเทอร์เฟซ AIDL

หากต้องการกำหนดอินเทอร์เฟซ AIDL ให้สร้างไฟล์ AIDL ต่อไปนี้สำหรับทั้งแอป LPA และผู้ให้บริการ

  • ICarrierEuiccProvisioningService.aidl

    package android.service.euicc;
    
    import android.service.euicc.IGetActivationCodeCallback;
    
    oneway interface ICarrierEuiccProvisioningService {
        // The method to get the activation code from the carrier app. The caller needs to pass in
        // the implementation of IGetActivationCodeCallback as the parameter.
        void getActivationCode(in IGetActivationCodeCallback callback);
    
        // The method to get the activation code from the carrier app. The caller needs to pass in
        // the activation code string as the first parameter and the implementation of
        // IGetActivationCodeCallback as the second parameter. This method provides the carrier
        // app the device EID which allows a carrier to pre-bind a profile to the device's EID before
        // the download process begins.
        void getActivationCodeForEid(in String eid, in IGetActivationCodeCallback callback);
    }
    
    
  • IGetActivationCodeCallback.aidl

    package android.service.euicc;
    
    oneway interface IGetActivationCodeCallback {
        // The call back method needs to be called when the carrier app gets the activation
        // code successfully. The caller needs to pass in the activation code string as the
        // parameter.
        void onSuccess(String activationCode);
    
        // The call back method needs to be called when the carrier app failed to get the
        // activation code.
        void onFailure();
    }
    

ตัวอย่างการนำ LPA ไปใช้

หากต้องการเชื่อมโยงกับการใช้งาน ICarrierEuiccProvisioningService ของแอปผู้ให้บริการ LPA จะต้องคัดลอกทั้ง ICarrierEuiccProvisioningService.aidl และ IGetActivationCodeCallback.aidl ไปยังโปรเจ็กต์ของคุณ และใช้ ServiceConnection

@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
    mCarrierProvisioningService = ICarrierEuiccProvisioningService.Stub.asInterface(iBinder);
}

หลังจากเชื่อมโยงกับการใช้งาน ICarrierEuiccProvisioningService ของแอปผู้ให้บริการแล้ว LPA จะเรียก getActivationCode หรือ getActivationCodeForEid เพื่อรับรหัสเปิดใช้งานจากแอปผู้ให้บริการโดยส่งผ่านการใช้งานคลาส stub IGetActivationCodeCallback

ความแตกต่างระหว่าง getActivationCode และ getActivationCodeForEid ก็คือ getActivationCodeForEid อนุญาตให้ผู้ให้บริการผูกโปรไฟล์ไว้ล่วงหน้ากับ EID ของอุปกรณ์ก่อนที่กระบวนการดาวน์โหลดจะเริ่มต้น

void getActivationCodeFromCarrierApp() {
    IGetActivationCodeCallback.Stub callback =
            new IGetActivationCodeCallback.Stub() {
                @Override
                public void onSuccess(String activationCode) throws RemoteException {
                    // Handle the case LPA success to get activation code from a carrier app.
                }

                @Override
                public void onFailure() throws RemoteException {
                    // Handle the case LPA failed to get activation code from a carrier app.
                }
            };
    
    try {
        mCarrierProvisioningService.getActivationCode(callback);
    } catch (RemoteException e) {
        // Handle Remote Exception
    }
}

ตัวอย่างการใช้งานสำหรับแอปของผู้ให้บริการ

เพื่อให้ LPA เชื่อมโยงกับแอปผู้ให้บริการ แอปผู้ให้บริการจะต้องคัดลอกทั้ง ICarrierEuiccProvisioningService.aidl และ IGetActivationCodeCallback.aidl ไปยังโปรเจ็กต์ของคุณและประกาศบริการ ICarrierEuiccProvisioningService ในไฟล์ AndroidManifest.xml บริการจะต้องได้รับอนุญาตจากระบบ android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS เพื่อให้แน่ใจว่ามีเพียง LPA ซึ่งเป็นแอปที่มีสิทธิ์ของระบบเท่านั้นที่สามารถผูกเข้ากับบริการได้ บริการยังต้องมีตัวกรองเจตนาพร้อมกับการดำเนินการ android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE

  • AndroidManifest.xml

    <application>
      ...
      <service
          android:name=".CarrierEuiccProvisioningService"
          android:exported="true"
          android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS">
        <intent-filter>
          <action android:name="android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE"/>
        </intent-filter>
      </service>
      ...
    </application>
    

หากต้องการใช้บริการแอปผู้ให้บริการ AIDL ให้สร้างบริการ ขยายคลาส Stub และใช้เมธอด getActivationCode และ getActivationCodeForEid จากนั้น LPA จะสามารถเรียกวิธีใดวิธีหนึ่งเพื่อดึงรหัสเปิดใช้งานโปรไฟล์ได้ แอพผู้ให้บริการควรตอบสนองด้วยการเรียก IGetActivationCodeCallback#onSuccess พร้อมรหัสเปิดใช้งาน หากดึงรหัสจากเซิร์ฟเวอร์ของผู้ให้บริการได้สำเร็จ หากไม่สำเร็จ แอปผู้ให้บริการควรตอบสนองด้วย IGetActivationCodeCallback#onFailure

  • CarrierEuiccProvisioningService.java

    import android.service.euicc.ICarrierEuiccProvisioningService;
    import android.service.euicc.ICarrierEuiccProvisioningService.Stub;
    import android.service.euicc.IGetActivationCodeCallback;
    
    public class CarrierEuiccProvisioningService extends Service {
        private final ICarrierEuiccProvisioningService.Stub binder =
            new Stub() {
              @Override
              public void getActivationCode(IGetActivationCodeCallback callback) throws RemoteException {
                String activationCode = // do whatever work necessary to get an activation code (HTTP requests to carrier server, fetch from storage, etc.)
                callback.onSuccess(activationCode);
              }
    
              @Override
              public void getActivationCodeForEid(String eid, IGetActivationCodeCallback callback) throws RemoteException {
                String activationCode = // do whatever work necessary (HTTP requests, fetch from storage, etc.)
                callback.onSuccess(activationCode);
              }
          }
    }
    

การเริ่มต้น UI ของแอปผู้ให้บริการในขั้นตอนการเปิดใช้งาน LPA

บนอุปกรณ์ที่ใช้ Android 11 ขึ้นไป LPA สามารถเริ่ม UI ของแอปของผู้ให้บริการได้ สิ่งนี้มีประโยชน์เนื่องจากแอพของผู้ให้บริการอาจต้องการข้อมูลเพิ่มเติมจากผู้ใช้ก่อนที่จะส่งรหัสเปิดใช้งานให้กับ LPA ตัวอย่างเช่น ผู้ให้บริการอาจกำหนดให้ผู้ใช้เข้าสู่ระบบเพื่อเปิดใช้งานหมายเลขโทรศัพท์ของตนหรือดำเนินการบริการย้ายอื่นๆ

นี่คือกระบวนการเริ่มต้น UI ของแอปผู้ให้บริการใน LPA:

  1. LPA เปิดตัวขั้นตอนการเปิดใช้งานแอปของผู้ให้บริการโดยส่ง Intent android.service.euicc.action.START_CARRIER_ACTIVATION ไปยังแพ็คเกจแอปของผู้ให้บริการที่มีการดำเนินการ (ตัวรับแอปของผู้ให้บริการจะต้องได้รับการปกป้องในการประกาศรายการด้วย android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" เพื่อหลีกเลี่ยงการรับ Intent จากแอปที่ไม่ใช่ LPA)

    String packageName = // The carrier app's package name
    
    Intent carrierAppIntent =
        new Intent(“android.service.euicc.action.START_CARRIER_ACTIVATION”)
            .setPackage(packageName);
    
    ResolveInfo activity =
        context.getPackageManager().resolveActivity(carrierAppIntent, 0);
    
    carrierAppIntent
        .setClassName(activity.activityInfo.packageName, activity.activityInfo.name);
    
    startActivityForResult(carrierAppIntent, requestCode);
    
  2. แอปผู้ให้บริการทำงานโดยใช้ UI ของตัวเอง ตัวอย่างเช่น การเข้าสู่ระบบผู้ใช้หรือการส่งคำขอ HTTP ไปยังแบ็กเอนด์ของผู้ให้บริการ

  3. แอปผู้ให้บริการตอบสนองต่อ LPA โดยการเรียก setResult(int, Intent) และ finish()

    1. หากแอปของผู้ให้บริการตอบสนองด้วย RESULT_OK LPA จะดำเนินขั้นตอนการเปิดใช้งานต่อไป หากแอปของผู้ให้บริการกำหนดว่าผู้ใช้ควรสแกนโค้ด QR แทนที่จะปล่อยให้ LPA ผูกบริการของแอปของผู้ให้บริการ แอปของผู้ให้บริการจะตอบสนองต่อ LPA โดยใช้ setResult(int, Intent) พร้อมด้วย RESULT_OK และอินสแตนซ์ Intent ที่มี android.telephony.euicc.extra.USE_QR_SCANNER พิเศษบูลีน android.telephony.euicc.extra.USE_QR_SCANNER ตั้งค่าเป็น true จากนั้น LPA จะตรวจสอบส่วนพิเศษและเปิดใช้เครื่องสแกน QR แทนการเชื่อมโยงการใช้งาน ICarrierEuiccProvisioningService ของแอปผู้ให้บริการ
    2. หากแอปของผู้ให้บริการขัดข้องหรือตอบสนองด้วย RESULT_CANCELED (นี่คือรหัสตอบกลับเริ่มต้น) LPA จะยกเลิกขั้นตอนการเปิดใช้งาน eSIM
    3. หากแอปของผู้ให้บริการตอบสนองด้วยสิ่งอื่นที่ไม่ใช่ RESULT_OK หรือ RESULT_CANCELED LPA จะถือว่าเป็นข้อผิดพลาด

    ด้วยเหตุผลด้านความปลอดภัย LPA ไม่ควร ยอมรับรหัสเปิดใช้งานที่ให้มาในผลลัพธ์โดยตรง เพื่อให้แน่ใจว่าผู้โทรที่ไม่ใช่ LPA จะไม่สามารถรับรหัสเปิดใช้งานจากแอปของผู้ให้บริการได้

การเปิดใช้งานขั้นตอนการเปิดใช้งาน LPA ในแอปผู้ให้บริการ

ตั้งแต่ Android 11 เป็นต้นไป แอปของผู้ให้บริการจะใช้ eUICC API เพื่อเริ่ม LUI สำหรับการเปิดใช้งาน eSIM ได้ วิธีการนี้จะแสดง UI ขั้นตอนการเปิดใช้งาน eSIM ของ LPA เพื่อเปิดใช้งานโปรไฟล์ eSIM จากนั้น LPA จะส่งการถ่ายทอดเมื่อการเปิดใช้งานโปรไฟล์ eSIM เสร็จสิ้น

  1. LPA ต้องประกาศกิจกรรมรวมถึงตัวกรองเจตนาด้วยการดำเนินการ android.service.euicc.action.START_EUICC_ACTIVATION ลำดับความสำคัญของตัวกรอง Intent ควรตั้งค่าเป็นค่าที่ไม่ใช่ศูนย์ ในกรณีที่มีการใช้งานหลายอย่างบนอุปกรณ์ ตัวอย่างเช่น:

    <application>
      ...
    <activity
        android:name=".CarrierAppInitActivity"
        android:exported="true">
    
        <intent-filter android:priority="100">
            <action android:name="android.service.euicc.action.START_EUICC_ACTIVATION" />
        </intent-filter>
    </activity>
      ...
    </application>
    
  2. แอปผู้ให้บริการทำงานโดยใช้ UI ของตัวเอง ตัวอย่างเช่น การเข้าสู่ระบบผู้ใช้หรือการส่งคำขอ HTTP ไปยังแบ็กเอนด์ของผู้ให้บริการ

  3. ณ จุดนี้ แอปผู้ให้บริการจะต้องพร้อมที่จะระบุรหัสเปิดใช้งานผ่านการใช้งาน ICarrierEuiccProvisioningService แอปผู้ให้บริการเปิดตัว LPA โดยการเรียก startActivityForResult(Intent, int) ด้วยการดำเนินการ android.telephony.euicc.action.START_EUICC_ACTIVATION LPA ยังตรวจสอบ android.telephony.euicc.extra.USE_QR_SCANNER บูลีนพิเศษด้วย หากค่าเป็น true LPA จะเปิดเครื่องสแกน QR เพื่อให้ผู้ใช้สแกนโค้ด QR ของโปรไฟล์

  4. ในด้าน LPA นั้น LPA จะเชื่อมโยงกับการใช้งาน ICarrierEuiccProvisioningService ของแอปผู้ให้บริการเพื่อดึงรหัสเปิดใช้งานและดาวน์โหลดโปรไฟล์ที่เกี่ยวข้อง LPA จะแสดงองค์ประกอบ UI ที่จำเป็นทั้งหมดในระหว่างการดาวน์โหลด เช่น หน้าจอการโหลด

  5. เมื่อขั้นตอนการเปิดใช้งาน LPA เสร็จสมบูรณ์ LPA จะตอบสนองต่อแอปผู้ให้บริการด้วยโค้ดผลลัพธ์ ซึ่งแอปผู้ให้บริการจัดการใน onActivityResult(int, int, Intent)

    1. หาก LPA ดาวน์โหลดโปรไฟล์ eSIM ใหม่ได้สำเร็จ LPA จะตอบกลับด้วย RESULT_OK
    2. หากผู้ใช้ยกเลิกการเปิดใช้งานโปรไฟล์ eSIM ใน LPA ผู้ใช้จะตอบกลับด้วย RESULT_CANCELED
    3. หาก LPA ตอบสนองด้วยสิ่งอื่นที่ไม่ใช่ RESULT_OK หรือ RESULT_CANCELED แอปของผู้ให้บริการจะถือว่าสิ่งนี้เป็นข้อผิดพลาด

    ด้วยเหตุผลด้านความปลอดภัย LPA จะไม่ ยอมรับรหัสเปิดใช้งานโดยตรงในเจตนาที่ให้มา เพื่อให้แน่ใจว่าผู้โทรที่ไม่ใช่ LPA จะไม่สามารถรับรหัสเปิดใช้งานจากแอปของผู้ให้บริการได้

รองรับ eSIM หลายอัน

สำหรับอุปกรณ์ที่ใช้ Android 10 หรือสูงกว่า คลาส EuiccManager รองรับอุปกรณ์ที่มี eSIM หลายอัน อุปกรณ์ที่มี eSIM เดียวที่กำลังอัปเกรดเป็น Android 10 ไม่จำเป็นต้องแก้ไขใดๆ ในการใช้งาน LPA เนื่องจากแพลตฟอร์มจะเชื่อมโยงอินสแตนซ์ EuiccManager กับ eUICC เริ่มต้นโดยอัตโนมัติ eUICC เริ่มต้นถูกกำหนดโดยแพลตฟอร์มสำหรับอุปกรณ์ที่มีวิทยุ HAL เวอร์ชัน 1.2 หรือสูงกว่า และโดย LPA สำหรับอุปกรณ์ที่มีวิทยุ HAL เวอร์ชันต่ำกว่า 1.2

ความต้องการ

หากต้องการรองรับ eSIM หลายอัน อุปกรณ์จะต้องมี eUICC มากกว่าหนึ่งอัน ซึ่งอาจเป็น eUICC ในตัวหรือช่องใส่ซิมจริงที่สามารถใส่ eUICC แบบถอดได้

ต้องใช้ Radio HAL เวอร์ชัน 1.2 ขึ้นไปเพื่อรองรับ eSIM หลายอัน แนะนำให้ใช้ Radio HAL เวอร์ชัน 1.4 และ RadioConfig HAL เวอร์ชัน 1.2

การนำไปปฏิบัติ

หากต้องการรองรับ eSIM หลายอัน (รวมถึง eUICC แบบถอดได้หรือ SIM แบบตั้งโปรแกรมได้) LPA ต้องใช้ EuiccService ซึ่งจะได้รับ ID สล็อตที่สอดคล้องกับ ID การ์ดที่ผู้โทรให้มา

ทรัพยากร non_removable_euicc_slots ที่ระบุใน arrays.xml คืออาร์เรย์ของจำนวนเต็มที่แสดง ID สล็อตของ eUICC ในตัวของอุปกรณ์ คุณต้องระบุทรัพยากรนี้เพื่ออนุญาตให้แพลตฟอร์มพิจารณาว่า eUICC ที่แทรกไว้นั้นสามารถถอดออกได้หรือไม่

แอพผู้ให้บริการสำหรับอุปกรณ์ที่มี eSIM หลายอัน

เมื่อสร้างแอพผู้ให้บริการสำหรับอุปกรณ์ที่มี eSIM หลายอัน ให้ใช้เมธอด createForCardId ใน EuiccManager เพื่อสร้างออบเจ็กต์ EuiccManager ที่ปักหมุดไว้กับ ID การ์ดที่กำหนด รหัสการ์ดเป็นค่าจำนวนเต็มที่ระบุ UICC หรือ eUICC บนอุปกรณ์โดยไม่ซ้ำกัน

หากต้องการรับ ID การ์ดสำหรับ eUICC เริ่มต้นของอุปกรณ์ ให้ใช้เมธอด getCardIdForDefaultEuicc ใน TelephonyManager เมธอดนี้จะส่งคืน UNSUPPORTED_CARD_ID หากเวอร์ชันวิทยุ HAL ต่ำกว่า 1.2 และส่งคืน UNINITIALIZED_CARD_ID หากอุปกรณ์ไม่ได้อ่าน eUICC

คุณยังสามารถรับ ID การ์ดจาก getUiccCardsInfo และ getUiccSlotsInfo (system API) ใน TelephonyManager และ getCardId ใน SubscriptionInfo

เมื่อออบเจ็กต์ EuiccManager ได้รับการสร้างอินสแตนซ์ด้วย ID การ์ดเฉพาะ การดำเนินการทั้งหมดจะถูกส่งไปยัง eUICC ด้วย ID การ์ดนั้น หาก eUICC ไม่สามารถเข้าถึงได้ (เช่น เมื่อปิดหรือลบออก) EuiccManager จะไม่ทำงานอีกต่อไป

คุณสามารถใช้ตัวอย่างโค้ดต่อไปนี้เพื่อสร้างแอปผู้ให้บริการ

ตัวอย่างที่ 1: รับการสมัครสมาชิกที่ใช้งานอยู่และสร้างอินสแตนซ์ EuiccManager

// Get the active subscription and instantiate an EuiccManager for the eUICC which holds
// that subscription
SubscriptionManager subMan = (SubscriptionManager)
        mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
int cardId = subMan.getActiveSubscriptionInfo().getCardId();
EuiccManager euiccMan = (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE)
            .createForCardId(cardId);

ตัวอย่างที่ 2: วนซ้ำผ่าน UICC และสร้างอินสแตนซ์ EuiccManager สำหรับ eUICC แบบถอดได้

// On a device with a built-in eUICC and a removable eUICC, iterate through the UICC cards
// to instantiate an EuiccManager associated with a removable eUICC
TelephonyManager telMan = (TelephonyManager)
        mContext.getSystemService(Context.TELEPHONY_SERVICE);
List<UiccCardInfo> infos = telMan.getUiccCardsInfo();
int removableCardId = -1; // valid cardIds are 0 or greater
for (UiccCardInfo info : infos) {
    if (info.isRemovable()) {
        removableCardId = info.getCardId();
        break;
    }
}
if (removableCardId != -1) {
    EuiccManager euiccMan = (EuiccManager) mContext.getSystemService(Context.EUICC_SERVICE)
            .createForCardId(removableCardId);
}

การตรวจสอบ

AOSP ไม่ได้มาพร้อมกับการใช้งาน LPA และคุณไม่คาดว่าจะมี LPA บน Android ทุกรุ่น (โทรศัพท์บางรุ่นไม่รองรับ eSIM) ด้วยเหตุนี้จึงไม่มีกรณีทดสอบ CTS แบบ end-to-end อย่างไรก็ตาม กรณีทดสอบพื้นฐานจะพร้อมใช้งานใน AOSP เพื่อให้แน่ใจว่า eUICC API ที่เปิดเผยนั้นใช้ได้ใน Android บิลด์

คุณควรตรวจสอบให้แน่ใจว่าบิลด์ผ่านกรณีทดสอบ CTS ต่อไปนี้ (สำหรับ API สาธารณะ): /platform/cts/tests/tests/telephony/current/src/android/telephony/euicc/cts

ผู้ให้บริการที่ใช้แอปของผู้ให้บริการควรผ่านวงจรการประกันคุณภาพภายในองค์กรตามปกติ เพื่อให้แน่ใจว่าฟีเจอร์ที่นำไปใช้ทั้งหมดทำงานได้ตามที่คาดหวัง อย่างน้อยที่สุด แอพของผู้ให้บริการควรจะสามารถแสดงรายการโปรไฟล์การสมัครสมาชิกทั้งหมดที่เป็นของผู้ให้บริการรายเดียวกัน ดาวน์โหลดและติดตั้งโปรไฟล์ เปิดใช้งานบริการบนโปรไฟล์ สลับระหว่างโปรไฟล์ และลบโปรไฟล์

หากคุณกำลังสร้าง LPA ของคุณเอง คุณควรผ่านการทดสอบที่เข้มงวดกว่านี้มาก คุณควรทำงานร่วมกับผู้จำหน่ายโมเด็ม, ชิป eUICC หรือผู้จำหน่าย eSIM OS, ผู้จำหน่าย SM-DP+ และผู้ให้บริการ เพื่อแก้ไขปัญหาและรับรองการทำงานร่วมกันของ LPA ของคุณภายในสถาปัตยกรรม RSP การทดสอบด้วยตนเองในปริมาณมากเป็นสิ่งที่หลีกเลี่ยงไม่ได้ เพื่อความครอบคลุมการทดสอบที่ดีที่สุด คุณควรปฏิบัติตาม แผนการทดสอบ GSMA SGP.23 RSP