blob: af30de647c100fcb9ec729f350fbe09a1cc71f3f [file] [log] [blame]
/*
* 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.
*
* <p>Supported {@code appId}: {@link #APP_VOLTE}, {@link #APP_VOWIFI}, {@link #APP_SMSOIP}.
*
* <p>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:
*
* <ul>
* <li>"app": {@code appId}
* <li>"vers": 0, or {@code request.configurationVersion()} if it's not 0.
* <li>"entitlement_version": "2.0", or {@code request.entitlementVersion()} if it's not empty.
* <li>"token": not set, or {@code request.authenticationToken()} if it's not empty.
* <li>"IMSI": if "token" is set, set to {@link android.telephony.TelephonyManager#getImei}.
* <li>"EAP_ID": if "token" is not set, set this parameter to trigger embedded EAP-AKA
* authentication as described in TS.43 section 2.6.1. Its value is derived from IMSI as per
* GSMA spec RCC.14 section C.2.
* <li>"terminal_id": IMEI, or {@code request.terminalId()} if it's not empty.
* <li>"terminal_vendor": {@link android.os.Build#MANUFACTURER}, or {@code
* request.terminalVendor()} if it's not empty.
* <li>"terminal_model": {@link android.os.Build#MODEL}, or {@code request.terminalModel()} if
* it's not empty.
* <li>"terminal_sw_version": {@link android.os.Build.VERSION#BASE_OS}, or {@code
* request.terminalSoftwareVersion()} if it's not empty.
* <li>"app_name": not set, or {@code request.appName()} if it's not empty.
* <li>"app_version": not set, or {@code request.appVersion()} if it's not empty.
* <li>"notif_token": not set, or {@code request.notificationToken()} if it's not empty.
* <li>"notif_action": {@code request.notificationAction()} if "notif_token" is set, otherwise
* not set.
* </ul>
*
* <p>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.
*
* <p>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<String> appIds,
ServiceEntitlementRequest request)
throws ServiceEntitlementException {
return getEntitlementStatusResponse(appIds, request).body();
}
/**
* 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.
*
* <p>Same as {@link #queryEntitlementStatus(ImmutableList, ServiceEntitlementRequest)}
* except that it returns the full HTTP response instead of just the body.
*/
@NonNull
public HttpResponse getEntitlementStatusResponse(ImmutableList<String> appIds,
ServiceEntitlementRequest request)
throws ServiceEntitlementException {
return eapAkaApi.queryEntitlementStatus(appIds, carrierConfig, request);
}
/**
* Performs on device service activation (ODSA) of eSIM for companion/primary devices.
*
* <p>Supported {@code appId}: {@link #APP_ODSA_COMPANION}, {@link #APP_ODSA_PRIMARY}.
*
* <p>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.
*
* <p>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.
*
* <p>Implementation based on section 2.8.2 of TS.43
*
* <p>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.
*
* <p>Implementation based on section 2.8.2 of TS.43.
*
* <p>{@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.
*
* <p>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<String> getHistory() {
return eapAkaApi.getHistory();
}
/**
* Clears the history of past HTTP request and responses.
*/
public void clearHistory() {
eapAkaApi.clearHistory();
}
}