API eUICC

Trong Android 9, các API quản lý hồ sơ (công khai và @SystemApi) có sẵn thông qua lớp EuiccManager . API giao tiếp eUICC (chỉ (@SystemApi) có sẵn thông qua lớp EuiccCardManager .

Giới thiệu về eUICC

Nhà cung cấp dịch vụ có thể tạo ứng dụng của nhà cung cấp dịch vụ bằng EuiccManager để quản lý hồ sơ, như trong Hình 1. Ứng dụng của nhà cung cấp dịch vụ không cần phải là ứng dụng hệ thống nhưng cần có các đặc quyền của nhà cung cấp dịch vụ do hồ sơ eUICC cấp. Ứng dụng LPA (phụ trợ LUI và LPA) cần phải là ứng dụng hệ thống (tức là có trong hình ảnh hệ thống) để gọi @SystemApi.

Điện thoại Android có ứng dụng Carrier và OEM LPA

Hình 1. Điện thoại Android có ứng dụng của nhà mạng và OEM LPA

Ngoài logic gọi EuiccCardManager và nói chuyện với eUICC, ứng dụng LPA phải triển khai những điều sau:

  • Máy khách SM-DP+ giao tiếp với máy chủ SM-DP+ để xác thực và tải xuống hồ sơ
  • [Tùy chọn] SM-DS để có thêm hồ sơ có thể tải xuống tiềm năng
  • Xử lý thông báo gửi thông báo đến máy chủ để cập nhật trạng thái hồ sơ
  • [Tùy chọn] Quản lý khe cắm bao gồm chuyển đổi giữa logic eSIM và pSIM. Đây là tùy chọn nếu điện thoại chỉ có chip eSIM.
  • eSIM OTA

Mặc dù có thể có nhiều ứng dụng LPA trong điện thoại Android nhưng chỉ có thể chọn một LPA làm LPA hoạt động thực tế dựa trên mức độ ưu tiên được xác định trong tệp AndroidManifest.xml của mỗi ứng dụng.

Sử dụng EuiccManager

API LPA được công khai thông qua EuiccManager (trong gói android.telephony.euicc ). Ứng dụng của nhà cung cấp dịch vụ có thể lấy phiên bản của EuiccManager và gọi các phương thức trong EuiccManager để lấy thông tin eUICC và quản lý đăng ký (được gọi là hồ sơ trong tài liệu GSMA RSP) dưới dạng phiên bản SubscriptionInfo.

Để gọi các API công khai bao gồm các hoạt động tải xuống, chuyển đổi và xóa đăng ký, ứng dụng của nhà cung cấp dịch vụ phải có các đặc quyền bắt buộc. Đặc quyền của nhà cung cấp dịch vụ được nhà cung cấp dịch vụ di động thêm vào trong siêu dữ liệu hồ sơ. API eUICC thực thi các quy tắc đặc quyền của nhà cung cấp dịch vụ tương ứng.

Nền tảng Android không xử lý các quy tắc chính sách hồ sơ. Nếu quy tắc chính sách được khai báo trong siêu dữ liệu hồ sơ, LPA có thể chọn cách xử lý quy trình cài đặt và tải xuống hồ sơ. Ví dụ: OEM LPA bên thứ ba có thể xử lý các quy tắc chính sách bằng mã lỗi đặc biệt (mã lỗi được chuyển từ OEM LPA đến nền tảng, sau đó nền tảng chuyển mã tới OEM LUI).

Để biết thông tin về nhiều API cấu hình đã bật, hãy xem Nhiều cấu hình đã bật .

API

Bạn có thể tìm thấy các API sau trong tài liệu tham khảo EuiccManagerEuiccManager.java .

Nhận phiên bản (công khai)

Lấy phiên bản của EuiccManager thông qua Context#getSystemService . Để biết chi tiết, xem getSystemService .

EuiccManager mgr = (EuiccManager) context.getSystemService(Context.EUICC_SERVICE);

Đã bật kiểm tra (công khai)

Kiểm tra xem đăng ký nhúng có được bật hay không. Điều này cần được kiểm tra trước khi truy cập API LPA. Để biết chi tiết, xem isEnabled .

boolean isEnabled = mgr.isEnabled();
if (!isEnabled) {
    return;
}

Nhận EID (công khai)

Lấy EID xác định phần cứng eUICC. Điều này có thể không có giá trị nếu eUICC chưa sẵn sàng. Người gọi phải có đặc quyền của nhà mạng hoặc quyền READ_PRIVILEGED_PHONE_STATE . Để biết chi tiết, xem getEid .

String eid = mgr.getEid();
if (eid == null) {
  // Handle null case.
}

Nhận EuiccInfo (công khai)

Nhận thông tin về eUICC. Điều này chứa phiên bản hệ điều hành. Để biết chi tiết, xem getEuiccInfo .

EuiccInfo info = mgr.getEuiccInfo();
String osVer = info.getOsVersion();

Đăng ký tải xuống (công khai)

Tải xuống đăng ký nhất định (được gọi là "hồ sơ" trong tài liệu GSMA RSP). Việc đăng ký có thể được tạo từ mã kích hoạt. Ví dụ: mã kích hoạt có thể được phân tích cú pháp từ mã QR. Tải xuống đăng ký là một hoạt động không đồng bộ.

Người gọi phải có quyền WRITE_EMBEDDED_SUBSCRIPTIONS hoặc có đặc quyền của nhà cung cấp dịch vụ đối với đăng ký mục tiêu. Để biết chi tiết, xem downloadSubscription .

// Register receiver.
String action = "download_subscription";
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),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Download subscription asynchronously.
DownloadableSubscription sub =
        DownloadableSubscription.forActivationCode(code /* encodedActivationCode*/);
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.downloadSubscription(sub, true /* switchAfterDownload */, callbackIntent);

Chuyển đổi đăng ký (công khai)

Chuyển sang (cho phép) đăng ký đã cho. Người gọi phải có WRITE_EMBEDDED_SUBSCRIPTIONS hoặc có đặc quyền của nhà cung cấp dịch vụ đối với đăng ký được kích hoạt hiện tại và đăng ký mục tiêu. Để biết chi tiết, xem switchToSubscription .

// Register receiver.
String action = "switch_to_subscription";
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),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Switch to a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);

Chuyển đổi đăng ký với cổng (công khai)

(Có sẵn từ Android 13) Chuyển sang (bật) đăng ký đã cho với chỉ mục cổng được chỉ định. Người gọi phải có WRITE_EMBEDDED_SUBSCRIPTIONS hoặc có đặc quyền của nhà cung cấp dịch vụ đối với đăng ký được kích hoạt hiện tại và đăng ký mục tiêu. Để biết chi tiết, xem switchToSubscription .

// Register receiver.
String action = "switch_to_subscription";
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),
        "example.broadcast.permission" /* broadcastPermission*/, null /* handler */);

// Switch to a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, 0 /*portIndex*/, callbackIntent);

Cổng SIM có sẵn không (công khai)

public boolean isSimPortAvailable(int portIndex)

(Có sẵn từ Android 13) Trả về xem có chỉ mục cổng chuyển hay không. Một cổng khả dụng nếu cổng đó không kích hoạt đăng ký hoặc ứng dụng gọi điện có đặc quyền của nhà cung cấp dịch vụ đối với đăng ký được cài đặt trên cổng đã chọn. Để biết chi tiết, hãy xem isSimPortAvailable .

Xóa đăng ký (công khai)

Xóa đăng ký có ID đăng ký. Nếu đăng ký hiện đang hoạt động thì trước tiên nó sẽ bị vô hiệu hóa. Người gọi phải có WRITE_EMBEDDED_SUBSCRIPTIONS hoặc đặc quyền của nhà cung cấp dịch vụ đối với đăng ký mục tiêu. Để biết chi tiết, xem deleteSubscription .

// Register receiver.
String action = "delete_subscription";
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),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Delete a subscription asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.deleteSubscription(1 /* subscriptionId */, callbackIntent);

Xóa tất cả đăng ký (API hệ thống)

Xóa tất cả đăng ký trên một thiết bị. Bắt đầu từ Android 11, bạn nên cung cấp giá trị enum EuiccCardManager#ResetOption để chỉ định xem có xóa tất cả các loại đăng ký thử nghiệm, vận hành hay cả hai loại hay không. Người gọi phải có quyền WRITE_EMBEDDED_SUBSCRIPTIONS .

// Register receiver.
String action = "delete_subscription";
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),
        "example.broadcast.permission" /* broadcastPermission*/,
        null /* handler */);

// Erase all operational subscriptions asynchronously.
Intent intent = new Intent(action);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent, PendingIntent.FLAG_UPDATE_CURRENT);
mgr.eraseSubscriptions(
        EuiccCardManager.RESET_OPTION_DELETE_OPERATIONAL_PROFILES, callbackIntent);

Bắt đầu hoạt động giải quyết (công khai)

Bắt đầu một hoạt động để giải quyết lỗi mà người dùng có thể giải quyết được. Nếu một thao tác trả về EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR , phương thức này có thể được gọi để nhắc người dùng giải quyết vấn đề. Phương thức này chỉ có thể được gọi một lần cho một lỗi cụ thể.

...
mgr.startResolutionActivity(getActivity(), 0 /* requestCode */, resultIntent, callbackIntent);

Hằng số

Để xem danh sách các hằng số public trong EuiccManager , hãy xem Hằng số .