Merge "Add wifi association heuristic"
diff --git a/src/com/android/loganalysis/item/DumpsysWifiStatsItem.java b/src/com/android/loganalysis/item/DumpsysWifiStatsItem.java
index 6ceb073..b956a65 100644
--- a/src/com/android/loganalysis/item/DumpsysWifiStatsItem.java
+++ b/src/com/android/loganalysis/item/DumpsysWifiStatsItem.java
@@ -27,9 +27,11 @@
     public static final String WIFI_DISCONNECT = "WIFI_DISCONNECT";
     /** Constant for JSON output */
     public static final String WIFI_SCAN = "WIFI_SCAN";
+    /** Constant for JSON output */
+    public static final String WIFI_ASSOCIATION = "WIFI_ASSOCIATION";
 
     private static final Set<String> ATTRIBUTES = new HashSet<String>(Arrays.asList(
-            WIFI_DISCONNECT, WIFI_SCAN));
+            WIFI_DISCONNECT, WIFI_SCAN, WIFI_ASSOCIATION));
 
      /**
      * The constructor for {@link DumpsysWifiStatsItem}.
@@ -53,6 +55,13 @@
     }
 
     /**
+     * Set number of times of wifi associations
+     */
+    public void setNumWifiAssociation(int numWifiAssociations) {
+        setAttribute(WIFI_ASSOCIATION, numWifiAssociations);
+    }
+
+    /**
      * Get the number of times wifi disconnected
      */
     public int getNumWifiDisconnects() {
@@ -65,4 +74,11 @@
     public int getNumWifiScans() {
         return (int) getAttribute(WIFI_SCAN);
     }
+
+    /**
+     * Get the number of times wifi association event triggered
+     */
+    public int getNumWifiAssociations() {
+        return (int) getAttribute(WIFI_ASSOCIATION);
+    }
 }
diff --git a/src/com/android/loganalysis/parser/DumpsysWifiStatsParser.java b/src/com/android/loganalysis/parser/DumpsysWifiStatsParser.java
index d977902..52c1bf3 100644
--- a/src/com/android/loganalysis/parser/DumpsysWifiStatsParser.java
+++ b/src/com/android/loganalysis/parser/DumpsysWifiStatsParser.java
@@ -41,6 +41,13 @@
             + "bssid=\\w+:\\w+:\\w+:\\w+:\\w+:\\w+ reason=\\d+(\\s*locally_generated=\\d+)?\\]");
 
     /**
+     * Matches: 01-21 18:17:23.15 - Event [IFNAME=wlan0 Trying to associate with SSID 'WL-power-2']
+     */
+    private static final Pattern WIFI_ASSOCIATION = Pattern.compile(
+            "^\\d+-\\d+ \\d+:\\d+:\\d+\\.\\d+ - Event \\[IFNAME=wlan0 Trying to associate with "
+            + "SSID \\'.*\\'\\]");
+
+    /**
      * {@inheritDoc}
      *
      * @return The {@link DumpsysWifiStatsItem}.
@@ -50,6 +57,7 @@
         DumpsysWifiStatsItem item = new DumpsysWifiStatsItem();
         int numWifiScans = 0;
         int numWifiDisconnects = 0;
+        int numWifiAssociations = 0;
         for (String line : lines) {
             Matcher m = WIFI_SCAN.matcher(line);
             if(m.matches()) {
@@ -59,10 +67,16 @@
             m = WIFI_DISCONNECT.matcher(line);
             if (m.matches()) {
                 numWifiDisconnects++;
+                continue;
+            }
+            m = WIFI_ASSOCIATION.matcher(line);
+            if (m.matches()) {
+                numWifiAssociations++;
             }
         }
         item.setNumWifiScan(numWifiScans);
         item.setNumWifiDisconnect(numWifiDisconnects);
+        item.setNumWifiAssociation(numWifiAssociations);
         return item;
     }
 
diff --git a/src/com/android/loganalysis/rule/WifiStatsRule.java b/src/com/android/loganalysis/rule/WifiStatsRule.java
index f9bca39..da422de 100644
--- a/src/com/android/loganalysis/rule/WifiStatsRule.java
+++ b/src/com/android/loganalysis/rule/WifiStatsRule.java
@@ -31,11 +31,13 @@
 
     private static final String WIFI_STATS = "WIFI_STATS";
     private static final int WIFI_DISCONNECT_THRESHOLD = 1; // wifi disconnect should never happen
+    private static final int WIFI_ASSOCIATION_THRESHOLD = 1;
     // Wifi scans are scheduled by GSA every 285 seconds, anything more frequent is an issue
     private static final long WIFI_SCAN_INTERVAL_THRESHOLD_MS = 285000;
 
     private long mFrequentWifiScansIntervalSecs = 0;
     private int mNumFrequentWifiDisconnects = 0;
+    private int mNumFrequentWifiAssociations = 0;
 
     private BugreportItem mBugreportItem = null;
 
@@ -65,6 +67,9 @@
         if (dumpsysWifiStatsItem.getNumWifiDisconnects() >= WIFI_DISCONNECT_THRESHOLD) {
             mNumFrequentWifiDisconnects = dumpsysWifiStatsItem.getNumWifiDisconnects();
         }
+        if (dumpsysWifiStatsItem.getNumWifiAssociations() > WIFI_ASSOCIATION_THRESHOLD) {
+            mNumFrequentWifiAssociations = dumpsysWifiStatsItem.getNumWifiAssociations();
+        }
     }
 
     @Override
@@ -83,6 +88,12 @@
             analysis.append(String.format("Wifi got disconnected %d times. ",
                     mNumFrequentWifiDisconnects));
         }
+        if (mNumFrequentWifiAssociations == 0) {
+            analysis.append("No frequent wifi associations were observed. ");
+        } else {
+            analysis.append(String.format("Wifi got associated with AP %d times. ",
+                    mNumFrequentWifiAssociations));
+        }
         try {
             wifiStatsAnalysis.put(WIFI_STATS, analysis.toString().trim());
         } catch (JSONException e) {
diff --git a/tests/src/com/android/loganalysis/parser/DumpsysWifiStatsParserTest.java b/tests/src/com/android/loganalysis/parser/DumpsysWifiStatsParserTest.java
index 6a9e302..f52e432 100644
--- a/tests/src/com/android/loganalysis/parser/DumpsysWifiStatsParserTest.java
+++ b/tests/src/com/android/loganalysis/parser/DumpsysWifiStatsParserTest.java
@@ -56,11 +56,15 @@
                 "10-08 13:06:25.363 - Event [IFNAME=wlan0 CTRL-EVENT-SCAN-STARTED ]",
                 "10-08 13:08:15.018 - Event [IFNAME=wlan0 CTRL-EVENT-DISCONNECTED "
                 + "bssid=9c:1c:12:e8:72:d2 reason=3 locally_generated=1]",
-                "10-08 13:08:15.324 - wlan0: 442:IFNAME=wlan0 ENABLE_NETWORK 0 -> true");
+                "10-08 13:08:15.324 - wlan0: 442:IFNAME=wlan0 ENABLE_NETWORK 0 -> true",
+                "01-21 13:17:23.1 - Event [IFNAME=wlan0 Trying to associate with SSID 'WL-power']",
+                "01-21 13:18:23.1 - Event [IFNAME=wlan0 Trying to associate with SSID 'WL-power']",
+                "01-21 13:18:23.1 - Event [IFNAME=wlan0 Trying to associate with SSID 'WL-power']");
 
         DumpsysWifiStatsItem wifiStats = new DumpsysWifiStatsParser().parse(inputBlock);
         assertEquals(2, wifiStats.getNumWifiDisconnects());
         assertEquals(3, wifiStats.getNumWifiScans());
+        assertEquals(3, wifiStats.getNumWifiAssociations());
     }
 
     /**
@@ -93,6 +97,7 @@
         DumpsysWifiStatsItem wifiStats = new DumpsysWifiStatsParser().parse(inputBlock);
         assertEquals(0, wifiStats.getNumWifiDisconnects());
         assertEquals(0, wifiStats.getNumWifiScans());
+        assertEquals(0, wifiStats.getNumWifiAssociations());
     }
 }
 
diff --git a/tests/src/com/android/loganalysis/rule/WifiStatsRuleTest.java b/tests/src/com/android/loganalysis/rule/WifiStatsRuleTest.java
index 628039e..984ed20 100644
--- a/tests/src/com/android/loganalysis/rule/WifiStatsRuleTest.java
+++ b/tests/src/com/android/loganalysis/rule/WifiStatsRuleTest.java
@@ -20,10 +20,6 @@
 import com.android.loganalysis.item.DumpsysBatteryStatsItem;
 import com.android.loganalysis.item.DumpsysItem;
 import com.android.loganalysis.item.DumpsysWifiStatsItem;
-import com.android.loganalysis.parser.BugreportParser;
-
-import java.util.Arrays;
-import java.util.List;
 
 import junit.framework.TestCase;
 
@@ -58,6 +54,7 @@
         DumpsysWifiStatsItem wifiStats = new DumpsysWifiStatsItem();
         wifiStats.setNumWifiDisconnect(1);
         wifiStats.setNumWifiScan(0);
+        wifiStats.setNumWifiAssociation(0);
 
         mDumpsys.setWifiStats(wifiStats);
         WifiStatsRule wifiStatsRule = new WifiStatsRule(mBugreport);
@@ -66,13 +63,15 @@
         assertNotNull(analysis);
         assertTrue(analysis.has("WIFI_STATS"));
         assertEquals(analysis.getString("WIFI_STATS"),
-                "No apps requested for frequent wifi scans. Wifi got disconnected 1 times.");
+                "No apps requested for frequent wifi scans. Wifi got disconnected 1 times. "
+                + "No frequent wifi associations were observed.");
     }
 
     public void testWifiScanAnalysis() throws Exception {
         DumpsysWifiStatsItem wifiStats = new DumpsysWifiStatsItem();
         wifiStats.setNumWifiDisconnect(0);
         wifiStats.setNumWifiScan(3);
+        wifiStats.setNumWifiAssociation(0);
 
         mDumpsys.setWifiStats(wifiStats);
         WifiStatsRule wifiStatsRule = new WifiStatsRule(mBugreport);
@@ -81,7 +80,24 @@
         assertNotNull(analysis);
         assertTrue(analysis.has("WIFI_STATS"));
         assertEquals(analysis.getString("WIFI_STATS"),
-                "Wifi scans happened every 100 seconds. No frequent wifi disconnects were observed."
-                );
+                "Wifi scans happened every 100 seconds. No frequent wifi disconnects were "
+                + "observed. No frequent wifi associations were observed.");
+    }
+
+    public void testWifiAssociationAnalysis() throws Exception {
+        DumpsysWifiStatsItem wifiStats = new DumpsysWifiStatsItem();
+        wifiStats.setNumWifiDisconnect(0);
+        wifiStats.setNumWifiScan(0);
+        wifiStats.setNumWifiAssociation(3);
+
+        mDumpsys.setWifiStats(wifiStats);
+        WifiStatsRule wifiStatsRule = new WifiStatsRule(mBugreport);
+        wifiStatsRule.applyRule();
+        JSONObject analysis = wifiStatsRule.getAnalysis();
+        assertNotNull(analysis);
+        assertTrue(analysis.has("WIFI_STATS"));
+        assertEquals(analysis.getString("WIFI_STATS"),
+                "No apps requested for frequent wifi scans. No frequent wifi disconnects were "
+                + "observed. Wifi got associated with AP 3 times.");
     }
 }