فناوری سیمکارت جاسازیشده (eSIM یا eUICC) به کاربران تلفن همراه این امکان را میدهد تا بدون داشتن سیمکارت فیزیکی، نمایه شرکت مخابراتی را دانلود کرده و خدمات شرکت مخابراتی را فعال کنند. این یک مشخصات جهانی است که توسط GSMA هدایت می شود و تهیه سیم کارت از راه دور (RSP) را برای هر دستگاه تلفن همراه ممکن می کند. با شروع Android 9، چارچوب Android API های استانداردی را برای دسترسی به eSIM و مدیریت پروفایل های اشتراک در eSIM ارائه می دهد. این APIهای eUICC به اشخاص ثالث امکان میدهند تا برنامههای شرکت مخابراتی و دستیاران نمایه محلی (LPA) خود را در دستگاههای اندرویدی دارای سیمکارت فعال توسعه دهند.
LPA یک برنامه سیستمی مستقل است که باید در تصویر ساخت اندروید گنجانده شود. مدیریت پروفایلهای روی eSIM عموماً توسط LPA انجام میشود، زیرا بهعنوان پلی بین SM-DP+ (سرویس راه دور که بستههای پروفایل را آماده میکند، ذخیره میکند و به دستگاهها تحویل میدهد) و تراشه eUICC عمل میکند. LPA APK میتواند به صورت اختیاری شامل یک مؤلفه رابط کاربری به نام LPA UI یا LUI باشد تا مکانی مرکزی برای کاربر نهایی برای مدیریت تمام پروفایلهای اشتراک تعبیهشده فراهم کند. چارچوب Android به طور خودکار بهترین LPA موجود را کشف کرده و به آن متصل می شود و تمام عملیات eUICC را از طریق یک نمونه LPA هدایت می کند.
شکل 1. معماری RSP ساده شده
اپراتورهای شبکه تلفن همراه که علاقه مند به ایجاد یک برنامه حامل هستند، باید به APIها در EuiccManager
نگاه کنند، که عملیات مدیریت نمایه سطح بالا مانند downloadSubscription()
، switchToSubscription()
و deleteSubscription()
ارائه می دهد.
اگر یک OEM دستگاه هستید که علاقه مند به ایجاد برنامه سیستم LPA خود هستید، باید EuiccService
را برای چارچوب Android گسترش دهید تا به خدمات LPA خود متصل شوید. علاوه بر این، باید از APIها در EuiccCardManager
استفاده کنید که توابع ES10x را بر اساس GSMA RSP v2.0 ارائه میکنند. از این توابع برای صدور دستورات به تراشه eUICC استفاده می شود، مانند prepareDownload()
، loadBoundProfilePackage()
retrieveNotificationList()
و resetMemory()
.
APIهای موجود در EuiccManager
برای عملکرد به یک برنامه LPA به درستی پیادهسازی شده نیاز دارند و تماسگیرنده APIهای EuiccCardManager
باید LPA باشد. این توسط چارچوب Android اعمال می شود.
دستگاههای دارای Android 10 یا بالاتر میتوانند از دستگاههایی با چندین eSIM پشتیبانی کنند. برای اطلاعات بیشتر، به پشتیبانی از چندین eSIM مراجعه کنید.
یک برنامه حامل بسازید
APIهای eUICC در Android 9 این امکان را برای اپراتورهای شبکه تلفن همراه ایجاد میکنند تا اپلیکیشنهایی با نام تجاری شرکت مخابراتی برای مدیریت مستقیم نمایههای خود ایجاد کنند. این شامل دانلود و حذف نمایههای اشتراک متعلق به شرکت مخابراتی و همچنین تغییر به نمایه متعلق به شرکت مخابراتی است.
EuiccManager
EuiccManager
نقطه ورود اصلی برنامه ها برای تعامل با LPA است. این شامل برنامههای شرکت مخابراتی میشود که دانلود، حذف و به اشتراکهای متعلق به شرکت مخابراتی تغییر میدهند. این همچنین شامل برنامه سیستم LUI میشود که یک مکان مرکزی/UI برای مدیریت همه اشتراکهای تعبیهشده ارائه میدهد و میتواند یک برنامه مجزا از برنامهای باشد که EuiccService
ارائه میدهد.
برای استفاده از APIهای عمومی، یک برنامه حامل ابتدا باید نمونه EuiccManager
را از طریق Context#getSystemService
دریافت کند:
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
قبل از انجام هرگونه عملیات eSIM، باید بررسی کنید که آیا eSIM در دستگاه پشتیبانی می شود یا خیر. اگر ویژگی android.hardware.telephony.euicc
تعریف شده باشد و بسته LPA وجود داشته باشد EuiccManager#isEnabled()
عموماً true
را برمیگرداند.
if (mgr == null || !mgr.isEnabled()) {
return;
}
برای دریافت اطلاعات در مورد سخت افزار eUICC و نسخه eSIM OS:
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
بسیاری از APIها، مانند downloadSubscription()
و switchToSubscription()
از تماسهای PendingIntent
استفاده میکنند زیرا ممکن است چند ثانیه یا حتی چند دقیقه طول بکشد. PendingIntent
با یک کد نتیجه در فضای EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_
ارسال میشود، که کدهای خطای تعریفشده از چارچوب را ارائه میکند، و همچنین یک کد نتیجه دلخواه با جزئیات منتشر شده از LPA بهعنوان EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE
، اجازه میدهد تا برنامهها را برای ردیابی اهداف/bugger.de. پاسخ تماس PendingIntent
باید BroadcastReceiver
باشد.
برای دانلود یک اشتراک قابل دانلود (که از یک کد فعال سازی یا یک کد QR ایجاد شده است):
// Register receiver.
static final String ACTION_DOWNLOAD_SUBSCRIPTION = "download_subscription";
static final String LPA_DECLARED_PERMISSION
= "com.your.company.lpa.permission.BROADCAST";
BroadcastReceiver receiver =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (!action.equals(intent.getAction())) {
return;
}
resultCode = getResultCode();
detailedCode = intent.getIntExtra(
EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
0 /* defaultValue*/);
// If the result code is a resolvable error, call startResolutionActivity
if (resultCode == EuiccManager.EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR) {
PendingIntent callbackIntent = PendingIntent.getBroadcast(
getContext(), 0 /* requestCode */, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
mgr.startResolutionActivity(
activity,
0 /* requestCode */,
intent,
callbackIntent);
}
resultIntent = intent;
}
};
context.registerReceiver(receiver,
new IntentFilter(ACTION_DOWNLOAD_SUBSCRIPTION),
LPA_DECLARED_PERMISSION /* broadcastPermission*/,
null /* handler */);
// Download subscription asynchronously.
DownloadableSubscription sub = DownloadableSubscription
.forActivationCode(code /* encodedActivationCode*/);
Intent intent = new Intent(action).setPackage(context.getPackageName());
PendingIntent callbackIntent = PendingIntent.getBroadcast(
getContext(), 0 /* requestCode */, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
mgr.downloadSubscription(sub, true /* switchAfterDownload */,
callbackIntent);
تعریف و استفاده از مجوز در AndroidManifest.xml
:
<permission android:protectionLevel="signature" android:name="com.your.company.lpa.permission.BROADCAST" />
<uses-permission android:name="com.your.company.lpa.permission.BROADCAST"/>
برای جابهجایی به اشتراک با توجه به شناسه اشتراک:
// Register receiver.
static final String ACTION_SWITCH_TO_SUBSCRIPTION = "switch_to_subscription";
static final String LPA_DECLARED_PERMISSION
= "com.your.company.lpa.permission.BROADCAST";
BroadcastReceiver receiver =
new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (!action.equals(intent.getAction())) {
return;
}
resultCode = getResultCode();
detailedCode = intent.getIntExtra(
EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE,
0 /* defaultValue*/);
resultIntent = intent;
}
};
context.registerReceiver(receiver,
new IntentFilter(ACTION_SWITCH_TO_SUBSCRIPTION),
LPA_DECLARED_PERMISSION /* broadcastPermission*/,
null /* handler */);
// Switch to a subscription asynchronously.
Intent intent = new Intent(action).setPackage(context.getPackageName());
PendingIntent callbackIntent = PendingIntent.getBroadcast(
getContext(), 0 /* requestCode */, intent,
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_MUTABLE);
mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);
برای فهرست کاملی از APIهای EuiccManager
و نمونه کد، APIهای eUICC را ببینید.
خطاهای قابل حل
مواردی وجود دارد که سیستم نمی تواند عملیات eSIM را کامل کند اما خطا توسط کاربر قابل حل است. برای مثال، اگر فراداده نمایه نشان دهد که کد تأیید شرکت مخابراتی مورد نیاز است، ممکن است downloadSubscription
ناموفق باشد. یا اگر برنامه شرکت مخابراتی دارای امتیازات شرکت مخابراتی بر نمایه مقصد باشد (یعنی شرکت مخابراتی مالک نمایه باشد) اما دارای امتیازات شرکت مخابراتی نسبت به نمایه فعال کنونی نباشد، ممکن است خراب switchToSubscription
و از این رو رضایت کاربر لازم است.
برای این موارد، تماس تماس گیرنده با EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
فراخوانی می شود. Callback Intent
حاوی موارد اضافی داخلی است به طوری که وقتی تماس گیرنده آن را به EuiccManager#startResolutionActivity
میدهد، وضوح میتواند از طریق LUI درخواست شود. برای مثال، با استفاده از کد تأیید مجدد، EuiccManager#startResolutionActivity
یک صفحه LUI را راه اندازی می کند که به کاربر اجازه می دهد یک کد تأیید را وارد کند. پس از وارد شدن کد، عملیات دانلود از سر گرفته می شود. این رویکرد به برنامه حامل کنترل کامل بر روی زمانی که UI نشان داده میشود، میدهد، اما به LPA/LUI یک روش توسعهیافته برای اضافه کردن مدیریت جدید مسائل قابل بازیابی توسط کاربر در آینده بدون نیاز به تغییر برنامههای مشتری میدهد.
اندروید 9 این خطاهای قابل حل را در EuiccService
تعریف می کند که LUI باید آنها را مدیریت کند:
/**
* Alert the user that this action will result in an active SIM being
* deactivated. To implement the LUI triggered by the system, you need to define
* this in AndroidManifest.xml.
*/
public static final String ACTION_RESOLVE_DEACTIVATE_SIM =
"android.service.euicc.action.RESOLVE_DEACTIVATE_SIM";
/**
* Alert the user about a download/switch being done for an app that doesn't
* currently have carrier privileges.
*/
public static final String ACTION_RESOLVE_NO_PRIVILEGES =
"android.service.euicc.action.RESOLVE_NO_PRIVILEGES";
/** Ask the user to resolve all the resolvable errors. */
public static final String ACTION_RESOLVE_RESOLVABLE_ERRORS =
"android.service.euicc.action.RESOLVE_RESOLVABLE_ERRORS";
امتیازات حامل
اگر شرکت مخابراتی هستید که برنامه شرکت مخابراتی خود را توسعه میدهد و EuiccManager
را برای بارگیری نمایهها در دستگاه فراخوانی میکند، نمایه شما باید قوانین امتیاز شرکت مخابراتی مربوط به برنامه شرکت مخابراتی شما را در فراداده درج کند. این به این دلیل است که نمایههای اشتراک متعلق به شرکتهای مخابراتی مختلف میتوانند در eUICC یک دستگاه وجود داشته باشند و هر برنامه شرکت مخابراتی فقط باید اجازه دسترسی به نمایههای متعلق به آن شرکت مخابراتی را داشته باشد. برای مثال، شرکت مخابراتی A نباید بتواند نمایه ای را که متعلق به شرکت مخابراتی B است دانلود، فعال یا غیرفعال کند.
برای اطمینان از اینکه یک نمایه فقط برای مالک آن قابل دسترسی است، Android از مکانیزمی برای اعطای امتیازات ویژه به برنامه مالک نمایه (یعنی برنامه حامل) استفاده می کند. پلتفرم Android گواهیهای ذخیرهشده در فایل قانون دسترسی نمایه (ARF) را بارگیری میکند و به برنامههای امضاشده توسط این گواهیها اجازه میدهد تا با APIهای EuiccManager
تماس بگیرند. فرآیند سطح بالا در زیر توضیح داده شده است:
- اپراتور APK برنامه حامل را امضا می کند. ابزار apksigner گواهی کلید عمومی را به APK متصل می کند.
Operator/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 و ادغام آن با سیستم اندروید دارد.
نیازهای سخت افزار/مودم
LPA و eSIM OS در تراشه eUICC باید حداقل از GSMA RSP (Remote SIM Provisioning) نسخه 2.0 یا 2.2 پشتیبانی کنند. همچنین باید برنامه ریزی کنید که از سرورهای SM-DP+ و SM-DS که دارای نسخه RSP منطبق هستند، استفاده کنید. برای جزئیات معماری RSP، مشخصات معماری RSP GSMA SGP.21 را ببینید.
علاوه بر این، برای ادغام با APIهای eUICC در اندروید 9، مودم دستگاه باید قابلیتهای ترمینال را با پشتیبانی از قابلیتهای eUICC رمزگذاری شده ارسال کند (مدیریت نمایه محلی و دانلود نمایه). همچنین نیاز به پیاده سازی روش های زیر دارد:
- IRadio HAL نسخه 1.1:
setSimPower
IRadio HAL نسخه 1.2:
getIccCardStatus
IRadioConfig HAL نسخه 1.0:
getSimSlotsStatus
IRadioConfig AIDL v1.0:
getAllowedCarriers
Google LPA باید وضعیت قفل شرکت مخابراتی را بداند تا بتواند دانلود یا انتقال eSIM را فقط برای شرکت مخابراتی مجاز مجاز کند. در غیر این صورت ممکن است کاربران به دانلود و انتقال سیمکارت بپردازند و بعدا متوجه شوند که دستگاه به شرکت مخابراتی دیگری قفل شده است.
فروشندگان یا OEM ها باید API IRadioSim.getAllowedCarriers()HAL را پیاده سازی کنند.
فروشنده RIL / مودم باید وضعیت قفل و شناسه حامل حاملی را که دستگاه در آن قفل شده است را به عنوان بخشی از API IRadioSimResponse.getAllowedCarriersResponse()HAL پر کند.
مودم باید 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 از دو جزء مجزا تشکیل شده است (هر دو ممکن است در یک APK پیاده سازی شوند): باطن LPA، و LPA UI یا LUI.
برای پیاده سازی باطن LPA، باید EuiccService
را گسترش دهید و این سرویس را در فایل مانیفست خود اعلام کنید. این سرویس باید به مجوز سیستم android.permission.BIND_EUICC_SERVICE
نیاز داشته باشد تا اطمینان حاصل شود که فقط سیستم می تواند به آن متصل شود. این سرویس همچنین باید دارای یک فیلتر هدف با عملکرد 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>
در داخل، چارچوب Android LPA فعال را تعیین می کند و در صورت لزوم با آن تعامل می کند تا از API های eUICC Android پشتیبانی کند. 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
و اولویت غیر صفر داشته باشند. منطق مشابهی برای انتخاب پیادهسازی برای این فعالیتها به کار میرود، مانند انتخاب اجرای 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 متفاوت از APK که EuiccService
را پیادهسازی میکند باشد. داشتن یک APK منفرد یا چندین APK (به عنوان مثال، یکی که EuiccService
را اجرا می کند و دیگری که فعالیت های LUI را ارائه می دهد) یک انتخاب طراحی است.
EuicCardManager
EuiccCardManager
رابطی برای برقراری ارتباط با تراشه eSIM است. این توابع ES10 (همانطور که در مشخصات GSMA RSP توضیح داده شده است) ارائه می کند و دستورات درخواست/پاسخ APDU سطح پایین و همچنین تجزیه ASN.1 را مدیریت می کند. EuiccCardManager
یک API سیستم است و فقط توسط برنامه های دارای امتیاز سیستم قابل فراخوانی است.
شکل 2. هم برنامه حامل و هم LPA از Euicc API استفاده می کنند
APIهای عملیات نمایه از طریق EuiccCardManager
نیاز دارند که تماس گیرنده یک LPA باشد. این توسط چارچوب 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
از طریق یک رابط AIDL به EuiccCardController
(که در فرآیند تلفن اجرا میشود) متصل میشود و هر روش EuiccCardManager
پاسخ تماس خود را از فرآیند تلفن از طریق یک رابط AIDL اختصاصی متفاوت دریافت میکند. هنگام استفاده از API های EuiccCardManager
، تماس گیرنده (LPA) باید یک شی Executor
ارائه دهد که از طریق آن تماس برگشتی فراخوانی می شود. این شی Executor
ممکن است بر روی یک رشته یا روی یک Thread Pool به انتخاب شما اجرا شود.
اکثر 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 می تواند کل جریان UI را کنترل کند، به این معنی که هیچ رابط کاربری برنامه حامل نشان داده نمی شود. این رویکرد بررسی برچسب 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
برنامه حامل، 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، یک برنامه دارای امتیاز سیستم، می تواند به آن متصل شود. این سرویس همچنین باید دارای یک فیلتر هدف با عملکرد 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 با ارسال هدف
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 به باطن حامل.
برنامه حامل با فراخوانی
setResult(int, Intent)
وfinish()
به LPA پاسخ می دهد.- اگر برنامه حامل با
RESULT_OK
پاسخ دهد، LPA به جریان فعالسازی ادامه میدهد. اگر برنامه حامل تشخیص دهد که کاربر به جای اینکه به LPA اجازه دهد به سرویس برنامه حامل متصل شود، باید یک کد QR را اسکن کند، برنامه حامل با استفاده از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 نمیتوانند کد فعالسازی را از برنامه شرکت مخابراتی دریافت کنند.
- اگر برنامه حامل با
جریان فعال سازی LPA را در یک برنامه حامل راه اندازی کنید
با شروع Android 11، برنامههای شرکت مخابراتی میتوانند از APIهای eUICC برای راهاندازی LUI برای فعالسازی eSIM استفاده کنند. این روش رابط کاربری جریان فعالسازی eSIM LPA را برای فعال کردن نمایه eSIM نشان میدهد. LPA پس از پایان فعالسازی نمایه eSIM، پخشی را ارسال میکند.
LPA باید فعالیتی از جمله فیلتر هدف را با عملکرد
android.service.euicc.action.START_EUICC_ACTIVATION
اعلام کند. اولویت فیلتر هدف باید روی یک مقدار غیر صفر تنظیم شود در صورتی که چندین پیاده سازی در دستگاه وجود داشته باشد. به عنوان مثال:<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 تمام عناصر UI ضروری را در حین دانلود نمایش می دهد، مانند صفحه بارگیری.هنگامی که جریان فعالسازی 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 واحد که در حال ارتقا به Android 10 هستند، نیازی به تغییر در اجرای LPA ندارند، زیرا پلتفرم به طور خودکار نمونه EuiccManager
را با eUICC پیشفرض مرتبط میکند. eUICC پیشفرض توسط پلتفرم برای دستگاههای دارای رادیو HAL نسخه 1.2 یا بالاتر و توسط LPA برای دستگاههایی با نسخههای رادیویی HAL کمتر از 1.2 تعیین میشود.
الزامات
برای پشتیبانی از چندین eSIM، دستگاه باید بیش از یک eUICC داشته باشد، که میتواند یک eUICC داخلی یا یک اسلات فیزیکی سیمکارت باشد که میتوان eUICCهای قابل جابجایی را در آن قرار داد.
رادیو HAL نسخه 1.2 یا بالاتر برای پشتیبانی از چندین eSIM مورد نیاز است. Radio HAL نسخه 1.4 و RadioConfig HAL نسخه 1.2 توصیه می شود.
پیاده سازی
برای پشتیبانی از چندین eSIM (از جمله eUICCهای قابل جابجایی یا سیمکارتهای قابل برنامهریزی)، LPA باید EuiccService
را پیادهسازی کند که شناسه اسلات مربوط به شناسه کارت ارائهشده توسط تماسگیرنده را دریافت میکند.
منبع non_removable_euicc_slots
مشخصشده در arrays.xml
آرایهای از اعداد صحیح است که شناسههای اسلات از eUICCهای داخلی دستگاه را نشان میدهد. شما باید این منبع را مشخص کنید تا به پلتفرم اجازه دهید تعیین کند که آیا eUICC درج شده قابل جابجایی است یا خیر.
برنامه شرکت مخابراتی برای دستگاهی با چندین eSIM
هنگام ساختن یک برنامه حامل برای دستگاهی با چندین eSIM، از روش createForCardId
در EuiccManager
برای ایجاد یک شی EuiccManager
استفاده کنید که به شناسه کارت معین پین شده است. شناسه کارت یک مقدار صحیح است که به طور منحصربهفرد یک UICC یا یک eUICC را در دستگاه شناسایی میکند.
برای دریافت شناسه کارت برای eUICC پیشفرض دستگاه، از روش getCardIdForDefaultEuicc
در TelephonyManager
استفاده کنید. اگر نسخه HAL رادیویی کمتر از 1.2 باشد، این روش UNSUPPORTED_CARD_ID
برمیگرداند و اگر دستگاه eUICC را نخوانده باشد، UNINITIALIZED_CARD_ID
را برمیگرداند.
همچنین میتوانید شناسههای کارت را از 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 در همه بیلدهای اندروید در دسترس باشد (هر گوشی از eSIM پشتیبانی نمی کند). به همین دلیل، هیچ مورد تست CTS سرتاسری وجود ندارد. با این حال، موارد آزمایش اولیه در AOSP برای اطمینان از معتبر بودن APIهای eUICC در معرض در ساختهای اندروید موجود است.
باید مطمئن شوید که ساختها موارد تست CTS زیر را (برای APIهای عمومی) گذراندهاند: /platform/cts/tests/tests/telephony/current/src/android/telephony/euicc/cts .
اپراتورهایی که یک برنامه حامل را پیادهسازی میکنند باید چرخههای عادی تضمین کیفیت داخلی خود را طی کنند تا مطمئن شوند که همه ویژگیهای پیادهسازی شده مطابق انتظار کار میکنند. حداقل، برنامه حامل باید بتواند تمام پروفایل های اشتراک متعلق به یک اپراتور را فهرست کند، یک نمایه را دانلود و نصب کند، یک سرویس را در نمایه فعال کند، بین پروفایل ها جابجا شود و نمایه ها را حذف کند.
اگر LPA خودتان را می سازید، باید آزمایش های بسیار دقیق تری را انجام دهید. شما باید با فروشنده مودم، تراشه eUICC یا فروشنده سیستم عامل eSIM، فروشندگان SM-DP+ و اپراتورها کار کنید تا مشکلات را حل کنید و از قابلیت همکاری LPA خود در معماری RSP اطمینان حاصل کنید. مقدار خوب تست دستی اجتناب ناپذیر است. برای بهترین پوشش آزمون، باید برنامه آزمایشی GSMA SGP.23 RSP را دنبال کنید.