aboutsummaryrefslogtreecommitdiff
path: root/java
diff options
context:
space:
mode:
authorJack Yu <jackyu@google.com>2023-05-31 01:12:28 -0700
committerJack Yu <jackyu@google.com>2023-06-05 21:51:29 +0000
commiteaf216b376887ebd037840f3c76f352986df32d1 (patch)
treeb69a508fd17561ffe60f872f0ab8ce1f4d0c3ee1 /java
parentb07310aeb030300e103a17f2c2f44cd3b5450cbd (diff)
downloadservice_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')
-rw-r--r--java/com/android/libraries/entitlement/Ts43Operation.java124
-rw-r--r--java/com/android/libraries/entitlement/odsa/AcquireConfigurationOperation.java327
-rw-r--r--java/com/android/libraries/entitlement/utils/Ts43XmlDoc.java3
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";