Merge "Watch network subtype, tethering teardown, empty."

This commit is contained in:
Jeff Sharkey
2011-09-25 23:44:10 -07:00
committed by Android (Google) Code Review
6 changed files with 102 additions and 30 deletions

View File

@@ -270,6 +270,11 @@ public class NetworkStatsHistory implements Parcelable {
|| entry.operations < 0) {
throw new IllegalArgumentException("tried recording negative data");
}
if (entry.rxBytes == 0 && entry.rxPackets == 0 && entry.txBytes == 0 && entry.txPackets == 0
&& entry.operations == 0) {
// nothing to record; skip
return;
}
// create any buckets needed by this range
ensureBuckets(start, end);

View File

@@ -35,6 +35,7 @@ import android.net.EthernetDataTracker;
import android.net.IConnectivityManager;
import android.net.INetworkPolicyListener;
import android.net.INetworkPolicyManager;
import android.net.INetworkStatsService;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.LinkProperties.CompareResult;
@@ -306,8 +307,8 @@ public class ConnectivityService extends IConnectivityManager.Stub {
// the set of network types that can only be enabled by system/sig apps
List mProtectedNetworks;
public ConnectivityService(
Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
public ConnectivityService(Context context, INetworkManagementService netd,
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
if (DBG) log("ConnectivityService starting up");
HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
@@ -496,7 +497,7 @@ public class ConnectivityService extends IConnectivityManager.Stub {
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
mTethering = new Tethering(mContext, nmService, mHandler.getLooper());
mTethering = new Tethering(mContext, nmService, statsService, mHandler.getLooper());
mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
mTethering.getTetherableWifiRegexs().length != 0 ||
mTethering.getTetherableBluetoothRegexs().length != 0) &&

View File

@@ -364,7 +364,8 @@ class ServerThread extends Thread {
try {
Slog.i(TAG, "Connectivity Service");
connectivity = new ConnectivityService(context, networkManagement, networkPolicy);
connectivity = new ConnectivityService(
context, networkManagement, networkStats, networkPolicy);
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
networkStats.bindConnectivityManager(connectivity);
networkPolicy.bindConnectivityManager(connectivity);

View File

@@ -29,6 +29,7 @@ import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
import android.net.INetworkStatsService;
import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
@@ -88,7 +89,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
// upstream type list and the DUN_REQUIRED secure-setting
private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
private INetworkManagementService mNMService;
private final INetworkManagementService mNMService;
private final INetworkStatsService mStatsService;
private Looper mLooper;
private HandlerThread mThread;
@@ -124,9 +126,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
private boolean mUsbTetherRequested; // true if USB tethering should be started
// when RNDIS is enabled
public Tethering(Context context, INetworkManagementService nmService, Looper looper) {
public Tethering(Context context, INetworkManagementService nmService,
INetworkStatsService statsService, Looper looper) {
mContext = context;
mNMService = nmService;
mStatsService = statsService;
mLooper = looper;
mIfaces = new HashMap<String, TetherInterfaceSM>();
@@ -913,6 +917,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
case CMD_INTERFACE_DOWN:
if (mMyUpstreamIfaceName != null) {
try {
// about to tear down NAT; gather remaining statistics
mStatsService.forceUpdate();
mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
mMyUpstreamIfaceName = null;
} catch (Exception e) {
@@ -957,6 +964,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
}
if (mMyUpstreamIfaceName != null) {
try {
// about to tear down NAT; gather remaining statistics
mStatsService.forceUpdate();
mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
mMyUpstreamIfaceName = null;
} catch (Exception e) {
@@ -995,6 +1005,9 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
case CMD_TETHER_MODE_DEAD:
if (mMyUpstreamIfaceName != null) {
try {
// about to tear down NAT; gather remaining statistics
mStatsService.forceUpdate();
mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
mMyUpstreamIfaceName = null;
} catch (Exception e) {

View File

@@ -24,8 +24,8 @@ import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
import static android.content.Intent.ACTION_SHUTDOWN;
import static android.content.Intent.ACTION_UID_REMOVED;
import static android.content.Intent.EXTRA_UID;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
import static android.net.NetworkStats.IFACE_ALL;
import static android.net.NetworkStats.SET_ALL;
import static android.net.NetworkStats.SET_DEFAULT;
@@ -43,9 +43,12 @@ import static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL;
import static android.provider.Settings.Secure.NETSTATS_TAG_MAX_HISTORY;
import static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION;
import static android.provider.Settings.Secure.NETSTATS_UID_MAX_HISTORY;
import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
import static android.telephony.PhoneStateListener.LISTEN_NONE;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import static com.android.internal.util.Preconditions.checkNotNull;
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
@@ -80,6 +83,7 @@ import android.os.PowerManager;
import android.os.RemoteException;
import android.os.SystemClock;
import android.provider.Settings;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.EventLog;
import android.util.Log;
@@ -121,7 +125,7 @@ import libcore.io.IoUtils;
*/
public class NetworkStatsService extends INetworkStatsService.Stub {
private static final String TAG = "NetworkStats";
private static final boolean LOGD = true;
private static final boolean LOGD = false;
private static final boolean LOGV = false;
/** File header magic number: "ANET" */
@@ -132,7 +136,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private static final int VERSION_UID_WITH_TAG = 3;
private static final int VERSION_UID_WITH_SET = 4;
private static final int MSG_PERFORM_POLL = 0x1;
private static final int MSG_PERFORM_POLL = 1;
private static final int MSG_UPDATE_IFACES = 2;
/** Flags to control detail level of poll event. */
private static final int FLAG_PERSIST_NETWORK = 0x10;
@@ -144,6 +149,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final INetworkManagementService mNetworkManager;
private final IAlarmManager mAlarmManager;
private final TrustedTime mTime;
private final TelephonyManager mTeleManager;
private final NetworkStatsSettings mSettings;
private final PowerManager.WakeLock mWakeLock;
@@ -227,6 +233,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager");
mTime = checkNotNull(time, "missing TrustedTime");
mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
final PowerManager powerManager = (PowerManager) context.getSystemService(
@@ -279,6 +286,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
// ignored; service lives in system_server
}
// watch for networkType changes that aren't broadcast through
// CONNECTIVITY_ACTION_IMMEDIATE above.
mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
registerPollAlarmLocked();
registerGlobalAlert();
@@ -288,10 +299,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private void shutdownLocked() {
mContext.unregisterReceiver(mConnReceiver);
mContext.unregisterReceiver(mTetherReceiver);
mContext.unregisterReceiver(mPollReceiver);
mContext.unregisterReceiver(mRemovedReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
mTeleManager.listen(mPhoneListener, LISTEN_NONE);
writeNetworkStatsLocked();
if (mUidStatsLoaded) {
writeUidStatsLocked();
@@ -535,14 +549,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
public void onReceive(Context context, Intent intent) {
// on background handler thread, and verified CONNECTIVITY_INTERNAL
// permission above.
synchronized (mStatsLock) {
mWakeLock.acquire();
try {
updateIfacesLocked();
} finally {
mWakeLock.release();
}
}
updateIfaces();
}
};
@@ -619,6 +626,46 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
}
};
private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN;
private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
/**
* Receiver that watches for {@link TelephonyManager} changes, such as
* transitioning between network types.
*/
private PhoneStateListener mPhoneListener = new PhoneStateListener() {
@Override
public void onDataConnectionStateChanged(int state, int networkType) {
final boolean stateChanged = state != mLastPhoneState;
final boolean networkTypeChanged = networkType != mLastPhoneNetworkType;
if (networkTypeChanged && !stateChanged) {
// networkType changed without a state change, which means we
// need to roll our own update. delay long enough for
// ConnectivityManager to process.
// TODO: add direct event to ConnectivityService instead of
// relying on this delay.
if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()");
mHandler.sendMessageDelayed(
mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS);
}
mLastPhoneState = state;
mLastPhoneNetworkType = networkType;
}
};
private void updateIfaces() {
synchronized (mStatsLock) {
mWakeLock.acquire();
try {
updateIfacesLocked();
} finally {
mWakeLock.release();
}
}
}
/**
* Inspect all current {@link NetworkState} to derive mapping from {@code
* iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
@@ -713,19 +760,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final long threshold = mSettings.getPersistThreshold();
try {
// record network stats
final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary();
performNetworkPollLocked(networkSnapshot, currentTime);
// persist when enough network data has occurred
final NetworkStats persistNetworkDelta = computeStatsDelta(
mLastPersistNetworkSnapshot, networkSnapshot, true);
final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
if (persistForce || (persistNetwork && networkPastThreshold)) {
writeNetworkStatsLocked();
mLastPersistNetworkSnapshot = networkSnapshot;
}
// record tethering stats; persisted during normal UID cycle below
final String[] ifacePairs = mConnManager.getTetheredIfacePairs();
final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering(
@@ -744,6 +778,19 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
writeUidStatsLocked();
mLastPersistUidSnapshot = uidSnapshot;
}
// record network stats
final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary();
performNetworkPollLocked(networkSnapshot, currentTime);
// persist when enough network data has occurred
final NetworkStats persistNetworkDelta = computeStatsDelta(
mLastPersistNetworkSnapshot, networkSnapshot, true);
final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
if (persistForce || (persistNetwork && networkPastThreshold)) {
writeNetworkStatsLocked();
mLastPersistNetworkSnapshot = networkSnapshot;
}
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e);
} catch (RemoteException e) {
@@ -1356,6 +1403,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
performPoll(flags);
return true;
}
case MSG_UPDATE_IFACES: {
updateIfaces();
return true;
}
default: {
return false;
}

View File

@@ -776,6 +776,7 @@ public class NetworkStatsServiceTest extends AndroidTestCase {
private void expectNetworkStatsPoll() throws Exception {
mNetManager.setGlobalAlert(anyLong());
expectLastCall().anyTimes();
expect(mConnManager.getTetheredIfacePairs()).andReturn(null).anyTimes();
}
private void assertStatsFilesExist(boolean exist) {