Merge tag 'android-13.0.0_r52' into int/13/fp3
Android 13.0.0 Release 52 (TQ3A.230605.012)
* tag 'android-13.0.0_r52':
Split iwlan error classname and first line of stacktrace in metrics
Add iwlan error classname and first line of stacktrace in metrics
Add control for enable/disable N1_MODE_CAPABILITY
Reset the error status once the tunnel is opened
Start the throttling handling only if the tunnel fails to bring up
Change-Id: I0a014189802e2cdc5168b5c2ba4ddf1a0a0a7186
diff --git a/src/com/google/android/iwlan/IwlanDataService.java b/src/com/google/android/iwlan/IwlanDataService.java
index ba00b97..a87d6eb 100644
--- a/src/com/google/android/iwlan/IwlanDataService.java
+++ b/src/com/google/android/iwlan/IwlanDataService.java
@@ -921,6 +921,12 @@
}
@VisibleForTesting
+ @Nullable
+ public MetricsAtom getMetricsAtomByApn(String apnName) {
+ return mMetricsAtomForApn.get(apnName);
+ }
+
+ @VisibleForTesting
public IwlanTunnelCallback getIwlanTunnelCallback() {
return mIwlanTunnelCallback;
}
@@ -1181,6 +1187,9 @@
// Record setup result for the Metrics
metricsAtom.setSetupRequestResult(DataServiceCallback.RESULT_SUCCESS);
metricsAtom.setIwlanError(iwlanError.getErrorType());
+
+ metricsAtom.setIwlanErrorWrappedClassnameAndStack(iwlanError);
+
metricsAtom.setTunnelState(tunnelState.getState());
metricsAtom.setMessageId(
IwlanStatsLog.IWLAN_SETUP_DATA_CALL_RESULT_REPORTED);
diff --git a/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java b/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java
index ca2586f..638b8ba 100644
--- a/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java
+++ b/src/com/google/android/iwlan/epdg/EpdgTunnelManager.java
@@ -1523,6 +1523,8 @@
(int) mEpdgServerSelectionDuration,
(int) mIkeTunnelEstablishmentDuration);
+ reportIwlanError(apnName, new IwlanError(IwlanError.NO_ERROR));
+
setIsEpdgAddressSelected(true);
mValidEpdgInfo.resetIndex();
printRequestQueue("EVENT_CHILD_SESSION_OPENED");
@@ -1563,10 +1565,12 @@
iface.close();
}
- if (tunnelConfig.isBackoffTimeValid()) {
- reportIwlanError(apnName, iwlanError, tunnelConfig.getBackoffTime());
- } else {
- reportIwlanError(apnName, iwlanError);
+ if (!tunnelConfig.hasTunnelOpened()) {
+ if (tunnelConfig.isBackoffTimeValid()) {
+ reportIwlanError(apnName, iwlanError, tunnelConfig.getBackoffTime());
+ } else {
+ reportIwlanError(apnName, iwlanError);
+ }
}
Log.d(TAG, "Tunnel Closed: " + iwlanError);
diff --git a/src/com/google/android/iwlan/proto/MetricsAtom.java b/src/com/google/android/iwlan/proto/MetricsAtom.java
index 33b0fcd..7ecf464 100644
--- a/src/com/google/android/iwlan/proto/MetricsAtom.java
+++ b/src/com/google/android/iwlan/proto/MetricsAtom.java
@@ -16,6 +16,10 @@
package com.google.android.iwlan.proto;
+import android.net.ipsec.ike.exceptions.IkeIOException;
+import android.net.ipsec.ike.exceptions.IkeInternalException;
+
+import com.google.android.iwlan.IwlanError;
import com.google.android.iwlan.IwlanStatsLog;
public class MetricsAtom {
@@ -37,6 +41,8 @@
private int mHandoverFailureMode;
private int mRetryDurationMillis;
private int mWifiSignalValue;
+ private String mIwlanErrorWrappedClassname;
+ private String mIwlanErrorWrappedStackFirstFrame;
public void setMessageId(int messageId) {
this.mMessageId = messageId;
@@ -110,6 +116,36 @@
this.mWifiSignalValue = wifiSignalValue;
}
+ public void setIwlanErrorWrappedClassnameAndStack(IwlanError iwlanError) {
+ Throwable iwlanErrorWrapped = iwlanError.getException();
+ if (iwlanErrorWrapped instanceof IkeInternalException
+ || iwlanErrorWrapped instanceof IkeIOException) {
+ iwlanErrorWrapped = iwlanErrorWrapped.getCause();
+ }
+
+ if (iwlanErrorWrapped == null) {
+ this.mIwlanErrorWrappedClassname = null;
+ this.mIwlanErrorWrappedStackFirstFrame = null;
+ return;
+ }
+
+ this.mIwlanErrorWrappedClassname = iwlanErrorWrapped.getClass().getCanonicalName();
+
+ StackTraceElement[] iwlanErrorWrappedStackTraceElements = iwlanErrorWrapped.getStackTrace();
+ this.mIwlanErrorWrappedStackFirstFrame =
+ iwlanErrorWrappedStackTraceElements.length != 0
+ ? iwlanErrorWrappedStackTraceElements[0].toString()
+ : null;
+ }
+
+ public String getIwlanErrorWrappedClassname() {
+ return mIwlanErrorWrappedClassname;
+ }
+
+ public String getIwlanErrorWrappedStackFirstFrame() {
+ return mIwlanErrorWrappedStackFirstFrame;
+ }
+
public void sendMetricsData() {
if (mMessageId == IwlanStatsLog.IWLAN_SETUP_DATA_CALL_RESULT_REPORTED) {
IwlanStatsLog.write(
@@ -129,7 +165,9 @@
mIkeTunnelEstablishmentDurationMillis,
mTunnelState,
mHandoverFailureMode,
- mRetryDurationMillis);
+ mRetryDurationMillis,
+ mIwlanErrorWrappedClassname,
+ mIwlanErrorWrappedStackFirstFrame);
return;
} else if (mMessageId == IwlanStatsLog.IWLAN_PDN_DISCONNECTED_REASON_REPORTED) {
IwlanStatsLog.write(
diff --git a/test/com/google/android/iwlan/IwlanDataServiceTest.java b/test/com/google/android/iwlan/IwlanDataServiceTest.java
index f67b384..ee416d4 100644
--- a/test/com/google/android/iwlan/IwlanDataServiceTest.java
+++ b/test/com/google/android/iwlan/IwlanDataServiceTest.java
@@ -31,6 +31,7 @@
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.net.ipsec.ike.exceptions.IkeInternalException;
import android.os.test.TestLooper;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.DataFailCause;
@@ -56,6 +57,7 @@
import com.google.android.iwlan.epdg.TunnelLinkProperties;
import com.google.android.iwlan.epdg.TunnelLinkPropertiesTest;
import com.google.android.iwlan.epdg.TunnelSetupRequest;
+import com.google.android.iwlan.proto.MetricsAtom;
import org.junit.After;
import org.junit.Before;
@@ -938,6 +940,114 @@
mTestLooper.dispatchAll();
}
+ @Test
+ public void testMetricsWhenTunnelClosedWithWrappedException() {
+ DataProfile dp = buildDataProfile();
+
+ mSpyIwlanDataServiceProvider.setTunnelState(
+ dp,
+ mMockDataServiceCallback,
+ TunnelState.TUNNEL_IN_BRINGUP,
+ null, /* linkProperties */
+ false /* isHandover */,
+ 1 /* pduSessionId */);
+
+ mSpyIwlanDataServiceProvider.setMetricsAtom(
+ TEST_APN_NAME,
+ 64, // type IMS
+ true,
+ 13, // LTE
+ false,
+ true,
+ 1 // Transport Wi-Fi
+ );
+
+ MetricsAtom metricsAtom = mSpyIwlanDataServiceProvider.getMetricsAtomByApn(TEST_APN_NAME);
+ assertNotNull(metricsAtom);
+
+ String exceptionMessage = "Some exception message";
+ Exception mockException = spy(new IllegalStateException(exceptionMessage));
+ String firstDeclaringClassName = "test.test.TestClass";
+ String firstMethodName = "someMethod";
+ String firstFileName = "TestClass.java";
+ int firstLineNumber = 12345;
+ StackTraceElement[] stackTraceElements = {
+ new StackTraceElement(
+ firstDeclaringClassName, firstMethodName, firstFileName, firstLineNumber),
+ new StackTraceElement("test", "test", "test.java", 123)
+ };
+ doReturn(stackTraceElements).when(mockException).getStackTrace();
+
+ when(ErrorPolicyManager.getInstance(eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
+ .thenReturn(mMockErrorPolicyManager);
+ when(mMockErrorPolicyManager.getDataFailCause(eq(TEST_APN_NAME)))
+ .thenReturn(DataFailCause.ERROR_UNSPECIFIED);
+
+ mSpyIwlanDataServiceProvider
+ .getIwlanTunnelCallback()
+ .onClosed(TEST_APN_NAME, new IwlanError(new IkeInternalException(mockException)));
+
+ mTestLooper.dispatchAll();
+
+ var expectedStackFirstFrame =
+ firstDeclaringClassName
+ + "."
+ + firstMethodName
+ + "("
+ + firstFileName
+ + ":"
+ + firstLineNumber
+ + ")";
+
+ assertEquals(
+ mockException.getClass().getCanonicalName(),
+ metricsAtom.getIwlanErrorWrappedClassname());
+
+ assertEquals(expectedStackFirstFrame, metricsAtom.getIwlanErrorWrappedStackFirstFrame());
+ }
+
+ @Test
+ public void testMetricsWhenTunnelClosedWithoutWrappedException() {
+ DataProfile dp = buildDataProfile();
+
+ mSpyIwlanDataServiceProvider.setTunnelState(
+ dp,
+ mMockDataServiceCallback,
+ TunnelState.TUNNEL_IN_BRINGUP,
+ null, /* linkProperties */
+ false /* isHandover */,
+ 1 /* pduSessionId */);
+
+ mSpyIwlanDataServiceProvider.setMetricsAtom(
+ TEST_APN_NAME,
+ 64, // type IMS
+ true,
+ 13, // LTE
+ false,
+ true,
+ 1 // Transport Wi-Fi
+ );
+
+ MetricsAtom metricsAtom = mSpyIwlanDataServiceProvider.getMetricsAtomByApn(TEST_APN_NAME);
+ assertNotNull(metricsAtom);
+
+ when(ErrorPolicyManager.getInstance(eq(mMockContext), eq(DEFAULT_SLOT_INDEX)))
+ .thenReturn(mMockErrorPolicyManager);
+ when(mMockErrorPolicyManager.getDataFailCause(eq(TEST_APN_NAME)))
+ .thenReturn(DataFailCause.ERROR_UNSPECIFIED);
+
+ mSpyIwlanDataServiceProvider
+ .getIwlanTunnelCallback()
+ .onClosed(
+ TEST_APN_NAME,
+ new IwlanError(IwlanError.EPDG_SELECTOR_SERVER_SELECTION_FAILED));
+
+ mTestLooper.dispatchAll();
+
+ assertEquals(null, metricsAtom.getIwlanErrorWrappedClassname());
+ assertEquals(null, metricsAtom.getIwlanErrorWrappedStackFirstFrame());
+ }
+
private void mockTunnelSetupFail(DataProfile dp) {
mSpyIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
diff --git a/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java b/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java
index 4297dbf..3d16135 100644
--- a/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java
+++ b/test/com/google/android/iwlan/epdg/EpdgTunnelManagerTest.java
@@ -536,7 +536,7 @@
final String secondApnName = "mms";
IkeSessionArgumentCaptors firstTunnelArgumentCaptors =
- verifyBringUpTunnelWithDnsQuery(firstApnName, null);
+ verifyBringUpTunnelWithDnsQuery(firstApnName);
ChildSessionCallback firstCallback =
firstTunnelArgumentCaptors.mChildSessionCallbackCaptor.getValue();
@@ -1215,6 +1215,10 @@
mEpdgTunnelManager.setIsEpdgAddressSelected(true);
}
+ private IkeSessionArgumentCaptors verifyBringUpTunnelWithDnsQuery(String apnName) {
+ return verifyBringUpTunnelWithDnsQuery(apnName, null);
+ }
+
private IkeSessionArgumentCaptors verifyBringUpTunnelWithDnsQuery(
String apnName, IkeSession ikeSession) {
reset(mMockIwlanTunnelCallback);
@@ -1286,6 +1290,9 @@
}
private void verifyTunnelOnOpened(String apnName, ChildSessionCallback childSessionCallback) {
+ doReturn(0L)
+ .when(mEpdgTunnelManager)
+ .reportIwlanError(eq(apnName), eq(new IwlanError(IwlanError.NO_ERROR)));
mEpdgTunnelManager
.getTmIkeSessionCallback(apnName, mEpdgTunnelManager.getCurrentTokenForApn(apnName))
.onOpened(mMockIkeSessionConfiguration);
@@ -1299,6 +1306,8 @@
childSessionCallback.onOpened(mMockChildSessionConfiguration);
mTestLooper.dispatchAll();
+ verify(mEpdgTunnelManager, times(1))
+ .reportIwlanError(eq(apnName), eq(new IwlanError(IwlanError.NO_ERROR)));
verify(mMockIwlanTunnelCallback, times(1)).onOpened(eq(apnName), any());
}
@@ -1322,7 +1331,7 @@
final String secondApnName = "mms";
IkeSessionArgumentCaptors firstTunnelArgumentCaptors =
- verifyBringUpTunnelWithDnsQuery(firstApnName, null);
+ verifyBringUpTunnelWithDnsQuery(firstApnName);
ChildSessionCallback firstCallback =
firstTunnelArgumentCaptors.mChildSessionCallbackCaptor.getValue();
@@ -1703,6 +1712,29 @@
}
@Test
+ public void testNeverReportIwlanErrorWhenCloseAnOpenedTunnel() throws Exception {
+ IkeInternalException ikeException =
+ new IkeInternalException(new IOException("Retransmitting failure"));
+
+ IkeSessionArgumentCaptors ikeSessionArgumentCaptors =
+ verifyBringUpTunnelWithDnsQuery(TEST_APN_NAME);
+
+ ChildSessionCallback childSessionCallback =
+ ikeSessionArgumentCaptors.mChildSessionCallbackCaptor.getValue();
+ verifyTunnelOnOpened(TEST_APN_NAME, childSessionCallback);
+
+ reset(mEpdgTunnelManager); // reset number of times of reportIwlanError()
+
+ mEpdgTunnelManager
+ .getTmIkeSessionCallback(TEST_APN_NAME, 0)
+ .onClosedExceptionally(ikeException);
+ mTestLooper.dispatchAll();
+ verify(mEpdgTunnelManager, never()).reportIwlanError(eq(TEST_APN_NAME), any());
+ verify(mMockIwlanTunnelCallback, times(1))
+ .onClosed(eq(TEST_APN_NAME), eq(new IwlanError(ikeException)));
+ }
+
+ @Test
public void testCanBringUpTunnel() throws Exception {
String testApnName = "www.xyz.com";
IwlanError error = new IwlanError(mMockIkeException);