From a967fb8038ff19f45cff2f38741ac5ffc25adc91 Mon Sep 17 00:00:00 2001 From: chiachangwang Date: Mon, 31 Oct 2022 09:43:17 +0000 Subject: [PATCH] Add dump for Vpn Adding additional logging and dump information to help VPN debug. Sample dump result(adb shell dumpsys vpn_management) VPNs: 0: com.vpn.test Active package name: com.vpn.test Active vpn type: 2 NetworkCapabilities: [ Transports: VPN Capabilities: NOT_METERED&INTERNET&NOT_RESTRICTED&TRUSTED&NOT_VCN_MANAGED TransportInfo: Uids: <{0-99999}> OwnerUid: 10106 AdminUids: [10106] UnderlyingNetworks: [107]] Token: 8876c2c4-df5f-46b8-82c7-8f124178254a MOBIKE enabled mUnderlyNetworkChanges (most recent first): 2022-10-31T17:42:31.039068 - Switch to 107 2022-10-31T17:42:29.510574 - Agent connect. Switch to 105 2022-10-31T17:41:57.590691 - Agent connect. Switch to 103 2022-10-31T17:41:31.269923 - Switch to 103 2022-10-31T17:41:20.145050 - Switch to 102 2022-10-31T17:41:14.480618 - Agent connect. Switch to 100 mVpnManagerEvent (most recent first): 2022-10-31T17:42:11.641201 - Event class=ERROR_CLASS_RECOVERABLE, err=ERROR_CODE_NETWORK_LOST for com.vpn.test on session 8876c2c4-df5f-46b8-82c7-8f124178254a 2022-10-31T17:41:34.921219 - com.vpn.test stopped Test: atest FrameworksNetTests Test: adb shell dumpsys vpn_management Bug: 238696406 Change-Id: I05b66ddb4a2b7a73707db39c6b89bf497aed1266 --- .../com/android/server/VpnManagerService.java | 4 + .../com/android/server/connectivity/Vpn.java | 73 ++++++++++++++++++- 2 files changed, 76 insertions(+), 1 deletion(-) diff --git a/services/core/java/com/android/server/VpnManagerService.java b/services/core/java/com/android/server/VpnManagerService.java index 3f1d1feec282c..ae50b23581397 100644 --- a/services/core/java/com/android/server/VpnManagerService.java +++ b/services/core/java/com/android/server/VpnManagerService.java @@ -186,6 +186,10 @@ public class VpnManagerService extends IVpnManager.Stub { synchronized (mVpns) { for (int i = 0; i < mVpns.size(); i++) { pw.println(mVpns.keyAt(i) + ": " + mVpns.valueAt(i).getPackage()); + pw.increaseIndent(); + mVpns.valueAt(i).dump(pw); + pw.decreaseIndent(); + pw.println(); } pw.decreaseIndent(); } diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java index 45b0f0a6d04aa..9985ffecc2abc 100644 --- a/services/core/java/com/android/server/connectivity/Vpn.java +++ b/services/core/java/com/android/server/connectivity/Vpn.java @@ -124,6 +124,8 @@ import android.system.keystore2.KeyDescriptor; import android.system.keystore2.KeyPermission; import android.text.TextUtils; import android.util.ArraySet; +import android.util.IndentingPrintWriter; +import android.util.LocalLog; import android.util.Log; import android.util.Range; @@ -289,6 +291,10 @@ public class Vpn { return mVpnProfileStore; } + private static final int MAX_EVENTS_LOGS = 20; + private final LocalLog mUnderlyNetworkChanges = new LocalLog(MAX_EVENTS_LOGS); + private final LocalLog mVpnManagerEvents = new LocalLog(MAX_EVENTS_LOGS); + /** * Whether to keep the connection active after rebooting, or upgrading or reinstalling. This * only applies to {@link VpnService} connections. @@ -816,6 +822,9 @@ public class Vpn { int errorCode, @NonNull final String packageName, @Nullable final String sessionKey, @NonNull final VpnProfileState profileState, @Nullable final Network underlyingNetwork, @Nullable final NetworkCapabilities nc, @Nullable final LinkProperties lp) { + mVpnManagerEvents.log("Event class=" + getVpnManagerEventClassName(errorClass) + + ", err=" + getVpnManagerEventErrorName(errorCode) + " for " + packageName + + " on session " + sessionKey); final Intent intent = buildVpnManagerEventIntent(category, errorClass, errorCode, packageName, sessionKey, profileState, underlyingNetwork, nc, lp); return sendEventToVpnManagerApp(intent, packageName); @@ -1539,6 +1548,7 @@ public class Vpn { ? Arrays.asList(mConfig.underlyingNetworks) : null); mNetworkCapabilities = capsBuilder.build(); + logUnderlyNetworkChanges(mNetworkCapabilities.getUnderlyingNetworks()); mNetworkAgent = mDeps.newNetworkAgent(mContext, mLooper, NETWORKTYPE /* logtag */, mNetworkCapabilities, lp, new NetworkScore.Builder().setLegacyInt(VPN_DEFAULT_SCORE).build(), @@ -1566,6 +1576,11 @@ public class Vpn { } } + private void logUnderlyNetworkChanges(List networks) { + mUnderlyNetworkChanges.log("Switch to " + + ((networks != null) ? TextUtils.join(", ", networks) : "null")); + } + private void agentDisconnect(NetworkAgent networkAgent) { if (networkAgent != null) { networkAgent.unregister(); @@ -4231,6 +4246,7 @@ public class Vpn { // TODO(b/230548427): Remove SDK check once VPN related stuff are decoupled from // ConnectivityServiceTest. if (SdkLevel.isAtLeastT()) { + mVpnManagerEvents.log(packageName + " stopped"); sendEventToVpnManagerApp(intent, packageName); } } @@ -4398,8 +4414,10 @@ public class Vpn { /** Proxy to allow different testing setups */ // TODO: b/240492694 Remove VpnNetworkAgentWrapper and this method when // NetworkAgent#setUnderlyingNetworks can be un-finalized. - private static void doSetUnderlyingNetworks( + private void doSetUnderlyingNetworks( @NonNull NetworkAgent agent, @NonNull List networks) { + logUnderlyNetworkChanges(networks); + if (agent instanceof VpnNetworkAgentWrapper) { ((VpnNetworkAgentWrapper) agent).doSetUnderlyingNetworks(networks); } else { @@ -4518,4 +4536,57 @@ public class Vpn { static Range createUidRangeForUser(int userId) { return new Range(userId * PER_USER_RANGE, (userId + 1) * PER_USER_RANGE - 1); } + + private String getVpnManagerEventClassName(int code) { + switch (code) { + case VpnManager.ERROR_CLASS_NOT_RECOVERABLE: + return "ERROR_CLASS_NOT_RECOVERABLE"; + case VpnManager.ERROR_CLASS_RECOVERABLE: + return "ERROR_CLASS_RECOVERABLE"; + default: + return "UNKNOWN_CLASS"; + } + } + + private String getVpnManagerEventErrorName(int code) { + switch (code) { + case VpnManager.ERROR_CODE_NETWORK_UNKNOWN_HOST: + return "ERROR_CODE_NETWORK_UNKNOWN_HOST"; + case VpnManager.ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT: + return "ERROR_CODE_NETWORK_PROTOCOL_TIMEOUT"; + case VpnManager.ERROR_CODE_NETWORK_IO: + return "ERROR_CODE_NETWORK_IO"; + case VpnManager.ERROR_CODE_NETWORK_LOST: + return "ERROR_CODE_NETWORK_LOST"; + default: + return "UNKNOWN_ERROR"; + } + } + + /** Dumps VPN state. */ + public void dump(IndentingPrintWriter pw) { + synchronized (Vpn.this) { + pw.println("Active package name: " + mPackage); + pw.println("Active vpn type: " + getActiveVpnType()); + pw.println("NetworkCapabilities: " + mNetworkCapabilities); + if (isIkev2VpnRunner()) { + final IkeV2VpnRunner runner = ((IkeV2VpnRunner) mVpnRunner); + pw.println("Token: " + runner.mSessionKey); + pw.println("MOBIKE " + (runner.mMobikeEnabled ? "enabled" : "disabled")); + if (mDataStallSuspected) pw.println("Data stall suspected"); + if (runner.mScheduledHandleDataStallFuture != null) { + pw.println("Reset session scheduled"); + } + } + pw.println("mUnderlyNetworkChanges (most recent first):"); + pw.increaseIndent(); + mUnderlyNetworkChanges.reverseDump(pw); + pw.decreaseIndent(); + + pw.println("mVpnManagerEvent (most recent first):"); + pw.increaseIndent(); + mVpnManagerEvents.reverseDump(pw); + pw.decreaseIndent(); + } + } }