טכנולוגיית ה-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.
איור 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. התהליך הכללי מתואר בהמשך:
- המפעיל חותם על ה-APK של אפליקציית הספק. ה APKsigner הכלי מצרף את האישור של המפתח הציבורי ל-APK.
אופרטור/SM-DP+ מכין פרופיל ואת המטא-נתונים שלו, כולל ARF שכולל:
- חתימה (SHA-1 או SHA-256) של אישור המפתח הציבורי של אפליקציית הספק (שדה חובה)
- שם החבילה של אפליקציית הספק (מומלץ מאוד)
אפליקציית הספק תנסה לבצע פעולת eUICC באמצעות ה-API
EuiccManager
.פלטפורמת Android מאמתת גיבוב SHA-1 או SHA-256 של אפליקציית הקריאה תואם לחתימה של האישור שהתקבל ARF של פרופיל היעד. אם שם החבילה של אפליקציית הספק כלול ה-ARF, הוא חייב גם להתאים לשם החבילה של אפליקציית המתקשר.
לאחר אימות החתימה ושם החבילה (אם הוא כלול), הרשאת ספק מוענקת לאפליקציית הקריאה החוזרת דרך פרופיל היעד.
מכיוון שמטא-נתונים של פרופיל יכולים להיות זמינים מחוץ לפרופיל עצמו (כך ערוץ 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 של מערכת וניתן לקרוא אותו רק למי שיש לו הרשאות מערכת
באפליקציות.
איור 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:
ה-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);
אפליקציית הספק פועלת באמצעות ממשק משתמש משלה. לדוגמה, רישום ביומן במשתמש או לשלוח בקשות HTTP לקצה העורפי של הספק.
אפליקציית הספק מגיבה ל-LPA בהתקשרות אל
setResult(int, Intent)
ו-finish()
.- אם האפליקציה של הספק מגיבה עם
RESULT_OK
, ה-LPA ממשיך את תהליך ההפעלה. אם אפליקציית הספק קובעת המשתמש צריך לסרוק קוד QR במקום לאפשר ל-LPA לקשר את הספק השירות של האפליקציה, אפליקציית הספק מגיבה ל-LPA באמצעותsetResult(int, Intent)
עםRESULT_OK
ומכונהIntent
שמכיל את תוספת הבוליאניתandroid.telephony.euicc.extra.USE_QR_SCANNER
הוגדר לערךtrue
. ה-LPA לאחר מכן בודק את התוספת ומפעיל את סורק קודי ה-QR במקום לקשר את הסורק הטמעתICarrierEuiccProvisioningService
של אפליקציית הספק. - אם אפליקציית הספק קורסת או מגיבה עם
RESULT_CANCELED
(זה קוד התגובה שמוגדר כברירת מחדל), ה-LPA מבטל את ה-eSIM תהליך ההפעלה. - אם התשובה של אפליקציית הספק היא לא
RESULT_OK
אוRESULT_CANCELED
, במכשיר ה-LPA מתייחסים לכך כשגיאה.
מטעמי אבטחה, ה-LPA לא אמור לקבל ישירות את קוד ההפעלה שסופק בכוונת התוצאה, כדי להבטיח המתקשרים לא יכולים לקבל קוד הפעלה מהאפליקציה של ספק הסלולר.
- אם האפליקציה של הספק מגיבה עם
הפעלת תהליך ההפעלה של LPA באפליקציה של ספק
החל מ-Android 11, אפליקציות ספק יכולות להשתמש בממשקי API של eUICC כדי להתחיל LUI ל-eSIM הפעלה. השיטה הזו מציגה את ממשק המשתמש של תהליך ההפעלה של eSIM ב-LPA כדי להפעיל פרופיל ה-eSIM. ה-LPA שולח שידור כשפרופיל ה-eSIM ההגדרה תסתיים.
בעל התוכן הדיגיטלי (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>
אפליקציית הספק פועלת באמצעות ממשק משתמש משלה. לדוגמה, רישום ביומן במשתמש או לשלוח בקשות HTTP לקצה העורפי של הספק.
בשלב הזה, אפליקציית הספק צריכה להיות מוכנה לספק הפעלה באמצעות ההטמעה של
ICarrierEuiccProvisioningService
. ספק הסלולר משיקה את ה-LPA באמצעות התקשרותstartActivityForResult(Intent, int)
עםandroid.telephony.euicc.action.START_EUICC_ACTIVATION
פעולה. ה-LPA בודק גם את התוספת הבוליאניתandroid.telephony.euicc.extra.USE_QR_SCANNER
אם הערך הואtrue
, LPA מפעיל את סורק ה-QR כדי לאפשר למשתמש לסרוק את קוד ה-QR של הפרופיל.בצד ה-LPA, ה-LPA מקשר הטמעת
ICarrierEuiccProvisioningService
לאחזור ההפעלה ומורידים את הפרופיל המתאים. מלאי שטחי הפרסום ל-LPA מציג את כל מה שצריך רכיבי ממשק המשתמש במהלך ההורדה, כמו מסך טעינה.לאחר השלמת תהליך ההפעלה של ה-LPA, הבעלים של ערוץ LPA מגיב אפליקציה של ספק עם קוד תוצאה, שאפליקציית הספק מטפלת בו
onActivityResult(int, int, Intent)
- אם ה-LPA מצליח להוריד את פרופיל ה-eSIM החדש,
עם התשובה
RESULT_OK
. - אם המשתמש מבטל את ההפעלה של פרופיל ה-eSIM ב-LPA,
עם התשובה
RESULT_CANCELED
. - אם תגובה של ה-LPA היא לא
RESULT_OK
, אוRESULT_CANCELED
, אפליקציית הספק מתייחסת לזה כשגיאה.
מטעמי אבטחה, ה-LPA לא מקבל קוד הפעלה ישירות מתוך הכוונה שסופקה כדי לוודא שמתקשרים שלא קשורים אל LPA לא יוכלו לקבל את קוד ההפעלה מאפליקציית הספק.
- אם ה-LPA מצליח להוריד את פרופיל ה-eSIM החדש,
עם התשובה
תמיכה בכמה כרטיסי 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 תוכנית בדיקה.