ใช้งาน eSIM

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

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

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

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

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

ในกรณีเหล่านี้ ระบบจะเรียกใช้การติดต่อกลับของผู้โทรด้วย EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR Callback 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

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

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

ข้อกำหนดเกี่ยวกับฮาร์ดแวร์/โมเด็ม

LPA และระบบปฏิบัติการ eSIM บนชิป eUICC ต้องรองรับ GSMA RSP (การจัดเตรียม SIM จากระยะไกล) 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 หรือ LUI ของ LPA

หากต้องการใช้แบ็กเอนด์ LPA คุณต้องขยาย EuiccService และประกาศบริการนี้ในไฟล์ Manifest บริการต้องกำหนดสิทธิ์android.permission.BIND_EUICC_SERVICEของระบบเพื่อให้มั่นใจว่ามีเพียงระบบเท่านั้นที่เชื่อมโยงกับบริการได้ บริการต้องมีตัวกรอง Intent ที่มีการดำเนินการ android.service.euicc.EuiccService ด้วย ควรตั้งค่าลำดับความสำคัญของตัวกรอง Intent เป็นค่าที่ไม่ใช่ 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สิทธิ์ของระบบ เช่นเดียวกับบริการ แต่ละรายการควรมีตัวกรองความตั้งใจที่มีการดำเนินการที่เหมาะสม หมวดหมู่ 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 (เช่น แบบที่ใช้ EuiccService และ APK ที่มีกิจกรรม LUI) คือทางเลือกในการออกแบบ

EuiccCardManager

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

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