1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.libraries.entitlement; 18 19 import android.content.Context; 20 21 import androidx.annotation.Nullable; 22 import androidx.annotation.VisibleForTesting; 23 24 import com.android.libraries.entitlement.eapaka.EapAkaApi; 25 26 import com.google.common.collect.ImmutableList; 27 28 import java.util.List; 29 30 /** 31 * Implemnets protocol for carrier service entitlement configuration query and operation, based on 32 * GSMA TS.43 spec. 33 */ 34 public class ServiceEntitlement { 35 /** 36 * App ID for Voice-Over-LTE entitlement. 37 */ 38 public static final String APP_VOLTE = "ap2003"; 39 /** 40 * App ID for Voice-Over-WiFi entitlement. 41 */ 42 public static final String APP_VOWIFI = "ap2004"; 43 /** 44 * App ID for SMS-Over-IP entitlement. 45 */ 46 public static final String APP_SMSOIP = "ap2005"; 47 /** 48 * App ID for on device service activation (OSDA) for companion device. 49 */ 50 public static final String APP_ODSA_COMPANION = "ap2006"; 51 /** 52 * App ID for on device service activation (OSDA) for primary device. 53 */ 54 public static final String APP_ODSA_PRIMARY = "ap2009"; 55 /** 56 * App ID for data plan information entitlement. 57 */ 58 public static final String APP_DATA_PLAN_BOOST = "ap2010"; 59 60 private final CarrierConfig carrierConfig; 61 private final EapAkaApi eapAkaApi; 62 63 /** 64 * Creates an instance for service entitlement configuration query and operation for the 65 * carrier. 66 * 67 * @param context context of application 68 * @param carrierConfig carrier specific configs used in the queries and operations. 69 * @param simSubscriptionId the subscroption ID of the carrier's SIM on device. This indicates 70 * which SIM to retrieve IMEI/IMSI from and perform EAP-AKA 71 * authentication with. See 72 * {@link android.telephony.SubscriptionManager} 73 * for how to get the subscroption ID. 74 */ ServiceEntitlement(Context context, CarrierConfig carrierConfig, int simSubscriptionId)75 public ServiceEntitlement(Context context, CarrierConfig carrierConfig, int simSubscriptionId) { 76 this( 77 context, 78 carrierConfig, 79 simSubscriptionId, 80 /* saveHttpHistory= */ false, 81 /* bypassEapAkaResponse= */ ""); 82 } 83 84 /** 85 * Creates an instance for service entitlement configuration query and operation for the 86 * carrier. 87 * 88 * @param context context of application 89 * @param carrierConfig carrier specific configs used in the queries and operations. 90 * @param simSubscriptionId the subscroption ID of the carrier's SIM on device. This indicates 91 * which SIM to retrieve IMEI/IMSI from and perform EAP-AKA authentication with. See {@link 92 * android.telephony.SubscriptionManager} for how to get the subscroption ID. 93 * @param saveHttpHistory set to {@code true} to save the history of request and response which 94 * can later be retrieved by {@code getHistory()}. Intended for debugging. 95 */ ServiceEntitlement( Context context, CarrierConfig carrierConfig, int simSubscriptionId, boolean saveHttpHistory)96 public ServiceEntitlement( 97 Context context, 98 CarrierConfig carrierConfig, 99 int simSubscriptionId, 100 boolean saveHttpHistory) { 101 this( 102 context, 103 carrierConfig, 104 simSubscriptionId, 105 saveHttpHistory, 106 /* bypassEapAkaResponse= */ ""); 107 } 108 109 /** 110 * Creates an instance for service entitlement configuration query and operation for the 111 * carrier. 112 * 113 * @param context context of application 114 * @param carrierConfig carrier specific configs used in the queries and operations. 115 * @param simSubscriptionId the subscroption ID of the carrier's SIM on device. This indicates 116 * which SIM to retrieve IMEI/IMSI from and perform EAP-AKA authentication with. See {@link 117 * android.telephony.SubscriptionManager} for how to get the subscroption ID. 118 * @param saveHttpHistory set to {@code true} to save the history of request and response which 119 * can later be retrieved by {@code getHistory()}. Intended for debugging. 120 * @param bypassEapAkaResponse set to non empty string to bypass EAP-AKA authentication. 121 * The client will accept any challenge from the server and return this string as a 122 * response. Must not be {@code null}. Intended for testing. 123 */ ServiceEntitlement( Context context, CarrierConfig carrierConfig, int simSubscriptionId, boolean saveHttpHistory, String bypassEapAkaResponse)124 public ServiceEntitlement( 125 Context context, 126 CarrierConfig carrierConfig, 127 int simSubscriptionId, 128 boolean saveHttpHistory, 129 String bypassEapAkaResponse) { 130 this.carrierConfig = carrierConfig; 131 this.eapAkaApi = 132 new EapAkaApi(context, simSubscriptionId, saveHttpHistory, bypassEapAkaResponse); 133 } 134 135 @VisibleForTesting ServiceEntitlement(CarrierConfig carrierConfig, EapAkaApi eapAkaApi)136 ServiceEntitlement(CarrierConfig carrierConfig, EapAkaApi eapAkaApi) { 137 this.carrierConfig = carrierConfig; 138 this.eapAkaApi = eapAkaApi; 139 } 140 141 /** 142 * Retrieves service entitlement configuration. For on device service activation (ODSA) of eSIM 143 * for companion/primary devices, use {@link #performEsimOdsa} instead. 144 * 145 * <p>Supported {@code appId}: {@link #APP_VOLTE}, {@link #APP_VOWIFI}, {@link #APP_SMSOIP}. 146 * 147 * <p>This method sends an HTTP GET request to entitlement server, responds to EAP-AKA 148 * challenge if needed, and returns the raw configuration doc as a string. The following 149 * parameters are set in the HTTP request: 150 * 151 * <ul> 152 * <li>"app": {@code appId} 153 * <li>"vers": 0, or {@code request.configurationVersion()} if it's not 0. 154 * <li>"entitlement_version": "2.0", or {@code request.entitlementVersion()} if it's not empty. 155 * <li>"token": not set, or {@code request.authenticationToken()} if it's not empty. 156 * <li>"IMSI": if "token" is set, set to {@link android.telephony.TelephonyManager#getImei}. 157 * <li>"EAP_ID": if "token" is not set, set this parameter to trigger embedded EAP-AKA 158 * authentication as decribed in TS.43 section 2.6.1. Its value is derived from IMSI as per 159 * GSMA spec RCC.14 section C.2. 160 * <li>"terminal_id": IMEI, or {@code request.terminalId()} if it's not empty. 161 * <li>"terminal_vendor": {@link android.os.Build#MANUFACTURER}, or {@code 162 * request.terminalVendor()} if it's not empty. 163 * <li>"terminal_model": {@link android.os.Build#MODEL}, or {@code request.terminalModel()} if 164 * it's not empty. 165 * <li>"terminal_sw_version": {@llink android.os.Build.VERSION#BASE_OS}, or {@code 166 * request.terminalSoftwareVersion()} if it's not empty. 167 * <li>"app_name": not set, or {@code request.appName()} if it's not empty. 168 * <li>"app_version": not set, or {@code request.appVersion()} if it's not empty. 169 * <li>"notif_token": not set, or {@code request.notificationToken()} if it's not empty. 170 * <li>"notif_action": {@code request.notificationAction()} if "notif_token" is set, otherwise 171 * not set. 172 * </ul> 173 * 174 * <p>Requires permission: READ_PRIVILEGED_PHONE_STATE, or carrier privilege. 175 * 176 * @param appId an app ID string defined in TS.43 section 2.2, e.g. {@link #APP_VOWIFI}. 177 * @param request contains parameters that can be used in the HTTP request. 178 */ 179 @Nullable queryEntitlementStatus(String appId, ServiceEntitlementRequest request)180 public String queryEntitlementStatus(String appId, ServiceEntitlementRequest request) 181 throws ServiceEntitlementException { 182 return eapAkaApi.queryEntitlementStatus(ImmutableList.of(appId), carrierConfig, request); 183 } 184 185 /** 186 * Retrieves service entitlement configurations for multiple app IDs in one HTTP 187 * request/response. For on device service activation (ODSA) of eSIM for companion/primary 188 * devices, use {@link #performEsimOdsa} instead. 189 * 190 * <p>Same with {@link #queryEntitlementStatus(String, ServiceEntitlementRequest)} except that 191 * multiple "app" parameters will be set in the HTTP request, in the order as they appear in 192 * parameter {@code appIds}. 193 */ queryEntitlementStatus(ImmutableList<String> appIds, ServiceEntitlementRequest request)194 public String queryEntitlementStatus(ImmutableList<String> appIds, 195 ServiceEntitlementRequest request) 196 throws ServiceEntitlementException { 197 return eapAkaApi.queryEntitlementStatus(appIds, carrierConfig, request); 198 } 199 200 /** 201 * Performs on device service activation (ODSA) of eSIM for companion/primary devices. 202 * 203 * <p>Supported {@code appId}: {@link #APP_ODSA_COMPANION}, {@link #APP_ODSA_PRIMARY}. 204 * 205 * <p>Similar to {@link #queryEntitlementStatus(String, ServiceEntitlementRequest)}, this 206 * method sends an HTTP GET request to entitlement server, responds to EAP-AKA challenge if 207 * needed, and returns the raw configuration doc as a string. Additional parameters from {@code 208 * operation} are set to the HTTP request. See {@link EsimOdsaOperation} for details. 209 */ performEsimOdsa( String appId, ServiceEntitlementRequest request, EsimOdsaOperation operation)210 public String performEsimOdsa( 211 String appId, ServiceEntitlementRequest request, EsimOdsaOperation operation) 212 throws ServiceEntitlementException { 213 return eapAkaApi.performEsimOdsaOperation(appId, carrierConfig, request, operation); 214 } 215 216 /** 217 * Retrieves the history of past HTTP request and responses if {@code saveHttpHistory} was set 218 * in constructor. 219 */ getHistory()220 public List<String> getHistory() { 221 return eapAkaApi.getHistory(); 222 } 223 224 /** 225 * Clears the history of past HTTP request and responses. 226 */ clearHistory()227 public void clearHistory() { 228 eapAkaApi.clearHistory(); 229 } 230 } 231