Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3f8306b8 authored by Erik Kline's avatar Erik Kline
Browse files

Add static IpClient logging

Support keeping IpClient logs around and dumping them
during dumpsys.  Previously we got this benefit for
wifi by virtue of WifiStateMachine's long-lived nature.
Now that this is changing we need to be sure we have
logs, and this method gets us Ethernet logs as well.

Bug: 62476366
Bug: 77999594
Test: as follows
    - built
    - flashed
    - booted
    - runtest frameworks-net passes
    - dumpsys connmetrics [ipclient] works
Change-Id: I1136a83de8097fdb4130debe1eaf689be7132fe5
parent a74dd692
Loading
Loading
Loading
Loading
+4 −10
Original line number Original line Diff line number Diff line
@@ -132,6 +132,7 @@ import com.android.internal.net.NetworkStatsFactory;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnConfig;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnInfo;
import com.android.internal.net.VpnProfile;
import com.android.internal.net.VpnProfile;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.AsyncChannel;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.DumpUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
@@ -1992,13 +1993,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
        return ret;
        return ret;
    }
    }


    private boolean argsContain(String[] args, String target) {
        for (String arg : args) {
            if (target.equals(arg)) return true;
        }
        return false;
    }

    private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
    private void dumpNetworkDiagnostics(IndentingPrintWriter pw) {
        final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
        final List<NetworkDiagnostics> netDiags = new ArrayList<NetworkDiagnostics>();
        final long DIAG_TIME_MS = 5000;
        final long DIAG_TIME_MS = 5000;
@@ -2027,10 +2021,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
        if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
        if (asProto) return;
        if (asProto) return;


        if (argsContain(args, DIAG_ARG)) {
        if (ArrayUtils.contains(args, DIAG_ARG)) {
            dumpNetworkDiagnostics(pw);
            dumpNetworkDiagnostics(pw);
            return;
            return;
        } else if (argsContain(args, TETHERING_ARG)) {
        } else if (ArrayUtils.contains(args, TETHERING_ARG)) {
            mTethering.dump(fd, pw, args);
            mTethering.dump(fd, pw, args);
            return;
            return;
        }
        }
@@ -2098,7 +2092,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
        pw.println();
        pw.println();
        mMultipathPolicyTracker.dump(pw);
        mMultipathPolicyTracker.dump(pw);


        if (argsContain(args, SHORT_ARG) == false) {
        if (ArrayUtils.contains(args, SHORT_ARG) == false) {
            pw.println();
            pw.println();
            synchronized (mValidationLogs) {
            synchronized (mValidationLogs) {
                pw.println("mValidationLogs (most recent first):");
                pw.println("mValidationLogs (most recent first):");
+19 −5
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context;
import android.net.ConnectivityMetricsEvent;
import android.net.ConnectivityMetricsEvent;
import android.net.IIpConnectivityMetrics;
import android.net.IIpConnectivityMetrics;
import android.net.INetdEventCallback;
import android.net.INetdEventCallback;
import android.net.ip.IpClient;
import android.net.metrics.ApfProgramEvent;
import android.net.metrics.ApfProgramEvent;
import android.net.metrics.IpConnectivityLog;
import android.net.metrics.IpConnectivityLog;
import android.os.Binder;
import android.os.Binder;
@@ -269,10 +270,12 @@ final public class IpConnectivityMetrics extends SystemService {
        // Dump the rolling buffer of metrics event and pretty print events using a human readable
        // Dump the rolling buffer of metrics event and pretty print events using a human readable
        // format. Also print network dns/connect statistics and default network event time series.
        // format. Also print network dns/connect statistics and default network event time series.
        static final String CMD_LIST = "list";
        static final String CMD_LIST = "list";
        // By default any other argument will fall into the default case which is remapped to the
        // Dump all IpClient logs ("ipclient").
        // "list" command. This includes most notably bug reports collected by dumpsys.cpp with
        static final String CMD_IPCLIENT = IpClient.DUMP_ARG;
        // the "-a" argument.
        // By default any other argument will fall into the default case which is the equivalent
        static final String CMD_DEFAULT = CMD_LIST;
        // of calling both the "list" and "ipclient" commands. This includes most notably bug
        // reports collected by dumpsys.cpp with the "-a" argument.
        static final String CMD_DEFAULT = "";


        @Override
        @Override
        public int logEvent(ConnectivityMetricsEvent event) {
        public int logEvent(ConnectivityMetricsEvent event) {
@@ -292,9 +295,20 @@ final public class IpConnectivityMetrics extends SystemService {
                case CMD_PROTO:
                case CMD_PROTO:
                    cmdListAsProto(pw);
                    cmdListAsProto(pw);
                    return;
                    return;
                case CMD_LIST: // fallthrough
                case CMD_IPCLIENT: {
                    final String[] ipclientArgs = ((args != null) && (args.length > 1))
                            ? Arrays.copyOfRange(args, 1, args.length)
                            : null;
                    IpClient.dumpAllLogs(pw, ipclientArgs);
                    return;
                }
                case CMD_LIST:
                    cmdList(pw);
                    return;
                default:
                default:
                    cmdList(pw);
                    cmdList(pw);
                    pw.println("");
                    IpClient.dumpAllLogs(pw, null);
                    return;
                    return;
            }
            }
        }
        }
+36 −2
Original line number Original line Diff line number Diff line
@@ -54,6 +54,7 @@ import android.util.SparseArray;


import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.R;
import com.android.internal.R;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.IState;
import com.android.internal.util.IState;
import com.android.internal.util.Preconditions;
import com.android.internal.util.Preconditions;
@@ -74,6 +75,7 @@ import java.util.Objects;
import java.util.List;
import java.util.List;
import java.util.Set;
import java.util.Set;
import java.util.StringJoiner;
import java.util.StringJoiner;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CountDownLatch;
import java.util.function.Predicate;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Collectors;
@@ -100,6 +102,36 @@ public class IpClient extends StateMachine {
    private static final Class[] sMessageClasses = { IpClient.class, DhcpClient.class };
    private static final Class[] sMessageClasses = { IpClient.class, DhcpClient.class };
    private static final SparseArray<String> sWhatToString =
    private static final SparseArray<String> sWhatToString =
            MessageUtils.findMessageNames(sMessageClasses);
            MessageUtils.findMessageNames(sMessageClasses);
    // Two static concurrent hashmaps of interface name to logging classes.
    // One holds StateMachine logs and the other connectivity packet logs.
    private static final ConcurrentHashMap<String, SharedLog> sSmLogs = new ConcurrentHashMap<>();
    private static final ConcurrentHashMap<String, LocalLog> sPktLogs = new ConcurrentHashMap<>();

    // If |args| is non-empty, assume it's a list of interface names for which
    // we should print IpClient logs (filter out all others).
    public static void dumpAllLogs(PrintWriter writer, String[] args) {
        for (String ifname : sSmLogs.keySet()) {
            if (!ArrayUtils.isEmpty(args) && !ArrayUtils.contains(args, ifname)) continue;

            writer.println(String.format("--- BEGIN %s ---", ifname));

            final SharedLog smLog = sSmLogs.get(ifname);
            if (smLog != null) {
                writer.println("State machine log:");
                smLog.dump(null, writer, null);
            }

            writer.println("");

            final LocalLog pktLog = sPktLogs.get(ifname);
            if (pktLog != null) {
                writer.println("Connectivity packet log:");
                pktLog.readOnlyLocalLog().dump(null, writer, null);
            }

            writer.println(String.format("--- END %s ---", ifname));
        }
    }


    /**
    /**
     * Callbacks for handling IpClient events.
     * Callbacks for handling IpClient events.
@@ -680,8 +712,10 @@ public class IpClient extends StateMachine {
        mShutdownLatch = new CountDownLatch(1);
        mShutdownLatch = new CountDownLatch(1);
        mNwService = deps.getNMS();
        mNwService = deps.getNMS();


        mLog = new SharedLog(MAX_LOG_RECORDS, mTag);
        sSmLogs.putIfAbsent(mInterfaceName, new SharedLog(MAX_LOG_RECORDS, mTag));
        mConnectivityPacketLog = new LocalLog(MAX_PACKET_RECORDS);
        mLog = sSmLogs.get(mInterfaceName);
        sPktLogs.putIfAbsent(mInterfaceName, new LocalLog(MAX_PACKET_RECORDS));
        mConnectivityPacketLog = sPktLogs.get(mInterfaceName);
        mMsgStateLogger = new MessageHandlingLogger();
        mMsgStateLogger = new MessageHandlingLogger();


        // TODO: Consider creating, constructing, and passing in some kind of
        // TODO: Consider creating, constructing, and passing in some kind of