Công nghệ SIM được nhúng (eSIM hay eUICC) cho phép người dùng di động tải hồ sơ nhà mạng xuống và kích hoạt dịch vụ của nhà mạng mà không cần phải thẻ SIM thực. Đây là một bộ thông số kỹ thuật toàn cầu dựa trên GSMA, cho phép cấp phép SIM từ xa (RSP) của bất kỳ thiết bị di động nào. Bắt đầu với Android 9, khung Android cung cấp các API tiêu chuẩn để truy cập vào eSIM và quản lý hồ sơ gói thuê bao trên eSIM đó. Các eUICC này API cho phép các bên thứ ba phát triển ứng dụng của nhà mạng và hồ sơ cục bộ của riêng họ trợ lý ảo (LPA) trên thiết bị Android hỗ trợ eSIM.
LPA là một ứng dụng hệ thống độc lập phải được đưa vào Hình ảnh bản dựng Android. Việc quản lý các hồ sơ trên eSIM thường được thực hiện bằng LPA, vì nó đóng vai trò là cầu nối giữa SM-DP+ (dịch vụ từ xa chuẩn bị, lưu trữ và phân phối các gói hồ sơ đến thiết bị) và chip eUICC. APK LPA có thể tùy chọn bao gồm một thành phần giao diện người dùng, được gọi là LPA UI hoặc LUI, để cung cấp một vị trí trung tâm để người dùng cuối quản lý tất cả các gói thuê bao được nhúng hồ sơ. Khung Android tự động phát hiện và kết nối với LPA có sẵn và định tuyến tất cả hoạt động eUICC thông qua một phiên bản LPA.
Hình 1. Kiến trúc RSP được đơn giản hoá
Các nhà mạng di động muốn tạo ứng dụng của nhà mạng nên xem xét
các API trong
EuiccManager
!
cung cấp các hoạt động quản lý hồ sơ cấp cao như
downloadSubscription()
, switchToSubscription()
và
deleteSubscription()
.
Nếu là nhà sản xuất thiết bị gốc (OEM) muốn tạo ứng dụng hệ thống LPA của riêng mình, thì bạn phải
mở rộng
EuiccService
cho khung Android kết nối với các dịch vụ LPA của bạn. Ngoài ra, bạn
nên sử dụng các API trong
EuiccCardManager
!
Cung cấp các chức năng ES10x dựa trên GSMA RSP v2.0.
Các hàm này dùng để phát lệnh cho chip eUICC, chẳng hạn như
prepareDownload()
, loadBoundProfilePackage()
, retrieveNotificationList()
và resetMemory()
.
Các API trong
EuiccManager
đòi hỏi một ứng dụng LPA được triển khai đúng cách để hoạt động và phương thức gọi của
EuiccCardManager
Các API phải là một LPA. Yêu cầu này do khung Android thực thi.
Các thiết bị chạy Android 10 trở lên có thể hỗ trợ thiết bị có nhiều eSIM. Để biết thêm thông tin, hãy xem Hỗ trợ nhiều eSIM.
Tạo ứng dụng của nhà mạng
API eUICC trong Android 9 có thể giúp nhà cung cấp dịch vụ mạng di động để tạo ứng dụng mang thương hiệu nhà mạng nhằm quản lý hồ sơ. Điều này bao gồm việc tải xuống và xoá hồ sơ của gói thuê bao thuộc sở hữu của nhà mạng cũng như chuyển sang hồ sơ thuộc sở hữu của nhà mạng.
Trình quản lý Euicc
EuiccManager
là điểm truy cập chính để các ứng dụng tương tác với
LPA. Điều này bao gồm cả những ứng dụng của nhà mạng tải xuống, xoá và chuyển sang
gói thuê bao do nhà mạng sở hữu. Trong đó cũng có ứng dụng hệ thống LUI,
cung cấp một vị trí/giao diện người dùng trung tâm để quản lý tất cả các gói thuê bao được nhúng, và
có thể là một ứng dụng riêng biệt với ứng dụng cung cấp EuiccService
.
Để sử dụng API công khai, trước tiên, ứng dụng của nhà mạng phải có được thực thể của
EuiccManager
đến Context#getSystemService
:
EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);
Bạn nên kiểm tra xem eSIM có được hỗ trợ trên thiết bị hay không trước khi thực hiện bất kỳ thao tác nào
Hoạt động trên eSIM. EuiccManager#isEnabled()
thường trả về true
nếu
Tính năng android.hardware.telephony.euicc
được định nghĩa và gói LPA được xác định
hiện tại.
if (mgr == null || !mgr.isEnabled()) {
return;
}
Cách nhận thông tin về phần cứng eUICC và phiên bản hệ điều hành eSIM:
EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();
Nhiều API, chẳng hạn như downloadSubscription()
và switchToSubscription()
, sử dụng
PendingIntent
vì có thể mất vài giây hoặc thậm chí vài phút để hoàn tất.
PendingIntent
được gửi cùng với một mã kết quả trong
EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_
không gian, cung cấp
mã lỗi do khung xác định, cũng như mã kết quả chi tiết tuỳ ý
được truyền từ LPA dưới dạng EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE
, cho phép
ứng dụng của nhà mạng để theo dõi cho mục đích ghi nhật ký/gỡ lỗi. PendingIntent
hàm callback phải là BroadcastReceiver
.
Để tải xuống một gói thuê bao có thể tải xuống nhất định (được tạo từ một mã kích hoạt hoặc mã 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);
Định nghĩa và sử dụng quyền trong AndroidManifest.xml
:
<permission android:protectionLevel="signature" android:name="com.your.company.lpa.permission.BROADCAST" />
<uses-permission android:name="com.your.company.lpa.permission.BROADCAST"/>
Cách chuyển sang gói thuê bao được cung cấp mã nhận dạng gói thuê bao:
// 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);
Để xem danh sách đầy đủ các API EuiccManager
và ví dụ về mã, hãy xem
Các API eUICC.
Lỗi có thể giải quyết
Có một số trường hợp hệ thống không thể hoàn tất thao tác eSIM
nhưng người dùng có thể khắc phục lỗi. Ví dụ: downloadSubscription
có thể không thành công nếu siêu dữ liệu của hồ sơ cho biết rằng có mã xác nhận của nhà mạng
là trường bắt buộc. Hoặc switchToSubscription
có thể không thành công nếu ứng dụng của nhà mạng có nhà mạng
đặc quyền đối với hồ sơ đích (tức là nhà cung cấp dịch vụ sở hữu hồ sơ) nhưng
không có đặc quyền của nhà mạng đối với hồ sơ hiện được bật và do đó
cần có sự đồng ý của người dùng.
Đối với những trường hợp này, lệnh gọi lại của phương thức gọi được gọi bằng
EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR
. Lệnh gọi lại
Intent
chứa các phần bổ sung nội bộ mà khi phương thức gọi truyền nó đến
EuiccManager#startResolutionActivity
,
có thể được yêu cầu thông qua LUI. Sử dụng mã xác nhận cho
một lần nữa,
EuiccManager#startResolutionActivity
kích hoạt màn hình LUI cho phép người dùng nhập mã xác nhận;
sau khi nhập mã, hoạt động tải xuống sẽ được tiếp tục. Phương pháp này
cung cấp cho ứng dụng của nhà mạng toàn quyền kiểm soát thời điểm giao diện người dùng được hiển thị, nhưng sẽ cho phép
LPA/LUI, một phương thức có thể mở rộng để thêm các thao tác xử lý mới đối với những
sự cố trong tương lai mà không cần ứng dụng khách thay đổi.
Android 9 xác định các lỗi có thể giải quyết này trong
EuiccService
!
mà LUI sẽ xử lý:
/**
* 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";
Đặc quyền của nhà mạng
Nếu bạn là một nhà mạng đang phát triển ứng dụng của riêng nhà mạng để gọi EuiccManager
để tải hồ sơ xuống một thiết bị, hồ sơ của bạn phải bao gồm nhà mạng
tương ứng với ứng dụng của nhà mạng trong siêu dữ liệu. Đây là
vì hồ sơ gói thuê bao của các nhà mạng khác nhau có thể cùng tồn tại ở
eUICC của một thiết bị và mỗi ứng dụng của nhà mạng chỉ được phép truy cập vào
hồ sơ thuộc sở hữu của nhà mạng đó. Ví dụ: nhà mạng A không thể
tải xuống, bật hoặc vô hiệu hoá hồ sơ do nhà mạng B sở hữu.
Để đảm bảo chỉ chủ sở hữu mới có thể truy cập vào hồ sơ, Android sử dụng một cơ chế để
cấp đặc quyền cho ứng dụng của chủ sở hữu trang doanh nghiệp (tức là ứng dụng của nhà mạng). Chiến lược phát hành đĩa đơn
Nền tảng Android tải các chứng chỉ được lưu trữ trong tệp quy tắc truy cập của hồ sơ
(ARF) và cấp quyền thực hiện cuộc gọi cho các ứng dụng được ký bởi những chứng chỉ này
vào các API EuiccManager
. Dưới đây là quy trình cấp cao:
- Nhà cung cấp ký APK ứng dụng của nhà mạng; thời gian apksigner sẽ đính kèm chứng chỉ khoá công khai vào APK.
Nhà cung cấp dịch vụ/SM-DP+ chuẩn bị một hồ sơ và siêu dữ liệu của hồ sơ đó, bao gồm cả ARF có chứa:
- Chữ ký (SHA-1 hoặc SHA-256) trong chứng chỉ khoá công khai của ứng dụng của nhà mạng (bắt buộc)
- Tên gói của ứng dụng của nhà mạng (rất nên dùng)
Ứng dụng của nhà mạng cố gắng thực hiện một thao tác eUICC bằng API
EuiccManager
.Nền tảng Android xác minh hàm băm SHA-1 hoặc SHA-256 của ứng dụng gọi khớp với chữ ký của chứng chỉ thu được từ ARF của hồ sơ mục tiêu. Nếu tên gói của ứng dụng của nhà mạng được đưa vào ARF thì mã này cũng phải khớp với tên gói của ứng dụng gọi.
Sau khi chữ ký và tên gói (nếu có) được xác minh, đặc quyền của nhà mạng sẽ được cấp cho ứng dụng gọi qua hồ sơ đích.
Vì siêu dữ liệu của hồ sơ có thể có sẵn bên ngoài chính hồ sơ (do đó LPA có thể truy xuất siêu dữ liệu hồ sơ từ SM-DP+ trước khi hồ sơ được được tải xuống hoặc từ ISD-R khi cấu hình bị vô hiệu hoá), tệp sẽ chứa quy tắc đặc quyền của nhà mạng như trong hồ sơ.
Hệ điều hành eUICC và SM-DP+ phải hỗ trợ một thẻ độc quyền BF76
trong hồ sơ
siêu dữ liệu. Nội dung thẻ phải giống với các quy tắc đặc quyền của nhà cung cấp dịch vụ như được trả về
theo chương trình phụ trợ quy tắc truy cập (ARA) được xác định trong
Đặc quyền của nhà mạng 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
}
}
Để biết thêm thông tin chi tiết về tính năng ký ứng dụng, hãy xem Ký ứng dụng. Để biết chi tiết về đặc quyền của nhà mạng, hãy xem Đặc quyền của nhà mạng UICC.
Tạo ứng dụng trợ lý hồ sơ cục bộ
Nhà sản xuất thiết bị có thể triển khai trợ lý hồ sơ cục bộ (LPA) của riêng họ, Nội dung phải hấp dẫn với API Euicc của Android. Các phần sau đây sẽ cung cấp tổng quan ngắn gọn về tạo một ứng dụng LPA và tích hợp ứng dụng này với hệ thống Android.
Yêu cầu về phần cứng/modem
LPA và eSIM OS trên chip eUICC phải hỗ trợ ít nhất GSMA RSP (Điều khiển từ xa Cấp phép SIM) v2.0 hoặc v2.2. Bạn cũng nên lên kế hoạch sử dụng SM-DP+ và SM-DS máy chủ có phiên bản RSP phù hợp. Để biết cấu trúc RSP chi tiết, hãy xem Thông số kỹ thuật kiến trúc GSMA SGP.21 RSP.
Ngoài ra, để tích hợp với các API eUICC trong Android 9, modem thiết bị phải gửi các tính năng của thiết bị đầu cuối với sự hỗ trợ cho các chức năng eUICC được mã hoá (quản lý hồ sơ cục bộ và tải hồ sơ xuống). Nền tảng này cũng cần triển khai các phương thức sau:
- IRadio HAL phiên bản 1.1:
setSimPower
IRadio HAL phiên bản 1.2:
getIccCardStatus
IRadioConfig HAL phiên bản 1.0:
getSimSlotsStatus
IRadioConfig AIDL phiên bản 1.0:
getAllowedCarriers
LPA của Google cần biết trạng thái khoá của nhà mạng để chỉ có thể cho phép tải hoặc chuyển eSIM xuống đối với nhà mạng được cho phép. Nếu không, người dùng có thể sẽ tải xuống và chuyển SIM, sau đó nhận ra rằng thiết bị bị khoá với một nhà mạng khác.
Nhà cung cấp hoặc OEM phải triển khai API IRadioSim.getAllowedCarriers().
RIL / Modem của nhà cung cấp sẽ điền trạng thái khoá và providerId của nhà mạng nơi thiết bị bị khoá như một phần của API IRadioSimResponse.getAllowedCarriersResponse().
Modem phải nhận ra eSIM đã bật hồ sơ khởi động mặc định là SIM hợp lệ và luôn bật nguồn SIM.
Đối với các thiết bị chạy Android 10, eUICC không thể tháo rời
phải xác định mảng ID vị trí. Ví dụ: hãy xem
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>
Để có danh sách đầy đủ các yêu cầu đối với modem, hãy xem Các yêu cầu về Modem để hỗ trợ eSIM.
Dịch vụ Euicc
Một LPA bao gồm hai thành phần riêng biệt (có thể cả hai được triển khai trong cùng một LPA APK): phần phụ trợ LPA và LPA UI hoặc LUI.
Để triển khai phần phụ trợ LPA, bạn phải mở rộng
EuiccService
rồi khai báo dịch vụ này trong tệp kê khai. Dịch vụ phải yêu cầu
android.permission.BIND_EUICC_SERVICE
quyền hệ thống để đảm bảo rằng chỉ
mà hệ thống có thể liên kết với tệp đó. Dịch vụ này cũng phải bao gồm một bộ lọc ý định có
thao tác android.service.euicc.EuiccService
. Mức độ ưu tiên của ý định
nên đặt bộ lọc thành một giá trị khác 0 trong trường hợp có nhiều lần triển khai
có trên thiết bị. Ví dụ:
<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>
Trong nội bộ, khung Android xác định LPA đang hoạt động và tương tác với
cần thiết để hỗ trợ các API eUICC của Android. PackageManager
được truy vấn
tất cả ứng dụng có quyền android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS
,
Mã này chỉ định một dịch vụ cho thao tác android.service.euicc.EuiccService
.
Dịch vụ có mức độ ưu tiên cao nhất sẽ được chọn. Nếu không tìm thấy dịch vụ nào, LPA
chế độ hỗ trợ đã bị tắt.
Để triển khai LUI, bạn phải cung cấp hoạt động cho những thao tác sau:
android.service.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS
android.service.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION
Giống như dịch vụ này, mỗi hoạt động phải yêu cầu
Quyền hệ thống android.permission.BIND_EUICC_SERVICE
. Mỗi nguồn cấp dữ liệu phải có một
bộ lọc ý định bằng hành động thích hợp,
android.service.euicc.category.EUICC_UI
và một mức độ ưu tiên khác 0.
Logic tương tự được dùng để chọn phương thức triển khai cho các hoạt động này làm
với việc chọn phương thức triển khai
EuiccService
.
Ví dụ:
<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>
Điều này có nghĩa là giao diện người dùng triển khai những màn hình này có thể đến từ một
APK của một dịch vụ triển khai
EuiccService
.
Liệu nên có một hay nhiều tệp APK (ví dụ: một tệp APK triển khai
EuiccService
và một thuộc tính cung cấp các hoạt động LUI) là một lựa chọn thiết kế.
EuiccCardManager
EuiccCardManager
là giao diện để giao tiếp với chip eSIM. Nó
cung cấp các chức năng ES10 (như được mô tả trong thông số kỹ thuật GSMA RSP) và xử lý
các lệnh yêu cầu/phản hồi APDU cấp thấp cũng như phân tích cú pháp ASN.1.
EuiccCardManager
là một API hệ thống và chỉ có đặc quyền hệ thống mới có thể gọi
của chúng tôi.
Hình 2. Cả ứng dụng của nhà mạng và LPA đều sử dụng API Euicc
Các API thao tác trên hồ sơ thông qua EuiccCardManager
yêu cầu phương thức gọi phải
một LPA. Yêu cầu này do khung Android thực thi. Điều này có nghĩa là phương thức gọi phải
mở rộng EuiccService
và được khai báo trong tệp kê khai, như mô tả trong
các phần trước.
Tương tự như EuiccManager
, để sử dụng các API EuiccCardManager
, LPA của bạn phải
trước tiên, hãy lấy thực thể của EuiccCardManager
thông qua
Context#getSystemService
:
EuiccCardManager cardMgr = (EuiccCardManager) context.getSystemService(Context.EUICC_CARD_SERVICE);
Sau đó, để tải tất cả các hồ sơ trên eUICC, hãy làm như sau:
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);
Trong nội bộ, EuiccCardManager
liên kết với EuiccCardController
(chạy trong
điện thoại) thông qua giao diện AIDL và từng phương thức EuiccCardManager
nhận lệnh gọi lại từ quy trình điện thoại thông qua một AIDL riêng, khác
. Khi sử dụng các API EuiccCardManager
, phương thức gọi (LPA) phải cung cấp
Executor
qua đối tượng mà lệnh gọi lại được gọi ra. Đối tượng Executor
này có thể chạy trên
một chuỗi hoặc trên một nhóm chuỗi mà bạn chọn.
Hầu hết API EuiccCardManager
đều có cùng một kiểu sử dụng. Ví dụ: để tải một
liên kết gói hồ sơ trên eUICC:
...
cardMgr.loadBoundProfilePackage(eid, boundProfilePackage,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
Cách chuyển sang một hồ sơ khác có ICCID cho trước:
...
cardMgr.switchToProfile(eid, iccid, true /* refresh */,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
Cách lấy địa chỉ SM-DP+ mặc định từ chip eUICC:
...
cardMgr.requestDefaultSmdpAddress(eid, AsyncTask.THREAD_POOL_EXECUTOR,
callback);
Cách truy xuất danh sách thông báo của các sự kiện thông báo nhất định:
...
cardMgr.listNotifications(eid,
EuiccNotification.Event.INSTALL
| EuiccNotification.Event.DELETE /* events */,
AsyncTask.THREAD_POOL_EXECUTOR, callback);
Kích hoạt hồ sơ eSIM thông qua một ứng dụng của nhà mạng
Trên thiết bị chạy Android 9 trở lên, bạn có thể dùng ứng dụng của nhà mạng để kích hoạt
eSIM và tải hồ sơ xuống. Ứng dụng của nhà mạng có thể tải hồ sơ xuống bằng cách
đang gọi
downloadSubscription
trực tiếp hoặc bằng cách cung cấp mã kích hoạt cho LPA.
Khi một ứng dụng của nhà mạng tải một hồ sơ xuống bằng cách gọi
downloadSubscription
!
lệnh gọi thực thi việc ứng dụng có thể quản lý hồ sơ thông qua BF76
thẻ siêu dữ liệu
để mã hoá các quy tắc đặc quyền của nhà mạng cho
hồ sơ. Nếu một hồ sơ không có thẻ BF76
hoặc nếu thẻ BF76
của hồ sơ đó không có
khớp với chữ ký của ứng dụng gọi của nhà mạng, thì nội dung tải xuống sẽ bị từ chối.
Phần dưới đây mô tả việc kích hoạt eSIM thông qua một ứng dụng của nhà mạng bằng mã kích hoạt.
Kích hoạt eSIM bằng mã kích hoạt
Khi sử dụng mã kích hoạt để kích hoạt hồ sơ eSIM, LPA sẽ tìm nạp
mã kích hoạt từ
ứng dụng của nhà mạng rồi tải hồ sơ xuống. Quy trình này có thể do LPA bắt đầu
và LPA có thể kiểm soát toàn bộ luồng giao diện người dùng, nghĩa là không có giao diện người dùng ứng dụng nào của nhà mạng
hiển thị. Phương pháp này bỏ qua bước kiểm tra thẻ BF76
, nên nhà vận hành mạng sẽ không
cần triển khai toàn bộ quy trình giao diện người dùng kích hoạt eSIM, bao gồm cả việc tải xuống
Hồ sơ eSIM và cách xử lý lỗi.
Xác định dịch vụ cung cấp eUICC của nhà mạng
LPA và ứng dụng của nhà mạng giao tiếp qua hai
AIDL
giao diện:
ICarrierEuiccProvisioningService
và IGetActivationCodeCallback
. Hãng vận chuyển
ứng dụng phải triển khai giao diện ICarrierEuiccProvisioningService
và
hiển thị dữ liệu đó trong
khai báo tệp kê khai.
LPA phải liên kết với ICarrierEuiccProvisioningService
và triển khai
IGetActivationCodeCallback
. Để biết thêm thông tin về cách triển khai và
hiển thị giao diện AIDL, hãy xem phần Xác định và giao diện AIDL.
Để xác định các giao diện AIDL, hãy tạo các tệp AIDL sau cho cả ứng dụng của nhà mạng và 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(); }
Ví dụ về cách triển khai LPA
Để liên kết với hoạt động triển khai ICarrierEuiccProvisioningService
của ứng dụng nhà mạng,
LPA phải sao chép cả ICarrierEuiccProvisioningService.aidl
và
IGetActivationCodeCallback.aidl
cho dự án của bạn và triển khai
ServiceConnection
.
@Override
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
mCarrierProvisioningService = ICarrierEuiccProvisioningService.Stub.asInterface(iBinder);
}
Sau khi liên kết với ICarrierEuiccProvisioningService
của ứng dụng mạng
LPA sẽ gọi getActivationCode
hoặc
getActivationCodeForEid
để nhận mã kích hoạt từ ứng dụng của nhà mạng bằng cách
truyền phương thức triển khai lớp mã giả lập IGetActivationCodeCallback
.
Sự khác biệt giữa getActivationCode
và getActivationCodeForEid
là
getActivationCodeForEid
cho phép nhà mạng liên kết trước một hồ sơ với
EID (mã định danh dành cho eSIM) trước khi quá trình tải xuống bắt đầu.
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
}
}
Ví dụ về cách triển khai cho ứng dụng của nhà mạng
Để LPA liên kết với ứng dụng của nhà mạng, ứng dụng của nhà mạng phải sao chép cả hai
ICarrierEuiccProvisioningService.aidl
và IGetActivationCodeCallback.aidl
đến
dự án của bạn và khai báo dịch vụ ICarrierEuiccProvisioningService
trong
AndroidManifest.xml
. Dịch vụ phải yêu cầu
Quyền hệ thống của android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS
để đảm bảo
mà chỉ LPA (một ứng dụng đặc quyền của hệ thống) mới có thể liên kết với ứng dụng đó. Dịch vụ phải
Ngoài ra, bạn cũng có thể thêm bộ lọc ý định với
android.service.euicc.action.BIND_CARRIER_PROVISIONING_SERVICE
hành động.
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>
Để triển khai dịch vụ ứng dụng của nhà mạng AIDL, hãy tạo một dịch vụ, mở rộng Stub
và triển khai getActivationCode
và getActivationCodeForEid
. Sau đó, LPA có thể gọi một trong hai phương thức để tìm nạp thông tin kích hoạt hồ sơ
. Ứng dụng của nhà mạng sẽ phản hồi bằng cách gọi
IGetActivationCodeCallback#onSuccess
kèm theo mã kích hoạt nếu mã đó
đã được tìm nạp từ máy chủ của nhà mạng. Nếu không thành công, ứng dụng của nhà mạng
phải phản hồi bằng 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); } } }
Khởi động giao diện người dùng của ứng dụng của nhà mạng trong quy trình kích hoạt LPA
Trên các thiết bị chạy Android 11 trở lên, LPA có thể khởi động giao diện người dùng của một ứng dụng của nhà mạng. Điều này rất hữu ích vì ứng dụng của nhà mạng có thể yêu cầu thêm thông tin từ người dùng trước khi cung cấp mã kích hoạt cho LPA. Ví dụ: các nhà mạng có thể yêu cầu người dùng đăng nhập để kích hoạt số điện thoại của họ hoặc thực hiện quá trình chuyển khác luôn miễn phí.
Đây là quy trình bắt đầu giao diện người dùng của một ứng dụng của nhà mạng trong LPA:
LPA khởi chạy quy trình kích hoạt của ứng dụng của nhà mạng bằng cách gửi Ý định
android.service.euicc.action.START_CARRIER_ACTIVATION
đối với gói ứng dụng của nhà mạng chứa hành động. (Người nhận ứng dụng của nhà mạng phải được bảo vệ trong phần khai báo tệp kê khai bằngandroid:permission="android.permission.WRITE_EMBEDDED_SUBSCRIPTIONS"
thành tránh nhận ý định từ các ứng dụng không phải 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);
Ứng dụng của nhà mạng thực hiện công việc bằng cách sử dụng giao diện người dùng riêng. Ví dụ: ghi nhật ký trong người dùng hoặc gửi yêu cầu HTTP đến máy chủ phụ trợ của nhà mạng.
Ứng dụng của nhà mạng phản hồi LPA bằng cách gọi
setResult(int, Intent)
vàfinish()
.- Nếu ứng dụng của nhà mạng phản hồi bằng
RESULT_OK
, thì LPA tiếp tục quy trình kích hoạt. Nếu ứng dụng của nhà mạng xác định rằng người dùng nên quét mã QR thay vì để LPA ràng buộc nhà mạng dịch vụ của ứng dụng, thì ứng dụng của nhà mạng sẽ phản hồi LPA bằng cách sử dụngsetResult(int, Intent)
choRESULT_OK
và một thực thểIntent
chứa boolean bổ sung Đã đặtandroid.telephony.euicc.extra.USE_QR_SCANNER
thànhtrue
. LPA sau đó kiểm tra phần bổ sung và chạy trình quét QR thay vì liên kết cách triển khaiICarrierEuiccProvisioningService
của ứng dụng nhà mạng. - Nếu ứng dụng của nhà mạng gặp sự cố hoặc phản hồi bằng
RESULT_CANCELED
(đây là mã phản hồi mặc định), LPA sẽ huỷ eSIM quy trình kích hoạt. - Nếu ứng dụng của nhà mạng phản hồi bằng thao tác nào đó không phải là
RESULT_OK
hoặcRESULT_CANCELED
, LPA sẽ coi đây là lỗi.
Vì lý do bảo mật, LPA không nên trực tiếp chấp nhận mã kích hoạt được cung cấp trong ý định kết quả để đảm bảo rằng không phải LPA Người gọi không thể nhận mã kích hoạt từ ứng dụng của nhà mạng.
- Nếu ứng dụng của nhà mạng phản hồi bằng
Chạy quy trình kích hoạt LPA trong một ứng dụng của nhà mạng
Kể từ Android 11, các ứng dụng của nhà mạng có thể dùng API eUICC để khởi động LUI cho eSIM để kích hoạt tài khoản. Phương thức này sẽ hiển thị giao diện người dùng quy trình kích hoạt eSIM của LPA để kích hoạt hồ sơ eSIM. Sau đó, LPA sẽ gửi thông báo phát đi khi hồ sơ eSIM kết thúc.
LPA phải khai báo một hoạt động bao gồm bộ lọc ý định với
android.service.euicc.action.START_EUICC_ACTIVATION
hành động. Mức độ ưu tiên của bộ lọc ý định phải được đặt thành một giá trị khác 0 trong trường hợp nhiều có các triển khai trên thiết bị. Ví dụ:<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>
Ứng dụng của nhà mạng thực hiện công việc bằng cách sử dụng giao diện người dùng riêng. Ví dụ: ghi nhật ký trong người dùng hoặc gửi yêu cầu HTTP đến máy chủ phụ trợ của nhà mạng.
Tại thời điểm này, ứng dụng của nhà mạng phải sẵn sàng cung cấp lệnh kích hoạt mã thông qua việc triển khai
ICarrierEuiccProvisioningService
. Chiến lược phát hành đĩa đơn ứng dụng của nhà mạng khởi chạy LPA bằng cách gọistartActivityForResult(Intent, int)
bằngandroid.telephony.euicc.action.START_EUICC_ACTIVATION
hành động. LPA cũng kiểm tra boolean bổ sungandroid.telephony.euicc.extra.USE_QR_SCANNER
. Nếu giá trị làtrue
, thì LPA chạy trình quét QR để cho phép người dùng quét mã QR của hồ sơ.Ở phía LPA, LPA liên kết với Phương thức triển khai
ICarrierEuiccProvisioningService
để tìm nạp lệnh kích hoạt và tải hồ sơ tương ứng xuống. LPA hiển thị tất cả thông tin cần thiết Các thành phần trên giao diện người dùng trong quá trình tải xuống, chẳng hạn như màn hình tải.Khi quy trình kích hoạt LPA hoàn tất, LPA sẽ phản hồi ứng dụng của nhà mạng có mã kết quả mà ứng dụng của nhà mạng sẽ xử lý
onActivityResult(int, int, Intent)
.- Nếu LPA tải thành công hồ sơ eSIM mới xuống, thiết bị
phản hồi bằng
RESULT_OK
. - Nếu người dùng huỷ kích hoạt hồ sơ eSIM trong LPA, thì thao tác đó
phản hồi bằng
RESULT_CANCELED
. - Nếu LPA phản hồi bằng lệnh không phải là
RESULT_OK
hoặcRESULT_CANCELED
, ứng dụng của nhà mạng sẽ coi đây là lỗi.
Vì lý do bảo mật, LPA không chấp nhận mã kích hoạt ngay trong ý định đã cung cấp để đảm bảo rằng những phương thức gọi không phải LLP không thể lấy thông tin mã kích hoạt từ ứng dụng của nhà mạng.
- Nếu LPA tải thành công hồ sơ eSIM mới xuống, thiết bị
phản hồi bằng
Hỗ trợ nhiều eSIM
Đối với các thiết bị chạy Android 10 trở lên,
Lớp EuiccManager
hỗ trợ thiết bị
bằng nhiều eSIM. Các thiết bị có một eSIM duy nhất mà sẽ nâng cấp lên
Android 10
không yêu cầu sửa đổi việc triển khai LPA với vai trò là nền tảng
tự động liên kết thực thể EuiccManager
với eUICC mặc định. Chiến lược phát hành đĩa đơn
eUICC mặc định được xác định theo nền tảng đối với các thiết bị có phiên bản HAL (Lớp trừu tượng phần cứng) vô tuyến
1.2 trở lên và theo LPA đối với các thiết bị có phiên bản HAL vô tuyến thấp hơn
1.2.
Yêu cầu
Để hỗ trợ nhiều eSIM, thiết bị phải có nhiều eUICC. Điều này có thể có thể là eUICC tích hợp sẵn hoặc khe cắm SIM thực, trong đó eUICC có thể tháo rời đã chèn.
Cần có Radio HAL phiên bản 1.2 trở lên để hỗ trợ nhiều eSIM. Lớp trừu tượng phần cứng (HAL) qua đài phát thanh phiên bản 1.4 và RadioConfig HAL phiên bản 1.2 được khuyến nghị.
Triển khai
Để hỗ trợ nhiều eSIM (bao gồm cả eUICC có thể tháo rời hoặc SIM có thể lập trình),
LPA phải triển khai
EuiccService
!
nhận được ID vị trí tương ứng với ID thẻ do người gọi cung cấp.
Chiến lược phát hành đĩa đơn
non_removable_euicc_slots
tài nguyên được chỉ định trong
arrays.xml
là một mảng số nguyên đại diện cho mã nhận dạng vị trí của mã nhận dạng được tích hợp sẵn trong thiết bị
eUICC. Bạn phải chỉ định tài nguyên này để cho phép nền tảng xác định
liệu một eUICC được chèn có thể tháo rời được hay không.
Ứng dụng của nhà mạng cho thiết bị có nhiều eSIM
Khi tạo ứng dụng của nhà mạng cho một thiết bị có nhiều eSIM, hãy dùng
createForCardId
trong EuiccManager
để tạo đối tượng EuiccManager
được ghim vào
ID thẻ được cung cấp. Mã thẻ là một giá trị số nguyên nhận dạng duy nhất một UICC
hoặc eUICC trên thiết bị.
Để lấy mã thẻ cho eUICC mặc định của thiết bị, hãy sử dụng
getCardIdForDefaultEuicc
trong TelephonyManager
. Phương thức này trả về
UNSUPPORTED_CARD_ID
nếu phiên bản HAL của đài phát thanh thấp hơn 1.2 và trả về
UNINITIALIZED_CARD_ID
nếu thiết bị chưa đọc eUICC.
Bạn cũng có thể lấy mã thẻ từ
getUiccCardsInfo
và getUiccSlotsInfo
(API hệ thống) trong TelephonyManager
và
getCardId
trong SubscriptionInfo
.
Khi một đối tượng EuiccManager
được tạo thực thể bằng một mã thẻ cụ thể, tất cả
các hoạt động đều được chuyển hướng đến eUICC bằng mã thẻ đó. Nếu eUICC trở thành
không kết nối được (ví dụ: khi thiết bị bị tắt hoặc bị xoá) EuiccManager
không
hoạt động lâu hơn.
Bạn có thể dùng các mã mẫu sau để tạo một ứng dụng của nhà mạng.
Ví dụ 1: Sử dụng gói thuê bao đang hoạt động và tạo thực thể 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);
Ví dụ 2: Lặp lại thông qua UICC và tạo thực thể EuiccManager
cho một
eUICC có thể xoá
// 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);
}
Xác nhận kết quả
AOSP không đi kèm với triển khai LPA và bạn sẽ không được dự kiến có sẵn LPA trên tất cả bản dựng Android (không phải mọi điện thoại hỗ trợ eSIM). Cho lý do là vì không có trường hợp thử nghiệm CTS toàn diện. Tuy nhiên, các trường hợp kiểm thử cơ bản có sẵn trong AOSP để đảm bảo các API eUICC bị lộ đều hợp lệ trong các bản dựng Android.
Bạn phải đảm bảo bản dựng vượt qua các trường hợp kiểm thử CTS sau đây (đối với API): /platform/cts/tests/tests/telephony/current/src/android/telephony/euicc/cts.
Các nhà mạng triển khai ứng dụng của nhà mạng nên thực hiện quy trình nội bộ thông thường đảm bảo chất lượng chu kỳ để đảm bảo tất cả các tính năng được triển khai đều hoạt động như mong đợi. Tại tối thiểu, ứng dụng của nhà mạng phải liệt kê được tất cả hồ sơ gói thuê bao thuộc sở hữu của cùng một nhà cung cấp dịch vụ, tải xuống và cài đặt hồ sơ, kích hoạt một dịch vụ trên hồ sơ, chuyển đổi giữa các hồ sơ và xoá hồ sơ.
Nếu tự tạo LPA, bạn sẽ phải trải qua nhiều quy trình nghiêm ngặt hơn kiểm thử. Bạn nên làm việc với nhà cung cấp modem, chip eUICC hoặc nhà cung cấp hệ điều hành eSIM, Nhà cung cấp và nhà cung cấp SM-DP+ để giải quyết các vấn đề và đảm bảo khả năng tương tác của LPA của bạn trong kiến trúc RSP. Bạn nên thử nghiệm thủ công là không thể tránh khỏi. Để có kết quả kiểm thử tốt nhất, bạn nên làm theo Gói thử nghiệm GSMA SGP.23 RSP.