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