blob: 5d6adc22685e4aa1fc1cc7084c41175c7aa0ac58 [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 Sharkey367d15a2011-09-22 14:59:51 -070029import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
Jeff Sharkey234766a2012-04-10 19:48:07 -070030import static android.net.ConnectivityManager.isNetworkTypeMobile;
Jeff Sharkeyd4dd7712012-03-16 11:11:54 -070031import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -070032import static android.net.NetworkStats.IFACE_ALL;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070033import static android.net.NetworkStats.SET_ALL;
34import static android.net.NetworkStats.SET_DEFAULT;
35import static android.net.NetworkStats.SET_FOREGROUND;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070036import static android.net.NetworkStats.TAG_NONE;
Jeff Sharkey75279902011-05-24 18:39:45 -070037import static android.net.NetworkStats.UID_ALL;
Jeff Sharkey234766a2012-04-10 19:48:07 -070038import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
Jeff Sharkey8fc27e82012-04-04 20:40:58 -070039import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -070040import static android.net.TrafficStats.KB_IN_BYTES;
Jeff Sharkey241dde22012-02-03 14:50:07 -080041import static android.net.TrafficStats.MB_IN_BYTES;
Jeff Sharkey023c05a2012-09-14 13:09:57 -070042import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
43import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
44import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
45import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE;
46import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
47import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
48import static android.provider.Settings.Global.NETSTATS_REPORT_XT_OVER_DEV;
49import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
50import static android.provider.Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE;
51import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
52import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
53import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
54import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE;
55import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
56import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
57import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
58import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
Jeff Sharkey367d15a2011-09-22 14:59:51 -070059import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
60import static android.telephony.PhoneStateListener.LISTEN_NONE;
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -070061import static android.text.format.DateUtils.DAY_IN_MILLIS;
62import static android.text.format.DateUtils.HOUR_IN_MILLIS;
63import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
Jeff Sharkey367d15a2011-09-22 14:59:51 -070064import static android.text.format.DateUtils.SECOND_IN_MILLIS;
Jeff Sharkey234766a2012-04-10 19:48:07 -070065import static com.android.internal.util.ArrayUtils.appendElement;
66import static com.android.internal.util.ArrayUtils.contains;
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070067import static com.android.internal.util.Preconditions.checkNotNull;
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070068import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -070069import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
70import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
Jeff Sharkey75279902011-05-24 18:39:45 -070071
72import android.app.AlarmManager;
73import android.app.IAlarmManager;
74import android.app.PendingIntent;
75import android.content.BroadcastReceiver;
Jeff Sharkey39ebc212011-06-11 17:25:42 -070076import android.content.ContentResolver;
Jeff Sharkey75279902011-05-24 18:39:45 -070077import android.content.Context;
78import android.content.Intent;
79import android.content.IntentFilter;
Jeff Sharkeydaa57e82012-09-19 14:10:39 -070080import android.content.pm.ApplicationInfo;
81import android.content.pm.PackageManager;
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070082import android.net.IConnectivityManager;
Jeff Sharkey8e9992a2011-08-23 18:37:23 -070083import android.net.INetworkManagementEventObserver;
Jeff Sharkey75279902011-05-24 18:39:45 -070084import android.net.INetworkStatsService;
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -070085import android.net.INetworkStatsSession;
Jeff Sharkey63abc372012-01-11 18:38:16 -080086import android.net.LinkProperties;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070087import android.net.NetworkIdentity;
Jeff Sharkeyd2a45872011-05-28 20:56:34 -070088import android.net.NetworkInfo;
89import android.net.NetworkState;
Jeff Sharkey75279902011-05-24 18:39:45 -070090import android.net.NetworkStats;
Jeff Sharkey5a7bcf32012-01-10 17:24:44 -080091import android.net.NetworkStats.NonMonotonicObserver;
Jeff Sharkey75279902011-05-24 18:39:45 -070092import android.net.NetworkStatsHistory;
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -070093import android.net.NetworkTemplate;
Jeff Sharkey63abc372012-01-11 18:38:16 -080094import android.net.TrafficStats;
Jeff Sharkeya63ba592011-07-19 23:47:12 -070095import android.os.Binder;
Jeff Sharkey163e6442011-10-31 16:37:52 -070096import android.os.DropBoxManager;
Jeff Sharkey3f391352011-06-05 17:42:53 -070097import android.os.Environment;
Jeff Sharkey75279902011-05-24 18:39:45 -070098import android.os.Handler;
Amith Yamasani450a16b2013-09-18 16:28:50 -070099import android.os.HandlerThread;
Jeff Sharkey75279902011-05-24 18:39:45 -0700100import android.os.INetworkManagementService;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700101import android.os.Message;
Jeff Sharkey62489262011-07-17 12:53:28 -0700102import android.os.PowerManager;
Jeff Sharkey75279902011-05-24 18:39:45 -0700103import android.os.RemoteException;
104import android.os.SystemClock;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700105import android.os.UserHandle;
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -0700106import android.provider.Settings;
Jeff Sharkey625239a2012-09-26 22:03:49 -0700107import android.provider.Settings.Global;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700108import android.telephony.PhoneStateListener;
Jeff Sharkey75279902011-05-24 18:39:45 -0700109import android.telephony.TelephonyManager;
Jeff Sharkey07b0dd92011-09-01 13:06:19 -0700110import android.util.EventLog;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700111import android.util.Log;
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700112import android.util.MathUtils;
Jeff Sharkey75279902011-05-24 18:39:45 -0700113import android.util.NtpTrustedTime;
114import android.util.Slog;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700115import android.util.SparseIntArray;
Jeff Sharkey75279902011-05-24 18:39:45 -0700116import android.util.TrustedTime;
117
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800118import com.android.internal.annotations.VisibleForTesting;
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700119import com.android.internal.util.ArrayUtils;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800120import com.android.internal.util.FileRotator;
121import com.android.internal.util.IndentingPrintWriter;
Jeff Sharkey07b0dd92011-09-01 13:06:19 -0700122import com.android.server.EventLogTags;
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700123import com.android.server.connectivity.Tethering;
Jeff Sharkey75279902011-05-24 18:39:45 -0700124import com.google.android.collect.Maps;
125
Jeff Sharkey3f391352011-06-05 17:42:53 -0700126import java.io.File;
Jeff Sharkey75279902011-05-24 18:39:45 -0700127import java.io.FileDescriptor;
Jeff Sharkey3f391352011-06-05 17:42:53 -0700128import java.io.IOException;
Jeff Sharkey75279902011-05-24 18:39:45 -0700129import java.io.PrintWriter;
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700130import java.util.Arrays;
Jeff Sharkey75279902011-05-24 18:39:45 -0700131import java.util.HashMap;
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -0700132import java.util.HashSet;
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700133import java.util.List;
Jeff Sharkey3f391352011-06-05 17:42:53 -0700134
Jeff Sharkey75279902011-05-24 18:39:45 -0700135/**
136 * Collect and persist detailed network statistics, and provide this data to
137 * other system services.
138 */
139public class NetworkStatsService extends INetworkStatsService.Stub {
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700140 private static final String TAG = "NetworkStats";
Jeff Sharkey706498d2012-02-06 17:35:07 -0800141 private static final boolean LOGV = false;
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700142
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700143 private static final int MSG_PERFORM_POLL = 1;
144 private static final int MSG_UPDATE_IFACES = 2;
Jeff Sharkey25ce9ed2012-02-02 13:07:47 -0800145 private static final int MSG_REGISTER_GLOBAL_ALERT = 3;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700146
147 /** Flags to control detail level of poll event. */
Jeff Sharkey905b5892011-09-30 15:19:49 -0700148 private static final int FLAG_PERSIST_NETWORK = 0x1;
149 private static final int FLAG_PERSIST_UID = 0x2;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700150 private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700151 private static final int FLAG_PERSIST_FORCE = 0x100;
Jeff Sharkey3f391352011-06-05 17:42:53 -0700152
Jeff Sharkey163e6442011-10-31 16:37:52 -0700153 private static final String TAG_NETSTATS_ERROR = "netstats_error";
154
Jeff Sharkey75279902011-05-24 18:39:45 -0700155 private final Context mContext;
156 private final INetworkManagementService mNetworkManager;
Christopher Tatee0a22b32013-07-11 14:43:13 -0700157 private final AlarmManager mAlarmManager;
Jeff Sharkey75279902011-05-24 18:39:45 -0700158 private final TrustedTime mTime;
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700159 private final TelephonyManager mTeleManager;
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700160 private final NetworkStatsSettings mSettings;
Jeff Sharkey75279902011-05-24 18:39:45 -0700161
Jeff Sharkey63abc372012-01-11 18:38:16 -0800162 private final File mSystemDir;
163 private final File mBaseDir;
164
Jeff Sharkey62489262011-07-17 12:53:28 -0700165 private final PowerManager.WakeLock mWakeLock;
166
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700167 private IConnectivityManager mConnManager;
168
Jeff Sharkey8b2c3a142012-11-12 11:45:05 -0800169 @VisibleForTesting
Jeff Sharkey3f391352011-06-05 17:42:53 -0700170 public static final String ACTION_NETWORK_STATS_POLL =
Jeff Sharkey75279902011-05-24 18:39:45 -0700171 "com.android.server.action.NETWORK_STATS_POLL";
Jeff Sharkey497e4432011-06-14 17:27:29 -0700172 public static final String ACTION_NETWORK_STATS_UPDATED =
173 "com.android.server.action.NETWORK_STATS_UPDATED";
Jeff Sharkey75279902011-05-24 18:39:45 -0700174
175 private PendingIntent mPollIntent;
176
Jeff Sharkey63abc372012-01-11 18:38:16 -0800177 private static final String PREFIX_DEV = "dev";
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700178 private static final String PREFIX_XT = "xt";
Jeff Sharkey63abc372012-01-11 18:38:16 -0800179 private static final String PREFIX_UID = "uid";
180 private static final String PREFIX_UID_TAG = "uid_tag";
181
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700182 /**
183 * Settings that can be changed externally.
184 */
185 public interface NetworkStatsSettings {
186 public long getPollInterval();
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700187 public long getTimeCacheMaxAge();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800188 public boolean getSampleEnabled();
Jeff Sharkey70c70532012-05-16 14:51:19 -0700189 public boolean getReportXtOverDev();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800190
191 public static class Config {
192 public final long bucketDuration;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800193 public final long rotateAgeMillis;
194 public final long deleteAgeMillis;
195
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700196 public Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis) {
Jeff Sharkey63abc372012-01-11 18:38:16 -0800197 this.bucketDuration = bucketDuration;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800198 this.rotateAgeMillis = rotateAgeMillis;
199 this.deleteAgeMillis = deleteAgeMillis;
200 }
201 }
202
203 public Config getDevConfig();
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700204 public Config getXtConfig();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800205 public Config getUidConfig();
206 public Config getUidTagConfig();
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700207
208 public long getGlobalAlertBytes(long def);
209 public long getDevPersistBytes(long def);
210 public long getXtPersistBytes(long def);
211 public long getUidPersistBytes(long def);
212 public long getUidTagPersistBytes(long def);
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700213 }
Jeff Sharkey75279902011-05-24 18:39:45 -0700214
215 private final Object mStatsLock = new Object();
216
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700217 /** Set of currently active ifaces. */
218 private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800219 /** Current default active iface. */
220 private String mActiveIface;
Jeff Sharkey234766a2012-04-10 19:48:07 -0700221 /** Set of any ifaces associated with mobile networks since boot. */
222 private String[] mMobileIfaces = new String[0];
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -0700223
Jeff Sharkey63abc372012-01-11 18:38:16 -0800224 private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
225 new DropBoxNonMonotonicObserver();
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -0700226
Jeff Sharkey63abc372012-01-11 18:38:16 -0800227 private NetworkStatsRecorder mDevRecorder;
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700228 private NetworkStatsRecorder mXtRecorder;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800229 private NetworkStatsRecorder mUidRecorder;
230 private NetworkStatsRecorder mUidTagRecorder;
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700231
Jeff Sharkey63abc372012-01-11 18:38:16 -0800232 /** Cached {@link #mDevRecorder} stats. */
233 private NetworkStatsCollection mDevStatsCached;
Jeff Sharkey70c70532012-05-16 14:51:19 -0700234 /** Cached {@link #mXtRecorder} stats. */
235 private NetworkStatsCollection mXtStatsCached;
Jeff Sharkey75279902011-05-24 18:39:45 -0700236
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700237 /** Current counter sets for each UID. */
238 private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
239
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700240 /** Data layer operation counters for splicing into other structures. */
Jeff Sharkey63abc372012-01-11 18:38:16 -0800241 private NetworkStats mUidOperations = new NetworkStats(0L, 10);
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700242
Jeff Sharkey75279902011-05-24 18:39:45 -0700243 private final Handler mHandler;
244
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800245 private boolean mSystemReady;
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700246 private long mPersistThreshold = 2 * MB_IN_BYTES;
247 private long mGlobalAlertBytes;
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800248
Jeff Sharkey75279902011-05-24 18:39:45 -0700249 public NetworkStatsService(
250 Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
Jeff Sharkey104344e2011-07-10 14:20:41 -0700251 this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
Jeff Sharkey63abc372012-01-11 18:38:16 -0800252 getDefaultSystemDir(), new DefaultNetworkStatsSettings(context));
Jeff Sharkey3f391352011-06-05 17:42:53 -0700253 }
254
Jeff Sharkey63abc372012-01-11 18:38:16 -0800255 private static File getDefaultSystemDir() {
Jeff Sharkey3f391352011-06-05 17:42:53 -0700256 return new File(Environment.getDataDirectory(), "system");
Jeff Sharkey75279902011-05-24 18:39:45 -0700257 }
258
259 public NetworkStatsService(Context context, INetworkManagementService networkManager,
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700260 IAlarmManager alarmManager, TrustedTime time, File systemDir,
261 NetworkStatsSettings settings) {
Jeff Sharkey75279902011-05-24 18:39:45 -0700262 mContext = checkNotNull(context, "missing Context");
263 mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
Jeff Sharkey75279902011-05-24 18:39:45 -0700264 mTime = checkNotNull(time, "missing TrustedTime");
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700265 mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700266 mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
Christopher Tatee0a22b32013-07-11 14:43:13 -0700267 mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Jeff Sharkey75279902011-05-24 18:39:45 -0700268
Jeff Sharkey62489262011-07-17 12:53:28 -0700269 final PowerManager powerManager = (PowerManager) context.getSystemService(
270 Context.POWER_SERVICE);
271 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
272
Amith Yamasani450a16b2013-09-18 16:28:50 -0700273 HandlerThread thread = new HandlerThread(TAG);
274 thread.start();
275 mHandler = new Handler(thread.getLooper(), mHandlerCallback);
Jeff Sharkey3f391352011-06-05 17:42:53 -0700276
Jeff Sharkey63abc372012-01-11 18:38:16 -0800277 mSystemDir = checkNotNull(systemDir);
278 mBaseDir = new File(systemDir, "netstats");
279 mBaseDir.mkdirs();
Jeff Sharkey75279902011-05-24 18:39:45 -0700280 }
281
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700282 public void bindConnectivityManager(IConnectivityManager connManager) {
283 mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
284 }
285
Jeff Sharkey75279902011-05-24 18:39:45 -0700286 public void systemReady() {
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800287 mSystemReady = true;
288
Jeff Sharkey418d12d2011-12-13 15:38:03 -0800289 if (!isBandwidthControlEnabled()) {
290 Slog.w(TAG, "bandwidth controls disabled, unable to track stats");
291 return;
292 }
293
Jeff Sharkey63abc372012-01-11 18:38:16 -0800294 // create data recorders along with historical rotators
295 mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700296 mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800297 mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
298 mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
Jeff Sharkey75279902011-05-24 18:39:45 -0700299
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700300 updatePersistThresholds();
301
Jeff Sharkey63abc372012-01-11 18:38:16 -0800302 synchronized (mStatsLock) {
303 // upgrade any legacy stats, migrating them to rotated files
304 maybeUpgradeLegacyStatsLocked();
305
306 // read historical network stats from disk, since policy service
307 // might need them right away.
308 mDevStatsCached = mDevRecorder.getOrLoadCompleteLocked();
Jeff Sharkey70c70532012-05-16 14:51:19 -0700309 mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800310
311 // bootstrap initial stats to prevent double-counting later
312 bootstrapStatsLocked();
313 }
Jeff Sharkey3359aca2011-11-08 18:08:48 -0800314
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700315 // watch for network interfaces to be claimed
Jeff Sharkey961e3042011-08-29 16:02:57 -0700316 final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700317 mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
Jeff Sharkey75279902011-05-24 18:39:45 -0700318
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700319 // watch for tethering changes
320 final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
321 mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler);
322
Jeff Sharkey75279902011-05-24 18:39:45 -0700323 // listen for periodic polling events
324 final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
Jeff Sharkey21c9c452011-06-07 12:26:43 -0700325 mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
Jeff Sharkey75279902011-05-24 18:39:45 -0700326
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700327 // listen for uid removal to clean stats
328 final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
329 mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
330
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700331 // listen for user changes to clean stats
332 final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
333 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
334
Jeff Sharkey75279902011-05-24 18:39:45 -0700335 // persist stats during clean shutdown
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700336 final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
337 mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
Jeff Sharkey75279902011-05-24 18:39:45 -0700338
339 try {
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700340 mNetworkManager.registerObserver(mAlertObserver);
Jeff Sharkey75279902011-05-24 18:39:45 -0700341 } catch (RemoteException e) {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700342 // ignored; service lives in system_server
Jeff Sharkey75279902011-05-24 18:39:45 -0700343 }
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700344
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700345 // watch for networkType changes that aren't broadcast through
346 // CONNECTIVITY_ACTION_IMMEDIATE above.
Jeff Sharkeyd4dd7712012-03-16 11:11:54 -0700347 if (!COMBINE_SUBTYPE_ENABLED) {
348 mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
349 }
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700350
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700351 registerPollAlarmLocked();
352 registerGlobalAlert();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800353 }
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700354
Jeff Sharkey63abc372012-01-11 18:38:16 -0800355 private NetworkStatsRecorder buildRecorder(
356 String prefix, NetworkStatsSettings.Config config, boolean includeTags) {
Jeff Sharkey6de357e2012-05-09 13:33:52 -0700357 final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
358 Context.DROPBOX_SERVICE);
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700359 return new NetworkStatsRecorder(new FileRotator(
360 mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
Jeff Sharkey6de357e2012-05-09 13:33:52 -0700361 mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
Jeff Sharkey75279902011-05-24 18:39:45 -0700362 }
363
Jeff Sharkey3f391352011-06-05 17:42:53 -0700364 private void shutdownLocked() {
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700365 mContext.unregisterReceiver(mConnReceiver);
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700366 mContext.unregisterReceiver(mTetherReceiver);
Jeff Sharkey3f391352011-06-05 17:42:53 -0700367 mContext.unregisterReceiver(mPollReceiver);
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700368 mContext.unregisterReceiver(mRemovedReceiver);
Jeff Sharkey3f391352011-06-05 17:42:53 -0700369 mContext.unregisterReceiver(mShutdownReceiver);
370
Jeff Sharkeyd4dd7712012-03-16 11:11:54 -0700371 if (!COMBINE_SUBTYPE_ENABLED) {
372 mTeleManager.listen(mPhoneListener, LISTEN_NONE);
373 }
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700374
Jeff Sharkey63abc372012-01-11 18:38:16 -0800375 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
376 : System.currentTimeMillis();
377
378 // persist any pending stats
379 mDevRecorder.forcePersistLocked(currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700380 mXtRecorder.forcePersistLocked(currentTime);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800381 mUidRecorder.forcePersistLocked(currentTime);
382 mUidTagRecorder.forcePersistLocked(currentTime);
383
384 mDevRecorder = null;
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700385 mXtRecorder = null;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800386 mUidRecorder = null;
387 mUidTagRecorder = null;
388
389 mDevStatsCached = null;
Jeff Sharkey70c70532012-05-16 14:51:19 -0700390 mXtStatsCached = null;
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800391
392 mSystemReady = false;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800393 }
394
395 private void maybeUpgradeLegacyStatsLocked() {
396 File file;
397 try {
398 file = new File(mSystemDir, "netstats.bin");
399 if (file.exists()) {
400 mDevRecorder.importLegacyNetworkLocked(file);
401 file.delete();
402 }
403
404 file = new File(mSystemDir, "netstats_xt.bin");
405 if (file.exists()) {
406 file.delete();
407 }
408
409 file = new File(mSystemDir, "netstats_uid.bin");
410 if (file.exists()) {
411 mUidRecorder.importLegacyUidLocked(file);
412 mUidTagRecorder.importLegacyUidLocked(file);
413 file.delete();
414 }
415 } catch (IOException e) {
416 Log.wtf(TAG, "problem during legacy upgrade", e);
Jeff Sharkeye4984be2013-09-10 21:03:27 -0700417 } catch (OutOfMemoryError e) {
418 Log.wtf(TAG, "problem during legacy upgrade", e);
Jeff Sharkeyc506ff62011-11-17 11:59:29 -0800419 }
Jeff Sharkey3f391352011-06-05 17:42:53 -0700420 }
421
Jeff Sharkey75279902011-05-24 18:39:45 -0700422 /**
423 * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700424 * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
Jeff Sharkey75279902011-05-24 18:39:45 -0700425 */
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700426 private void registerPollAlarmLocked() {
Christopher Tatee0a22b32013-07-11 14:43:13 -0700427 if (mPollIntent != null) {
428 mAlarmManager.cancel(mPollIntent);
Jeff Sharkey75279902011-05-24 18:39:45 -0700429 }
Christopher Tatee0a22b32013-07-11 14:43:13 -0700430
431 mPollIntent = PendingIntent.getBroadcast(
432 mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
433
434 final long currentRealtime = SystemClock.elapsedRealtime();
435 mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
436 mSettings.getPollInterval(), mPollIntent);
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700437 }
Jeff Sharkey75279902011-05-24 18:39:45 -0700438
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700439 /**
440 * Register for a global alert that is delivered through
441 * {@link INetworkManagementEventObserver} once a threshold amount of data
442 * has been transferred.
443 */
444 private void registerGlobalAlert() {
445 try {
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700446 mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700447 } catch (IllegalStateException e) {
448 Slog.w(TAG, "problem registering for global alert: " + e);
449 } catch (RemoteException e) {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700450 // ignored; service lives in system_server
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700451 }
Jeff Sharkey75279902011-05-24 18:39:45 -0700452 }
453
454 @Override
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700455 public INetworkStatsSession openSession() {
456 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
Jeff Sharkey4190a042012-04-21 15:36:48 -0700457 assertBandwidthControlEnabled();
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700458
459 // return an IBinder which holds strong references to any loaded stats
460 // for its lifetime; when caller closes only weak references remain.
461
462 return new INetworkStatsSession.Stub() {
463 private NetworkStatsCollection mUidComplete;
464 private NetworkStatsCollection mUidTagComplete;
465
466 private NetworkStatsCollection getUidComplete() {
467 if (mUidComplete == null) {
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700468 synchronized (mStatsLock) {
469 mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
470 }
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700471 }
472 return mUidComplete;
473 }
474
475 private NetworkStatsCollection getUidTagComplete() {
476 if (mUidTagComplete == null) {
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700477 synchronized (mStatsLock) {
478 mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
479 }
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700480 }
481 return mUidTagComplete;
482 }
483
484 @Override
485 public NetworkStats getSummaryForNetwork(
486 NetworkTemplate template, long start, long end) {
Jeff Sharkey70c70532012-05-16 14:51:19 -0700487 return internalGetSummaryForNetwork(template, start, end);
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700488 }
489
490 @Override
491 public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
Jeff Sharkey70c70532012-05-16 14:51:19 -0700492 return internalGetHistoryForNetwork(template, fields);
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700493 }
494
495 @Override
496 public NetworkStats getSummaryForAllUid(
497 NetworkTemplate template, long start, long end, boolean includeTags) {
498 final NetworkStats stats = getUidComplete().getSummary(template, start, end);
499 if (includeTags) {
500 final NetworkStats tagStats = getUidTagComplete()
501 .getSummary(template, start, end);
502 stats.combineAllValues(tagStats);
503 }
504 return stats;
505 }
506
507 @Override
508 public NetworkStatsHistory getHistoryForUid(
509 NetworkTemplate template, int uid, int set, int tag, int fields) {
510 if (tag == TAG_NONE) {
511 return getUidComplete().getHistory(template, uid, set, tag, fields);
512 } else {
513 return getUidTagComplete().getHistory(template, uid, set, tag, fields);
514 }
515 }
516
517 @Override
518 public void close() {
519 mUidComplete = null;
520 mUidTagComplete = null;
521 }
522 };
Jeff Sharkey905b5892011-09-30 15:19:49 -0700523 }
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700524
Jeff Sharkey70c70532012-05-16 14:51:19 -0700525 /**
526 * Return network summary, splicing between {@link #mDevStatsCached}
527 * and {@link #mXtStatsCached} when appropriate.
528 */
529 private NetworkStats internalGetSummaryForNetwork(
530 NetworkTemplate template, long start, long end) {
531 if (!mSettings.getReportXtOverDev()) {
532 // shortcut when XT reporting disabled
533 return mDevStatsCached.getSummary(template, start, end);
534 }
535
536 // splice stats between DEV and XT, switching over from DEV to XT at
537 // first atomic bucket.
538 final long firstAtomicBucket = mXtStatsCached.getFirstAtomicBucketMillis();
539 final NetworkStats dev = mDevStatsCached.getSummary(
540 template, Math.min(start, firstAtomicBucket), Math.min(end, firstAtomicBucket));
541 final NetworkStats xt = mXtStatsCached.getSummary(
542 template, Math.max(start, firstAtomicBucket), Math.max(end, firstAtomicBucket));
543
544 xt.combineAllValues(dev);
545 return xt;
546 }
547
548 /**
549 * Return network history, splicing between {@link #mDevStatsCached}
550 * and {@link #mXtStatsCached} when appropriate.
551 */
552 private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, int fields) {
553 if (!mSettings.getReportXtOverDev()) {
554 // shortcut when XT reporting disabled
555 return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
556 }
557
558 // splice stats between DEV and XT, switching over from DEV to XT at
559 // first atomic bucket.
560 final long firstAtomicBucket = mXtStatsCached.getFirstAtomicBucketMillis();
561 final NetworkStatsHistory dev = mDevStatsCached.getHistory(
562 template, UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, firstAtomicBucket);
563 final NetworkStatsHistory xt = mXtStatsCached.getHistory(
564 template, UID_ALL, SET_ALL, TAG_NONE, fields, firstAtomicBucket, Long.MAX_VALUE);
565
566 xt.recordEntireHistory(dev);
567 return xt;
568 }
569
Jeff Sharkey63abc372012-01-11 18:38:16 -0800570 @Override
Jeff Sharkeyb52e3e52012-04-06 11:12:08 -0700571 public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
572 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
Jeff Sharkey4190a042012-04-21 15:36:48 -0700573 assertBandwidthControlEnabled();
Jeff Sharkey70c70532012-05-16 14:51:19 -0700574 return internalGetSummaryForNetwork(template, start, end).getTotalBytes();
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700575 }
576
Jeff Sharkey350083e2011-06-29 10:45:16 -0700577 @Override
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700578 public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
579 if (Binder.getCallingUid() != uid) {
580 mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
581 }
Jeff Sharkey4190a042012-04-21 15:36:48 -0700582 assertBandwidthControlEnabled();
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700583
584 // TODO: switch to data layer stats once kernel exports
585 // for now, read network layer stats and flatten across all ifaces
Jeff Sharkey4529bb62011-12-14 10:31:54 -0800586 final long token = Binder.clearCallingIdentity();
587 final NetworkStats networkLayer;
588 try {
589 networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid);
590 } finally {
591 Binder.restoreCallingIdentity(token);
592 }
593
Jeff Sharkey21a54782012-04-09 10:27:55 -0700594 // splice in operation counts
595 networkLayer.spliceOperationsFrom(mUidOperations);
596
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700597 final NetworkStats dataLayer = new NetworkStats(
598 networkLayer.getElapsedRealtime(), networkLayer.size());
599
600 NetworkStats.Entry entry = null;
601 for (int i = 0; i < networkLayer.size(); i++) {
602 entry = networkLayer.getValues(i, entry);
603 entry.iface = IFACE_ALL;
604 dataLayer.combineValues(entry);
605 }
606
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700607 return dataLayer;
608 }
609
610 @Override
Jeff Sharkey234766a2012-04-10 19:48:07 -0700611 public String[] getMobileIfaces() {
612 return mMobileIfaces;
613 }
614
615 @Override
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700616 public void incrementOperationCount(int uid, int tag, int operationCount) {
617 if (Binder.getCallingUid() != uid) {
618 mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
619 }
620
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700621 if (operationCount < 0) {
622 throw new IllegalArgumentException("operation count can only be incremented");
623 }
624 if (tag == TAG_NONE) {
625 throw new IllegalArgumentException("operation count must have specific tag");
626 }
627
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700628 synchronized (mStatsLock) {
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700629 final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800630 mUidOperations.combineValues(
631 mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
632 mUidOperations.combineValues(
633 mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -0700634 }
635 }
636
637 @Override
638 public void setUidForeground(int uid, boolean uidForeground) {
639 mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
640
641 synchronized (mStatsLock) {
642 final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
643 final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
644 if (oldSet != set) {
645 mActiveUidCounterSet.put(uid, set);
646 setKernelCounterSet(uid, set);
647 }
Jeff Sharkeya63ba592011-07-19 23:47:12 -0700648 }
649 }
650
651 @Override
Jeff Sharkey350083e2011-06-29 10:45:16 -0700652 public void forceUpdate() {
653 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
Jeff Sharkey4190a042012-04-21 15:36:48 -0700654 assertBandwidthControlEnabled();
Jeff Sharkeye630f7b2012-01-31 17:12:53 -0800655
656 final long token = Binder.clearCallingIdentity();
657 try {
658 performPoll(FLAG_PERSIST_ALL);
659 } finally {
660 Binder.restoreCallingIdentity(token);
661 }
Jeff Sharkey350083e2011-06-29 10:45:16 -0700662 }
663
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700664 @Override
665 public void advisePersistThreshold(long thresholdBytes) {
666 mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
667 assertBandwidthControlEnabled();
668
669 // clamp threshold into safe range
670 mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700671 if (LOGV) {
672 Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
673 + mPersistThreshold);
674 }
675
Jeff Sharkey20f5c3d2012-05-09 19:59:07 -0700676 // update and persist if beyond new thresholds
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700677 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
678 : System.currentTimeMillis();
Jeff Sharkey58015972012-05-07 11:08:49 -0700679 synchronized (mStatsLock) {
Jeff Sharkey20f5c3d2012-05-09 19:59:07 -0700680 if (!mSystemReady) return;
681
682 updatePersistThresholds();
683
Jeff Sharkey58015972012-05-07 11:08:49 -0700684 mDevRecorder.maybePersistLocked(currentTime);
685 mXtRecorder.maybePersistLocked(currentTime);
686 mUidRecorder.maybePersistLocked(currentTime);
687 mUidTagRecorder.maybePersistLocked(currentTime);
688 }
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700689
690 // re-arm global alert
691 registerGlobalAlert();
692 }
693
694 /**
695 * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
696 * reflect current {@link #mPersistThreshold} value. Always defers to
Jeff Sharkey625239a2012-09-26 22:03:49 -0700697 * {@link Global} values when defined.
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -0700698 */
699 private void updatePersistThresholds() {
700 mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
701 mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
702 mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
703 mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
704 mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold);
705 }
706
Jeff Sharkey75279902011-05-24 18:39:45 -0700707 /**
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700708 * Receiver that watches for {@link IConnectivityManager} to claim network
Jeff Sharkey75279902011-05-24 18:39:45 -0700709 * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
710 * with mobile interfaces.
711 */
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700712 private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
Jeff Sharkey75279902011-05-24 18:39:45 -0700713 @Override
714 public void onReceive(Context context, Intent intent) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700715 // on background handler thread, and verified CONNECTIVITY_INTERNAL
716 // permission above.
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700717 updateIfaces();
Jeff Sharkey75279902011-05-24 18:39:45 -0700718 }
719 };
720
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700721 /**
722 * Receiver that watches for {@link Tethering} to claim interface pairs.
723 */
724 private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
725 @Override
726 public void onReceive(Context context, Intent intent) {
727 // on background handler thread, and verified CONNECTIVITY_INTERNAL
728 // permission above.
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700729 performPoll(FLAG_PERSIST_NETWORK);
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700730 }
731 };
732
Jeff Sharkey75279902011-05-24 18:39:45 -0700733 private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
734 @Override
735 public void onReceive(Context context, Intent intent) {
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700736 // on background handler thread, and verified UPDATE_DEVICE_STATS
737 // permission above.
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700738 performPoll(FLAG_PERSIST_ALL);
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700739
740 // verify that we're watching global alert
741 registerGlobalAlert();
Jeff Sharkey75279902011-05-24 18:39:45 -0700742 }
743 };
744
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700745 private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
746 @Override
747 public void onReceive(Context context, Intent intent) {
748 // on background handler thread, and UID_REMOVED is protected
749 // broadcast.
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700750
751 final int uid = intent.getIntExtra(EXTRA_UID, -1);
752 if (uid == -1) return;
753
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700754 synchronized (mStatsLock) {
Jeff Sharkey62489262011-07-17 12:53:28 -0700755 mWakeLock.acquire();
756 try {
Jeff Sharkeydaa57e82012-09-19 14:10:39 -0700757 removeUidsLocked(uid);
758 } finally {
759 mWakeLock.release();
760 }
761 }
762 }
763 };
764
765 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
766 @Override
767 public void onReceive(Context context, Intent intent) {
768 // On background handler thread, and USER_REMOVED is protected
769 // broadcast.
770
771 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
772 if (userId == -1) return;
773
774 synchronized (mStatsLock) {
775 mWakeLock.acquire();
776 try {
777 removeUserLocked(userId);
Jeff Sharkey62489262011-07-17 12:53:28 -0700778 } finally {
779 mWakeLock.release();
780 }
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700781 }
782 }
783 };
784
Jeff Sharkey75279902011-05-24 18:39:45 -0700785 private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
786 @Override
787 public void onReceive(Context context, Intent intent) {
Jeff Sharkeyb09540f2011-06-19 01:08:12 -0700788 // SHUTDOWN is protected broadcast.
Jeff Sharkey75279902011-05-24 18:39:45 -0700789 synchronized (mStatsLock) {
Jeff Sharkey3f391352011-06-05 17:42:53 -0700790 shutdownLocked();
Jeff Sharkey75279902011-05-24 18:39:45 -0700791 }
792 }
793 };
794
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700795 /**
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700796 * Observer that watches for {@link INetworkManagementService} alerts.
797 */
Jeff Sharkey216c1812012-08-05 14:29:23 -0700798 private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700799 @Override
800 public void limitReached(String limitName, String iface) {
801 // only someone like NMS should be calling us
802 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
803
804 if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
805 // kick off background poll to collect network stats; UID stats
806 // are handled during normal polling interval.
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700807 final int flags = FLAG_PERSIST_NETWORK;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700808 mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700809
810 // re-arm global alert for next update
Jeff Sharkey25ce9ed2012-02-02 13:07:47 -0800811 mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget();
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700812 }
813 }
814 };
815
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700816 private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN;
817 private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
818
819 /**
820 * Receiver that watches for {@link TelephonyManager} changes, such as
821 * transitioning between network types.
822 */
823 private PhoneStateListener mPhoneListener = new PhoneStateListener() {
824 @Override
825 public void onDataConnectionStateChanged(int state, int networkType) {
826 final boolean stateChanged = state != mLastPhoneState;
827 final boolean networkTypeChanged = networkType != mLastPhoneNetworkType;
828
829 if (networkTypeChanged && !stateChanged) {
830 // networkType changed without a state change, which means we
831 // need to roll our own update. delay long enough for
832 // ConnectivityManager to process.
833 // TODO: add direct event to ConnectivityService instead of
834 // relying on this delay.
835 if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()");
836 mHandler.sendMessageDelayed(
837 mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS);
838 }
839
840 mLastPhoneState = state;
841 mLastPhoneNetworkType = networkType;
842 }
843 };
844
845 private void updateIfaces() {
846 synchronized (mStatsLock) {
847 mWakeLock.acquire();
848 try {
849 updateIfacesLocked();
850 } finally {
851 mWakeLock.release();
852 }
853 }
854 }
855
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700856 /**
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700857 * Inspect all current {@link NetworkState} to derive mapping from {@code
858 * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
859 * are active on a single {@code iface}, they are combined under a single
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700860 * {@link NetworkIdentitySet}.
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700861 */
862 private void updateIfacesLocked() {
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800863 if (!mSystemReady) return;
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700864 if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700865
866 // take one last stats snapshot before updating iface mapping. this
867 // isn't perfect, since the kernel may already be counting traffic from
868 // the updated network.
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700869
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700870 // poll, but only persist network stats to keep codepath fast. UID stats
871 // will be persisted during next alarm poll event.
872 performPollLocked(FLAG_PERSIST_NETWORK);
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700873
874 final NetworkState[] states;
Jeff Sharkey63abc372012-01-11 18:38:16 -0800875 final LinkProperties activeLink;
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700876 try {
877 states = mConnManager.getAllNetworkState();
Jeff Sharkey63abc372012-01-11 18:38:16 -0800878 activeLink = mConnManager.getActiveLinkProperties();
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700879 } catch (RemoteException e) {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700880 // ignored; service lives in system_server
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700881 return;
882 }
883
Jeff Sharkey63abc372012-01-11 18:38:16 -0800884 mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null;
885
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700886 // rebuild active interfaces based on connected networks
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700887 mActiveIfaces.clear();
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700888
889 for (NetworkState state : states) {
890 if (state.networkInfo.isConnected()) {
891 // collect networks under their parent interfaces
892 final String iface = state.linkProperties.getInterfaceName();
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -0700893
894 NetworkIdentitySet ident = mActiveIfaces.get(iface);
895 if (ident == null) {
896 ident = new NetworkIdentitySet();
897 mActiveIfaces.put(iface, ident);
898 }
899
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700900 ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
Jeff Sharkey234766a2012-04-10 19:48:07 -0700901
902 // remember any ifaces associated with mobile networks
Jeff Sharkey6a328af2012-11-30 17:49:39 -0800903 if (isNetworkTypeMobile(state.networkInfo.getType()) && iface != null) {
Jeff Sharkey234766a2012-04-10 19:48:07 -0700904 if (!contains(mMobileIfaces, iface)) {
905 mMobileIfaces = appendElement(String.class, mMobileIfaces, iface);
906 }
907 }
Jeff Sharkeyd2a45872011-05-28 20:56:34 -0700908 }
909 }
910 }
911
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700912 /**
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700913 * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
914 * so we have baseline values without double-counting.
915 */
Jeff Sharkey63abc372012-01-11 18:38:16 -0800916 private void bootstrapStatsLocked() {
917 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
918 : System.currentTimeMillis();
919
Jeff Sharkey8e9992a2011-08-23 18:37:23 -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 Sharkey63abc372012-01-11 18:38:16 -0800926
927 mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700928 mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800929 mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime);
930 mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime);
931
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700932 } catch (IllegalStateException e) {
933 Slog.w(TAG, "problem reading network stats: " + e);
934 } catch (RemoteException e) {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700935 // ignored; service lives in system_server
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700936 }
937 }
938
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700939 private void performPoll(int flags) {
Anders 3 Fridlund36bc5b62012-06-07 11:24:10 +0200940 // try refreshing time source when stale
941 if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
942 mTime.forceRefresh();
943 }
944
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700945 synchronized (mStatsLock) {
946 mWakeLock.acquire();
Jeff Sharkey684c54a2011-11-16 17:46:30 -0800947
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700948 try {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700949 performPollLocked(flags);
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700950 } finally {
951 mWakeLock.release();
952 }
953 }
954 }
955
956 /**
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700957 * Periodic poll operation, reading current statistics and recording into
958 * {@link NetworkStatsHistory}.
Jeff Sharkey39ebc212011-06-11 17:25:42 -0700959 */
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700960 private void performPollLocked(int flags) {
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800961 if (!mSystemReady) return;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700962 if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
Jeff Sharkey6341fce2012-03-06 19:59:57 -0800963
Jeff Sharkey8e9992a2011-08-23 18:37:23 -0700964 final long startRealtime = SystemClock.elapsedRealtime();
Jeff Sharkey75279902011-05-24 18:39:45 -0700965
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700966 final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
967 final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -0700968 final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700969
Jeff Sharkey75279902011-05-24 18:39:45 -0700970 // TODO: consider marking "untrusted" times in historical stats
971 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
972 : System.currentTimeMillis();
973
Jeff Sharkey75279902011-05-24 18:39:45 -0700974 try {
Jeff Sharkey63abc372012-01-11 18:38:16 -0800975 // snapshot and record current counters; read UID stats first to
976 // avoid overcounting dev stats.
977 final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700978 final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
979 final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
Jeff Sharkeycdd02c5d2011-09-16 01:52:49 -0700980
Jeff Sharkey63abc372012-01-11 18:38:16 -0800981 mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700982 mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800983 mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime);
984 mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime);
Jeff Sharkey367d15a2011-09-22 14:59:51 -0700985
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700986 } catch (IllegalStateException e) {
987 Log.wtf(TAG, "problem reading network stats", e);
Jeff Sharkey905b5892011-09-30 15:19:49 -0700988 return;
Jeff Sharkeyb3d59572011-09-07 17:20:27 -0700989 } catch (RemoteException e) {
990 // ignored; service lives in system_server
Jeff Sharkey905b5892011-09-30 15:19:49 -0700991 return;
992 }
993
Jeff Sharkey63abc372012-01-11 18:38:16 -0800994 // persist any pending data depending on requested flags
995 if (persistForce) {
996 mDevRecorder.forcePersistLocked(currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -0700997 mXtRecorder.forcePersistLocked(currentTime);
Jeff Sharkey63abc372012-01-11 18:38:16 -0800998 mUidRecorder.forcePersistLocked(currentTime);
999 mUidTagRecorder.forcePersistLocked(currentTime);
1000 } else {
1001 if (persistNetwork) {
1002 mDevRecorder.maybePersistLocked(currentTime);
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001003 mXtRecorder.maybePersistLocked(currentTime);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001004 }
1005 if (persistUid) {
1006 mUidRecorder.maybePersistLocked(currentTime);
1007 mUidTagRecorder.maybePersistLocked(currentTime);
1008 }
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001009 }
Jeff Sharkey497e4432011-06-14 17:27:29 -07001010
Jeff Sharkey8e9992a2011-08-23 18:37:23 -07001011 if (LOGV) {
1012 final long duration = SystemClock.elapsedRealtime() - startRealtime;
1013 Slog.v(TAG, "performPollLocked() took " + duration + "ms");
1014 }
1015
Jeff Sharkey63abc372012-01-11 18:38:16 -08001016 if (mSettings.getSampleEnabled()) {
Jeff Sharkey905b5892011-09-30 15:19:49 -07001017 // sample stats after each full poll
Jeff Sharkey63abc372012-01-11 18:38:16 -08001018 performSampleLocked();
Jeff Sharkey905b5892011-09-30 15:19:49 -07001019 }
Jeff Sharkey07b0dd92011-09-01 13:06:19 -07001020
Jeff Sharkey497e4432011-06-14 17:27:29 -07001021 // finally, dispatch updated event to any listeners
1022 final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
1023 updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
Dianne Hackborn5ac72a22012-08-29 18:32:08 -07001024 mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
1025 READ_NETWORK_USAGE_HISTORY);
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001026 }
1027
1028 /**
Jeff Sharkey07b0dd92011-09-01 13:06:19 -07001029 * Sample recent statistics summary into {@link EventLog}.
1030 */
Jeff Sharkey63abc372012-01-11 18:38:16 -08001031 private void performSampleLocked() {
1032 // TODO: migrate trustedtime fixes to separate binary log events
Jeff Sharkey905b5892011-09-30 15:19:49 -07001033 final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
1034
Jeff Sharkey63abc372012-01-11 18:38:16 -08001035 NetworkTemplate template;
1036 NetworkStats.Entry devTotal;
1037 NetworkStats.Entry xtTotal;
1038 NetworkStats.Entry uidTotal;
Jeff Sharkey07b0dd92011-09-01 13:06:19 -07001039
1040 // collect mobile sample
Jeff Sharkey234766a2012-04-10 19:48:07 -07001041 template = buildTemplateMobileWildcard();
Jeff Sharkey63abc372012-01-11 18:38:16 -08001042 devTotal = mDevRecorder.getTotalSinceBootLocked(template);
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001043 xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001044 uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
Jeff Sharkey684c54a2011-11-16 17:46:30 -08001045
Jeff Sharkey905b5892011-09-30 15:19:49 -07001046 EventLogTags.writeNetstatsMobileSample(
1047 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1048 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1049 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
Jeff Sharkey63abc372012-01-11 18:38:16 -08001050 trustedTime);
Jeff Sharkey07b0dd92011-09-01 13:06:19 -07001051
1052 // collect wifi sample
Jeff Sharkey8fc27e82012-04-04 20:40:58 -07001053 template = buildTemplateWifiWildcard();
Jeff Sharkey63abc372012-01-11 18:38:16 -08001054 devTotal = mDevRecorder.getTotalSinceBootLocked(template);
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001055 xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001056 uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
1057
Jeff Sharkey905b5892011-09-30 15:19:49 -07001058 EventLogTags.writeNetstatsWifiSample(
1059 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1060 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1061 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
Jeff Sharkey63abc372012-01-11 18:38:16 -08001062 trustedTime);
Jeff Sharkey07b0dd92011-09-01 13:06:19 -07001063 }
1064
1065 /**
Jeff Sharkey63abc372012-01-11 18:38:16 -08001066 * Clean up {@link #mUidRecorder} after UID is removed.
Jeff Sharkeyb09540f2011-06-19 01:08:12 -07001067 */
Jeff Sharkeydaa57e82012-09-19 14:10:39 -07001068 private void removeUidsLocked(int... uids) {
1069 if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
1070
1071 // Perform one last poll before removing
Jeff Sharkey163e6442011-10-31 16:37:52 -07001072 performPollLocked(FLAG_PERSIST_ALL);
1073
Jeff Sharkeydaa57e82012-09-19 14:10:39 -07001074 mUidRecorder.removeUidsLocked(uids);
1075 mUidTagRecorder.removeUidsLocked(uids);
Jeff Sharkey163e6442011-10-31 16:37:52 -07001076
Jeff Sharkeydaa57e82012-09-19 14:10:39 -07001077 // Clear kernel stats associated with UID
1078 for (int uid : uids) {
1079 resetKernelUidStats(uid);
1080 }
1081 }
1082
1083 /**
1084 * Clean up {@link #mUidRecorder} after user is removed.
1085 */
1086 private void removeUserLocked(int userId) {
1087 if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
1088
1089 // Build list of UIDs that we should clean up
1090 int[] uids = new int[0];
1091 final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
1092 PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
1093 for (ApplicationInfo app : apps) {
1094 final int uid = UserHandle.getUid(userId, app.uid);
1095 uids = ArrayUtils.appendInt(uids, uid);
1096 }
1097
1098 removeUidsLocked(uids);
Jeff Sharkey75279902011-05-24 18:39:45 -07001099 }
1100
1101 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001102 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
Jeff Sharkey75279902011-05-24 18:39:45 -07001103 mContext.enforceCallingOrSelfPermission(DUMP, TAG);
1104
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001105 final HashSet<String> argSet = new HashSet<String>();
1106 for (String arg : args) {
1107 argSet.add(arg);
Jeff Sharkey75279902011-05-24 18:39:45 -07001108 }
1109
Jeff Sharkey706498d2012-02-06 17:35:07 -08001110 // usage: dumpsys netstats --full --uid --tag --poll --checkin
Jeff Sharkey63abc372012-01-11 18:38:16 -08001111 final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
Jeff Sharkey706498d2012-02-06 17:35:07 -08001112 final boolean checkin = argSet.contains("--checkin");
Jeff Sharkey63abc372012-01-11 18:38:16 -08001113 final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
1114 final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
1115 final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
1116
1117 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " ");
Jeff Sharkey350083e2011-06-29 10:45:16 -07001118
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001119 synchronized (mStatsLock) {
Jeff Sharkey63abc372012-01-11 18:38:16 -08001120 if (poll) {
Jeff Sharkey1f0b13b2011-09-18 13:30:23 -07001121 performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
Jeff Sharkey3f391352011-06-05 17:42:53 -07001122 pw.println("Forced poll");
1123 return;
1124 }
1125
Jeff Sharkey706498d2012-02-06 17:35:07 -08001126 if (checkin) {
1127 // list current stats files to verify rotation
1128 pw.println("Current files:");
1129 pw.increaseIndent();
1130 for (String file : mBaseDir.list()) {
1131 pw.println(file);
1132 }
1133 pw.decreaseIndent();
1134 return;
1135 }
1136
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001137 pw.println("Active interfaces:");
Jeff Sharkey63abc372012-01-11 18:38:16 -08001138 pw.increaseIndent();
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -07001139 for (String iface : mActiveIfaces.keySet()) {
1140 final NetworkIdentitySet ident = mActiveIfaces.get(iface);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001141 pw.print("iface="); pw.print(iface);
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001142 pw.print(" ident="); pw.println(ident.toString());
1143 }
Jeff Sharkey63abc372012-01-11 18:38:16 -08001144 pw.decreaseIndent();
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001145
Jeff Sharkey63abc372012-01-11 18:38:16 -08001146 pw.println("Dev stats:");
1147 pw.increaseIndent();
1148 mDevRecorder.dumpLocked(pw, fullHistory);
1149 pw.decreaseIndent();
1150
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001151 pw.println("Xt stats:");
1152 pw.increaseIndent();
1153 mXtRecorder.dumpLocked(pw, fullHistory);
1154 pw.decreaseIndent();
1155
Jeff Sharkey63abc372012-01-11 18:38:16 -08001156 if (includeUid) {
1157 pw.println("UID stats:");
1158 pw.increaseIndent();
1159 mUidRecorder.dumpLocked(pw, fullHistory);
1160 pw.decreaseIndent();
Jeff Sharkey905b5892011-09-30 15:19:49 -07001161 }
1162
Jeff Sharkey63abc372012-01-11 18:38:16 -08001163 if (includeTag) {
1164 pw.println("UID tag stats:");
1165 pw.increaseIndent();
1166 mUidTagRecorder.dumpLocked(pw, fullHistory);
1167 pw.decreaseIndent();
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001168 }
1169 }
1170 }
1171
1172 /**
Jeff Sharkey63abc372012-01-11 18:38:16 -08001173 * Return snapshot of current UID statistics, including any
1174 * {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values.
Jeff Sharkey61ee0bb2011-05-29 22:50:42 -07001175 */
Jeff Sharkey63abc372012-01-11 18:38:16 -08001176 private NetworkStats getNetworkStatsUidDetail() throws RemoteException {
1177 final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -07001178
Jeff Sharkey63abc372012-01-11 18:38:16 -08001179 // fold tethering stats and operations into uid snapshot
1180 final NetworkStats tetherSnapshot = getNetworkStatsTethering();
1181 uidSnapshot.combineAllValues(tetherSnapshot);
1182 uidSnapshot.combineAllValues(mUidOperations);
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -07001183
Jeff Sharkey63abc372012-01-11 18:38:16 -08001184 return uidSnapshot;
Jeff Sharkey75279902011-05-24 18:39:45 -07001185 }
1186
Jeff Sharkeyd4ef8c8f2011-11-10 17:54:23 -08001187 /**
1188 * Return snapshot of current tethering statistics. Will return empty
1189 * {@link NetworkStats} if any problems are encountered.
1190 */
1191 private NetworkStats getNetworkStatsTethering() throws RemoteException {
1192 try {
Jeff Sharkeye4984be2013-09-10 21:03:27 -07001193 return mNetworkManager.getNetworkStatsTethering();
Jeff Sharkeyd4ef8c8f2011-11-10 17:54:23 -08001194 } catch (IllegalStateException e) {
1195 Log.wtf(TAG, "problem reading network stats", e);
1196 return new NetworkStats(0L, 10);
1197 }
1198 }
1199
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001200 private Handler.Callback mHandlerCallback = new Handler.Callback() {
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001201 @Override
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001202 public boolean handleMessage(Message msg) {
1203 switch (msg.what) {
Jeff Sharkey8e9992a2011-08-23 18:37:23 -07001204 case MSG_PERFORM_POLL: {
Jeff Sharkeyb3d59572011-09-07 17:20:27 -07001205 final int flags = msg.arg1;
1206 performPoll(flags);
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001207 return true;
1208 }
Jeff Sharkey367d15a2011-09-22 14:59:51 -07001209 case MSG_UPDATE_IFACES: {
1210 updateIfaces();
1211 return true;
1212 }
Jeff Sharkey25ce9ed2012-02-02 13:07:47 -08001213 case MSG_REGISTER_GLOBAL_ALERT: {
1214 registerGlobalAlert();
1215 return true;
1216 }
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001217 default: {
1218 return false;
1219 }
1220 }
1221 }
1222 };
1223
Jeff Sharkey4190a042012-04-21 15:36:48 -07001224 private void assertBandwidthControlEnabled() {
1225 if (!isBandwidthControlEnabled()) {
1226 throw new IllegalStateException("Bandwidth module disabled");
1227 }
1228 }
1229
Jeff Sharkey418d12d2011-12-13 15:38:03 -08001230 private boolean isBandwidthControlEnabled() {
Jeff Sharkey49c1d172012-04-23 14:39:19 -07001231 final long token = Binder.clearCallingIdentity();
Jeff Sharkey418d12d2011-12-13 15:38:03 -08001232 try {
1233 return mNetworkManager.isBandwidthControlEnabled();
1234 } catch (RemoteException e) {
1235 // ignored; service lives in system_server
1236 return false;
Jeff Sharkey49c1d172012-04-23 14:39:19 -07001237 } finally {
1238 Binder.restoreCallingIdentity(token);
Jeff Sharkey418d12d2011-12-13 15:38:03 -08001239 }
1240 }
1241
Jeff Sharkey63abc372012-01-11 18:38:16 -08001242 private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001243 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001244 public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
1245 int rightIndex, String cookie) {
1246 Log.w(TAG, "found non-monotonic values; saving to dropbox");
1247
1248 // record error for debugging
1249 final StringBuilder builder = new StringBuilder();
1250 builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
1251 + "] - right[" + rightIndex + "]\n");
1252 builder.append("left=").append(left).append('\n');
1253 builder.append("right=").append(right).append('\n');
1254
1255 final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
1256 Context.DROPBOX_SERVICE);
1257 dropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
Jeff Sharkeyb5d55e32011-08-10 17:53:27 -07001258 }
1259 }
1260
Jeff Sharkey1b5a2a92011-06-18 18:34:16 -07001261 /**
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001262 * Default external settings that read from
Jeff Sharkey625239a2012-09-26 22:03:49 -07001263 * {@link android.provider.Settings.Global}.
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001264 */
1265 private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
1266 private final ContentResolver mResolver;
1267
1268 public DefaultNetworkStatsSettings(Context context) {
1269 mResolver = checkNotNull(context.getContentResolver());
1270 // TODO: adjust these timings for production builds
1271 }
1272
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001273 private long getGlobalLong(String name, long def) {
1274 return Settings.Global.getLong(mResolver, name, def);
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001275 }
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001276 private boolean getGlobalBoolean(String name, boolean def) {
Jeff Sharkey991d1b12011-09-14 19:31:04 -07001277 final int defInt = def ? 1 : 0;
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001278 return Settings.Global.getInt(mResolver, name, defInt) != 0;
Jeff Sharkey991d1b12011-09-14 19:31:04 -07001279 }
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001280
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001281 @Override
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001282 public long getPollInterval() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001283 return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001284 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001285 @Override
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001286 public long getTimeCacheMaxAge() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001287 return getGlobalLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001288 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001289 @Override
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -07001290 public long getGlobalAlertBytes(long def) {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001291 return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001292 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001293 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001294 public boolean getSampleEnabled() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001295 return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
Jeff Sharkey63abc372012-01-11 18:38:16 -08001296 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001297 @Override
Jeff Sharkey70c70532012-05-16 14:51:19 -07001298 public boolean getReportXtOverDev() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001299 return getGlobalBoolean(NETSTATS_REPORT_XT_OVER_DEV, true);
Jeff Sharkey70c70532012-05-16 14:51:19 -07001300 }
1301 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001302 public Config getDevConfig() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001303 return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
1304 getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
1305 getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
Jeff Sharkey63abc372012-01-11 18:38:16 -08001306 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001307 @Override
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001308 public Config getXtConfig() {
1309 return getDevConfig();
1310 }
Jeff Sharkeye8914c32012-05-01 16:26:09 -07001311 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001312 public Config getUidConfig() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001313 return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
1314 getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
1315 getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
Jeff Sharkey63abc372012-01-11 18:38:16 -08001316 }
Jeff Sharkeybfdd6802012-04-09 10:49:19 -07001317 @Override
Jeff Sharkey63abc372012-01-11 18:38:16 -08001318 public Config getUidTagConfig() {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001319 return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
1320 getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
1321 getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -07001322 }
1323 @Override
1324 public long getDevPersistBytes(long def) {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001325 return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -07001326 }
1327 @Override
1328 public long getXtPersistBytes(long def) {
1329 return getDevPersistBytes(def);
1330 }
1331 @Override
1332 public long getUidPersistBytes(long def) {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001333 return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
Jeff Sharkeyac3fcb12012-05-02 18:11:52 -07001334 }
1335 @Override
1336 public long getUidTagPersistBytes(long def) {
Jeff Sharkeye6e61972012-09-14 13:47:51 -07001337 return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
Jeff Sharkey39ebc212011-06-11 17:25:42 -07001338 }
1339 }
Jeff Sharkey75279902011-05-24 18:39:45 -07001340}