/* * Copyright (C) 2021 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.libraries.entitlement; import android.content.Context; import androidx.annotation.NonNull; import androidx.annotation.VisibleForTesting; import com.android.libraries.entitlement.eapaka.EapAkaApi; import com.android.libraries.entitlement.http.HttpResponse; import com.android.libraries.entitlement.utils.DebugUtils; import com.android.libraries.entitlement.utils.Ts43Constants; import com.google.common.collect.ImmutableList; import java.util.List; /** * Implements protocol for carrier service entitlement configuration query and operation, based on * GSMA TS.43 spec. */ public class ServiceEntitlement { /** * App ID for Voice-Over-LTE entitlement. */ public static final String APP_VOLTE = Ts43Constants.APP_VOLTE; /** * App ID for Voice-Over-WiFi entitlement. */ public static final String APP_VOWIFI = Ts43Constants.APP_VOWIFI; /** * App ID for SMS-Over-IP entitlement. */ public static final String APP_SMSOIP = Ts43Constants.APP_SMSOIP; /** * App ID for on device service activation (ODSA) for companion device. */ public static final String APP_ODSA_COMPANION = Ts43Constants.APP_ODSA_COMPANION; /** * App ID for on device service activation (ODSA) for primary device. */ public static final String APP_ODSA_PRIMARY = Ts43Constants.APP_ODSA_PRIMARY; /** * App ID for data plan information entitlement. */ public static final String APP_DATA_PLAN_BOOST = Ts43Constants.APP_DATA_PLAN_BOOST; /** * App ID for server initiated requests, entitlement and activation. */ public static final String APP_ODSA_SERVER_INITIATED_REQUESTS = Ts43Constants.APP_ODSA_SERVER_INITIATED_REQUESTS; /** * App ID for direct carrier billing. */ public static final String APP_DIRECT_CARRIER_BILLING = Ts43Constants.APP_DIRECT_CARRIER_BILLING; /** * App ID for private user identity. */ public static final String APP_PRIVATE_USER_IDENTITY = Ts43Constants.APP_PRIVATE_USER_IDENTITY; /** * App ID for phone number information. */ public static final String APP_PHONE_NUMBER_INFORMATION = Ts43Constants.APP_PHONE_NUMBER_INFORMATION; /** * App ID for satellite entitlement. */ public static final String APP_SATELLITE_ENTITLEMENT = Ts43Constants.APP_SATELLITE_ENTITLEMENT; private final CarrierConfig carrierConfig; private final EapAkaApi eapAkaApi; private ServiceEntitlementRequest mOidcRequest; /** * Creates an instance for service entitlement configuration query and operation for the * carrier. * * @param context context of application * @param carrierConfig carrier specific configs used in the queries and operations. * @param simSubscriptionId the subscription ID of the carrier's SIM on device. This indicates * which SIM to retrieve IMEI/IMSI from and perform EAP-AKA * authentication with. See * {@link android.telephony.SubscriptionManager} * for how to get the subscription ID. */ public ServiceEntitlement(Context context, CarrierConfig carrierConfig, int simSubscriptionId) { this(context, carrierConfig, simSubscriptionId, /* saveHttpHistory= */ false); } /** * Creates an instance for service entitlement configuration query and operation for the * carrier. * * @param context context of application * @param carrierConfig carrier specific configs used in the queries and operations. * @param simSubscriptionId the subscription ID of the carrier's SIM on device. This indicates * which SIM to retrieve IMEI/IMSI from and perform EAP-AKA authentication with. See {@link * android.telephony.SubscriptionManager} for how to get the subscription ID. * @param saveHttpHistory set to {@code true} to save the history of request and response which * can later be retrieved by {@code getHistory()}. Intended for debugging. */ public ServiceEntitlement( Context context, CarrierConfig carrierConfig, int simSubscriptionId, boolean saveHttpHistory) { this( context, carrierConfig, simSubscriptionId, saveHttpHistory, DebugUtils.getBypassEapAkaResponse()); } /** * Creates an instance for service entitlement configuration query and operation for the * carrier. * * @param context context of application * @param carrierConfig carrier specific configs used in the queries and operations. * @param simSubscriptionId the subscription ID of the carrier's SIM on device. This indicates * which SIM to retrieve IMEI/IMSI from and perform EAP-AKA authentication with. See {@link * android.telephony.SubscriptionManager} for how to get the subscription ID. * @param saveHttpHistory set to {@code true} to save the history of request and response which * can later be retrieved by {@code getHistory()}. Intended for debugging. * @param bypassEapAkaResponse set to non empty string to bypass EAP-AKA authentication. * The client will accept any challenge from the server and return this string as a * response. Must not be {@code null}. Intended for testing. */ public ServiceEntitlement( Context context, CarrierConfig carrierConfig, int simSubscriptionId, boolean saveHttpHistory, String bypassEapAkaResponse) { this.carrierConfig = carrierConfig; this.eapAkaApi = new EapAkaApi(context, simSubscriptionId, saveHttpHistory, bypassEapAkaResponse); } @VisibleForTesting ServiceEntitlement(CarrierConfig carrierConfig, EapAkaApi eapAkaApi) { this.carrierConfig = carrierConfig; this.eapAkaApi = eapAkaApi; } /** * Retrieves service entitlement configuration. For on device service activation (ODSA) of eSIM * for companion/primary devices, use {@link #performEsimOdsa} instead. * *
Supported {@code appId}: {@link #APP_VOLTE}, {@link #APP_VOWIFI}, {@link #APP_SMSOIP}. * *
This method sends an HTTP GET request to entitlement server, responds to EAP-AKA * challenge if needed, and returns the raw configuration doc as a string. The following * parameters are set in the HTTP request: * *
Requires permission: READ_PRIVILEGED_PHONE_STATE, or carrier privilege. * * @param appId an app ID string defined in TS.43 section 2.2, e.g. {@link #APP_VOWIFI}. * @param request contains parameters that can be used in the HTTP request. */ @NonNull public String queryEntitlementStatus(String appId, ServiceEntitlementRequest request) throws ServiceEntitlementException { return queryEntitlementStatus(ImmutableList.of(appId), request); } /** * Retrieves service entitlement configurations for multiple app IDs in one HTTP * request/response. For on device service activation (ODSA) of eSIM for companion/primary * devices, use {@link #performEsimOdsa} instead. * *
Same as {@link #queryEntitlementStatus(String, ServiceEntitlementRequest)} except that
* multiple "app" parameters will be set in the HTTP request, in the order as they appear in
* parameter {@code appIds}.
*/
@NonNull
public String queryEntitlementStatus(ImmutableList Same as {@link #queryEntitlementStatus(ImmutableList, ServiceEntitlementRequest)}
* except that it returns the full HTTP response instead of just the body.
*/
@NonNull
public HttpResponse getEntitlementStatusResponse(ImmutableList Supported {@code appId}: {@link #APP_ODSA_COMPANION}, {@link #APP_ODSA_PRIMARY}.
*
* Similar to {@link #queryEntitlementStatus(String, ServiceEntitlementRequest)}, this
* method sends an HTTP GET request to entitlement server, responds to EAP-AKA challenge if
* needed, and returns the raw configuration doc as a string. Additional parameters from {@code
* operation} are set to the HTTP request. See {@link EsimOdsaOperation} for details.
*/
@NonNull
public String performEsimOdsa(
String appId, ServiceEntitlementRequest request, EsimOdsaOperation operation)
throws ServiceEntitlementException {
return getEsimOdsaResponse(appId, request, operation).body();
}
/**
* Retrieves the HTTP response after performing on device service activation (ODSA) of eSIM for
* companion/primary devices.
*
* Same as {@link #performEsimOdsa(String, ServiceEntitlementRequest, EsimOdsaOperation)}
* except that it returns the full HTTP response instead of just the body.
*/
@NonNull
public HttpResponse getEsimOdsaResponse(
String appId, ServiceEntitlementRequest request, EsimOdsaOperation operation)
throws ServiceEntitlementException {
return eapAkaApi.performEsimOdsaOperation(appId, carrierConfig, request, operation);
}
/**
* Retrieves the endpoint for OpenID Connect(OIDC) authentication.
*
* Implementation based on section 2.8.2 of TS.43
*
* The user should call {@link #queryEntitlementStatusFromOidc(String url)} with the
* authentication result to retrieve the service entitlement configuration.
*
* @param appId an app ID string defined in TS.43 section 2.2
* @param request contains parameters that can be used in the HTTP request
*/
@NonNull
public String acquireOidcAuthenticationEndpoint(String appId, ServiceEntitlementRequest request)
throws ServiceEntitlementException {
mOidcRequest = request;
return eapAkaApi.acquireOidcAuthenticationEndpoint(appId, carrierConfig, request);
}
/**
* Retrieves the service entitlement configuration from OIDC authentication result.
*
* Implementation based on section 2.8.2 of TS.43.
*
* {@link #acquireOidcAuthenticationEndpoint} must be called before calling this method.
*
* @param url the redirect url from OIDC authentication result.
*/
@NonNull
public String queryEntitlementStatusFromOidc(String url) throws ServiceEntitlementException {
return getEntitlementStatusResponseFromOidc(url).body();
}
/**
* Retrieves the HTTP response containing the service entitlement configuration from
* OIDC authentication result.
*
* Same as {@link #queryEntitlementStatusFromOidc(String)} except that it returns the
* full HTTP response instead of just the body.
*
* @param url the redirect url from OIDC authentication result.
*/
@NonNull
public HttpResponse getEntitlementStatusResponseFromOidc(String url)
throws ServiceEntitlementException {
return eapAkaApi.queryEntitlementStatusFromOidc(url, carrierConfig, mOidcRequest);
}
/**
* Retrieves the history of past HTTP request and responses if {@code saveHttpHistory} was set
* in constructor.
*/
@NonNull
public List