Modify wifi BatchedScan.

Add pollBatchedScan API to allow forced retrieval.
Modified driver API, adding MSCAN, removing nextCount and making
the results look more like normal manual scan results.

bug:9301872
Change-Id: I58bce0624c36e2ad8d3c3f5defcb4d4e155dc8f9
diff --git a/framework/java/android/net/wifi/BatchedScanSettings.java b/framework/java/android/net/wifi/BatchedScanSettings.java
index 82945d6..44a2ab4 100644
--- a/framework/java/android/net/wifi/BatchedScanSettings.java
+++ b/framework/java/android/net/wifi/BatchedScanSettings.java
@@ -51,6 +51,7 @@
     public final static int MAX_AP_FOR_DISTANCE = MAX_AP_PER_SCAN;
     public final static int DEFAULT_AP_FOR_DISTANCE = 0;
 
+    public final static int MAX_WIFI_CHANNEL = 196;
 
     /** The expected number of scans per batch.  Note that the firmware may drop scans
      *  leading to fewer scans during the normal batch scan duration.  This value need not
@@ -113,7 +114,7 @@
         for (String channel : channelSet) {
             try {
                 int i = Integer.parseInt(channel);
-                if (i > 0 && i < 197) continue;
+                if (i > 0 && i <= MAX_WIFI_CHANNEL) continue;
             } catch (NumberFormatException e) {}
             if (channel.equals("A") || channel.equals("B")) continue;
             return false;
diff --git a/framework/java/android/net/wifi/IWifiManager.aidl b/framework/java/android/net/wifi/IWifiManager.aidl
index c8cf323..4f68ca0 100644
--- a/framework/java/android/net/wifi/IWifiManager.aidl
+++ b/framework/java/android/net/wifi/IWifiManager.aidl
@@ -124,5 +124,7 @@
     List<BatchedScanResult> getBatchedScanResults(String callingPackage);
 
     boolean isBatchedScanSupported();
+
+    void pollBatchedScan();
 }
 
diff --git a/framework/java/android/net/wifi/WifiManager.java b/framework/java/android/net/wifi/WifiManager.java
index 01ca378..a15b664 100644
--- a/framework/java/android/net/wifi/WifiManager.java
+++ b/framework/java/android/net/wifi/WifiManager.java
@@ -840,6 +840,32 @@
     }
 
     /**
+     * Force a re-reading of batched scan results.  This will attempt
+     * to read more information from the chip, but will do so at the expense
+     * of previous data.  Rate limited to the current scan frequency.
+     *
+     * pollBatchedScan will always wait 1 period from the start of the batch
+     * before trying to read from the chip, so if your #scans/batch == 1 this will
+     * have no effect.
+     *
+     * If you had already waited 1 period before calling, this should have
+     * immediate (though async) effect.
+     *
+     * If you call before that 1 period is up this will set up a timer and fetch
+     * results when the 1 period is up.
+     *
+     * Servicing a pollBatchedScan request (immediate or after timed delay) starts a
+     * new batch, so if you were doing 10 scans/batch and called in the 4th scan, you
+     * would get data in the 4th and then again 10 scans later.
+     * @hide
+     */
+    public void pollBatchedScan() {
+        try {
+            mService.pollBatchedScan();
+        } catch (RemoteException e) { }
+    }
+
+    /**
      * Return dynamic information about the current Wi-Fi connection, if any is active.
      * @return the Wi-Fi information, contained in {@link WifiInfo}.
      */
diff --git a/framework/java/android/net/wifi/WifiNative.java b/framework/java/android/net/wifi/WifiNative.java
index 0359076..48c5ae3 100644
--- a/framework/java/android/net/wifi/WifiNative.java
+++ b/framework/java/android/net/wifi/WifiNative.java
@@ -221,8 +221,9 @@
 
     /**
      * Format of command
-     * DRIVER WLS_BATCHING SET SCAN_FRQ=x BESTN=y CHANNEL=<z, w, t> RTT=s
+     * DRIVER WLS_BATCHING SET SCAN_FRQ=x MSCAN=r BESTN=y CHANNEL=<z, w, t> RTT=s
      * where x is an ascii representation of an integer number of seconds between scans
+     *       r is an ascii representation of an integer number of scans per batch
      *       y is an ascii representation of an integer number of the max AP to remember per scan
      *       z, w, t represent a 1..n size list of channel numbers and/or 'A', 'B' values
      *           indicating entire ranges of channels
@@ -235,8 +236,9 @@
     public String setBatchedScanSettings(BatchedScanSettings settings) {
         if (settings == null) return doStringCommand("DRIVER WLS_BATCHING STOP");
         String cmd = "DRIVER WLS_BATCHING SET SCAN_FRQ=" + settings.scanIntervalSec;
+        cmd += " MSCAN=" + settings.maxScansPerBatch;
         if (settings.maxApPerScan != BatchedScanSettings.UNSPECIFIED) {
-            cmd += " BESTN " + settings.maxApPerScan;
+            cmd += " BESTN=" + settings.maxApPerScan;
         }
         if (settings.channelSet != null && !settings.channelSet.isEmpty()) {
             cmd += " CHANNEL=<";
diff --git a/framework/java/android/net/wifi/WifiStateMachine.java b/framework/java/android/net/wifi/WifiStateMachine.java
index 764c00a..8b7b8ae 100644
--- a/framework/java/android/net/wifi/WifiStateMachine.java
+++ b/framework/java/android/net/wifi/WifiStateMachine.java
@@ -127,6 +127,8 @@
     private final List<BatchedScanResult> mBatchedScanResults =
             new ArrayList<BatchedScanResult>();
     private int mBatchedScanOwnerUid = UNKNOWN_SCAN_SOURCE;
+    private int mExpectedBatchedScans = 0;
+    private long mBatchedScanMinPollTime = 0;
 
     /* Chipset supports background scan */
     private final boolean mBackgroundScanSupported;
@@ -366,8 +368,9 @@
      * arg1 = responsible UID
      * obj = the new settings
      */
-    public static final int CMD_SET_BATCH_SCAN            = BASE + 135;
+    public static final int CMD_SET_BATCHED_SCAN          = BASE + 135;
     public static final int CMD_START_NEXT_BATCHED_SCAN   = BASE + 136;
+    public static final int CMD_POLL_BATCHED_SCAN         = BASE + 137;
 
     public static final int CONNECT_MODE                   = 1;
     public static final int SCAN_ONLY_MODE                 = 2;
@@ -766,7 +769,7 @@
      * start or stop batched scanning using the given settings
      */
     public void setBatchedScanSettings(BatchedScanSettings settings, int callingUid) {
-        sendMessage(CMD_SET_BATCH_SCAN, callingUid, 0, settings);
+        sendMessage(CMD_SET_BATCHED_SCAN, callingUid, 0, settings);
     }
 
     public List<BatchedScanResult> syncGetBatchedScanResultsList() {
@@ -780,6 +783,10 @@
         }
     }
 
+    public void requestBatchedScanPoll() {
+        sendMessage(CMD_POLL_BATCHED_SCAN);
+    }
+
     private void startBatchedScan() {
         // first grab any existing data
         retrieveBatchedScanData();
@@ -789,8 +796,8 @@
         String scansExpected = mWifiNative.setBatchedScanSettings(mBatchedScanSettings);
 
         try {
-            int expected = Integer.parseInt(scansExpected);
-            setNextBatchedAlarm(expected);
+            mExpectedBatchedScans = Integer.parseInt(scansExpected);
+            setNextBatchedAlarm(mExpectedBatchedScans);
         } catch (NumberFormatException e) {
             loge("Exception parsing WifiNative.setBatchedScanSettings response " + e);
         }
@@ -803,9 +810,27 @@
 
     private void startNextBatchedScan() {
         // first grab any existing data
-        int nextCount = retrieveBatchedScanData();
+        retrieveBatchedScanData();
 
-        setNextBatchedAlarm(nextCount);
+        setNextBatchedAlarm(mExpectedBatchedScans);
+    }
+
+    private void handleBatchedScanPollRequest() {
+        // if there is no appropriate PollTime that's because we either aren't
+        // batching or we've already set a time for a poll request
+        if (mBatchedScanMinPollTime == 0) return;
+        if (mBatchedScanSettings == null) return;
+
+        long now = System.currentTimeMillis();
+
+        if (now > mBatchedScanMinPollTime) {
+            // do the poll and reset our timers
+            startNextBatchedScan();
+        } else {
+            mAlarmManager.set(AlarmManager.RTC_WAKEUP, mBatchedScanMinPollTime,
+                    mBatchedScanIntervalIntent);
+            mBatchedScanMinPollTime = 0;
+        }
     }
 
     // return true if new/different
@@ -832,6 +857,9 @@
 
         if (mBatchedScanSettings == null || scansExpected < 1) return;
 
+        mBatchedScanMinPollTime = System.currentTimeMillis() +
+                mBatchedScanSettings.scanIntervalSec * 1000;
+
         if (mBatchedScanSettings.maxScansPerBatch < scansExpected) {
             scansExpected = mBatchedScanSettings.maxScansPerBatch;
         }
@@ -876,22 +904,18 @@
      *   etc
      *   "----"
      */
-    private int retrieveBatchedScanData() {
+    private void retrieveBatchedScanData() {
         String rawData = mWifiNative.getBatchedScanResults();
+        mBatchedScanMinPollTime = 0;
         if (rawData == null) {
             loge("Unexpected null BatchedScanResults");
-            return 0;
+            return;
         }
 
-        int nextCount = 0;
         int scanCount = 0;
-        final String END_OF_SCAN = "====";
-        final String END_OF_BATCH = "%%%%";
         final String END_OF_BATCHES = "----";
         final String SCANCOUNT = "scancount=";
-        final String NEXTCOUNT = "nextcount=";
         final String TRUNCATED = "trunc";
-        final String APCOUNT = "apcount=";
         final String AGE = "age=";
         final String DIST = "dist=";
         final String DISTSD = "distsd=";
@@ -905,16 +929,7 @@
         }
         if (scanCount == 0) {
             loge("scanCount not found");
-            return 0;
-        }
-        if (splitData[n].startsWith(NEXTCOUNT)) {
-            try {
-                nextCount = Integer.parseInt(splitData[n++].substring(NEXTCOUNT.length()));
-            } catch (NumberFormatException e) {}
-        }
-        if (nextCount == 0) {
-            loge("nextCount not found");
-            return 0;
+            return;
         }
 
         final Intent intent = new Intent(WifiManager.BATCHED_SCAN_RESULTS_AVAILABLE_ACTION);
@@ -942,9 +957,9 @@
                         if (mBatchedScanResults.size() > 0) {
                             mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
                         }
-                        return nextCount;
+                        return;
                     }
-                    if ((splitData[n].equals(END_OF_SCAN)) || splitData[n].equals(END_OF_BATCH)) {
+                    if ((splitData[n].equals(END_STR)) || splitData[n].equals(DELIMITER_STR)) {
                         if (bssid != null) {
                             batchedScanResult.scanResults.add(new ScanResult(
                                     wifiSsid, bssid, "", level, freq, tsf, dist, distSd));
@@ -955,7 +970,7 @@
                             tsf = 0;
                             dist = distSd = ScanResult.UNSPECIFIED;
                         }
-                        if (splitData[n].equals(END_OF_BATCH)) {
+                        if (splitData[n].equals(END_STR)) {
                             if (batchedScanResult.scanResults.size() != 0) {
                                 mBatchedScanResults.add(batchedScanResult);
                                 batchedScanResult = new BatchedScanResult();
@@ -1010,7 +1025,7 @@
                 rawData = mWifiNative.getBatchedScanResults();
                 if (rawData == null) {
                     loge("Unexpected null BatchedScanResults");
-                    return nextCount;
+                    return;
                 }
                 splitData = rawData.split("\n");
                 if (splitData.length == 0 || splitData[0].equals("ok")) {
@@ -1018,7 +1033,7 @@
                     if (mBatchedScanResults.size() > 0) {
                         mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
                     }
-                    return nextCount;
+                    return;
                 }
                 n = 0;
             }
@@ -2266,9 +2281,11 @@
                         sendMessageAtFrontOfQueue(CMD_SET_COUNTRY_CODE, countryCode);
                     }
                     break;
-                case CMD_SET_BATCH_SCAN:
+                case CMD_SET_BATCHED_SCAN:
                     recordBatchedScanSettings((BatchedScanSettings)message.obj);
                     break;
+                case CMD_POLL_BATCHED_SCAN:
+                    handleBatchedScanPollRequest();
                 case CMD_START_NEXT_BATCHED_SCAN:
                     startNextBatchedScan();
                     break;
@@ -2808,7 +2825,7 @@
                     noteScanStart(message.arg1, (WorkSource) message.obj);
                     startScanNative(WifiNative.SCAN_WITH_CONNECTION_SETUP);
                     break;
-                case CMD_SET_BATCH_SCAN:
+                case CMD_SET_BATCHED_SCAN:
                     recordBatchedScanSettings((BatchedScanSettings)message.obj);
                     startBatchedScan();
                     break;