diff options
author | Robert Greenwalt <robdroid@android.com> | 2009-05-13 15:10:16 -0700 |
---|---|---|
committer | Robert Greenwalt <robdroid@android.com> | 2009-05-13 15:10:16 -0700 |
commit | 5347bd4cda2b6afc18f8acab48e52131f35ed13c (patch) | |
tree | af3c0e520ff5712344bd5174b7d02d24ef34c4e7 | |
parent | 6347c322b36cdf6a30a35e80d205d00d40368e61 (diff) | |
download | frameworks_base-5347bd4cda2b6afc18f8acab48e52131f35ed13c.zip frameworks_base-5347bd4cda2b6afc18f8acab48e52131f35ed13c.tar.gz frameworks_base-5347bd4cda2b6afc18f8acab48e52131f35ed13c.tar.bz2 |
Add wifi multicast filter api (enable/disable).
Fixes 1833432. Automatically re-disables any request when the app
exits/crashes. Also hooked into Battery Stats for power managment analysis.
-rw-r--r-- | core/java/android/os/BatteryStats.java | 11 | ||||
-rw-r--r-- | core/java/com/android/internal/app/IBatteryStats.aidl | 2 | ||||
-rw-r--r-- | core/java/com/android/internal/os/BatteryStatsImpl.java | 58 | ||||
-rw-r--r-- | services/java/com/android/server/WifiService.java | 135 | ||||
-rw-r--r-- | services/java/com/android/server/am/BatteryStatsService.java | 14 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/IWifiManager.aidl | 6 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/WifiManager.java | 61 | ||||
-rw-r--r-- | wifi/java/android/net/wifi/WifiStateTracker.java | 14 |
8 files changed, 273 insertions, 28 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index 333ba73..8a0fd58 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -61,6 +61,13 @@ public abstract class BatteryStats implements Parcelable { */ public static final int SCAN_WIFI_LOCK = 6; + /** + * A constant indicating a wifi multicast timer + * + * {@hide} + */ + public static final int WIFI_MULTICAST_ENABLED = 7; + /** * Include all of the data in the stats, including previously saved data. */ @@ -225,9 +232,13 @@ public abstract class BatteryStats implements Parcelable { public abstract void noteFullWifiLockReleasedLocked(); public abstract void noteScanWifiLockAcquiredLocked(); public abstract void noteScanWifiLockReleasedLocked(); + public abstract void noteWifiMulticastEnabledLocked(); + public abstract void noteWifiMulticastDisabledLocked(); public abstract long getWifiTurnedOnTime(long batteryRealtime, int which); public abstract long getFullWifiLockTime(long batteryRealtime, int which); public abstract long getScanWifiLockTime(long batteryRealtime, int which); + public abstract long getWifiMulticastTime(long batteryRealtime, + int which); /** * Note that these must match the constants in android.os.LocalPowerManager. diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl index 9ce532c..e1ff2a5 100644 --- a/core/java/com/android/internal/app/IBatteryStats.aidl +++ b/core/java/com/android/internal/app/IBatteryStats.aidl @@ -45,6 +45,8 @@ interface IBatteryStats { void noteFullWifiLockReleased(int uid); void noteScanWifiLockAcquired(int uid); void noteScanWifiLockReleased(int uid); + void noteWifiMulticastEnabled(int uid); + void noteWifiMulticastDisabled(int uid); void setOnBattery(boolean onBattery, int level); void recordCurrentLevel(int level); long getAwakeTimeBattery(); diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 1218fe3..e8356a2 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -1115,7 +1115,21 @@ public final class BatteryStatsImpl extends BatteryStats { u.noteScanWifiLockReleasedLocked(); } } - + + public void noteWifiMulticastEnabledLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteWifiMulticastEnabledLocked(); + } + } + + public void noteWifiMulticastDisabledLocked(int uid) { + Uid u = mUidStats.get(uid); + if (u != null) { + u.noteWifiMulticastDisabledLocked(); + } + } + @Override public long getScreenOnTime(long batteryRealtime, int which) { return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which); } @@ -1200,7 +1214,10 @@ public final class BatteryStatsImpl extends BatteryStats { boolean mScanWifiLockOut; StopwatchTimer mScanWifiLockTimer; - + + boolean mWifiMulticastEnabled; + StopwatchTimer mWifiMulticastTimer; + Counter[] mUserActivityCounters; /** @@ -1228,6 +1245,8 @@ public final class BatteryStatsImpl extends BatteryStats { mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables); mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables); mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables); + mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, + null, mUnpluggables); } @Override @@ -1334,7 +1353,23 @@ public final class BatteryStatsImpl extends BatteryStats { mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this); } } - + + @Override + public void noteWifiMulticastEnabledLocked() { + if (!mWifiMulticastEnabled) { + mWifiMulticastEnabled = true; + mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this); + } + } + + @Override + public void noteWifiMulticastDisabledLocked() { + if (mWifiMulticastEnabled) { + mWifiMulticastEnabled = false; + mWifiMulticastTimer.stopRunningLocked(BatteryStatsImpl.this); + } + } + @Override public long getWifiTurnedOnTime(long batteryRealtime, int which) { return mWifiTurnedOnTimer.getTotalTimeLocked(batteryRealtime, which); @@ -1349,7 +1384,13 @@ public final class BatteryStatsImpl extends BatteryStats { public long getScanWifiLockTime(long batteryRealtime, int which) { return mScanWifiLockTimer.getTotalTimeLocked(batteryRealtime, which); } - + + @Override + public long getWifiMulticastTime(long batteryRealtime, int which) { + return mWifiMulticastTimer.getTotalTimeLocked(batteryRealtime, + which); + } + @Override public void noteUserActivityLocked(int type) { if (mUserActivityCounters == null) { @@ -1423,6 +1464,7 @@ public final class BatteryStatsImpl extends BatteryStats { mWifiTurnedOnTimer.writeToParcel(out, batteryRealtime); mFullWifiLockTimer.writeToParcel(out, batteryRealtime); mScanWifiLockTimer.writeToParcel(out, batteryRealtime); + mWifiMulticastTimer.writeToParcel(out, batteryRealtime); if (mUserActivityCounters == null) { out.writeInt(0); } else { @@ -1482,6 +1524,9 @@ public final class BatteryStatsImpl extends BatteryStats { mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables, in); mScanWifiLockOut = false; mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables, in); + mWifiMulticastEnabled = false; + mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED, + null, mUnpluggables, in); if (in.readInt() == 0) { mUserActivityCounters = null; } else { @@ -2709,7 +2754,9 @@ public final class BatteryStatsImpl extends BatteryStats { u.mFullWifiLockTimer.readSummaryFromParcelLocked(in); u.mScanWifiLockOut = false; u.mScanWifiLockTimer.readSummaryFromParcelLocked(in); - + u.mWifiMulticastEnabled = false; + u.mWifiMulticastTimer.readSummaryFromParcelLocked(in); + if (in.readInt() != 0) { if (u.mUserActivityCounters == null) { u.initUserActivityLocked(); @@ -2842,6 +2889,7 @@ public final class BatteryStatsImpl extends BatteryStats { u.mWifiTurnedOnTimer.writeSummaryFromParcelLocked(out, NOWREAL); u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL); + u.mWifiMulticastTimer.writeSummaryFromParcelLocked(out, NOWREAL); if (u.mUserActivityCounters == null) { out.writeInt(0); diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java index 8850c31..348f0a1 100644 --- a/services/java/com/android/server/WifiService.java +++ b/services/java/com/android/server/WifiService.java @@ -96,6 +96,11 @@ public class WifiService extends IWifiManager.Stub { private int mScanLocksAcquired; private int mScanLocksReleased; + private final List<WifiMulticaster> mMulticasters = + new ArrayList<WifiMulticaster>(); + private int mMulticastEnabled; + private int mMulticastDisabled; + private final IBatteryStats mBatteryStats; /** @@ -1727,21 +1732,9 @@ public class WifiService extends IWifiManager.Stub { } } - private class WifiLock implements IBinder.DeathRecipient { - String mTag; - int mLockMode; - IBinder mBinder; - + private class WifiLock extends WifiDeathRecipient { WifiLock(int lockMode, String tag, IBinder binder) { - super(); - mTag = tag; - mLockMode = lockMode; - mBinder = binder; - try { - mBinder.linkToDeath(this, 0); - } catch (RemoteException e) { - binderDied(); - } + super(lockMode, tag, binder); } public void binderDied() { @@ -1751,7 +1744,7 @@ public class WifiService extends IWifiManager.Stub { } public String toString() { - return "WifiLock{" + mTag + " type=" + mLockMode + " binder=" + mBinder + "}"; + return "WifiLock{" + mTag + " type=" + mMode + " binder=" + mBinder + "}"; } } @@ -1771,7 +1764,7 @@ public class WifiService extends IWifiManager.Stub { return WifiManager.WIFI_MODE_FULL; } for (WifiLock l : mList) { - if (l.mLockMode == WifiManager.WIFI_MODE_FULL) { + if (l.mMode == WifiManager.WIFI_MODE_FULL) { return WifiManager.WIFI_MODE_FULL; } } @@ -1826,7 +1819,7 @@ public class WifiService extends IWifiManager.Stub { int uid = Binder.getCallingUid(); long ident = Binder.clearCallingIdentity(); try { - switch(wifiLock.mLockMode) { + switch(wifiLock.mMode) { case WifiManager.WIFI_MODE_FULL: ++mFullLocksAcquired; mBatteryStats.noteFullWifiLockAcquired(uid); @@ -1862,7 +1855,7 @@ public class WifiService extends IWifiManager.Stub { int uid = Binder.getCallingUid(); long ident = Binder.clearCallingIdentity(); try { - switch(wifiLock.mLockMode) { + switch(wifiLock.mMode) { case WifiManager.WIFI_MODE_FULL: ++mFullLocksReleased; mBatteryStats.noteFullWifiLockReleased(uid); @@ -1881,4 +1874,110 @@ public class WifiService extends IWifiManager.Stub { updateWifiState(); return hadLock; } + + private abstract class WifiDeathRecipient + implements IBinder.DeathRecipient { + String mTag; + int mMode; + IBinder mBinder; + + WifiDeathRecipient(int mode, String tag, IBinder binder) { + super(); + mTag = tag; + mMode = mode; + mBinder = binder; + try { + mBinder.linkToDeath(this, 0); + } catch (RemoteException e) { + binderDied(); + } + } + } + + private class WifiMulticaster extends WifiDeathRecipient { + WifiMulticaster(String tag, IBinder binder) { + super(Binder.getCallingUid(), tag, binder); + } + + public void binderDied() { + Log.e(TAG, "WifiMulticaster binderDied"); + synchronized (mMulticasters) { + int i = mMulticasters.indexOf(this); + if (i != -1) { + removeMulticasterLocked(i, mMode); + } + } + } + + public String toString() { + return "WifiMulticaster{" + mTag + " binder=" + mBinder + "}"; + } + + public int getUid() { + return mMode; + } + } + + public void enableWifiMulticast(IBinder binder, String tag) { + enforceChangePermission(); + + synchronized (mMulticasters) { + mMulticastEnabled++; + mMulticasters.add(new WifiMulticaster(tag, binder)); + // Note that we could call stopPacketFiltering only when + // our new size == 1 (first call), but this function won't + // be called often and by making the stopPacket call each + // time we're less fragile and self-healing. + WifiNative.stopPacketFiltering(); + } + + int uid = Binder.getCallingUid(); + Long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteWifiMulticastEnabled(uid); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + public void disableWifiMulticast() { + enforceChangePermission(); + + int uid = Binder.getCallingUid(); + synchronized (mMulticasters) { + mMulticastDisabled++; + int size = mMulticasters.size(); + for (int i = size - 1; i >= 0; i--) { + WifiMulticaster m = mMulticasters.get(i); + if ((m != null) && (m.getUid() == uid)) { + removeMulticasterLocked(i, uid); + } + } + } + } + + private void removeMulticasterLocked(int i, int uid) + { + mMulticasters.remove(i); + if (mMulticasters.size() == 0) { + WifiNative.startPacketFiltering(); + } + + Long ident = Binder.clearCallingIdentity(); + try { + mBatteryStats.noteWifiMulticastDisabled(uid); + } catch (RemoteException e) { + } finally { + Binder.restoreCallingIdentity(ident); + } + } + + public boolean isWifiMulticastEnabled() { + enforceAccessPermission(); + + synchronized (mMulticasters) { + return (mMulticasters.size() > 0); + } + } } diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java index a21893b..0387be5 100644 --- a/services/java/com/android/server/am/BatteryStatsService.java +++ b/services/java/com/android/server/am/BatteryStatsService.java @@ -261,6 +261,20 @@ public final class BatteryStatsService extends IBatteryStats.Stub { } } + public void noteWifiMulticastEnabled(int uid) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteWifiMulticastEnabledLocked(uid); + } + } + + public void noteWifiMulticastDisabled(int uid) { + enforceCallingPermission(); + synchronized (mStats) { + mStats.noteWifiMulticastDisabledLocked(uid); + } + } + public boolean isOnBattery() { return mStats.isOnBattery(); } diff --git a/wifi/java/android/net/wifi/IWifiManager.aidl b/wifi/java/android/net/wifi/IWifiManager.aidl index f9a0845..00829d6 100644 --- a/wifi/java/android/net/wifi/IWifiManager.aidl +++ b/wifi/java/android/net/wifi/IWifiManager.aidl @@ -69,5 +69,11 @@ interface IWifiManager boolean acquireWifiLock(IBinder lock, int lockType, String tag); boolean releaseWifiLock(IBinder lock); + + boolean isWifiMulticastEnabled(); + + void enableWifiMulticast(IBinder binder, String tag); + + void disableWifiMulticast(); } diff --git a/wifi/java/android/net/wifi/WifiManager.java b/wifi/java/android/net/wifi/WifiManager.java index a51e88f..658a7b2 100644 --- a/wifi/java/android/net/wifi/WifiManager.java +++ b/wifi/java/android/net/wifi/WifiManager.java @@ -823,4 +823,65 @@ public class WifiManager { public WifiLock createWifiLock(String tag) { return new WifiLock(WIFI_MODE_FULL, tag); } + + /** + * Check multicast filter status. + * + * @return true if multicast packets are allowed. + * + * @hide pending API council approval + */ + public boolean isWifiMulticastEnabled() { + try { + return mService.isWifiMulticastEnabled(); + } catch (RemoteException e) { + return false; + } + } + + /** + * Turn on the reception of multicast packets. + * The default behavior is to disable multicast packets as they + * have a noticable negative effect on battery life. An + * application can turn them on, but should not leave it on for longer + * than needed. When the app quits (or crashes) its request will + * be reverted. + * + * @param tag a string associated with this request for debugging. + * + * @return true on success + * + * @see #disableWifiMulticast + * + * @hide pending API council approval + */ + public boolean enableWifiMulticast(String tag) { + try { + mService.enableWifiMulticast(new Binder(), tag); + return true; + } catch (RemoteException e) { + return false; + } + } + + /** + * Return to the default multicast-off setting. + * Note that if others had turned on Multicast reception, your + * call will not turn it back off - they must also turn off their + * request for multicast reception. + * + * @return true on success + * + * @see #enableWifiMulticast + * + * @hide pending API council approval + */ + public boolean disableWifiMulticast() { + try { + mService.disableWifiMulticast(); + return true; + } catch (RemoteException e) { + return false; + } + } } diff --git a/wifi/java/android/net/wifi/WifiStateTracker.java b/wifi/java/android/net/wifi/WifiStateTracker.java index 6ea35f5..64084cf 100644 --- a/wifi/java/android/net/wifi/WifiStateTracker.java +++ b/wifi/java/android/net/wifi/WifiStateTracker.java @@ -732,15 +732,19 @@ public class WifiStateTracker extends NetworkStateTracker { /* * Filter out multicast packets. This saves battery power, since * the CPU doesn't have to spend time processing packets that - * are going to end up being thrown away. Obviously, if we - * ever want to support multicast, this will have to change. + * are going to end up being thrown away. + * + * Note that rather than turn this off directly, we use the + * public api - this keeps us all in sync - turn multicast on + * first and then off.. if nobody else wants it on it'll be + * off then and it's all synchronized within the API. */ + mWM.enableWifiMulticast("WifiStateTracker"); + mWM.disableWifiMulticast(); + if (mBluetoothA2dp == null) { mBluetoothA2dp = new BluetoothA2dp(mContext); } - synchronized (this) { - WifiNative.startPacketFiltering(); - } checkIsBluetoothPlaying(); break; |