הטמעת eSIM

טכנולוגיית ה-SIM המוטמע (eSIM או eUICC) מאפשרת למשתמשים בנייד להוריד פרופיל ספק ולהפעיל שירות של ספק ללא צורך כרטיס SIM פיזי. זה מפרט גלובלי שמבוסס על חוק ה-GSMA, הקצאת כרטיס SIM מרחוק (RSP) של כל מכשיר נייד. מתחילים ב-Android 9, מסגרת Android מספקת ממשקי API סטנדרטיים עבור גישה ל-eSIM וניהול פרופילי המינויים ב-eSIM. ה-eUICC האלה ממשקי API מאפשרים לצדדים שלישיים לפתח אפליקציות ספק ופרופיל מקומי משלהם עוזרים דיגיטליים (LPA) במכשירי Android עם תמיכה ב-eSIM.

ה-LPA היא אפליקציית מערכת עצמאית שצריך לכלול קובץ אימג' של גרסת ה-build של Android. ניהול הפרופילים ב-eSIM מתבצע בדרך כלל על ידי ה-LPA, כי הוא משמש כגשר בין ה-SM-DP+ (שירות מרוחק מכינה, מאחסנת ושולחת חבילות פרופיל למכשירים) ואת שבב eUICC. ה-APK של ה-LPA יכול לכלול רכיב של ממשק משתמש, שנקרא LPA UI או LUI, כדי לספק למשתמש הקצה מקום מרכזי לניהול כל המינויים המוטמעים פרופילים. מערכת Android מגלה באופן אוטומטי ומתחברת אל המוצרים הטובים ביותר זמינה ב-LPA, ותנתב את כל פעולות ה-eUICC דרך מכונת LPA.

ארכיטקטורה פשוטה יותר להקצאת כרטיסי SIM מרוחקים (RSP)

איור 1. ארכיטקטורת RSP פשוטה

מפעילי רשתות סלולריות שרוצים ליצור אפליקציה לספקי הסלולר צריכים לבדוק את ממשקי ה-API EuiccManager, שמאפשר לבצע פעולות ניהול ברמה גבוהה של פרופילים, downloadSubscription(), switchToSubscription() וגם deleteSubscription().

אם את/ה יצרנית ציוד מקורי (OEM) של מכשיר וברצונך ליצור אפליקציה משלך של מערכת LPA, עליך להאריך EuiccService ל-framework של Android כדי להתחבר לשירותי ה-LPA. בנוסף, צריך להשתמש בממשקי ה-API EuiccCardManager שמספקות פונקציות ES10x שמבוססות על GSMA RSP גרסה 2.0. הפונקציות האלה משמשות לביצוע פקודות לצ'יפ eUICC, prepareDownload(), loadBoundProfilePackage(), retrieveNotificationList() ו-resetMemory().

ממשקי ה-API ב- EuiccManager נדרשת אפליקציית LPA שהוטמעה באופן תקין כדי שהקוראים EuiccCardManager ממשקי API חייבים להיות LPA. המדיניות הזו נאכפת על ידי מסגרת Android.

מכשירים עם Android מגרסה 10 ואילך יכולים לתמוך מכשירים שיש בהם כמה כרטיסי eSIM. מידע נוסף זמין במאמר הבא: תמיכה במספר כרטיסי eSIM.

יצירת אפליקציה של ספק

ממשקי ה-API של eUICC ב-Android 9 מאפשרים למפעילי רשתות סלולריות ליצור אפליקציות במיתוג של הספק כדי לנהל פרופילים ישירות. זה כולל הורדה ומחיקה של פרופילים של מינויים בבעלות הספק, וגם מעבר לפרופיל בבעלות ספק.

מנהל EuiccManager

EuiccManager הוא נקודת הכניסה העיקרית שבה אפליקציות יוכלו לקיים אינטראקציה עם אל"א. ההרשאה הזו כוללת אפליקציות ספק שמורידות, מוחקים ועוברות אל מינויים בבעלות הספק. זה כולל גם את אפליקציית המערכת LUI, מספק מיקום מרכזי או ממשק משתמש מרכזי לניהול כל המינויים המוטמעים, וגם יכולה להיות אפליקציה נפרדת מהאפליקציה שמספקת את 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 קריאות חוזרות (callback) – התהליך עשוי להימשך שניות או אפילו דקות. PendingIntent נשלח עם קוד תוצאה ב EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_, שמספק קודי שגיאה בהגדרת ה-framework, וגם קוד תוצאה מפורט ושרירותי מופץ מה-LPA בתור EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, מה שמאפשר אפליקציית הספק למעקב לצורכי רישום ביומן או ניפוי באגים. PendingIntent הקריאה החוזרת (callback) חייבת להיות 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 ודוגמאות לקודים, אפשר לעיין בכתובת ממשקי API של eUICC.

שגיאות שניתנות לפתרון

יש מקרים שבהם המערכת לא יכולה להשלים את פעולת ה-eSIM אבל המשתמש יכול לפתור את השגיאה. לדוגמה, downloadSubscription. עלול להיכשל אם המטא-נתונים של הפרופיל מראים שקוד אישור של ספק הוא שדה חובה. לחלופין, אם אפליקציית הספק כוללת ספק, יכול להיות ששירות switchToSubscription ייכשל הרשאות בפרופיל היעד (כלומר, הספק הוא הבעלים של הפרופיל), אבל אין הרשאות ספק בפרופיל שמופעל כרגע, ולכן נדרשת הסכמה מהמשתמשים.

במקרים כאלה, תתבצע שיחה חוזרת של המתקשר עם EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR הקריאה החוזרת (callback) Intent מכיל תוספות פנימיות, כך שהמתקשר מעביר אותו אל EuiccManager#startResolutionActivity, שאפשר לבקש פתרון דרך LUI. שימוש בקוד האישור עבור דוגמה שוב, EuiccManager#startResolutionActivity מפעיל מסך LUI שמאפשר למשתמש להזין קוד אישור; לאחר הזנת הקוד, פעולת ההורדה תמשיך. בגישה הזאת מספקת לאפליקציית הספק שליטה מלאה על הזמנים שבהם ממשק המשתמש מוצג, אבל ל-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 באמצעות ה-API EuiccManager.

  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), והם חייבים להיות מושכים את ממשקי ה-API של Android Euicc. בקטעים הבאים יש סקירה כללית קצרה של יצירה של אפליקציית LPA ושילוב שלה עם מערכת Android.

דרישות חומרה/מודם

ה-LPA וה-eSIM שבשבב ה-eUICC חייבים לתמוך לפחות ב-GSMA RSP (מרחוק הקצאת כרטיס SIM) גרסה 2.0 או גרסה 2.2. מומלץ להשתמש גם ב-SM-DP+ וב-SM-DS שיש להם גרסת RSP תואמת. למידע מפורט על ארכיטקטורת RSP, ראו GSMA SGP.21 RSP Architecture Specification.

בנוסף, כדי לשלב אותו עם ממשקי ה-API של eUICC ב-Android 9, המודם של המכשיר צריך לשלוח יכולות מסוף עם תמיכה ביכולות eUICC באמצעות קידוד (ניהול פרופילים מקומי הורדת הפרופיל). כמו כן, צריך להטמיע את השיטות הבאות:

  • IRadio HAL v1.1: setSimPower
  • IRadio HAL גרסה 1.2: getIccCardStatus

  • IRadioConfig HAL גרסה 1.0: getSimSlotsStatus

  • IRadioConfig AIDL גרסה 1.0: getAllowedCarriers

    ה-LPA של Google צריך לדעת את סטטוס הנעילה של הספק כדי לאפשר הורדה או העברה של eSIM רק לספק המורשה. אחרת, המשתמשים עלולים בסופו של דבר להוריד ולהעביר כרטיס SIM, ובהמשך יבינו שהמכשיר נעול על ידי ספק אחר.

    • ספקים או יצרני ציוד מקורי חייבים להטמיע את ממשק ה-API של IRadioSim.getAllowedCarriers()HAL.

    • הספק RIL / מודם יאכלס את סטטוס הנעילה ואת מזהה הספק של הספק שאליו המכשיר נעול כחלק מ-IRadioSimResponse.getAllowedCarriersResponse()HAL API.

המודם אמור לזהות את ה-eSIM כשפרופיל ההפעלה שמוגדר כברירת מחדל מופעל בתור כרטיס SIM תקין ולהשאיר את הפעלת ה-SIM במצב מופעל.

במכשירים עם 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 מורכב משני רכיבים נפרדים (אפשר להטמיע את שניהם באותו אופן APK): הקצה העורפי של ה-LPA, וממשק המשתמש של LPA או LUI.

כדי להטמיע את הקצה העורפי של ה-LPA, צריך להאריך EuiccService ולהצהיר על השירות הזה בקובץ המניפסט. השירות חייב לכלול את הפרטים הרשאת מערכת android.permission.BIND_EUICC_SERVICE כדי לוודא שרק שהמערכת יכולה לקשר אליו. השירות חייב לכלול גם מסנן Intent עם את הפעולה android.service.euicc.EuiccService. העדיפות של הכוונה יש להגדיר את המסנן לערך שאינו אפס במקרה שכמה יישומים יש במכשיר. לדוגמה:

<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>

באופן פנימי, ה-framework של Android קובע את ה-LPA הפעיל ומקיים אינטראקציה עם אותו כנדרש כדי לתמוך בממשקי ה-API של Android eUICC. נשלחה שאילתה ל-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>

זה רומז על כך שממשק המשתמש שמטמיע את המסכים האלה יכול להגיע ה-APK מהאפליקציה שמוטמעת EuiccService האם יש לך APK יחיד או כמה חבילות APK (לדוגמה, אפליקציה שמטמיעה העיצוב של EuiccService וגם אתר שמספק פעילויות LUI הוא בחירה.

EuiccCardManager

EuiccCardManager הוא הממשק לתקשורת עם צ'יפ ה-eSIM. הוא מספק פונקציות ES10 (כפי שמתואר במפרט GSMA RSP) ומטפל ופקודות APDU ברמה נמוכה של בקשה/תשובה, וכן ניתוח ASN.1. EuiccCardManager הוא ממשק API של מערכת וניתן לקרוא אותו רק למי שיש לו הרשאות מערכת באפליקציות.

אפליקציות של ספקים, ממשקי API של LPA ו-Euicc API

איור 2. גם אפליקציית הספק וגם ספק ה-LPA משתמשים בממשקי API של Euicc API

ממשקי ה-API של פעולת הפרופיל דרך EuiccCardManager מחייבים את מבצע הקריאה החוזרת אל"ה. המדיניות הזו נאכפת על ידי מסגרת Android. כלומר, מבצע הקריאה החוזרת יצטרך להרחיב את EuiccService ולקבל הצהרה בקובץ המניפסט, כפי שמתואר ב בקטעים הקודמים.

בדומה ל-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 ייעודי אחר גרפי. כשמשתמשים בממשקי API של EuiccCardManager, מבצע הקריאה החוזרת (LPA) צריך לספק קוד גישה Executor את האובייקט שדרכו מתבצעת הקריאה החוזרת. אובייקט 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 וה-LPA יכול לשלוט בכל התהליך של ממשק המשתמש, כלומר אף ממשק משתמש של אפליקציית ספק מוצגת. הגישה הזאת עוקפת את בדיקת התג BF76, ומפעילי רשת לא תצטרכו להטמיע את כל התהליך של ממשק המשתמש להפעלת ה-eSIM, כולל הורדה של פרופיל 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 באפליקציית הספק, חובה להעתיק גם את ICarrierEuiccProvisioningService.aidl וגם את ה-LPA 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);
              }
          }
    }
    

צריך להפעיל את ממשק המשתמש של האפליקציה של הספק בתהליך ההפעלה של ה-LPA

במכשירים עם Android מגרסה 11 ואילך, ערוץ LPA יכול הפעלת ממשק משתמש של אפליקציית ספק. האפשרות הזו שימושית כי אפליקציית ספק עשויה לדרוש מידע נוסף לפני שהוא מספק קוד הפעלה ל-LPA. לדוגמה, ספקים לדרוש מהמשתמשים להתחבר כדי להפעיל את מספרי הטלפון שלהם או לבצע ניוד מסוגים אחרים שירותים שונים.

זה התהליך להפעלת ממשק משתמש של אפליקציית ספק ב-LPA:

  1. ה-LPA מפעיל את תהליך ההפעלה של אפליקציית הספק על ידי שליחת Intent של android.service.euicc.action.START_CARRIER_ACTIVATION חבילת האפליקציה של הספק שמכילה את הפעולה. (מקבל האפליקציות דרך ספק הסלולר צריך להיות מוגן בהצהרת המניפסט באמצעות android:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS" עד להימנע מקבלת כוונות מאפליקציות שאינן 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. אפליקציית הספק פועלת באמצעות ממשק משתמש משלה. לדוגמה, רישום ביומן במשתמש או לשלוח בקשות 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 הוגדר לערך true. ה-LPA לאחר מכן בודק את התוספת ומפעיל את סורק קודי ה-QR במקום לקשר את הסורק הטמעת ICarrierEuiccProvisioningService של אפליקציית הספק.
    2. אם אפליקציית הספק קורסת או מגיבה עם RESULT_CANCELED (זה קוד התגובה שמוגדר כברירת מחדל), ה-LPA מבטל את ה-eSIM תהליך ההפעלה.
    3. אם התשובה של אפליקציית הספק היא לא RESULT_OK או RESULT_CANCELED, במכשיר ה-LPA מתייחסים לכך כשגיאה.

    מטעמי אבטחה, ה-LPA לא אמור לקבל ישירות את קוד ההפעלה שסופק בכוונת התוצאה, כדי להבטיח המתקשרים לא יכולים לקבל קוד הפעלה מהאפליקציה של ספק הסלולר.

הפעלת תהליך ההפעלה של LPA באפליקציה של ספק

החל מ-Android 11, אפליקציות ספק יכולות להשתמש בממשקי API של eUICC כדי להתחיל LUI ל-eSIM הפעלה. השיטה הזו מציגה את ממשק המשתמש של תהליך ההפעלה של eSIM ב-LPA כדי להפעיל פרופיל ה-eSIM. ה-LPA שולח שידור כשפרופיל ה-eSIM ההגדרה תסתיים.

  1. בעל התוכן הדיגיטלי (LPA) חייב להצהיר על פעילות שכוללת מסנן Intent עם פעולה אחת (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. אפליקציית הספק פועלת באמצעות ממשק משתמש משלה. לדוגמה, רישום ביומן במשתמש או לשלוח בקשות 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 מציג את כל מה שצריך רכיבי ממשק המשתמש במהלך ההורדה, כמו מסך טעינה.

  5. לאחר השלמת תהליך ההפעלה של ה-LPA, הבעלים של ערוץ LPA מגיב אפליקציה של ספק עם קוד תוצאה, שאפליקציית הספק מטפלת בו onActivityResult(int, int, Intent)

    1. אם ה-LPA מצליח להוריד את פרופיל ה-eSIM החדש, עם התשובה RESULT_OK.
    2. אם המשתמש מבטל את ההפעלה של פרופיל ה-eSIM ב-LPA, עם התשובה RESULT_CANCELED.
    3. אם תגובה של ה-LPA היא לא RESULT_OK, או RESULT_CANCELED, אפליקציית הספק מתייחסת לזה כשגיאה.

    מטעמי אבטחה, ה-LPA לא מקבל קוד הפעלה ישירות מתוך הכוונה שסופקה כדי לוודא שמתקשרים שלא קשורים אל LPA לא יוכלו לקבל את קוד ההפעלה מאפליקציית הספק.

תמיכה בכמה כרטיסי eSIM

במכשירים עם Android מגרסה 10 ואילך, ההגדרות הכיתה של EuiccManager תומכת במכשירים עם כמה כרטיסי eSIM. מכשירים עם eSIM יחיד שמשדרגים 10 Android לא מצריכות שינוי כלשהו בהטמעה של מודעות ה-LPA כפלטפורמה. משייך באופן אוטומטי את המכונה EuiccManager ל-eUICC שמוגדר כברירת מחדל. ברירת המחדל של eUICC נקבעת על ידי הפלטפורמה למכשירים עם גרסת HAL של רדיו. 1.2 ואילך ועל ידי ה-LPA במכשירים עם גרסאות HAL ברדיו שנמוכות מ- 1.2.

הדרישות

כדי לתמוך בכמה כרטיסי eSIM, במכשיר צריך להיות יותר מכרטיס eUICC אחד, להיות eUICC מובנה או חריץ פיזי ל-SIM שבו ניתן להציב מפתחות eUICC נשלפים. נוסף.

כדי לתמוך בכמה כרטיסי eSIM נדרשת רדיו HAL מגרסה 1.2 ואילך. ציוד רדיו עם HAL מומלץ להשתמש בגרסה 1.4 ובגרסה 1.2 של RadioConfig HAL.

הטמעה

כדי לתמוך בכמה כרטיסי 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 זמין בכל גרסאות ה-build של Android (לא כל טלפון תומך ב-eSIM). עבור ולכן אין מקרי בדיקות CTS מקצה לקצה. אבל מקרי בדיקה בסיסיים זמינות ב-AOSP כדי לוודא שממשקי ה-API של eUICC חשופים תקפים בגרסאות build של Android.

צריך לוודא שגרסאות ה-build עוברות את מקרי הבדיקה הבאים של 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 תוכנית בדיקה.