eUICC API

В Android 9 API-интерфейсы управления профилями (публичные и @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

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

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

Получает экземпляр EuiccManager через Context#getSystemService . Подробности см. в getSystemService .

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

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

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

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

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

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

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

Получить EuiccInfo (публично)

Получает информацию о eUICC. Здесь указана версия ОС. Подробности см. в getEuiccInfo .

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

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

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

Вызывающая сторона должна либо иметь разрешение WRITE_EMBEDDED_SUBSCRIPTIONS , либо иметь привилегии оператора связи для целевой подписки. Подробности см. в разделе 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);

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

Переключает (включает) данную подписку. Вызывающий абонент должен либо иметь WRITE_EMBEDDED_SUBSCRIPTIONS , либо иметь привилегии оператора связи для текущей включенной подписки и целевой подписки. Дополнительные сведения см. в разделе 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);

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

(Доступно с Android 13) Переключает (включает) данную подписку с указанным индексом порта. Вызывающий абонент должен либо иметь WRITE_EMBEDDED_SUBSCRIPTIONS , либо иметь привилегии оператора связи для текущей включенной подписки и целевой подписки. Дополнительные сведения см. в разделе 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);

Доступен ли SIM-порт (общедоступный)

public boolean isSimPortAvailable(int portIndex)

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

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

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

Удалить все подписки (системный 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 , см. Константы .