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.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__DISABLED;
20 import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__ENABLED;
21 import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED;
22 import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT;
23 import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_EIGHT;
24 import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_TWO;
25 
26 import static com.google.common.truth.Truth.assertThat;
27 
28 import static org.mockito.ArgumentMatchers.anyBoolean;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
32 
33 import android.app.job.JobParameters;
34 import android.app.job.JobScheduler;
35 import android.content.Context;
36 import android.os.PersistableBundle;
37 import android.telephony.CarrierConfigManager;
38 import android.telephony.SubscriptionInfo;
39 import android.telephony.SubscriptionManager;
40 import android.util.SparseArray;
41 
42 import androidx.test.core.app.ApplicationProvider;
43 import androidx.test.runner.AndroidJUnit4;
44 
45 import com.android.imsserviceentitlement.entitlement.EntitlementResult;
46 import com.android.imsserviceentitlement.job.JobManager;
47 import com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementStatus;
48 import com.android.imsserviceentitlement.ts43.Ts43SmsOverIpStatus;
49 import com.android.imsserviceentitlement.ts43.Ts43VolteStatus;
50 import com.android.imsserviceentitlement.ts43.Ts43VonrStatus;
51 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus;
52 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.AddrStatus;
53 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.ProvStatus;
54 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.TcStatus;
55 import com.android.imsserviceentitlement.utils.ImsUtils;
56 
57 import org.junit.After;
58 import org.junit.Before;
59 import org.junit.Rule;
60 import org.junit.Test;
61 import org.junit.runner.RunWith;
62 import org.mockito.Mock;
63 import org.mockito.Spy;
64 import org.mockito.junit.MockitoJUnit;
65 import org.mockito.junit.MockitoRule;
66 
67 import java.lang.reflect.Field;
68 
69 @RunWith(AndroidJUnit4.class)
70 public class ImsEntitlementPollingServiceTest {
71     @Rule public final MockitoRule rule = MockitoJUnit.rule();
72 
73     @Spy private Context mContext = ApplicationProvider.getApplicationContext();
74 
75     @Mock private ImsUtils mImsUtils;
76     @Mock private JobParameters mJobParameters;
77     @Mock private SubscriptionManager mSubscriptionManager;
78     @Mock private SubscriptionInfo mSubscriptionInfo;
79     @Mock private ImsEntitlementApi mImsEntitlementApi;
80     @Mock private CarrierConfigManager mCarrierConfigManager;
81 
82     private ImsEntitlementPollingService mService;
83     private JobScheduler mScheduler;
84     private PersistableBundle mCarrierConfig;
85 
86     private static final int SUB_ID = 1;
87     private static final int SLOT_ID = 0;
88     private static final String KEY_ENTITLEMENT_VERSION_INT =
89             "imsserviceentitlement.entitlement_version_int";
90 
91     @Before
setUp()92     public void setUp() throws Exception {
93         mService = new ImsEntitlementPollingService();
94         mService.attachBaseContext(mContext);
95         mService.onCreate();
96         mService.onBind(null);
97         mService.injectImsEntitlementApi(mImsEntitlementApi);
98         mScheduler = mContext.getSystemService(JobScheduler.class);
99         setActivedSubscription();
100         setupImsUtils();
101         setJobParameters();
102         setWfcEnabledByUser(true);
103         setImsProvisioningBool(false);
104         setEntitlementVersion(ENTITLEMENT_VERSION_TWO);
105     }
106 
107     @After
tearDown()108     public void tearDown() {
109         mCarrierConfig = null;
110     }
111 
112     @Test
doEntitlementCheck_isWfcEnabledByUserFalse_doNothing()113     public void doEntitlementCheck_isWfcEnabledByUserFalse_doNothing() throws Exception {
114         setWfcEnabledByUser(false);
115 
116         mService.onStartJob(mJobParameters);
117         mService.mOngoingTask.get(); // wait for job finish.
118 
119         verify(mImsEntitlementApi, never()).checkEntitlementStatus();
120     }
121 
122 
123     @Test
doEntitlementCheck_shouldTurnOffWfc_disableWfc()124     public void doEntitlementCheck_shouldTurnOffWfc_disableWfc() throws Exception {
125         EntitlementResult entitlementResult = getEntitlementResult(sDisableVoWiFi);
126         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
127 
128         mService.onStartJob(mJobParameters);
129         mService.mOngoingTask.get(); // wait for job finish.
130 
131         verify(mImsUtils).disableWfc();
132     }
133 
134     @Test
doEntitlementCheck_shouldNotTurnOffWfc_enableWfc()135     public void doEntitlementCheck_shouldNotTurnOffWfc_enableWfc() throws Exception {
136         EntitlementResult entitlementResult = getEntitlementResult(sEnableVoWiFi);
137         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
138 
139         mService.onStartJob(mJobParameters);
140         mService.mOngoingTask.get(); // wait for job finish.
141 
142         verify(mImsUtils, never()).disableWfc();
143     }
144 
145     @Test
doEntitlementCheck_shouldTurnOffImsApps_setAllProvisionedFalse()146     public void doEntitlementCheck_shouldTurnOffImsApps_setAllProvisionedFalse() throws Exception {
147         setImsProvisioningBool(true);
148         EntitlementResult entitlementResult = getImsEntitlementResult(
149                 sDisableVoWiFi,
150                 sDisableVoLte,
151                 sDisableSmsoverip
152         );
153         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
154 
155         mService.onStartJob(mJobParameters);
156         mService.mOngoingTask.get(); // wait for job finish.
157 
158         verify(mImsUtils).setVolteProvisioned(false);
159         verify(mImsUtils).setVowifiProvisioned(false);
160         verify(mImsUtils).setSmsoipProvisioned(false);
161         verify(mImsUtils, never()).setVonrProvisioned(anyBoolean());
162         assertThat(mService.mOngoingTask.getVonrResult())
163                 .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT);
164     }
165 
166     @Test
doV8EntitlementCheck_shouldTurnOffImsApps_setAllProvisionedFalse()167     public void doV8EntitlementCheck_shouldTurnOffImsApps_setAllProvisionedFalse()
168             throws Exception {
169         setImsProvisioningBool(true);
170         setEntitlementVersion(ENTITLEMENT_VERSION_EIGHT);
171         EntitlementResult entitlementResult =
172                 getImsEntitlementResult(
173                         sDisableVoWiFi, sDisableVoLte, sDisableVonr, sDisableSmsoverip);
174         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
175 
176         mService.onStartJob(mJobParameters);
177         mService.mOngoingTask.get(); // wait for job finish.
178 
179         verify(mImsUtils).setVolteProvisioned(false);
180         verify(mImsUtils).setVowifiProvisioned(false);
181         verify(mImsUtils).setSmsoipProvisioned(false);
182         verify(mImsUtils).setVonrProvisioned(false);
183         assertThat(mService.mOngoingTask.getVonrResult())
184                 .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__DISABLED);
185     }
186 
187     @Test
doEntitlementCheck_shouldTurnOnImsApps_setAllProvisionedTrue()188     public void doEntitlementCheck_shouldTurnOnImsApps_setAllProvisionedTrue() throws Exception {
189         setImsProvisioningBool(true);
190         EntitlementResult entitlementResult = getImsEntitlementResult(
191                 sEnableVoWiFi,
192                 sEnableVoLte,
193                 sEnableSmsoverip
194         );
195         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
196 
197         mService.onStartJob(mJobParameters);
198         mService.mOngoingTask.get(); // wait for job finish.
199 
200         verify(mImsUtils).setVolteProvisioned(true);
201         verify(mImsUtils).setVowifiProvisioned(true);
202         verify(mImsUtils).setSmsoipProvisioned(true);
203         verify(mImsUtils, never()).setVonrProvisioned(anyBoolean());
204         assertThat(mService.mOngoingTask.getVonrResult())
205                 .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT);
206     }
207 
208     @Test
doV8EntitlementCheck_shouldTurnOnImsApps_setAllProvisionedTrue()209     public void doV8EntitlementCheck_shouldTurnOnImsApps_setAllProvisionedTrue() throws Exception {
210         setImsProvisioningBool(true);
211         setEntitlementVersion(ENTITLEMENT_VERSION_EIGHT);
212         EntitlementResult entitlementResult =
213                 getImsEntitlementResult(sEnableVoWiFi, sEnableVoLte, sEnableVonr, sEnableSmsoverip);
214         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
215 
216         mService.onStartJob(mJobParameters);
217         mService.mOngoingTask.get(); // wait for job finish.
218 
219         verify(mImsUtils).setVolteProvisioned(true);
220         verify(mImsUtils).setVowifiProvisioned(true);
221         verify(mImsUtils).setSmsoipProvisioned(true);
222         verify(mImsUtils).setVonrProvisioned(true);
223         assertThat(mService.mOngoingTask.getVonrResult())
224                 .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__ENABLED);
225     }
226 
227     @Test
doV8EntitlementCheck_entitlementResultNull_setAllProvisionedTrue()228     public void doV8EntitlementCheck_entitlementResultNull_setAllProvisionedTrue()
229             throws Exception {
230         setImsProvisioningBool(true);
231         setEntitlementVersion(ENTITLEMENT_VERSION_EIGHT);
232         EntitlementResult entitlementResult = null;
233         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
234 
235         mService.onStartJob(mJobParameters);
236         mService.mOngoingTask.get(); // wait for job finish.
237 
238         verify(mImsUtils).setVolteProvisioned(true);
239         verify(mImsUtils).setVowifiProvisioned(true);
240         verify(mImsUtils).setSmsoipProvisioned(true);
241         verify(mImsUtils).setVonrProvisioned(true);
242         assertThat(mService.mOngoingTask.getVonrResult())
243                 .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__ENABLED);
244     }
245 
246     @Test
doEntitlementCheck_ImsEntitlementShouldRetry_rescheduleJob()247     public void doEntitlementCheck_ImsEntitlementShouldRetry_rescheduleJob() throws Exception {
248         setImsProvisioningBool(true);
249         EntitlementResult entitlementResult =
250                 EntitlementResult.builder(false).setRetryAfterSeconds(120).build();
251         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
252 
253         mService.onStartJob(mJobParameters);
254         mService.mOngoingTask.get(); // wait for job finish.
255 
256         verify(mImsUtils, never()).setVolteProvisioned(anyBoolean());
257         verify(mImsUtils, never()).setVowifiProvisioned(anyBoolean());
258         verify(mImsUtils, never()).setSmsoipProvisioned(anyBoolean());
259         verify(mImsUtils, never()).setVonrProvisioned(anyBoolean());
260         assertThat(mService.mOngoingTask.getVonrResult())
261                 .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT);
262         assertThat(
263                 mScheduler.getPendingJob(
264                         jobIdWithSubId(JobManager.QUERY_ENTITLEMENT_STATUS_JOB_ID, SUB_ID)))
265                 .isNotNull();
266     }
267 
268     @Test
doEntitlementCheck_WfcEntitlementShouldRetry_rescheduleJob()269     public void doEntitlementCheck_WfcEntitlementShouldRetry_rescheduleJob() throws Exception {
270         EntitlementResult entitlementResult =
271                 EntitlementResult.builder(false).setRetryAfterSeconds(120).build();
272         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
273 
274         mService.onStartJob(mJobParameters);
275         mService.mOngoingTask.get(); // wait for job finish.
276 
277         verify(mImsUtils, never()).setVolteProvisioned(anyBoolean());
278         verify(mImsUtils, never()).setVowifiProvisioned(anyBoolean());
279         verify(mImsUtils, never()).setSmsoipProvisioned(anyBoolean());
280         verify(mImsUtils, never()).setVonrProvisioned(anyBoolean());
281         assertThat(mService.mOngoingTask.getVonrResult())
282                 .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT);
283         assertThat(
284                 mScheduler.getPendingJob(
285                         jobIdWithSubId(JobManager.QUERY_ENTITLEMENT_STATUS_JOB_ID, SUB_ID)))
286                 .isNotNull();
287     }
288 
289     @Test
doEntitlementCheck_runtimeException_entitlementUpdateFail()290     public void doEntitlementCheck_runtimeException_entitlementUpdateFail() throws Exception {
291         setImsProvisioningBool(true);
292         when(mImsEntitlementApi.checkEntitlementStatus()).thenThrow(new RuntimeException());
293 
294         mService.onStartJob(mJobParameters);
295         mService.mOngoingTask.get(); // wait for job finish.
296 
297         assertThat(mService.mOngoingTask.getVonrResult())
298                 .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED);
299     }
300 
301     @Test
doWfcEntitlementCheck_runtimeException_entitlementUpdateFail()302     public void doWfcEntitlementCheck_runtimeException_entitlementUpdateFail() throws Exception {
303         when(mImsEntitlementApi.checkEntitlementStatus()).thenThrow(new RuntimeException());
304 
305         mService.onStartJob(mJobParameters);
306         mService.mOngoingTask.get(); // wait for job finish.
307 
308         assertThat(mService.mOngoingTask.getVowifiResult())
309                 .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED);
310     }
311 
312     @Test
enqueueJob_hasJob()313     public void enqueueJob_hasJob() {
314         ImsEntitlementPollingService.enqueueJob(mContext, SUB_ID, 0);
315 
316         assertThat(
317                 mScheduler.getPendingJob(
318                         jobIdWithSubId(JobManager.QUERY_ENTITLEMENT_STATUS_JOB_ID, SUB_ID)))
319                 .isNotNull();
320     }
321 
setActivedSubscription()322     private void setActivedSubscription() {
323         when(mSubscriptionInfo.getSimSlotIndex()).thenReturn(SLOT_ID);
324         when(mSubscriptionManager.getActiveSubscriptionInfo(SUB_ID)).thenReturn(mSubscriptionInfo);
325         when(mContext.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE))
326                 .thenReturn(mSubscriptionManager);
327     }
328 
setupImsUtils()329     private void setupImsUtils() throws Exception {
330         SparseArray<ImsUtils> imsUtilsInstances = new SparseArray<>();
331         imsUtilsInstances.put(SUB_ID, mImsUtils);
332         Field field = ImsUtils.class.getDeclaredField("sInstances");
333         field.setAccessible(true);
334         field.set(null, imsUtilsInstances);
335     }
336 
setWfcEnabledByUser(boolean isEnabled)337     private void setWfcEnabledByUser(boolean isEnabled) {
338         when(mImsUtils.isWfcEnabledByUser()).thenReturn(isEnabled);
339     }
340 
setJobParameters()341     private void setJobParameters() {
342         PersistableBundle bundle = new PersistableBundle();
343         bundle.putInt(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, SUB_ID);
344         bundle.putInt(JobManager.EXTRA_SLOT_ID, SLOT_ID);
345         when(mJobParameters.getExtras()).thenReturn(bundle);
346         when(mJobParameters.getJobId()).thenReturn(JobManager.QUERY_ENTITLEMENT_STATUS_JOB_ID);
347     }
348 
setImsProvisioningBool(boolean provisioning)349     private void setImsProvisioningBool(boolean provisioning) {
350         initializeCarrierConfig();
351         mCarrierConfig.putBoolean(
352                 CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL,
353                 provisioning
354         );
355     }
356 
setEntitlementVersion(int entitlementVersion)357     private void setEntitlementVersion(int entitlementVersion) {
358         initializeCarrierConfig();
359         mCarrierConfig.putInt(KEY_ENTITLEMENT_VERSION_INT, entitlementVersion);
360     }
361 
initializeCarrierConfig()362     private void initializeCarrierConfig() {
363         if (mCarrierConfig == null) {
364             mCarrierConfig = new PersistableBundle();
365             when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfig);
366             when(mContext.getSystemService(CarrierConfigManager.class))
367                     .thenReturn(mCarrierConfigManager);
368         }
369     }
370 
getEntitlementResult(Ts43VowifiStatus vowifiStatus)371     private static EntitlementResult getEntitlementResult(Ts43VowifiStatus vowifiStatus) {
372         return EntitlementResult.builder(false).setVowifiStatus(vowifiStatus).build();
373     }
374 
getImsEntitlementResult( Ts43VowifiStatus vowifiStatus, Ts43VolteStatus volteStatus, Ts43SmsOverIpStatus smsOverIpStatus)375     private static EntitlementResult getImsEntitlementResult(
376             Ts43VowifiStatus vowifiStatus,
377             Ts43VolteStatus volteStatus,
378             Ts43SmsOverIpStatus smsOverIpStatus) {
379         return EntitlementResult.builder(false)
380                 .setVowifiStatus(vowifiStatus)
381                 .setVolteStatus(volteStatus)
382                 .setSmsoveripStatus(smsOverIpStatus)
383                 .build();
384     }
385 
getImsEntitlementResult( Ts43VowifiStatus vowifiStatus, Ts43VolteStatus volteStatus, Ts43VonrStatus vonrStatus, Ts43SmsOverIpStatus smsOverIpStatus)386     private static EntitlementResult getImsEntitlementResult(
387             Ts43VowifiStatus vowifiStatus,
388             Ts43VolteStatus volteStatus,
389             Ts43VonrStatus vonrStatus,
390             Ts43SmsOverIpStatus smsOverIpStatus) {
391         return EntitlementResult.builder(false)
392                 .setVowifiStatus(vowifiStatus)
393                 .setVolteStatus(volteStatus)
394                 .setVonrStatus(vonrStatus)
395                 .setSmsoveripStatus(smsOverIpStatus)
396                 .build();
397     }
398 
jobIdWithSubId(int jobId, int subId)399     private int jobIdWithSubId(int jobId, int subId) {
400         return 1000 * subId + jobId;
401     }
402 
403     private static final Ts43VowifiStatus sDisableVoWiFi =
404             Ts43VowifiStatus.builder()
405                     .setEntitlementStatus(EntitlementStatus.DISABLED)
406                     .setTcStatus(TcStatus.NOT_AVAILABLE)
407                     .setAddrStatus(AddrStatus.NOT_AVAILABLE)
408                     .setProvStatus(ProvStatus.NOT_PROVISIONED)
409                     .build();
410 
411     private static final Ts43VowifiStatus sEnableVoWiFi =
412             Ts43VowifiStatus.builder()
413                     .setEntitlementStatus(EntitlementStatus.ENABLED)
414                     .setTcStatus(TcStatus.AVAILABLE)
415                     .setAddrStatus(AddrStatus.AVAILABLE)
416                     .setProvStatus(ProvStatus.PROVISIONED)
417                     .build();
418 
419     private static final Ts43VolteStatus sDisableVoLte =
420             Ts43VolteStatus.builder()
421                     .setEntitlementStatus(EntitlementStatus.DISABLED)
422                     .build();
423 
424     private static final Ts43VolteStatus sEnableVoLte =
425             Ts43VolteStatus.builder()
426                     .setEntitlementStatus(EntitlementStatus.ENABLED)
427                     .build();
428 
429     private static final Ts43VonrStatus sDisableVonr =
430             Ts43VonrStatus.builder()
431                     .setHomeEntitlementStatus(EntitlementStatus.DISABLED)
432                     .setRoamingEntitlementStatus(EntitlementStatus.DISABLED)
433                     .build();
434 
435     private static final Ts43VonrStatus sEnableVonr =
436             Ts43VonrStatus.builder()
437                     .setHomeEntitlementStatus(EntitlementStatus.ENABLED)
438                     .setRoamingEntitlementStatus(EntitlementStatus.ENABLED)
439                     .build();
440 
441     private static final Ts43SmsOverIpStatus sDisableSmsoverip =
442             Ts43SmsOverIpStatus.builder()
443                     .setEntitlementStatus(EntitlementStatus.DISABLED)
444                     .build();
445 
446     private static final Ts43SmsOverIpStatus sEnableSmsoverip =
447             Ts43SmsOverIpStatus.builder()
448                     .setEntitlementStatus(EntitlementStatus.ENABLED)
449                     .build();
450 }
451