Android 9的新特性 eSIM LPA

本文深入解析了eSIM技术,介绍了其如何允许移动设备无需实体SIM卡即可下载运营商配置文件并激活服务。详细说明了从Android 9开始,框架如何提供标准API来访问eSIM并管理订阅配置文件,包括实现LPA应用、使用EuiccManager和EuiccCardManager进行远程SIM配置等关键操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载:

https://source.android.com/devices/tech/connect/esim-overview

说简单点呢,eSIM就是Google Android 9支持的一个新特性。达到的目的是不用实际的sim卡,也能享受到运营商的相关服务。

Implementing eSIM

Embedded SIM (eSIM, or eUICC) is the latest technology to allow mobile users to download a carrier profile and activate a carrier's service without having a physical SIM card. It is a global specification driven by the GSMA that enables remote SIM provisioning of any mobile device. Starting with Android 9, the Android framework provides standard APIs for accessing eSIM and managing subscription profiles on the eSIM. These eUICC APIs enable third parties to develop their own carrier apps and Local Profile Assistants (LPAs) on eSIM-enabled Android devices.

The LPA is a standalone, system application that should be included in the Android build image. Management of the profiles on the eSIM is generally done by the LPA, as it serves as a bridge between the SM-DP+ (remote service that prepares, stores, and delivers profile packages to devices) and the eUICC chip. The LPA APK can optionally include a UI component, called the LPA UI or LUI, to provide a central place for the end user to manage all embedded subscription profiles. The Android framework automatically discovers and connects to the best available LPA, and routes all the eUICC operations through an LPA instance.

Simplified Remote SIM Provisioning (RSP) architecture

Figure 1. Simplified Remote SIM Provisioning (RSP) architecture

Mobile network operators interested in creating a carrier app should look at the APIs in EuiccManager, which provides high-level profile management operations such as downloadSubscription()switchToSubscription(), anddeleteSubscription().

If you are a device OEM interested in creating your own LPA system app, you must extend EuiccService for the Android framework to connect to your LPA services. In addition, you should use the APIs in EuiccCardManager, which provides ES10x functions based on GSMA Remote SIM Provisioning (RSP) v2.0. These functions are used to issue commands to the eUICC chip, such as prepareDownload()loadBoundProfilePackage()retrieveNotificationList(), and resetMemory().

The APIs in EuiccManager require a properly implemented LPA app to function and the caller of EuiccCardManagerAPIs must be an LPA. This is enforced by the Android framework.

Making a carrier app

The eUICC APIs in Android 9 make it possible for mobile network operators to create carrier-branded applications to manage their profiles directly. This includes downloading and deleting subscription profiles owned by the carrier, as well as switching to a profile owned by a carrier.

EuiccManager

EuiccManager is the main entry point for applications to interact with the LPA. This includes carrier apps that download, delete, and switch to subscriptions owned by the carrier. This also includes the LUI system app, which provides a central location/UI for managing all embedded subscriptions, and can be a separate app from the one that provides the EuiccService.

To use the public APIs, a carrier app must first obtain the instance of EuiccManager through Context#getSystemService:

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

 

You should check whether eSIM is supported on the device before performing any eSIM operations. EuiccManager#isEnabled() generally returns true if the android.hardware.telephony.euicc feature is defined and an LPA package is present.

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

 

To get information about the eUICC hardware and the eSIM OS version:

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

 

Many APIs, such as downloadSubscription() and switchToSubscription(), use PendingIntent callbacks as they may take seconds or even minutes to complete. The PendingIntent is sent with a result code in theEuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_ space, which provides framework-defined error codes, as well as an arbitrary detailed result code propagated from the LPA as EXTRA_EMBEDDED_SUBSCRIPTION_DETAILED_CODE, allowing the carrier app to track for logging/debugging purposes. The PendingIntent must be a BroadcastReceiver.

To download a given DownloadableSubscription (created from an activation code or a QR code):

// 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*/);
                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);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent,
        PendingIntent.FLAG_UPDATE_CURRENT);
mgr.downloadSubscription(sub, true /* switchAfterDownload */,
        callbackIntent);

 

To switch to a subscription given the subscription ID:

// 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);
PendingIntent callbackIntent = PendingIntent.getBroadcast(
        getContext(), 0 /* requestCode */, intent,
        PendingIntent.FLAG_UPDATE_CURRENT);
mgr.switchToSubscription(1 /* subscriptionId */, callbackIntent);

 

For a complete list of EuiccManager APIs and code examples, see eUICC APIs.

Resolvable errors

There are some cases where the system is unable to complete the eSIM operation but the error can be resolved by the user. For example, downloadSubscription may fail if the profile metadata indicates that a carrier confirmation code is required. Or switchToSubscription may fail if the carrier app has carrier privileges over the destination profile (i.e. carrier owns the profile) but doesn't have carrier privileges over the currently enabled profile, and hence user consent is required.

For these cases, the caller's callback is called withEuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR. The callback Intent will contain internal extras such that when the caller passes it to EuiccManager#startResolutionActivity, resolution can be requested through the LUI. Using the confirmation code for example again,EuiccManager#startResolutionActivity triggers an LUI screen that allows the user to enter a confirmation code; after the code is entered, the download operation is resumed. This approach provides the carrier app with full control over when the UI is shown, but gives the LPA/LUI an extensible method for adding new handling of user-recoverable issues in the future without needing client apps to change.

Android 9 defines these resolvable errors in EuiccService, which the LUI should handle:

/**
 * 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 input carrier confirmation code. */
public static final String ACTION_RESOLVE_CONFIRMATION_CODE =
        "android.service.euicc.action.RESOLVE_CONFIRMATION_CODE";

 

Carrier privileges

If you are a carrier developing your own carrier app that calls EuiccManager to download profiles onto a device, your profile should include carrier privilege rules corresponding to your carrier app in the metadata. This is because subscription profiles belonging to different carriers can co-exist in the eUICC of a device, and each carrier app should only be allowed to access the profiles owned by that carrier. For example, carrier A should not be able to download, enable, or disable a profile owned by carrier B.

To ensure a profile is only accessible to its owner, Android uses a mechanism to grant special privileges to the profile owner's app (i.e. carrier app). The Android platform loads certificates stored in the profile's Access Rule File (ARF) and grants permission to apps signed by these certificates to make calls to EuiccManager APIs. The high-level process is described below:

  1. Operator signs the carrier app APK; the apksigner tool attaches the public-key certificate to the APK.
  2. Operator/SM-DP+ prepares a profile and its metadata, which include an ARF that contains:

    1. Signature (SHA-1 or SHA-256) of the carrier app's public-key certificate (required)
    2. Package name of the carrier app (optional)
  3. Carrier app tries to perform an eUICC operation via EuiccManager API.

  4. Android platform verifies SHA-1 or SHA-256 hash of the caller app's certificate matches the signature of the certificate obtained from the target profile's ARF. If the package name of the carrier app is included in the ARF, it must also match the package name of the caller app.

  5. After the signature and the package name (if included) are verified, the carrier privilege is granted to the caller app over the target profile.

Because profile metadata can be available outside of the profile itself (so that LPA can retrieve the profile metadata from SM-DP+ before the profile is downloaded, or from ISD-R when the profile is disabled), it should contain the same carrier privilege rules as in the profile.

The eUICC OS and SM-DP+ must support a proprietary tag BF76 in the profile metadata. The tag content should be the same carrier privilege rules as returned by the ARA (Access Rule Applet) defined in UICC Carrier Privileges:

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] BIT STRING (SIZE(8))  -- Tag DB
    }
}

 

For more details on app signing, see Sign your app. For details on carrier privileges, see UICC Carrier Privileges.

Making an LPA app

You can implement your own LPA, which must be hooked up with Android Euicc APIs. The following sections give a brief overview of making an LPA app and integrating it with the Android system.

Hardware/modem requirements

The LPA and the eSIM OS on the eUICC chip must support at least GSMA RSP (Remote SIM Provisioning) v2.0 or v2.2. You should also plan to use SM-DP+ and SM-DS servers that have a matching RSP version. For detailed RSP architecture, seeGSMA SGP.21 RSP Architecture Specification.

In addition, to integrate with the eUICC APIs in Android 9, the device modem should send terminal capabilities with the support for eUICC capabilities encoded (Local Profile Management and Profile Download). It also needs to implement the following APIs:

  • IRadio HAL v1.1: setSimPower
  • IRadio HAL v1.2: getIccCardStatus
  • IRadioConfig HAL v1.0: getSimSlotsStatus

The modem should recognize the eSIM with the default boot profile enabled as a valid SIM and keep the SIM power on.

For a complete list of modem requirements, see Modem Requirements for eSIM Support.

EuiccService

An LPA consists of two separate components (may both be implemented in the same APK): the LPA backend, and the LPA UI or LUI.

To implement the LPA backend, you must extend EuiccService and declare this service in your manifest file. The service must require the android.permission.BIND_EUICC_SERVICE system permission to ensure that only the system can bind to it. The service must also include an intent filter with the android.service.euicc.EuiccServiceaction. The priority of the intent filter should be set to a non-zero value in case multiple implementations are present on the device. For example:

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

 

Internally, the Android framework determines the active LPA and interacts with it as needed to support the Android eUICC APIs. PackageManager is queried for all apps with the android.permission.WRITE_EMBEDDED_SUBSCRIPTIONSpermission, which specifies a service for the android.service.euicc.EuiccService action. The service with the highest priority is selected. If no service is found, LPA support is disabled.

To implement the LUI, you must provide an activity for the following actions:

  • android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS
  • android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION

As with the service, each activity must require the android.permission.BIND_EUICC_SERVICE system permission. Each should have an intent filter with the appropriate action, the android.service.euicc.category.EUICC_UIcategory, and a non-zero priority. Similar logic is used to pick the implementations for these activities as with picking the implementation of EuiccService. For example:

<activity android:name=".MyLuiActivity"
          android:exported="true"
          android:permission="android.permission.BIND_EUICC_SERVICE">
    <intent-filter android:priority="100">
        <action android:name=
             "android.telephony.euicc.action.MANAGE_EMBEDDED_SUBSCRIPTIONS" />
        <action android:name=
             "android.telephony.euicc.action.PROVISION_EMBEDDED_SUBSCRIPTION" />
        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.service.euicc.category.EUICC_UI" />
    </intent-filter>
</activity>

 

This implies that the UI implementing these screens can come from a different APK from the one that implementsEuiccService. Whether to have a single APK or multiple APKs (e.g. one that implements EuiccService and one that provides LUI activities) is a design choice.

EuiccCardManager

EuiccCardManager is the interface for communicating with the eSIM chip. It provides ES10 functions (as described in the GSMA RSP spec) and handles the low-level APDU request/response commands as well as ASN.1 parsing.EuiccCardManager is a system API and can be called only by system-privileged applications.

Carrier apps, LPA, and Euicc APIs

Figure 2. Both carrier app and LPA use Euicc APIs

The profile operation APIs through EuiccCardManager require the caller to be an LPA. This is enforced by the Android framework. This means the caller must extend the EuiccService and be declared in your manifest file, as described in the previous sections.

Similar to the EuiccManager, to use the EuiccCardManager APIs, your LPA must first obtain the instance of EuiccCardManager through Context#getSystemService:

EuiccCardManager cardMgr = context.getSystemService(Context.EUICC_CARD_SERVICE);

 

Then, to get all the profiles on the 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);

 

Internally, EuiccCardManager binds to EuiccCardController (which runs in the phone process) through an AIDL interface, and each EuiccCardManager method receives its callback from the phone process through a different, dedicated AIDL interface. When using EuiccCardManager APIs, the caller (LPA) must provide an Executor through which the callback is invoked. This Executor may run on a single thread or on a thread pool of your choice.

Most EuiccCardManager APIs have the same usage pattern. For example, to load a bound profile package onto the eUICC:

...
cardMgr.loadBoundProfilePackage(eid, boundProfilePackage,
        AsyncTask.THREAD_POOL_EXECUTOR, callback);

 

To switch to a different profile with a given ICCID:

...
cardMgr.switchToProfile(eid, iccid, true /* refresh */,
        AsyncTask.THREAD_POOL_EXECUTOR, callback);

 

To get the default SM-DP+ address from the eUICC chip:

...
cardMgr.requestDefaultSmdpAddress(eid, AsyncTask.THREAD_POOL_EXECUTOR,
        callback);

 

To retrieve a list of notifications of the given notification events:

...
cardMgr.listNotifications(eid,
        EuiccNotification.Event.INSTALL
              | EuiccNotification.Event.DELETE /* events */,
        AsyncTask.THREAD_POOL_EXECUTOR, callback);

 

Validation

AOSP does not come with an LPA implementation and you are not expected to have an LPA available on all Android builds (not every phone supports eSIM). For this reason, there are no end-to-end CTS test cases. However, basic test cases are available in AOSP to ensure the exposed eUICC APIs are valid in Android builds.

You should make sure the builds pass the following CTS test cases (for public APIs):

https://android.googlesource.com/platform/cts/+/master/tests/tests/telephony/src/android/telephony/

Carriers implementing a carrier app should go through their normal in-house quality assurance cycles to ensure all implemented features are working as expected. At the minimum, the carrier app should be able to list all the subscription profiles owned by the same operator, download and install a profile, activate service on the profile, switch between profiles, and delete profiles.

If you are making your own LPA, you should go through much more rigorous testing. You should work with your modem vendor, eUICC chip or eSIM OS vendor, SM-DP+ vendors, and carriers to resolve issues and ensure interoperability of your LPA within the RSP architecture. A good amount of manual testing is inevitable. For best test coverage, you should follow the GSMA SGP.23 RSP Test Plan.

### eSIM手机在5G SA模式下的支持情况 eSIM技术支持的5G独立组网(SA)模式能够显著提升用户体验,尤其是在低延迟和高灵活性方面。OPPO作为行业先锋,在其旗舰机型Find X3 Pro中实现了全球首次对5G SA架构的支持[^1]。这一创新不仅标志着智能手机技术的进步,还体现了eSIM技术和5G网络深度融合的可能性。 #### 配置方法概述 为了使eSIM手机能够在5G SA模式下正常运行,需完成以下几个方面的设置: 1. **设备兼容性确认** 用户应确保所使用的手机型号支持eSIM功能并已启用5G SA模式。例如,OPPO Find X3 Pro已经内置了针对5G SA优化的技术方案[^2]。 2. **运营商服务开通** 使用eSIM前,用户需要联系所在地区的移动通信服务商申请激活相应的套餐和服务计划。部分国家和地区可能尚未全面部署5G SA基础设施,因此建议提前咨询运营商关于覆盖范围和支持状态的信息[^3]。 3. **软件更新至最新版本** 厂商通常会通过固件升级来增强硬件对于新标准协议栈的支持能力。保持操作系统处于最新状态有助于获得最佳性能表现以及修复潜在漏洞问题。 4. **手动切换到5G SA网络偏好选项** 在大多数安卓系统的设置菜单里,“双卡与移动网络”子项提供了调整优先连接类型的入口。选择“仅限5G (SA)”而非默认混合模式(即NSA+SA),即可强制让终端尝试接入纯粹基于独立架构构建起来的新一代无线宽带环境[^4]。 ```bash # 示例命令用于检查当前是否成功连入目标频段 adb shell dumpsys telephony.registry | grep dataNetworkType ``` 上述脚本可以帮助开发者或者高级用户验证实际建立链接时采用的具体制式类别。 ---
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值