Merge change 1590 into donut

* changes:
  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.
This commit is contained in:
Android (Google) Code Review
2009-05-14 13:24:52 -07:00
8 changed files with 273 additions and 28 deletions

View File

@@ -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.

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);
}
}
}

View File

@@ -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();
}

View File

@@ -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();
}

View File

@@ -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;
}
}
}

View File

@@ -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;