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