aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMeng Wang <mewan@google.com>2021-02-10 19:49:26 -0800
committerMeng Wang <mewan@google.com>2021-02-18 12:57:31 -0800
commit941c588c6abd615851539467a94ae31da88135ce (patch)
treeb3a73188c4ebba019da1994966627d7166e1374e
parentb7c355416b105a93ee6b7f0f1ae83248184b08cb (diff)
downloadservice_entitlement-941c588c6abd615851539467a94ae31da88135ce.tar.gz
Allow client to specify timeout and Network
API surface change: - setTimeoutInSec and setNetwork added to CarrierConfig.Builder Bug: 175827888 Bug: 177100676 Test: atest Change-Id: I909fe568898074598d8ae0bd5db90b273534a09d
-rw-r--r--Android.bp38
-rw-r--r--java/com/android/libraries/entitlement/CarrierConfig.java41
-rw-r--r--java/com/android/libraries/entitlement/ServiceEntitlement.java5
-rw-r--r--java/com/android/libraries/entitlement/eapaka/EapAkaApi.java20
-rw-r--r--java/com/android/libraries/entitlement/http/HttpClient.java15
-rw-r--r--java/com/android/libraries/entitlement/http/HttpRequest.java52
-rw-r--r--tests/src/com/android/libraries/entitlement/ServiceEntitlementTest.java10
-rw-r--r--tests/src/com/android/libraries/entitlement/eapaka/EapAkaApiTest.java103
-rw-r--r--tests/src/com/android/libraries/entitlement/http/HttpClientTest.java93
-rw-r--r--tests/utils/com/android/libraries/entitlement/testing/FakeURLStreamHandler.java61
10 files changed, 294 insertions, 144 deletions
diff --git a/Android.bp b/Android.bp
index eebc190..fcb2b26 100644
--- a/Android.bp
+++ b/Android.bp
@@ -12,7 +12,20 @@
// 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.
+
+java_defaults {
+ name: "service-entitlement-defaults",
+ libs: [
+ "androidx.annotation_annotation",
+ "auto_value_annotations",
+ ],
+ plugins: ["auto_value_plugin"],
+ sdk_version: "system_current",
+ min_sdk_version: "29",
+}
+
java_library {
+ defaults: ["service-entitlement-defaults"],
name: "service-entitlement-impl",
visibility: [
"//visibility:private"
@@ -22,30 +35,23 @@ java_library {
"java/com/android/libraries/entitlement/http/*.java",
"java/com/android/libraries/entitlement/utils/*.java",
],
- libs: [
- "androidx.annotation_annotation",
- "auto_value_annotations",
- ],
static_libs: [
"guava",
"service-entitlement-data",
],
- plugins: ["auto_value_plugin"],
- sdk_version: "system_current",
- min_sdk_version: "29",
}
java_library {
+ defaults: ["service-entitlement-defaults"],
name: "service-entitlement",
static_libs: [
"service-entitlement-api",
"service-entitlement-data",
],
- sdk_version: "system_current",
- min_sdk_version: "29",
}
java_library {
+ defaults: ["service-entitlement-defaults"],
name: "service-entitlement-api",
visibility: [
"//visibility:private",
@@ -53,22 +59,16 @@ java_library {
srcs: [
"java/com/android/libraries/entitlement/ServiceEntitlement.java",
],
- libs: [
- "androidx.annotation_annotation",
- "auto_value_annotations",
- ],
static_libs: [
"guava",
"service-entitlement-data",
"service-entitlement-impl",
],
- plugins: ["auto_value_plugin"],
- sdk_version: "system_current",
- min_sdk_version: "29",
}
java_library {
+ defaults: ["service-entitlement-defaults"],
name: "service-entitlement-data",
visibility: [
"//visibility:private",
@@ -79,10 +79,4 @@ java_library {
"java/com/android/libraries/entitlement/ServiceEntitlementException.java",
"java/com/android/libraries/entitlement/ServiceEntitlementRequest.java",
],
- libs: [
- "auto_value_annotations",
- ],
- plugins: ["auto_value_plugin"],
- sdk_version: "current",
- min_sdk_version: "29",
}
diff --git a/java/com/android/libraries/entitlement/CarrierConfig.java b/java/com/android/libraries/entitlement/CarrierConfig.java
index 8f040c1..44a4170 100644
--- a/java/com/android/libraries/entitlement/CarrierConfig.java
+++ b/java/com/android/libraries/entitlement/CarrierConfig.java
@@ -16,6 +16,10 @@
package com.android.libraries.entitlement;
+import android.net.Network;
+
+import androidx.annotation.Nullable;
+
import com.google.auto.value.AutoValue;
/**
@@ -25,16 +29,24 @@ import com.google.auto.value.AutoValue;
*/
@AutoValue
public abstract class CarrierConfig {
- /**
- * Returns the carrier's entitlement server URL. If not set, will use {@code
- * https://aes.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org} as defined in GSMA spec TS.43 section 2.1.
- */
+ /** Default value of {@link #timeoutInSec} if not set. */
+ public static final int DEFAULT_TIMEOUT_IN_SEC = 30;
+
+ /** The carrier's entitlement server URL. See {@link Builder#setServerUrl}. */
public abstract String serverUrl();
+ /** Client side timeout for HTTP connection. See {@link Builder#setTimeoutInSec}. */
+ public abstract int timeoutInSec();
+
+ /** The {@link Network} used for HTTP connection. See {@link Builder#setNetwork}. */
+ @Nullable
+ public abstract Network network();
+
/** Returns a new {@link Builder} object. */
public static Builder builder() {
return new AutoValue_CarrierConfig.Builder()
- .setServerUrl("");
+ .setServerUrl("")
+ .setTimeoutInSec(DEFAULT_TIMEOUT_IN_SEC);
}
/** Builder. */
@@ -43,9 +55,24 @@ public abstract class CarrierConfig {
public abstract CarrierConfig build();
/**
- * Set's the carrier's entitlement server URL. If not set, will use {@code
- * https://aes.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org} as defined in GSMA spec TS.43 section 2.1.
+ * Sets the carrier's entitlement server URL. If not set, will use {@code
+ * https://aes.mnc<MNC>.mcc<MCC>.pub.3gppnetwork.org} as defined in GSMA TS.43 section 2.1.
*/
public abstract Builder setServerUrl(String url);
+
+ /**
+ * Sets the client side timeout for HTTP connection. Default to
+ * {@link DEFAULT_TIMEOUT_IN_SEC}.
+ *
+ * <p>This timeout is used by both {@link java.net.URLConnection#setConnectTimeout} and
+ * {@link java.net.URLConnection#setReadTimeout}.
+ */
+ public abstract Builder setTimeoutInSec(int timeoutInSec);
+
+ /**
+ * Sets the {@link Network} used for HTTP connection. If not set, the device default network
+ * is used.
+ */
+ public abstract Builder setNetwork(Network network);
}
}
diff --git a/java/com/android/libraries/entitlement/ServiceEntitlement.java b/java/com/android/libraries/entitlement/ServiceEntitlement.java
index 77cc5ae..16aeeaa 100644
--- a/java/com/android/libraries/entitlement/ServiceEntitlement.java
+++ b/java/com/android/libraries/entitlement/ServiceEntitlement.java
@@ -121,8 +121,7 @@ public class ServiceEntitlement {
@Nullable
public String queryEntitlementStatus(String appId, ServiceEntitlementRequest request)
throws ServiceEntitlementException {
- return eapAkaApi.queryEntitlementStatus(ImmutableList.of(appId), carrierConfig.serverUrl(),
- request);
+ return eapAkaApi.queryEntitlementStatus(ImmutableList.of(appId), carrierConfig, request);
}
/**
@@ -137,7 +136,7 @@ public class ServiceEntitlement {
public String queryEntitlementStatus(ImmutableList<String> appIds,
ServiceEntitlementRequest request)
throws ServiceEntitlementException {
- return eapAkaApi.queryEntitlementStatus(appIds, carrierConfig.serverUrl(), request);
+ return eapAkaApi.queryEntitlementStatus(appIds, carrierConfig, request);
}
/**
diff --git a/java/com/android/libraries/entitlement/eapaka/EapAkaApi.java b/java/com/android/libraries/entitlement/eapaka/EapAkaApi.java
index 4ad0332..86fd0c5 100644
--- a/java/com/android/libraries/entitlement/eapaka/EapAkaApi.java
+++ b/java/com/android/libraries/entitlement/eapaka/EapAkaApi.java
@@ -27,6 +27,7 @@ import android.util.Log;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
+import com.android.libraries.entitlement.CarrierConfig;
import com.android.libraries.entitlement.ServiceEntitlementException;
import com.android.libraries.entitlement.ServiceEntitlementRequest;
import com.android.libraries.entitlement.http.HttpClient;
@@ -132,14 +133,17 @@ public class EapAkaApi {
* @throws ServiceEntitlementException when getting an unexpected http response.
*/
@Nullable
- public String queryEntitlementStatus(
- ImmutableList<String> appIds, String serverUrl, ServiceEntitlementRequest request)
+ public String queryEntitlementStatus(ImmutableList<String> appIds,
+ CarrierConfig carrierConfig,
+ ServiceEntitlementRequest request)
throws ServiceEntitlementException {
HttpRequest httpRequest =
HttpRequest.builder()
- .setUrl(entitlementStatusUrl(appIds, serverUrl, request))
+ .setUrl(entitlementStatusUrl(appIds, carrierConfig.serverUrl(), request))
.setRequestMethod(RequestMethod.GET)
.addRequestProperty(HttpHeaders.ACCEPT, ACCEPT_CONTENT_TYPE_JSON_AND_XML)
+ .setTimeoutInSec(carrierConfig.timeoutInSec())
+ .setNetwork(carrierConfig.network())
.build();
HttpResponse response = mHttpClient.request(httpRequest);
if (request.authenticationToken().isEmpty()) {
@@ -160,7 +164,7 @@ public class EapAkaApi {
}
return challengeResponse(
new EapAkaResponse(responseData).getEapAkaChallengeResponse(mContext,
- mSimSubscriptionId), serverUrl, response.cookie());
+ mSimSubscriptionId), carrierConfig, response.cookie());
} else {
// Result of fast AuthN
Log.d(TAG, "fast AuthN");
@@ -168,7 +172,9 @@ public class EapAkaApi {
}
}
- private String challengeResponse(String akaChallengeResponse, String serverUrl, String cookie)
+ private String challengeResponse(String akaChallengeResponse,
+ CarrierConfig carrierConfig,
+ String cookie)
throws ServiceEntitlementException {
Log.d(TAG, "challengeResponse");
JSONObject postData = new JSONObject();
@@ -180,12 +186,14 @@ public class EapAkaApi {
}
HttpRequest request =
HttpRequest.builder()
- .setUrl(serverUrl)
+ .setUrl(carrierConfig.serverUrl())
.setRequestMethod(RequestMethod.POST)
.setPostData(postData)
.addRequestProperty(HttpHeaders.ACCEPT, ACCEPT_CONTENT_TYPE_JSON_AND_XML)
.addRequestProperty(HttpHeaders.CONTENT_TYPE, REQUEST_CONTENT_TYPE_JSON)
.addRequestProperty(HttpHeaders.COOKIE, cookie)
+ .setTimeoutInSec(carrierConfig.timeoutInSec())
+ .setNetwork(carrierConfig.network())
.build();
return mHttpClient.request(request).body();
}
diff --git a/java/com/android/libraries/entitlement/http/HttpClient.java b/java/com/android/libraries/entitlement/http/HttpClient.java
index 1144c5a..f88a42c 100644
--- a/java/com/android/libraries/entitlement/http/HttpClient.java
+++ b/java/com/android/libraries/entitlement/http/HttpClient.java
@@ -27,6 +27,7 @@ import static com.google.common.base.Strings.nullToEmpty;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.concurrent.TimeUnit.SECONDS;
+import android.net.Network;
import android.text.TextUtils;
import android.util.Log;
@@ -51,9 +52,6 @@ import java.util.Map;
public class HttpClient {
private static final String TAG = "ServiceEntitlement";
- private static final int SOCKET_TIMEOUT_VALUE = (int) SECONDS.toMillis(30);
- private static final int CONNECT_TIMEOUT_VALUE = (int) SECONDS.toMillis(30);
-
private HttpURLConnection mConnection;
@WorkerThread
@@ -85,7 +83,12 @@ public class HttpClient {
private void createConnection(HttpRequest request) throws ServiceEntitlementException {
try {
URL url = new URL(request.url());
- mConnection = (HttpURLConnection) url.openConnection();
+ Network network = request.network();
+ if (network == null) {
+ mConnection = (HttpURLConnection) url.openConnection();
+ } else {
+ mConnection = (HttpURLConnection) network.openConnection(url);
+ }
// add HTTP headers
for (Map.Entry<String, String> entry : request.requestProperties().entrySet()) {
@@ -94,8 +97,8 @@ public class HttpClient {
// set parameters
mConnection.setRequestMethod(request.requestMethod());
- mConnection.setConnectTimeout(CONNECT_TIMEOUT_VALUE);
- mConnection.setReadTimeout(SOCKET_TIMEOUT_VALUE);
+ mConnection.setConnectTimeout((int) SECONDS.toMillis(request.timeoutInSec()));
+ mConnection.setReadTimeout((int) SECONDS.toMillis(request.timeoutInSec()));
if (POST.equals(request.requestMethod())) {
mConnection.setDoOutput(true);
}
diff --git a/java/com/android/libraries/entitlement/http/HttpRequest.java b/java/com/android/libraries/entitlement/http/HttpRequest.java
index 4a56a60..af567db 100644
--- a/java/com/android/libraries/entitlement/http/HttpRequest.java
+++ b/java/com/android/libraries/entitlement/http/HttpRequest.java
@@ -16,8 +16,13 @@
package com.android.libraries.entitlement.http;
+import android.net.Network;
import android.util.ArrayMap;
+import androidx.annotation.Nullable;
+
+import com.android.libraries.entitlement.CarrierConfig;
+
import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableMap;
@@ -25,24 +30,32 @@ import org.json.JSONObject;
import java.util.Map;
-/**
- * The parameters of the http request.
- */
+/** The parameters of an http request. */
@AutoValue
public abstract class HttpRequest {
+ /** The URL. */
public abstract String url();
+ /** The HTTP request method, like "GET" or "POST". */
public abstract String requestMethod();
+ /** For "POST" request method, the body of the request in JSON format. */
public abstract JSONObject postData();
+ /** For "GET" request method, the parameters to be encoded into the URL. */
public abstract ImmutableMap<String, String> requestValues();
+ /** HTTP header fields. */
public abstract ImmutableMap<String, String> requestProperties();
- /**
- * Builder of {@link HttpRequest}.
- */
+ /** The client side timeout, in seconds. See {@link Builder#setTimeoutInSec}. */
+ public abstract int timeoutInSec();
+
+ /** The network used for this HTTP connection. See {@link Builder#setNetwork}. */
+ @Nullable
+ public abstract Network network();
+
+ /** Builder of {@link HttpRequest}. */
@AutoValue.Builder
public abstract static class Builder {
private final Map<String, String> values = new ArrayMap<>();
@@ -50,25 +63,49 @@ public abstract class HttpRequest {
public abstract HttpRequest build();
+ /** Sets the URL. */
public abstract Builder setUrl(String url);
+ /**
+ * Sets the HTTP request method, like "GET" or "POST".
+ *
+ * @see HttpConstants.RequestMethod
+ */
public abstract Builder setRequestMethod(String requestMethod);
+ /** For "POST" request method, sets the body of the request in JSON format. */
public abstract Builder setPostData(JSONObject postData);
abstract Builder setRequestValues(ImmutableMap<String, String> value);
abstract Builder setRequestProperties(ImmutableMap<String, String> properties);
+ /** For "GET" request method, adds a parameter to be encoded into the URL. */
public Builder addRequestValues(String key, String value) {
values.put(key, value);
return this.setRequestValues(ImmutableMap.copyOf(values));
}
+ /** Adds an HTTP header field. */
public Builder addRequestProperty(String key, String value) {
properties.put(key, value);
return this.setRequestProperties(ImmutableMap.copyOf(properties));
}
+
+ /**
+ * Sets the client side timeout for HTTP connection. Default to
+ * {@link com.android.libraries.entitlement.CarrierConfig#DEFAULT_TIMEOUT_IN_SEC}.
+ *
+ * <p>This timeout is used by both {@link java.net.URLConnection#setConnectTimeout} and
+ * {@link java.net.URLConnection#setReadTimeout}.
+ */
+ public abstract Builder setTimeoutInSec(int timeoutInSec);
+
+ /**
+ * Sets the network used for this HTTP connection. If not set, the device default network
+ * is used.
+ */
+ public abstract Builder setNetwork(@Nullable Network network);
}
public static Builder builder() {
@@ -77,6 +114,7 @@ public abstract class HttpRequest {
.setRequestMethod("")
.setPostData(new JSONObject())
.setRequestValues(ImmutableMap.of())
- .setRequestProperties(ImmutableMap.of());
+ .setRequestProperties(ImmutableMap.of())
+ .setTimeoutInSec(CarrierConfig.DEFAULT_TIMEOUT_IN_SEC);
}
}
diff --git a/tests/src/com/android/libraries/entitlement/ServiceEntitlementTest.java b/tests/src/com/android/libraries/entitlement/ServiceEntitlementTest.java
index 410375d..c9f9b06 100644
--- a/tests/src/com/android/libraries/entitlement/ServiceEntitlementTest.java
+++ b/tests/src/com/android/libraries/entitlement/ServiceEntitlementTest.java
@@ -61,9 +61,8 @@ public class ServiceEntitlementTest {
@Test
public void queryEntitlementStatus_appVolte_returnResult() throws Exception {
ServiceEntitlementRequest request = ServiceEntitlementRequest.builder().build();
- when(mMockEapAkaApi.queryEntitlementStatus(ImmutableList.of(ServiceEntitlement.APP_VOLTE),
- TEST_URL,
- request))
+ when(mMockEapAkaApi.queryEntitlementStatus(
+ ImmutableList.of(ServiceEntitlement.APP_VOLTE), mCarrierConfig, request))
.thenReturn(QUERY_APP_VOLTE_RESULT);
assertThat(
@@ -74,9 +73,8 @@ public class ServiceEntitlementTest {
@Test
public void queryEntitlementStatus_appVowifi_returnResult() throws Exception {
ServiceEntitlementRequest request = ServiceEntitlementRequest.builder().build();
- when(mMockEapAkaApi.queryEntitlementStatus(ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
- TEST_URL,
- request))
+ when(mMockEapAkaApi.queryEntitlementStatus(
+ ImmutableList.of(ServiceEntitlement.APP_VOWIFI), mCarrierConfig, request))
.thenReturn(QUERY_APP_VOWIFI_RESULT);
assertThat(
diff --git a/tests/src/com/android/libraries/entitlement/eapaka/EapAkaApiTest.java b/tests/src/com/android/libraries/entitlement/eapaka/EapAkaApiTest.java
index 4d4f49f..62297a7 100644
--- a/tests/src/com/android/libraries/entitlement/eapaka/EapAkaApiTest.java
+++ b/tests/src/com/android/libraries/entitlement/eapaka/EapAkaApiTest.java
@@ -23,14 +23,16 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static org.testng.Assert.fail;
+import static org.testng.Assert.expectThrows;
import android.content.Context;
+import android.net.Network;
import android.telephony.TelephonyManager;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.runner.AndroidJUnit4;
+import com.android.libraries.entitlement.CarrierConfig;
import com.android.libraries.entitlement.ServiceEntitlement;
import com.android.libraries.entitlement.ServiceEntitlementException;
import com.android.libraries.entitlement.ServiceEntitlementRequest;
@@ -95,6 +97,7 @@ public class EapAkaApiTest {
@Rule public final MockitoRule rule = MockitoJUnit.rule();
@Mock private HttpClient mMockHttpClient;
+ @Mock private Network mMockNetwork;
@Mock private TelephonyManager mMockTelephonyManager;
@Mock private TelephonyManager mMockTelephonyManagerForSubId;
@Captor private ArgumentCaptor<HttpRequest> mHttpRequestCaptor;
@@ -110,6 +113,13 @@ public class EapAkaApiTest {
.thenReturn(mMockTelephonyManager);
when(mMockTelephonyManager.createForSubscriptionId(SUB_ID))
.thenReturn(mMockTelephonyManagerForSubId);
+ when(mMockTelephonyManagerForSubId.getSubscriberId()).thenReturn(IMSI);
+ when(mMockTelephonyManagerForSubId.getSimOperator()).thenReturn(MCCMNC);
+ when(mMockTelephonyManagerForSubId.getIccAuthentication(
+ TelephonyManager.APPTYPE_USIM,
+ TelephonyManager.AUTHTYPE_EAP_AKA,
+ GSM_SECURITY_CONTEXT_REQUEST))
+ .thenReturn(GSM_SECURITY_CONTEXT_RESPONSE);
}
@Test
@@ -118,26 +128,24 @@ public class EapAkaApiTest {
HttpResponse.builder().setContentType(ContentType.XML).setBody(RESPONSE_XML)
.build();
when(mMockHttpClient.request(any())).thenReturn(response);
+ CarrierConfig carrierConfig =
+ CarrierConfig.builder().setServerUrl(TEST_URL).setNetwork(mMockNetwork).build();
ServiceEntitlementRequest request =
ServiceEntitlementRequest.builder().setAuthenticationToken(TOKEN).build();
String respopnse =
mEapAkaApi.queryEntitlementStatus(
- ImmutableList.of(ServiceEntitlement.APP_VOWIFI), TEST_URL, request);
+ ImmutableList.of(ServiceEntitlement.APP_VOWIFI), carrierConfig, request);
assertThat(respopnse).isEqualTo(RESPONSE_XML);
verify(mMockHttpClient).request(mHttpRequestCaptor.capture());
+ assertThat(mHttpRequestCaptor.getValue().timeoutInSec())
+ .isEqualTo(CarrierConfig.DEFAULT_TIMEOUT_IN_SEC);
+ assertThat(mHttpRequestCaptor.getValue().network()).isEqualTo(mMockNetwork);
}
@Test
public void queryEntitlementStatus_noAuthenticationToken() throws Exception {
- when(mMockTelephonyManagerForSubId.getSubscriberId()).thenReturn(IMSI);
- when(mMockTelephonyManagerForSubId.getSimOperator()).thenReturn(MCCMNC);
- when(mMockTelephonyManagerForSubId.getIccAuthentication(
- TelephonyManager.APPTYPE_USIM,
- TelephonyManager.AUTHTYPE_EAP_AKA,
- GSM_SECURITY_CONTEXT_REQUEST))
- .thenReturn(GSM_SECURITY_CONTEXT_RESPONSE);
HttpResponse eapChallengeResponse =
HttpResponse
.builder().setContentType(ContentType.JSON).setBody(EAP_AKA_CHALLENGE)
@@ -147,80 +155,91 @@ public class EapAkaApiTest {
.build();
when(mMockHttpClient.request(any()))
.thenReturn(eapChallengeResponse).thenReturn(xmlResponse);
+ CarrierConfig carrierConfig = CarrierConfig.builder().setServerUrl(TEST_URL).build();
ServiceEntitlementRequest request = ServiceEntitlementRequest.builder().build();
String respopnse =
mEapAkaApi.queryEntitlementStatus(
- ImmutableList.of(ServiceEntitlement.APP_VOWIFI), TEST_URL, request);
+ ImmutableList.of(ServiceEntitlement.APP_VOWIFI), carrierConfig, request);
assertThat(respopnse).isEqualTo(RESPONSE_XML);
// Verify that the 2nd request has cookie set by the 1st response
verify(mMockHttpClient, times(2)).request(mHttpRequestCaptor.capture());
assertThat(mHttpRequestCaptor.getAllValues().get(1).requestProperties())
.containsEntry(HTTP_HEADER_COOKIE, COOKIE_VALUE);
+ assertThat(mHttpRequestCaptor.getAllValues().get(0).timeoutInSec())
+ .isEqualTo(CarrierConfig.DEFAULT_TIMEOUT_IN_SEC);
+ assertThat(mHttpRequestCaptor.getAllValues().get(0).network()).isNull();
+ assertThat(mHttpRequestCaptor.getAllValues().get(1).timeoutInSec())
+ .isEqualTo(CarrierConfig.DEFAULT_TIMEOUT_IN_SEC);
+ assertThat(mHttpRequestCaptor.getAllValues().get(1).network()).isNull();
}
@Test
- public void queryEntitlementStatus_multipleAppIds_verifyEntitlementUrl() throws Exception {
- when(mMockTelephonyManagerForSubId.getSubscriberId()).thenReturn(IMSI);
- when(mMockTelephonyManagerForSubId.getImei()).thenReturn(IMEI);
+ public void queryEntitlementStatus_hasAuthenticationToken_multipleAppIds() throws Exception {
HttpResponse response =
HttpResponse.builder().setContentType(ContentType.XML).setBody(RESPONSE_XML)
.build();
when(mMockHttpClient.request(any())).thenReturn(response);
-
ImmutableList<String> appIds = ImmutableList.of(ServiceEntitlement.APP_VOWIFI,
ServiceEntitlement.APP_VOLTE);
+ CarrierConfig carrierConfig =
+ CarrierConfig.builder().setServerUrl(TEST_URL).setTimeoutInSec(70).build();
ServiceEntitlementRequest request =
ServiceEntitlementRequest.builder().setAuthenticationToken(TOKEN).build();
- mEapAkaApi.queryEntitlementStatus(appIds, TEST_URL, request);
+
+ mEapAkaApi.queryEntitlementStatus(appIds, carrierConfig, request);
verify(mMockHttpClient).request(mHttpRequestCaptor.capture());
- assertThat(mHttpRequestCaptor.getAllValues().get(0).url())
- .contains(ServiceEntitlement.APP_VOWIFI);
- assertThat(mHttpRequestCaptor.getAllValues().get(0).url())
- .contains(ServiceEntitlement.APP_VOLTE);
+ assertThat(mHttpRequestCaptor.getValue().url()).contains(ServiceEntitlement.APP_VOWIFI);
+ assertThat(mHttpRequestCaptor.getValue().url()).contains(ServiceEntitlement.APP_VOLTE);
+ assertThat(mHttpRequestCaptor.getValue().timeoutInSec()).isEqualTo(70);
+ assertThat(mHttpRequestCaptor.getValue().network()).isNull();
}
@Test
- public void queryEntitlementStatus_noAuthenticationTokenContentTypeNotJson_throwException()
+ public void queryEntitlementStatus_noAuthenticationToken_contentTypeNotJson_throwException()
throws Exception {
HttpResponse xmlResponse =
HttpResponse.builder().setContentType(ContentType.XML).setBody(RESPONSE_XML)
.build();
when(mMockHttpClient.request(any())).thenReturn(xmlResponse);
+ CarrierConfig carrierConfig =
+ CarrierConfig.builder().setServerUrl(TEST_URL).build();
ServiceEntitlementRequest request = ServiceEntitlementRequest.builder().build();
- try {
- mEapAkaApi.queryEntitlementStatus(ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
- TEST_URL,
- request);
- fail();
- } catch (ServiceEntitlementException exception) {
- assertThat(exception.getErrorCode()).isEqualTo(
- ServiceEntitlementException.MALFORMED_HTTP_RESPONSE);
- assertThat(exception.getMessage()).isEqualTo("Unexpected http ContentType");
- }
+ ServiceEntitlementException exception = expectThrows(
+ ServiceEntitlementException.class,
+ () -> mEapAkaApi.queryEntitlementStatus(
+ ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
+ carrierConfig,
+ request));
+
+ assertThat(exception.getErrorCode()).isEqualTo(
+ ServiceEntitlementException.MALFORMED_HTTP_RESPONSE);
+ assertThat(exception.getMessage()).isEqualTo("Unexpected http ContentType");
}
@Test
- public void queryEntitlementStatus_noAuthenticationTokenEmptyResponseBody_throwException()
+ public void queryEntitlementStatus_noAuthenticationToken_emptyResponseBody_throwException()
throws Exception {
HttpResponse eapChallengeResponse =
HttpResponse.builder().setContentType(ContentType.JSON).build();
when(mMockHttpClient.request(any())).thenReturn(eapChallengeResponse);
+ CarrierConfig carrierConfig =
+ CarrierConfig.builder().setServerUrl(TEST_URL).build();
ServiceEntitlementRequest request = ServiceEntitlementRequest.builder().build();
- try {
- mEapAkaApi.queryEntitlementStatus(ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
- TEST_URL,
- request);
- fail();
- } catch (ServiceEntitlementException exception) {
- assertThat(exception.getErrorCode()).isEqualTo(
- ServiceEntitlementException.MALFORMED_HTTP_RESPONSE);
- assertThat(exception.getMessage()).isEqualTo("Failed to parse json object");
- assertThat(exception.getCause()).isInstanceOf(JSONException.class);
- }
+ ServiceEntitlementException exception = expectThrows(
+ ServiceEntitlementException.class,
+ () -> mEapAkaApi.queryEntitlementStatus(
+ ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
+ carrierConfig,
+ request));
+
+ assertThat(exception.getErrorCode()).isEqualTo(
+ ServiceEntitlementException.MALFORMED_HTTP_RESPONSE);
+ assertThat(exception.getMessage()).isEqualTo("Failed to parse json object");
+ assertThat(exception.getCause()).isInstanceOf(JSONException.class);
}
}
diff --git a/tests/src/com/android/libraries/entitlement/http/HttpClientTest.java b/tests/src/com/android/libraries/entitlement/http/HttpClientTest.java
index 3be93ca..6a08295 100644
--- a/tests/src/com/android/libraries/entitlement/http/HttpClientTest.java
+++ b/tests/src/com/android/libraries/entitlement/http/HttpClientTest.java
@@ -18,20 +18,27 @@ package com.android.libraries.entitlement.http;
import static com.google.common.truth.Truth.assertThat;
-import static org.testng.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.testng.Assert.expectThrows;
import static java.nio.charset.StandardCharsets.UTF_8;
+import android.net.Network;
+
import androidx.test.runner.AndroidJUnit4;
import com.android.libraries.entitlement.ServiceEntitlementException;
import com.android.libraries.entitlement.http.HttpConstants.ContentType;
import com.android.libraries.entitlement.http.HttpConstants.RequestMethod;
import com.android.libraries.entitlement.testing.FakeURLStreamHandler;
+import com.android.libraries.entitlement.testing.FakeURLStreamHandler.FakeHttpsURLConnection;
import com.android.libraries.entitlement.testing.FakeURLStreamHandler.FakeResponse;
import com.google.common.collect.ImmutableMap;
+import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,7 +56,7 @@ public class HttpClientTest {
private static FakeURLStreamHandler sFakeURLStreamHandler;
- private final HttpClient mHttpClient = new HttpClient();
+ private HttpClient mHttpClient;
@BeforeClass
public static void setupURLStreamHandlerFactory() {
@@ -57,6 +64,14 @@ public class HttpClientTest {
URL.setURLStreamHandlerFactory(sFakeURLStreamHandler);
}
+ @Before
+ public void setUp() {
+ // Reset sFakeURLStreamHandler
+ sFakeURLStreamHandler.stubResponse(ImmutableMap.of());
+
+ mHttpClient = new HttpClient();
+ }
+
@Test
public void request_contentTypeXml_returnsXmlBody() throws Exception {
FakeResponse responseContent =
@@ -66,13 +81,23 @@ public class HttpClientTest {
.setResponseBody(TEST_RESPONSE_BODY.getBytes(UTF_8))
.setContentType(CONTENT_TYPE_STRING_JSON)
.build();
- HttpRequest request =
- HttpRequest.builder().setUrl(TEST_URL).setRequestMethod(RequestMethod.GET).build();
Map<String, FakeResponse> response = ImmutableMap.of(TEST_URL, responseContent);
sFakeURLStreamHandler.stubResponse(response);
+ HttpRequest request =
+ HttpRequest.builder()
+ .setUrl(TEST_URL)
+ .setRequestMethod(RequestMethod.GET)
+ .setTimeoutInSec(70)
+ .build();
HttpResponse httpResponse = mHttpClient.request(request);
+ // Verify that one HttpURLConnection was opened and its timeout is 70 seconds.
+ assertThat(sFakeURLStreamHandler.getConnections()).hasSize(1);
+ HttpURLConnection connection = sFakeURLStreamHandler.getConnections().get(0);
+ assertThat(connection.getConnectTimeout()).isEqualTo(70 * 1000);
+ assertThat(connection.getReadTimeout()).isEqualTo(70 * 1000);
+ // Verify the HttpResponse.
assertThat(httpResponse.contentType()).isEqualTo(ContentType.JSON);
assertThat(httpResponse.body()).isEqualTo(TEST_RESPONSE_BODY);
assertThat(httpResponse.responseCode()).isEqualTo(HttpURLConnection.HTTP_OK);
@@ -93,15 +118,53 @@ public class HttpClientTest {
Map<String, FakeResponse> response = ImmutableMap.of(TEST_URL, responseContent);
sFakeURLStreamHandler.stubResponse(response);
- try {
- mHttpClient.request(request);
- fail();
- } catch (ServiceEntitlementException exception) {
- assertThat(exception.getErrorCode()).isEqualTo(
- ServiceEntitlementException.ERROR_HTTP_STATUS_NOT_SUCCESS);
- assertThat(exception.getHttpStatus()).isEqualTo(HttpURLConnection.HTTP_BAD_REQUEST);
- assertThat(exception.getMessage()).isEqualTo("Invalid connection response");
- assertThat(exception.getRetryAfter()).isEqualTo(RETRY_AFTER);
- }
+ ServiceEntitlementException exception =
+ expectThrows(ServiceEntitlementException.class, () -> mHttpClient.request(request));
+
+ // Verify the ServiceEntitlementException.
+ assertThat(exception.getErrorCode()).isEqualTo(
+ ServiceEntitlementException.ERROR_HTTP_STATUS_NOT_SUCCESS);
+ assertThat(exception.getHttpStatus()).isEqualTo(HttpURLConnection.HTTP_BAD_REQUEST);
+ assertThat(exception).hasMessageThat().contains("Invalid connection response");
+ assertThat(exception.getRetryAfter()).isEqualTo(RETRY_AFTER);
+ // Verify that one HttpURLConnection was opened and its timeout is 30 seconds.
+ assertThat(sFakeURLStreamHandler.getConnections()).hasSize(1);
+ HttpURLConnection connection = sFakeURLStreamHandler.getConnections().get(0);
+ assertThat(connection.getConnectTimeout()).isEqualTo(30 * 1000);
+ assertThat(connection.getReadTimeout()).isEqualTo(30 * 1000);
+ }
+
+ @Test
+ public void request_contentTypeXml_returnsXmlBody_useSpecificNetwork() throws Exception {
+ FakeResponse responseContent =
+ FakeResponse.builder()
+ .setResponseCode(HttpURLConnection.HTTP_OK)
+ .setResponseLocation(null)
+ .setResponseBody(TEST_RESPONSE_BODY.getBytes(UTF_8))
+ .setContentType(CONTENT_TYPE_STRING_JSON)
+ .build();
+ Network network = mock(Network.class);
+ URL url = new URL(TEST_URL);
+ FakeHttpsURLConnection connection = new FakeHttpsURLConnection(url, responseContent);
+ when(network.openConnection(url)).thenReturn(connection);
+ HttpRequest request =
+ HttpRequest.builder()
+ .setUrl(TEST_URL)
+ .setRequestMethod(RequestMethod.GET)
+ .setNetwork(network)
+ .setTimeoutInSec(70)
+ .build();
+
+ HttpResponse httpResponse = mHttpClient.request(request);
+
+ // Verify that the HttpURLConnection associsted with Netwotk was opened
+ // and its timeout is 70 seconds.
+ verify(network).openConnection(url);
+ assertThat(connection.getConnectTimeout()).isEqualTo(70 * 1000);
+ assertThat(connection.getReadTimeout()).isEqualTo(70 * 1000);
+ // Verify the HttpResponse.
+ assertThat(httpResponse.contentType()).isEqualTo(ContentType.JSON);
+ assertThat(httpResponse.body()).isEqualTo(TEST_RESPONSE_BODY);
+ assertThat(httpResponse.responseCode()).isEqualTo(HttpURLConnection.HTTP_OK);
}
-} \ No newline at end of file
+}
diff --git a/tests/utils/com/android/libraries/entitlement/testing/FakeURLStreamHandler.java b/tests/utils/com/android/libraries/entitlement/testing/FakeURLStreamHandler.java
index d323412..bee3d0c 100644
--- a/tests/utils/com/android/libraries/entitlement/testing/FakeURLStreamHandler.java
+++ b/tests/utils/com/android/libraries/entitlement/testing/FakeURLStreamHandler.java
@@ -17,6 +17,7 @@
package com.android.libraries.entitlement.testing;
import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import java.io.ByteArrayInputStream;
@@ -37,12 +38,12 @@ import javax.annotation.Nullable;
import javax.net.ssl.HttpsURLConnection;
/**
- * Fakes {@linkplain java.net.URLStreamHandler} which is used to set URLStreamHandlerFactory for URL
- * as {@linkplain java.net.URL} is a final class and cannot be mocked using mockito.
+ * A {@link URLStreamHandlerFactory} to return faked {@link URLConnection}, as {@link URL} is a
+ * final class and {@link URL#openConnection} cannot be mocked using mockito.
*/
public class FakeURLStreamHandler extends URLStreamHandler implements URLStreamHandlerFactory {
-
- private Map<String, FakeResponse> mResponseMap;
+ private Map<String, FakeResponse> mResponses = ImmutableMap.of();
+ private List<FakeHttpsURLConnection> mConnections = new ArrayList<>();
private static final String ACCESS_TOKEN = "8dGozfI6%2FEaSsE7LaTfJKwdy";
private static final String LOCATION = "Location";
@@ -51,7 +52,9 @@ public class FakeURLStreamHandler extends URLStreamHandler implements URLStreamH
@Override
public URLConnection openConnection(URL u) {
- FakeHttpsURLConnection connection = new FakeHttpsURLConnection(u);
+ FakeHttpsURLConnection connection =
+ new FakeHttpsURLConnection(u, mResponses.get(u.toString()));
+ mConnections.add(connection);
return connection;
}
@@ -60,50 +63,48 @@ public class FakeURLStreamHandler extends URLStreamHandler implements URLStreamH
return this;
}
+ /**
+ * Prepares canned responses. Must be called before using this handler to open any {@link
+ * URLConnection}.
+ */
public FakeURLStreamHandler stubResponse(Map<String, FakeResponse> response) {
- this.mResponseMap = response;
+ mResponses = response;
+ mConnections = new ArrayList<>();
return this;
}
- /**
- * Fakes {@linkplain java.net.HttpURLConnection} to avoid making any network connection.
- */
- public class FakeHttpsURLConnection extends HttpsURLConnection {
-
- public ByteArrayOutputStream mByteArrayOutputStream;
+ /** Returns {@link URLConnection}s opened by this handler since last {@link #stubResponse}. */
+ public ImmutableList<FakeHttpsURLConnection> getConnections() {
+ return ImmutableList.copyOf(mConnections);
+ }
- private final String mUrlString;
+ /** Faked {@link HttpsURLConnection} to avoid making any network connection. */
+ public static class FakeHttpsURLConnection extends HttpsURLConnection {
+ private final FakeResponse mResponse;
- protected FakeHttpsURLConnection(URL url) {
+ public FakeHttpsURLConnection(URL url, FakeResponse response) {
super(url);
- this.mUrlString = url.toString();
+ mResponse = response;
}
@Override
public InputStream getInputStream() throws IOException {
- InputStream inputStream = new ByteArrayInputStream(
- mResponseMap.get(mUrlString).responseBody());
- if (inputStream == null) {
- throw new IOException();
- }
- return inputStream;
+ return new ByteArrayInputStream(mResponse.responseBody());
}
@Override
public OutputStream getOutputStream() {
- mByteArrayOutputStream = new ByteArrayOutputStream();
- return mByteArrayOutputStream;
+ return new ByteArrayOutputStream();
}
@Override
public int getResponseCode() {
- return mResponseMap.get(mUrlString).responseCode();
+ return mResponse.responseCode();
}
@Override
public Map<String, List<String>> getHeaderFields() {
- List<String> locationList = new ArrayList<>();
- locationList.add("access_token=" + ACCESS_TOKEN);
+ List<String> locationList = ImmutableList.of("access_token=" + ACCESS_TOKEN);
return ImmutableMap.of("Location", locationList);
}
@@ -111,11 +112,11 @@ public class FakeURLStreamHandler extends URLStreamHandler implements URLStreamH
public String getHeaderField(String name) {
switch (name) {
case LOCATION:
- return "Location: " + mResponseMap.get(mUrlString).responseLocation();
+ return "Location: " + mResponse.responseLocation();
case CONTENT_TYPE:
- return mResponseMap.get(mUrlString).contentType();
+ return mResponse.contentType();
case RETRY_AFTER:
- return mResponseMap.get(mUrlString).retryAfter();
+ return mResponse.retryAfter();
default:
return null;
}
@@ -188,4 +189,4 @@ public class FakeURLStreamHandler extends URLStreamHandler implements URLStreamH
public abstract FakeResponse build();
}
}
-} \ No newline at end of file
+}