blob: 856a07667d5c75a5eb53e3f8af56fbede31fd63c [file] [log] [blame]
Jeff Sharkey75279902011-05-24 18:39:45 -07001/*
Jeff Sharkeyd2a45872011-05-28 20:56:34 -07002 * Copyright (C) 2011 The Android Open Source Project
Jeff Sharkey75279902011-05-24 18:39:45 -07003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server.net;
18
Jeff Sharkeya63ba592011-07-19 23:47:12 -070019import static android.Manifest.permission.ACCESS_NETWORK_STATE;
Jeff Sharkey63d27a92011-08-03 17:04:22 -070020import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
Jeff Sharkey75279902011-05-24 18:39:45 -070021import static android.Manifest.permission.DUMP;
Jeff Sharkey63d27a92011-08-03 17:04:22 -070022import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING;
Jeff Sharkey21c9c452011-06-07 12:26:43 -070023import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
Jeff Sharkeyb09540f2011-06-19 01:08:12 -070024import static android.content.Intent.ACTION_SHUTDOWN;
25import static android.content.Intent.ACTION_UID_REMOVED;
Jeff Sharkeydaa57e82012-09-19 14:10:39 -070026import static android.content.Intent.ACTION_USER_REMOVED;
Jeff Sharkeyb09540f2011-06-19 01:08:12 -070027import static android.content.Intent.EXTRA_UID;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -070028import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
Jeff Sharkey234766a2012-04-10 19:48:07 -070029import static android.net.ConnectivityManager.isNetworkTypeMobile;
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -070030import static android.net.NetworkStats.IFACE_ALL;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070031import static android.net.NetworkStats.SET_ALL;
32import static android.net.NetworkStats.SET_DEFAULT;
33import static android.net.NetworkStats.SET_FOREGROUND;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070034import static android.net.NetworkStats.TAG_NONE;
Jeff Sharkey75279902011-05-24 18:39:45 -070035import static android.net.NetworkStats.UID_ALL;
Jeff Sharkey234766a2012-04-10 19:48:07 -070036import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
Jeff Sharkey8fc27e82012-04-04 20:40:58 -070037import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -070038import static android.net.TrafficStats.KB_IN_BYTES;
Jeff Sharkey241dde22012-02-03 14:50:07 -080039import static android.net.TrafficStats.MB_IN_BYTES;
Jeff Sharkey023c05a2012-09-14 13:09:57 -070040import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
41import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
42import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
43import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE;
44import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
45import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
Jeff Sharkey023c05a2012-09-14 13:09:57 -070046import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
47import static android.provider.Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE;
48import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
49import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
50import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
51import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE;
52import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
53import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
54import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
55import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -070056import static android.text.format.DateUtils.DAY_IN_MILLIS;
57import static android.text.format.DateUtils.HOUR_IN_MILLIS;
58import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
Jeff Sharkey367d15a2011-09-22 14:59:51 -070059import static android.text.format.DateUtils.SECOND_IN_MILLIS;
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070060import static com.android.internal.util.Preconditions.checkNotNull;
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070061import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070062import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
63import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
Jeff Sharkey75279902011-05-24 18:39:45 -070064
65import android.app.AlarmManager;
66import android.app.IAlarmManager;
67import android.app.PendingIntent;
68import android.content.BroadcastReceiver;
Jeff Sharkey39ebc212011-06-11 17:25:42 -070069import android.content.ContentResolver;
Jeff Sharkey75279902011-05-24 18:39:45 -070070import android.content.Context;
71import android.content.Intent;
72import android.content.IntentFilter;
Jeff Sharkeydaa57e82012-09-19 14:10:39 -070073import android.content.pm.ApplicationInfo;
74import android.content.pm.PackageManager;
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070075import android.net.IConnectivityManager;
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070076import android.net.INetworkManagementEventObserver;
Jeff Sharkey75279902011-05-24 18:39:45 -070077import android.net.INetworkStatsService;
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -070078import android.net.INetworkStatsSession;
Jeff Sharkey63abc372012-01-11 18:38:16 -080079import android.net.LinkProperties;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070080import android.net.NetworkIdentity;
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070081import android.net.NetworkInfo;
82import android.net.NetworkState;
Jeff Sharkey75279902011-05-24 18:39:45 -070083import android.net.NetworkStats;
Jeff Sharkey5a7bcf32012-01-10 17:24:44 -080084import android.net.NetworkStats.NonMonotonicObserver;
Jeff Sharkey75279902011-05-24 18:39:45 -070085import android.net.NetworkStatsHistory;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070086import android.net.NetworkTemplate;
Jeff Sharkey63abc372012-01-11 18:38:16 -080087import android.net.TrafficStats;
Jeff Sharkeya63ba592011-07-19 23:47:12 -070088import android.os.Binder;
Jeff Sharkey163e6442011-10-31 16:37:52 -070089import android.os.DropBoxManager;
Jeff Sharkey3f391352011-06-05 17:42:53 -070090import android.os.Environment;
Jeff Sharkey75279902011-05-24 18:39:45 -070091import android.os.Handler;
Amith Yamasani450a16b2013-09-18 16:28:50 -070092import android.os.HandlerThread;
Jeff Sharkey75279902011-05-24 18:39:45 -070093import android.os.INetworkManagementService;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070094import android.os.Message;
Jeff Sharkey62489262011-07-17 12:53:28 -070095import android.os.PowerManager;
Jeff Sharkey75279902011-05-24 18:39:45 -070096import android.os.RemoteException;
97import android.os.SystemClock;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070098import android.os.UserHandle;
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -070099import android.provider.Settings;
Jeff Sharkey625239a2012-09-26 22:03:49 -0700100import android.provider.Settings.Global;
Jeff Sharkey75279902011-05-24 18:39:45 -0700101import android.telephony.TelephonyManager;
Jeff Sharkey55a442e2014-11-18 18:22:21 -0800102import android.text.format.DateUtils;
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700103import android.util.ArrayMap;
104import android.util.ArraySet;
Jeff Sharkey07b0dd92011-09-01 13:06:19 -0700105import android.util.EventLog;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700106import android.util.Log;
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700107import android.util.MathUtils;
Jeff Sharkey75279902011-05-24 18:39:45 -0700108import android.util.NtpTrustedTime;
109import android.util.Slog;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700110import android.util.SparseIntArray;
Jeff Sharkey75279902011-05-24 18:39:45 -0700111import android.util.TrustedTime;
112
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800113import com.android.internal.annotations.VisibleForTesting;
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700114import com.android.internal.util.ArrayUtils;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800115import com.android.internal.util.FileRotator;
116import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey07b0dd92011-09-01 13:06:19 -0700117import com.android.server.EventLogTags;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700118import com.android.server.connectivity.Tethering;
Jeff Sharkey75279902011-05-24 18:39:45 -0700119
Jeff Sharkey3f391352011-06-05 17:42:53 -0700120import java.io.File;
Jeff Sharkey75279902011-05-24 18:39:45 -0700121import java.io.FileDescriptor;
Jeff Sharkey3f391352011-06-05 17:42:53 -0700122import java.io.IOException;
Jeff Sharkey75279902011-05-24 18:39:45 -0700123import java.io.PrintWriter;
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700124import java.util.Arrays;
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -0700125import java.util.HashSet;
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700126import java.util.List;
Jeff Sharkey3f391352011-06-05 17:42:53 -0700127
Jeff Sharkey75279902011-05-24 18:39:45 -0700128/**
129 * Collect and persist detailed network statistics, and provide this data to
130 * other system services.
131 */
132public class NetworkStatsService extends INetworkStatsService.Stub {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700133 private static final String TAG = "NetworkStats";
Jeff Sharkey706498d2012-02-06 17:35:07 -0800134 private static final boolean LOGV = false;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700135
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700136 private static final int MSG_PERFORM_POLL = 1;
137 private static final int MSG_UPDATE_IFACES = 2;
Jeff Sharkey25ce9ed2012-02-02 13:07:47 -0800138 private static final int MSG_REGISTER_GLOBAL_ALERT = 3;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700139
140 /** Flags to control detail level of poll event. */
Jeff Sharkey905b5892011-09-30 15:19:49 -0700141 private static final int FLAG_PERSIST_NETWORK = 0x1;
142 private static final int FLAG_PERSIST_UID = 0x2;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700143 private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700144 private static final int FLAG_PERSIST_FORCE = 0x100;
Jeff Sharkey3f391352011-06-05 17:42:53 -0700145
Jeff Sharkey163e6442011-10-31 16:37:52 -0700146 private static final String TAG_NETSTATS_ERROR = "netstats_error";
147
Jeff Sharkey75279902011-05-24 18:39:45 -0700148 private final Context mContext;
149 private final INetworkManagementService mNetworkManager;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700150 private final AlarmManager mAlarmManager;
Jeff Sharkey75279902011-05-24 18:39:45 -0700151 private final TrustedTime mTime;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700152 private final TelephonyManager mTeleManager;
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700153 private final NetworkStatsSettings mSettings;
Jeff Sharkey75279902011-05-24 18:39:45 -0700154
Jeff Sharkey63abc372012-01-11 18:38:16 -0800155 private final File mSystemDir;
156 private final File mBaseDir;
157
Jeff Sharkey62489262011-07-17 12:53:28 -0700158 private final PowerManager.WakeLock mWakeLock;
159
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700160 private IConnectivityManager mConnManager;
161
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800162 @VisibleForTesting
Jeff Sharkey3f391352011-06-05 17:42:53 -0700163 public static final String ACTION_NETWORK_STATS_POLL =
Jeff Sharkey75279902011-05-24 18:39:45 -0700164 "com.android.server.action.NETWORK_STATS_POLL";
Jeff Sharkey497e4432011-06-14 17:27:29 -0700165 public static final String ACTION_NETWORK_STATS_UPDATED =
166 "com.android.server.action.NETWORK_STATS_UPDATED";
Jeff Sharkey75279902011-05-24 18:39:45 -0700167
168 private PendingIntent mPollIntent;
169
Jeff Sharkey63abc372012-01-11 18:38:16 -0800170 private static final String PREFIX_DEV = "dev";
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700171 private static final String PREFIX_XT = "xt";
Jeff Sharkey63abc372012-01-11 18:38:16 -0800172 private static final String PREFIX_UID = "uid";
173 private static final String PREFIX_UID_TAG = "uid_tag";
174
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700175 /**
176 * Settings that can be changed externally.
177 */
178 public interface NetworkStatsSettings {
179 public long getPollInterval();
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700180 public long getTimeCacheMaxAge();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800181 public boolean getSampleEnabled();
182
183 public static class Config {
184 public final long bucketDuration;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800185 public final long rotateAgeMillis;
186 public final long deleteAgeMillis;
187
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700188 public Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis) {
Jeff Sharkey63abc372012-01-11 18:38:16 -0800189 this.bucketDuration = bucketDuration;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800190 this.rotateAgeMillis = rotateAgeMillis;
191 this.deleteAgeMillis = deleteAgeMillis;
192 }
193 }
194
195 public Config getDevConfig();
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700196 public Config getXtConfig();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800197 public Config getUidConfig();
198 public Config getUidTagConfig();
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700199
200 public long getGlobalAlertBytes(long def);
201 public long getDevPersistBytes(long def);
202 public long getXtPersistBytes(long def);
203 public long getUidPersistBytes(long def);
204 public long getUidTagPersistBytes(long def);
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700205 }
Jeff Sharkey75279902011-05-24 18:39:45 -0700206
207 private final Object mStatsLock = new Object();
208
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700209 /** Set of currently active ifaces. */
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700210 private final ArrayMap<String, NetworkIdentitySet> mActiveIfaces = new ArrayMap<>();
211 /** Set of currently active ifaces for UID stats. */
212 private final ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces = new ArrayMap<>();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800213 /** Current default active iface. */
214 private String mActiveIface;
Jeff Sharkey234766a2012-04-10 19:48:07 -0700215 /** Set of any ifaces associated with mobile networks since boot. */
216 private String[] mMobileIfaces = new String[0];
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -0700217
Jeff Sharkey63abc372012-01-11 18:38:16 -0800218 private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
219 new DropBoxNonMonotonicObserver();
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -0700220
Jeff Sharkey63abc372012-01-11 18:38:16 -0800221 private NetworkStatsRecorder mDevRecorder;
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700222 private NetworkStatsRecorder mXtRecorder;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800223 private NetworkStatsRecorder mUidRecorder;
224 private NetworkStatsRecorder mUidTagRecorder;
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700225
Jeff Sharkey70c70532012-05-16 14:51:19 -0700226 /** Cached {@link #mXtRecorder} stats. */
227 private NetworkStatsCollection mXtStatsCached;
Jeff Sharkey75279902011-05-24 18:39:45 -0700228
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700229 /** Current counter sets for each UID. */
230 private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
231
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700232 /** Data layer operation counters for splicing into other structures. */
Jeff Sharkey63abc372012-01-11 18:38:16 -0800233 private NetworkStats mUidOperations = new NetworkStats(0L, 10);
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700234
Jeff Sharkey75279902011-05-24 18:39:45 -0700235 private final Handler mHandler;
236
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800237 private boolean mSystemReady;
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700238 private long mPersistThreshold = 2 * MB_IN_BYTES;
239 private long mGlobalAlertBytes;
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800240
Jeff Sharkey75279902011-05-24 18:39:45 -0700241 public NetworkStatsService(
242 Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
Jeff Sharkey104344e2011-07-10 14:20:41 -0700243 this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
Jeff Sharkey63abc372012-01-11 18:38:16 -0800244 getDefaultSystemDir(), new DefaultNetworkStatsSettings(context));
Jeff Sharkey3f391352011-06-05 17:42:53 -0700245 }
246
Jeff Sharkey63abc372012-01-11 18:38:16 -0800247 private static File getDefaultSystemDir() {
Jeff Sharkey3f391352011-06-05 17:42:53 -0700248 return new File(Environment.getDataDirectory(), "system");
Jeff Sharkey75279902011-05-24 18:39:45 -0700249 }
250
251 public NetworkStatsService(Context context, INetworkManagementService networkManager,
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700252 IAlarmManager alarmManager, TrustedTime time, File systemDir,
253 NetworkStatsSettings settings) {
Jeff Sharkey75279902011-05-24 18:39:45 -0700254 mContext = checkNotNull(context, "missing Context");
255 mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
Jeff Sharkey75279902011-05-24 18:39:45 -0700256 mTime = checkNotNull(time, "missing TrustedTime");
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700257 mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700258 mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
Christopher Tatee0a22b32013-07-11 14:43:13 -0700259 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Jeff Sharkey75279902011-05-24 18:39:45 -0700260
Jeff Sharkey62489262011-07-17 12:53:28 -0700261 final PowerManager powerManager = (PowerManager) context.getSystemService(
262 Context.POWER_SERVICE);
263 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
264
Amith Yamasani450a16b2013-09-18 16:28:50 -0700265 HandlerThread thread = new HandlerThread(TAG);
266 thread.start();
267 mHandler = new Handler(thread.getLooper(), mHandlerCallback);
Jeff Sharkey3f391352011-06-05 17:42:53 -0700268
Jeff Sharkey63abc372012-01-11 18:38:16 -0800269 mSystemDir = checkNotNull(systemDir);
270 mBaseDir = new File(systemDir, "netstats");
271 mBaseDir.mkdirs();
Jeff Sharkey75279902011-05-24 18:39:45 -0700272 }
273
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700274 public void bindConnectivityManager(IConnectivityManager connManager) {
275 mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
276 }
277
Jeff Sharkey75279902011-05-24 18:39:45 -0700278 public void systemReady() {
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800279 mSystemReady = true;
280
Jeff Sharkey418d12d2011-12-13 15:38:03 -0800281 if (!isBandwidthControlEnabled()) {
282 Slog.w(TAG, "bandwidth controls disabled, unable to track stats");
283 return;
284 }
285
Jeff Sharkey63abc372012-01-11 18:38:16 -0800286 // create data recorders along with historical rotators
287 mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700288 mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800289 mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
290 mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
Jeff Sharkey75279902011-05-24 18:39:45 -0700291
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700292 updatePersistThresholds();
293
Jeff Sharkey63abc372012-01-11 18:38:16 -0800294 synchronized (mStatsLock) {
295 // upgrade any legacy stats, migrating them to rotated files
296 maybeUpgradeLegacyStatsLocked();
297
298 // read historical network stats from disk, since policy service
299 // might need them right away.
Jeff Sharkey70c70532012-05-16 14:51:19 -0700300 mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800301
302 // bootstrap initial stats to prevent double-counting later
303 bootstrapStatsLocked();
304 }
Jeff Sharkey3359aca2011-11-08 18:08:48 -0800305
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700306 // watch for tethering changes
307 final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
Vinit Deshpande92d141f2014-09-10 18:05:10 -0700308 mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler);
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700309
Jeff Sharkey75279902011-05-24 18:39:45 -0700310 // listen for periodic polling events
311 final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700312 mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
Jeff Sharkey75279902011-05-24 18:39:45 -0700313
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700314 // listen for uid removal to clean stats
315 final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
316 mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
317
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700318 // listen for user changes to clean stats
319 final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
320 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
321
Jeff Sharkey75279902011-05-24 18:39:45 -0700322 // persist stats during clean shutdown
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700323 final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
324 mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
Jeff Sharkey75279902011-05-24 18:39:45 -0700325
326 try {
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700327 mNetworkManager.registerObserver(mAlertObserver);
Jeff Sharkey75279902011-05-24 18:39:45 -0700328 } catch (RemoteException e) {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700329 // ignored; service lives in system_server
Jeff Sharkey75279902011-05-24 18:39:45 -0700330 }
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700331
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700332 registerPollAlarmLocked();
333 registerGlobalAlert();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800334 }
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700335
Jeff Sharkey63abc372012-01-11 18:38:16 -0800336 private NetworkStatsRecorder buildRecorder(
337 String prefix, NetworkStatsSettings.Config config, boolean includeTags) {
Jeff Sharkey6de357e2012-05-09 13:33:52 -0700338 final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
339 Context.DROPBOX_SERVICE);
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700340 return new NetworkStatsRecorder(new FileRotator(
341 mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
Jeff Sharkey6de357e2012-05-09 13:33:52 -0700342 mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
Jeff Sharkey75279902011-05-24 18:39:45 -0700343 }
344
Jeff Sharkey3f391352011-06-05 17:42:53 -0700345 private void shutdownLocked() {
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700346 mContext.unregisterReceiver(mTetherReceiver);
Jeff Sharkey3f391352011-06-05 17:42:53 -0700347 mContext.unregisterReceiver(mPollReceiver);
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700348 mContext.unregisterReceiver(mRemovedReceiver);
Jeff Sharkey3f391352011-06-05 17:42:53 -0700349 mContext.unregisterReceiver(mShutdownReceiver);
350
Jeff Sharkey63abc372012-01-11 18:38:16 -0800351 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
352 : System.currentTimeMillis();
353
354 // persist any pending stats
355 mDevRecorder.forcePersistLocked(currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700356 mXtRecorder.forcePersistLocked(currentTime);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800357 mUidRecorder.forcePersistLocked(currentTime);
358 mUidTagRecorder.forcePersistLocked(currentTime);
359
360 mDevRecorder = null;
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700361 mXtRecorder = null;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800362 mUidRecorder = null;
363 mUidTagRecorder = null;
364
Jeff Sharkey70c70532012-05-16 14:51:19 -0700365 mXtStatsCached = null;
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800366
367 mSystemReady = false;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800368 }
369
370 private void maybeUpgradeLegacyStatsLocked() {
371 File file;
372 try {
373 file = new File(mSystemDir, "netstats.bin");
374 if (file.exists()) {
375 mDevRecorder.importLegacyNetworkLocked(file);
376 file.delete();
377 }
378
379 file = new File(mSystemDir, "netstats_xt.bin");
380 if (file.exists()) {
381 file.delete();
382 }
383
384 file = new File(mSystemDir, "netstats_uid.bin");
385 if (file.exists()) {
386 mUidRecorder.importLegacyUidLocked(file);
387 mUidTagRecorder.importLegacyUidLocked(file);
388 file.delete();
389 }
390 } catch (IOException e) {
391 Log.wtf(TAG, "problem during legacy upgrade", e);
Jeff Sharkeye4984be2013-09-10 21:03:27 -0700392 } catch (OutOfMemoryError e) {
393 Log.wtf(TAG, "problem during legacy upgrade", e);
Jeff Sharkeyc506ff62011-11-17 11:59:29 -0800394 }
Jeff Sharkey3f391352011-06-05 17:42:53 -0700395 }
396
Jeff Sharkey75279902011-05-24 18:39:45 -0700397 /**
398 * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700399 * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
Jeff Sharkey75279902011-05-24 18:39:45 -0700400 */
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700401 private void registerPollAlarmLocked() {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700402 if (mPollIntent != null) {
403 mAlarmManager.cancel(mPollIntent);
Jeff Sharkey75279902011-05-24 18:39:45 -0700404 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700405
406 mPollIntent = PendingIntent.getBroadcast(
407 mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
408
409 final long currentRealtime = SystemClock.elapsedRealtime();
410 mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
411 mSettings.getPollInterval(), mPollIntent);
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700412 }
Jeff Sharkey75279902011-05-24 18:39:45 -0700413
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700414 /**
415 * Register for a global alert that is delivered through
416 * {@link INetworkManagementEventObserver} once a threshold amount of data
417 * has been transferred.
418 */
419 private void registerGlobalAlert() {
420 try {
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700421 mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700422 } catch (IllegalStateException e) {
423 Slog.w(TAG, "problem registering for global alert: " + e);
424 } catch (RemoteException e) {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700425 // ignored; service lives in system_server
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700426 }
Jeff Sharkey75279902011-05-24 18:39:45 -0700427 }
428
429 @Override
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700430 public INetworkStatsSession openSession() {
431 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
Jeff Sharkey4190a042012-04-21 15:36:48 -0700432 assertBandwidthControlEnabled();
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700433
434 // return an IBinder which holds strong references to any loaded stats
435 // for its lifetime; when caller closes only weak references remain.
436
437 return new INetworkStatsSession.Stub() {
438 private NetworkStatsCollection mUidComplete;
439 private NetworkStatsCollection mUidTagComplete;
440
441 private NetworkStatsCollection getUidComplete() {
Ashish Sharmac13b9452013-11-01 14:57:30 -0700442 synchronized (mStatsLock) {
443 if (mUidComplete == null) {
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700444 mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
445 }
Ashish Sharmac13b9452013-11-01 14:57:30 -0700446 return mUidComplete;
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700447 }
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700448 }
449
450 private NetworkStatsCollection getUidTagComplete() {
Ashish Sharmac13b9452013-11-01 14:57:30 -0700451 synchronized (mStatsLock) {
452 if (mUidTagComplete == null) {
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700453 mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
454 }
Ashish Sharmac13b9452013-11-01 14:57:30 -0700455 return mUidTagComplete;
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700456 }
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700457 }
458
459 @Override
460 public NetworkStats getSummaryForNetwork(
461 NetworkTemplate template, long start, long end) {
Jeff Sharkey70c70532012-05-16 14:51:19 -0700462 return internalGetSummaryForNetwork(template, start, end);
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700463 }
464
465 @Override
466 public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
Jeff Sharkey70c70532012-05-16 14:51:19 -0700467 return internalGetHistoryForNetwork(template, fields);
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700468 }
469
470 @Override
471 public NetworkStats getSummaryForAllUid(
472 NetworkTemplate template, long start, long end, boolean includeTags) {
473 final NetworkStats stats = getUidComplete().getSummary(template, start, end);
474 if (includeTags) {
475 final NetworkStats tagStats = getUidTagComplete()
476 .getSummary(template, start, end);
477 stats.combineAllValues(tagStats);
478 }
479 return stats;
480 }
481
482 @Override
483 public NetworkStatsHistory getHistoryForUid(
484 NetworkTemplate template, int uid, int set, int tag, int fields) {
485 if (tag == TAG_NONE) {
486 return getUidComplete().getHistory(template, uid, set, tag, fields);
487 } else {
488 return getUidTagComplete().getHistory(template, uid, set, tag, fields);
489 }
490 }
491
492 @Override
493 public void close() {
494 mUidComplete = null;
495 mUidTagComplete = null;
496 }
497 };
Jeff Sharkey905b5892011-09-30 15:19:49 -0700498 }
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700499
Jeff Sharkey70c70532012-05-16 14:51:19 -0700500 /**
Jeff Sharkey5274dcc2014-10-24 13:15:15 -0700501 * Return network summary, splicing between DEV and XT stats when
502 * appropriate.
Jeff Sharkey70c70532012-05-16 14:51:19 -0700503 */
504 private NetworkStats internalGetSummaryForNetwork(
505 NetworkTemplate template, long start, long end) {
Jeff Sharkey5274dcc2014-10-24 13:15:15 -0700506 // We've been using pure XT stats long enough that we no longer need to
507 // splice DEV and XT together.
508 return mXtStatsCached.getSummary(template, start, end);
Jeff Sharkey70c70532012-05-16 14:51:19 -0700509 }
510
511 /**
Jeff Sharkey5274dcc2014-10-24 13:15:15 -0700512 * Return network history, splicing between DEV and XT stats when
513 * appropriate.
Jeff Sharkey70c70532012-05-16 14:51:19 -0700514 */
515 private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, int fields) {
Jeff Sharkey5274dcc2014-10-24 13:15:15 -0700516 // We've been using pure XT stats long enough that we no longer need to
517 // splice DEV and XT together.
518 return mXtStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
Jeff Sharkey70c70532012-05-16 14:51:19 -0700519 }
520
Jeff Sharkey63abc372012-01-11 18:38:16 -0800521 @Override
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700522 public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
523 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
Jeff Sharkey4190a042012-04-21 15:36:48 -0700524 assertBandwidthControlEnabled();
Jeff Sharkey70c70532012-05-16 14:51:19 -0700525 return internalGetSummaryForNetwork(template, start, end).getTotalBytes();
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700526 }
527
Jeff Sharkey350083e2011-06-29 10:45:16 -0700528 @Override
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700529 public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
530 if (Binder.getCallingUid() != uid) {
531 mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
532 }
Jeff Sharkey4190a042012-04-21 15:36:48 -0700533 assertBandwidthControlEnabled();
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700534
535 // TODO: switch to data layer stats once kernel exports
536 // for now, read network layer stats and flatten across all ifaces
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800537 final long token = Binder.clearCallingIdentity();
538 final NetworkStats networkLayer;
539 try {
540 networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid);
541 } finally {
542 Binder.restoreCallingIdentity(token);
543 }
544
Jeff Sharkey21a54782012-04-09 10:27:55 -0700545 // splice in operation counts
546 networkLayer.spliceOperationsFrom(mUidOperations);
547
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700548 final NetworkStats dataLayer = new NetworkStats(
549 networkLayer.getElapsedRealtime(), networkLayer.size());
550
551 NetworkStats.Entry entry = null;
552 for (int i = 0; i < networkLayer.size(); i++) {
553 entry = networkLayer.getValues(i, entry);
554 entry.iface = IFACE_ALL;
555 dataLayer.combineValues(entry);
556 }
557
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700558 return dataLayer;
559 }
560
561 @Override
Jeff Sharkey234766a2012-04-10 19:48:07 -0700562 public String[] getMobileIfaces() {
563 return mMobileIfaces;
564 }
565
566 @Override
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700567 public void incrementOperationCount(int uid, int tag, int operationCount) {
568 if (Binder.getCallingUid() != uid) {
569 mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
570 }
571
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700572 if (operationCount < 0) {
573 throw new IllegalArgumentException("operation count can only be incremented");
574 }
575 if (tag == TAG_NONE) {
576 throw new IllegalArgumentException("operation count must have specific tag");
577 }
578
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700579 synchronized (mStatsLock) {
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700580 final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800581 mUidOperations.combineValues(
582 mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
583 mUidOperations.combineValues(
584 mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700585 }
586 }
587
588 @Override
589 public void setUidForeground(int uid, boolean uidForeground) {
590 mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
591
592 synchronized (mStatsLock) {
593 final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
594 final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
595 if (oldSet != set) {
596 mActiveUidCounterSet.put(uid, set);
597 setKernelCounterSet(uid, set);
598 }
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700599 }
600 }
601
602 @Override
Jeff Sharkey69736342014-12-08 14:50:12 -0800603 public void forceUpdateIfaces() {
604 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
605 assertBandwidthControlEnabled();
606
607 final long token = Binder.clearCallingIdentity();
608 try {
609 updateIfaces();
610 } finally {
611 Binder.restoreCallingIdentity(token);
612 }
613 }
614
615 @Override
Jeff Sharkey350083e2011-06-29 10:45:16 -0700616 public void forceUpdate() {
617 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
Jeff Sharkey4190a042012-04-21 15:36:48 -0700618 assertBandwidthControlEnabled();
Jeff Sharkeye630f7b2012-01-31 17:12:53 -0800619
620 final long token = Binder.clearCallingIdentity();
621 try {
622 performPoll(FLAG_PERSIST_ALL);
623 } finally {
624 Binder.restoreCallingIdentity(token);
625 }
Jeff Sharkey350083e2011-06-29 10:45:16 -0700626 }
627
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700628 @Override
629 public void advisePersistThreshold(long thresholdBytes) {
630 mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
631 assertBandwidthControlEnabled();
632
633 // clamp threshold into safe range
634 mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700635 if (LOGV) {
636 Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
637 + mPersistThreshold);
638 }
639
Jeff Sharkey20f5c3d2012-05-09 19:59:07 -0700640 // update and persist if beyond new thresholds
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700641 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
642 : System.currentTimeMillis();
Jeff Sharkey58015972012-05-07 11:08:49 -0700643 synchronized (mStatsLock) {
Jeff Sharkey20f5c3d2012-05-09 19:59:07 -0700644 if (!mSystemReady) return;
645
646 updatePersistThresholds();
647
Jeff Sharkey58015972012-05-07 11:08:49 -0700648 mDevRecorder.maybePersistLocked(currentTime);
649 mXtRecorder.maybePersistLocked(currentTime);
650 mUidRecorder.maybePersistLocked(currentTime);
651 mUidTagRecorder.maybePersistLocked(currentTime);
652 }
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700653
654 // re-arm global alert
655 registerGlobalAlert();
656 }
657
658 /**
659 * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
660 * reflect current {@link #mPersistThreshold} value. Always defers to
Jeff Sharkey625239a2012-09-26 22:03:49 -0700661 * {@link Global} values when defined.
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700662 */
663 private void updatePersistThresholds() {
664 mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
665 mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
666 mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
667 mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
668 mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold);
669 }
670
Jeff Sharkey75279902011-05-24 18:39:45 -0700671 /**
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700672 * Receiver that watches for {@link Tethering} to claim interface pairs.
673 */
674 private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
675 @Override
676 public void onReceive(Context context, Intent intent) {
677 // on background handler thread, and verified CONNECTIVITY_INTERNAL
678 // permission above.
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700679 performPoll(FLAG_PERSIST_NETWORK);
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700680 }
681 };
682
Jeff Sharkey75279902011-05-24 18:39:45 -0700683 private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
684 @Override
685 public void onReceive(Context context, Intent intent) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700686 // on background handler thread, and verified UPDATE_DEVICE_STATS
687 // permission above.
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700688 performPoll(FLAG_PERSIST_ALL);
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700689
690 // verify that we're watching global alert
691 registerGlobalAlert();
Jeff Sharkey75279902011-05-24 18:39:45 -0700692 }
693 };
694
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700695 private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
696 @Override
697 public void onReceive(Context context, Intent intent) {
698 // on background handler thread, and UID_REMOVED is protected
699 // broadcast.
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700700
701 final int uid = intent.getIntExtra(EXTRA_UID, -1);
702 if (uid == -1) return;
703
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700704 synchronized (mStatsLock) {
Jeff Sharkey62489262011-07-17 12:53:28 -0700705 mWakeLock.acquire();
706 try {
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700707 removeUidsLocked(uid);
708 } finally {
709 mWakeLock.release();
710 }
711 }
712 }
713 };
714
715 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
716 @Override
717 public void onReceive(Context context, Intent intent) {
718 // On background handler thread, and USER_REMOVED is protected
719 // broadcast.
720
721 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
722 if (userId == -1) return;
723
724 synchronized (mStatsLock) {
725 mWakeLock.acquire();
726 try {
727 removeUserLocked(userId);
Jeff Sharkey62489262011-07-17 12:53:28 -0700728 } finally {
729 mWakeLock.release();
730 }
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700731 }
732 }
733 };
734
Jeff Sharkey75279902011-05-24 18:39:45 -0700735 private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
736 @Override
737 public void onReceive(Context context, Intent intent) {
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700738 // SHUTDOWN is protected broadcast.
Jeff Sharkey75279902011-05-24 18:39:45 -0700739 synchronized (mStatsLock) {
Jeff Sharkey3f391352011-06-05 17:42:53 -0700740 shutdownLocked();
Jeff Sharkey75279902011-05-24 18:39:45 -0700741 }
742 }
743 };
744
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700745 /**
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700746 * Observer that watches for {@link INetworkManagementService} alerts.
747 */
Jeff Sharkey216c1812012-08-05 14:29:23 -0700748 private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700749 @Override
750 public void limitReached(String limitName, String iface) {
751 // only someone like NMS should be calling us
752 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
753
754 if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
755 // kick off background poll to collect network stats; UID stats
756 // are handled during normal polling interval.
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700757 final int flags = FLAG_PERSIST_NETWORK;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700758 mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700759
760 // re-arm global alert for next update
Jeff Sharkey25ce9ed2012-02-02 13:07:47 -0800761 mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget();
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700762 }
763 }
764 };
765
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700766 private void updateIfaces() {
767 synchronized (mStatsLock) {
768 mWakeLock.acquire();
769 try {
770 updateIfacesLocked();
771 } finally {
772 mWakeLock.release();
773 }
774 }
775 }
776
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700777 /**
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700778 * Inspect all current {@link NetworkState} to derive mapping from {@code
779 * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
780 * are active on a single {@code iface}, they are combined under a single
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700781 * {@link NetworkIdentitySet}.
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700782 */
783 private void updateIfacesLocked() {
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800784 if (!mSystemReady) return;
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700785 if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700786
787 // take one last stats snapshot before updating iface mapping. this
788 // isn't perfect, since the kernel may already be counting traffic from
789 // the updated network.
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700790
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700791 // poll, but only persist network stats to keep codepath fast. UID stats
792 // will be persisted during next alarm poll event.
793 performPollLocked(FLAG_PERSIST_NETWORK);
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700794
795 final NetworkState[] states;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800796 final LinkProperties activeLink;
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700797 try {
798 states = mConnManager.getAllNetworkState();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800799 activeLink = mConnManager.getActiveLinkProperties();
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700800 } catch (RemoteException e) {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700801 // ignored; service lives in system_server
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700802 return;
803 }
804
Jeff Sharkey63abc372012-01-11 18:38:16 -0800805 mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null;
806
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700807 // Rebuild active interfaces based on connected networks
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700808 mActiveIfaces.clear();
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700809 mActiveUidIfaces.clear();
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700810
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700811 final ArraySet<String> mobileIfaces = new ArraySet<>();
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700812 for (NetworkState state : states) {
813 if (state.networkInfo.isConnected()) {
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700814 final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType());
815 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700816
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700817 // Traffic occurring on the base interface is always counted for
818 // both total usage and UID details.
819 final String baseIface = state.linkProperties.getInterfaceName();
Jeff Sharkey9da2f1e2014-08-14 12:55:00 -0700820 if (baseIface != null) {
821 findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident);
822 findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident);
823 if (isMobile) {
824 mobileIfaces.add(baseIface);
825 }
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700826 }
827
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700828 // Traffic occurring on stacked interfaces is usually clatd,
829 // which is already accounted against its final egress interface
830 // by the kernel. Thus, we only need to collect stacked
831 // interface stats at the UID level.
832 final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
833 for (LinkProperties stackedLink : stackedLinks) {
834 final String stackedIface = stackedLink.getInterfaceName();
Jeff Sharkey9da2f1e2014-08-14 12:55:00 -0700835 if (stackedIface != null) {
836 findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident);
837 if (isMobile) {
838 mobileIfaces.add(stackedIface);
839 }
Jeff Sharkey234766a2012-04-10 19:48:07 -0700840 }
841 }
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700842 }
843 }
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700844
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700845 mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
846 }
847
848 private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
849 ArrayMap<K, NetworkIdentitySet> map, K key) {
850 NetworkIdentitySet ident = map.get(key);
851 if (ident == null) {
852 ident = new NetworkIdentitySet();
853 map.put(key, ident);
854 }
855 return ident;
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700856 }
857
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700858 /**
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700859 * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
860 * so we have baseline values without double-counting.
861 */
Jeff Sharkey63abc372012-01-11 18:38:16 -0800862 private void bootstrapStatsLocked() {
863 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
864 : System.currentTimeMillis();
865
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700866 try {
Jeff Sharkey63abc372012-01-11 18:38:16 -0800867 // snapshot and record current counters; read UID stats first to
868 // avoid overcounting dev stats.
869 final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700870 final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
871 final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800872
873 mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700874 mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700875 mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
876 mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800877
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700878 } catch (IllegalStateException e) {
879 Slog.w(TAG, "problem reading network stats: " + e);
880 } catch (RemoteException e) {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700881 // ignored; service lives in system_server
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700882 }
883 }
884
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700885 private void performPoll(int flags) {
Anders 3 Fridlund36bc5b62012-06-07 11:24:10 +0200886 // try refreshing time source when stale
887 if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
888 mTime.forceRefresh();
889 }
890
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700891 synchronized (mStatsLock) {
892 mWakeLock.acquire();
Jeff Sharkey684c54a2011-11-16 17:46:30 -0800893
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700894 try {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700895 performPollLocked(flags);
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700896 } finally {
897 mWakeLock.release();
898 }
899 }
900 }
901
902 /**
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700903 * Periodic poll operation, reading current statistics and recording into
904 * {@link NetworkStatsHistory}.
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700905 */
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700906 private void performPollLocked(int flags) {
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800907 if (!mSystemReady) return;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700908 if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800909
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700910 final long startRealtime = SystemClock.elapsedRealtime();
Jeff Sharkey75279902011-05-24 18:39:45 -0700911
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700912 final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
913 final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700914 final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700915
Jeff Sharkey75279902011-05-24 18:39:45 -0700916 // TODO: consider marking "untrusted" times in historical stats
917 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
918 : System.currentTimeMillis();
919
Jeff Sharkey75279902011-05-24 18:39:45 -0700920 try {
Jeff Sharkey63abc372012-01-11 18:38:16 -0800921 // snapshot and record current counters; read UID stats first to
922 // avoid overcounting dev stats.
923 final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700924 final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
925 final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700926
Jeff Sharkey63abc372012-01-11 18:38:16 -0800927 mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700928 mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700929 mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
930 mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700931
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700932 } catch (IllegalStateException e) {
933 Log.wtf(TAG, "problem reading network stats", e);
Jeff Sharkey905b5892011-09-30 15:19:49 -0700934 return;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700935 } catch (RemoteException e) {
936 // ignored; service lives in system_server
Jeff Sharkey905b5892011-09-30 15:19:49 -0700937 return;
938 }
939
Jeff Sharkey63abc372012-01-11 18:38:16 -0800940 // persist any pending data depending on requested flags
941 if (persistForce) {
942 mDevRecorder.forcePersistLocked(currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700943 mXtRecorder.forcePersistLocked(currentTime);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800944 mUidRecorder.forcePersistLocked(currentTime);
945 mUidTagRecorder.forcePersistLocked(currentTime);
946 } else {
947 if (persistNetwork) {
948 mDevRecorder.maybePersistLocked(currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700949 mXtRecorder.maybePersistLocked(currentTime);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800950 }
951 if (persistUid) {
952 mUidRecorder.maybePersistLocked(currentTime);
953 mUidTagRecorder.maybePersistLocked(currentTime);
954 }
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -0700955 }
Jeff Sharkey497e4432011-06-14 17:27:29 -0700956
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700957 if (LOGV) {
958 final long duration = SystemClock.elapsedRealtime() - startRealtime;
959 Slog.v(TAG, "performPollLocked() took " + duration + "ms");
960 }
961
Jeff Sharkey63abc372012-01-11 18:38:16 -0800962 if (mSettings.getSampleEnabled()) {
Jeff Sharkey905b5892011-09-30 15:19:49 -0700963 // sample stats after each full poll
Jeff Sharkey63abc372012-01-11 18:38:16 -0800964 performSampleLocked();
Jeff Sharkey905b5892011-09-30 15:19:49 -0700965 }
Jeff Sharkey07b0dd92011-09-01 13:06:19 -0700966
Jeff Sharkey497e4432011-06-14 17:27:29 -0700967 // finally, dispatch updated event to any listeners
968 final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
969 updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700970 mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
971 READ_NETWORK_USAGE_HISTORY);
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -0700972 }
973
974 /**
Jeff Sharkey07b0dd92011-09-01 13:06:19 -0700975 * Sample recent statistics summary into {@link EventLog}.
976 */
Jeff Sharkey63abc372012-01-11 18:38:16 -0800977 private void performSampleLocked() {
978 // TODO: migrate trustedtime fixes to separate binary log events
Jeff Sharkey905b5892011-09-30 15:19:49 -0700979 final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
980
Jeff Sharkey63abc372012-01-11 18:38:16 -0800981 NetworkTemplate template;
982 NetworkStats.Entry devTotal;
983 NetworkStats.Entry xtTotal;
984 NetworkStats.Entry uidTotal;
Jeff Sharkey07b0dd92011-09-01 13:06:19 -0700985
986 // collect mobile sample
Jeff Sharkey234766a2012-04-10 19:48:07 -0700987 template = buildTemplateMobileWildcard();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800988 devTotal = mDevRecorder.getTotalSinceBootLocked(template);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700989 xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800990 uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
Jeff Sharkey684c54a2011-11-16 17:46:30 -0800991
Jeff Sharkey905b5892011-09-30 15:19:49 -0700992 EventLogTags.writeNetstatsMobileSample(
993 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
994 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
995 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
Jeff Sharkey63abc372012-01-11 18:38:16 -0800996 trustedTime);
Jeff Sharkey07b0dd92011-09-01 13:06:19 -0700997
998 // collect wifi sample
Jeff Sharkey8fc27e82012-04-04 20:40:58 -0700999 template = buildTemplateWifiWildcard();
Jeff Sharkey63abc372012-01-11 18:38:16 -08001000 devTotal = mDevRecorder.getTotalSinceBootLocked(template);
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001001 xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001002 uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
1003
Jeff Sharkey905b5892011-09-30 15:19:49 -07001004 EventLogTags.writeNetstatsWifiSample(
1005 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1006 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1007 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
Jeff Sharkey63abc372012-01-11 18:38:16 -08001008 trustedTime);
Jeff Sharkey07b0dd92011-09-01 13:06:19 -07001009 }
1010
1011 /**
Jeff Sharkey63abc372012-01-11 18:38:16 -08001012 * Clean up {@link #mUidRecorder} after UID is removed.
Jeff Sharkeyb09540f2011-06-19 01:08:12 -07001013 */
Jeff Sharkeydaa57e82012-09-19 14:10:39 -07001014 private void removeUidsLocked(int... uids) {
1015 if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
1016
1017 // Perform one last poll before removing
Jeff Sharkey163e6442011-10-31 16:37:52 -07001018 performPollLocked(FLAG_PERSIST_ALL);
1019
Jeff Sharkeydaa57e82012-09-19 14:10:39 -07001020 mUidRecorder.removeUidsLocked(uids);
1021 mUidTagRecorder.removeUidsLocked(uids);
Jeff Sharkey163e6442011-10-31 16:37:52 -07001022
Jeff Sharkeydaa57e82012-09-19 14:10:39 -07001023 // Clear kernel stats associated with UID
1024 for (int uid : uids) {
1025 resetKernelUidStats(uid);
1026 }
1027 }
1028
1029 /**
1030 * Clean up {@link #mUidRecorder} after user is removed.
1031 */
1032 private void removeUserLocked(int userId) {
1033 if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
1034
1035 // Build list of UIDs that we should clean up
1036 int[] uids = new int[0];
1037 final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
1038 PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
1039 for (ApplicationInfo app : apps) {
1040 final int uid = UserHandle.getUid(userId, app.uid);
1041 uids = ArrayUtils.appendInt(uids, uid);
1042 }
1043
1044 removeUidsLocked(uids);
Jeff Sharkey75279902011-05-24 18:39:45 -07001045 }
1046
1047 @Override
Jeff Sharkey55a442e2014-11-18 18:22:21 -08001048 protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
Jeff Sharkey75279902011-05-24 18:39:45 -07001049 mContext.enforceCallingOrSelfPermission(DUMP, TAG);
1050
Jeff Sharkey55a442e2014-11-18 18:22:21 -08001051 long duration = DateUtils.DAY_IN_MILLIS;
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001052 final HashSet<String> argSet = new HashSet<String>();
1053 for (String arg : args) {
1054 argSet.add(arg);
Jeff Sharkey55a442e2014-11-18 18:22:21 -08001055
1056 if (arg.startsWith("--duration=")) {
1057 try {
1058 duration = Long.parseLong(arg.substring(11));
1059 } catch (NumberFormatException ignored) {
1060 }
1061 }
Jeff Sharkey75279902011-05-24 18:39:45 -07001062 }
1063
Jeff Sharkey706498d2012-02-06 17:35:07 -08001064 // usage: dumpsys netstats --full --uid --tag --poll --checkin
Jeff Sharkey63abc372012-01-11 18:38:16 -08001065 final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
Jeff Sharkey706498d2012-02-06 17:35:07 -08001066 final boolean checkin = argSet.contains("--checkin");
Jeff Sharkey63abc372012-01-11 18:38:16 -08001067 final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
1068 final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
1069 final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
1070
Jeff Sharkey55a442e2014-11-18 18:22:21 -08001071 final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, " ");
Jeff Sharkey350083e2011-06-29 10:45:16 -07001072
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001073 synchronized (mStatsLock) {
Jeff Sharkey63abc372012-01-11 18:38:16 -08001074 if (poll) {
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -07001075 performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
Jeff Sharkey3f391352011-06-05 17:42:53 -07001076 pw.println("Forced poll");
1077 return;
1078 }
1079
Jeff Sharkey706498d2012-02-06 17:35:07 -08001080 if (checkin) {
Jeff Sharkey55a442e2014-11-18 18:22:21 -08001081 final long end = System.currentTimeMillis();
1082 final long start = end - duration;
1083
1084 pw.print("v1,");
1085 pw.print(start / SECOND_IN_MILLIS); pw.print(',');
1086 pw.print(end / SECOND_IN_MILLIS); pw.println();
1087
1088 pw.println("xt");
1089 mXtRecorder.dumpCheckin(rawWriter, start, end);
1090
1091 if (includeUid) {
1092 pw.println("uid");
1093 mUidRecorder.dumpCheckin(rawWriter, start, end);
Jeff Sharkey706498d2012-02-06 17:35:07 -08001094 }
Jeff Sharkey55a442e2014-11-18 18:22:21 -08001095 if (includeTag) {
1096 pw.println("tag");
1097 mUidTagRecorder.dumpCheckin(rawWriter, start, end);
1098 }
Jeff Sharkey706498d2012-02-06 17:35:07 -08001099 return;
1100 }
1101
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001102 pw.println("Active interfaces:");
Jeff Sharkey63abc372012-01-11 18:38:16 -08001103 pw.increaseIndent();
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -07001104 for (int i = 0; i < mActiveIfaces.size(); i++) {
1105 pw.printPair("iface", mActiveIfaces.keyAt(i));
1106 pw.printPair("ident", mActiveIfaces.valueAt(i));
1107 pw.println();
1108 }
1109 pw.decreaseIndent();
1110
1111 pw.println("Active UID interfaces:");
1112 pw.increaseIndent();
1113 for (int i = 0; i < mActiveUidIfaces.size(); i++) {
1114 pw.printPair("iface", mActiveUidIfaces.keyAt(i));
1115 pw.printPair("ident", mActiveUidIfaces.valueAt(i));
1116 pw.println();
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001117 }
Jeff Sharkey63abc372012-01-11 18:38:16 -08001118 pw.decreaseIndent();
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001119
Jeff Sharkey63abc372012-01-11 18:38:16 -08001120 pw.println("Dev stats:");
1121 pw.increaseIndent();
1122 mDevRecorder.dumpLocked(pw, fullHistory);
1123 pw.decreaseIndent();
1124
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001125 pw.println("Xt stats:");
1126 pw.increaseIndent();
1127 mXtRecorder.dumpLocked(pw, fullHistory);
1128 pw.decreaseIndent();
1129
Jeff Sharkey63abc372012-01-11 18:38:16 -08001130 if (includeUid) {
1131 pw.println("UID stats:");
1132 pw.increaseIndent();
1133 mUidRecorder.dumpLocked(pw, fullHistory);
1134 pw.decreaseIndent();
Jeff Sharkey905b5892011-09-30 15:19:49 -07001135 }
1136
Jeff Sharkey63abc372012-01-11 18:38:16 -08001137 if (includeTag) {
1138 pw.println("UID tag stats:");
1139 pw.increaseIndent();
1140 mUidTagRecorder.dumpLocked(pw, fullHistory);
1141 pw.decreaseIndent();
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001142 }
1143 }
1144 }
1145
1146 /**
Jeff Sharkey63abc372012-01-11 18:38:16 -08001147 * Return snapshot of current UID statistics, including any
1148 * {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values.
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001149 */
Jeff Sharkey63abc372012-01-11 18:38:16 -08001150 private NetworkStats getNetworkStatsUidDetail() throws RemoteException {
1151 final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -07001152
Jeff Sharkey63abc372012-01-11 18:38:16 -08001153 // fold tethering stats and operations into uid snapshot
1154 final NetworkStats tetherSnapshot = getNetworkStatsTethering();
1155 uidSnapshot.combineAllValues(tetherSnapshot);
1156 uidSnapshot.combineAllValues(mUidOperations);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -07001157
Jeff Sharkey63abc372012-01-11 18:38:16 -08001158 return uidSnapshot;
Jeff Sharkey75279902011-05-24 18:39:45 -07001159 }
1160
Jeff Sharkeyd4ef8c8f2011-11-10 17:54:23 -08001161 /**
1162 * Return snapshot of current tethering statistics. Will return empty
1163 * {@link NetworkStats} if any problems are encountered.
1164 */
1165 private NetworkStats getNetworkStatsTethering() throws RemoteException {
1166 try {
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001167 return mNetworkManager.getNetworkStatsTethering();
Jeff Sharkeyd4ef8c8f2011-11-10 17:54:23 -08001168 } catch (IllegalStateException e) {
1169 Log.wtf(TAG, "problem reading network stats", e);
1170 return new NetworkStats(0L, 10);
1171 }
1172 }
1173
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001174 private Handler.Callback mHandlerCallback = new Handler.Callback() {
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001175 @Override
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001176 public boolean handleMessage(Message msg) {
1177 switch (msg.what) {
Jeff Sharkey8e9992a2011-08-23 18:37:23 -07001178 case MSG_PERFORM_POLL: {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -07001179 final int flags = msg.arg1;
1180 performPoll(flags);
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001181 return true;
1182 }
Jeff Sharkey367d15a2011-09-22 14:59:51 -07001183 case MSG_UPDATE_IFACES: {
1184 updateIfaces();
1185 return true;
1186 }
Jeff Sharkey25ce9ed2012-02-02 13:07:47 -08001187 case MSG_REGISTER_GLOBAL_ALERT: {
1188 registerGlobalAlert();
1189 return true;
1190 }
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001191 default: {
1192 return false;
1193 }
1194 }
1195 }
1196 };
1197
Jeff Sharkey4190a042012-04-21 15:36:48 -07001198 private void assertBandwidthControlEnabled() {
1199 if (!isBandwidthControlEnabled()) {
1200 throw new IllegalStateException("Bandwidth module disabled");
1201 }
1202 }
1203
Jeff Sharkey418d12d2011-12-13 15:38:03 -08001204 private boolean isBandwidthControlEnabled() {
Jeff Sharkey49c1d172012-04-23 14:39:19 -07001205 final long token = Binder.clearCallingIdentity();
Jeff Sharkey418d12d2011-12-13 15:38:03 -08001206 try {
1207 return mNetworkManager.isBandwidthControlEnabled();
1208 } catch (RemoteException e) {
1209 // ignored; service lives in system_server
1210 return false;
Jeff Sharkey49c1d172012-04-23 14:39:19 -07001211 } finally {
1212 Binder.restoreCallingIdentity(token);
Jeff Sharkey418d12d2011-12-13 15:38:03 -08001213 }
1214 }
1215
Jeff Sharkey63abc372012-01-11 18:38:16 -08001216 private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001217 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001218 public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
1219 int rightIndex, String cookie) {
1220 Log.w(TAG, "found non-monotonic values; saving to dropbox");
1221
1222 // record error for debugging
1223 final StringBuilder builder = new StringBuilder();
1224 builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
1225 + "] - right[" + rightIndex + "]\n");
1226 builder.append("left=").append(left).append('\n');
1227 builder.append("right=").append(right).append('\n');
1228
1229 final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
1230 Context.DROPBOX_SERVICE);
1231 dropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001232 }
1233 }
1234
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -07001235 /**
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001236 * Default external settings that read from
Jeff Sharkey625239a2012-09-26 22:03:49 -07001237 * {@link android.provider.Settings.Global}.
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001238 */
1239 private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
1240 private final ContentResolver mResolver;
1241
1242 public DefaultNetworkStatsSettings(Context context) {
1243 mResolver = checkNotNull(context.getContentResolver());
1244 // TODO: adjust these timings for production builds
1245 }
1246
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001247 private long getGlobalLong(String name, long def) {
1248 return Settings.Global.getLong(mResolver, name, def);
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001249 }
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001250 private boolean getGlobalBoolean(String name, boolean def) {
Jeff Sharkey991d1b12011-09-14 19:31:04 -07001251 final int defInt = def ? 1 : 0;
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001252 return Settings.Global.getInt(mResolver, name, defInt) != 0;
Jeff Sharkey991d1b12011-09-14 19:31:04 -07001253 }
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001254
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001255 @Override
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001256 public long getPollInterval() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001257 return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001258 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001259 @Override
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001260 public long getTimeCacheMaxAge() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001261 return getGlobalLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001262 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001263 @Override
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -07001264 public long getGlobalAlertBytes(long def) {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001265 return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001266 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001267 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001268 public boolean getSampleEnabled() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001269 return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001270 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001271 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001272 public Config getDevConfig() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001273 return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
1274 getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
1275 getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
Jeff Sharkey63abc372012-01-11 18:38:16 -08001276 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001277 @Override
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001278 public Config getXtConfig() {
1279 return getDevConfig();
1280 }
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001281 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001282 public Config getUidConfig() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001283 return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
1284 getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
1285 getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
Jeff Sharkey63abc372012-01-11 18:38:16 -08001286 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001287 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001288 public Config getUidTagConfig() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001289 return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
1290 getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
1291 getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -07001292 }
1293 @Override
1294 public long getDevPersistBytes(long def) {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001295 return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -07001296 }
1297 @Override
1298 public long getXtPersistBytes(long def) {
1299 return getDevPersistBytes(def);
1300 }
1301 @Override
1302 public long getUidPersistBytes(long def) {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001303 return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -07001304 }
1305 @Override
1306 public long getUidTagPersistBytes(long def) {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001307 return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001308 }
1309 }
Jeff Sharkey75279902011-05-24 18:39:45 -07001310}