[go: nahoru, domu]

1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
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
19import static android.Manifest.permission.ACCESS_NETWORK_STATE;
20import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
21import static android.Manifest.permission.DUMP;
22import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING;
23import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
24import static android.content.Intent.ACTION_SHUTDOWN;
25import static android.content.Intent.ACTION_UID_REMOVED;
26import static android.content.Intent.ACTION_USER_REMOVED;
27import static android.content.Intent.EXTRA_UID;
28import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
29import static android.net.ConnectivityManager.isNetworkTypeMobile;
30import static android.net.NetworkStats.IFACE_ALL;
31import static android.net.NetworkStats.SET_ALL;
32import static android.net.NetworkStats.SET_DEFAULT;
33import static android.net.NetworkStats.SET_FOREGROUND;
34import static android.net.NetworkStats.TAG_NONE;
35import static android.net.NetworkStats.UID_ALL;
36import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
37import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
38import static android.net.TrafficStats.KB_IN_BYTES;
39import static android.net.TrafficStats.MB_IN_BYTES;
40import 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;
46import 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;
56import 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;
59import static android.text.format.DateUtils.SECOND_IN_MILLIS;
60import static com.android.internal.util.Preconditions.checkArgument;
61import static com.android.internal.util.Preconditions.checkNotNull;
62import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
63import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
64import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
65
66import android.app.AlarmManager;
67import android.app.IAlarmManager;
68import android.app.PendingIntent;
69import android.content.BroadcastReceiver;
70import android.content.ContentResolver;
71import android.content.Context;
72import android.content.Intent;
73import android.content.IntentFilter;
74import android.content.pm.ApplicationInfo;
75import android.content.pm.PackageManager;
76import android.net.DataUsageRequest;
77import android.net.IConnectivityManager;
78import android.net.INetworkManagementEventObserver;
79import android.net.INetworkStatsService;
80import android.net.INetworkStatsSession;
81import android.net.LinkProperties;
82import android.net.NetworkIdentity;
83import android.net.NetworkInfo;
84import android.net.NetworkState;
85import android.net.NetworkStats;
86import android.net.NetworkStats.NonMonotonicObserver;
87import android.net.NetworkStatsHistory;
88import android.net.NetworkTemplate;
89import android.net.TrafficStats;
90import android.os.Binder;
91import android.os.DropBoxManager;
92import android.os.Environment;
93import android.os.Handler;
94import android.os.HandlerThread;
95import android.os.IBinder;
96import android.os.INetworkManagementService;
97import android.os.Message;
98import android.os.Messenger;
99import android.os.PowerManager;
100import android.os.RemoteException;
101import android.os.SystemClock;
102import android.os.UserHandle;
103import android.provider.Settings;
104import android.provider.Settings.Global;
105import android.telephony.TelephonyManager;
106import android.text.format.DateUtils;
107import android.util.ArrayMap;
108import android.util.ArraySet;
109import android.util.EventLog;
110import android.util.Log;
111import android.util.MathUtils;
112import android.util.NtpTrustedTime;
113import android.util.Slog;
114import android.util.SparseIntArray;
115import android.util.TrustedTime;
116
117import com.android.internal.annotations.VisibleForTesting;
118import com.android.internal.net.VpnInfo;
119import com.android.internal.util.ArrayUtils;
120import com.android.internal.util.FileRotator;
121import com.android.internal.util.IndentingPrintWriter;
122import com.android.server.EventLogTags;
123import com.android.server.connectivity.Tethering;
124
125import java.io.File;
126import java.io.FileDescriptor;
127import java.io.IOException;
128import java.io.PrintWriter;
129import java.util.Arrays;
130import java.util.HashSet;
131import java.util.List;
132
133/**
134 * Collect and persist detailed network statistics, and provide this data to
135 * other system services.
136 */
137public class NetworkStatsService extends INetworkStatsService.Stub {
138    private static final String TAG = "NetworkStats";
139    private static final boolean LOGV = false;
140
141    private static final int MSG_PERFORM_POLL = 1;
142    private static final int MSG_UPDATE_IFACES = 2;
143    private static final int MSG_REGISTER_GLOBAL_ALERT = 3;
144
145    /** Flags to control detail level of poll event. */
146    private static final int FLAG_PERSIST_NETWORK = 0x1;
147    private static final int FLAG_PERSIST_UID = 0x2;
148    private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
149    private static final int FLAG_PERSIST_FORCE = 0x100;
150
151    private static final String TAG_NETSTATS_ERROR = "netstats_error";
152
153    private final Context mContext;
154    private final INetworkManagementService mNetworkManager;
155    private final AlarmManager mAlarmManager;
156    private final TrustedTime mTime;
157    private final TelephonyManager mTeleManager;
158    private final NetworkStatsSettings mSettings;
159    private final NetworkStatsObservers mStatsObservers;
160
161    private final File mSystemDir;
162    private final File mBaseDir;
163
164    private final PowerManager.WakeLock mWakeLock;
165
166    private IConnectivityManager mConnManager;
167
168    @VisibleForTesting
169    public static final String ACTION_NETWORK_STATS_POLL =
170            "com.android.server.action.NETWORK_STATS_POLL";
171    public static final String ACTION_NETWORK_STATS_UPDATED =
172            "com.android.server.action.NETWORK_STATS_UPDATED";
173
174    private PendingIntent mPollIntent;
175
176    private static final String PREFIX_DEV = "dev";
177    private static final String PREFIX_XT = "xt";
178    private static final String PREFIX_UID = "uid";
179    private static final String PREFIX_UID_TAG = "uid_tag";
180
181    /**
182     * Settings that can be changed externally.
183     */
184    public interface NetworkStatsSettings {
185        public long getPollInterval();
186        public long getTimeCacheMaxAge();
187        public boolean getSampleEnabled();
188
189        public static class Config {
190            public final long bucketDuration;
191            public final long rotateAgeMillis;
192            public final long deleteAgeMillis;
193
194            public Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis) {
195                this.bucketDuration = bucketDuration;
196                this.rotateAgeMillis = rotateAgeMillis;
197                this.deleteAgeMillis = deleteAgeMillis;
198            }
199        }
200
201        public Config getDevConfig();
202        public Config getXtConfig();
203        public Config getUidConfig();
204        public Config getUidTagConfig();
205
206        public long getGlobalAlertBytes(long def);
207        public long getDevPersistBytes(long def);
208        public long getXtPersistBytes(long def);
209        public long getUidPersistBytes(long def);
210        public long getUidTagPersistBytes(long def);
211    }
212
213    private final Object mStatsLock = new Object();
214
215    /** Set of currently active ifaces. */
216    private final ArrayMap<String, NetworkIdentitySet> mActiveIfaces = new ArrayMap<>();
217    /** Set of currently active ifaces for UID stats. */
218    private final ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces = new ArrayMap<>();
219    /** Current default active iface. */
220    private String mActiveIface;
221    /** Set of any ifaces associated with mobile networks since boot. */
222    private String[] mMobileIfaces = new String[0];
223
224    private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
225            new DropBoxNonMonotonicObserver();
226
227    private NetworkStatsRecorder mDevRecorder;
228    private NetworkStatsRecorder mXtRecorder;
229    private NetworkStatsRecorder mUidRecorder;
230    private NetworkStatsRecorder mUidTagRecorder;
231
232    /** Cached {@link #mXtRecorder} stats. */
233    private NetworkStatsCollection mXtStatsCached;
234
235    /** Current counter sets for each UID. */
236    private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
237
238    /** Data layer operation counters for splicing into other structures. */
239    private NetworkStats mUidOperations = new NetworkStats(0L, 10);
240
241    /** Must be set in factory by calling #setHandler. */
242    private Handler mHandler;
243    private Handler.Callback mHandlerCallback;
244
245    private boolean mSystemReady;
246    private long mPersistThreshold = 2 * MB_IN_BYTES;
247    private long mGlobalAlertBytes;
248
249    private static File getDefaultSystemDir() {
250        return new File(Environment.getDataDirectory(), "system");
251    }
252
253    private static File getDefaultBaseDir() {
254        File baseDir = new File(getDefaultSystemDir(), "netstats");
255        baseDir.mkdirs();
256        return baseDir;
257    }
258
259    public static NetworkStatsService create(Context context,
260                INetworkManagementService networkManager) {
261        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
262        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
263        PowerManager.WakeLock wakeLock =
264                powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
265
266        NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager,
267                wakeLock, NtpTrustedTime.getInstance(context), TelephonyManager.getDefault(),
268                new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(),
269                getDefaultSystemDir(), getDefaultBaseDir());
270
271        HandlerThread handlerThread = new HandlerThread(TAG);
272        Handler.Callback callback = new HandlerCallback(service);
273        handlerThread.start();
274        Handler handler = new Handler(handlerThread.getLooper(), callback);
275        service.setHandler(handler, callback);
276        return service;
277    }
278
279    @VisibleForTesting
280    NetworkStatsService(Context context, INetworkManagementService networkManager,
281            AlarmManager alarmManager, PowerManager.WakeLock wakeLock, TrustedTime time,
282            TelephonyManager teleManager, NetworkStatsSettings settings,
283            NetworkStatsObservers statsObservers, File systemDir, File baseDir) {
284        mContext = checkNotNull(context, "missing Context");
285        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
286        mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager");
287        mTime = checkNotNull(time, "missing TrustedTime");
288        mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
289        mTeleManager = checkNotNull(teleManager, "missing TelephonyManager");
290        mWakeLock = checkNotNull(wakeLock, "missing WakeLock");
291        mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers");
292        mSystemDir = checkNotNull(systemDir, "missing systemDir");
293        mBaseDir = checkNotNull(baseDir, "missing baseDir");
294    }
295
296    @VisibleForTesting
297    void setHandler(Handler handler, Handler.Callback callback) {
298        mHandler = handler;
299        mHandlerCallback = callback;
300    }
301
302    public void bindConnectivityManager(IConnectivityManager connManager) {
303        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
304    }
305
306    public void systemReady() {
307        mSystemReady = true;
308
309        if (!isBandwidthControlEnabled()) {
310            Slog.w(TAG, "bandwidth controls disabled, unable to track stats");
311            return;
312        }
313
314        // create data recorders along with historical rotators
315        mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
316        mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
317        mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
318        mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
319
320        updatePersistThresholds();
321
322        synchronized (mStatsLock) {
323            // upgrade any legacy stats, migrating them to rotated files
324            maybeUpgradeLegacyStatsLocked();
325
326            // read historical network stats from disk, since policy service
327            // might need them right away.
328            mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked();
329
330            // bootstrap initial stats to prevent double-counting later
331            bootstrapStatsLocked();
332        }
333
334        // watch for tethering changes
335        final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
336        mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler);
337
338        // listen for periodic polling events
339        final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
340        mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
341
342        // listen for uid removal to clean stats
343        final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
344        mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
345
346        // listen for user changes to clean stats
347        final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
348        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
349
350        // persist stats during clean shutdown
351        final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
352        mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
353
354        try {
355            mNetworkManager.registerObserver(mAlertObserver);
356        } catch (RemoteException e) {
357            // ignored; service lives in system_server
358        }
359
360        registerPollAlarmLocked();
361        registerGlobalAlert();
362    }
363
364    private NetworkStatsRecorder buildRecorder(
365            String prefix, NetworkStatsSettings.Config config, boolean includeTags) {
366        final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
367                Context.DROPBOX_SERVICE);
368        return new NetworkStatsRecorder(new FileRotator(
369                mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
370                mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
371    }
372
373    private void shutdownLocked() {
374        mContext.unregisterReceiver(mTetherReceiver);
375        mContext.unregisterReceiver(mPollReceiver);
376        mContext.unregisterReceiver(mRemovedReceiver);
377        mContext.unregisterReceiver(mShutdownReceiver);
378
379        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
380                : System.currentTimeMillis();
381
382        // persist any pending stats
383        mDevRecorder.forcePersistLocked(currentTime);
384        mXtRecorder.forcePersistLocked(currentTime);
385        mUidRecorder.forcePersistLocked(currentTime);
386        mUidTagRecorder.forcePersistLocked(currentTime);
387
388        mDevRecorder = null;
389        mXtRecorder = null;
390        mUidRecorder = null;
391        mUidTagRecorder = null;
392
393        mXtStatsCached = null;
394
395        mSystemReady = false;
396    }
397
398    private void maybeUpgradeLegacyStatsLocked() {
399        File file;
400        try {
401            file = new File(mSystemDir, "netstats.bin");
402            if (file.exists()) {
403                mDevRecorder.importLegacyNetworkLocked(file);
404                file.delete();
405            }
406
407            file = new File(mSystemDir, "netstats_xt.bin");
408            if (file.exists()) {
409                file.delete();
410            }
411
412            file = new File(mSystemDir, "netstats_uid.bin");
413            if (file.exists()) {
414                mUidRecorder.importLegacyUidLocked(file);
415                mUidTagRecorder.importLegacyUidLocked(file);
416                file.delete();
417            }
418        } catch (IOException e) {
419            Log.wtf(TAG, "problem during legacy upgrade", e);
420        } catch (OutOfMemoryError e) {
421            Log.wtf(TAG, "problem during legacy upgrade", e);
422        }
423    }
424
425    /**
426     * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
427     * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
428     */
429    private void registerPollAlarmLocked() {
430        if (mPollIntent != null) {
431            mAlarmManager.cancel(mPollIntent);
432        }
433
434        mPollIntent = PendingIntent.getBroadcast(
435                mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
436
437        final long currentRealtime = SystemClock.elapsedRealtime();
438        mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
439                mSettings.getPollInterval(), mPollIntent);
440    }
441
442    /**
443     * Register for a global alert that is delivered through
444     * {@link INetworkManagementEventObserver} once a threshold amount of data
445     * has been transferred.
446     */
447    private void registerGlobalAlert() {
448        try {
449            mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
450        } catch (IllegalStateException e) {
451            Slog.w(TAG, "problem registering for global alert: " + e);
452        } catch (RemoteException e) {
453            // ignored; service lives in system_server
454        }
455    }
456
457    @Override
458    public INetworkStatsSession openSession() {
459        return createSession(null, /* poll on create */ false);
460    }
461
462    @Override
463    public INetworkStatsSession openSessionForUsageStats(final String callingPackage) {
464        return createSession(callingPackage, /* poll on create */ true);
465    }
466
467    private INetworkStatsSession createSession(final String callingPackage, boolean pollOnCreate) {
468        assertBandwidthControlEnabled();
469
470        if (pollOnCreate) {
471            final long ident = Binder.clearCallingIdentity();
472            try {
473                performPoll(FLAG_PERSIST_ALL);
474            } finally {
475                Binder.restoreCallingIdentity(ident);
476            }
477        }
478
479        // return an IBinder which holds strong references to any loaded stats
480        // for its lifetime; when caller closes only weak references remain.
481
482        return new INetworkStatsSession.Stub() {
483            private NetworkStatsCollection mUidComplete;
484            private NetworkStatsCollection mUidTagComplete;
485            private String mCallingPackage = callingPackage;
486
487            private NetworkStatsCollection getUidComplete() {
488                synchronized (mStatsLock) {
489                    if (mUidComplete == null) {
490                        mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
491                    }
492                    return mUidComplete;
493                }
494            }
495
496            private NetworkStatsCollection getUidTagComplete() {
497                synchronized (mStatsLock) {
498                    if (mUidTagComplete == null) {
499                        mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
500                    }
501                    return mUidTagComplete;
502                }
503            }
504
505            @Override
506            public int[] getRelevantUids() {
507                return getUidComplete().getRelevantUids(checkAccessLevel(mCallingPackage));
508            }
509
510            @Override
511            public NetworkStats getDeviceSummaryForNetwork(NetworkTemplate template, long start,
512                    long end) {
513                @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
514                if (accessLevel < NetworkStatsAccess.Level.DEVICESUMMARY) {
515                    throw new SecurityException("Calling package " + mCallingPackage
516                            + " cannot access device summary network stats");
517                }
518                NetworkStats result = new NetworkStats(end - start, 1);
519                final long ident = Binder.clearCallingIdentity();
520                try {
521                    // Using access level higher than the one we checked for above.
522                    // Reason is that we are combining usage data in a way that is not PII
523                    // anymore.
524                    result.combineAllValues(
525                            internalGetSummaryForNetwork(template, start, end,
526                                    NetworkStatsAccess.Level.DEVICE));
527                } finally {
528                    Binder.restoreCallingIdentity(ident);
529                }
530                return result;
531            }
532
533            @Override
534            public NetworkStats getSummaryForNetwork(
535                    NetworkTemplate template, long start, long end) {
536                @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
537                return internalGetSummaryForNetwork(template, start, end, accessLevel);
538            }
539
540            @Override
541            public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
542                @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
543                return internalGetHistoryForNetwork(template, fields, accessLevel);
544            }
545
546            @Override
547            public NetworkStats getSummaryForAllUid(
548                    NetworkTemplate template, long start, long end, boolean includeTags) {
549                @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
550                final NetworkStats stats =
551                        getUidComplete().getSummary(template, start, end, accessLevel);
552                if (includeTags) {
553                    final NetworkStats tagStats = getUidTagComplete()
554                            .getSummary(template, start, end, accessLevel);
555                    stats.combineAllValues(tagStats);
556                }
557                return stats;
558            }
559
560            @Override
561            public NetworkStatsHistory getHistoryForUid(
562                    NetworkTemplate template, int uid, int set, int tag, int fields) {
563                @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
564                if (tag == TAG_NONE) {
565                    return getUidComplete().getHistory(template, uid, set, tag, fields,
566                            accessLevel);
567                } else {
568                    return getUidTagComplete().getHistory(template, uid, set, tag, fields,
569                            accessLevel);
570                }
571            }
572
573            @Override
574            public NetworkStatsHistory getHistoryIntervalForUid(
575                    NetworkTemplate template, int uid, int set, int tag, int fields,
576                    long start, long end) {
577                @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(mCallingPackage);
578                if (tag == TAG_NONE) {
579                    return getUidComplete().getHistory(template, uid, set, tag, fields, start, end,
580                            accessLevel);
581                } else if (uid == Binder.getCallingUid()) {
582                    return getUidTagComplete().getHistory(template, uid, set, tag, fields,
583                            start, end, accessLevel);
584                } else {
585                    throw new SecurityException("Calling package " + mCallingPackage
586                            + " cannot access tag information from a different uid");
587                }
588            }
589
590            @Override
591            public void close() {
592                mUidComplete = null;
593                mUidTagComplete = null;
594            }
595        };
596    }
597
598    private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
599        return NetworkStatsAccess.checkAccessLevel(
600                mContext, Binder.getCallingUid(), callingPackage);
601    }
602
603    /**
604     * Return network summary, splicing between DEV and XT stats when
605     * appropriate.
606     */
607    private NetworkStats internalGetSummaryForNetwork(
608            NetworkTemplate template, long start, long end,
609            @NetworkStatsAccess.Level int accessLevel) {
610        // We've been using pure XT stats long enough that we no longer need to
611        // splice DEV and XT together.
612        return mXtStatsCached.getSummary(template, start, end, accessLevel);
613    }
614
615    /**
616     * Return network history, splicing between DEV and XT stats when
617     * appropriate.
618     */
619    private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, int fields,
620            @NetworkStatsAccess.Level int accessLevel) {
621        // We've been using pure XT stats long enough that we no longer need to
622        // splice DEV and XT together.
623        return mXtStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields, accessLevel);
624    }
625
626    @Override
627    public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
628        // Special case - since this is for internal use only, don't worry about a full access level
629        // check and just require the signature/privileged permission.
630        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
631        assertBandwidthControlEnabled();
632        return internalGetSummaryForNetwork(template, start, end, NetworkStatsAccess.Level.DEVICE)
633                .getTotalBytes();
634    }
635
636    @Override
637    public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
638        if (Binder.getCallingUid() != uid) {
639            mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
640        }
641        assertBandwidthControlEnabled();
642
643        // TODO: switch to data layer stats once kernel exports
644        // for now, read network layer stats and flatten across all ifaces
645        final long token = Binder.clearCallingIdentity();
646        final NetworkStats networkLayer;
647        try {
648            networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid);
649        } finally {
650            Binder.restoreCallingIdentity(token);
651        }
652
653        // splice in operation counts
654        networkLayer.spliceOperationsFrom(mUidOperations);
655
656        final NetworkStats dataLayer = new NetworkStats(
657                networkLayer.getElapsedRealtime(), networkLayer.size());
658
659        NetworkStats.Entry entry = null;
660        for (int i = 0; i < networkLayer.size(); i++) {
661            entry = networkLayer.getValues(i, entry);
662            entry.iface = IFACE_ALL;
663            dataLayer.combineValues(entry);
664        }
665
666        return dataLayer;
667    }
668
669    @Override
670    public String[] getMobileIfaces() {
671        return mMobileIfaces;
672    }
673
674    @Override
675    public void incrementOperationCount(int uid, int tag, int operationCount) {
676        if (Binder.getCallingUid() != uid) {
677            mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
678        }
679
680        if (operationCount < 0) {
681            throw new IllegalArgumentException("operation count can only be incremented");
682        }
683        if (tag == TAG_NONE) {
684            throw new IllegalArgumentException("operation count must have specific tag");
685        }
686
687        synchronized (mStatsLock) {
688            final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
689            mUidOperations.combineValues(
690                    mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
691            mUidOperations.combineValues(
692                    mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
693        }
694    }
695
696    @Override
697    public void setUidForeground(int uid, boolean uidForeground) {
698        mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
699
700        synchronized (mStatsLock) {
701            final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
702            final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
703            if (oldSet != set) {
704                mActiveUidCounterSet.put(uid, set);
705                setKernelCounterSet(uid, set);
706            }
707        }
708    }
709
710    @Override
711    public void forceUpdateIfaces() {
712        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
713        assertBandwidthControlEnabled();
714
715        final long token = Binder.clearCallingIdentity();
716        try {
717            updateIfaces();
718        } finally {
719            Binder.restoreCallingIdentity(token);
720        }
721    }
722
723    @Override
724    public void forceUpdate() {
725        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
726        assertBandwidthControlEnabled();
727
728        final long token = Binder.clearCallingIdentity();
729        try {
730            performPoll(FLAG_PERSIST_ALL);
731        } finally {
732            Binder.restoreCallingIdentity(token);
733        }
734    }
735
736    @Override
737    public void advisePersistThreshold(long thresholdBytes) {
738        mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
739        assertBandwidthControlEnabled();
740
741        // clamp threshold into safe range
742        mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
743        if (LOGV) {
744            Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
745                    + mPersistThreshold);
746        }
747
748        // update and persist if beyond new thresholds
749        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
750                : System.currentTimeMillis();
751        synchronized (mStatsLock) {
752            if (!mSystemReady) return;
753
754            updatePersistThresholds();
755
756            mDevRecorder.maybePersistLocked(currentTime);
757            mXtRecorder.maybePersistLocked(currentTime);
758            mUidRecorder.maybePersistLocked(currentTime);
759            mUidTagRecorder.maybePersistLocked(currentTime);
760        }
761
762        // re-arm global alert
763        registerGlobalAlert();
764    }
765
766    @Override
767    public DataUsageRequest registerUsageCallback(String callingPackage,
768                DataUsageRequest request, Messenger messenger, IBinder binder) {
769        checkNotNull(callingPackage, "calling package is null");
770        checkNotNull(request, "DataUsageRequest is null");
771        checkNotNull(request.template, "NetworkTemplate is null");
772        checkNotNull(messenger, "messenger is null");
773        checkNotNull(binder, "binder is null");
774
775        int callingUid = Binder.getCallingUid();
776        @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
777        DataUsageRequest normalizedRequest;
778        final long token = Binder.clearCallingIdentity();
779        try {
780            normalizedRequest = mStatsObservers.register(request, messenger, binder,
781                    callingUid, accessLevel);
782        } finally {
783            Binder.restoreCallingIdentity(token);
784        }
785
786        // Create baseline stats
787        mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL, FLAG_PERSIST_ALL));
788
789        return normalizedRequest;
790   }
791
792    @Override
793    public void unregisterUsageRequest(DataUsageRequest request) {
794        checkNotNull(request, "DataUsageRequest is null");
795
796        int callingUid = Binder.getCallingUid();
797        final long token = Binder.clearCallingIdentity();
798        try {
799            mStatsObservers.unregister(request, callingUid);
800        } finally {
801            Binder.restoreCallingIdentity(token);
802        }
803    }
804
805    /**
806     * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
807     * reflect current {@link #mPersistThreshold} value. Always defers to
808     * {@link Global} values when defined.
809     */
810    private void updatePersistThresholds() {
811        mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
812        mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
813        mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
814        mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
815        mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold);
816    }
817
818    /**
819     * Receiver that watches for {@link Tethering} to claim interface pairs.
820     */
821    private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
822        @Override
823        public void onReceive(Context context, Intent intent) {
824            // on background handler thread, and verified CONNECTIVITY_INTERNAL
825            // permission above.
826            performPoll(FLAG_PERSIST_NETWORK);
827        }
828    };
829
830    private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
831        @Override
832        public void onReceive(Context context, Intent intent) {
833            // on background handler thread, and verified UPDATE_DEVICE_STATS
834            // permission above.
835            performPoll(FLAG_PERSIST_ALL);
836
837            // verify that we're watching global alert
838            registerGlobalAlert();
839        }
840    };
841
842    private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
843        @Override
844        public void onReceive(Context context, Intent intent) {
845            // on background handler thread, and UID_REMOVED is protected
846            // broadcast.
847
848            final int uid = intent.getIntExtra(EXTRA_UID, -1);
849            if (uid == -1) return;
850
851            synchronized (mStatsLock) {
852                mWakeLock.acquire();
853                try {
854                    removeUidsLocked(uid);
855                } finally {
856                    mWakeLock.release();
857                }
858            }
859        }
860    };
861
862    private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
863        @Override
864        public void onReceive(Context context, Intent intent) {
865            // On background handler thread, and USER_REMOVED is protected
866            // broadcast.
867
868            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
869            if (userId == -1) return;
870
871            synchronized (mStatsLock) {
872                mWakeLock.acquire();
873                try {
874                    removeUserLocked(userId);
875                } finally {
876                    mWakeLock.release();
877                }
878            }
879        }
880    };
881
882    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
883        @Override
884        public void onReceive(Context context, Intent intent) {
885            // SHUTDOWN is protected broadcast.
886            synchronized (mStatsLock) {
887                shutdownLocked();
888            }
889        }
890    };
891
892    /**
893     * Observer that watches for {@link INetworkManagementService} alerts.
894     */
895    private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
896        @Override
897        public void limitReached(String limitName, String iface) {
898            // only someone like NMS should be calling us
899            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
900
901            if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
902                // kick off background poll to collect network stats; UID stats
903                // are handled during normal polling interval.
904                final int flags = FLAG_PERSIST_NETWORK;
905                mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
906
907                // re-arm global alert for next update
908                mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget();
909            }
910        }
911    };
912
913    private void updateIfaces() {
914        synchronized (mStatsLock) {
915            mWakeLock.acquire();
916            try {
917                updateIfacesLocked();
918            } finally {
919                mWakeLock.release();
920            }
921        }
922    }
923
924    /**
925     * Inspect all current {@link NetworkState} to derive mapping from {@code
926     * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
927     * are active on a single {@code iface}, they are combined under a single
928     * {@link NetworkIdentitySet}.
929     */
930    private void updateIfacesLocked() {
931        if (!mSystemReady) return;
932        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
933
934        // take one last stats snapshot before updating iface mapping. this
935        // isn't perfect, since the kernel may already be counting traffic from
936        // the updated network.
937
938        // poll, but only persist network stats to keep codepath fast. UID stats
939        // will be persisted during next alarm poll event.
940        performPollLocked(FLAG_PERSIST_NETWORK);
941
942        final NetworkState[] states;
943        final LinkProperties activeLink;
944        try {
945            states = mConnManager.getAllNetworkState();
946            activeLink = mConnManager.getActiveLinkProperties();
947        } catch (RemoteException e) {
948            // ignored; service lives in system_server
949            return;
950        }
951
952        mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null;
953
954        // Rebuild active interfaces based on connected networks
955        mActiveIfaces.clear();
956        mActiveUidIfaces.clear();
957
958        final ArraySet<String> mobileIfaces = new ArraySet<>();
959        for (NetworkState state : states) {
960            if (state.networkInfo.isConnected()) {
961                final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType());
962                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
963
964                // Traffic occurring on the base interface is always counted for
965                // both total usage and UID details.
966                final String baseIface = state.linkProperties.getInterfaceName();
967                if (baseIface != null) {
968                    findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident);
969                    findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident);
970                    if (isMobile) {
971                        mobileIfaces.add(baseIface);
972                    }
973                }
974
975                // Traffic occurring on stacked interfaces is usually clatd,
976                // which is already accounted against its final egress interface
977                // by the kernel. Thus, we only need to collect stacked
978                // interface stats at the UID level.
979                final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
980                for (LinkProperties stackedLink : stackedLinks) {
981                    final String stackedIface = stackedLink.getInterfaceName();
982                    if (stackedIface != null) {
983                        findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident);
984                        if (isMobile) {
985                            mobileIfaces.add(stackedIface);
986                        }
987                    }
988                }
989            }
990        }
991
992        mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
993    }
994
995    private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
996            ArrayMap<K, NetworkIdentitySet> map, K key) {
997        NetworkIdentitySet ident = map.get(key);
998        if (ident == null) {
999            ident = new NetworkIdentitySet();
1000            map.put(key, ident);
1001        }
1002        return ident;
1003    }
1004
1005    private void recordSnapshotLocked(long currentTime) throws RemoteException {
1006        // snapshot and record current counters; read UID stats first to
1007        // avoid overcounting dev stats.
1008        final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
1009        final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
1010        final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
1011
1012
1013        // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
1014        // can't be reattributed to responsible apps.
1015        mDevRecorder.recordSnapshotLocked(
1016                devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
1017        mXtRecorder.recordSnapshotLocked(
1018                xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
1019
1020        // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
1021        VpnInfo[] vpnArray = mConnManager.getAllVpnInfo();
1022        mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
1023        mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
1024
1025        // We need to make copies of member fields that are sent to the observer to avoid
1026        // a race condition between the service handler thread and the observer's
1027        mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces),
1028                new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime);
1029    }
1030
1031    /**
1032     * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
1033     * so we have baseline values without double-counting.
1034     */
1035    private void bootstrapStatsLocked() {
1036        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
1037                : System.currentTimeMillis();
1038
1039        try {
1040            recordSnapshotLocked(currentTime);
1041        } catch (IllegalStateException e) {
1042            Slog.w(TAG, "problem reading network stats: " + e);
1043        } catch (RemoteException e) {
1044            // ignored; service lives in system_server
1045        }
1046    }
1047
1048    private void performPoll(int flags) {
1049        // try refreshing time source when stale
1050        if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
1051            mTime.forceRefresh();
1052        }
1053
1054        synchronized (mStatsLock) {
1055            mWakeLock.acquire();
1056
1057            try {
1058                performPollLocked(flags);
1059            } finally {
1060                mWakeLock.release();
1061            }
1062        }
1063    }
1064
1065    /**
1066     * Periodic poll operation, reading current statistics and recording into
1067     * {@link NetworkStatsHistory}.
1068     */
1069    private void performPollLocked(int flags) {
1070        if (!mSystemReady) return;
1071        if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
1072
1073        final long startRealtime = SystemClock.elapsedRealtime();
1074
1075        final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
1076        final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
1077        final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
1078
1079        // TODO: consider marking "untrusted" times in historical stats
1080        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
1081                : System.currentTimeMillis();
1082
1083        try {
1084            recordSnapshotLocked(currentTime);
1085        } catch (IllegalStateException e) {
1086            Log.wtf(TAG, "problem reading network stats", e);
1087            return;
1088        } catch (RemoteException e) {
1089            // ignored; service lives in system_server
1090            return;
1091        }
1092
1093        // persist any pending data depending on requested flags
1094        if (persistForce) {
1095            mDevRecorder.forcePersistLocked(currentTime);
1096            mXtRecorder.forcePersistLocked(currentTime);
1097            mUidRecorder.forcePersistLocked(currentTime);
1098            mUidTagRecorder.forcePersistLocked(currentTime);
1099        } else {
1100            if (persistNetwork) {
1101                mDevRecorder.maybePersistLocked(currentTime);
1102                mXtRecorder.maybePersistLocked(currentTime);
1103            }
1104            if (persistUid) {
1105                mUidRecorder.maybePersistLocked(currentTime);
1106                mUidTagRecorder.maybePersistLocked(currentTime);
1107            }
1108        }
1109
1110        if (LOGV) {
1111            final long duration = SystemClock.elapsedRealtime() - startRealtime;
1112            Slog.v(TAG, "performPollLocked() took " + duration + "ms");
1113        }
1114
1115        if (mSettings.getSampleEnabled()) {
1116            // sample stats after each full poll
1117            performSampleLocked();
1118        }
1119
1120        // finally, dispatch updated event to any listeners
1121        final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
1122        updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1123        mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
1124                READ_NETWORK_USAGE_HISTORY);
1125    }
1126
1127    /**
1128     * Sample recent statistics summary into {@link EventLog}.
1129     */
1130    private void performSampleLocked() {
1131        // TODO: migrate trustedtime fixes to separate binary log events
1132        final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
1133
1134        NetworkTemplate template;
1135        NetworkStats.Entry devTotal;
1136        NetworkStats.Entry xtTotal;
1137        NetworkStats.Entry uidTotal;
1138
1139        // collect mobile sample
1140        template = buildTemplateMobileWildcard();
1141        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
1142        xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
1143        uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
1144
1145        EventLogTags.writeNetstatsMobileSample(
1146                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1147                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1148                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
1149                trustedTime);
1150
1151        // collect wifi sample
1152        template = buildTemplateWifiWildcard();
1153        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
1154        xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
1155        uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
1156
1157        EventLogTags.writeNetstatsWifiSample(
1158                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1159                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1160                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
1161                trustedTime);
1162    }
1163
1164    /**
1165     * Clean up {@link #mUidRecorder} after UID is removed.
1166     */
1167    private void removeUidsLocked(int... uids) {
1168        if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
1169
1170        // Perform one last poll before removing
1171        performPollLocked(FLAG_PERSIST_ALL);
1172
1173        mUidRecorder.removeUidsLocked(uids);
1174        mUidTagRecorder.removeUidsLocked(uids);
1175
1176        // Clear kernel stats associated with UID
1177        for (int uid : uids) {
1178            resetKernelUidStats(uid);
1179        }
1180    }
1181
1182    /**
1183     * Clean up {@link #mUidRecorder} after user is removed.
1184     */
1185    private void removeUserLocked(int userId) {
1186        if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
1187
1188        // Build list of UIDs that we should clean up
1189        int[] uids = new int[0];
1190        final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
1191                PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
1192        for (ApplicationInfo app : apps) {
1193            final int uid = UserHandle.getUid(userId, app.uid);
1194            uids = ArrayUtils.appendInt(uids, uid);
1195        }
1196
1197        removeUidsLocked(uids);
1198    }
1199
1200    @Override
1201    protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
1202        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
1203
1204        long duration = DateUtils.DAY_IN_MILLIS;
1205        final HashSet<String> argSet = new HashSet<String>();
1206        for (String arg : args) {
1207            argSet.add(arg);
1208
1209            if (arg.startsWith("--duration=")) {
1210                try {
1211                    duration = Long.parseLong(arg.substring(11));
1212                } catch (NumberFormatException ignored) {
1213                }
1214            }
1215        }
1216
1217        // usage: dumpsys netstats --full --uid --tag --poll --checkin
1218        final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
1219        final boolean checkin = argSet.contains("--checkin");
1220        final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
1221        final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
1222        final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
1223
1224        final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, "  ");
1225
1226        synchronized (mStatsLock) {
1227            if (poll) {
1228                performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
1229                pw.println("Forced poll");
1230                return;
1231            }
1232
1233            if (checkin) {
1234                final long end = System.currentTimeMillis();
1235                final long start = end - duration;
1236
1237                pw.print("v1,");
1238                pw.print(start / SECOND_IN_MILLIS); pw.print(',');
1239                pw.print(end / SECOND_IN_MILLIS); pw.println();
1240
1241                pw.println("xt");
1242                mXtRecorder.dumpCheckin(rawWriter, start, end);
1243
1244                if (includeUid) {
1245                    pw.println("uid");
1246                    mUidRecorder.dumpCheckin(rawWriter, start, end);
1247                }
1248                if (includeTag) {
1249                    pw.println("tag");
1250                    mUidTagRecorder.dumpCheckin(rawWriter, start, end);
1251                }
1252                return;
1253            }
1254
1255            pw.println("Active interfaces:");
1256            pw.increaseIndent();
1257            for (int i = 0; i < mActiveIfaces.size(); i++) {
1258                pw.printPair("iface", mActiveIfaces.keyAt(i));
1259                pw.printPair("ident", mActiveIfaces.valueAt(i));
1260                pw.println();
1261            }
1262            pw.decreaseIndent();
1263
1264            pw.println("Active UID interfaces:");
1265            pw.increaseIndent();
1266            for (int i = 0; i < mActiveUidIfaces.size(); i++) {
1267                pw.printPair("iface", mActiveUidIfaces.keyAt(i));
1268                pw.printPair("ident", mActiveUidIfaces.valueAt(i));
1269                pw.println();
1270            }
1271            pw.decreaseIndent();
1272
1273            pw.println("Dev stats:");
1274            pw.increaseIndent();
1275            mDevRecorder.dumpLocked(pw, fullHistory);
1276            pw.decreaseIndent();
1277
1278            pw.println("Xt stats:");
1279            pw.increaseIndent();
1280            mXtRecorder.dumpLocked(pw, fullHistory);
1281            pw.decreaseIndent();
1282
1283            if (includeUid) {
1284                pw.println("UID stats:");
1285                pw.increaseIndent();
1286                mUidRecorder.dumpLocked(pw, fullHistory);
1287                pw.decreaseIndent();
1288            }
1289
1290            if (includeTag) {
1291                pw.println("UID tag stats:");
1292                pw.increaseIndent();
1293                mUidTagRecorder.dumpLocked(pw, fullHistory);
1294                pw.decreaseIndent();
1295            }
1296        }
1297    }
1298
1299    /**
1300     * Return snapshot of current UID statistics, including any
1301     * {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values.
1302     */
1303    private NetworkStats getNetworkStatsUidDetail() throws RemoteException {
1304        final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
1305
1306        // fold tethering stats and operations into uid snapshot
1307        final NetworkStats tetherSnapshot = getNetworkStatsTethering();
1308        uidSnapshot.combineAllValues(tetherSnapshot);
1309        uidSnapshot.combineAllValues(mUidOperations);
1310
1311        return uidSnapshot;
1312    }
1313
1314    /**
1315     * Return snapshot of current tethering statistics. Will return empty
1316     * {@link NetworkStats} if any problems are encountered.
1317     */
1318    private NetworkStats getNetworkStatsTethering() throws RemoteException {
1319        try {
1320            return mNetworkManager.getNetworkStatsTethering();
1321        } catch (IllegalStateException e) {
1322            Log.wtf(TAG, "problem reading network stats", e);
1323            return new NetworkStats(0L, 10);
1324        }
1325    }
1326
1327    @VisibleForTesting
1328    static class HandlerCallback implements Handler.Callback {
1329        private final NetworkStatsService mService;
1330
1331        HandlerCallback(NetworkStatsService service) {
1332            this.mService = service;
1333        }
1334
1335        @Override
1336        public boolean handleMessage(Message msg) {
1337            switch (msg.what) {
1338                case MSG_PERFORM_POLL: {
1339                    final int flags = msg.arg1;
1340                    mService.performPoll(flags);
1341                    return true;
1342                }
1343                case MSG_UPDATE_IFACES: {
1344                    mService.updateIfaces();
1345                    return true;
1346                }
1347                case MSG_REGISTER_GLOBAL_ALERT: {
1348                    mService.registerGlobalAlert();
1349                    return true;
1350                }
1351                default: {
1352                    return false;
1353                }
1354            }
1355        }
1356    }
1357
1358    private void assertBandwidthControlEnabled() {
1359        if (!isBandwidthControlEnabled()) {
1360            throw new IllegalStateException("Bandwidth module disabled");
1361        }
1362    }
1363
1364    private boolean isBandwidthControlEnabled() {
1365        final long token = Binder.clearCallingIdentity();
1366        try {
1367            return mNetworkManager.isBandwidthControlEnabled();
1368        } catch (RemoteException e) {
1369            // ignored; service lives in system_server
1370            return false;
1371        } finally {
1372            Binder.restoreCallingIdentity(token);
1373        }
1374    }
1375
1376    private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
1377        @Override
1378        public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
1379                int rightIndex, String cookie) {
1380            Log.w(TAG, "found non-monotonic values; saving to dropbox");
1381
1382            // record error for debugging
1383            final StringBuilder builder = new StringBuilder();
1384            builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
1385                    + "] - right[" + rightIndex + "]\n");
1386            builder.append("left=").append(left).append('\n');
1387            builder.append("right=").append(right).append('\n');
1388
1389            final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
1390                    Context.DROPBOX_SERVICE);
1391            dropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
1392        }
1393    }
1394
1395    /**
1396     * Default external settings that read from
1397     * {@link android.provider.Settings.Global}.
1398     */
1399    private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
1400        private final ContentResolver mResolver;
1401
1402        public DefaultNetworkStatsSettings(Context context) {
1403            mResolver = checkNotNull(context.getContentResolver());
1404            // TODO: adjust these timings for production builds
1405        }
1406
1407        private long getGlobalLong(String name, long def) {
1408            return Settings.Global.getLong(mResolver, name, def);
1409        }
1410        private boolean getGlobalBoolean(String name, boolean def) {
1411            final int defInt = def ? 1 : 0;
1412            return Settings.Global.getInt(mResolver, name, defInt) != 0;
1413        }
1414
1415        @Override
1416        public long getPollInterval() {
1417            return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
1418        }
1419        @Override
1420        public long getTimeCacheMaxAge() {
1421            return getGlobalLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
1422        }
1423        @Override
1424        public long getGlobalAlertBytes(long def) {
1425            return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
1426        }
1427        @Override
1428        public boolean getSampleEnabled() {
1429            return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
1430        }
1431        @Override
1432        public Config getDevConfig() {
1433            return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
1434                    getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
1435                    getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
1436        }
1437        @Override
1438        public Config getXtConfig() {
1439            return getDevConfig();
1440        }
1441        @Override
1442        public Config getUidConfig() {
1443            return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
1444                    getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
1445                    getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
1446        }
1447        @Override
1448        public Config getUidTagConfig() {
1449            return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
1450                    getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
1451                    getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
1452        }
1453        @Override
1454        public long getDevPersistBytes(long def) {
1455            return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
1456        }
1457        @Override
1458        public long getXtPersistBytes(long def) {
1459            return getDevPersistBytes(def);
1460        }
1461        @Override
1462        public long getUidPersistBytes(long def) {
1463            return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
1464        }
1465        @Override
1466        public long getUidTagPersistBytes(long def) {
1467            return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
1468        }
1469    }
1470}
1471