Better handling of NTP-based clocks.

Now that we have a nice Clock abstraction, we can use it to represent
a clock backed by an NTP fix.  (This makes testing logic much easier
to write.)

We now rely completely on NetworkTimeUpdateService to keep our NTP
fix up to date, instead of trying to refresh in the middle of
critical paths which could trigger random ANRs.

Add internal FallbackClock to make it easier to handle missing NTP
fixes.  Add internal SimpleClock to let implementers focus on single
millis() method.

Test: bit FrameworksNetTests:com.android.server.net.NetworkStatsServiceTest
Test: bit FrameworksServicesTests:com.android.server.NetworkPolicyManagerServiceTest
Bug: 69714690, 72320957
Change-Id: Ic32cdcbe093d08b73b0e4b23d6910b23ea8e1968
Exempt-From-Owner-Approval: approved in previous PS
This commit is contained in:
Jeff Sharkey
2018-02-14 22:29:11 -07:00
committed by Jeff Sharkey
parent 5e58ea8a2f
commit 77bd2dfb9f

View File

@@ -68,6 +68,7 @@ import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
import android.annotation.NonNull;
import android.app.AlarmManager; import android.app.AlarmManager;
import android.app.PendingIntent; import android.app.PendingIntent;
import android.app.usage.NetworkStatsManager; import android.app.usage.NetworkStatsManager;
@@ -97,6 +98,7 @@ import android.net.TrafficStats;
import android.os.Binder; import android.os.Binder;
import android.os.DropBoxManager; import android.os.DropBoxManager;
import android.os.Environment; import android.os.Environment;
import android.os.BestClock;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import android.os.IBinder; import android.os.IBinder;
@@ -120,10 +122,8 @@ import android.util.ArraySet;
import android.util.EventLog; import android.util.EventLog;
import android.util.Log; import android.util.Log;
import android.util.MathUtils; import android.util.MathUtils;
import android.util.NtpTrustedTime;
import android.util.Slog; import android.util.Slog;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import android.util.TrustedTime;
import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoOutputStream;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
@@ -140,6 +140,8 @@ import java.io.File;
import java.io.FileDescriptor; import java.io.FileDescriptor;
import java.io.IOException; import java.io.IOException;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.time.Clock;
import java.time.ZoneOffset;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -167,7 +169,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private final Context mContext; private final Context mContext;
private final INetworkManagementService mNetworkManager; private final INetworkManagementService mNetworkManager;
private final AlarmManager mAlarmManager; private final AlarmManager mAlarmManager;
private final TrustedTime mTime; private final Clock mClock;
private final TelephonyManager mTeleManager; private final TelephonyManager mTeleManager;
private final NetworkStatsSettings mSettings; private final NetworkStatsSettings mSettings;
private final NetworkStatsObservers mStatsObservers; private final NetworkStatsObservers mStatsObservers;
@@ -202,7 +204,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
*/ */
public interface NetworkStatsSettings { public interface NetworkStatsSettings {
public long getPollInterval(); public long getPollInterval();
public long getTimeCacheMaxAge();
public boolean getSampleEnabled(); public boolean getSampleEnabled();
public boolean getAugmentEnabled(); public boolean getAugmentEnabled();
@@ -281,16 +282,21 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
private long mPersistThreshold = 2 * MB_IN_BYTES; private long mPersistThreshold = 2 * MB_IN_BYTES;
private long mGlobalAlertBytes; private long mGlobalAlertBytes;
private static File getDefaultSystemDir() { private static @NonNull File getDefaultSystemDir() {
return new File(Environment.getDataDirectory(), "system"); return new File(Environment.getDataDirectory(), "system");
} }
private static File getDefaultBaseDir() { private static @NonNull File getDefaultBaseDir() {
File baseDir = new File(getDefaultSystemDir(), "netstats"); File baseDir = new File(getDefaultSystemDir(), "netstats");
baseDir.mkdirs(); baseDir.mkdirs();
return baseDir; return baseDir;
} }
private static @NonNull Clock getDefaultClock() {
return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
Clock.systemUTC());
}
public static NetworkStatsService create(Context context, public static NetworkStatsService create(Context context,
INetworkManagementService networkManager) { INetworkManagementService networkManager) {
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
@@ -299,7 +305,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager, NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager,
wakeLock, NtpTrustedTime.getInstance(context), TelephonyManager.getDefault(), wakeLock, getDefaultClock(), TelephonyManager.getDefault(),
new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(), new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(),
getDefaultSystemDir(), getDefaultBaseDir()); getDefaultSystemDir(), getDefaultBaseDir());
@@ -313,13 +319,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@VisibleForTesting @VisibleForTesting
NetworkStatsService(Context context, INetworkManagementService networkManager, NetworkStatsService(Context context, INetworkManagementService networkManager,
AlarmManager alarmManager, PowerManager.WakeLock wakeLock, TrustedTime time, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
TelephonyManager teleManager, NetworkStatsSettings settings, TelephonyManager teleManager, NetworkStatsSettings settings,
NetworkStatsObservers statsObservers, File systemDir, File baseDir) { NetworkStatsObservers statsObservers, File systemDir, File baseDir) {
mContext = checkNotNull(context, "missing Context"); mContext = checkNotNull(context, "missing Context");
mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService"); mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager"); mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager");
mTime = checkNotNull(time, "missing TrustedTime"); mClock = checkNotNull(clock, "missing Clock");
mSettings = checkNotNull(settings, "missing NetworkStatsSettings"); mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
mTeleManager = checkNotNull(teleManager, "missing TelephonyManager"); mTeleManager = checkNotNull(teleManager, "missing TelephonyManager");
mWakeLock = checkNotNull(wakeLock, "missing WakeLock"); mWakeLock = checkNotNull(wakeLock, "missing WakeLock");
@@ -413,8 +419,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
mContext.unregisterReceiver(mUserReceiver); mContext.unregisterReceiver(mUserReceiver);
mContext.unregisterReceiver(mShutdownReceiver); mContext.unregisterReceiver(mShutdownReceiver);
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() final long currentTime = mClock.millis();
: System.currentTimeMillis();
// persist any pending stats // persist any pending stats
mDevRecorder.forcePersistLocked(currentTime); mDevRecorder.forcePersistLocked(currentTime);
@@ -831,8 +836,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
// update and persist if beyond new thresholds // update and persist if beyond new thresholds
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() final long currentTime = mClock.millis();
: System.currentTimeMillis();
synchronized (mStatsLock) { synchronized (mStatsLock) {
if (!mSystemReady) return; if (!mSystemReady) return;
@@ -1170,8 +1174,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
*/ */
@GuardedBy("mStatsLock") @GuardedBy("mStatsLock")
private void bootstrapStatsLocked() { private void bootstrapStatsLocked() {
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() final long currentTime = mClock.millis();
: System.currentTimeMillis();
try { try {
recordSnapshotLocked(currentTime); recordSnapshotLocked(currentTime);
@@ -1183,11 +1186,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
} }
private void performPoll(int flags) { private void performPoll(int flags) {
// try refreshing time source when stale
if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
mTime.forceRefresh();
}
synchronized (mStatsLock) { synchronized (mStatsLock) {
mWakeLock.acquire(); mWakeLock.acquire();
@@ -1215,8 +1213,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
// TODO: consider marking "untrusted" times in historical stats // TODO: consider marking "untrusted" times in historical stats
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() final long currentTime = mClock.millis();
: System.currentTimeMillis();
try { try {
recordSnapshotLocked(currentTime); recordSnapshotLocked(currentTime);
@@ -1268,7 +1265,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
@GuardedBy("mStatsLock") @GuardedBy("mStatsLock")
private void performSampleLocked() { private void performSampleLocked() {
// TODO: migrate trustedtime fixes to separate binary log events // TODO: migrate trustedtime fixes to separate binary log events
final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1; final long currentTime = mClock.millis();
NetworkTemplate template; NetworkTemplate template;
NetworkStats.Entry devTotal; NetworkStats.Entry devTotal;
@@ -1285,7 +1282,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
trustedTime); currentTime);
// collect wifi sample // collect wifi sample
template = buildTemplateWifiWildcard(); template = buildTemplateWifiWildcard();
@@ -1297,7 +1294,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
trustedTime); currentTime);
} }
/** /**
@@ -1621,10 +1618,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
} }
@Override @Override
public long getTimeCacheMaxAge() {
return getGlobalLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
}
@Override
public long getGlobalAlertBytes(long def) { public long getGlobalAlertBytes(long def) {
return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def); return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
} }