summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--core/jni/android_net_wifi_Wifi.cpp10
-rw-r--r--services/java/com/android/server/WifiService.java51
-rw-r--r--wifi/java/android/net/wifi/WifiManager.java15
-rw-r--r--wifi/java/android/net/wifi/WifiNative.java2
-rw-r--r--wifi/java/android/net/wifi/WifiStateTracker.java103
5 files changed, 163 insertions, 18 deletions
diff --git a/core/jni/android_net_wifi_Wifi.cpp b/core/jni/android_net_wifi_Wifi.cpp
index 7392442..903283e 100644
--- a/core/jni/android_net_wifi_Wifi.cpp
+++ b/core/jni/android_net_wifi_Wifi.cpp
@@ -493,6 +493,15 @@ static jboolean android_net_wifi_clearBlacklistCommand(JNIEnv* env, jobject claz
return doBooleanCommand("BLACKLIST clear", "OK");
}
+static jboolean android_net_wifi_setSuspendOptimizationsCommand(JNIEnv* env, jobject clazz, jboolean enabled)
+{
+ char cmdstr[25];
+
+ snprintf(cmdstr, sizeof(cmdstr), "DRIVER SETSUSPEND %d", enabled ? 0 : 1);
+ return doBooleanCommand(cmdstr, "OK");
+}
+
+
static jboolean android_net_wifi_doDhcpRequest(JNIEnv* env, jobject clazz, jobject info)
{
jint ipaddr, gateway, mask, dns1, dns2, server, lease;
@@ -571,6 +580,7 @@ static JNINativeMethod gWifiMethods[] = {
{ "setScanResultHandlingCommand", "(I)Z", (void*) android_net_wifi_setScanResultHandlingCommand },
{ "addToBlacklistCommand", "(Ljava/lang/String;)Z", (void*) android_net_wifi_addToBlacklistCommand },
{ "clearBlacklistCommand", "()Z", (void*) android_net_wifi_clearBlacklistCommand },
+ { "setSuspendOptimizationsCommand", "(Z)Z", (void*) android_net_wifi_setSuspendOptimizationsCommand},
{ "doDhcpRequest", "(Landroid/net/DhcpInfo;)Z", (void*) android_net_wifi_doDhcpRequest },
{ "getDhcpError", "()Ljava/lang/String;", (void*) android_net_wifi_getDhcpError },
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index 509c789..af4d7e4 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -116,6 +116,8 @@ public class WifiService extends IWifiManager.Stub {
private final LockList mLocks = new LockList();
// some wifi lock statistics
+ private int mFullHighPerfLocksAcquired;
+ private int mFullHighPerfLocksReleased;
private int mFullLocksAcquired;
private int mFullLocksReleased;
private int mScanLocksAcquired;
@@ -1782,8 +1784,8 @@ public class WifiService extends IWifiManager.Stub {
msg.sendToTarget();
}
- private void sendStartMessage(boolean scanOnlyMode) {
- Message.obtain(mWifiHandler, MESSAGE_START_WIFI, scanOnlyMode ? 1 : 0, 0).sendToTarget();
+ private void sendStartMessage(int lockMode) {
+ Message.obtain(mWifiHandler, MESSAGE_START_WIFI, lockMode, 0).sendToTarget();
}
private void sendAccessPointMessage(boolean enable, WifiConfiguration wifiConfig, int uid) {
@@ -1801,12 +1803,15 @@ public class WifiService extends IWifiManager.Stub {
boolean wifiEnabled = getPersistedWifiEnabled();
boolean airplaneMode = isAirplaneModeOn() && !mAirplaneModeOverwridden;
boolean lockHeld = mLocks.hasLocks();
- int strongestLockMode;
+ int strongestLockMode = WifiManager.WIFI_MODE_FULL;
boolean wifiShouldBeEnabled = wifiEnabled && !airplaneMode;
boolean wifiShouldBeStarted = !mDeviceIdle || lockHeld;
- if (mDeviceIdle && lockHeld) {
+
+ if (lockHeld) {
strongestLockMode = mLocks.getStrongestLockMode();
- } else {
+ }
+ /* If device is not idle, lockmode cannot be scan only */
+ if (!mDeviceIdle && strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY) {
strongestLockMode = WifiManager.WIFI_MODE_FULL;
}
@@ -1827,7 +1832,7 @@ public class WifiService extends IWifiManager.Stub {
sWakeLock.acquire();
sendEnableMessage(true, false, mLastEnableUid);
sWakeLock.acquire();
- sendStartMessage(strongestLockMode == WifiManager.WIFI_MODE_SCAN_ONLY);
+ sendStartMessage(strongestLockMode);
} else if (!mWifiStateTracker.isDriverStopped()) {
int wakeLockTimeout =
Settings.Secure.getInt(
@@ -1905,8 +1910,10 @@ public class WifiService extends IWifiManager.Stub {
break;
case MESSAGE_START_WIFI:
- mWifiStateTracker.setScanOnlyMode(msg.arg1 != 0);
+ mWifiStateTracker.setScanOnlyMode(msg.arg1 == WifiManager.WIFI_MODE_SCAN_ONLY);
mWifiStateTracker.restart();
+ mWifiStateTracker.setHighPerfMode(msg.arg1 ==
+ WifiManager.WIFI_MODE_FULL_HIGH_PERF);
sWakeLock.release();
break;
@@ -1986,8 +1993,10 @@ public class WifiService extends IWifiManager.Stub {
}
pw.println();
pw.println("Locks acquired: " + mFullLocksAcquired + " full, " +
+ mFullHighPerfLocksAcquired + " full high perf, " +
mScanLocksAcquired + " scan");
pw.println("Locks released: " + mFullLocksReleased + " full, " +
+ mFullHighPerfLocksReleased + " full high perf, " +
mScanLocksReleased + " scan");
pw.println();
pw.println("Locks held:");
@@ -2042,11 +2051,15 @@ public class WifiService extends IWifiManager.Stub {
if (mList.isEmpty()) {
return WifiManager.WIFI_MODE_FULL;
}
- for (WifiLock l : mList) {
- if (l.mMode == WifiManager.WIFI_MODE_FULL) {
- return WifiManager.WIFI_MODE_FULL;
- }
+
+ if (mFullHighPerfLocksAcquired > mFullHighPerfLocksReleased) {
+ return WifiManager.WIFI_MODE_FULL_HIGH_PERF;
}
+
+ if (mFullLocksAcquired > mFullLocksReleased) {
+ return WifiManager.WIFI_MODE_FULL;
+ }
+
return WifiManager.WIFI_MODE_SCAN_ONLY;
}
@@ -2085,7 +2098,11 @@ public class WifiService extends IWifiManager.Stub {
public boolean acquireWifiLock(IBinder binder, int lockMode, String tag) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
- if (lockMode != WifiManager.WIFI_MODE_FULL && lockMode != WifiManager.WIFI_MODE_SCAN_ONLY) {
+ if (lockMode != WifiManager.WIFI_MODE_FULL &&
+ lockMode != WifiManager.WIFI_MODE_SCAN_ONLY &&
+ lockMode != WifiManager.WIFI_MODE_FULL_HIGH_PERF) {
+ Slog.e(TAG, "Illegal argument, lockMode= " + lockMode);
+ if (DBG) throw new IllegalArgumentException("lockMode=" + lockMode);
return false;
}
WifiLock wifiLock = new WifiLock(lockMode, tag, binder);
@@ -2107,6 +2124,12 @@ public class WifiService extends IWifiManager.Stub {
++mFullLocksAcquired;
mBatteryStats.noteFullWifiLockAcquired(uid);
break;
+ case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
+ ++mFullHighPerfLocksAcquired;
+ /* Treat high power as a full lock for battery stats */
+ mBatteryStats.noteFullWifiLockAcquired(uid);
+ break;
+
case WifiManager.WIFI_MODE_SCAN_ONLY:
++mScanLocksAcquired;
mBatteryStats.noteScanWifiLockAcquired(uid);
@@ -2146,6 +2169,10 @@ public class WifiService extends IWifiManager.Stub {
++mFullLocksReleased;
mBatteryStats.noteFullWifiLockReleased(uid);
break;
+ case WifiManager.WIFI_MODE_FULL_HIGH_PERF:
+ ++mFullHighPerfLocksReleased;
+ mBatteryStats.noteFullWifiLockReleased(uid);
+ break;
case WifiManager.WIFI_MODE_SCAN_ONLY:
++mScanLocksReleased;
mBatteryStats.noteScanWifiLockReleased(uid);
diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java
index 4a22b68..3b41dc1 100644
--- a/wifi/java/android/net/wifi/WifiManager.java
+++ b/wifi/java/android/net/wifi/WifiManager.java
@@ -307,6 +307,16 @@ public class WifiManager {
public static final String ACTION_PICK_WIFI_NETWORK = "android.net.wifi.PICK_WIFI_NETWORK";
/**
+ * In this Wi-Fi lock mode, Wi-Fi will behave as in the mode
+ * {@link #WIFI_MODE_FULL} but it operates at high performance
+ * at the expense of power. This mode should be used
+ * only when the wifi connection needs to have minimum loss and low
+ * latency as it can impact the battery life.
+ * @hide
+ */
+ public static final int WIFI_MODE_FULL_HIGH_PERF = 3;
+
+ /**
* In this Wi-Fi lock mode, Wi-Fi will be kept active,
* and will behave normally, i.e., it will attempt to automatically
* establish a connection to a remembered access point that is
@@ -993,8 +1003,9 @@ public class WifiManager {
/**
* Creates a new WifiLock.
*
- * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL} and
- * {@link #WIFI_MODE_SCAN_ONLY} for descriptions of the types of Wi-Fi locks.
+ * @param lockType the type of lock to create. See {@link #WIFI_MODE_FULL},
+ * {@link #WIFI_MODE_SCAN_ONLY} and {@link #WIFI_MODE_FULL_HIGH_PERF} for descriptions
+ * of the types of Wi-Fi locks.
* @param tag a tag for the WifiLock to identify it in debugging messages. This string is
* never shown to the user under normal conditions, but should be descriptive
* enough to identify your application and the specific WifiLock within it, if it
diff --git a/wifi/java/android/net/wifi/WifiNative.java b/wifi/java/android/net/wifi/WifiNative.java
index 7a3282c..25f05c0 100644
--- a/wifi/java/android/net/wifi/WifiNative.java
+++ b/wifi/java/android/net/wifi/WifiNative.java
@@ -149,6 +149,8 @@ public class WifiNative {
public native static String getDhcpError();
+ public native static boolean setSuspendOptimizationsCommand(boolean enabled);
+
/**
* Wait for the supplicant to send an event, returning the event string.
* @return the event string sent by the supplicant.
diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java
index f57df62..0cc1f46 100644
--- a/wifi/java/android/net/wifi/WifiStateTracker.java
+++ b/wifi/java/android/net/wifi/WifiStateTracker.java
@@ -276,6 +276,9 @@ public class WifiStateTracker extends NetworkStateTracker {
private boolean mIsScanModeActive;
private boolean mEnableRssiPolling;
+ private boolean mIsHighPerfEnabled;
+ private int mPowerModeRefCount = 0;
+ private int mOptimizationsDisabledRefCount = 0;
/**
* One of {@link WifiManager#WIFI_STATE_DISABLED},
@@ -659,6 +662,67 @@ public class WifiStateTracker extends NetworkStateTracker {
}
}
+ /**
+ * Set suspend mode optimizations. These include:
+ * - packet filtering
+ * - turn off roaming
+ * - DTIM settings
+ *
+ * Uses reference counting to keep the suspend optimizations disabled
+ * as long as one entity wants optimizations disabled.
+ *
+ * For example, WifiLock can keep suspend optimizations disabled
+ * or the user setting (wifi never sleeps) can keep suspend optimizations
+ * disabled. As long as one entity wants it disabled, it should stay
+ * that way
+ *
+ * @param enabled true if optimizations need enabled, false otherwise
+ */
+ public synchronized void setSuspendModeOptimizations(boolean enabled) {
+
+ /* It is good to plumb suspend optimization enable
+ * or disable even if ref count indicates already done
+ * since we could have a case of previous failure.
+ */
+ if (!enabled) {
+ mOptimizationsDisabledRefCount++;
+ } else {
+ mOptimizationsDisabledRefCount--;
+ if (mOptimizationsDisabledRefCount > 0) {
+ return;
+ } else {
+ /* Keep refcount from becoming negative */
+ mOptimizationsDisabledRefCount = 0;
+ }
+ }
+
+ if (mWifiState.get() != WIFI_STATE_ENABLED || isDriverStopped()) {
+ return;
+ }
+
+ WifiNative.setSuspendOptimizationsCommand(enabled);
+ }
+
+
+ /**
+ * Set high performance mode of operation. This would mean
+ * use active power mode and disable suspend optimizations
+ * @param enabled true if enabled, false otherwise
+ */
+ public synchronized void setHighPerfMode(boolean enabled) {
+ if (mIsHighPerfEnabled != enabled) {
+ if (enabled) {
+ setPowerMode(DRIVER_POWER_MODE_ACTIVE);
+ setSuspendModeOptimizations(false);
+ } else {
+ setPowerMode(DRIVER_POWER_MODE_AUTO);
+ setSuspendModeOptimizations(true);
+ }
+ mIsHighPerfEnabled = enabled;
+ Log.d(TAG,"high performance mode: " + enabled);
+ }
+ }
+
private void checkIsBluetoothPlaying() {
boolean isBluetoothPlaying = false;
@@ -744,6 +808,9 @@ public class WifiStateTracker extends NetworkStateTracker {
dhcpThread.start();
mDhcpTarget = new DhcpHandler(dhcpThread.getLooper(), this);
mIsScanModeActive = true;
+ mIsHighPerfEnabled = false;
+ mOptimizationsDisabledRefCount = 0;
+ mPowerModeRefCount = 0;
mTornDownByConnMgr = false;
mLastBssid = null;
mLastSsid = null;
@@ -1947,13 +2014,41 @@ public class WifiStateTracker extends NetworkStateTracker {
* @param mode
* DRIVER_POWER_MODE_AUTO
* DRIVER_POWER_MODE_ACTIVE
- * @return {@code true} if the operation succeeds, {@code false} otherwise
+ *
+ * Uses reference counting to keep power mode active
+ * as long as one entity wants power mode to be active.
+ *
+ * For example, WifiLock high perf mode can keep power mode active
+ * or a DHCP session can keep it active. As long as one entity wants
+ * it enabled, it should stay that way
+ *
*/
- public synchronized boolean setPowerMode(int mode) {
+ private synchronized void setPowerMode(int mode) {
+
+ /* It is good to plumb power mode change
+ * even if ref count indicates already done
+ * since we could have a case of previous failure.
+ */
+ switch(mode) {
+ case DRIVER_POWER_MODE_ACTIVE:
+ mPowerModeRefCount++;
+ break;
+ case DRIVER_POWER_MODE_AUTO:
+ mPowerModeRefCount--;
+ if (mPowerModeRefCount > 0) {
+ return;
+ } else {
+ /* Keep refcount from becoming negative */
+ mPowerModeRefCount = 0;
+ }
+ break;
+ }
+
if (mWifiState.get() != WIFI_STATE_ENABLED || isDriverStopped()) {
- return false;
+ return;
}
- return WifiNative.setPowerModeCommand(mode);
+
+ WifiNative.setPowerModeCommand(mode);
}
/**