ติดตั้งใช้งาน eSIM

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

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

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

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

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

EuiccManager

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

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

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

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

// 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 และตัวอย่างโค้ดทั้งหมดได้ที่ API ของ eUICC

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

ในบางกรณี ระบบอาจดำเนินการกับ 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 ของอุปกรณ์ได้ และควรอนุญาตให้แอปของผู้ให้บริการแต่ละรายเข้าถึงได้เฉพาะโปรไฟล์ที่เป็นของผู้ให้บริการรายนั้น เช่น ผู้ให้บริการ ก ไม่ควรดาวน์โหลด เปิดใช้ หรือปิดใช้โปรไฟล์ที่เป็นของผู้ให้บริการ ข ได้

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 และ SM-DP+ ต้องรองรับแท็กที่เป็นกรรมสิทธิ์ BF76 ในข้อมูลเมตาของโปรไฟล์ เนื้อหาของแท็กควรเป็นกฎสิทธิ์ของผู้ให้บริการขนส่งเดียวกันกับที่แอปเพล็ตกฎการเข้าถึง (ARA) ส่งคืน ซึ่งกำหนดไว้ใน สิทธิ์ของผู้ให้บริการขนส่งใน UICC

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 ในชิป eUICC ต้องรองรับ GSMA RSP (การจัดสรรซิมระยะไกล) 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

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

    • ผู้ให้บริการหรือ OEM ต้องใช้ IRadioSim.getAllowedCarriers() HAL API

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

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

สำหรับอุปกรณ์ที่ใช้ Android 10 ต้องกำหนดอาร์เรย์รหัสช่อง 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

EuiccService

LPA ประกอบด้วยคอมโพเนนต์ 2 อย่างที่แยกจากกัน (อาจติดตั้งทั้ง 2 อย่างใน APK เดียวกันได้) ได้แก่ แบ็กเอนด์ของ LPA และ UI ของ LPA หรือ LUI

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

<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 ที่ใช้งานอยู่และโต้ตอบกับ 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 และลำดับความสำคัญที่ไม่ใช่ 0 ระบบจะใช้ตรรกะที่คล้ายกันในการเลือกการติดตั้งใช้งานสำหรับกิจกรรมเหล่านี้เช่นเดียวกับการเลือกการติดตั้งใช้งานของ 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 (เช่น APK ที่ใช้ EuiccService และ APK ที่มีกิจกรรม LUI) เป็นตัวเลือกการออกแบบ

EuiccCardManager

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

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

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

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

เช่นเดียวกับ EuiccManager ในการใช้ API ของ EuiccCardManager 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 ซึ่งจะเรียกใช้ Callback Executorออบเจ็กต์นี้อาจทำงานใน เธรดเดียวหรือในกลุ่มเธรดที่คุณเลือก

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

กำหนดบริการจัดสรร eUICC ของผู้ให้บริการขนส่ง

แอป LPA และแอปของผู้ให้บริการจะสื่อสารกันผ่านอินเทอร์เฟซ AIDL 2 รายการ ICarrierEuiccProvisioningService และ IGetActivationCodeCallback แอปของผู้ให้บริการ ต้องใช้ICarrierEuiccProvisioningServiceอินเทอร์เฟซและ เปิดเผยในประกาศในไฟล์ Manifest 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 ซึ่งเป็นแอปที่มีสิทธิ์ของระบบเท่านั้นที่เชื่อมโยงกับบริการได้ บริการต้องมีตัวกรอง Intent ที่มี การดำเนินการ 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 ไปยัง แพ็กเกจแอปผู้ให้บริการที่มีการดำเนินการ (ตัวรับแอปของผู้ให้บริการต้อง ได้รับการปกป้องในการประกาศไฟล์ Manifest ด้วย 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 จะดำเนินการตามขั้นตอนการเปิดใช้งานต่อไป หากแอปของผู้ให้บริการพิจารณาว่าผู้ใช้ควรสแกนคิวอาร์โค้ดแทนการอนุญาตให้ LPA ผูกบริการของแอปของผู้ให้บริการ แอปของผู้ให้บริการจะตอบกลับ LPA โดยใช้ setResult(int, Intent) พร้อม RESULT_OK และอินสแตนซ์ Intent ที่มีส่วนขยายบูลีน android.telephony.euicc.extra.USE_QR_SCANNER ซึ่งตั้งค่าเป็น true จากนั้น LPA จะตรวจสอบส่วนเสริมและเปิดใช้เครื่องสแกน QR แทนการเชื่อมโยง การติดตั้งใช้งาน ICarrierEuiccProvisioningService ของแอปผู้ให้บริการ
    2. หากแอปของผู้ให้บริการขัดข้องหรือตอบกลับด้วย RESULT_CANCELED (นี่คือรหัสการตอบกลับเริ่มต้น) LPA จะยกเลิกขั้นตอนการเปิดใช้งาน eSIM
    3. หากแอปของผู้ให้บริการตอบกลับด้วยข้อความอื่นที่ไม่ใช่ RESULT_OK หรือ RESULT_CANCELED LPA จะถือว่าเป็นการเกิดข้อผิดพลาด

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

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

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

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

    <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 จะเปิดตัวสแกนคิวอาร์เพื่อให้ผู้ใช้สแกนคิวอาร์โค้ดโปรไฟล์

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

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

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

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

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

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

ข้อกำหนด

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

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

การใช้งาน

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

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

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

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

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

นอกจากนี้ คุณยังดูรหัสบัตรได้จาก getUiccCardsInfo และ getUiccSlotsInfo (API ของระบบ) ใน TelephonyManager รวมถึง getCardId ใน SubscriptionInfo

เมื่อมีการสร้างอินสแตนซ์ของออบเจ็กต์ EuiccManager ด้วยรหัสการ์ดที่เฉพาะเจาะจง ระบบจะส่งการดำเนินการทั้งหมดไปยัง eUICC ที่มีรหัสการ์ดนั้น หาก 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 แบบต้นทางถึงปลายทาง อย่างไรก็ตาม กรณีทดสอบพื้นฐาน พร้อมใช้งานใน AOSP เพื่อให้มั่นใจว่า API ของ eUICC ที่เปิดเผย ใช้ได้ในการสร้าง Android

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

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

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