1 /*
2  * Copyright 2020 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.google.android.iwlan;
18 
19 import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
20 
21 import static org.junit.Assert.assertEquals;
22 import static org.junit.Assert.assertFalse;
23 import static org.junit.Assert.assertTrue;
24 import static org.mockito.Mockito.*;
25 import static org.mockito.Mockito.mock;
26 import static org.mockito.Mockito.spy;
27 
28 import android.content.ContentResolver;
29 import android.content.Context;
30 import android.content.res.AssetManager;
31 import android.net.ipsec.ike.exceptions.IkeProtocolException;
32 import android.os.PersistableBundle;
33 import android.telephony.CarrierConfigManager;
34 import android.telephony.DataFailCause;
35 import android.telephony.SubscriptionInfo;
36 import android.telephony.SubscriptionManager;
37 import android.telephony.TelephonyManager;
38 import android.telephony.data.DataService;
39 
40 import androidx.test.InstrumentationRegistry;
41 
42 import org.junit.After;
43 import org.junit.Before;
44 import org.junit.Test;
45 import org.mockito.Mock;
46 import org.mockito.MockitoAnnotations;
47 import org.mockito.MockitoSession;
48 import org.mockito.quality.Strictness;
49 
50 import java.io.InputStream;
51 import java.util.Map;
52 
53 public class ErrorPolicyManagerTest {
54     private static final String TAG = "ErrorPolicyManagerTest";
55 
56     // @Rule public final MockitoRule mockito = MockitoJUnit.rule();
57 
58     private ErrorPolicyManager mErrorPolicyManager;
59     private static final int DEFAULT_SLOT_INDEX = 0;
60     private static final int DEFAULT_SUBID = 0;
61     private static final int TEST_CARRIER_ID = 1;
62 
63     @Mock private Context mMockContext;
64     @Mock CarrierConfigManager mMockCarrierConfigManager;
65     @Mock SubscriptionManager mMockSubscriptionManager;
66     @Mock TelephonyManager mMockTelephonyManager;
67     @Mock SubscriptionInfo mMockSubscriptionInfo;
68     @Mock DataService.DataServiceProvider mMockDataServiceProvider;
69     @Mock private ContentResolver mMockContentResolver;
70     MockitoSession mStaticMockSession;
71 
72     @Before
setUp()73     public void setUp() throws Exception {
74         MockitoAnnotations.initMocks(this);
75         mStaticMockSession =
76                 mockitoSession()
77                         .mockStatic(IwlanDataService.class)
78                         .strictness(Strictness.LENIENT)
79                         .startMocking();
80         when(IwlanDataService.getDataServiceProvider(anyInt()))
81                 .thenReturn(mMockDataServiceProvider);
82         AssetManager mockAssetManager = mock(AssetManager.class);
83         Context context = InstrumentationRegistry.getTargetContext();
84         InputStream is = context.getResources().getAssets().open("defaultiwlanerrorconfig.json");
85         doReturn(mockAssetManager).when(mMockContext).getAssets();
86         doReturn(is).when(mockAssetManager).open(any());
87         setupMockForCarrierConfig(null);
88         mErrorPolicyManager = spy(ErrorPolicyManager.getInstance(mMockContext, DEFAULT_SLOT_INDEX));
89     }
90 
91     @After
cleanUp()92     public void cleanUp() throws Exception {
93         mStaticMockSession.finishMocking();
94         mErrorPolicyManager.releaseInstance();
95     }
96 
buildIwlanIkeProtocolError(int errorCode, byte[] errorData)97     private static IwlanError buildIwlanIkeProtocolError(int errorCode, byte[] errorData) {
98         final IkeProtocolException exception = mock(IkeProtocolException.class);
99         when(exception.getErrorType()).thenReturn(errorCode);
100         when(exception.getErrorData()).thenReturn(errorData);
101         return new IwlanError(exception);
102     }
103 
buildIwlanIkeProtocolError(int errorCode)104     private static IwlanError buildIwlanIkeProtocolError(int errorCode) {
105         return buildIwlanIkeProtocolError(errorCode, new byte[0]);
106     }
107 
buildIwlanIkeAuthFailedError()108     private static IwlanError buildIwlanIkeAuthFailedError() {
109         return buildIwlanIkeProtocolError(IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED);
110     }
111 
buildIwlanIkeChildSaNotFoundError()112     private static IwlanError buildIwlanIkeChildSaNotFoundError() {
113         return buildIwlanIkeProtocolError(IkeProtocolException.ERROR_TYPE_CHILD_SA_NOT_FOUND);
114     }
115 
116     @Test
testValidCarrierConfig()117     public void testValidCarrierConfig() throws Exception {
118         String apn = "ims";
119         String config =
120                 "[{"
121                         + "\"ApnName\": \""
122                         + apn
123                         + "\","
124                         + "\"ErrorTypes\": [{"
125                         + getErrorTypeInJSON(
126                                 "IKE_PROTOCOL_ERROR_TYPE",
127                                 new String[] {"24", "34", "9000-9050"},
128                                 new String[] {"4", "8", "16"},
129                                 new String[] {"APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT"})
130                         + "}, {"
131                         + getErrorTypeInJSON(
132                                 "GENERIC_ERROR_TYPE",
133                                 new String[] {"SERVER_SELECTION_FAILED"},
134                                 new String[] {"0"},
135                                 new String[] {"APM_ENABLE_EVENT"})
136                         + "}]"
137                         + "}]";
138 
139         PersistableBundle bundle = new PersistableBundle();
140         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
141         setupMockForCarrierConfig(bundle);
142         mErrorPolicyManager
143                 .mHandler
144                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
145                 .sendToTarget();
146 
147         sleep(1000);
148 
149         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16
150         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
151         long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
152         assertEquals(4, time);
153         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
154         assertEquals(8, time);
155         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
156         assertEquals(16, time);
157         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
158         assertEquals(86400, time);
159 
160         // Validate the range error detail.
161         iwlanError = buildIwlanIkeProtocolError(9030, new byte[] {0x00, 0x01});
162         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
163         assertEquals(4, time);
164         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
165         assertEquals(8, time);
166         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
167         assertEquals(16, time);
168         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
169         assertEquals(86400, time);
170 
171         // GENERIC_PROTOCOL_ERROR_TYPE - SERVER_SELECTION_FAILED and retryArray = 0
172         iwlanError = new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED);
173         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
174         assertEquals(0, time);
175         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
176         assertEquals(86400, time);
177         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
178         assertEquals(86400, time);
179 
180         // Fallback case GENERIC_PROTOCOL_ERROR_TYPE(44) and retryArray is 5, 10, -1 as in
181         // DEFAULT_CONFIG
182         iwlanError = buildIwlanIkeChildSaNotFoundError();
183         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
184         assertEquals(5, time);
185         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
186         assertEquals(10, time);
187         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
188         assertEquals(10, time);
189         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
190         assertEquals(10, time);
191     }
192 
193     @Test
testInvalidCarrierConfig()194     public void testInvalidCarrierConfig() throws Exception {
195         String apn = "ims";
196         String config =
197                 "[{"
198                         + "\"ApnName\": \""
199                         + apn
200                         + "\","
201                         + "\"ErrorTypes\": [{"
202                         + getErrorTypeInJSON(
203                                 "IKE_PROTOCOL_ERROR_TYPE",
204                                 new String[] {"WRONG_ERROR_DETAIL"},
205                                 new String[] {"4", "8", "16"},
206                                 new String[] {"APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT"})
207                         + "}]"
208                         + "}]";
209 
210         PersistableBundle bundle = new PersistableBundle();
211         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
212         setupMockForCarrierConfig(bundle);
213         mErrorPolicyManager
214                 .mHandler
215                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
216                 .sendToTarget();
217 
218         sleep(1000);
219 
220         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 5, 10, 15 as it will fallback due to failed
221         // parsing
222         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
223         long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
224         assertEquals(5, time);
225         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
226         assertEquals(10, time);
227         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
228         assertEquals(10, time);
229         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
230         assertEquals(10, time);
231     }
232 
233     @Test
testChoosingFallbackPolicy()234     public void testChoosingFallbackPolicy() throws Exception {
235         String apn = "ims";
236         String config =
237                 "[{"
238                         + "\"ApnName\": \""
239                         + apn
240                         + "\","
241                         + "\"ErrorTypes\": [{"
242                         + getErrorTypeInJSON(
243                                 "IKE_PROTOCOL_ERROR_TYPE",
244                                 new String[] {"24", "34"},
245                                 new String[] {"4", "8", "16"},
246                                 new String[] {"APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT"})
247                         + "}, {"
248                         + getErrorTypeInJSON(
249                                 "IKE_PROTOCOL_ERROR_TYPE",
250                                 new String[] {"*"},
251                                 new String[] {"0"},
252                                 new String[] {"APM_ENABLE_EVENT"})
253                         + "}]"
254                         + "}]";
255         PersistableBundle bundle = new PersistableBundle();
256         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
257         setupMockForCarrierConfig(bundle);
258         mErrorPolicyManager
259                 .mHandler
260                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
261                 .sendToTarget();
262 
263         sleep(1000);
264 
265         mErrorPolicyManager.logErrorPolicies();
266 
267         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4, 8, 16
268         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
269         long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
270         assertEquals(4, time);
271         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
272         assertEquals(8, time);
273         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
274         assertEquals(16, time);
275         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
276         assertEquals(86400, time);
277 
278         // IKE_PROTOCOL_ERROR_TYPE(44) and retryArray = 0 as it will fallback to
279         // IKE_PROTOCOL_ERROR_TYPE generic fallback first.
280         iwlanError = buildIwlanIkeChildSaNotFoundError();
281         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
282         assertEquals(0, time);
283         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
284         assertEquals(86400, time);
285     }
286 
287     @Test
testCanBringUpTunnel()288     public void testCanBringUpTunnel() throws Exception {
289         String apn = "ims";
290         String config =
291                 "[{"
292                         + "\"ApnName\": \""
293                         + apn
294                         + "\","
295                         + "\"ErrorTypes\": [{"
296                         + getErrorTypeInJSON(
297                                 "IKE_PROTOCOL_ERROR_TYPE",
298                                 new String[] {"24", "34"},
299                                 new String[] {"4", "8", "16"},
300                                 new String[] {"APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT"})
301                         + "}, {"
302                         + getErrorTypeInJSON(
303                                 "GENERIC_ERROR_TYPE",
304                                 new String[] {"SERVER_SELECTION_FAILED"},
305                                 new String[] {"0"},
306                                 new String[] {"APM_ENABLE_EVENT"})
307                         + "}]"
308                         + "}]";
309         PersistableBundle bundle = new PersistableBundle();
310         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
311         setupMockForCarrierConfig(bundle);
312         mErrorPolicyManager
313                 .mHandler
314                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
315                 .sendToTarget();
316 
317         sleep(1000);
318 
319         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16
320         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
321         long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
322         assertEquals(4, time);
323 
324         boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn);
325         assertFalse(bringUpTunnel);
326 
327         sleep(4000);
328 
329         bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn);
330         assertTrue(bringUpTunnel);
331 
332         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
333         assertEquals(8, time);
334 
335         bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn);
336         assertFalse(bringUpTunnel);
337     }
338 
339     @Test
testNoErrorScenario()340     public void testNoErrorScenario() throws Exception {
341         String apn = "ims";
342         String config =
343                 "[{"
344                         + "\"ApnName\": \""
345                         + apn
346                         + "\","
347                         + "\"ErrorTypes\": [{"
348                         + getErrorTypeInJSON(
349                                 "IKE_PROTOCOL_ERROR_TYPE",
350                                 new String[] {"24", "34"},
351                                 new String[] {"4", "8", "16"},
352                                 new String[] {"APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT"})
353                         + "}, {"
354                         + getErrorTypeInJSON(
355                                 "GENERIC_ERROR_TYPE",
356                                 new String[] {"SERVER_SELECTION_FAILED"},
357                                 new String[] {"0"},
358                                 new String[] {"APM_ENABLE_EVENT"})
359                         + "}]"
360                         + "}]";
361         PersistableBundle bundle = new PersistableBundle();
362         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
363         setupMockForCarrierConfig(bundle);
364         mErrorPolicyManager
365                 .mHandler
366                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
367                 .sendToTarget();
368 
369         sleep(1000);
370 
371         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16
372         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
373         long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
374         assertEquals(4, time);
375 
376         // report no error
377         iwlanError = new IwlanError(IwlanError.NO_ERROR);
378         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
379         assertEquals(-1, time);
380 
381         // Check whether the error is cleared after NO_ERROR is reported
382         boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn);
383         assertTrue(bringUpTunnel);
384     }
385 
386     @Test
testWifiDisableUnthrottle()387     public void testWifiDisableUnthrottle() throws Exception {
388         String apn = "ims";
389         String config =
390                 "[{"
391                         + "\"ApnName\": \""
392                         + apn
393                         + "\","
394                         + "\"ErrorTypes\": [{"
395                         + getErrorTypeInJSON(
396                                 "IKE_PROTOCOL_ERROR_TYPE",
397                                 new String[] {"24", "34"},
398                                 new String[] {"6", "12", "24"},
399                                 new String[] {"APM_ENABLE_EVENT", "WIFI_DISABLE_EVENT"})
400                         + "}, {"
401                         + getErrorTypeInJSON(
402                                 "GENERIC_ERROR_TYPE",
403                                 new String[] {"SERVER_SELECTION_FAILED"},
404                                 new String[] {"0"},
405                                 new String[] {"APM_DISABLE_EVENT"})
406                         + "}]"
407                         + "}]";
408         PersistableBundle bundle = new PersistableBundle();
409         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
410         setupMockForCarrierConfig(bundle);
411         mErrorPolicyManager
412                 .mHandler
413                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
414                 .sendToTarget();
415         sleep(1000);
416 
417         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 6, 12, 24
418         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
419         long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
420         assertEquals(6, time);
421 
422         mErrorPolicyManager
423                 .mHandler
424                 .obtainMessage(IwlanEventListener.WIFI_DISABLE_EVENT)
425                 .sendToTarget();
426         sleep(500);
427         verify(mMockDataServiceProvider, times(1)).notifyApnUnthrottled(eq(apn));
428 
429         boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn);
430         assertTrue(bringUpTunnel);
431 
432         iwlanError = buildIwlanIkeAuthFailedError();
433         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
434         assertEquals(6, time);
435     }
436 
437     @Test
testWFCDisableUnthrottle()438     public void testWFCDisableUnthrottle() throws Exception {
439         String apn = "ims";
440         String config =
441                 "[{"
442                         + "\"ApnName\": \""
443                         + apn
444                         + "\","
445                         + "\"ErrorTypes\": [{"
446                         + getErrorTypeInJSON(
447                                 "IKE_PROTOCOL_ERROR_TYPE",
448                                 new String[] {"24", "34"},
449                                 new String[] {"6", "12", "24"},
450                                 new String[] {"WIFI_CALLING_DISABLE_EVENT", "WIFI_DISABLE_EVENT"})
451                         + "}, {"
452                         + getErrorTypeInJSON(
453                                 "GENERIC_ERROR_TYPE",
454                                 new String[] {"SERVER_SELECTION_FAILED"},
455                                 new String[] {"0"},
456                                 new String[] {"APM_DISABLE_EVENT"})
457                         + "}]"
458                         + "}]";
459         PersistableBundle bundle = new PersistableBundle();
460         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
461         setupMockForCarrierConfig(bundle);
462         mErrorPolicyManager
463                 .mHandler
464                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
465                 .sendToTarget();
466         sleep(1000);
467 
468         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 6, 12, 24
469         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
470         long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
471         assertEquals(6, time);
472 
473         mErrorPolicyManager
474                 .mHandler
475                 .obtainMessage(IwlanEventListener.WIFI_CALLING_DISABLE_EVENT)
476                 .sendToTarget();
477         sleep(500);
478         verify(mMockDataServiceProvider, times(1)).notifyApnUnthrottled(eq(apn));
479 
480         boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn);
481         assertTrue(bringUpTunnel);
482 
483         iwlanError = buildIwlanIkeAuthFailedError();
484         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
485         assertEquals(6, time);
486     }
487 
488     @Test
testAPMUnthrottle()489     public void testAPMUnthrottle() throws Exception {
490         String apn = "ims";
491         String config =
492                 "[{"
493                         + "\"ApnName\": \""
494                         + apn
495                         + "\","
496                         + "\"ErrorTypes\": [{"
497                         + getErrorTypeInJSON(
498                                 "IKE_PROTOCOL_ERROR_TYPE",
499                                 new String[] {"24", "34"},
500                                 new String[] {"4", "8", "16"},
501                                 new String[] {"APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT"})
502                         + "}, {"
503                         + getErrorTypeInJSON(
504                                 "GENERIC_ERROR_TYPE",
505                                 new String[] {"SERVER_SELECTION_FAILED"},
506                                 new String[] {"0"},
507                                 new String[] {"APM_DISABLE_EVENT"})
508                         + "}]"
509                         + "}]";
510         PersistableBundle bundle = new PersistableBundle();
511         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
512         setupMockForCarrierConfig(bundle);
513         mErrorPolicyManager
514                 .mHandler
515                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
516                 .sendToTarget();
517         sleep(1000);
518 
519         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16
520         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
521         long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
522         assertEquals(4, time);
523 
524         mErrorPolicyManager
525                 .mHandler
526                 .obtainMessage(IwlanEventListener.APM_ENABLE_EVENT)
527                 .sendToTarget();
528         sleep(500);
529         verify(mMockDataServiceProvider, times(1)).notifyApnUnthrottled(eq(apn));
530 
531         boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn);
532         assertTrue(bringUpTunnel);
533 
534         iwlanError = buildIwlanIkeAuthFailedError();
535         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
536         assertEquals(4, time);
537     }
538 
539     @Test
testGetDataFailCauseRetryTime()540     public void testGetDataFailCauseRetryTime() throws Exception {
541         String apn1 = "ims";
542         String apn2 = "mms";
543         String config =
544                 "[{"
545                         + "\"ApnName\": \""
546                         + apn1
547                         + "\","
548                         + "\"ErrorTypes\": [{"
549                         + getErrorTypeInJSON(
550                                 "IKE_PROTOCOL_ERROR_TYPE",
551                                 new String[] {"24", "34"},
552                                 new String[] {"4", "8", "16"},
553                                 new String[] {"APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT"})
554                         + "}, {"
555                         + getErrorTypeInJSON(
556                                 "GENERIC_ERROR_TYPE",
557                                 new String[] {"SERVER_SELECTION_FAILED"},
558                                 new String[] {"0"},
559                                 new String[] {"APM_ENABLE_EVENT"})
560                         + "}]"
561                         + "}]";
562         PersistableBundle bundle = new PersistableBundle();
563         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
564         setupMockForCarrierConfig(bundle);
565         mErrorPolicyManager
566                 .mHandler
567                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
568                 .sendToTarget();
569 
570         sleep(1000);
571 
572         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16
573         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
574         long time = mErrorPolicyManager.reportIwlanError(apn1, iwlanError);
575         assertEquals(4, time);
576 
577         iwlanError =
578                 buildIwlanIkeProtocolError(
579                         8192 /*PDN_CONNECTION_REJECTION*/, new byte[] {0x00, 0x01});
580         time = mErrorPolicyManager.reportIwlanError(apn2, iwlanError);
581         assertEquals(5, time);
582 
583         int failCause = mErrorPolicyManager.getDataFailCause(apn1);
584         assertEquals(DataFailCause.IWLAN_IKEV2_AUTH_FAILURE, failCause);
585 
586         failCause = mErrorPolicyManager.getDataFailCause(apn2);
587         assertEquals(DataFailCause.IWLAN_PDN_CONNECTION_REJECTION, failCause);
588 
589         long retryTime =
590                 Math.round((double) mErrorPolicyManager.getCurrentRetryTimeMs(apn1) / 1000);
591         assertEquals(4, retryTime);
592 
593         retryTime = Math.round((double) mErrorPolicyManager.getCurrentRetryTimeMs(apn2) / 1000);
594         assertEquals(5, retryTime);
595     }
596 
597     @Test
testBackOffTime()598     public void testBackOffTime() throws Exception {
599         String apn = "ims";
600         String config =
601                 "[{"
602                         + "\"ApnName\": \""
603                         + apn
604                         + "\","
605                         + "\"ErrorTypes\": [{"
606                         + getErrorTypeInJSON(
607                                 "IKE_PROTOCOL_ERROR_TYPE",
608                                 new String[] {"24", "34"},
609                                 new String[] {"10", "15", "20"},
610                                 new String[] {"APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT"})
611                         + "}, {"
612                         + getErrorTypeInJSON(
613                                 "GENERIC_ERROR_TYPE",
614                                 new String[] {"SERVER_SELECTION_FAILED"},
615                                 new String[] {"0"},
616                                 new String[] {"APM_ENABLE_EVENT"})
617                         + "}]"
618                         + "}]";
619 
620         PersistableBundle bundle = new PersistableBundle();
621         bundle.putString(ErrorPolicyManager.KEY_ERROR_POLICY_CONFIG_STRING, config);
622         setupMockForCarrierConfig(bundle);
623         mErrorPolicyManager
624                 .mHandler
625                 .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT)
626                 .sendToTarget();
627 
628         sleep(1000);
629 
630         // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16
631         IwlanError iwlanError = buildIwlanIkeAuthFailedError();
632         long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError, 2);
633 
634         time = Math.round((double) mErrorPolicyManager.getCurrentRetryTimeMs(apn) / 1000);
635         assertEquals(time, 2);
636 
637         // sleep for 2 seconds and make sure that we can bring up tunnel after 2 secs
638         // as back off time - 2 secs should override the retry time in policy - 10 secs
639         sleep(2000);
640         boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn);
641         assertTrue(bringUpTunnel);
642 
643         // test whether the same error reported later uses the right policy
644         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
645         assertEquals(10, time);
646 
647         bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn);
648         assertFalse(bringUpTunnel);
649 
650         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError, 5);
651         time = Math.round((double) mErrorPolicyManager.getCurrentRetryTimeMs(apn) / 1000);
652         assertEquals(time, 5);
653 
654         // test whether the same error reported later starts from the beginning of retry array
655         time = mErrorPolicyManager.reportIwlanError(apn, iwlanError);
656         assertEquals(10, time);
657     }
658 
659     @Test
testErrorStats()660     public void testErrorStats() throws Exception {
661         String apn1 = "ims";
662         String apn2 = "mms";
663 
664         setupMockForCarrierConfig(null);
665 
666         IwlanError iwlanError1 = buildIwlanIkeAuthFailedError();
667         long ikeAuthCountApn1 = 4L;
668         long ikeAuthCountApn2 = 5L;
669         for (int i = 0; i < ikeAuthCountApn1; i++) {
670             mErrorPolicyManager.reportIwlanError(apn1, iwlanError1);
671         }
672         for (int i = 0; i < ikeAuthCountApn2; i++) {
673             mErrorPolicyManager.reportIwlanError(apn2, iwlanError1);
674         }
675 
676         long serverSelectionCountApn1 = 3L;
677         long serverSelectionCountApn2 = 6L;
678         IwlanError iwlanError2 = new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED);
679         for (int i = 0; i < serverSelectionCountApn1; i++) {
680             mErrorPolicyManager.reportIwlanError(apn1, iwlanError2);
681         }
682         // calling backoff timer api
683         for (int i = 0; i < serverSelectionCountApn2; i++) {
684             mErrorPolicyManager.reportIwlanError(apn2, iwlanError2, 3);
685         }
686 
687         Map<String, Long> apn1Stats = mErrorPolicyManager.getErrorStats().mStats.get(apn1);
688         Map<String, Long> apn2Stats = mErrorPolicyManager.getErrorStats().mStats.get(apn2);
689 
690         long resultAuthApn1 = apn1Stats.get(iwlanError1.toString());
691         long resultAuthApn2 = apn2Stats.get(iwlanError1.toString());
692         long resultServerApn1 = apn1Stats.get(iwlanError2.toString());
693         long resultServerApn2 = apn2Stats.get(iwlanError2.toString());
694         assertEquals(resultAuthApn1, ikeAuthCountApn1);
695         assertEquals(resultAuthApn2, ikeAuthCountApn2);
696         assertEquals(resultServerApn1, serverSelectionCountApn1);
697         assertEquals(resultServerApn2, serverSelectionCountApn2);
698     }
699 
getErrorTypeInJSON( String ErrorType, String[] errorDetails, String[] retryArray, String[] unthrottlingEvents)700     private String getErrorTypeInJSON(
701             String ErrorType,
702             String[] errorDetails,
703             String[] retryArray,
704             String[] unthrottlingEvents) {
705         return "\"ErrorType\": \""
706                 + ErrorType
707                 + "\","
708                 + "\"ErrorDetails\": [\""
709                 + String.join("\", \"", errorDetails)
710                 + "\"],"
711                 + "\"RetryArray\": [\""
712                 + String.join("\", \"", retryArray)
713                 + "\"],"
714                 + "\"UnthrottlingEvents\": [\""
715                 + String.join("\", \"", unthrottlingEvents)
716                 + "\"]";
717     }
718 
sleep(long time)719     private void sleep(long time) {
720         try {
721             Thread.sleep(time);
722         } catch (Exception e) {
723             e.printStackTrace();
724         }
725     }
726 
setupMockForCarrierConfig(PersistableBundle bundle)727     private void setupMockForCarrierConfig(PersistableBundle bundle) {
728         doReturn(mMockCarrierConfigManager)
729                 .when(mMockContext)
730                 .getSystemService(eq(CarrierConfigManager.class));
731         doReturn(mMockSubscriptionManager)
732                 .when(mMockContext)
733                 .getSystemService(eq(SubscriptionManager.class));
734         doReturn(mMockTelephonyManager).when(mMockContext).getSystemService(TelephonyManager.class);
735         doReturn(mMockTelephonyManager)
736                 .when(mMockTelephonyManager)
737                 .createForSubscriptionId(anyInt());
738         doReturn(TEST_CARRIER_ID).when(mMockTelephonyManager).getSimCarrierId();
739         SubscriptionInfo mockSubInfo = mock(SubscriptionInfo.class);
740         doReturn(mockSubInfo)
741                 .when(mMockSubscriptionManager)
742                 .getActiveSubscriptionInfoForSimSlotIndex(DEFAULT_SLOT_INDEX);
743         doReturn(DEFAULT_SUBID).when(mockSubInfo).getSubscriptionId();
744         doReturn(bundle).when(mMockCarrierConfigManager).getConfigForSubId(DEFAULT_SLOT_INDEX);
745         when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver);
746     }
747 }
748