Merge "Add wake lock that is acquired during full wifi scans" into mnc-dev
diff --git a/service/java/com/android/server/wifi/WifiScanningServiceImpl.java b/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
index e7d3d3a..bfe7302 100644
--- a/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
+++ b/service/java/com/android/server/wifi/WifiScanningServiceImpl.java
@@ -38,6 +38,7 @@
 import android.os.Looper;
 import android.os.Message;
 import android.os.Messenger;
+import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.WorkSource;
@@ -70,6 +71,11 @@
     private static final int MIN_PERIOD_PER_CHANNEL_MS = 200;               // DFS needs 120 ms
     private static final int UNKNOWN_PID = -1;
 
+    /**
+     * Timeout for acquired wake lock while a scan is running
+     */
+    private static final int SCAN_WAKE_LOCK_TIME_OUT_MSECS = 5 * 1000;
+
     private static final LocalLog mLocalLog = new LocalLog(1024);
 
     private static void localLog(String message) {
@@ -215,6 +221,7 @@
     private WifiScanningStateMachine mStateMachine;
     private ClientHandler mClientHandler;
     private IBatteryStats mBatteryStats;
+    private PowerManager mPowerManager;
     private final WifiNative.ScanCapabilities mScanCapabilities = new WifiNative.ScanCapabilities();
 
     WifiScanningServiceImpl() { }
@@ -225,14 +232,15 @@
 
     public void startService(Context context) {
         mContext = context;
+        mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
+        mBatteryStats = BatteryStatsService.getService();
 
         HandlerThread thread = new HandlerThread("WifiScanningService");
         thread.start();
 
         mClientHandler = new ClientHandler(thread.getLooper());
         mStateMachine = new WifiScanningStateMachine(thread.getLooper());
-        mWifiChangeStateMachine = new WifiChangeStateMachine(thread.getLooper());
-        mBatteryStats = BatteryStatsService.getService();
+        mWifiChangeStateMachine = new WifiChangeStateMachine(thread.getLooper(), mPowerManager);
 
         mContext.registerReceiver(
                 new BroadcastReceiver() {
@@ -552,13 +560,19 @@
         private final Messenger mMessenger;
         private final int mUid;
         private final WorkSource mWorkSource;
+        private final PowerManager.WakeLock mFullScanWakeLock;
         private boolean mScanWorkReported = false;
+        private boolean mFullScanRequested = false;
 
         ClientInfo(int uid, AsyncChannel c, Messenger m) {
             mChannel = c;
             mMessenger = m;
             mUid = uid;
             mWorkSource = new WorkSource(uid, TAG);
+            mFullScanWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+                    "WifiScan");
+            mFullScanWakeLock.setReferenceCounted(false);
+            mFullScanWakeLock.setWorkSource(mWorkSource);
             if (DBG) localLog("New client, channel: " + c + " messenger: " + m);
         }
 
@@ -607,10 +621,21 @@
             if (mScanWorkReported) {
                 reportBatchedScanStop();
                 mScanWorkReported = false;
+                mFullScanRequested = false;
             }
             if (mScanSettings.isEmpty() == false) {
                 reportBatchedScanStart();
                 mScanWorkReported = true;
+
+                for (ScanSettings settings : getScanSettings()) {
+                    if (settings.reportEvents == WifiScanner.REPORT_EVENT_FULL_SCAN_RESULT) {
+                        mFullScanRequested = true;
+                    }
+                }
+                // make sure to charge first full scan even if there are no results
+                if (mFullScanRequested) {
+                    mFullScanWakeLock.acquire(SCAN_WAKE_LOCK_TIME_OUT_MSECS);
+                }
             }
         }
 
@@ -732,6 +757,7 @@
                 /* this is a single shot scan; stop the scan now */
                 mStateMachine.sendMessage(CMD_STOP_SCAN_INTERNAL, 0, handler, this);
             }
+            mFullScanWakeLock.release();
         }
 
         void deliverScanResults(int handler, ScanData results[]) {
@@ -742,6 +768,7 @@
 
         void reportFullScanResult(ScanResult result) {
             Iterator<Integer> it = mScanSettings.keySet().iterator();
+            boolean reportedFullScanResult = false;
             while (it.hasNext()) {
                 int handler = it.next();
                 ScanSettings settings = mScanSettings.get(handler);
@@ -757,9 +784,13 @@
                         newResult.informationElements = result.informationElements.clone();
                         mChannel.sendMessage(
                                 WifiScanner.CMD_FULL_SCAN_RESULT, 0, handler, newResult);
+                        reportedFullScanResult = true;
                     }
                 }
             }
+            if (mFullScanRequested && reportedFullScanResult) {
+                mFullScanWakeLock.acquire(SCAN_WAKE_LOCK_TIME_OUT_MSECS);
+            }
         }
 
         void reportPeriodChanged(int handler, ScanSettings settings, int newPeriodInMs) {
@@ -1410,9 +1441,10 @@
         PendingIntent mTimeoutIntent;
         ScanResult    mCurrentBssids[];
 
-        WifiChangeStateMachine(Looper looper) {
+        WifiChangeStateMachine(Looper looper, PowerManager powerManager) {
             super("SignificantChangeStateMachine", looper);
 
+            mClientInfo = new ClientInfoLocal();
             mClients.put(null, mClientInfo);
 
             addState(mDefaultState);
@@ -1748,7 +1780,7 @@
             sendMessage(WIFI_CHANGE_CMD_CHANGE_DETECTED, 0, 0, results);
         }
 
-        ClientInfo mClientInfo = new ClientInfoLocal();
+        ClientInfo mClientInfo;
         private static final int SCAN_COMMAND_ID = 1;
 
         void addScanRequest(ScanSettings settings) {
diff --git a/service/java/com/android/server/wifi/WifiStateMachine.java b/service/java/com/android/server/wifi/WifiStateMachine.java
index 04bafb0..2c543b7 100644
--- a/service/java/com/android/server/wifi/WifiStateMachine.java
+++ b/service/java/com/android/server/wifi/WifiStateMachine.java
@@ -344,6 +344,11 @@
     private int mSupplicantStopFailureToken = 0;
 
     /**
+     * Timeout for acquired wake lock while a scan is running
+     */
+    private static final int SCAN_WAKE_LOCK_TIME_OUT_MSECS = 5 * 1000;
+
+    /**
      * Tether state change notification time out
      */
     private static final int TETHER_NOTIFICATION_TIME_OUT_MSECS = 5000;
@@ -377,6 +382,9 @@
     // Wakelock held during wifi start/stop and driver load/unload
     private PowerManager.WakeLock mWakeLock;
 
+    // Wakelock held during wifi scan
+    private PowerManager.WakeLock mScanWakeLock;
+
     private Context mContext;
 
     private final Object mDhcpResultsLock = new Object();
@@ -1221,6 +1229,9 @@
         PowerManager powerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getName());
 
+        mScanWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiScan");
+        mScanWakeLock.setReferenceCounted(false);
+
         mSuspendWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WifiSuspend");
         mSuspendWakeLock.setReferenceCounted(false);
 
@@ -1810,6 +1821,8 @@
                 batteryWorkSource = new WorkSource(Process.WIFI_UID);
             }
 
+            mScanWakeLock.setWorkSource(batteryWorkSource);
+            mScanWakeLock.acquire(SCAN_WAKE_LOCK_TIME_OUT_MSECS);
             try {
                 mBatteryStats.noteWifiScanStartedFromSource(batteryWorkSource);
             } catch (RemoteException e) {
@@ -1840,6 +1853,8 @@
                 log(e.toString());
             } finally {
                 mScanWorkSource = null;
+                mScanWakeLock.release();
+                mScanWakeLock.setWorkSource(null);
             }
         }
     }