diff options
author | Jack Yu <jackyu@google.com> | 2023-05-31 01:12:28 -0700 |
---|---|---|
committer | Jack Yu <jackyu@google.com> | 2023-06-05 21:51:29 +0000 |
commit | eaf216b376887ebd037840f3c76f352986df32d1 (patch) | |
tree | b69a508fd17561ffe60f872f0ab8ce1f4d0c3ee1 /java | |
parent | b07310aeb030300e103a17f2c2f44cd3b5450cbd (diff) | |
download | service_entitlement-eaf216b376887ebd037840f3c76f352986df32d1.tar.gz |
Added acquire configuration support
Added acquire configuration described in GSMA Service
Entitlement Configuration section 6.5.5.
Test: Manual & atest Ts43OperationTest
Bug: 279132691
Change-Id: I1fc709396f2dee1e8850c3d1708bcfb4cdaba0c1
Diffstat (limited to 'java')
3 files changed, 343 insertions, 111 deletions
diff --git a/java/com/android/libraries/entitlement/Ts43Operation.java b/java/com/android/libraries/entitlement/Ts43Operation.java index a49427b..9a0d75d 100644 --- a/java/com/android/libraries/entitlement/Ts43Operation.java +++ b/java/com/android/libraries/entitlement/Ts43Operation.java @@ -61,7 +61,7 @@ import java.util.List; import java.util.Objects; /** - * TS43 operations described in GSMA Service Entitlement Configuration section. + * TS43 operations described in GSMA Service Entitlement Configuration spec. */ public class Ts43Operation { private static final String TAG = "Ts43"; @@ -393,7 +393,102 @@ public class Ts43Operation { public AcquireConfigurationResponse acquireConfiguration( @NonNull AcquireConfigurationRequest acquireConfigurationRequest) throws ServiceEntitlementException { - return null; + Objects.requireNonNull(acquireConfigurationRequest); + + ServiceEntitlementRequest request = ServiceEntitlementRequest.builder() + .setEntitlementVersion(mEntitlementVersion) + .setTerminalId(mImei) + .setAuthenticationToken(mAuthToken) + .build(); + + OdsaOperation operation = OdsaOperation.builder() + .setOperation(OdsaOperation.OPERATION_ACQUIRE_CONFIGURATION) + .setCompanionTerminalId(acquireConfigurationRequest.companionTerminalId()) + .setCompanionTerminalIccid(acquireConfigurationRequest.companionTerminalIccid()) + .setCompanionTerminalEid(acquireConfigurationRequest.companionTerminalEid()) + .setTerminalIccid(acquireConfigurationRequest.terminalIccid()) + .setTerminalEid(acquireConfigurationRequest.terminalEid()) + .setTargetTerminalId(acquireConfigurationRequest.targetTerminalId()) + .setTargetTerminalIccid(acquireConfigurationRequest.targetTerminalIccid()) + .setTargetTerminalEid(acquireConfigurationRequest.targetTerminalEid()) + .build(); + + String rawXml; + try { + rawXml = mServiceEntitlement.performEsimOdsa(acquireConfigurationRequest.appId(), + request, operation); + } catch (ServiceEntitlementException e) { + Log.w(TAG, "acquireConfiguration: Failed to perform ODSA operation. e=" + e); + throw e; + } + + AcquireConfigurationResponse.Builder responseBuilder = + AcquireConfigurationResponse.builder(); + AcquireConfigurationResponse.Configuration.Builder configBuilder = + AcquireConfigurationResponse.Configuration.builder(); + + Ts43XmlDoc ts43XmlDoc = new Ts43XmlDoc(rawXml); + + try { + processGeneralResult(ts43XmlDoc, responseBuilder); + } catch (MalformedURLException e) { + throw new ServiceEntitlementException( + ServiceEntitlementException.ERROR_MALFORMED_HTTP_RESPONSE, + "manageSubscription: Malformed URL " + rawXml); + } + + // Parse service status. + String serviceStatusString = ts43XmlDoc.get(ImmutableList.of( + Ts43XmlDoc.CharacteristicType.APPLICATION, + Ts43XmlDoc.CharacteristicType.PRIMARY_CONFIGURATION), + Ts43XmlDoc.Parm.SERVICE_STATUS); + + if (!TextUtils.isEmpty(serviceStatusString)) { + configBuilder.setServiceStatus(getServiceStatusFromString(serviceStatusString)); + } + + // Parse ICCID + String iccIdString = ts43XmlDoc.get(ImmutableList.of( + Ts43XmlDoc.CharacteristicType.APPLICATION, + Ts43XmlDoc.CharacteristicType.PRIMARY_CONFIGURATION), + Ts43XmlDoc.Parm.ICCID); + + if (!TextUtils.isEmpty(iccIdString)) { + configBuilder.setIccid(iccIdString); + } + + // Parse polling interval + String pollingIntervalString = ts43XmlDoc.get(ImmutableList.of( + Ts43XmlDoc.CharacteristicType.APPLICATION, + Ts43XmlDoc.CharacteristicType.PRIMARY_CONFIGURATION), + Ts43XmlDoc.Parm.POLLING_INTERVAL); + + if (!TextUtils.isEmpty(pollingIntervalString)) { + try { + configBuilder.setPollingInterval(Integer.parseInt(pollingIntervalString)); + } catch (NumberFormatException e) { + Log.w(TAG, "acquireConfiguration: Failed to parse polling interval " + + pollingIntervalString); + } + } + + // Parse download info + DownloadInfo downloadInfo = parseDownloadInfo( + ImmutableList.of( + Ts43XmlDoc.CharacteristicType.APPLICATION, + Ts43XmlDoc.CharacteristicType.PRIMARY_CONFIGURATION, + Ts43XmlDoc.CharacteristicType.DOWNLOAD_INFO), + ts43XmlDoc); + if (downloadInfo != null) { + configBuilder.setDownloadInfo(downloadInfo); + } + + // TODO: Support different type of configuration. + configBuilder.setType( + AcquireConfigurationResponse.Configuration.CONFIGURATION_TYPE_PRIMARY); + + // TODO: Support multiple configurations. + return responseBuilder.setConfigurations(ImmutableList.of(configBuilder.build())).build(); } /** @@ -627,4 +722,29 @@ public class Ts43Operation { Log.d(TAG, "processGeneralResult: Token replaced."); } } + + /** + * Get the service status from string as described in GSMA Service Entitlement Configuration + * section 6.5.4. + * + * @param serviceStatusString Service status in string format defined in GSMA Service + * Entitlement Configuration section 6.5.4. + * + * @return The converted service status. {@link OdsaOperation#SERVICE_STATUS_UNKNOWN} if not + * able to convert. + */ + @ServiceStatus + private int getServiceStatusFromString(@NonNull String serviceStatusString) { + switch (serviceStatusString) { + case Ts43XmlDoc.ParmValues.SERVICE_STATUS_ACTIVATED: + return OdsaOperation.SERVICE_STATUS_ACTIVATED; + case Ts43XmlDoc.ParmValues.SERVICE_STATUS_ACTIVATING: + return OdsaOperation.SERVICE_STATUS_ACTIVATING; + case Ts43XmlDoc.ParmValues.SERVICE_STATUS_DEACTIVATED: + return OdsaOperation.SERVICE_STATUS_DEACTIVATED; + case Ts43XmlDoc.ParmValues.SERVICE_STATUS_DEACTIVATED_NO_REUSE: + return OdsaOperation.SERVICE_STATUS_DEACTIVATED_NO_REUSE; + } + return OdsaOperation.SERVICE_STATUS_UNKNOWN; + } } diff --git a/java/com/android/libraries/entitlement/odsa/AcquireConfigurationOperation.java b/java/com/android/libraries/entitlement/odsa/AcquireConfigurationOperation.java index 9da2092..549063d 100644 --- a/java/com/android/libraries/entitlement/odsa/AcquireConfigurationOperation.java +++ b/java/com/android/libraries/entitlement/odsa/AcquireConfigurationOperation.java @@ -16,6 +16,7 @@ package com.android.libraries.entitlement.odsa; +import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -25,11 +26,18 @@ import com.android.libraries.entitlement.utils.Ts43Constants; import com.android.libraries.entitlement.utils.Ts43Constants.AppId; import com.google.auto.value.AutoValue; +import com.google.common.collect.ImmutableList; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; /** * Acquire configuration operation described in GSMA Service Entitlement Configuration section 6. */ public class AcquireConfigurationOperation { + /** Indicating polling inverval not available. */ + public static final int POLLING_INTERVAL_NOT_AVAILABLE = -1; + /** * HTTP request parameters specific to on device service activation (ODSA) acquire configuration * operation. See GSMA spec TS.43 section 6.2. @@ -47,56 +55,56 @@ public class AcquireConfigurationOperation { * Returns the unique identifier of the companion device, like IMEI. Used by HTTP parameter * {@code companion_terminal_id}. */ - @Nullable + @NonNull public abstract String companionTerminalId(); /** * Returns the ICCID of the companion device. Used by HTTP parameter * {@code companion_terminal_iccid}. */ - @Nullable + @NonNull public abstract String companionTerminalIccid(); /** * Returns the EID of the companion device. Used by HTTP parameter * {@code companion_terminal_eid}. */ - @Nullable + @NonNull public abstract String companionTerminalEid(); /** * Returns the ICCID of the primary device eSIM. Used by HTTP parameter * {@code terminal_iccid}. */ - @Nullable + @NonNull public abstract String terminalIccid(); /** * Returns the eUICC identifier (EID) of the primary device eSIM. Used by HTTP parameter * {@code terminal_eid}. */ - @Nullable + @NonNull public abstract String terminalEid(); /** * Returns the unique identifier of the primary device eSIM, like the IMEI associated with * the eSIM. Used by HTTP parameter {@code target_terminal_id}. */ - @Nullable + @NonNull public abstract String targetTerminalId(); /** * Returns the ICCID primary device eSIM. Used by HTTP parameter * {@code target_terminal_iccid}. */ - @Nullable + @NonNull public abstract String targetTerminalIccid(); /** * Returns the eUICC identifier (EID) of the primary device eSIM. Used by HTTP parameter * {@code target_terminal_eid}. */ - @Nullable + @NonNull public abstract String targetTerminalEid(); /** @@ -254,140 +262,241 @@ public class AcquireConfigurationOperation { * section 6.5.5 table 40. */ @AutoValue - public abstract static class AcquireConfigurationResponse { + public abstract static class AcquireConfigurationResponse extends OdsaResponse { /** - * Integrated Circuit Card Identification - Identifier of the eSIM profile on the device’s - * eSIM. {@code null} if an eSIM profile does not exist for the device. + * Configuration */ - @Nullable - public abstract String iccid(); + @AutoValue + public abstract static class Configuration { + /** + * The configuration type is unknown. + */ + public static final int CONFIGURATION_TYPE_UNKNOWN = -1; - /** - * Indicates the applicable companion device service. {@code null} if not for companion - * configuration. - */ - @Nullable - @CompanionService - public abstract String companionDeviceService(); + /** + * The configuration is for ODSA primary device. + */ + public static final int CONFIGURATION_TYPE_PRIMARY = 1; - /** - * Service status. - * - * @see OdsaOperation#SERVICE_STATUS_UNKNOWN - * @see OdsaOperation#SERVICE_STATUS_ACTIVATED - * @see OdsaOperation#SERVICE_STATUS_ACTIVATING - * @see OdsaOperation#SERVICE_STATUS_DEACTIVATED - * @see OdsaOperation#SERVICE_STATUS_DEACTIVATED_NO_REUSE - */ - @ServiceStatus - public abstract int serviceStatus(); + /** + * The configuration is for companion device. + */ + public static final int CONFIGURATION_TYPE_COMPANION = 2; - /** - * Specifies the minimum interval (in minutes) with which the device application may poll - * the ECS to refresh the current {@link #serviceStatus()} using - * {@link AcquireConfigurationRequest}. This parameter will be present only when - * {@link #serviceStatus()} is {@link OdsaOperation#SERVICE_STATUS_ACTIVATING}. If parameter - * is not present or value is 0, this polling procedure is not triggered and ODSA - * app will keep waiting for any external action to continue the flow. - * - * The maximum number of {@link AcquireConfigurationRequest} before sending a - * {@link #serviceStatus()} with {@link OdsaOperation#SERVICE_STATUS_DEACTIVATED_NO_REUSE} - * will be defined as an ECS configuration variable (MaxRefreshRequest). - */ - public abstract int pollingInterval(); + /** + * The configuration is for server-initiated ODSA. + */ + public static final int CONFIGURATION_TYPE_ENTERPRISE = 3; - /** - * Specifies how and where to download the eSIM profile associated with the device. - * Present in case the profile is to be downloaded at this stage. - */ - @Nullable - public abstract DownloadInfo downloadInfo(); + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + CONFIGURATION_TYPE_UNKNOWN, + CONFIGURATION_TYPE_PRIMARY, + CONFIGURATION_TYPE_COMPANION, + CONFIGURATION_TYPE_ENTERPRISE + }) + public @interface ConfigurationType {} - /** - * Includes all information collected by the ES of the companion device. - */ - @Nullable - public abstract CompanionDeviceInfo companionDeviceInfo(); + /** + * Indicates the configuration type. + */ + @ConfigurationType + public abstract int type(); - /** - * @return The builder. - */ - public static Builder builder() { - return new AutoValue_AcquireConfigurationOperation_AcquireConfigurationResponse - .Builder(); - } + /** + * Integrated Circuit Card Identification - Identifier of the eSIM profile on the + * device’s eSIM. {@code null} if an eSIM profile does not exist for the device. + */ + @Nullable + public abstract String iccid(); - /** - * The builder of {@link AcquireConfigurationResponse} - */ - @AutoValue.Builder - public abstract static class Builder { /** - * Set the iccid. - * - * @param iccid Integrated Circuit Card Identification - Identifier of the eSIM - * profile on the device’s eSIM. - * - * @return The builder. + * Indicates the applicable companion device service. {@code null} if not for companion + * configuration. */ - @NonNull - public abstract Builder setIccid(@NonNull String iccid); + @Nullable + @CompanionService + public abstract String companionDeviceService(); /** - * Set the applicable companion device service. - * - * @param companionDeviceService Indicates the applicable companion device service. + * Service status. * - * @return The builder. + * @see OdsaOperation#SERVICE_STATUS_UNKNOWN + * @see OdsaOperation#SERVICE_STATUS_ACTIVATED + * @see OdsaOperation#SERVICE_STATUS_ACTIVATING + * @see OdsaOperation#SERVICE_STATUS_DEACTIVATED + * @see OdsaOperation#SERVICE_STATUS_DEACTIVATED_NO_REUSE */ - @NonNull - public abstract Builder setCompanionDeviceService( - @NonNull @CompanionService String companionDeviceService); + @ServiceStatus + public abstract int serviceStatus(); /** - * Set the service status. - * - * @param serviceStatus Service status. - * - * @return The builder. + * Specifies the minimum interval (in minutes) with which the device application may + * poll the ECS to refresh the current {@link #serviceStatus()} using + * {@link AcquireConfigurationRequest}. This parameter will be present only when + * {@link #serviceStatus()} is {@link OdsaOperation#SERVICE_STATUS_ACTIVATING}. If + * parameter is not present or value is 0, this polling procedure is not triggered and + * ODSA app will keep waiting for any external action to continue the flow. + * + * The maximum number of {@link AcquireConfigurationRequest} before sending a + * {@link #serviceStatus()} with + * {@link OdsaOperation#SERVICE_STATUS_DEACTIVATED_NO_REUSE} will be defined as an ECS + * configuration variable (MaxRefreshRequest). + * + * {@link #POLLING_INTERVAL_NOT_AVAILABLE} when polling inverval is not available. */ - @NonNull - public abstract Builder setServiceStatus(@ServiceStatus int serviceStatus); + public abstract int pollingInterval(); /** - * Set the polling interval. - * - * @param pollingInterval The minimum interval (in minutes) with which the device - * application may poll the ECS to refresh the current {@link #serviceStatus()} using - * {@link AcquireConfigurationRequest}. - * - * @return The builder. + * Specifies how and where to download the eSIM profile associated with the device. + * Present in case the profile is to be downloaded at this stage. */ - @NonNull - public abstract Builder setPollingInterval(int pollingInterval); + @Nullable + public abstract DownloadInfo downloadInfo(); + + /** + * Includes all information collected by the ES of the companion device. + */ + @Nullable + public abstract CompanionDeviceInfo companionDeviceInfo(); /** - * Set the download information. - * - * @param downloadInfo Specifies how and where to download the eSIM profile associated - * with the device. - * * @return The builder. */ @NonNull - public abstract Builder setDownloadInfo(@NonNull DownloadInfo downloadInfo); + public static Builder builder() { + return new AutoValue_AcquireConfigurationOperation_AcquireConfigurationResponse_Configuration + .Builder() + .setType(CONFIGURATION_TYPE_UNKNOWN) + .setIccid("") + .setServiceStatus(OdsaOperation.SERVICE_STATUS_UNKNOWN) + .setPollingInterval(POLLING_INTERVAL_NOT_AVAILABLE); + } /** - * Set the companion device info. + * The builder of {@link Configuration} + */ + @AutoValue.Builder + public abstract static class Builder { + /** + * Set the configuration type + * + * @param configType The configuration type. + * + * @return The builder. + */ + @NonNull + public abstract Builder setType(@ConfigurationType int configType); + /** + * Set the iccid. + * + * @param iccid Integrated Circuit Card Identification - Identifier of the eSIM + * profile on the device’s eSIM. + * + * @return The builder. + */ + @NonNull + public abstract Builder setIccid(@NonNull String iccid); + + /** + * Set the applicable companion device service. + * + * @param companionDeviceService Indicates the applicable companion device service. + * + * @return The builder. + */ + @NonNull + public abstract Builder setCompanionDeviceService( + @NonNull @CompanionService String companionDeviceService); + + /** + * Set the service status. + * + * @param serviceStatus Service status. + * + * @return The builder. + */ + @NonNull + public abstract Builder setServiceStatus(@ServiceStatus int serviceStatus); + + /** + * Set the polling interval. + * + * @param pollingInterval The minimum interval (in minutes) with which the device + * application may poll the ECS to refresh the current {@link #serviceStatus()} + * using {@link AcquireConfigurationRequest}. + * + * @return The builder. + */ + @NonNull + public abstract Builder setPollingInterval(int pollingInterval); + + /** + * Set the download information. + * + * @param downloadInfo Specifies how and where to download the eSIM profile + * associated with the device. + * + * @return The builder. + */ + @NonNull + public abstract Builder setDownloadInfo(@NonNull DownloadInfo downloadInfo); + + /** + * Set the companion device info. + * + * @param companionDeviceInfo Includes all information collected by the ES of the + * companion device. + * + * @return The builder. + */ + @NonNull + public abstract Builder setCompanionDeviceInfo( + @NonNull CompanionDeviceInfo companionDeviceInfo); + + /** + * @return Build the {@link Configuration} object. + */ + @NonNull + public abstract Configuration build(); + } + } + + /** + * Configurations defined in GSMA Service Entitlement Configuration section 6.5.5. Could be + * more than one if multiple companion device(s) associated with the requesting device that + * carry a configuration for ODSA. + */ + @NonNull + public abstract ImmutableList<Configuration> configurations(); + + /** + * @return The builder. + */ + @NonNull + public static Builder builder() { + return new AutoValue_AcquireConfigurationOperation_AcquireConfigurationResponse + .Builder() + .setConfigurations(ImmutableList.of()); + } + + /** + * The builder of {@link AcquireConfigurationResponse} + */ + @AutoValue.Builder + public abstract static class Builder extends OdsaResponse.Builder { + /** + * Set the configurations * - * @param companionDeviceInfo Includes all information collected by the ES of the - * companion device. + * @param configs Configurations defined in GSMA Service Entitlement Configuration + * section 6.5.5. Could be more than one if multiple companion device(s) associated with + * the requesting device that carry a configuration for ODSA. * * @return The builder. */ @NonNull - public abstract Builder setCompanionDeviceInfo( - @NonNull CompanionDeviceInfo companionDeviceInfo); + public abstract Builder setConfigurations( + @NonNull ImmutableList<Configuration> configs); /** * @return Build the {@link AcquireConfigurationResponse} object. diff --git a/java/com/android/libraries/entitlement/utils/Ts43XmlDoc.java b/java/com/android/libraries/entitlement/utils/Ts43XmlDoc.java index 8cf4261..37c4379 100644 --- a/java/com/android/libraries/entitlement/utils/Ts43XmlDoc.java +++ b/java/com/android/libraries/entitlement/utils/Ts43XmlDoc.java @@ -56,6 +56,9 @@ public final class Ts43XmlDoc { public static final String APPLICATION = "APPLICATION"; public static final String PRIMARY_CONFIGURATION = "PrimaryConfiguration"; + public static final String COMPANION_CONFIGURATIONS = "CompanionConfigurations"; + public static final String COMPANION_CONFIGURATION = "CompanionConfiguration"; + public static final String ENTERPRISE_CONFIGURATION = "EnterpriseConfiguration"; public static final String USER = "USER"; public static final String TOKEN = "TOKEN"; public static final String DOWNLOAD_INFO = "DownloadInfo"; |