/* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * 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. */ package com.google.android.iwlan; import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ContentResolver; import android.content.Context; import android.content.res.AssetManager; import android.net.ipsec.ike.exceptions.IkeProtocolException; import android.os.test.TestLooper; import android.telephony.CarrierConfigManager; import android.telephony.DataFailCause; import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; import android.telephony.data.DataService; import com.google.auto.value.AutoValue; import org.json.JSONArray; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoSession; import org.mockito.quality.Strictness; import java.time.Duration; import java.util.List; import java.util.Map; import java.util.Optional; public class ErrorPolicyManagerTest { @AutoValue abstract static class ErrorPolicyString { abstract String errorType(); abstract List errorDetails(); abstract List retryArray(); abstract List unthrottlingEvents(); abstract Optional numAttemptsPerFqdn(); abstract Optional handoverAttemptCount(); static Builder builder() { return new AutoValue_ErrorPolicyManagerTest_ErrorPolicyString.Builder(); } @AutoValue.Builder abstract static class Builder { abstract Builder setErrorType(String errorType); abstract Builder setErrorDetails(List errorDetails); abstract Builder setRetryArray(List retryArray); abstract Builder setUnthrottlingEvents(List unthrottlingEvents); abstract Builder setNumAttemptsPerFqdn(String numAttemptsPerFqdn); abstract Builder setHandoverAttemptCount(String handoverAttemptCount); abstract ErrorPolicyString build(); } String getErrorPolicyInString() { StringBuilder errorPolicy = new StringBuilder( "\"ErrorType\": \"" + errorType() + "\"," + "\"ErrorDetails\": [\"" + String.join("\", \"", errorDetails()) + "\"]," + "\"RetryArray\": [\"" + String.join("\", \"", retryArray()) + "\"]," + "\"UnthrottlingEvents\": [\"" + String.join("\", \"", unthrottlingEvents()) + "\"]"); numAttemptsPerFqdn() .ifPresent( numAttemptsPerFqdn -> errorPolicy .append(",\"NumAttemptsPerFqdn\": \"") .append(numAttemptsPerFqdn) .append("\"")); handoverAttemptCount() .ifPresent( handoverAttemptCount -> errorPolicy .append(",\"HandoverAttemptCount\": \"") .append(handoverAttemptCount) .append("\"")); return errorPolicy.toString(); } } private static final String TAG = "ErrorPolicyManagerTest"; // @Rule public final MockitoRule mockito = MockitoJUnit.rule(); private ErrorPolicyManager mErrorPolicyManager; private static final int DEFAULT_SLOT_INDEX = 0; private static final int DEFAULT_SUBID = 0; private static final int TEST_CARRIER_ID = 1; private final TestLooper mTestLooper = new TestLooper(); private long mMockedClockTime = 0; private int mCarrierId = TEST_CARRIER_ID; @Mock private Context mMockContext; @Mock CarrierConfigManager mMockCarrierConfigManager; @Mock SubscriptionManager mMockSubscriptionManager; @Mock TelephonyManager mMockTelephonyManager; @Mock SubscriptionInfo mMockSubscriptionInfo; @Mock DataService.DataServiceProvider mMockDataServiceProvider; @Mock private ContentResolver mMockContentResolver; MockitoSession mStaticMockSession; @Before public void setUp() throws Exception { MockitoAnnotations.initMocks(this); mStaticMockSession = mockitoSession() .mockStatic(IwlanDataService.class) .spyStatic(IwlanHelper.class) .strictness(Strictness.LENIENT) .startMocking(); when(IwlanDataService.getDataServiceProvider(anyInt())) .thenReturn(mMockDataServiceProvider); when(IwlanHelper.elapsedRealtime()).thenAnswer(i -> mMockedClockTime); doReturn(mMockSubscriptionManager) .when(mMockContext) .getSystemService(eq(SubscriptionManager.class)); doReturn(mMockTelephonyManager).when(mMockContext).getSystemService(TelephonyManager.class); doReturn(mMockTelephonyManager) .when(mMockTelephonyManager) .createForSubscriptionId(anyInt()); when(mMockTelephonyManager.getSimCarrierId()).thenAnswer(i -> mCarrierId); SubscriptionInfo mockSubInfo = mock(SubscriptionInfo.class); doReturn(mockSubInfo) .when(mMockSubscriptionManager) .getActiveSubscriptionInfoForSimSlotIndex(DEFAULT_SLOT_INDEX); doReturn(DEFAULT_SUBID).when(mockSubInfo).getSubscriptionId(); when(mMockContext.getContentResolver()).thenReturn(mMockContentResolver); ErrorPolicyManager.resetAllInstances(); mErrorPolicyManager = spy(ErrorPolicyManager.getInstance(mMockContext, DEFAULT_SLOT_INDEX)); doReturn(mTestLooper.getLooper()).when(mErrorPolicyManager).getLooper(); mErrorPolicyManager.initHandler(); } @After public void cleanUp() throws Exception { mStaticMockSession.finishMocking(); mErrorPolicyManager.releaseInstance(); IwlanCarrierConfig.resetTestConfig(); } private static IwlanError buildIwlanIkeProtocolError(int errorCode, byte[] errorData) { final IkeProtocolException exception = mock(IkeProtocolException.class); when(exception.getErrorType()).thenReturn(errorCode); when(exception.getErrorData()).thenReturn(errorData); return new IwlanError(exception); } private static IwlanError buildIwlanIkeProtocolError(int errorCode) { return buildIwlanIkeProtocolError(errorCode, new byte[0]); } private static IwlanError buildIwlanIkeAuthFailedError() { return buildIwlanIkeProtocolError(IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED); } private static IwlanError buildIwlanIkeChildSaNotFoundError() { return buildIwlanIkeProtocolError(IkeProtocolException.ERROR_TYPE_CHILD_SA_NOT_FOUND); } private static IwlanError buildIwlanIkeInternalAddressFailure() { return buildIwlanIkeProtocolError(IkeProtocolException.ERROR_TYPE_INTERNAL_ADDRESS_FAILURE); } @Test public void testValidCarrierConfig() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34", "9000-9050")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(4, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(8, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(16, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(86400, time); // Validate the range error detail. iwlanError = buildIwlanIkeProtocolError(9030, new byte[] {0x00, 0x01}); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(4, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(8, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(16, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(86400, time); // GENERIC_PROTOCOL_ERROR_TYPE - SERVER_SELECTION_FAILED and retryArray = 0 iwlanError = new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(86400, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(86400, time); // Fallback case IKE_INIT_TIMEOUT and retryArray is 1, 2, 2, 10, 20 // Should start at RetryIndex 0 iwlanError = new IwlanError(IwlanError.IKE_INIT_TIMEOUT); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(1, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(2, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(2, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); // Fallback case GENERIC_PROTOCOL_ERROR_TYPE(44) and retryArray is 5, 10, -1 as in // DEFAULT_CONFIG iwlanError = buildIwlanIkeChildSaNotFoundError(); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(5, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(20, time); } @Test public void testShouldKeepRetryIndexForDifferentErrorCause() { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34", "9000-9050")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16 IwlanError authFailedIwlanError = buildIwlanIkeAuthFailedError(); IwlanError customProtocolIwlanError = buildIwlanIkeProtocolError(9030); IwlanError serverSelectionIwlanError = new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED); long time = mErrorPolicyManager.reportIwlanError(apn, authFailedIwlanError); assertEquals(4, time); // Different protocol error should have its own Index (i.e. not shared with auth error) time = mErrorPolicyManager.reportIwlanError(apn, customProtocolIwlanError); assertEquals(4, time); time = mErrorPolicyManager.reportIwlanError(apn, customProtocolIwlanError); assertEquals(8, time); time = mErrorPolicyManager.reportIwlanError(apn, customProtocolIwlanError); assertEquals(16, time); // Different IwlanError type should have its own index time = mErrorPolicyManager.reportIwlanError(apn, serverSelectionIwlanError); assertEquals(0, time); time = mErrorPolicyManager.reportIwlanError(apn, serverSelectionIwlanError); assertEquals(86400, time); // Retry index should not be cleared, should start from last same cause index (auth error) time = mErrorPolicyManager.reportIwlanError(apn, authFailedIwlanError); assertEquals(8, time); time = mErrorPolicyManager.reportIwlanError(apn, authFailedIwlanError); assertEquals(16, time); time = mErrorPolicyManager.reportIwlanError(apn, serverSelectionIwlanError); assertEquals(86400, time); // if no error, it should clear the retry index time = mErrorPolicyManager.reportIwlanError(apn, new IwlanError(IwlanError.NO_ERROR)); assertEquals(-1, time); // if backoff time is specified, should use the specified time instead time = mErrorPolicyManager.reportIwlanError(apn, authFailedIwlanError); assertEquals(4, time); time = mErrorPolicyManager.reportIwlanError(apn, authFailedIwlanError, 5); assertEquals(5, time); } @Test public void testDefaultPolicyFallback() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("WRONG_ERROR_DETAIL")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // Fallback to default Iwlan error policy for IKE_PROTOCOL_ERROR_TYPE(24) because of failed // parsing (or lack of explicit carrier-defined policy). IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(5, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(20, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(40, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(80, time); iwlanError = buildIwlanIkeProtocolError(9002); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(5, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(20, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(40, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(80, time); iwlanError = buildIwlanIkeInternalAddressFailure(); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); } @Test public void testChoosingFallbackPolicy() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("*")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); mErrorPolicyManager.logErrorPolicies(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4, 8, 16 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(4, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(8, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(16, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(86400, time); // IKE_PROTOCOL_ERROR_TYPE(44) and retryArray = 0 as it will fallback to // IKE_PROTOCOL_ERROR_TYPE generic fallback first. iwlanError = buildIwlanIkeChildSaNotFoundError(); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(86400, time); } @Test public void testNullCarrierConfig() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24")) .setRetryArray(List.of("100")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mCarrierId = 1; mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retry time = 100. IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(100, time); IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, null); mCarrierId = 2; mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24). Fall back to default error policy, retry time = 5. time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(5, time); } @Test public void testGetLastError() { String apn1 = "ims"; String apn2 = "mms"; String config = "[{" + "\"ApnName\": \"" + apn1 + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("*")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_DISABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); IwlanError iwlanAuthError = buildIwlanIkeAuthFailedError(); mErrorPolicyManager.reportIwlanError(apn1, iwlanAuthError); assertEquals(iwlanAuthError, mErrorPolicyManager.getLastError(apn1)); assertEquals(new IwlanError(IwlanError.NO_ERROR), mErrorPolicyManager.getLastError(apn2)); mErrorPolicyManager.reportIwlanError(apn2, iwlanAuthError); assertEquals(iwlanAuthError, mErrorPolicyManager.getLastError(apn1)); assertEquals(iwlanAuthError, mErrorPolicyManager.getLastError(apn2)); IwlanError iwlanInternalAddressFailure = buildIwlanIkeInternalAddressFailure(); mErrorPolicyManager.reportIwlanError(apn1, iwlanInternalAddressFailure); assertEquals(iwlanInternalAddressFailure, mErrorPolicyManager.getLastError(apn1)); assertEquals(iwlanAuthError, mErrorPolicyManager.getLastError(apn2)); // After APM enable, apn2 should have no last error and apn1 should keep last error // Because apn1 protocol error config have no APM_ENABLE_EVENT in unthrottling events mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.APM_ENABLE_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); assertEquals(iwlanInternalAddressFailure, mErrorPolicyManager.getLastError(apn1)); assertEquals(new IwlanError(IwlanError.NO_ERROR), mErrorPolicyManager.getLastError(apn2)); // After CarrierConfigChanged, all last error should be cleared IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mCarrierId = 2; mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); assertEquals(new IwlanError(IwlanError.NO_ERROR), mErrorPolicyManager.getLastError(apn1)); assertEquals(new IwlanError(IwlanError.NO_ERROR), mErrorPolicyManager.getLastError(apn2)); } @Test public void testCanBringUpTunnel() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(4, time); boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertFalse(bringUpTunnel); advanceClockByTimeMs(4000); bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertTrue(bringUpTunnel); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(8, time); bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertFalse(bringUpTunnel); } @Test public void testNoErrorScenario() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(4, time); // report no error iwlanError = new IwlanError(IwlanError.NO_ERROR); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(-1, time); // Check whether the error is cleared after NO_ERROR is reported boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertTrue(bringUpTunnel); } @Test public void testWifiDisableUnthrottle() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("6", "12", "24")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_DISABLE_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 6, 12, 24 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(6, time); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.WIFI_DISABLE_EVENT) .sendToTarget(); advanceClockByTimeMs(500); verify(mMockDataServiceProvider).notifyApnUnthrottled(eq(apn)); boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertTrue(bringUpTunnel); iwlanError = buildIwlanIkeAuthFailedError(); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(6, time); } @Test public void testWFCDisableUnthrottle() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("6", "12", "24")) .setUnthrottlingEvents( List.of("WIFI_CALLING_DISABLE_EVENT", "WIFI_DISABLE_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 6, 12, 24 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(6, time); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.WIFI_CALLING_DISABLE_EVENT) .sendToTarget(); advanceClockByTimeMs(500); verify(mMockDataServiceProvider).notifyApnUnthrottled(eq(apn)); boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertTrue(bringUpTunnel); iwlanError = buildIwlanIkeAuthFailedError(); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(6, time); } @Test public void testAPMUnthrottle() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(4, time); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.APM_ENABLE_EVENT) .sendToTarget(); advanceClockByTimeMs(500); verify(mMockDataServiceProvider).notifyApnUnthrottled(eq(apn)); boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertTrue(bringUpTunnel); iwlanError = buildIwlanIkeAuthFailedError(); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(4, time); } @Test public void testWifiApChangedUnthrottle() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("6", "12", "24")) .setUnthrottlingEvents( List.of( "WIFI_CALLING_DISABLE_EVENT", "WIFI_DISABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 6, 12, 24 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(6, time); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.WIFI_AP_CHANGED_EVENT) .sendToTarget(); advanceClockByTimeMs(500); verify(mMockDataServiceProvider).notifyApnUnthrottled(eq(apn)); boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertTrue(bringUpTunnel); iwlanError = buildIwlanIkeAuthFailedError(); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(6, time); } @Test public void testGetDataFailCauseRetryTime() throws Exception { String apn1 = "ims"; String apn2 = "mms"; String config = "[{" + "\"ApnName\": \"" + apn1 + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn1, iwlanError); assertEquals(4, time); iwlanError = buildIwlanIkeProtocolError( 8192 /*PDN_CONNECTION_REJECTION*/, new byte[] {0x00, 0x01}); time = mErrorPolicyManager.reportIwlanError(apn2, iwlanError); assertEquals(5, time); int failCause = mErrorPolicyManager.getDataFailCause(apn1); assertEquals(DataFailCause.IWLAN_IKEV2_AUTH_FAILURE, failCause); failCause = mErrorPolicyManager.getDataFailCause(apn2); assertEquals(DataFailCause.IWLAN_PDN_CONNECTION_REJECTION, failCause); assertEquals(Duration.ofSeconds(4), mErrorPolicyManager.getRemainingBackoffDuration(apn1)); assertEquals(Duration.ofSeconds(5), mErrorPolicyManager.getRemainingBackoffDuration(apn2)); } @Test public void testBackOffTime() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("10", "15", "20")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); mErrorPolicyManager.reportIwlanError(apn, iwlanError, 2); assertEquals(Duration.ofSeconds(2), mErrorPolicyManager.getRemainingBackoffDuration(apn)); // advanceClockByTimeMs for 2 seconds and make sure that we can bring up tunnel after 2 secs // as back off time - 2 secs should override the retry time in policy - 10 secs advanceClockByTimeMs(2000); boolean bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertTrue(bringUpTunnel); // test whether the same error reported later uses the right policy long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); bringUpTunnel = mErrorPolicyManager.canBringUpTunnel(apn); assertFalse(bringUpTunnel); mErrorPolicyManager.reportIwlanError(apn, iwlanError, 5); assertEquals(Duration.ofSeconds(5), mErrorPolicyManager.getRemainingBackoffDuration(apn)); // test whether the same error reported later starts from the beginning of retry array time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(10, time); // retry time should be -1 when no error time = mErrorPolicyManager.reportIwlanError(apn, new IwlanError(IwlanError.NO_ERROR), 5); assertEquals(time, -1); } @Test public void testErrorPolicyWithNumAttemptsPerFqdn() throws Exception { // ErrorPolicyManager#getCurrentFqdnIndex() is tested when the ErrorType // parameter "NumAttemptsPerFqdn" is configured. String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("15500")) /* CONGESTION */ .setRetryArray( List.of( "0", "0", "300", "600", "1200", "0", "0", "0", "300", "600", "1200", "-1")) .setUnthrottlingEvents( List.of( "APM_ENABLE_EVENT", "WIFI_DISABLE_EVENT", "WIFI_CALLING_DISABLE_EVENT")) .setNumAttemptsPerFqdn("6") .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); assertEquals(DataFailCause.NONE, mErrorPolicyManager.getMostRecentDataFailCause()); // IKE_PROTOCOL_ERROR_TYPE(15500) // UE constructs 2 PLMN FQDNs. IwlanError iwlanError = buildIwlanIkeProtocolError(15500 /* CONGESTION */); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); assertEquals( DataFailCause.IWLAN_CONGESTION, mErrorPolicyManager.getMostRecentDataFailCause()); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(300, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(600, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(1200, time); assertEquals(0, mErrorPolicyManager.getCurrentFqdnIndex(2)); // Cycles to next FQDN time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); assertEquals(1, mErrorPolicyManager.getCurrentFqdnIndex(2)); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); assertEquals(1, mErrorPolicyManager.getCurrentFqdnIndex(2)); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(300, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(600, time); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(1200, time); // Steady state retry duration, cycles back to 1st FQDN. time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(1200, time); assertEquals(0, mErrorPolicyManager.getCurrentFqdnIndex(2)); } @Test public void testShouldRetryWithInitialAttach() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .setHandoverAttemptCount("2") .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // IKE_PROTOCOL_ERROR_TYPE(24) and retryArray = 4,8,16 IwlanError iwlanError = buildIwlanIkeAuthFailedError(); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(4, time); assertFalse(mErrorPolicyManager.shouldRetryWithInitialAttach(apn)); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(8, time); // Reached handover attempt count and error is IKE protocol error assertTrue(mErrorPolicyManager.shouldRetryWithInitialAttach(apn)); } @Test public void testShouldRetryWithInitialAttachForInternalError() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("IKE_PROTOCOL_ERROR_TYPE") .setErrorDetails(List.of("24", "34")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .setHandoverAttemptCount("2") .build() .getErrorPolicyInString() + "}, {" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("SERVER_SELECTION_FAILED")) .setRetryArray(List.of("0", "0")) .setUnthrottlingEvents(List.of("APM_ENABLE_EVENT")) .build() .getErrorPolicyInString() + "}]" + "}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, config); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // GENERIC_PROTOCOL_ERROR_TYPE - SERVER_SELECTION_FAILED and retryArray = 0, 0 IwlanError iwlanError = new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED); long time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); assertFalse(mErrorPolicyManager.shouldRetryWithInitialAttach(apn)); time = mErrorPolicyManager.reportIwlanError(apn, iwlanError); assertEquals(0, time); // Should not retry with initial attach as the errors are not IKE_PROTOCOL_ERROR_TYPE assertFalse(mErrorPolicyManager.shouldRetryWithInitialAttach(apn)); } @Test public void testHandoverAttemptCountInvalidErrorType() throws Exception { String apn = "ims"; String config = "[{" + "\"ApnName\": \"" + apn + "\"," + "\"ErrorTypes\": [{" + ErrorPolicyString.builder() .setErrorType("GENERIC_ERROR_TYPE") .setErrorDetails(List.of("*")) .setRetryArray(List.of("4", "8", "16")) .setUnthrottlingEvents( List.of("APM_ENABLE_EVENT", "WIFI_AP_CHANGED_EVENT")) .setHandoverAttemptCount("2") .build() .getErrorPolicyInString() + "}]" + "}]"; assertThrows( IllegalArgumentException.class, () -> mErrorPolicyManager.readErrorPolicies(new JSONArray(config))); } @Test public void testErrorStats() throws Exception { String apn1 = "ims"; String apn2 = "mms"; IwlanError iwlanError1 = buildIwlanIkeAuthFailedError(); long ikeAuthCountApn1 = 4L; long ikeAuthCountApn2 = 5L; for (int i = 0; i < ikeAuthCountApn1; i++) { mErrorPolicyManager.reportIwlanError(apn1, iwlanError1); } for (int i = 0; i < ikeAuthCountApn2; i++) { mErrorPolicyManager.reportIwlanError(apn2, iwlanError1); } long serverSelectionCountApn1 = 3L; long serverSelectionCountApn2 = 6L; IwlanError iwlanError2 = new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED); for (int i = 0; i < serverSelectionCountApn1; i++) { mErrorPolicyManager.reportIwlanError(apn1, iwlanError2); } // calling backoff timer api for (int i = 0; i < serverSelectionCountApn2; i++) { mErrorPolicyManager.reportIwlanError(apn2, iwlanError2, 3); } Map apn1Stats = mErrorPolicyManager.getErrorStats().mStats.get(apn1); Map apn2Stats = mErrorPolicyManager.getErrorStats().mStats.get(apn2); long resultAuthApn1 = apn1Stats.get(iwlanError1.toString()); long resultAuthApn2 = apn2Stats.get(iwlanError1.toString()); long resultServerApn1 = apn1Stats.get(iwlanError2.toString()); long resultServerApn2 = apn2Stats.get(iwlanError2.toString()); assertEquals(resultAuthApn1, ikeAuthCountApn1); assertEquals(resultAuthApn2, ikeAuthCountApn2); assertEquals(resultServerApn1, serverSelectionCountApn1); assertEquals(resultServerApn2, serverSelectionCountApn2); } @Test public void testGetLastRetryIndex() { String apn = "ims"; mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // error count should be 0 when no error yet assertEquals(0, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); // same error reported, should accumulate IwlanError iwlanAuthError = buildIwlanIkeAuthFailedError(); mErrorPolicyManager.reportIwlanError(apn, iwlanAuthError); assertEquals(1, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); mErrorPolicyManager.reportIwlanError(apn, iwlanAuthError); assertEquals(2, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); mErrorPolicyManager.reportIwlanError(apn, iwlanAuthError); assertEquals(3, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); // different error reported, should start with 1 then accumulate IwlanError iwlanOtherProtocolError = buildIwlanIkeProtocolError(9002); mErrorPolicyManager.reportIwlanError(apn, iwlanOtherProtocolError); assertEquals(1, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); mErrorPolicyManager.reportIwlanError(apn, iwlanOtherProtocolError); assertEquals(2, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); // different error with specific backoff time reported, should start with 1 then accumulate IwlanError iwlanInternalAddressFailure = buildIwlanIkeInternalAddressFailure(); mErrorPolicyManager.reportIwlanError(apn, iwlanInternalAddressFailure, 5); assertEquals(1, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); mErrorPolicyManager.reportIwlanError(apn, iwlanInternalAddressFailure, 5); assertEquals(2, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); // same error with specific backoff time, should continue from last error count (2) mErrorPolicyManager.reportIwlanError(apn, iwlanOtherProtocolError, 5); assertEquals(3, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); // error without backoff time again, should continue from last error count (3) mErrorPolicyManager.reportIwlanError(apn, iwlanOtherProtocolError); assertEquals(4, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); // the retry index from iwlan auth error should be reserved mErrorPolicyManager.reportIwlanError(apn, iwlanAuthError); assertEquals(4, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); // Unthrottle event should reset the error count mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.APM_ENABLE_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); assertEquals(0, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); mErrorPolicyManager.reportIwlanError(apn, iwlanAuthError); assertEquals(1, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); mErrorPolicyManager.reportIwlanError(apn, iwlanOtherProtocolError, 5); assertEquals(1, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); mErrorPolicyManager.reportIwlanError(apn, new IwlanError(IwlanError.NO_ERROR)); // NO_ERROR should reset the error count assertEquals(0, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); mErrorPolicyManager.reportIwlanError(apn, iwlanAuthError); assertEquals(1, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); mErrorPolicyManager.reportIwlanError(apn, iwlanOtherProtocolError, 5); assertEquals(1, mErrorPolicyManager.getLastErrorCountOfSameCause(apn)); } private void advanceClockByTimeMs(long time) { mMockedClockTime += time; mTestLooper.dispatchAll(); } @Test public void testShouldNotThrowWhenDefaultConfigInvalid() throws Exception { String apn = "ims"; AssetManager mockAssetManager = mock(AssetManager.class); doReturn(mockAssetManager).when(mMockContext).getAssets(); // when the default config do not match all error with "ErrorType": "*" String defaultConfigErrorTypeJson = "{\"ErrorType\": \"IKE_PROTOCOL_ERROR_TYPE\", \"ErrorDetails\": [\"*\"], " + "\"RetryArray\": [\"0\"], \"UnthrottlingEvents\": []}"; String defaultConfigJson = "[{\"ApnName\": \"*\", \"ErrorTypes\": [" + defaultConfigErrorTypeJson + "]}]"; IwlanCarrierConfig.putTestConfigString( IwlanCarrierConfig.KEY_ERROR_POLICY_CONFIG_STRING, defaultConfigJson); // need to reconstruct error policy manager with the mocked default config mErrorPolicyManager.releaseInstance(); mErrorPolicyManager = spy(ErrorPolicyManager.getInstance(mMockContext, DEFAULT_SLOT_INDEX)); doReturn(mTestLooper.getLooper()).when(mErrorPolicyManager).getLooper(); mErrorPolicyManager.initHandler(); mErrorPolicyManager .mHandler .obtainMessage(IwlanEventListener.CARRIER_CONFIG_CHANGED_EVENT) .sendToTarget(); mTestLooper.dispatchAll(); // if some error happen and no policy in carrier config match, and the default config do // not have at least 1 policy can apply to all error, it should not throw error IwlanError iwlanError = new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED); mErrorPolicyManager.reportIwlanError(apn, iwlanError); } }