eUICC API

В Android 9 API управления профилями (public и @SystemApi) доступны через класс EuiccManager . Интерфейсы API связи eUICC (только (@SystemApi) доступны через класс EuiccCardManager .

О eUICC

Операторы связи могут создавать приложения оператора с помощью EuiccManager для управления профилями, как показано на рис. 1. Приложения оператора связи не обязательно должны быть системными приложениями, но должны иметь привилегии оператора, предоставленные профилями eUICC. Приложение LPA (LUI и серверная часть LPA) должно быть системным приложением (т. е. включенным в образ системы) для вызова @SystemApi.

Телефон Android с приложением Carrier и OEM LPA

Рис. 1. Телефоны Android с операторским приложением и OEM LPA

Помимо логики вызова EuiccCardManager и взаимодействия с eUICC, приложения LPA должны реализовывать следующее:

  • Клиент SM-DP+ взаимодействует с сервером SM-DP+ для аутентификации и загрузки профилей.
  • [Необязательно] SM-DS, чтобы получить больше потенциальных загружаемых профилей
  • Обработка уведомлений для отправки уведомлений на сервер для обновления состояния профиля
  • [Необязательно] Управление слотами, включая переключение между логикой eSIM и pSIM. Это необязательно, если в телефоне есть только чип eSIM.
  • eSIM ОТА

Хотя в телефоне Android может быть несколько приложений LPA, только одно LPA может быть выбрано в качестве фактического рабочего LPA на основе приоритета, определенного в файле AndroidManifest.xml каждого приложения.

Использование EuiccManager

API-интерфейсы LPA общедоступны через EuiccManager (в пакете android.telephony.euicc ). Приложение оператора связи может получить экземпляр EuiccManager и вызвать методы в EuiccManager , чтобы получить информацию eUICC и управлять подписками (называемыми профилями в документах GSMA RSP) как экземплярами SubscriptionInfo.

Чтобы вызывать общедоступные API, включая операции загрузки, переключения и удаления подписки, приложение оператора связи должно иметь необходимые привилегии. Привилегии оператора добавляются оператором мобильной связи в метаданные профиля. API eUICC соответствующим образом применяет правила привилегий оператора связи.

Платформа Android не поддерживает правила политики профиля. Если правило политики объявлено в метаданных профиля, LPA может выбрать способ обработки загрузки и установки профиля. Например, сторонний OEM LPA может обрабатывать правила политики, используя специальный код ошибки (код ошибки передается от OEM LPA на платформу, затем платформа передает код в OEM LUI).

API

Следующие API можно найти в справочной EuiccManager EuiccManager и EuiccManager.java .

Получить экземпляр (общедоступный)

Получает экземпляр EuiccManager через Context#getSystemService .

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

Проверка включена (общедоступная)

Проверяет, включена ли встроенная подписка. Это следует проверить перед доступом к API LPA.

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

Получить EID (общедоступный)

Получает EID, идентифицирующий оборудование eUICC. Это может быть пустым, если карта eUICC не готова. Вызывающий должен иметь привилегию оператора связи или разрешение READ_PRIVILEGED_PHONE_STATE .

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

Получить EuiccInfo (общедоступный)

Получает информацию о eUICC. Он содержит версию ОС.

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

Скачать подписку (общедоступную)

Загружает данную подписку (называемую «профилем» в документах GSMA RSP). Подписку можно создать из кода активации. Например, код активации можно получить из QR-кода. Загрузка подписки — это асинхронная операция.

Вызывающий должен либо иметь разрешение WRITE_EMBEDDED_SUBSCRIPTIONS , либо иметь привилегии оператора для целевой подписки.

// 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);

Переключить подписку (общедоступную)

Переключает (включает) данную подписку. Вызывающий должен либо иметь WRITE_EMBEDDED_SUBSCRIPTIONS , либо иметь привилегии оператора связи для текущей включенной подписки и целевой подписки.

// 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);

Удалить подписку (общедоступную)

Удаляет подписку с идентификатором подписки. Если подписка в данный момент активна, она сначала отключается. Вызывающий должен иметь 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 */);

// 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);

Удалить все подписки (системный API)

Удаляет все подписки на устройстве. Начиная с Android 11, вы должны указать значение перечисления EuiccCardManager#ResetOption , чтобы указать, нужно ли удалять все тестовые, рабочие или оба типа подписок. Вызывающий должен иметь разрешение 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);

Начать действие по разрешению (общедоступное)

Запускает действие для устранения разрешаемой пользователем ошибки. Если операция возвращает EuiccManager#EMBEDDED_SUBSCRIPTION_RESULT_RESOLVABLE_ERROR , этот метод можно вызвать, чтобы предложить пользователю решить проблему. Этот метод можно вызвать только один раз для конкретной ошибки.

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

Константы

Список public констант в EuiccManager см. в разделе Константы .