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.imsserviceentitlement;
18 
19 import static com.android.imsserviceentitlement.entitlement.EntitlementConfiguration.ClientBehavior.NEEDS_TO_RESET;
20 import static com.android.imsserviceentitlement.entitlement.EntitlementConfiguration.ClientBehavior.VALID_DURING_VALIDITY;
21 import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_TWO;
22 import static com.android.libraries.entitlement.ServiceEntitlementException.ERROR_HTTP_STATUS_NOT_SUCCESS;
23 
24 import static com.google.common.truth.Truth.assertThat;
25 
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.ArgumentMatchers.eq;
28 import static org.mockito.Mockito.verify;
29 import static org.mockito.Mockito.when;
30 
31 import android.content.Context;
32 import android.os.PersistableBundle;
33 import android.telephony.CarrierConfigManager;
34 import android.telephony.SubscriptionManager;
35 
36 import androidx.test.core.app.ApplicationProvider;
37 import androidx.test.runner.AndroidJUnit4;
38 
39 import com.android.imsserviceentitlement.entitlement.EntitlementConfiguration;
40 import com.android.imsserviceentitlement.entitlement.EntitlementResult;
41 import com.android.imsserviceentitlement.fcm.FcmTokenStore;
42 import com.android.imsserviceentitlement.utils.TelephonyUtils;
43 import com.android.libraries.entitlement.ServiceEntitlement;
44 import com.android.libraries.entitlement.ServiceEntitlementException;
45 import com.android.libraries.entitlement.ServiceEntitlementRequest;
46 
47 import com.google.common.collect.ImmutableList;
48 
49 import org.junit.After;
50 import org.junit.Before;
51 import org.junit.Rule;
52 import org.junit.Test;
53 import org.junit.runner.RunWith;
54 import org.mockito.Mock;
55 import org.mockito.Spy;
56 import org.mockito.junit.MockitoJUnit;
57 import org.mockito.junit.MockitoRule;
58 
59 import java.text.SimpleDateFormat;
60 import java.time.Clock;
61 import java.time.Instant;
62 import java.time.ZoneOffset;
63 import java.util.Date;
64 import java.util.Locale;
65 import java.util.TimeZone;
66 
67 @RunWith(AndroidJUnit4.class)
68 public class ImsEntitlementApiTest {
69     @Rule public final MockitoRule rule = MockitoJUnit.rule();
70 
71     @Spy private Context mContext = ApplicationProvider.getApplicationContext();
72 
73     @Mock private ServiceEntitlement mMockServiceEntitlement;
74     @Mock private EntitlementConfiguration mMockEntitlementConfiguration;
75     @Mock private CarrierConfigManager mCarrierConfigManager;
76 
77     private PersistableBundle mCarrierConfig;
78 
79     private static final int SUB_ID = 1;
80     private static final int ENTITLEMENT_VERSION = 2;
81     private static final String FCM_TOKEN = "FCM_TOKEN";
82     private static final String KEY_DEFAULT_SERVICE_ENTITLEMENT_STATUS_BOOL =
83             "imsserviceentitlement.default_service_entitlement_status_bool";
84     private static final String RAW_XML =
85             "<wap-provisioningdoc version=\"1.1\">"
86                     + "  <characteristic type=\"VERS\">"
87                     + "    <parm name=\"version\" value=\"1\"/>"
88                     + "    <parm name=\"validity\" value=\"1728000\"/>"
89                     + "  </characteristic>"
90                     + "  <characteristic type=\"TOKEN\">"
91                     + "    <parm name=\"token\" value=\"kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX\"/>"
92                     + "    <parm name=\"validity\" value=\"3600\"/>"
93                     + "  </characteristic>"
94                     + "  <characteristic type=\"APPLICATION\">"
95                     + "    <parm name=\"AppID\" value=\"ap2004\"/>"
96                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
97                     + "  </characteristic>"
98                     + "</wap-provisioningdoc>";
99     private static final String RAW_XML_NEW_TOKEN =
100             "<wap-provisioningdoc version=\"1.1\">"
101                     + "  <characteristic type=\"VERS\">"
102                     + "    <parm name=\"version\" value=\"1\"/>"
103                     + "    <parm name=\"validity\" value=\"1728000\"/>"
104                     + "  </characteristic>"
105                     + "  <characteristic type=\"TOKEN\">"
106                     + "    <parm name=\"token\" value=\"NEW_TOKEN\"/>"
107                     + "    <parm name=\"validity\" value=\"3600\"/>"
108                     + "  </characteristic>\n"
109                     + "  <characteristic type=\"APPLICATION\">"
110                     + "    <parm name=\"AppID\" value=\"ap2004\"/>"
111                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
112                     + "  </characteristic>"
113                     + "</wap-provisioningdoc>";
114     private static final String MULTIPLE_APPIDS_RAW_XML =
115             "<wap-provisioningdoc version=\"1.1\">"
116                     + "  <characteristic type=\"VERS\">"
117                     + "    <parm name=\"version\" value=\"1\"/>"
118                     + "    <parm name=\"validity\" value=\"1728000\"/>"
119                     + "  </characteristic>"
120                     + "  <characteristic type=\"TOKEN\">"
121                     + "    <parm name=\"token\" value=\"kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX\"/>"
122                     + "    <parm name=\"validity\" value=\"3600\"/>"
123                     + "  </characteristic>"
124                     + "  <characteristic type=\"APPLICATION\">"
125                     + "    <parm name=\"AppID\" value=\"ap2003\"/>"
126                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
127                     + "  </characteristic>\n"
128                     + "  <characteristic type=\"APPLICATION\">"
129                     + "    <parm name=\"AppID\" value=\"ap2004\"/>\n"
130                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
131                     + "  </characteristic>"
132                     + "  <characteristic type=\"APPLICATION\">"
133                     + "    <parm name=\"AppID\" value=\"ap2005\"/>"
134                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
135                     + "  </characteristic>"
136                     + "</wap-provisioningdoc>";
137     private static final String RAW_XML_NEED_TO_RESET =
138             "<wap-provisioningdoc version=\"1.1\">"
139                     + "  <characteristic type=\"VERS\">"
140                     + "    <parm name=\"version\" value=\"0\"/>"
141                     + "    <parm name=\"validity\" value=\"0\"/>"
142                     + "  </characteristic>"
143                     + "  <characteristic type=\"TOKEN\">"
144                     + "    <parm name=\"token\" value=\"kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX\"/>"
145                     + "    <parm name=\"validity\" value=\"3600\"/>"
146                     + "  </characteristic>"
147                     + "  <characteristic type=\"APPLICATION\">"
148                     + "    <parm name=\"AppID\" value=\"ap2004\"/>"
149                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
150                     + "  </characteristic>"
151                     + "</wap-provisioningdoc>";
152     private static final String RAW_XML_NEED_TO_RESET_EXCEPT_VERS =
153             "<wap-provisioningdoc version=\"1.1\">"
154                     + "  <characteristic type=\"VERS\">"
155                     + "    <parm name=\"version\" value=\"-1\"/>"
156                     + "    <parm name=\"validity\" value=\"-1\"/>"
157                     + "  </characteristic>"
158                     + "  <characteristic type=\"TOKEN\">"
159                     + "    <parm name=\"token\" value=\"kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX\"/>"
160                     + "    <parm name=\"validity\" value=\"3600\"/>"
161                     + "  </characteristic>"
162                     + "  <characteristic type=\"APPLICATION\">"
163                     + "    <parm name=\"AppID\" value=\"ap2004\"/>"
164                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
165                     + "  </characteristic>"
166                     + "</wap-provisioningdoc>";
167     private static final String RAW_XML_NEED_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON =
168             "<wap-provisioningdoc version=\"1.1\">"
169                     + "  <characteristic type=\"VERS\">"
170                     + "    <parm name=\"version\" value=\"-2\"/>"
171                     + "    <parm name=\"validity\" value=\"-2\"/>"
172                     + "  </characteristic>"
173                     + "  <characteristic type=\"TOKEN\">"
174                     + "    <parm name=\"token\" value=\"kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX\"/>"
175                     + "    <parm name=\"validity\" value=\"3600\"/>"
176                     + "  </characteristic>"
177                     + "  <characteristic type=\"APPLICATION\">"
178                     + "    <parm name=\"AppID\" value=\"ap2004\"/>"
179                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
180                     + "  </characteristic>"
181                     + "</wap-provisioningdoc>";
182 
183     private final EntitlementConfiguration mEntitlementConfiguration =
184             new EntitlementConfiguration(ApplicationProvider.getApplicationContext(), SUB_ID);
185 
186     private ImsEntitlementApi mImsEntitlementApi;
187 
188     @Before
setUp()189     public void setUp() {
190         setImsProvisioningBool(true);
191         setDefaultStatus(false);
192         FcmTokenStore.setToken(mContext, SUB_ID, FCM_TOKEN);
193         mEntitlementConfiguration.reset();
194     }
195 
196     @After
tearDown()197     public void tearDown() {
198         mCarrierConfig = null;
199     }
200 
201     @Test
checkEntitlementStatus_verifyVowifiStatus()202     public void checkEntitlementStatus_verifyVowifiStatus() throws Exception {
203         setImsProvisioningBool(false);
204         setupImsEntitlementApi(mEntitlementConfiguration);
205         when(mMockServiceEntitlement.queryEntitlementStatus(
206                 eq(ImmutableList.of(ServiceEntitlement.APP_VOWIFI)), any())).thenReturn(RAW_XML);
207 
208         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
209 
210         assertThat(result.getVowifiStatus().vowifiEntitled()).isTrue();
211     }
212 
213     @Test
checkEntitlementStatus_verifyImsAppsStatus()214     public void checkEntitlementStatus_verifyImsAppsStatus() throws Exception {
215         setupImsEntitlementApi(mEntitlementConfiguration);
216         when(mMockServiceEntitlement.queryEntitlementStatus(
217                 eq(ImmutableList.of(
218                         ServiceEntitlement.APP_VOWIFI,
219                         ServiceEntitlement.APP_VOLTE,
220                         ServiceEntitlement.APP_SMSOIP)), any())
221         ).thenReturn(MULTIPLE_APPIDS_RAW_XML);
222 
223         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
224 
225         assertThat(result.getVowifiStatus().vowifiEntitled()).isTrue();
226         assertThat(result.getVolteStatus().isActive()).isTrue();
227         assertThat(result.getSmsoveripStatus().isActive()).isTrue();
228     }
229 
230     @Test
checkEntitlementStatus_responseWithVersZero_resetConfiguration()231     public void checkEntitlementStatus_responseWithVersZero_resetConfiguration() throws Exception {
232         setupImsEntitlementApi(mEntitlementConfiguration);
233         when(mMockServiceEntitlement.queryEntitlementStatus(
234                 eq(ImmutableList.of(
235                         ServiceEntitlement.APP_VOWIFI,
236                         ServiceEntitlement.APP_VOLTE,
237                         ServiceEntitlement.APP_SMSOIP)), any())
238         ).thenReturn(RAW_XML_NEED_TO_RESET);
239 
240         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
241 
242         assertThat(mEntitlementConfiguration.getRawXml()).isEqualTo(null);
243         verifyDefaultEntitlementResult(result, false);
244     }
245 
246     @Test
checkEntitlementStatus_responseWithVersMinusOne_resetConfiguration()247     public void checkEntitlementStatus_responseWithVersMinusOne_resetConfiguration()
248             throws Exception {
249         setupImsEntitlementApi(mEntitlementConfiguration);
250         when(mMockServiceEntitlement.queryEntitlementStatus(
251                 eq(ImmutableList.of(
252                         ServiceEntitlement.APP_VOWIFI,
253                         ServiceEntitlement.APP_VOLTE,
254                         ServiceEntitlement.APP_SMSOIP)), any())
255         ).thenReturn(RAW_XML_NEED_TO_RESET_EXCEPT_VERS);
256 
257         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
258 
259         assertThat(mEntitlementConfiguration.getRawXml())
260                 .isEqualTo(EntitlementConfiguration.RAW_XML_VERS_MINUS_ONE);
261         verifyDefaultEntitlementResult(result, false);
262     }
263 
264     @Test
checkEntitlementStatus_responseWithVersMinusTwo_resetConfiguration()265     public void checkEntitlementStatus_responseWithVersMinusTwo_resetConfiguration()
266             throws Exception {
267         setupImsEntitlementApi(mEntitlementConfiguration);
268         when(mMockServiceEntitlement.queryEntitlementStatus(
269                 eq(ImmutableList.of(
270                         ServiceEntitlement.APP_VOWIFI,
271                         ServiceEntitlement.APP_VOLTE,
272                         ServiceEntitlement.APP_SMSOIP)), any())
273         ).thenReturn(RAW_XML_NEED_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON);
274 
275         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
276 
277         assertThat(mEntitlementConfiguration.getRawXml())
278                 .isEqualTo(EntitlementConfiguration.RAW_XML_VERS_MINUS_TWO);
279         verifyDefaultEntitlementResult(result, false);
280     }
281 
282     @Test
283     public void
checkEntitlementStatus_defaultEnabledAndResponseWithVersZero_resetConfiguration()284             checkEntitlementStatus_defaultEnabledAndResponseWithVersZero_resetConfiguration()
285                     throws Exception {
286         setDefaultStatus(true);
287         setupImsEntitlementApi(mEntitlementConfiguration);
288         when(mMockServiceEntitlement.queryEntitlementStatus(
289                 eq(ImmutableList.of(
290                         ServiceEntitlement.APP_VOWIFI,
291                         ServiceEntitlement.APP_VOLTE,
292                         ServiceEntitlement.APP_SMSOIP)), any())
293         ).thenReturn(RAW_XML_NEED_TO_RESET);
294 
295         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
296 
297         assertThat(mEntitlementConfiguration.getRawXml()).isEqualTo(null);
298         verifyDefaultEntitlementResult(result, true);
299     }
300 
301     @Test
302     public void
checkEntitlementStatus_defaultEnabledAndResponseWithVersMinusOne_resetConfiguration()303             checkEntitlementStatus_defaultEnabledAndResponseWithVersMinusOne_resetConfiguration()
304                     throws Exception {
305         setupImsEntitlementApi(mEntitlementConfiguration);
306         setDefaultStatus(true);
307         when(mMockServiceEntitlement.queryEntitlementStatus(
308                 eq(ImmutableList.of(
309                         ServiceEntitlement.APP_VOWIFI,
310                         ServiceEntitlement.APP_VOLTE,
311                         ServiceEntitlement.APP_SMSOIP)), any())
312         ).thenReturn(RAW_XML_NEED_TO_RESET_EXCEPT_VERS);
313 
314         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
315 
316         assertThat(mEntitlementConfiguration.getRawXml())
317                 .isEqualTo(EntitlementConfiguration.RAW_XML_VERS_MINUS_ONE);
318         verifyDefaultEntitlementResult(result, true);
319     }
320 
321     @Test
322     public void
checkEntitlementStatus_defaultEnabledAndResponseWithVersMinusTwo_resetConfiguration()323             checkEntitlementStatus_defaultEnabledAndResponseWithVersMinusTwo_resetConfiguration()
324                     throws Exception {
325         setupImsEntitlementApi(mEntitlementConfiguration);
326         setDefaultStatus(true);
327         when(mMockServiceEntitlement.queryEntitlementStatus(
328                 eq(ImmutableList.of(
329                         ServiceEntitlement.APP_VOWIFI,
330                         ServiceEntitlement.APP_VOLTE,
331                         ServiceEntitlement.APP_SMSOIP)), any())
332         ).thenReturn(RAW_XML_NEED_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON);
333 
334         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
335 
336         assertThat(mEntitlementConfiguration.getRawXml())
337                 .isEqualTo(EntitlementConfiguration.RAW_XML_VERS_MINUS_TWO);
338         verifyDefaultEntitlementResult(result, true);
339     }
340 
341     @Test
checkEntitlementStatus_verifyConfigs()342     public void checkEntitlementStatus_verifyConfigs() throws Exception {
343         setImsProvisioningBool(false);
344         setupImsEntitlementApi(mEntitlementConfiguration);
345         when(mMockServiceEntitlement.queryEntitlementStatus(
346                 eq(ImmutableList.of(ServiceEntitlement.APP_VOWIFI)),
347                 any())).thenReturn(RAW_XML);
348 
349         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
350 
351         assertThat(mEntitlementConfiguration.getRawXml()).isEqualTo(RAW_XML);
352         assertThat(mEntitlementConfiguration.getToken().get()).isEqualTo(
353                 "kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX");
354         assertThat(mEntitlementConfiguration.getTokenValidity()).isEqualTo(3600);
355         assertThat(mEntitlementConfiguration.entitlementValidation()).isEqualTo(
356                 VALID_DURING_VALIDITY);
357     }
358 
359     @Test
checkEntitlementStatus_resultNull_verifyVowifiStatusAndConfigs()360     public void checkEntitlementStatus_resultNull_verifyVowifiStatusAndConfigs() throws Exception {
361         setImsProvisioningBool(false);
362         setupImsEntitlementApi(mEntitlementConfiguration);
363         when(mMockServiceEntitlement.queryEntitlementStatus(
364                 eq(ImmutableList.of(ServiceEntitlement.APP_VOWIFI)), any())).thenReturn(null);
365 
366         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
367 
368         assertThat(result.getVowifiStatus().vowifiEntitled()).isFalse();
369         assertThat(mEntitlementConfiguration.getRawXml()).isEqualTo(null);
370         assertThat(mEntitlementConfiguration.getToken().isPresent()).isFalse();
371         assertThat(mEntitlementConfiguration.getTokenValidity()).isEqualTo(0);
372         assertThat(mEntitlementConfiguration.entitlementValidation()).isEqualTo(NEEDS_TO_RESET);
373     }
374 
375     @Test
checkEntitlementStatus_httpResponse511_dataStoreReset()376     public void checkEntitlementStatus_httpResponse511_dataStoreReset() throws Exception {
377         setImsProvisioningBool(false);
378         setupImsEntitlementApi(mMockEntitlementConfiguration);
379         when(mMockServiceEntitlement.queryEntitlementStatus(
380                 eq(ImmutableList.of(ServiceEntitlement.APP_VOWIFI)), any()))
381                 .thenThrow(
382                         new ServiceEntitlementException(
383                                 ERROR_HTTP_STATUS_NOT_SUCCESS, 511, "Invalid connection response"));
384 
385         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
386 
387         verify(mMockEntitlementConfiguration).reset();
388         assertThat(result).isNull();
389     }
390 
391     @Test
checkEntitlementStatus_httpResponse511_fullAuthnDone()392     public void checkEntitlementStatus_httpResponse511_fullAuthnDone() throws Exception {
393         setImsProvisioningBool(false);
394         setupImsEntitlementApi(mEntitlementConfiguration);
395         mEntitlementConfiguration.update(ENTITLEMENT_VERSION, RAW_XML);
396         // While perform fast-authn, throws exception with code 511
397         when(mMockServiceEntitlement.queryEntitlementStatus(
398                 ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
399                 authenticationRequest("kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX")))
400                 .thenThrow(
401                         new ServiceEntitlementException(
402                                 ERROR_HTTP_STATUS_NOT_SUCCESS, 511, "Invalid connection response"));
403         // While perform full-authn, return the result
404         when(mMockServiceEntitlement.queryEntitlementStatus(
405                 ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
406                 authenticationRequest(null)))
407                 .thenReturn(RAW_XML_NEW_TOKEN);
408 
409         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
410 
411         assertThat(result).isNotNull();
412         assertThat(mEntitlementConfiguration.getToken().get()).isEqualTo("NEW_TOKEN");
413     }
414 
415     @Test
checkEntitlementStatus_httpResponse503WithDateTime_returnsRetryAfter()416     public void checkEntitlementStatus_httpResponse503WithDateTime_returnsRetryAfter()
417             throws Exception {
418         setImsProvisioningBool(false);
419         setupImsEntitlementApi(mEntitlementConfiguration);
420         mEntitlementConfiguration.update(ENTITLEMENT_VERSION, RAW_XML);
421         Clock fixedClock = Clock.fixed(Instant.ofEpochSecond(0), ZoneOffset.UTC);
422         ImsEntitlementApi.sClock = fixedClock;
423 
424         // While perform fast-authn, throws exception with code 503
425         when(mMockServiceEntitlement.queryEntitlementStatus(
426                 ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
427                 authenticationRequest("kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX")))
428                 .thenThrow(
429                         new ServiceEntitlementException(
430                                 ERROR_HTTP_STATUS_NOT_SUCCESS,
431                                 503,
432                                 getDateTimeAfter(120, fixedClock),
433                                 "Invalid connection response"));
434 
435         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
436 
437         assertThat(result).isNotNull();
438         assertThat(result.getRetryAfterSeconds()).isEqualTo(120);
439     }
440 
441     @Test
checkEntitlementStatus_httpResponse503WithNumericValue_returnsRetryAfter()442     public void checkEntitlementStatus_httpResponse503WithNumericValue_returnsRetryAfter()
443             throws Exception {
444         setImsProvisioningBool(false);
445         setupImsEntitlementApi(mEntitlementConfiguration);
446         mEntitlementConfiguration.update(ENTITLEMENT_VERSION, RAW_XML);
447         // While perform fast-authn, throws exception with code 503
448         when(mMockServiceEntitlement.queryEntitlementStatus(
449                 ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
450                 authenticationRequest("kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX")))
451                 .thenThrow(
452                         new ServiceEntitlementException(
453                                 ERROR_HTTP_STATUS_NOT_SUCCESS,
454                                 503,
455                                 "120",
456                                 "Invalid connection response"));
457 
458         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
459 
460         assertThat(result).isNotNull();
461         assertThat(result.getRetryAfterSeconds()).isEqualTo(120);
462     }
463 
464     @Test
checkEntitlementStatus_invalidSubId_resultNull()465     public void checkEntitlementStatus_invalidSubId_resultNull() {
466         ImsEntitlementApi imsEntitlementApi =
467                 new ImsEntitlementApi(mContext, SubscriptionManager.INVALID_SUBSCRIPTION_ID);
468 
469         EntitlementResult result = imsEntitlementApi.checkEntitlementStatus();
470 
471         assertThat(result).isNull();
472     }
473 
authenticationRequest(String token)474     private ServiceEntitlementRequest authenticationRequest(String token) {
475         ServiceEntitlementRequest.Builder requestBuilder = ServiceEntitlementRequest.builder();
476         if (token != null) {
477             requestBuilder.setAuthenticationToken(token);
478         }
479         requestBuilder.setEntitlementVersion(String.valueOf(ENTITLEMENT_VERSION_TWO) + ".0");
480         requestBuilder.setNotificationToken(FcmTokenStore.getToken(mContext, SUB_ID));
481         requestBuilder.setAcceptContentType(ServiceEntitlementRequest.ACCEPT_CONTENT_TYPE_XML);
482         return requestBuilder.build();
483     }
484 
setupImsEntitlementApi(EntitlementConfiguration entitlementConfiguration)485     private void setupImsEntitlementApi(EntitlementConfiguration entitlementConfiguration) {
486         mImsEntitlementApi = new ImsEntitlementApi(
487                 mContext,
488                 SUB_ID,
489                 TelephonyUtils.isImsProvisioningRequired(mContext, SUB_ID),
490                 mMockServiceEntitlement,
491                 entitlementConfiguration);
492     }
493 
setImsProvisioningBool(boolean provisioning)494     private void setImsProvisioningBool(boolean provisioning) {
495         initializeCarrierConfig();
496         mCarrierConfig.putBoolean(
497                 CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL, provisioning);
498     }
499 
setDefaultStatus(Boolean defaultStatus)500     private void setDefaultStatus(Boolean defaultStatus) {
501         initializeCarrierConfig();
502         mCarrierConfig.putBoolean(
503                 KEY_DEFAULT_SERVICE_ENTITLEMENT_STATUS_BOOL, defaultStatus);
504     }
505 
initializeCarrierConfig()506     private void initializeCarrierConfig() {
507         if (mCarrierConfig == null) {
508             mCarrierConfig = new PersistableBundle();
509             when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfig);
510             when(mContext.getSystemService(CarrierConfigManager.class))
511                     .thenReturn(mCarrierConfigManager);
512         }
513     }
514 
getDateTimeAfter(long seconds, Clock fixedClock)515     private String getDateTimeAfter(long seconds, Clock fixedClock) {
516         SimpleDateFormat dateFormat = new SimpleDateFormat(
517                 "EEE, dd MMM yyyy HH:mm:ss z", Locale.US);
518         dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
519         return dateFormat.format(Date.from(fixedClock.instant().plusSeconds(seconds)));
520     }
521 
verifyDefaultEntitlementResult(EntitlementResult result, boolean isActive)522     private void verifyDefaultEntitlementResult(EntitlementResult result, boolean isActive) {
523         assertThat(result.getVowifiStatus().vowifiEntitled()).isEqualTo(isActive);
524         assertThat(result.getVowifiStatus().serverDataMissing()).isEqualTo(false);
525         assertThat(result.getVowifiStatus().inProgress()).isEqualTo(false);
526         assertThat(result.getVolteStatus().isActive()).isEqualTo(isActive);
527         assertThat(result.getVonrStatus().isHomeActive()).isEqualTo(isActive);
528         assertThat(result.getVonrStatus().isRoamingActive()).isEqualTo(isActive);
529         assertThat(result.getSmsoveripStatus().isActive()).isEqualTo(isActive);
530     }
531 }
532