diff options
| author | 2009-05-13 15:10:16 -0700 | |
|---|---|---|
| committer | 2009-05-13 15:10:16 -0700 | |
| commit | 5347bd4cda2b6afc18f8acab48e52131f35ed13c (patch) | |
| tree | af3c0e520ff5712344bd5174b7d02d24ef34c4e7 | |
| parent | 6347c322b36cdf6a30a35e80d205d00d40368e61 (diff) | |
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 333ba731742e..8a0fd58530b0 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 9ce532c49577..e1ff2a52062f 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 1218fe37cf7f..e8356a2c6415 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 8850c3123e22..348f0a19c717 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 a21893bbb44c..0387be5285fd 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 f9a0845f12ea..00829d6deedc 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 a51e88f978e9..658a7b24805b 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 6ea35f58be02..64084cf403c3 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; |