Skip to content

Commit 367d15a

Browse files
committed
Watch network subtype, tethering teardown, empty.
Watch for changes to telephony network subtype, and update iface mapping to persist stats under correct type. Update network stats before removing tethering NAT rules. Skip recording that would create empty historical buckets. Query UID stats before iface stats to always skew positive when counters are actively rolling forward. Bug: 5360042, 5359860, 5335674, 5334448 Change-Id: I8aa37b568e8ffb70647218aa1aff5195d3e44d5a
1 parent 745f1e3 commit 367d15a

File tree

6 files changed

+102
-30
lines changed

6 files changed

+102
-30
lines changed

core/java/android/net/NetworkStatsHistory.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,11 @@ public void recordData(long start, long end, NetworkStats.Entry entry) {
270270
|| entry.operations < 0) {
271271
throw new IllegalArgumentException("tried recording negative data");
272272
}
273+
if (entry.rxBytes == 0 && entry.rxPackets == 0 && entry.txBytes == 0 && entry.txPackets == 0
274+
&& entry.operations == 0) {
275+
// nothing to record; skip
276+
return;
277+
}
273278

274279
// create any buckets needed by this range
275280
ensureBuckets(start, end);

services/java/com/android/server/ConnectivityService.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import android.net.IConnectivityManager;
3636
import android.net.INetworkPolicyListener;
3737
import android.net.INetworkPolicyManager;
38+
import android.net.INetworkStatsService;
3839
import android.net.LinkAddress;
3940
import android.net.LinkProperties;
4041
import android.net.LinkProperties.CompareResult;
@@ -306,8 +307,8 @@ public RadioAttributes(String init) {
306307
// the set of network types that can only be enabled by system/sig apps
307308
List mProtectedNetworks;
308309

309-
public ConnectivityService(
310-
Context context, INetworkManagementService netd, INetworkPolicyManager policyManager) {
310+
public ConnectivityService(Context context, INetworkManagementService netd,
311+
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
311312
if (DBG) log("ConnectivityService starting up");
312313

313314
HandlerThread handlerThread = new HandlerThread("ConnectivityServiceThread");
@@ -496,7 +497,7 @@ public ConnectivityService(
496497
IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
497498
INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);
498499

499-
mTethering = new Tethering(mContext, nmService, mHandler.getLooper());
500+
mTethering = new Tethering(mContext, nmService, statsService, mHandler.getLooper());
500501
mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
501502
mTethering.getTetherableWifiRegexs().length != 0 ||
502503
mTethering.getTetherableBluetoothRegexs().length != 0) &&

services/java/com/android/server/SystemServer.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,8 @@ public void run() {
364364

365365
try {
366366
Slog.i(TAG, "Connectivity Service");
367-
connectivity = new ConnectivityService(context, networkManagement, networkPolicy);
367+
connectivity = new ConnectivityService(
368+
context, networkManagement, networkStats, networkPolicy);
368369
ServiceManager.addService(Context.CONNECTIVITY_SERVICE, connectivity);
369370
networkStats.bindConnectivityManager(connectivity);
370371
networkPolicy.bindConnectivityManager(connectivity);

services/java/com/android/server/connectivity/Tethering.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import android.net.ConnectivityManager;
3030
import android.net.IConnectivityManager;
3131
import android.net.INetworkManagementEventObserver;
32+
import android.net.INetworkStatsService;
3233
import android.net.InterfaceConfiguration;
3334
import android.net.LinkAddress;
3435
import android.net.LinkProperties;
@@ -88,7 +89,8 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
8889
// upstream type list and the DUN_REQUIRED secure-setting
8990
private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
9091

91-
private INetworkManagementService mNMService;
92+
private final INetworkManagementService mNMService;
93+
private final INetworkStatsService mStatsService;
9294
private Looper mLooper;
9395
private HandlerThread mThread;
9496

@@ -124,9 +126,11 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
124126
private boolean mUsbTetherRequested; // true if USB tethering should be started
125127
// when RNDIS is enabled
126128

127-
public Tethering(Context context, INetworkManagementService nmService, Looper looper) {
129+
public Tethering(Context context, INetworkManagementService nmService,
130+
INetworkStatsService statsService, Looper looper) {
128131
mContext = context;
129132
mNMService = nmService;
133+
mStatsService = statsService;
130134
mLooper = looper;
131135

132136
mIfaces = new HashMap<String, TetherInterfaceSM>();
@@ -913,6 +917,9 @@ public boolean processMessage(Message message) {
913917
case CMD_INTERFACE_DOWN:
914918
if (mMyUpstreamIfaceName != null) {
915919
try {
920+
// about to tear down NAT; gather remaining statistics
921+
mStatsService.forceUpdate();
922+
916923
mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
917924
mMyUpstreamIfaceName = null;
918925
} catch (Exception e) {
@@ -957,6 +964,9 @@ public boolean processMessage(Message message) {
957964
}
958965
if (mMyUpstreamIfaceName != null) {
959966
try {
967+
// about to tear down NAT; gather remaining statistics
968+
mStatsService.forceUpdate();
969+
960970
mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
961971
mMyUpstreamIfaceName = null;
962972
} catch (Exception e) {
@@ -995,6 +1005,9 @@ public boolean processMessage(Message message) {
9951005
case CMD_TETHER_MODE_DEAD:
9961006
if (mMyUpstreamIfaceName != null) {
9971007
try {
1008+
// about to tear down NAT; gather remaining statistics
1009+
mStatsService.forceUpdate();
1010+
9981011
mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
9991012
mMyUpstreamIfaceName = null;
10001013
} catch (Exception e) {

services/java/com/android/server/net/NetworkStatsService.java

Lines changed: 75 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
import static android.content.Intent.ACTION_SHUTDOWN;
2525
import static android.content.Intent.ACTION_UID_REMOVED;
2626
import static android.content.Intent.EXTRA_UID;
27-
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
2827
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
28+
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
2929
import static android.net.NetworkStats.IFACE_ALL;
3030
import static android.net.NetworkStats.SET_ALL;
3131
import static android.net.NetworkStats.SET_DEFAULT;
@@ -43,9 +43,12 @@
4343
import static android.provider.Settings.Secure.NETSTATS_TAG_MAX_HISTORY;
4444
import static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION;
4545
import static android.provider.Settings.Secure.NETSTATS_UID_MAX_HISTORY;
46+
import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
47+
import static android.telephony.PhoneStateListener.LISTEN_NONE;
4648
import static android.text.format.DateUtils.DAY_IN_MILLIS;
4749
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
4850
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
51+
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
4952
import static com.android.internal.util.Preconditions.checkNotNull;
5053
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
5154
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
@@ -80,6 +83,7 @@
8083
import android.os.RemoteException;
8184
import android.os.SystemClock;
8285
import android.provider.Settings;
86+
import android.telephony.PhoneStateListener;
8387
import android.telephony.TelephonyManager;
8488
import android.util.EventLog;
8589
import android.util.Log;
@@ -121,7 +125,7 @@
121125
*/
122126
public class NetworkStatsService extends INetworkStatsService.Stub {
123127
private static final String TAG = "NetworkStats";
124-
private static final boolean LOGD = true;
128+
private static final boolean LOGD = false;
125129
private static final boolean LOGV = false;
126130

127131
/** File header magic number: "ANET" */
@@ -132,7 +136,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
132136
private static final int VERSION_UID_WITH_TAG = 3;
133137
private static final int VERSION_UID_WITH_SET = 4;
134138

135-
private static final int MSG_PERFORM_POLL = 0x1;
139+
private static final int MSG_PERFORM_POLL = 1;
140+
private static final int MSG_UPDATE_IFACES = 2;
136141

137142
/** Flags to control detail level of poll event. */
138143
private static final int FLAG_PERSIST_NETWORK = 0x10;
@@ -144,6 +149,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
144149
private final INetworkManagementService mNetworkManager;
145150
private final IAlarmManager mAlarmManager;
146151
private final TrustedTime mTime;
152+
private final TelephonyManager mTeleManager;
147153
private final NetworkStatsSettings mSettings;
148154

149155
private final PowerManager.WakeLock mWakeLock;
@@ -227,6 +233,7 @@ public NetworkStatsService(Context context, INetworkManagementService networkMan
227233
mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
228234
mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager");
229235
mTime = checkNotNull(time, "missing TrustedTime");
236+
mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
230237
mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
231238

232239
final PowerManager powerManager = (PowerManager) context.getSystemService(
@@ -279,6 +286,10 @@ public void systemReady() {
279286
// ignored; service lives in system_server
280287
}
281288

289+
// watch for networkType changes that aren't broadcast through
290+
// CONNECTIVITY_ACTION_IMMEDIATE above.
291+
mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
292+
282293
registerPollAlarmLocked();
283294
registerGlobalAlert();
284295

@@ -288,10 +299,13 @@ public void systemReady() {
288299

289300
private void shutdownLocked() {
290301
mContext.unregisterReceiver(mConnReceiver);
302+
mContext.unregisterReceiver(mTetherReceiver);
291303
mContext.unregisterReceiver(mPollReceiver);
292304
mContext.unregisterReceiver(mRemovedReceiver);
293305
mContext.unregisterReceiver(mShutdownReceiver);
294306

307+
mTeleManager.listen(mPhoneListener, LISTEN_NONE);
308+
295309
writeNetworkStatsLocked();
296310
if (mUidStatsLoaded) {
297311
writeUidStatsLocked();
@@ -535,14 +549,7 @@ public void forceUpdate() {
535549
public void onReceive(Context context, Intent intent) {
536550
// on background handler thread, and verified CONNECTIVITY_INTERNAL
537551
// permission above.
538-
synchronized (mStatsLock) {
539-
mWakeLock.acquire();
540-
try {
541-
updateIfacesLocked();
542-
} finally {
543-
mWakeLock.release();
544-
}
545-
}
552+
updateIfaces();
546553
}
547554
};
548555

@@ -619,6 +626,46 @@ public void limitReached(String limitName, String iface) {
619626
}
620627
};
621628

629+
private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN;
630+
private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
631+
632+
/**
633+
* Receiver that watches for {@link TelephonyManager} changes, such as
634+
* transitioning between network types.
635+
*/
636+
private PhoneStateListener mPhoneListener = new PhoneStateListener() {
637+
@Override
638+
public void onDataConnectionStateChanged(int state, int networkType) {
639+
final boolean stateChanged = state != mLastPhoneState;
640+
final boolean networkTypeChanged = networkType != mLastPhoneNetworkType;
641+
642+
if (networkTypeChanged && !stateChanged) {
643+
// networkType changed without a state change, which means we
644+
// need to roll our own update. delay long enough for
645+
// ConnectivityManager to process.
646+
// TODO: add direct event to ConnectivityService instead of
647+
// relying on this delay.
648+
if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()");
649+
mHandler.sendMessageDelayed(
650+
mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS);
651+
}
652+
653+
mLastPhoneState = state;
654+
mLastPhoneNetworkType = networkType;
655+
}
656+
};
657+
658+
private void updateIfaces() {
659+
synchronized (mStatsLock) {
660+
mWakeLock.acquire();
661+
try {
662+
updateIfacesLocked();
663+
} finally {
664+
mWakeLock.release();
665+
}
666+
}
667+
}
668+
622669
/**
623670
* Inspect all current {@link NetworkState} to derive mapping from {@code
624671
* iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
@@ -713,19 +760,6 @@ private void performPollLocked(int flags) {
713760
final long threshold = mSettings.getPersistThreshold();
714761

715762
try {
716-
// record network stats
717-
final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary();
718-
performNetworkPollLocked(networkSnapshot, currentTime);
719-
720-
// persist when enough network data has occurred
721-
final NetworkStats persistNetworkDelta = computeStatsDelta(
722-
mLastPersistNetworkSnapshot, networkSnapshot, true);
723-
final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
724-
if (persistForce || (persistNetwork && networkPastThreshold)) {
725-
writeNetworkStatsLocked();
726-
mLastPersistNetworkSnapshot = networkSnapshot;
727-
}
728-
729763
// record tethering stats; persisted during normal UID cycle below
730764
final String[] ifacePairs = mConnManager.getTetheredIfacePairs();
731765
final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering(
@@ -744,6 +778,19 @@ private void performPollLocked(int flags) {
744778
writeUidStatsLocked();
745779
mLastPersistUidSnapshot = uidSnapshot;
746780
}
781+
782+
// record network stats
783+
final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary();
784+
performNetworkPollLocked(networkSnapshot, currentTime);
785+
786+
// persist when enough network data has occurred
787+
final NetworkStats persistNetworkDelta = computeStatsDelta(
788+
mLastPersistNetworkSnapshot, networkSnapshot, true);
789+
final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
790+
if (persistForce || (persistNetwork && networkPastThreshold)) {
791+
writeNetworkStatsLocked();
792+
mLastPersistNetworkSnapshot = networkSnapshot;
793+
}
747794
} catch (IllegalStateException e) {
748795
Log.wtf(TAG, "problem reading network stats", e);
749796
} catch (RemoteException e) {
@@ -1356,6 +1403,10 @@ public boolean handleMessage(Message msg) {
13561403
performPoll(flags);
13571404
return true;
13581405
}
1406+
case MSG_UPDATE_IFACES: {
1407+
updateIfaces();
1408+
return true;
1409+
}
13591410
default: {
13601411
return false;
13611412
}

services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -776,6 +776,7 @@ private void expectCurrentTime() throws Exception {
776776
private void expectNetworkStatsPoll() throws Exception {
777777
mNetManager.setGlobalAlert(anyLong());
778778
expectLastCall().anyTimes();
779+
expect(mConnManager.getTetheredIfacePairs()).andReturn(null).anyTimes();
779780
}
780781

781782
private void assertStatsFilesExist(boolean exist) {

0 commit comments

Comments
 (0)