1a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle/*
2a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle * Copyright (C) 2010 The Android Open Source Project
3a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle *
4a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle * Licensed under the Apache License, Version 2.0 (the "License");
5a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle * you may not use this file except in compliance with the License.
6a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle * You may obtain a copy of the License at
7a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle *
8a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle *      http://www.apache.org/licenses/LICENSE-2.0
9a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle *
10a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle * Unless required by applicable law or agreed to in writing, software
11a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle * distributed under the License is distributed on an "AS IS" BASIS,
12a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle * See the License for the specific language governing permissions and
14a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle * limitations under the License.
15a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle */
16a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
17a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwallepackage com.android.server.wifi;
18a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
19d3be501437efd5f176e7541cace20b8db467eb47Roshan Piusimport android.annotation.NonNull;
20eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawalimport android.content.Context;
210bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpandeimport android.util.Base64;
22a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
23eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawalimport com.android.internal.R;
24f46c533931224296b11d98798344c049f88db9a1mukesh agrawalimport com.android.internal.annotations.VisibleForTesting;
25b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawalimport com.android.server.wifi.util.ByteArrayRingBuffer;
26d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawalimport com.android.server.wifi.util.StringUtil;
27b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal
287e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpandeimport java.io.BufferedReader;
290bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpandeimport java.io.ByteArrayOutputStream;
30a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalleimport java.io.FileDescriptor;
310bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpandeimport java.io.IOException;
327e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpandeimport java.io.InputStreamReader;
33a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalleimport java.io.PrintWriter;
34d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawalimport java.nio.charset.Charset;
357e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpandeimport java.util.ArrayList;
360bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpandeimport java.util.Calendar;
37ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawalimport java.util.Collections;
38ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawalimport java.util.Comparator;
390bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpandeimport java.util.HashMap;
400bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpandeimport java.util.zip.Deflater;
41a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
42a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle/**
43d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal * Tracks various logs for framework.
44a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle */
45019fda2109ea79daee3fb4442080b1b83be2e7b3mukesh agrawalclass WifiDiagnostics extends BaseWifiDiagnostics {
46d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal    /**
47d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal     * Thread-safety:
48d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal     * 1) All non-private methods are |synchronized|.
49019fda2109ea79daee3fb4442080b1b83be2e7b3mukesh agrawal     * 2) Callbacks into WifiDiagnostics use non-private (and hence, synchronized) methods. See, e.g,
50d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal     *    onRingBufferData(), onWifiAlert().
51d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal     */
52a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
53019fda2109ea79daee3fb4442080b1b83be2e7b3mukesh agrawal    private static final String TAG = "WifiDiags";
546414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande    private static final boolean DBG = false;
550bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
560bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** log level flags; keep these consistent with wifi_logger.h */
570bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
580bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** No logs whatsoever */
590bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int VERBOSE_NO_LOG = 0;
600bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** No logs whatsoever */
610bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int VERBOSE_NORMAL_LOG = 1;
620bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** Be careful since this one can affect performance and power */
630bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int VERBOSE_LOG_WITH_WAKEUP  = 2;
640bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** Be careful since this one can affect performance and power and memory */
650bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int VERBOSE_DETAILED_LOG_WITH_WAKEUP  = 3;
660bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
670bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** ring buffer flags; keep these consistent with wifi_logger.h */
680bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int RING_BUFFER_FLAG_HAS_BINARY_ENTRIES     = 0x00000001;
690bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int RING_BUFFER_FLAG_HAS_ASCII_ENTRIES      = 0x00000002;
700bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int RING_BUFFER_FLAG_HAS_PER_PACKET_ENTRIES = 0x00000004;
710bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
720bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** various reason codes */
730bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int REPORT_REASON_NONE                      = 0;
740bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int REPORT_REASON_ASSOC_FAILURE             = 1;
750bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int REPORT_REASON_AUTH_FAILURE              = 2;
760bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int REPORT_REASON_AUTOROAM_FAILURE          = 3;
770bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int REPORT_REASON_DHCP_FAILURE              = 4;
780bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int REPORT_REASON_UNEXPECTED_DISCONNECT     = 5;
790bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int REPORT_REASON_SCAN_FAILURE              = 6;
809a41261e4f688411a7038781ca959b2007965f06Vinit Deshpande    public static final int REPORT_REASON_USER_ACTION               = 7;
8126e5eb3545a8d67c66e546f4ce413c0611573cfbRoshan Pius    public static final int REPORT_REASON_WIFINATIVE_FAILURE        = 8;
820bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
830bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** number of bug reports to hold */
840bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int MAX_BUG_REPORTS                         = 4;
850bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
860bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** number of alerts to hold */
870bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public static final int MAX_ALERT_REPORTS                       = 1;
880bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
890bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** minimum wakeup interval for each of the log levels */
900bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private static final int MinWakeupIntervals[] = new int[] { 0, 3600, 60, 10 };
910bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /** minimum buffer size for each of the log levels */
920bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private static final int MinBufferSizes[] = new int[] { 0, 16384, 16384, 65536 };
930bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
94d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal    @VisibleForTesting public static final String FIRMWARE_DUMP_SECTION_HEADER =
95d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal            "FW Memory dump";
96d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal    @VisibleForTesting public static final String DRIVER_DUMP_SECTION_HEADER =
97d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal            "Driver state dump";
98d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal
99eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawal    private final int RING_BUFFER_BYTE_LIMIT_SMALL;
100eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawal    private final int RING_BUFFER_BYTE_LIMIT_LARGE;
1010bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private int mLogLevel = VERBOSE_NO_LOG;
102956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal    private boolean mIsLoggingEventHandlerRegistered;
1030bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private WifiNative.RingBufferStatus[] mRingBuffers;
1040bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private WifiNative.RingBufferStatus mPerPacketRingBuffer;
1058df302f5b9c647f69acee24e09fa20d8b5c54c4amukesh agrawal    private final BuildProperties mBuildProperties;
106d3ab97d3cf26342610204b6492f082d62d3e51e3mukesh agrawal    private final WifiLog mLog;
107d3ab97d3cf26342610204b6492f082d62d3e51e3mukesh agrawal    private final LastMileLogger mLastMileLogger;
1083bbf564af91515b33fcba33e7039ffe09c8c025cmukesh agrawal    private final Runtime mJavaRuntime;
109d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius    private final WifiMetrics mWifiMetrics;
110eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawal    private int mMaxRingBufferSizeBytes;
11181659f852667dc4ff3904fb2f002ab8669b47410xshu    private WifiInjector mWifiInjector;
112eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawal
1135b06b91ac414e5c756e0974063f87e23cce8d68cmukesh agrawal    public WifiDiagnostics(Context context, WifiInjector wifiInjector,
114d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius                           WifiNative wifiNative, BuildProperties buildProperties,
115d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius                           LastMileLogger lastMileLogger) {
116b8b3fb8228a1f90106bad8c59ce006b81ef7921cRoshan Pius        super(wifiNative);
117eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawal        RING_BUFFER_BYTE_LIMIT_SMALL = context.getResources().getInteger(
118eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawal                R.integer.config_wifi_logger_ring_buffer_default_size_limit_kb) * 1024;
119eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawal        RING_BUFFER_BYTE_LIMIT_LARGE = context.getResources().getInteger(
120eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawal                R.integer.config_wifi_logger_ring_buffer_verbose_size_limit_kb) * 1024;
121a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
1228df302f5b9c647f69acee24e09fa20d8b5c54c4amukesh agrawal        mBuildProperties = buildProperties;
123956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal        mIsLoggingEventHandlerRegistered = false;
124eacd212af097fada70bdb49da3ed06e8d172237bmukesh agrawal        mMaxRingBufferSizeBytes = RING_BUFFER_BYTE_LIMIT_SMALL;
12563fad8b4722c94ce9107690b647cdbe7e8a1c4f9mukesh agrawal        mLog = wifiInjector.makeLog(TAG);
126d3ab97d3cf26342610204b6492f082d62d3e51e3mukesh agrawal        mLastMileLogger = lastMileLogger;
1273bbf564af91515b33fcba33e7039ffe09c8c025cmukesh agrawal        mJavaRuntime = wifiInjector.getJavaRuntime();
128d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius        mWifiMetrics = wifiInjector.getWifiMetrics();
12981659f852667dc4ff3904fb2f002ab8669b47410xshu        mWifiInjector = wifiInjector;
130f7db07b9cc88ceef2ca3d77414834d0d75b4ece7Vinit Deshpande    }
13103ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
132e28ce6be22c1389847e77d2be9c8390689cdf395Vinit Deshpande    @Override
1330bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public synchronized void startLogging(boolean verboseEnabled) {
13418786eca942042388748b0d98979f21c9dff4a89Mitchell Wills        mFirmwareVersion = mWifiNative.getFirmwareVersion();
13518786eca942042388748b0d98979f21c9dff4a89Mitchell Wills        mDriverVersion = mWifiNative.getDriverVersion();
13618786eca942042388748b0d98979f21c9dff4a89Mitchell Wills        mSupportedFeatureSet = mWifiNative.getSupportedLoggerFeatureSet();
137a1276378c5a215774193e745568d6dec0d19a722Vinit Deshpande
138956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal        if (!mIsLoggingEventHandlerRegistered) {
139956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal            mIsLoggingEventHandlerRegistered = mWifiNative.setLoggingEventHandler(mHandler);
140956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal        }
141a1276378c5a215774193e745568d6dec0d19a722Vinit Deshpande
1420bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (verboseEnabled) {
1430bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            mLogLevel = VERBOSE_LOG_WITH_WAKEUP;
144d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal            mMaxRingBufferSizeBytes = RING_BUFFER_BYTE_LIMIT_LARGE;
1450bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        } else {
1460bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            mLogLevel = VERBOSE_NORMAL_LOG;
1478df302f5b9c647f69acee24e09fa20d8b5c54c4amukesh agrawal            mMaxRingBufferSizeBytes = enableVerboseLoggingForDogfood()
1488df302f5b9c647f69acee24e09fa20d8b5c54c4amukesh agrawal                    ? RING_BUFFER_BYTE_LIMIT_LARGE : RING_BUFFER_BYTE_LIMIT_SMALL;
1492ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal            clearVerboseLogs();
1500bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
1517e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande
1520bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (mRingBuffers == null) {
1537e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            fetchRingBuffers();
1547e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        }
1557e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande
15628a073ae465df4e92b11bc8c9b3a1890de375d30mukesh agrawal        if (mRingBuffers != null) {
15728a073ae465df4e92b11bc8c9b3a1890de375d30mukesh agrawal            /* log level may have changed, so restart logging with new levels */
1587e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            stopLoggingAllBuffers();
159d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal            resizeRingBuffers();
1607e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            startLoggingAllExceptPerPacketBuffers();
16103ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe        }
162ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
16352ed1731664f7e0b76adb14eec7a76eaa95144c3Roshan Pius        if (!mWifiNative.startPktFateMonitoring(mWifiNative.getClientInterfaceName())) {
164f5d90be206db98bbd5894afc8d757dd32360b2d9mukesh agrawal            mLog.wC("Failed to start packet fate monitoring");
165ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        }
16603ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe    }
16703ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
168e28ce6be22c1389847e77d2be9c8390689cdf395Vinit Deshpande    @Override
1690bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public synchronized void startPacketLog() {
1700bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (mPerPacketRingBuffer != null) {
1710bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            startLoggingRingBuffer(mPerPacketRingBuffer);
172a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle        } else {
173f5d90be206db98bbd5894afc8d757dd32360b2d9mukesh agrawal            if (DBG) mLog.tC("There is no per packet ring buffer");
174a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle        }
175a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle    }
176a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
177e28ce6be22c1389847e77d2be9c8390689cdf395Vinit Deshpande    @Override
1780bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public synchronized void stopPacketLog() {
1790bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (mPerPacketRingBuffer != null) {
1800bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            stopLoggingRingBuffer(mPerPacketRingBuffer);
1810bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        } else {
182f5d90be206db98bbd5894afc8d757dd32360b2d9mukesh agrawal            if (DBG) mLog.tC("There is no per packet ring buffer");
1830bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
1840bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    }
1850bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
186e28ce6be22c1389847e77d2be9c8390689cdf395Vinit Deshpande    @Override
1870bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public synchronized void stopLogging() {
188956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal        if (mIsLoggingEventHandlerRegistered) {
189956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal            if (!mWifiNative.resetLogHandler()) {
190f5d90be206db98bbd5894afc8d757dd32360b2d9mukesh agrawal                mLog.wC("Fail to reset log handler");
191b797893fc1966803d0c013faac42e6396a37a384xinhe            } else {
192f5d90be206db98bbd5894afc8d757dd32360b2d9mukesh agrawal                if (DBG) mLog.tC("Reset log handler");
193b797893fc1966803d0c013faac42e6396a37a384xinhe            }
194956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal            // Clear mIsLoggingEventHandlerRegistered even if resetLogHandler() failed, because
195956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal            // the log handler is in an indeterminate state.
196956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal            mIsLoggingEventHandlerRegistered = false;
197956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal        }
198956fd40b6145c4aba9160e10bfc1ea609873ce8dmukesh agrawal        if (mLogLevel != VERBOSE_NO_LOG) {
199ba5908f65b0470be02ec7b5c035a3aec22eb0c11Vinit Deshpande            stopLoggingAllBuffers();
200ba5908f65b0470be02ec7b5c035a3aec22eb0c11Vinit Deshpande            mRingBuffers = null;
201ba5908f65b0470be02ec7b5c035a3aec22eb0c11Vinit Deshpande            mLogLevel = VERBOSE_NO_LOG;
202ba5908f65b0470be02ec7b5c035a3aec22eb0c11Vinit Deshpande        }
2030bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    }
2040bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
205e28ce6be22c1389847e77d2be9c8390689cdf395Vinit Deshpande    @Override
2063f2187fdcc3ed55c909cb4cdee589744655d3243mukesh agrawal    synchronized void reportConnectionEvent(long connectionId, byte event) {
2073f2187fdcc3ed55c909cb4cdee589744655d3243mukesh agrawal        mLastMileLogger.reportConnectionEvent(connectionId, event);
208d3ab97d3cf26342610204b6492f082d62d3e51e3mukesh agrawal        if (event == CONNECTION_EVENT_FAILED) {
209d3ab97d3cf26342610204b6492f082d62d3e51e3mukesh agrawal            mPacketFatesForLastFailure = fetchPacketFates();
210cf99aa8a53e95f220fa0b627e712b4a4d87b6017mukesh agrawal        }
211ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal    }
212ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
213ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal    @Override
2140bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public synchronized void captureBugReportData(int reason) {
215f8c50b1e8239d843dd01e6dcf956629dad0771c1mukesh agrawal        BugReport report = captureBugreport(reason, isVerboseLoggingEnabled());
2160bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        mLastBugReports.addLast(report);
2170bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    }
2180bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
219e28ce6be22c1389847e77d2be9c8390689cdf395Vinit Deshpande    @Override
2200bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public synchronized void captureAlertData(int errorCode, byte[] alertData) {
221f8c50b1e8239d843dd01e6dcf956629dad0771c1mukesh agrawal        BugReport report = captureBugreport(errorCode, isVerboseLoggingEnabled());
2220bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        report.alertData = alertData;
2230bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        mLastAlerts.addLast(report);
2240bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    }
22503ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
226e28ce6be22c1389847e77d2be9c8390689cdf395Vinit Deshpande    @Override
2270bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    public synchronized void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
228ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        super.dump(pw);
2290bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
2300bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        for (int i = 0; i < mLastAlerts.size(); i++) {
2310bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            pw.println("--------------------------------------------------------------------");
2320bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            pw.println("Alert dump " + i);
2330bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            pw.print(mLastAlerts.get(i));
2340bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            pw.println("--------------------------------------------------------------------");
2350bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
2360bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
2370bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        for (int i = 0; i < mLastBugReports.size(); i++) {
2380bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            pw.println("--------------------------------------------------------------------");
2390bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            pw.println("Bug dump " + i);
2400bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            pw.print(mLastBugReports.get(i));
2410bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            pw.println("--------------------------------------------------------------------");
2420bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
2430bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
244ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        dumpPacketFates(pw);
245d3ab97d3cf26342610204b6492f082d62d3e51e3mukesh agrawal        mLastMileLogger.dump(pw);
246d3ab97d3cf26342610204b6492f082d62d3e51e3mukesh agrawal
2470bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        pw.println("--------------------------------------------------------------------");
2480bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    }
2490bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
25081659f852667dc4ff3904fb2f002ab8669b47410xshu    @Override
25181659f852667dc4ff3904fb2f002ab8669b47410xshu    /**
25281659f852667dc4ff3904fb2f002ab8669b47410xshu     * Initiates a system-level bugreport, in a non-blocking fashion.
25381659f852667dc4ff3904fb2f002ab8669b47410xshu     */
254a5a83f137409921fe95dc01214a0307838b8508cxshu    public void takeBugReport(String bugTitle, String bugDetail) {
25581659f852667dc4ff3904fb2f002ab8669b47410xshu        if (mBuildProperties.isUserBuild()) {
25681659f852667dc4ff3904fb2f002ab8669b47410xshu            return;
25781659f852667dc4ff3904fb2f002ab8669b47410xshu        }
25881659f852667dc4ff3904fb2f002ab8669b47410xshu
25981659f852667dc4ff3904fb2f002ab8669b47410xshu        try {
260a5a83f137409921fe95dc01214a0307838b8508cxshu            mWifiInjector.getActivityManagerService().requestWifiBugReport(
261a5a83f137409921fe95dc01214a0307838b8508cxshu                    bugTitle, bugDetail);
26281659f852667dc4ff3904fb2f002ab8669b47410xshu        } catch (Exception e) {  // diagnostics should never crash system_server
26381659f852667dc4ff3904fb2f002ab8669b47410xshu            mLog.err("error taking bugreport: %").c(e.getClass().getName()).flush();
26481659f852667dc4ff3904fb2f002ab8669b47410xshu        }
26581659f852667dc4ff3904fb2f002ab8669b47410xshu    }
26681659f852667dc4ff3904fb2f002ab8669b47410xshu
2670bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    /* private methods and data */
268b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal    class BugReport {
2696414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande        long systemTimeMs;
2706414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande        long kernelTimeNanos;
2710bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        int errorCode;
2720bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        HashMap<String, byte[][]> ringBuffers = new HashMap();
2730bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        byte[] fwMemoryDump;
274d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal        byte[] mDriverStateDump;
2750bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        byte[] alertData;
2767e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        LimitedCircularArray<String> kernelLogLines;
27737e073350c5e3bdac08d4fa2a0cc9f37190d1173Ningyuan Wang        ArrayList<String> logcatLines;
2780bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
2792ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal        void clearVerboseLogs() {
2802ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal            fwMemoryDump = null;
2812ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal            mDriverStateDump = null;
2822ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal        }
2832ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal
2840bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        public String toString() {
2850bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            StringBuilder builder = new StringBuilder();
2860bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
2870bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            Calendar c = Calendar.getInstance();
2886414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande            c.setTimeInMillis(systemTimeMs);
2896414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande            builder.append("system time = ").append(
2900bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                    String.format("%tm-%td %tH:%tM:%tS.%tL", c, c, c, c, c, c)).append("\n");
2910bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
2926414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande            long kernelTimeMs = kernelTimeNanos/(1000*1000);
2936414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande            builder.append("kernel time = ").append(kernelTimeMs/1000).append(".").append
2946414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande                    (kernelTimeMs%1000).append("\n");
2956414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande
2960bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            if (alertData == null)
2970bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                builder.append("reason = ").append(errorCode).append("\n");
2980bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            else {
2990bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                builder.append("errorCode = ").append(errorCode);
3000bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                builder.append("data \n");
3010bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                builder.append(compressToBase64(alertData)).append("\n");
3020bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            }
3030bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
3047e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            if (kernelLogLines != null) {
3057e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                builder.append("kernel log: \n");
3067e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                for (int i = 0; i < kernelLogLines.size(); i++) {
3077e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                    builder.append(kernelLogLines.get(i)).append("\n");
3087e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                }
3097e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                builder.append("\n");
3107e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            }
3117e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande
3127e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            if (logcatLines != null) {
3137e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                builder.append("system log: \n");
3147e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                for (int i = 0; i < logcatLines.size(); i++) {
3157e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                    builder.append(logcatLines.get(i)).append("\n");
3167e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                }
3177e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                builder.append("\n");
3187e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            }
3197e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande
3200bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            for (HashMap.Entry<String, byte[][]> e : ringBuffers.entrySet()) {
3210bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                String ringName = e.getKey();
3220bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                byte[][] buffers = e.getValue();
3230bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                builder.append("ring-buffer = ").append(ringName).append("\n");
3240bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
3250bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                int size = 0;
3260bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                for (int i = 0; i < buffers.length; i++) {
3270bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                    size += buffers[i].length;
3280bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                }
3290bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
3300bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                byte[] buffer = new byte[size];
3310bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                int index = 0;
3320bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                for (int i = 0; i < buffers.length; i++) {
3330bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                    System.arraycopy(buffers[i], 0, buffer, index, buffers[i].length);
3340bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                    index += buffers[i].length;
3350bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                }
3360bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
3370bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                builder.append(compressToBase64(buffer));
3380bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                builder.append("\n");
3390bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            }
3400bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
3410bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            if (fwMemoryDump != null) {
342d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                builder.append(FIRMWARE_DUMP_SECTION_HEADER);
343d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                builder.append("\n");
3440bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                builder.append(compressToBase64(fwMemoryDump));
345d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                builder.append("\n");
346d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal            }
347d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal
348d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal            if (mDriverStateDump != null) {
349d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                builder.append(DRIVER_DUMP_SECTION_HEADER);
350d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                if (StringUtil.isAsciiPrintable(mDriverStateDump)) {
351d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                    builder.append(" (ascii)\n");
352d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                    builder.append(new String(mDriverStateDump, Charset.forName("US-ASCII")));
353d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                    builder.append("\n");
354d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                } else {
355d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                    builder.append(" (base64)\n");
356d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                    builder.append(compressToBase64(mDriverStateDump));
357d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal                }
3580bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            }
3590bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
3600bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            return builder.toString();
3610bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
3620bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    }
3630bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
364b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal    class LimitedCircularArray<E> {
3657e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        private ArrayList<E> mArrayList;
3660bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        private int mMax;
3670bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        LimitedCircularArray(int max) {
3687e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            mArrayList = new ArrayList<E>(max);
3690bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            mMax = max;
3700bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
37103ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
3720bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        public final void addLast(E e) {
3737e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            if (mArrayList.size() >= mMax)
3747e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                mArrayList.remove(0);
3757e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            mArrayList.add(e);
3760bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
37703ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
3780bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        public final int size() {
3797e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            return mArrayList.size();
380a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle        }
381a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
3820bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        public final E get(int i) {
3837e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            return mArrayList.get(i);
3840bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
38503ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe    }
386a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
3870bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private final LimitedCircularArray<BugReport> mLastAlerts =
3880bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            new LimitedCircularArray<BugReport>(MAX_ALERT_REPORTS);
3890bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private final LimitedCircularArray<BugReport> mLastBugReports =
3900bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            new LimitedCircularArray<BugReport>(MAX_BUG_REPORTS);
391b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal    private final HashMap<String, ByteArrayRingBuffer> mRingBufferData = new HashMap();
3920bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
3930bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private final WifiNative.WifiLoggerEventHandler mHandler =
3940bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            new WifiNative.WifiLoggerEventHandler() {
3950bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        @Override
3960bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        public void onRingBufferData(WifiNative.RingBufferStatus status, byte[] buffer) {
397019fda2109ea79daee3fb4442080b1b83be2e7b3mukesh agrawal            WifiDiagnostics.this.onRingBufferData(status, buffer);
3980bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
3990bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
4000bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        @Override
4010bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        public void onWifiAlert(int errorCode, byte[] buffer) {
402019fda2109ea79daee3fb4442080b1b83be2e7b3mukesh agrawal            WifiDiagnostics.this.onWifiAlert(errorCode, buffer);
4030bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
4040bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    };
4050bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
4060bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    synchronized void onRingBufferData(WifiNative.RingBufferStatus status, byte[] buffer) {
407b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal        ByteArrayRingBuffer ring = mRingBufferData.get(status.name);
4080bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (ring != null) {
409b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal            ring.appendBuffer(buffer);
4100bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
41103ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe    }
412a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
413d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius    synchronized void onWifiAlert(int errorCode, @NonNull byte[] buffer) {
414d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius        captureAlertData(errorCode, buffer);
415d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius        mWifiMetrics.incrementAlertReasonCount(errorCode);
416a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle    }
417a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
418f8c50b1e8239d843dd01e6dcf956629dad0771c1mukesh agrawal    private boolean isVerboseLoggingEnabled() {
419f8c50b1e8239d843dd01e6dcf956629dad0771c1mukesh agrawal        return mLogLevel > VERBOSE_NORMAL_LOG;
420f8c50b1e8239d843dd01e6dcf956629dad0771c1mukesh agrawal    }
421f8c50b1e8239d843dd01e6dcf956629dad0771c1mukesh agrawal
4222ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal    private void clearVerboseLogs() {
4232ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal        mPacketFatesForLastFailure = null;
4242ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal
4252ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal        for (int i = 0; i < mLastAlerts.size(); i++) {
4262ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal            mLastAlerts.get(i).clearVerboseLogs();
4272ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal        }
4282ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal
4292ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal        for (int i = 0; i < mLastBugReports.size(); i++) {
4302ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal            mLastBugReports.get(i).clearVerboseLogs();
4312ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal        }
4322ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal    }
4332ecb62764d26c3f0d95a9dc5c0a616af1b2bf8demukesh agrawal
4340bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private boolean fetchRingBuffers() {
4350bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (mRingBuffers != null) return true;
436a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
43718786eca942042388748b0d98979f21c9dff4a89Mitchell Wills        mRingBuffers = mWifiNative.getRingBufferStatus();
4380bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (mRingBuffers != null) {
4390bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            for (WifiNative.RingBufferStatus buffer : mRingBuffers) {
440f46c533931224296b11d98798344c049f88db9a1mukesh agrawal                if (DBG) mLog.trace("RingBufferStatus is: %").c(buffer.name).flush();
4410bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                if (mRingBufferData.containsKey(buffer.name) == false) {
4420bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                    mRingBufferData.put(buffer.name,
443fef1495477206d4cabfc95325d71de41790cf9ccmukesh agrawal                            new ByteArrayRingBuffer(mMaxRingBufferSizeBytes));
4440bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                }
4450bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                if ((buffer.flag & RING_BUFFER_FLAG_HAS_PER_PACKET_ENTRIES) != 0) {
4460bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                    mPerPacketRingBuffer = buffer;
44703ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe                }
448a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle            }
44903ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe        } else {
450f5d90be206db98bbd5894afc8d757dd32360b2d9mukesh agrawal            mLog.wC("no ring buffers found");
451a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle        }
45203ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
4530bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        return mRingBuffers != null;
454a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle    }
455a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
456d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal    private void resizeRingBuffers() {
457d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal        for (ByteArrayRingBuffer byteArrayRingBuffer : mRingBufferData.values()) {
458d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal            byteArrayRingBuffer.resize(mMaxRingBufferSizeBytes);
459d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal        }
460d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal    }
461d604bbd63d620244ef43408de10f65ead01d5026mukesh agrawal
4620bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private boolean startLoggingAllExceptPerPacketBuffers() {
46303ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
4640bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (mRingBuffers == null) {
465f5d90be206db98bbd5894afc8d757dd32360b2d9mukesh agrawal            if (DBG) mLog.tC("No ring buffers to log anything!");
4660bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            return false;
46703ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe        }
46803ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
4690bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        for (WifiNative.RingBufferStatus buffer : mRingBuffers){
4700bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
4710bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            if ((buffer.flag & RING_BUFFER_FLAG_HAS_PER_PACKET_ENTRIES) != 0) {
4720bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                /* skip per-packet-buffer */
473f46c533931224296b11d98798344c049f88db9a1mukesh agrawal                if (DBG) mLog.trace("skipped per packet logging ring %").c(buffer.name).flush();
4740bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                continue;
47503ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe            }
4760bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
4770bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            startLoggingRingBuffer(buffer);
47803ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe        }
47903ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
48003ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe        return true;
481a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle    }
482a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
4830bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private boolean startLoggingRingBuffer(WifiNative.RingBufferStatus buffer) {
4840bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
4850bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        int minInterval = MinWakeupIntervals[mLogLevel];
4860bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        int minDataSize = MinBufferSizes[mLogLevel];
4870bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
48818786eca942042388748b0d98979f21c9dff4a89Mitchell Wills        if (mWifiNative.startLoggingRingBuffer(
4890bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                mLogLevel, 0, minInterval, minDataSize, buffer.name) == false) {
490f46c533931224296b11d98798344c049f88db9a1mukesh agrawal            if (DBG) mLog.warn("Could not start logging ring %").c(buffer.name).flush();
4910bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            return false;
4920bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
4930bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
4940bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        return true;
49503ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe    }
496a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle
4970bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private boolean stopLoggingRingBuffer(WifiNative.RingBufferStatus buffer) {
49818786eca942042388748b0d98979f21c9dff4a89Mitchell Wills        if (mWifiNative.startLoggingRingBuffer(0, 0, 0, 0, buffer.name) == false) {
499f46c533931224296b11d98798344c049f88db9a1mukesh agrawal            if (DBG) mLog.warn("Could not stop logging ring %").c(buffer.name).flush();
50003ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe        }
5010bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        return true;
5020bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    }
5030bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
5040bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    private boolean stopLoggingAllBuffers() {
505d27cbe81e1b51f09081c667c275019e63a0399a2Vinit Deshpande        if (mRingBuffers != null) {
506d27cbe81e1b51f09081c667c275019e63a0399a2Vinit Deshpande            for (WifiNative.RingBufferStatus buffer : mRingBuffers) {
507d27cbe81e1b51f09081c667c275019e63a0399a2Vinit Deshpande                stopLoggingRingBuffer(buffer);
508d27cbe81e1b51f09081c667c275019e63a0399a2Vinit Deshpande            }
5090bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
5100bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        return true;
5110bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    }
51203ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
5138df302f5b9c647f69acee24e09fa20d8b5c54c4amukesh agrawal    private boolean enableVerboseLoggingForDogfood() {
5144776ec875d92edd7ed00d739720ed08c7894bc8amukesh agrawal        return true;
5154776ec875d92edd7ed00d739720ed08c7894bc8amukesh agrawal
5168df302f5b9c647f69acee24e09fa20d8b5c54c4amukesh agrawal    }
5178df302f5b9c647f69acee24e09fa20d8b5c54c4amukesh agrawal
518f7db07b9cc88ceef2ca3d77414834d0d75b4ece7Vinit Deshpande    private BugReport captureBugreport(int errorCode, boolean captureFWDump) {
5190bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        BugReport report = new BugReport();
5200bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        report.errorCode = errorCode;
5216414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande        report.systemTimeMs = System.currentTimeMillis();
5226414301b7b685307e8ae8cea6976ed05cc49b254Vinit Deshpande        report.kernelTimeNanos = System.nanoTime();
5230bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
524ba5908f65b0470be02ec7b5c035a3aec22eb0c11Vinit Deshpande        if (mRingBuffers != null) {
525ba5908f65b0470be02ec7b5c035a3aec22eb0c11Vinit Deshpande            for (WifiNative.RingBufferStatus buffer : mRingBuffers) {
526ba5908f65b0470be02ec7b5c035a3aec22eb0c11Vinit Deshpande                /* this will push data in mRingBuffers */
52718786eca942042388748b0d98979f21c9dff4a89Mitchell Wills                mWifiNative.getRingBufferData(buffer.name);
528b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal                ByteArrayRingBuffer data = mRingBufferData.get(buffer.name);
529b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal                byte[][] buffers = new byte[data.getNumBuffers()][];
530b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal                for (int i = 0; i < data.getNumBuffers(); i++) {
531b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal                    buffers[i] = data.getBuffer(i).clone();
532ba5908f65b0470be02ec7b5c035a3aec22eb0c11Vinit Deshpande                }
533ba5908f65b0470be02ec7b5c035a3aec22eb0c11Vinit Deshpande                report.ringBuffers.put(buffer.name, buffers);
5340bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            }
5350bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
5360bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
53737e073350c5e3bdac08d4fa2a0cc9f37190d1173Ningyuan Wang        report.logcatLines = getLogcat(127);
5387e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        report.kernelLogLines = getKernelLog(127);
5397e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande
540f7db07b9cc88ceef2ca3d77414834d0d75b4ece7Vinit Deshpande        if (captureFWDump) {
54118786eca942042388748b0d98979f21c9dff4a89Mitchell Wills            report.fwMemoryDump = mWifiNative.getFwMemoryDump();
542d0cb2fae195ebb9f658095667f3c7b7b8d69a204mukesh agrawal            report.mDriverStateDump = mWifiNative.getDriverStateDump();
543f7db07b9cc88ceef2ca3d77414834d0d75b4ece7Vinit Deshpande        }
5440bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        return report;
545a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle    }
54603ba4a5b108ab2bbdb5d0e7be46ac45c00a6d9ffxinhe
547b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal    @VisibleForTesting
548b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal    LimitedCircularArray<BugReport> getBugReports() {
549b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal        return mLastBugReports;
550b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal    }
551b46c550a7305e6c42af4ca92a964b801c33f1f72mukesh agrawal
552d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius    @VisibleForTesting
553d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius    LimitedCircularArray<BugReport> getAlertReports() {
554d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius        return mLastAlerts;
555d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius    }
556d3be501437efd5f176e7541cace20b8db467eb47Roshan Pius
557235d4d28542d8007c9609a84af0ac7b4c4bba02amukesh agrawal    private String compressToBase64(byte[] input) {
5580bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        String result;
5590bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        //compress
5600bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        Deflater compressor = new Deflater();
5619a312a13ba34712f3de7f4d0c8d04ff695a41caemukesh agrawal        compressor.setLevel(Deflater.BEST_SPEED);
5620bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        compressor.setInput(input);
5630bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        compressor.finish();
5640bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        ByteArrayOutputStream bos = new ByteArrayOutputStream(input.length);
5650bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        final byte[] buf = new byte[1024];
5660bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
5670bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        while (!compressor.finished()) {
5680bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            int count = compressor.deflate(buf);
5690bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            bos.write(buf, 0, count);
5700bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
5710bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
5720bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        try {
5730bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            compressor.end();
5740bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            bos.close();
5750bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        } catch (IOException e) {
576f5d90be206db98bbd5894afc8d757dd32360b2d9mukesh agrawal            mLog.wC("ByteArrayOutputStream close error");
5770bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            result =  android.util.Base64.encodeToString(input, Base64.DEFAULT);
5780bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande            return result;
5790bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
5800bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
5810bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        byte[] compressed = bos.toByteArray();
5820bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (DBG) {
583f46c533931224296b11d98798344c049f88db9a1mukesh agrawal            mLog.dump("length is: %").c(compressed == null ? 0 : compressed.length).flush();
5840bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
5850bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
5860bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        //encode
5870bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        result = android.util.Base64.encodeToString(
5880bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande                compressed.length < input.length ? compressed : input , Base64.DEFAULT);
5890bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
5900bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        if (DBG) {
591f46c533931224296b11d98798344c049f88db9a1mukesh agrawal            mLog.dump("FwMemoryDump length is: %").c(result.length()).flush();
5920bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        }
5930bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande
5940bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande        return result;
5950bf150b2d69ec62df905bc6f8603437dc4caee1fVinit Deshpande    }
5967e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande
59737e073350c5e3bdac08d4fa2a0cc9f37190d1173Ningyuan Wang    private ArrayList<String> getLogcat(int maxLines) {
59837e073350c5e3bdac08d4fa2a0cc9f37190d1173Ningyuan Wang        ArrayList<String> lines = new ArrayList<String>(maxLines);
5997e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        try {
6003bbf564af91515b33fcba33e7039ffe09c8c025cmukesh agrawal            Process process = mJavaRuntime.exec(String.format("logcat -t %d", maxLines));
6017e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            BufferedReader reader = new BufferedReader(
6027e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                    new InputStreamReader(process.getInputStream()));
6037e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            String line;
6047e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            while ((line = reader.readLine()) != null) {
60537e073350c5e3bdac08d4fa2a0cc9f37190d1173Ningyuan Wang                lines.add(line);
6067e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            }
6077e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            reader = new BufferedReader(
6087e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande                    new InputStreamReader(process.getErrorStream()));
6097e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            while ((line = reader.readLine()) != null) {
61037e073350c5e3bdac08d4fa2a0cc9f37190d1173Ningyuan Wang                lines.add(line);
6117e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            }
6127e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            process.waitFor();
61337e073350c5e3bdac08d4fa2a0cc9f37190d1173Ningyuan Wang        } catch (InterruptedException|IOException e) {
614f46c533931224296b11d98798344c049f88db9a1mukesh agrawal            mLog.dump("Exception while capturing logcat: %").c(e.toString()).flush();
6157e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        }
6167e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        return lines;
6177e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande    }
6187e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande
6197e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande    private LimitedCircularArray<String> getKernelLog(int maxLines) {
620f5d90be206db98bbd5894afc8d757dd32360b2d9mukesh agrawal        if (DBG) mLog.tC("Reading kernel log ...");
6217e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        LimitedCircularArray<String> lines = new LimitedCircularArray<String>(maxLines);
6227e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        String log = mWifiNative.readKernelLog();
6237e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        String logLines[] = log.split("\n");
6247e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        for (int i = 0; i < logLines.length; i++) {
6257e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande            lines.addLast(logLines[i]);
6267e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        }
627f46c533931224296b11d98798344c049f88db9a1mukesh agrawal        if (DBG) mLog.dump("Added % lines").c(logLines.length).flush();
6287e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande        return lines;
6297e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande    }
6307e0315140767e6f12200f7dbbe7aff43b4f75089Vinit Deshpande
631ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal    /** Packet fate reporting */
632ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal    private ArrayList<WifiNative.FateReport> mPacketFatesForLastFailure;
633ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
634ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal    private ArrayList<WifiNative.FateReport> fetchPacketFates() {
635ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        ArrayList<WifiNative.FateReport> mergedFates = new ArrayList<WifiNative.FateReport>();
636ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        WifiNative.TxFateReport[] txFates =
637ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal                new WifiNative.TxFateReport[WifiLoggerHal.MAX_FATE_LOG_LEN];
63852ed1731664f7e0b76adb14eec7a76eaa95144c3Roshan Pius        if (mWifiNative.getTxPktFates(mWifiNative.getClientInterfaceName(), txFates)) {
639ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            for (int i = 0; i < txFates.length && txFates[i] != null; i++) {
640ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal                mergedFates.add(txFates[i]);
641ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            }
642ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        }
643ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
644ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        WifiNative.RxFateReport[] rxFates =
645ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal                new WifiNative.RxFateReport[WifiLoggerHal.MAX_FATE_LOG_LEN];
64652ed1731664f7e0b76adb14eec7a76eaa95144c3Roshan Pius        if (mWifiNative.getRxPktFates(mWifiNative.getClientInterfaceName(), rxFates)) {
647ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            for (int i = 0; i < rxFates.length && rxFates[i] != null; i++) {
648ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal                mergedFates.add(rxFates[i]);
649ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            }
650ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        }
651ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
652ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        Collections.sort(mergedFates, new Comparator<WifiNative.FateReport>() {
653ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            @Override
654ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            public int compare(WifiNative.FateReport lhs, WifiNative.FateReport rhs) {
655ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal                return Long.compare(lhs.mDriverTimestampUSec, rhs.mDriverTimestampUSec);
656ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            }
657ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        });
658ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
659ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        return mergedFates;
660ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal    }
661ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
662ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal    private void dumpPacketFates(PrintWriter pw) {
663590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan        dumpPacketFatesInternal(pw, "Last failed connection fates", mPacketFatesForLastFailure,
664590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan                isVerboseLoggingEnabled());
6651bf155710ada7a6ee27453a120690d2c91a0fec5mukesh agrawal        dumpPacketFatesInternal(pw, "Latest fates", fetchPacketFates(), isVerboseLoggingEnabled());
666ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal    }
667ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
668590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan    private static void dumpPacketFatesInternal(PrintWriter pw, String description,
669590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan            ArrayList<WifiNative.FateReport> fates, boolean verbose) {
670ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        if (fates == null) {
671ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            pw.format("No fates fetched for \"%s\"\n", description);
672ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            return;
673ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        }
674ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
675ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        if (fates.size() == 0) {
676ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            pw.format("HAL provided zero fates for \"%s\"\n", description);
677ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal            return;
678ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        }
679ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal
680ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        pw.format("--------------------- %s ----------------------\n", description);
681590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan
682590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan        StringBuilder verboseOutput = new StringBuilder();
683590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan        pw.print(WifiNative.FateReport.getTableHeader());
684ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        for (WifiNative.FateReport fate : fates) {
685590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan            pw.print(fate.toTableRowString());
686590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan            if (verbose) {
687590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan                // Important: only print Personally Identifiable Information (PII) if verbose
688590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan                // logging is turned on.
689590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan                verboseOutput.append(fate.toVerboseStringWithPiiAllowed());
690590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan                verboseOutput.append("\n");
691590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan            }
692590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan        }
693590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan
694590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan        if (verbose) {
695590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan            pw.format("\n>>> VERBOSE PACKET FATE DUMP <<<\n\n");
696590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan            pw.print(verboseOutput.toString());
697ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        }
698590f3fc2045389d5ef274c4b3bd6162d93b1a0acSamuel Tan
699ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal        pw.println("--------------------------------------------------------------------");
700ed510cfa64decd813f76faf9bb1b0a70b74b9898mukesh agrawal    }
701a0d34d3626bd9631039a485d2d428b1b7de390e2Pierre Vandwalle}
702