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.DUMP;
     22 import static android.Manifest.permission.MANAGE_NETWORK_POLICY;
     23 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
     24 import static android.Manifest.permission.READ_PHONE_STATE;
     25 import static android.content.Intent.ACTION_PACKAGE_ADDED;
     26 import static android.content.Intent.ACTION_UID_REMOVED;
     27 import static android.content.Intent.ACTION_USER_ADDED;
     28 import static android.content.Intent.ACTION_USER_REMOVED;
     29 import static android.content.Intent.EXTRA_UID;
     30 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
     31 import static android.net.ConnectivityManager.TYPE_ETHERNET;
     32 import static android.net.ConnectivityManager.TYPE_MOBILE;
     33 import static android.net.ConnectivityManager.TYPE_WIFI;
     34 import static android.net.ConnectivityManager.TYPE_WIMAX;
     35 import static android.net.ConnectivityManager.isNetworkTypeMobile;
     36 import static android.net.NetworkPolicy.CYCLE_NONE;
     37 import static android.net.NetworkPolicy.LIMIT_DISABLED;
     38 import static android.net.NetworkPolicy.SNOOZE_NEVER;
     39 import static android.net.NetworkPolicy.WARNING_DISABLED;
     40 import static android.net.NetworkPolicyManager.EXTRA_NETWORK_TEMPLATE;
     41 import static android.net.NetworkPolicyManager.POLICY_NONE;
     42 import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
     43 import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
     44 import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
     45 import static android.net.NetworkPolicyManager.computeLastCycleBoundary;
     46 import static android.net.NetworkPolicyManager.dumpPolicy;
     47 import static android.net.NetworkPolicyManager.dumpRules;
     48 import static android.net.NetworkTemplate.MATCH_ETHERNET;
     49 import static android.net.NetworkTemplate.MATCH_MOBILE_3G_LOWER;
     50 import static android.net.NetworkTemplate.MATCH_MOBILE_4G;
     51 import static android.net.NetworkTemplate.MATCH_MOBILE_ALL;
     52 import static android.net.NetworkTemplate.MATCH_WIFI;
     53 import static android.net.NetworkTemplate.buildTemplateMobileAll;
     54 import static android.net.TrafficStats.MB_IN_BYTES;
     55 import static android.net.wifi.WifiManager.CHANGE_REASON_ADDED;
     56 import static android.net.wifi.WifiManager.CHANGE_REASON_REMOVED;
     57 import static android.net.wifi.WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION;
     58 import static android.net.wifi.WifiManager.EXTRA_CHANGE_REASON;
     59 import static android.net.wifi.WifiManager.EXTRA_NETWORK_INFO;
     60 import static android.net.wifi.WifiManager.EXTRA_WIFI_CONFIGURATION;
     61 import static android.net.wifi.WifiManager.EXTRA_WIFI_INFO;
     62 import static android.telephony.TelephonyManager.SIM_STATE_READY;
     63 import static android.text.format.DateUtils.DAY_IN_MILLIS;
     64 import static com.android.internal.util.ArrayUtils.appendInt;
     65 import static com.android.internal.util.Preconditions.checkNotNull;
     66 import static com.android.internal.util.XmlUtils.readBooleanAttribute;
     67 import static com.android.internal.util.XmlUtils.readIntAttribute;
     68 import static com.android.internal.util.XmlUtils.readLongAttribute;
     69 import static com.android.internal.util.XmlUtils.writeBooleanAttribute;
     70 import static com.android.internal.util.XmlUtils.writeIntAttribute;
     71 import static com.android.internal.util.XmlUtils.writeLongAttribute;
     72 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
     73 import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
     74 import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
     75 import static org.xmlpull.v1.XmlPullParser.START_TAG;
     76 
     77 import android.app.IActivityManager;
     78 import android.app.INotificationManager;
     79 import android.app.IProcessObserver;
     80 import android.app.Notification;
     81 import android.app.PendingIntent;
     82 import android.content.BroadcastReceiver;
     83 import android.content.ComponentName;
     84 import android.content.Context;
     85 import android.content.Intent;
     86 import android.content.IntentFilter;
     87 import android.content.pm.ApplicationInfo;
     88 import android.content.pm.PackageManager;
     89 import android.content.pm.UserInfo;
     90 import android.content.res.Resources;
     91 import android.net.ConnectivityManager;
     92 import android.net.IConnectivityManager;
     93 import android.net.INetworkManagementEventObserver;
     94 import android.net.INetworkPolicyListener;
     95 import android.net.INetworkPolicyManager;
     96 import android.net.INetworkStatsService;
     97 import android.net.NetworkIdentity;
     98 import android.net.NetworkInfo;
     99 import android.net.NetworkPolicy;
    100 import android.net.NetworkQuotaInfo;
    101 import android.net.NetworkState;
    102 import android.net.NetworkTemplate;
    103 import android.net.wifi.WifiConfiguration;
    104 import android.net.wifi.WifiInfo;
    105 import android.net.wifi.WifiManager;
    106 import android.os.Binder;
    107 import android.os.Environment;
    108 import android.os.Handler;
    109 import android.os.HandlerThread;
    110 import android.os.INetworkManagementService;
    111 import android.os.IPowerManager;
    112 import android.os.Message;
    113 import android.os.MessageQueue.IdleHandler;
    114 import android.os.RemoteCallbackList;
    115 import android.os.RemoteException;
    116 import android.os.UserHandle;
    117 import android.os.UserManager;
    118 import android.provider.Settings;
    119 import android.telephony.TelephonyManager;
    120 import android.text.format.Formatter;
    121 import android.text.format.Time;
    122 import android.util.AtomicFile;
    123 import android.util.Log;
    124 import android.util.NtpTrustedTime;
    125 import android.util.Slog;
    126 import android.util.SparseArray;
    127 import android.util.SparseBooleanArray;
    128 import android.util.SparseIntArray;
    129 import android.util.TrustedTime;
    130 import android.util.Xml;
    131 
    132 import com.android.internal.R;
    133 import com.android.internal.annotations.VisibleForTesting;
    134 import com.android.internal.util.FastXmlSerializer;
    135 import com.android.internal.util.IndentingPrintWriter;
    136 import com.android.internal.util.Objects;
    137 import com.google.android.collect.Lists;
    138 import com.google.android.collect.Maps;
    139 import com.google.android.collect.Sets;
    140 
    141 import org.xmlpull.v1.XmlPullParser;
    142 import org.xmlpull.v1.XmlPullParserException;
    143 import org.xmlpull.v1.XmlSerializer;
    144 
    145 import java.io.File;
    146 import java.io.FileDescriptor;
    147 import java.io.FileInputStream;
    148 import java.io.FileNotFoundException;
    149 import java.io.FileOutputStream;
    150 import java.io.IOException;
    151 import java.io.PrintWriter;
    152 import java.util.ArrayList;
    153 import java.util.Arrays;
    154 import java.util.HashMap;
    155 import java.util.HashSet;
    156 import java.util.List;
    157 import java.util.Map;
    158 
    159 import libcore.io.IoUtils;
    160 
    161 /**
    162  * Service that maintains low-level network policy rules, using
    163  * {@link NetworkStatsService} statistics to drive those rules.
    164  * <p>
    165  * Derives active rules by combining a given policy with other system status,
    166  * and delivers to listeners, such as {@link ConnectivityManager}, for
    167  * enforcement.
    168  */
    169 public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
    170     private static final String TAG = "NetworkPolicy";
    171     private static final boolean LOGD = false;
    172     private static final boolean LOGV = false;
    173 
    174     private static final int VERSION_INIT = 1;
    175     private static final int VERSION_ADDED_SNOOZE = 2;
    176     private static final int VERSION_ADDED_RESTRICT_BACKGROUND = 3;
    177     private static final int VERSION_ADDED_METERED = 4;
    178     private static final int VERSION_SPLIT_SNOOZE = 5;
    179     private static final int VERSION_ADDED_TIMEZONE = 6;
    180     private static final int VERSION_ADDED_INFERRED = 7;
    181     private static final int VERSION_SWITCH_APP_ID = 8;
    182     private static final int VERSION_ADDED_NETWORK_ID = 9;
    183     private static final int VERSION_SWITCH_UID = 10;
    184     private static final int VERSION_LATEST = VERSION_SWITCH_UID;
    185 
    186     @VisibleForTesting
    187     public static final int TYPE_WARNING = 0x1;
    188     @VisibleForTesting
    189     public static final int TYPE_LIMIT = 0x2;
    190     @VisibleForTesting
    191     public static final int TYPE_LIMIT_SNOOZED = 0x3;
    192 
    193     private static final String TAG_POLICY_LIST = "policy-list";
    194     private static final String TAG_NETWORK_POLICY = "network-policy";
    195     private static final String TAG_UID_POLICY = "uid-policy";
    196     private static final String TAG_APP_POLICY = "app-policy";
    197 
    198     private static final String ATTR_VERSION = "version";
    199     private static final String ATTR_RESTRICT_BACKGROUND = "restrictBackground";
    200     private static final String ATTR_NETWORK_TEMPLATE = "networkTemplate";
    201     private static final String ATTR_SUBSCRIBER_ID = "subscriberId";
    202     private static final String ATTR_NETWORK_ID = "networkId";
    203     private static final String ATTR_CYCLE_DAY = "cycleDay";
    204     private static final String ATTR_CYCLE_TIMEZONE = "cycleTimezone";
    205     private static final String ATTR_WARNING_BYTES = "warningBytes";
    206     private static final String ATTR_LIMIT_BYTES = "limitBytes";
    207     private static final String ATTR_LAST_SNOOZE = "lastSnooze";
    208     private static final String ATTR_LAST_WARNING_SNOOZE = "lastWarningSnooze";
    209     private static final String ATTR_LAST_LIMIT_SNOOZE = "lastLimitSnooze";
    210     private static final String ATTR_METERED = "metered";
    211     private static final String ATTR_INFERRED = "inferred";
    212     private static final String ATTR_UID = "uid";
    213     private static final String ATTR_APP_ID = "appId";
    214     private static final String ATTR_POLICY = "policy";
    215 
    216     private static final String TAG_ALLOW_BACKGROUND = TAG + ":allowBackground";
    217 
    218     private static final String ACTION_ALLOW_BACKGROUND =
    219             "com.android.server.net.action.ALLOW_BACKGROUND";
    220     private static final String ACTION_SNOOZE_WARNING =
    221             "com.android.server.net.action.SNOOZE_WARNING";
    222 
    223     private static final long TIME_CACHE_MAX_AGE = DAY_IN_MILLIS;
    224 
    225     private static final int MSG_RULES_CHANGED = 1;
    226     private static final int MSG_METERED_IFACES_CHANGED = 2;
    227     private static final int MSG_FOREGROUND_ACTIVITIES_CHANGED = 3;
    228     private static final int MSG_PROCESS_DIED = 4;
    229     private static final int MSG_LIMIT_REACHED = 5;
    230     private static final int MSG_RESTRICT_BACKGROUND_CHANGED = 6;
    231     private static final int MSG_ADVISE_PERSIST_THRESHOLD = 7;
    232     private static final int MSG_SCREEN_ON_CHANGED = 8;
    233 
    234     private final Context mContext;
    235     private final IActivityManager mActivityManager;
    236     private final IPowerManager mPowerManager;
    237     private final INetworkStatsService mNetworkStats;
    238     private final INetworkManagementService mNetworkManager;
    239     private final TrustedTime mTime;
    240 
    241     private IConnectivityManager mConnManager;
    242     private INotificationManager mNotifManager;
    243 
    244     private final Object mRulesLock = new Object();
    245 
    246     private volatile boolean mScreenOn;
    247     private volatile boolean mRestrictBackground;
    248 
    249     private final boolean mSuppressDefaultPolicy;
    250 
    251     /** Defined network policies. */
    252     private HashMap<NetworkTemplate, NetworkPolicy> mNetworkPolicy = Maps.newHashMap();
    253     /** Currently active network rules for ifaces. */
    254     private HashMap<NetworkPolicy, String[]> mNetworkRules = Maps.newHashMap();
    255 
    256     /** Defined UID policies. */
    257     private SparseIntArray mUidPolicy = new SparseIntArray();
    258     /** Currently derived rules for each UID. */
    259     private SparseIntArray mUidRules = new SparseIntArray();
    260 
    261     /** Set of ifaces that are metered. */
    262     private HashSet<String> mMeteredIfaces = Sets.newHashSet();
    263     /** Set of over-limit templates that have been notified. */
    264     private HashSet<NetworkTemplate> mOverLimitNotified = Sets.newHashSet();
    265 
    266     /** Set of currently active {@link Notification} tags. */
    267     private HashSet<String> mActiveNotifs = Sets.newHashSet();
    268 
    269     /** Foreground at both UID and PID granularity. */
    270     private SparseBooleanArray mUidForeground = new SparseBooleanArray();
    271     private SparseArray<SparseBooleanArray> mUidPidForeground = new SparseArray<
    272             SparseBooleanArray>();
    273 
    274     private final RemoteCallbackList<INetworkPolicyListener> mListeners = new RemoteCallbackList<
    275             INetworkPolicyListener>();
    276 
    277     private final HandlerThread mHandlerThread;
    278     private final Handler mHandler;
    279 
    280     private final AtomicFile mPolicyFile;
    281 
    282     // TODO: keep whitelist of system-critical services that should never have
    283     // rules enforced, such as system, phone, and radio UIDs.
    284 
    285     // TODO: migrate notifications to SystemUI
    286 
    287     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
    288             IPowerManager powerManager, INetworkStatsService networkStats,
    289             INetworkManagementService networkManagement) {
    290         this(context, activityManager, powerManager, networkStats, networkManagement,
    291                 NtpTrustedTime.getInstance(context), getSystemDir(), false);
    292     }
    293 
    294     private static File getSystemDir() {
    295         return new File(Environment.getDataDirectory(), "system");
    296     }
    297 
    298     public NetworkPolicyManagerService(Context context, IActivityManager activityManager,
    299             IPowerManager powerManager, INetworkStatsService networkStats,
    300             INetworkManagementService networkManagement, TrustedTime time, File systemDir,
    301             boolean suppressDefaultPolicy) {
    302         mContext = checkNotNull(context, "missing context");
    303         mActivityManager = checkNotNull(activityManager, "missing activityManager");
    304         mPowerManager = checkNotNull(powerManager, "missing powerManager");
    305         mNetworkStats = checkNotNull(networkStats, "missing networkStats");
    306         mNetworkManager = checkNotNull(networkManagement, "missing networkManagement");
    307         mTime = checkNotNull(time, "missing TrustedTime");
    308 
    309         mHandlerThread = new HandlerThread(TAG);
    310         mHandlerThread.start();
    311         mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
    312 
    313         mSuppressDefaultPolicy = suppressDefaultPolicy;
    314 
    315         mPolicyFile = new AtomicFile(new File(systemDir, "netpolicy.xml"));
    316     }
    317 
    318     public void bindConnectivityManager(IConnectivityManager connManager) {
    319         mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
    320     }
    321 
    322     public void bindNotificationManager(INotificationManager notifManager) {
    323         mNotifManager = checkNotNull(notifManager, "missing INotificationManager");
    324     }
    325 
    326     public void systemReady() {
    327         if (!isBandwidthControlEnabled()) {
    328             Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
    329             return;
    330         }
    331 
    332         synchronized (mRulesLock) {
    333             // read policy from disk
    334             readPolicyLocked();
    335 
    336             if (mRestrictBackground) {
    337                 updateRulesForRestrictBackgroundLocked();
    338                 updateNotificationsLocked();
    339             }
    340         }
    341 
    342         updateScreenOn();
    343 
    344         try {
    345             mActivityManager.registerProcessObserver(mProcessObserver);
    346             mNetworkManager.registerObserver(mAlertObserver);
    347         } catch (RemoteException e) {
    348             // ignored; both services live in system_server
    349         }
    350 
    351         // TODO: traverse existing processes to know foreground state, or have
    352         // activitymanager dispatch current state when new observer attached.
    353 
    354         final IntentFilter screenFilter = new IntentFilter();
    355         screenFilter.addAction(Intent.ACTION_SCREEN_ON);
    356         screenFilter.addAction(Intent.ACTION_SCREEN_OFF);
    357         mContext.registerReceiver(mScreenReceiver, screenFilter);
    358 
    359         // watch for network interfaces to be claimed
    360         final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
    361         mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
    362 
    363         // listen for package changes to update policy
    364         final IntentFilter packageFilter = new IntentFilter();
    365         packageFilter.addAction(ACTION_PACKAGE_ADDED);
    366         packageFilter.addDataScheme("package");
    367         mContext.registerReceiver(mPackageReceiver, packageFilter, null, mHandler);
    368 
    369         // listen for UID changes to update policy
    370         mContext.registerReceiver(
    371                 mUidRemovedReceiver, new IntentFilter(ACTION_UID_REMOVED), null, mHandler);
    372 
    373         // listen for user changes to update policy
    374         final IntentFilter userFilter = new IntentFilter();
    375         userFilter.addAction(ACTION_USER_ADDED);
    376         userFilter.addAction(ACTION_USER_REMOVED);
    377         mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
    378 
    379         // listen for stats update events
    380         final IntentFilter statsFilter = new IntentFilter(ACTION_NETWORK_STATS_UPDATED);
    381         mContext.registerReceiver(
    382                 mStatsReceiver, statsFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
    383 
    384         // listen for restrict background changes from notifications
    385         final IntentFilter allowFilter = new IntentFilter(ACTION_ALLOW_BACKGROUND);
    386         mContext.registerReceiver(mAllowReceiver, allowFilter, MANAGE_NETWORK_POLICY, mHandler);
    387 
    388         // listen for snooze warning from notifications
    389         final IntentFilter snoozeWarningFilter = new IntentFilter(ACTION_SNOOZE_WARNING);
    390         mContext.registerReceiver(mSnoozeWarningReceiver, snoozeWarningFilter,
    391                 MANAGE_NETWORK_POLICY, mHandler);
    392 
    393         // listen for configured wifi networks to be removed
    394         final IntentFilter wifiConfigFilter = new IntentFilter(CONFIGURED_NETWORKS_CHANGED_ACTION);
    395         mContext.registerReceiver(
    396                 mWifiConfigReceiver, wifiConfigFilter, CONNECTIVITY_INTERNAL, mHandler);
    397 
    398         // listen for wifi state changes to catch metered hint
    399         final IntentFilter wifiStateFilter = new IntentFilter(
    400                 WifiManager.NETWORK_STATE_CHANGED_ACTION);
    401         mContext.registerReceiver(
    402                 mWifiStateReceiver, wifiStateFilter, CONNECTIVITY_INTERNAL, mHandler);
    403 
    404     }
    405 
    406     private IProcessObserver mProcessObserver = new IProcessObserver.Stub() {
    407         @Override
    408         public void onForegroundActivitiesChanged(int pid, int uid, boolean foregroundActivities) {
    409             mHandler.obtainMessage(MSG_FOREGROUND_ACTIVITIES_CHANGED,
    410                     pid, uid, foregroundActivities).sendToTarget();
    411         }
    412 
    413         @Override
    414         public void onImportanceChanged(int pid, int uid, int importance) {
    415         }
    416 
    417         @Override
    418         public void onProcessDied(int pid, int uid) {
    419             mHandler.obtainMessage(MSG_PROCESS_DIED, pid, uid).sendToTarget();
    420         }
    421     };
    422 
    423     private BroadcastReceiver mScreenReceiver = new BroadcastReceiver() {
    424         @Override
    425         public void onReceive(Context context, Intent intent) {
    426             // screen-related broadcasts are protected by system, no need
    427             // for permissions check.
    428             mHandler.obtainMessage(MSG_SCREEN_ON_CHANGED).sendToTarget();
    429         }
    430     };
    431 
    432     private BroadcastReceiver mPackageReceiver = new BroadcastReceiver() {
    433         @Override
    434         public void onReceive(Context context, Intent intent) {
    435             // on background handler thread, and PACKAGE_ADDED is protected
    436 
    437             final String action = intent.getAction();
    438             final int uid = intent.getIntExtra(EXTRA_UID, -1);
    439             if (uid == -1) return;
    440 
    441             if (ACTION_PACKAGE_ADDED.equals(action)) {
    442                 // update rules for UID, since it might be subject to
    443                 // global background data policy
    444                 if (LOGV) Slog.v(TAG, "ACTION_PACKAGE_ADDED for uid=" + uid);
    445                 synchronized (mRulesLock) {
    446                     updateRulesForUidLocked(uid);
    447                 }
    448             }
    449         }
    450     };
    451 
    452     private BroadcastReceiver mUidRemovedReceiver = new BroadcastReceiver() {
    453         @Override
    454         public void onReceive(Context context, Intent intent) {
    455             // on background handler thread, and UID_REMOVED is protected
    456 
    457             final int uid = intent.getIntExtra(EXTRA_UID, -1);
    458             if (uid == -1) return;
    459 
    460             // remove any policy and update rules to clean up
    461             if (LOGV) Slog.v(TAG, "ACTION_UID_REMOVED for uid=" + uid);
    462             synchronized (mRulesLock) {
    463                 mUidPolicy.delete(uid);
    464                 updateRulesForUidLocked(uid);
    465                 writePolicyLocked();
    466             }
    467         }
    468     };
    469 
    470     private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
    471         @Override
    472         public void onReceive(Context context, Intent intent) {
    473             // on background handler thread, and USER_ADDED and USER_REMOVED
    474             // broadcasts are protected
    475 
    476             final String action = intent.getAction();
    477             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
    478             if (userId == -1) return;
    479 
    480             // Remove any policies for given user; both cleaning up after a
    481             // USER_REMOVED, and one last sanity check during USER_ADDED
    482             removePoliciesForUserLocked(userId);
    483 
    484             // Update global restrict for new user
    485             synchronized (mRulesLock) {
    486                 updateRulesForRestrictBackgroundLocked();
    487             }
    488         }
    489     };
    490 
    491     /**
    492      * Receiver that watches for {@link INetworkStatsService} updates, which we
    493      * use to check against {@link NetworkPolicy#warningBytes}.
    494      */
    495     private BroadcastReceiver mStatsReceiver = new BroadcastReceiver() {
    496         @Override
    497         public void onReceive(Context context, Intent intent) {
    498             // on background handler thread, and verified
    499             // READ_NETWORK_USAGE_HISTORY permission above.
    500 
    501             maybeRefreshTrustedTime();
    502             synchronized (mRulesLock) {
    503                 updateNetworkEnabledLocked();
    504                 updateNotificationsLocked();
    505             }
    506         }
    507     };
    508 
    509     /**
    510      * Receiver that watches for {@link Notification} control of
    511      * {@link #mRestrictBackground}.
    512      */
    513     private BroadcastReceiver mAllowReceiver = new BroadcastReceiver() {
    514         @Override
    515         public void onReceive(Context context, Intent intent) {
    516             // on background handler thread, and verified MANAGE_NETWORK_POLICY
    517             // permission above.
    518 
    519             setRestrictBackground(false);
    520         }
    521     };
    522 
    523     /**
    524      * Receiver that watches for {@link Notification} control of
    525      * {@link NetworkPolicy#lastWarningSnooze}.
    526      */
    527     private BroadcastReceiver mSnoozeWarningReceiver = new BroadcastReceiver() {
    528         @Override
    529         public void onReceive(Context context, Intent intent) {
    530             // on background handler thread, and verified MANAGE_NETWORK_POLICY
    531             // permission above.
    532 
    533             final NetworkTemplate template = intent.getParcelableExtra(EXTRA_NETWORK_TEMPLATE);
    534             performSnooze(template, TYPE_WARNING);
    535         }
    536     };
    537 
    538     /**
    539      * Receiver that watches for {@link WifiConfiguration} to be changed.
    540      */
    541     private BroadcastReceiver mWifiConfigReceiver = new BroadcastReceiver() {
    542         @Override
    543         public void onReceive(Context context, Intent intent) {
    544             // on background handler thread, and verified CONNECTIVITY_INTERNAL
    545             // permission above.
    546 
    547             final int reason = intent.getIntExtra(EXTRA_CHANGE_REASON, CHANGE_REASON_ADDED);
    548             if (reason == CHANGE_REASON_REMOVED) {
    549                 final WifiConfiguration config = intent.getParcelableExtra(
    550                         EXTRA_WIFI_CONFIGURATION);
    551                 if (config.SSID != null) {
    552                     final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(config.SSID);
    553                     synchronized (mRulesLock) {
    554                         if (mNetworkPolicy.containsKey(template)) {
    555                             mNetworkPolicy.remove(template);
    556                             writePolicyLocked();
    557                         }
    558                     }
    559                 }
    560             }
    561         }
    562     };
    563 
    564     /**
    565      * Receiver that watches {@link WifiInfo} state changes to infer metered
    566      * state. Ignores hints when policy is user-defined.
    567      */
    568     private BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() {
    569         @Override
    570         public void onReceive(Context context, Intent intent) {
    571             // on background handler thread, and verified CONNECTIVITY_INTERNAL
    572             // permission above.
    573 
    574             // ignore when not connected
    575             final NetworkInfo netInfo = intent.getParcelableExtra(EXTRA_NETWORK_INFO);
    576             if (!netInfo.isConnected()) return;
    577 
    578             final WifiInfo info = intent.getParcelableExtra(EXTRA_WIFI_INFO);
    579             final boolean meteredHint = info.getMeteredHint();
    580 
    581             final NetworkTemplate template = NetworkTemplate.buildTemplateWifi(info.getSSID());
    582             synchronized (mRulesLock) {
    583                 NetworkPolicy policy = mNetworkPolicy.get(template);
    584                 if (policy == null && meteredHint) {
    585                     // policy doesn't exist, and AP is hinting that it's
    586                     // metered: create an inferred policy.
    587                     policy = new NetworkPolicy(template, CYCLE_NONE, Time.TIMEZONE_UTC,
    588                             WARNING_DISABLED, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER,
    589                             meteredHint, true);
    590                     addNetworkPolicyLocked(policy);
    591 
    592                 } else if (policy != null && policy.inferred) {
    593                     // policy exists, and was inferred: update its current
    594                     // metered state.
    595                     policy.metered = meteredHint;
    596 
    597                     // since this is inferred for each wifi session, just update
    598                     // rules without persisting.
    599                     updateNetworkRulesLocked();
    600                 }
    601             }
    602         }
    603     };
    604 
    605     /**
    606      * Observer that watches for {@link INetworkManagementService} alerts.
    607      */
    608     private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
    609         @Override
    610         public void limitReached(String limitName, String iface) {
    611             // only someone like NMS should be calling us
    612             mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    613 
    614             if (!LIMIT_GLOBAL_ALERT.equals(limitName)) {
    615                 mHandler.obtainMessage(MSG_LIMIT_REACHED, iface).sendToTarget();
    616             }
    617         }
    618     };
    619 
    620     /**
    621      * Check {@link NetworkPolicy} against current {@link INetworkStatsService}
    622      * to show visible notifications as needed.
    623      */
    624     private void updateNotificationsLocked() {
    625         if (LOGV) Slog.v(TAG, "updateNotificationsLocked()");
    626 
    627         // keep track of previously active notifications
    628         final HashSet<String> beforeNotifs = Sets.newHashSet();
    629         beforeNotifs.addAll(mActiveNotifs);
    630         mActiveNotifs.clear();
    631 
    632         // TODO: when switching to kernel notifications, compute next future
    633         // cycle boundary to recompute notifications.
    634 
    635         // examine stats for each active policy
    636         final long currentTime = currentTimeMillis();
    637         for (NetworkPolicy policy : mNetworkPolicy.values()) {
    638             // ignore policies that aren't relevant to user
    639             if (!isTemplateRelevant(policy.template)) continue;
    640             if (!policy.hasCycle()) continue;
    641 
    642             final long start = computeLastCycleBoundary(currentTime, policy);
    643             final long end = currentTime;
    644             final long totalBytes = getTotalBytes(policy.template, start, end);
    645 
    646             if (policy.isOverLimit(totalBytes)) {
    647                 if (policy.lastLimitSnooze >= start) {
    648                     enqueueNotification(policy, TYPE_LIMIT_SNOOZED, totalBytes);
    649                 } else {
    650                     enqueueNotification(policy, TYPE_LIMIT, totalBytes);
    651                     notifyOverLimitLocked(policy.template);
    652                 }
    653 
    654             } else {
    655                 notifyUnderLimitLocked(policy.template);
    656 
    657                 if (policy.isOverWarning(totalBytes) && policy.lastWarningSnooze < start) {
    658                     enqueueNotification(policy, TYPE_WARNING, totalBytes);
    659                 }
    660             }
    661         }
    662 
    663         // ongoing notification when restricting background data
    664         if (mRestrictBackground) {
    665             enqueueRestrictedNotification(TAG_ALLOW_BACKGROUND);
    666         }
    667 
    668         // cancel stale notifications that we didn't renew above
    669         for (String tag : beforeNotifs) {
    670             if (!mActiveNotifs.contains(tag)) {
    671                 cancelNotification(tag);
    672             }
    673         }
    674     }
    675 
    676     /**
    677      * Test if given {@link NetworkTemplate} is relevant to user based on
    678      * current device state, such as when
    679      * {@link TelephonyManager#getSubscriberId()} matches. This is regardless of
    680      * data connection status.
    681      */
    682     private boolean isTemplateRelevant(NetworkTemplate template) {
    683         final TelephonyManager tele = TelephonyManager.from(mContext);
    684 
    685         switch (template.getMatchRule()) {
    686             case MATCH_MOBILE_3G_LOWER:
    687             case MATCH_MOBILE_4G:
    688             case MATCH_MOBILE_ALL:
    689                 // mobile templates are relevant when SIM is ready and
    690                 // subscriberId matches.
    691                 if (tele.getSimState() == SIM_STATE_READY) {
    692                     return Objects.equal(tele.getSubscriberId(), template.getSubscriberId());
    693                 } else {
    694                     return false;
    695                 }
    696         }
    697         return true;
    698     }
    699 
    700     /**
    701      * Notify that given {@link NetworkTemplate} is over
    702      * {@link NetworkPolicy#limitBytes}, potentially showing dialog to user.
    703      */
    704     private void notifyOverLimitLocked(NetworkTemplate template) {
    705         if (!mOverLimitNotified.contains(template)) {
    706             mContext.startActivity(buildNetworkOverLimitIntent(template));
    707             mOverLimitNotified.add(template);
    708         }
    709     }
    710 
    711     private void notifyUnderLimitLocked(NetworkTemplate template) {
    712         mOverLimitNotified.remove(template);
    713     }
    714 
    715     /**
    716      * Build unique tag that identifies an active {@link NetworkPolicy}
    717      * notification of a specific type, like {@link #TYPE_LIMIT}.
    718      */
    719     private String buildNotificationTag(NetworkPolicy policy, int type) {
    720         return TAG + ":" + policy.template.hashCode() + ":" + type;
    721     }
    722 
    723     /**
    724      * Show notification for combined {@link NetworkPolicy} and specific type,
    725      * like {@link #TYPE_LIMIT}. Okay to call multiple times.
    726      */
    727     private void enqueueNotification(NetworkPolicy policy, int type, long totalBytes) {
    728         final String tag = buildNotificationTag(policy, type);
    729         final Notification.Builder builder = new Notification.Builder(mContext);
    730         builder.setOnlyAlertOnce(true);
    731         builder.setWhen(0L);
    732 
    733         final Resources res = mContext.getResources();
    734         switch (type) {
    735             case TYPE_WARNING: {
    736                 final CharSequence title = res.getText(R.string.data_usage_warning_title);
    737                 final CharSequence body = res.getString(R.string.data_usage_warning_body);
    738 
    739                 builder.setSmallIcon(R.drawable.stat_notify_error);
    740                 builder.setTicker(title);
    741                 builder.setContentTitle(title);
    742                 builder.setContentText(body);
    743 
    744                 final Intent snoozeIntent = buildSnoozeWarningIntent(policy.template);
    745                 builder.setDeleteIntent(PendingIntent.getBroadcast(
    746                         mContext, 0, snoozeIntent, PendingIntent.FLAG_UPDATE_CURRENT));
    747 
    748                 final Intent viewIntent = buildViewDataUsageIntent(policy.template);
    749                 builder.setContentIntent(PendingIntent.getActivity(
    750                         mContext, 0, viewIntent, PendingIntent.FLAG_UPDATE_CURRENT));
    751 
    752                 break;
    753             }
    754             case TYPE_LIMIT: {
    755                 final CharSequence body = res.getText(R.string.data_usage_limit_body);
    756 
    757                 final CharSequence title;
    758                 switch (policy.template.getMatchRule()) {
    759                     case MATCH_MOBILE_3G_LOWER:
    760                         title = res.getText(R.string.data_usage_3g_limit_title);
    761                         break;
    762                     case MATCH_MOBILE_4G:
    763                         title = res.getText(R.string.data_usage_4g_limit_title);
    764                         break;
    765                     case MATCH_MOBILE_ALL:
    766                         title = res.getText(R.string.data_usage_mobile_limit_title);
    767                         break;
    768                     case MATCH_WIFI:
    769                         title = res.getText(R.string.data_usage_wifi_limit_title);
    770                         break;
    771                     default:
    772                         title = null;
    773                         break;
    774                 }
    775 
    776                 builder.setOngoing(true);
    777                 builder.setSmallIcon(R.drawable.stat_notify_disabled);
    778                 builder.setTicker(title);
    779                 builder.setContentTitle(title);
    780                 builder.setContentText(body);
    781 
    782                 final Intent intent = buildNetworkOverLimitIntent(policy.template);
    783                 builder.setContentIntent(PendingIntent.getActivity(
    784                         mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
    785                 break;
    786             }
    787             case TYPE_LIMIT_SNOOZED: {
    788                 final long overBytes = totalBytes - policy.limitBytes;
    789                 final CharSequence body = res.getString(R.string.data_usage_limit_snoozed_body,
    790                         Formatter.formatFileSize(mContext, overBytes));
    791 
    792                 final CharSequence title;
    793                 switch (policy.template.getMatchRule()) {
    794                     case MATCH_MOBILE_3G_LOWER:
    795                         title = res.getText(R.string.data_usage_3g_limit_snoozed_title);
    796                         break;
    797                     case MATCH_MOBILE_4G:
    798                         title = res.getText(R.string.data_usage_4g_limit_snoozed_title);
    799                         break;
    800                     case MATCH_MOBILE_ALL:
    801                         title = res.getText(R.string.data_usage_mobile_limit_snoozed_title);
    802                         break;
    803                     case MATCH_WIFI:
    804                         title = res.getText(R.string.data_usage_wifi_limit_snoozed_title);
    805                         break;
    806                     default:
    807                         title = null;
    808                         break;
    809                 }
    810 
    811                 builder.setOngoing(true);
    812                 builder.setSmallIcon(R.drawable.stat_notify_error);
    813                 builder.setTicker(title);
    814                 builder.setContentTitle(title);
    815                 builder.setContentText(body);
    816 
    817                 final Intent intent = buildViewDataUsageIntent(policy.template);
    818                 builder.setContentIntent(PendingIntent.getActivity(
    819                         mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
    820                 break;
    821             }
    822         }
    823 
    824         // TODO: move to NotificationManager once we can mock it
    825         // XXX what to do about multi-user?
    826         try {
    827             final String packageName = mContext.getPackageName();
    828             final int[] idReceived = new int[1];
    829             mNotifManager.enqueueNotificationWithTag(
    830                     packageName, packageName, tag, 0x0, builder.getNotification(), idReceived,
    831                     UserHandle.USER_OWNER);
    832             mActiveNotifs.add(tag);
    833         } catch (RemoteException e) {
    834             // ignored; service lives in system_server
    835         }
    836     }
    837 
    838     /**
    839      * Show ongoing notification to reflect that {@link #mRestrictBackground}
    840      * has been enabled.
    841      */
    842     private void enqueueRestrictedNotification(String tag) {
    843         final Resources res = mContext.getResources();
    844         final Notification.Builder builder = new Notification.Builder(mContext);
    845 
    846         final CharSequence title = res.getText(R.string.data_usage_restricted_title);
    847         final CharSequence body = res.getString(R.string.data_usage_restricted_body);
    848 
    849         builder.setOnlyAlertOnce(true);
    850         builder.setOngoing(true);
    851         builder.setSmallIcon(R.drawable.stat_notify_error);
    852         builder.setTicker(title);
    853         builder.setContentTitle(title);
    854         builder.setContentText(body);
    855 
    856         final Intent intent = buildAllowBackgroundDataIntent();
    857         builder.setContentIntent(
    858                 PendingIntent.getBroadcast(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT));
    859 
    860         // TODO: move to NotificationManager once we can mock it
    861         // XXX what to do about multi-user?
    862         try {
    863             final String packageName = mContext.getPackageName();
    864             final int[] idReceived = new int[1];
    865             mNotifManager.enqueueNotificationWithTag(packageName, packageName, tag,
    866                     0x0, builder.getNotification(), idReceived, UserHandle.USER_OWNER);
    867             mActiveNotifs.add(tag);
    868         } catch (RemoteException e) {
    869             // ignored; service lives in system_server
    870         }
    871     }
    872 
    873     private void cancelNotification(String tag) {
    874         // TODO: move to NotificationManager once we can mock it
    875         // XXX what to do about multi-user?
    876         try {
    877             final String packageName = mContext.getPackageName();
    878             mNotifManager.cancelNotificationWithTag(
    879                     packageName, tag, 0x0, UserHandle.USER_OWNER);
    880         } catch (RemoteException e) {
    881             // ignored; service lives in system_server
    882         }
    883     }
    884 
    885     /**
    886      * Receiver that watches for {@link IConnectivityManager} to claim network
    887      * interfaces. Used to apply {@link NetworkPolicy} to matching networks.
    888      */
    889     private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
    890         @Override
    891         public void onReceive(Context context, Intent intent) {
    892             // on background handler thread, and verified CONNECTIVITY_INTERNAL
    893             // permission above.
    894 
    895             maybeRefreshTrustedTime();
    896             synchronized (mRulesLock) {
    897                 ensureActiveMobilePolicyLocked();
    898                 updateNetworkEnabledLocked();
    899                 updateNetworkRulesLocked();
    900                 updateNotificationsLocked();
    901             }
    902         }
    903     };
    904 
    905     /**
    906      * Proactively control network data connections when they exceed
    907      * {@link NetworkPolicy#limitBytes}.
    908      */
    909     private void updateNetworkEnabledLocked() {
    910         if (LOGV) Slog.v(TAG, "updateNetworkEnabledLocked()");
    911 
    912         // TODO: reset any policy-disabled networks when any policy is removed
    913         // completely, which is currently rare case.
    914 
    915         final long currentTime = currentTimeMillis();
    916         for (NetworkPolicy policy : mNetworkPolicy.values()) {
    917             // shortcut when policy has no limit
    918             if (policy.limitBytes == LIMIT_DISABLED || !policy.hasCycle()) {
    919                 setNetworkTemplateEnabled(policy.template, true);
    920                 continue;
    921             }
    922 
    923             final long start = computeLastCycleBoundary(currentTime, policy);
    924             final long end = currentTime;
    925             final long totalBytes = getTotalBytes(policy.template, start, end);
    926 
    927             // disable data connection when over limit and not snoozed
    928             final boolean overLimitWithoutSnooze = policy.isOverLimit(totalBytes)
    929                     && policy.lastLimitSnooze < start;
    930             final boolean networkEnabled = !overLimitWithoutSnooze;
    931 
    932             setNetworkTemplateEnabled(policy.template, networkEnabled);
    933         }
    934     }
    935 
    936     /**
    937      * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}
    938      * for the given {@link NetworkTemplate}.
    939      */
    940     private void setNetworkTemplateEnabled(NetworkTemplate template, boolean enabled) {
    941         final TelephonyManager tele = TelephonyManager.from(mContext);
    942 
    943         switch (template.getMatchRule()) {
    944             case MATCH_MOBILE_3G_LOWER:
    945             case MATCH_MOBILE_4G:
    946             case MATCH_MOBILE_ALL:
    947                 // TODO: offer more granular control over radio states once
    948                 // 4965893 is available.
    949                 if (tele.getSimState() == SIM_STATE_READY
    950                         && Objects.equal(tele.getSubscriberId(), template.getSubscriberId())) {
    951                     setPolicyDataEnable(TYPE_MOBILE, enabled);
    952                     setPolicyDataEnable(TYPE_WIMAX, enabled);
    953                 }
    954                 break;
    955             case MATCH_WIFI:
    956                 setPolicyDataEnable(TYPE_WIFI, enabled);
    957                 break;
    958             case MATCH_ETHERNET:
    959                 setPolicyDataEnable(TYPE_ETHERNET, enabled);
    960                 break;
    961             default:
    962                 throw new IllegalArgumentException("unexpected template");
    963         }
    964     }
    965 
    966     /**
    967      * Examine all connected {@link NetworkState}, looking for
    968      * {@link NetworkPolicy} that need to be enforced. When matches found, set
    969      * remaining quota based on usage cycle and historical stats.
    970      */
    971     private void updateNetworkRulesLocked() {
    972         if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
    973 
    974         final NetworkState[] states;
    975         try {
    976             states = mConnManager.getAllNetworkState();
    977         } catch (RemoteException e) {
    978             // ignored; service lives in system_server
    979             return;
    980         }
    981 
    982         // first, derive identity for all connected networks, which can be used
    983         // to match against templates.
    984         final HashMap<NetworkIdentity, String> networks = Maps.newHashMap();
    985         for (NetworkState state : states) {
    986             // stash identity and iface away for later use
    987             if (state.networkInfo.isConnected()) {
    988                 final String iface = state.linkProperties.getInterfaceName();
    989                 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
    990                 networks.put(ident, iface);
    991             }
    992         }
    993 
    994         // build list of rules and ifaces to enforce them against
    995         mNetworkRules.clear();
    996         final ArrayList<String> ifaceList = Lists.newArrayList();
    997         for (NetworkPolicy policy : mNetworkPolicy.values()) {
    998 
    999             // collect all active ifaces that match this template
   1000             ifaceList.clear();
   1001             for (Map.Entry<NetworkIdentity, String> entry : networks.entrySet()) {
   1002                 final NetworkIdentity ident = entry.getKey();
   1003                 if (policy.template.matches(ident)) {
   1004                     final String iface = entry.getValue();
   1005                     ifaceList.add(iface);
   1006                 }
   1007             }
   1008 
   1009             if (ifaceList.size() > 0) {
   1010                 final String[] ifaces = ifaceList.toArray(new String[ifaceList.size()]);
   1011                 mNetworkRules.put(policy, ifaces);
   1012             }
   1013         }
   1014 
   1015         long lowestRule = Long.MAX_VALUE;
   1016         final HashSet<String> newMeteredIfaces = Sets.newHashSet();
   1017 
   1018         // apply each policy that we found ifaces for; compute remaining data
   1019         // based on current cycle and historical stats, and push to kernel.
   1020         final long currentTime = currentTimeMillis();
   1021         for (NetworkPolicy policy : mNetworkRules.keySet()) {
   1022             final String[] ifaces = mNetworkRules.get(policy);
   1023 
   1024             final long start;
   1025             final long totalBytes;
   1026             if (policy.hasCycle()) {
   1027                 start = computeLastCycleBoundary(currentTime, policy);
   1028                 totalBytes = getTotalBytes(policy.template, start, currentTime);
   1029             } else {
   1030                 start = Long.MAX_VALUE;
   1031                 totalBytes = 0;
   1032             }
   1033 
   1034             if (LOGD) {
   1035                 Slog.d(TAG, "applying policy " + policy.toString() + " to ifaces "
   1036                         + Arrays.toString(ifaces));
   1037             }
   1038 
   1039             final boolean hasWarning = policy.warningBytes != LIMIT_DISABLED;
   1040             final boolean hasLimit = policy.limitBytes != LIMIT_DISABLED;
   1041             if (hasLimit || policy.metered) {
   1042                 final long quotaBytes;
   1043                 if (!hasLimit) {
   1044                     // metered network, but no policy limit; we still need to
   1045                     // restrict apps, so push really high quota.
   1046                     quotaBytes = Long.MAX_VALUE;
   1047                 } else if (policy.lastLimitSnooze >= start) {
   1048                     // snoozing past quota, but we still need to restrict apps,
   1049                     // so push really high quota.
   1050                     quotaBytes = Long.MAX_VALUE;
   1051                 } else {
   1052                     // remaining "quota" bytes are based on total usage in
   1053                     // current cycle. kernel doesn't like 0-byte rules, so we
   1054                     // set 1-byte quota and disable the radio later.
   1055                     quotaBytes = Math.max(1, policy.limitBytes - totalBytes);
   1056                 }
   1057 
   1058                 if (ifaces.length > 1) {
   1059                     // TODO: switch to shared quota once NMS supports
   1060                     Slog.w(TAG, "shared quota unsupported; generating rule for each iface");
   1061                 }
   1062 
   1063                 for (String iface : ifaces) {
   1064                     removeInterfaceQuota(iface);
   1065                     setInterfaceQuota(iface, quotaBytes);
   1066                     newMeteredIfaces.add(iface);
   1067                 }
   1068             }
   1069 
   1070             // keep track of lowest warning or limit of active policies
   1071             if (hasWarning && policy.warningBytes < lowestRule) {
   1072                 lowestRule = policy.warningBytes;
   1073             }
   1074             if (hasLimit && policy.limitBytes < lowestRule) {
   1075                 lowestRule = policy.limitBytes;
   1076             }
   1077         }
   1078 
   1079         mHandler.obtainMessage(MSG_ADVISE_PERSIST_THRESHOLD, lowestRule).sendToTarget();
   1080 
   1081         // remove quota on any trailing interfaces
   1082         for (String iface : mMeteredIfaces) {
   1083             if (!newMeteredIfaces.contains(iface)) {
   1084                 removeInterfaceQuota(iface);
   1085             }
   1086         }
   1087         mMeteredIfaces = newMeteredIfaces;
   1088 
   1089         final String[] meteredIfaces = mMeteredIfaces.toArray(new String[mMeteredIfaces.size()]);
   1090         mHandler.obtainMessage(MSG_METERED_IFACES_CHANGED, meteredIfaces).sendToTarget();
   1091     }
   1092 
   1093     /**
   1094      * Once any {@link #mNetworkPolicy} are loaded from disk, ensure that we
   1095      * have at least a default mobile policy defined.
   1096      */
   1097     private void ensureActiveMobilePolicyLocked() {
   1098         if (LOGV) Slog.v(TAG, "ensureActiveMobilePolicyLocked()");
   1099         if (mSuppressDefaultPolicy) return;
   1100 
   1101         final TelephonyManager tele = TelephonyManager.from(mContext);
   1102 
   1103         // avoid creating policy when SIM isn't ready
   1104         if (tele.getSimState() != SIM_STATE_READY) return;
   1105 
   1106         final String subscriberId = tele.getSubscriberId();
   1107         final NetworkIdentity probeIdent = new NetworkIdentity(
   1108                 TYPE_MOBILE, TelephonyManager.NETWORK_TYPE_UNKNOWN, subscriberId, null, false);
   1109 
   1110         // examine to see if any policy is defined for active mobile
   1111         boolean mobileDefined = false;
   1112         for (NetworkPolicy policy : mNetworkPolicy.values()) {
   1113             if (policy.template.matches(probeIdent)) {
   1114                 mobileDefined = true;
   1115             }
   1116         }
   1117 
   1118         if (!mobileDefined) {
   1119             Slog.i(TAG, "no policy for active mobile network; generating default policy");
   1120 
   1121             // build default mobile policy, and assume usage cycle starts today
   1122             final long warningBytes = mContext.getResources().getInteger(
   1123                     com.android.internal.R.integer.config_networkPolicyDefaultWarning)
   1124                     * MB_IN_BYTES;
   1125 
   1126             final Time time = new Time();
   1127             time.setToNow();
   1128 
   1129             final int cycleDay = time.monthDay;
   1130             final String cycleTimezone = time.timezone;
   1131 
   1132             final NetworkTemplate template = buildTemplateMobileAll(subscriberId);
   1133             final NetworkPolicy policy = new NetworkPolicy(template, cycleDay, cycleTimezone,
   1134                     warningBytes, LIMIT_DISABLED, SNOOZE_NEVER, SNOOZE_NEVER, true, true);
   1135             addNetworkPolicyLocked(policy);
   1136         }
   1137     }
   1138 
   1139     private void readPolicyLocked() {
   1140         if (LOGV) Slog.v(TAG, "readPolicyLocked()");
   1141 
   1142         // clear any existing policy and read from disk
   1143         mNetworkPolicy.clear();
   1144         mUidPolicy.clear();
   1145 
   1146         FileInputStream fis = null;
   1147         try {
   1148             fis = mPolicyFile.openRead();
   1149             final XmlPullParser in = Xml.newPullParser();
   1150             in.setInput(fis, null);
   1151 
   1152             int type;
   1153             int version = VERSION_INIT;
   1154             while ((type = in.next()) != END_DOCUMENT) {
   1155                 final String tag = in.getName();
   1156                 if (type == START_TAG) {
   1157                     if (TAG_POLICY_LIST.equals(tag)) {
   1158                         version = readIntAttribute(in, ATTR_VERSION);
   1159                         if (version >= VERSION_ADDED_RESTRICT_BACKGROUND) {
   1160                             mRestrictBackground = readBooleanAttribute(
   1161                                     in, ATTR_RESTRICT_BACKGROUND);
   1162                         } else {
   1163                             mRestrictBackground = false;
   1164                         }
   1165 
   1166                     } else if (TAG_NETWORK_POLICY.equals(tag)) {
   1167                         final int networkTemplate = readIntAttribute(in, ATTR_NETWORK_TEMPLATE);
   1168                         final String subscriberId = in.getAttributeValue(null, ATTR_SUBSCRIBER_ID);
   1169                         final String networkId;
   1170                         if (version >= VERSION_ADDED_NETWORK_ID) {
   1171                             networkId = in.getAttributeValue(null, ATTR_NETWORK_ID);
   1172                         } else {
   1173                             networkId = null;
   1174                         }
   1175                         final int cycleDay = readIntAttribute(in, ATTR_CYCLE_DAY);
   1176                         final String cycleTimezone;
   1177                         if (version >= VERSION_ADDED_TIMEZONE) {
   1178                             cycleTimezone = in.getAttributeValue(null, ATTR_CYCLE_TIMEZONE);
   1179                         } else {
   1180                             cycleTimezone = Time.TIMEZONE_UTC;
   1181                         }
   1182                         final long warningBytes = readLongAttribute(in, ATTR_WARNING_BYTES);
   1183                         final long limitBytes = readLongAttribute(in, ATTR_LIMIT_BYTES);
   1184                         final long lastLimitSnooze;
   1185                         if (version >= VERSION_SPLIT_SNOOZE) {
   1186                             lastLimitSnooze = readLongAttribute(in, ATTR_LAST_LIMIT_SNOOZE);
   1187                         } else if (version >= VERSION_ADDED_SNOOZE) {
   1188                             lastLimitSnooze = readLongAttribute(in, ATTR_LAST_SNOOZE);
   1189                         } else {
   1190                             lastLimitSnooze = SNOOZE_NEVER;
   1191                         }
   1192                         final boolean metered;
   1193                         if (version >= VERSION_ADDED_METERED) {
   1194                             metered = readBooleanAttribute(in, ATTR_METERED);
   1195                         } else {
   1196                             switch (networkTemplate) {
   1197                                 case MATCH_MOBILE_3G_LOWER:
   1198                                 case MATCH_MOBILE_4G:
   1199                                 case MATCH_MOBILE_ALL:
   1200                                     metered = true;
   1201                                     break;
   1202                                 default:
   1203                                     metered = false;
   1204                             }
   1205                         }
   1206                         final long lastWarningSnooze;
   1207                         if (version >= VERSION_SPLIT_SNOOZE) {
   1208                             lastWarningSnooze = readLongAttribute(in, ATTR_LAST_WARNING_SNOOZE);
   1209                         } else {
   1210                             lastWarningSnooze = SNOOZE_NEVER;
   1211                         }
   1212                         final boolean inferred;
   1213                         if (version >= VERSION_ADDED_INFERRED) {
   1214                             inferred = readBooleanAttribute(in, ATTR_INFERRED);
   1215                         } else {
   1216                             inferred = false;
   1217                         }
   1218 
   1219                         final NetworkTemplate template = new NetworkTemplate(
   1220                                 networkTemplate, subscriberId, networkId);
   1221                         mNetworkPolicy.put(template, new NetworkPolicy(template, cycleDay,
   1222                                 cycleTimezone, warningBytes, limitBytes, lastWarningSnooze,
   1223                                 lastLimitSnooze, metered, inferred));
   1224 
   1225                     } else if (TAG_UID_POLICY.equals(tag)) {
   1226                         final int uid = readIntAttribute(in, ATTR_UID);
   1227                         final int policy = readIntAttribute(in, ATTR_POLICY);
   1228 
   1229                         if (UserHandle.isApp(uid)) {
   1230                             setUidPolicyUnchecked(uid, policy, false);
   1231                         } else {
   1232                             Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
   1233                         }
   1234                     } else if (TAG_APP_POLICY.equals(tag)) {
   1235                         final int appId = readIntAttribute(in, ATTR_APP_ID);
   1236                         final int policy = readIntAttribute(in, ATTR_POLICY);
   1237 
   1238                         // TODO: set for other users during upgrade
   1239                         final int uid = UserHandle.getUid(UserHandle.USER_OWNER, appId);
   1240                         if (UserHandle.isApp(uid)) {
   1241                             setUidPolicyUnchecked(uid, policy, false);
   1242                         } else {
   1243                             Slog.w(TAG, "unable to apply policy to UID " + uid + "; ignoring");
   1244                         }
   1245                     }
   1246                 }
   1247             }
   1248 
   1249         } catch (FileNotFoundException e) {
   1250             // missing policy is okay, probably first boot
   1251             upgradeLegacyBackgroundData();
   1252         } catch (IOException e) {
   1253             Log.wtf(TAG, "problem reading network policy", e);
   1254         } catch (XmlPullParserException e) {
   1255             Log.wtf(TAG, "problem reading network policy", e);
   1256         } finally {
   1257             IoUtils.closeQuietly(fis);
   1258         }
   1259     }
   1260 
   1261     /**
   1262      * Upgrade legacy background data flags, notifying listeners of one last
   1263      * change to always-true.
   1264      */
   1265     private void upgradeLegacyBackgroundData() {
   1266         mRestrictBackground = Settings.Secure.getInt(
   1267                 mContext.getContentResolver(), Settings.Secure.BACKGROUND_DATA, 1) != 1;
   1268 
   1269         // kick off one last broadcast if restricted
   1270         if (mRestrictBackground) {
   1271             final Intent broadcast = new Intent(
   1272                     ConnectivityManager.ACTION_BACKGROUND_DATA_SETTING_CHANGED);
   1273             mContext.sendBroadcastAsUser(broadcast, UserHandle.ALL);
   1274         }
   1275     }
   1276 
   1277     private void writePolicyLocked() {
   1278         if (LOGV) Slog.v(TAG, "writePolicyLocked()");
   1279 
   1280         FileOutputStream fos = null;
   1281         try {
   1282             fos = mPolicyFile.startWrite();
   1283 
   1284             XmlSerializer out = new FastXmlSerializer();
   1285             out.setOutput(fos, "utf-8");
   1286             out.startDocument(null, true);
   1287 
   1288             out.startTag(null, TAG_POLICY_LIST);
   1289             writeIntAttribute(out, ATTR_VERSION, VERSION_LATEST);
   1290             writeBooleanAttribute(out, ATTR_RESTRICT_BACKGROUND, mRestrictBackground);
   1291 
   1292             // write all known network policies
   1293             for (NetworkPolicy policy : mNetworkPolicy.values()) {
   1294                 final NetworkTemplate template = policy.template;
   1295 
   1296                 out.startTag(null, TAG_NETWORK_POLICY);
   1297                 writeIntAttribute(out, ATTR_NETWORK_TEMPLATE, template.getMatchRule());
   1298                 final String subscriberId = template.getSubscriberId();
   1299                 if (subscriberId != null) {
   1300                     out.attribute(null, ATTR_SUBSCRIBER_ID, subscriberId);
   1301                 }
   1302                 final String networkId = template.getNetworkId();
   1303                 if (networkId != null) {
   1304                     out.attribute(null, ATTR_NETWORK_ID, networkId);
   1305                 }
   1306                 writeIntAttribute(out, ATTR_CYCLE_DAY, policy.cycleDay);
   1307                 out.attribute(null, ATTR_CYCLE_TIMEZONE, policy.cycleTimezone);
   1308                 writeLongAttribute(out, ATTR_WARNING_BYTES, policy.warningBytes);
   1309                 writeLongAttribute(out, ATTR_LIMIT_BYTES, policy.limitBytes);
   1310                 writeLongAttribute(out, ATTR_LAST_WARNING_SNOOZE, policy.lastWarningSnooze);
   1311                 writeLongAttribute(out, ATTR_LAST_LIMIT_SNOOZE, policy.lastLimitSnooze);
   1312                 writeBooleanAttribute(out, ATTR_METERED, policy.metered);
   1313                 writeBooleanAttribute(out, ATTR_INFERRED, policy.inferred);
   1314                 out.endTag(null, TAG_NETWORK_POLICY);
   1315             }
   1316 
   1317             // write all known uid policies
   1318             for (int i = 0; i < mUidPolicy.size(); i++) {
   1319                 final int uid = mUidPolicy.keyAt(i);
   1320                 final int policy = mUidPolicy.valueAt(i);
   1321 
   1322                 // skip writing empty policies
   1323                 if (policy == POLICY_NONE) continue;
   1324 
   1325                 out.startTag(null, TAG_UID_POLICY);
   1326                 writeIntAttribute(out, ATTR_UID, uid);
   1327                 writeIntAttribute(out, ATTR_POLICY, policy);
   1328                 out.endTag(null, TAG_UID_POLICY);
   1329             }
   1330 
   1331             out.endTag(null, TAG_POLICY_LIST);
   1332             out.endDocument();
   1333 
   1334             mPolicyFile.finishWrite(fos);
   1335         } catch (IOException e) {
   1336             if (fos != null) {
   1337                 mPolicyFile.failWrite(fos);
   1338             }
   1339         }
   1340     }
   1341 
   1342     @Override
   1343     public void setUidPolicy(int uid, int policy) {
   1344         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1345 
   1346         if (!UserHandle.isApp(uid)) {
   1347             throw new IllegalArgumentException("cannot apply policy to UID " + uid);
   1348         }
   1349 
   1350         setUidPolicyUnchecked(uid, policy, true);
   1351     }
   1352 
   1353     private void setUidPolicyUnchecked(int uid, int policy, boolean persist) {
   1354         final int oldPolicy;
   1355         synchronized (mRulesLock) {
   1356             oldPolicy = getUidPolicy(uid);
   1357             mUidPolicy.put(uid, policy);
   1358 
   1359             // uid policy changed, recompute rules and persist policy.
   1360             updateRulesForUidLocked(uid);
   1361             if (persist) {
   1362                 writePolicyLocked();
   1363             }
   1364         }
   1365     }
   1366 
   1367     @Override
   1368     public int getUidPolicy(int uid) {
   1369         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1370 
   1371         synchronized (mRulesLock) {
   1372             return mUidPolicy.get(uid, POLICY_NONE);
   1373         }
   1374     }
   1375 
   1376     @Override
   1377     public int[] getUidsWithPolicy(int policy) {
   1378         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1379 
   1380         int[] uids = new int[0];
   1381         synchronized (mRulesLock) {
   1382             for (int i = 0; i < mUidPolicy.size(); i++) {
   1383                 final int uid = mUidPolicy.keyAt(i);
   1384                 final int uidPolicy = mUidPolicy.valueAt(i);
   1385                 if (uidPolicy == policy) {
   1386                     uids = appendInt(uids, uid);
   1387                 }
   1388             }
   1389         }
   1390         return uids;
   1391     }
   1392 
   1393     /**
   1394      * Remove any policies associated with given {@link UserHandle}, persisting
   1395      * if any changes are made.
   1396      */
   1397     private void removePoliciesForUserLocked(int userId) {
   1398         if (LOGV) Slog.v(TAG, "removePoliciesForUserLocked()");
   1399 
   1400         int[] uids = new int[0];
   1401         for (int i = 0; i < mUidPolicy.size(); i++) {
   1402             final int uid = mUidPolicy.keyAt(i);
   1403             if (UserHandle.getUserId(uid) == userId) {
   1404                 uids = appendInt(uids, uid);
   1405             }
   1406         }
   1407 
   1408         if (uids.length > 0) {
   1409             for (int uid : uids) {
   1410                 mUidPolicy.delete(uid);
   1411                 updateRulesForUidLocked(uid);
   1412             }
   1413             writePolicyLocked();
   1414         }
   1415     }
   1416 
   1417     @Override
   1418     public void registerListener(INetworkPolicyListener listener) {
   1419         // TODO: create permission for observing network policy
   1420         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1421 
   1422         mListeners.register(listener);
   1423 
   1424         // TODO: consider dispatching existing rules to new listeners
   1425     }
   1426 
   1427     @Override
   1428     public void unregisterListener(INetworkPolicyListener listener) {
   1429         // TODO: create permission for observing network policy
   1430         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
   1431 
   1432         mListeners.unregister(listener);
   1433     }
   1434 
   1435     @Override
   1436     public void setNetworkPolicies(NetworkPolicy[] policies) {
   1437         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1438 
   1439         maybeRefreshTrustedTime();
   1440         synchronized (mRulesLock) {
   1441             mNetworkPolicy.clear();
   1442             for (NetworkPolicy policy : policies) {
   1443                 mNetworkPolicy.put(policy.template, policy);
   1444             }
   1445 
   1446             updateNetworkEnabledLocked();
   1447             updateNetworkRulesLocked();
   1448             updateNotificationsLocked();
   1449             writePolicyLocked();
   1450         }
   1451     }
   1452 
   1453     private void addNetworkPolicyLocked(NetworkPolicy policy) {
   1454         mNetworkPolicy.put(policy.template, policy);
   1455 
   1456         updateNetworkEnabledLocked();
   1457         updateNetworkRulesLocked();
   1458         updateNotificationsLocked();
   1459         writePolicyLocked();
   1460     }
   1461 
   1462     @Override
   1463     public NetworkPolicy[] getNetworkPolicies() {
   1464         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1465         mContext.enforceCallingOrSelfPermission(READ_PHONE_STATE, TAG);
   1466 
   1467         synchronized (mRulesLock) {
   1468             return mNetworkPolicy.values().toArray(new NetworkPolicy[mNetworkPolicy.size()]);
   1469         }
   1470     }
   1471 
   1472     @Override
   1473     public void snoozeLimit(NetworkTemplate template) {
   1474         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1475 
   1476         final long token = Binder.clearCallingIdentity();
   1477         try {
   1478             performSnooze(template, TYPE_LIMIT);
   1479         } finally {
   1480             Binder.restoreCallingIdentity(token);
   1481         }
   1482     }
   1483 
   1484     private void performSnooze(NetworkTemplate template, int type) {
   1485         maybeRefreshTrustedTime();
   1486         final long currentTime = currentTimeMillis();
   1487         synchronized (mRulesLock) {
   1488             // find and snooze local policy that matches
   1489             final NetworkPolicy policy = mNetworkPolicy.get(template);
   1490             if (policy == null) {
   1491                 throw new IllegalArgumentException("unable to find policy for " + template);
   1492             }
   1493 
   1494             switch (type) {
   1495                 case TYPE_WARNING:
   1496                     policy.lastWarningSnooze = currentTime;
   1497                     break;
   1498                 case TYPE_LIMIT:
   1499                     policy.lastLimitSnooze = currentTime;
   1500                     break;
   1501                 default:
   1502                     throw new IllegalArgumentException("unexpected type");
   1503             }
   1504 
   1505             updateNetworkEnabledLocked();
   1506             updateNetworkRulesLocked();
   1507             updateNotificationsLocked();
   1508             writePolicyLocked();
   1509         }
   1510     }
   1511 
   1512     @Override
   1513     public void setRestrictBackground(boolean restrictBackground) {
   1514         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1515 
   1516         maybeRefreshTrustedTime();
   1517         synchronized (mRulesLock) {
   1518             mRestrictBackground = restrictBackground;
   1519             updateRulesForRestrictBackgroundLocked();
   1520             updateNotificationsLocked();
   1521             writePolicyLocked();
   1522         }
   1523 
   1524         mHandler.obtainMessage(MSG_RESTRICT_BACKGROUND_CHANGED, restrictBackground ? 1 : 0, 0)
   1525                 .sendToTarget();
   1526     }
   1527 
   1528     @Override
   1529     public boolean getRestrictBackground() {
   1530         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1531 
   1532         synchronized (mRulesLock) {
   1533             return mRestrictBackground;
   1534         }
   1535     }
   1536 
   1537     private NetworkPolicy findPolicyForNetworkLocked(NetworkIdentity ident) {
   1538         for (NetworkPolicy policy : mNetworkPolicy.values()) {
   1539             if (policy.template.matches(ident)) {
   1540                 return policy;
   1541             }
   1542         }
   1543         return null;
   1544     }
   1545 
   1546     @Override
   1547     public NetworkQuotaInfo getNetworkQuotaInfo(NetworkState state) {
   1548         mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
   1549 
   1550         // only returns usage summary, so we don't require caller to have
   1551         // READ_NETWORK_USAGE_HISTORY.
   1552         final long token = Binder.clearCallingIdentity();
   1553         try {
   1554             return getNetworkQuotaInfoUnchecked(state);
   1555         } finally {
   1556             Binder.restoreCallingIdentity(token);
   1557         }
   1558     }
   1559 
   1560     private NetworkQuotaInfo getNetworkQuotaInfoUnchecked(NetworkState state) {
   1561         final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
   1562 
   1563         final NetworkPolicy policy;
   1564         synchronized (mRulesLock) {
   1565             policy = findPolicyForNetworkLocked(ident);
   1566         }
   1567 
   1568         if (policy == null || !policy.hasCycle()) {
   1569             // missing policy means we can't derive useful quota info
   1570             return null;
   1571         }
   1572 
   1573         final long currentTime = currentTimeMillis();
   1574 
   1575         // find total bytes used under policy
   1576         final long start = computeLastCycleBoundary(currentTime, policy);
   1577         final long end = currentTime;
   1578         final long totalBytes = getTotalBytes(policy.template, start, end);
   1579 
   1580         // report soft and hard limits under policy
   1581         final long softLimitBytes = policy.warningBytes != WARNING_DISABLED ? policy.warningBytes
   1582                 : NetworkQuotaInfo.NO_LIMIT;
   1583         final long hardLimitBytes = policy.limitBytes != LIMIT_DISABLED ? policy.limitBytes
   1584                 : NetworkQuotaInfo.NO_LIMIT;
   1585 
   1586         return new NetworkQuotaInfo(totalBytes, softLimitBytes, hardLimitBytes);
   1587     }
   1588 
   1589     @Override
   1590     public boolean isNetworkMetered(NetworkState state) {
   1591         final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
   1592 
   1593         // roaming networks are always considered metered
   1594         if (ident.getRoaming()) {
   1595             return true;
   1596         }
   1597 
   1598         final NetworkPolicy policy;
   1599         synchronized (mRulesLock) {
   1600             policy = findPolicyForNetworkLocked(ident);
   1601         }
   1602 
   1603         if (policy != null) {
   1604             return policy.metered;
   1605         } else {
   1606             final int type = state.networkInfo.getType();
   1607             if (isNetworkTypeMobile(type) || type == TYPE_WIMAX) {
   1608                 return true;
   1609             }
   1610             return false;
   1611         }
   1612     }
   1613 
   1614     @Override
   1615     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
   1616         mContext.enforceCallingOrSelfPermission(DUMP, TAG);
   1617 
   1618         final IndentingPrintWriter fout = new IndentingPrintWriter(writer, "  ");
   1619 
   1620         final HashSet<String> argSet = new HashSet<String>();
   1621         for (String arg : args) {
   1622             argSet.add(arg);
   1623         }
   1624 
   1625         synchronized (mRulesLock) {
   1626             if (argSet.contains("--unsnooze")) {
   1627                 for (NetworkPolicy policy : mNetworkPolicy.values()) {
   1628                     policy.clearSnooze();
   1629                 }
   1630 
   1631                 updateNetworkEnabledLocked();
   1632                 updateNetworkRulesLocked();
   1633                 updateNotificationsLocked();
   1634                 writePolicyLocked();
   1635 
   1636                 fout.println("Cleared snooze timestamps");
   1637                 return;
   1638             }
   1639 
   1640             fout.print("Restrict background: "); fout.println(mRestrictBackground);
   1641             fout.println("Network policies:");
   1642             fout.increaseIndent();
   1643             for (NetworkPolicy policy : mNetworkPolicy.values()) {
   1644                 fout.println(policy.toString());
   1645             }
   1646             fout.decreaseIndent();
   1647 
   1648             fout.println("Policy for UIDs:");
   1649             fout.increaseIndent();
   1650             int size = mUidPolicy.size();
   1651             for (int i = 0; i < size; i++) {
   1652                 final int uid = mUidPolicy.keyAt(i);
   1653                 final int policy = mUidPolicy.valueAt(i);
   1654                 fout.print("UID=");
   1655                 fout.print(uid);
   1656                 fout.print(" policy=");
   1657                 dumpPolicy(fout, policy);
   1658                 fout.println();
   1659             }
   1660             fout.decreaseIndent();
   1661 
   1662             final SparseBooleanArray knownUids = new SparseBooleanArray();
   1663             collectKeys(mUidForeground, knownUids);
   1664             collectKeys(mUidRules, knownUids);
   1665 
   1666             fout.println("Status for known UIDs:");
   1667             fout.increaseIndent();
   1668             size = knownUids.size();
   1669             for (int i = 0; i < size; i++) {
   1670                 final int uid = knownUids.keyAt(i);
   1671                 fout.print("UID=");
   1672                 fout.print(uid);
   1673 
   1674                 fout.print(" foreground=");
   1675                 final int foregroundIndex = mUidPidForeground.indexOfKey(uid);
   1676                 if (foregroundIndex < 0) {
   1677                     fout.print("UNKNOWN");
   1678                 } else {
   1679                     dumpSparseBooleanArray(fout, mUidPidForeground.valueAt(foregroundIndex));
   1680                 }
   1681 
   1682                 fout.print(" rules=");
   1683                 final int rulesIndex = mUidRules.indexOfKey(uid);
   1684                 if (rulesIndex < 0) {
   1685                     fout.print("UNKNOWN");
   1686                 } else {
   1687                     dumpRules(fout, mUidRules.valueAt(rulesIndex));
   1688                 }
   1689 
   1690                 fout.println();
   1691             }
   1692             fout.decreaseIndent();
   1693         }
   1694     }
   1695 
   1696     @Override
   1697     public boolean isUidForeground(int uid) {
   1698         mContext.enforceCallingOrSelfPermission(MANAGE_NETWORK_POLICY, TAG);
   1699 
   1700         synchronized (mRulesLock) {
   1701             // only really in foreground when screen is also on
   1702             return mUidForeground.get(uid, false) && mScreenOn;
   1703         }
   1704     }
   1705 
   1706     /**
   1707      * Foreground for PID changed; recompute foreground at UID level. If
   1708      * changed, will trigger {@link #updateRulesForUidLocked(int)}.
   1709      */
   1710     private void computeUidForegroundLocked(int uid) {
   1711         final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
   1712 
   1713         // current pid is dropping foreground; examine other pids
   1714         boolean uidForeground = false;
   1715         final int size = pidForeground.size();
   1716         for (int i = 0; i < size; i++) {
   1717             if (pidForeground.valueAt(i)) {
   1718                 uidForeground = true;
   1719                 break;
   1720             }
   1721         }
   1722 
   1723         final boolean oldUidForeground = mUidForeground.get(uid, false);
   1724         if (oldUidForeground != uidForeground) {
   1725             // foreground changed, push updated rules
   1726             mUidForeground.put(uid, uidForeground);
   1727             updateRulesForUidLocked(uid);
   1728         }
   1729     }
   1730 
   1731     private void updateScreenOn() {
   1732         synchronized (mRulesLock) {
   1733             try {
   1734                 mScreenOn = mPowerManager.isScreenOn();
   1735             } catch (RemoteException e) {
   1736                 // ignored; service lives in system_server
   1737             }
   1738             updateRulesForScreenLocked();
   1739         }
   1740     }
   1741 
   1742     /**
   1743      * Update rules that might be changed by {@link #mScreenOn} value.
   1744      */
   1745     private void updateRulesForScreenLocked() {
   1746         // only update rules for anyone with foreground activities
   1747         final int size = mUidForeground.size();
   1748         for (int i = 0; i < size; i++) {
   1749             if (mUidForeground.valueAt(i)) {
   1750                 final int uid = mUidForeground.keyAt(i);
   1751                 updateRulesForUidLocked(uid);
   1752             }
   1753         }
   1754     }
   1755 
   1756     /**
   1757      * Update rules that might be changed by {@link #mRestrictBackground} value.
   1758      */
   1759     private void updateRulesForRestrictBackgroundLocked() {
   1760         final PackageManager pm = mContext.getPackageManager();
   1761         final UserManager um = (UserManager) mContext.getSystemService(Context.USER_SERVICE);
   1762 
   1763         // update rules for all installed applications
   1764         final List<UserInfo> users = um.getUsers();
   1765         final List<ApplicationInfo> apps = pm.getInstalledApplications(
   1766                 PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
   1767 
   1768         for (UserInfo user : users) {
   1769             for (ApplicationInfo app : apps) {
   1770                 final int uid = UserHandle.getUid(user.id, app.uid);
   1771                 updateRulesForUidLocked(uid);
   1772             }
   1773         }
   1774 
   1775         // limit data usage for some internal system services
   1776         updateRulesForUidLocked(android.os.Process.MEDIA_UID);
   1777         updateRulesForUidLocked(android.os.Process.DRM_UID);
   1778     }
   1779 
   1780     private static boolean isUidValidForRules(int uid) {
   1781         // allow rules on specific system services, and any apps
   1782         if (uid == android.os.Process.MEDIA_UID || uid == android.os.Process.DRM_UID
   1783                 || UserHandle.isApp(uid)) {
   1784             return true;
   1785         }
   1786 
   1787         return false;
   1788     }
   1789 
   1790     private void updateRulesForUidLocked(int uid) {
   1791         if (!isUidValidForRules(uid)) return;
   1792 
   1793         final int uidPolicy = getUidPolicy(uid);
   1794         final boolean uidForeground = isUidForeground(uid);
   1795 
   1796         // derive active rules based on policy and active state
   1797         int uidRules = RULE_ALLOW_ALL;
   1798         if (!uidForeground && (uidPolicy & POLICY_REJECT_METERED_BACKGROUND) != 0) {
   1799             // uid in background, and policy says to block metered data
   1800             uidRules = RULE_REJECT_METERED;
   1801         }
   1802         if (!uidForeground && mRestrictBackground) {
   1803             // uid in background, and global background disabled
   1804             uidRules = RULE_REJECT_METERED;
   1805         }
   1806 
   1807         // TODO: only dispatch when rules actually change
   1808 
   1809         if (uidRules == RULE_ALLOW_ALL) {
   1810             mUidRules.delete(uid);
   1811         } else {
   1812             mUidRules.put(uid, uidRules);
   1813         }
   1814 
   1815         final boolean rejectMetered = (uidRules & RULE_REJECT_METERED) != 0;
   1816         setUidNetworkRules(uid, rejectMetered);
   1817 
   1818         // dispatch changed rule to existing listeners
   1819         mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
   1820 
   1821         try {
   1822             // adjust stats accounting based on foreground status
   1823             mNetworkStats.setUidForeground(uid, uidForeground);
   1824         } catch (RemoteException e) {
   1825             // ignored; service lives in system_server
   1826         }
   1827     }
   1828 
   1829     private Handler.Callback mHandlerCallback = new Handler.Callback() {
   1830         @Override
   1831         public boolean handleMessage(Message msg) {
   1832             switch (msg.what) {
   1833                 case MSG_RULES_CHANGED: {
   1834                     final int uid = msg.arg1;
   1835                     final int uidRules = msg.arg2;
   1836                     final int length = mListeners.beginBroadcast();
   1837                     for (int i = 0; i < length; i++) {
   1838                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
   1839                         if (listener != null) {
   1840                             try {
   1841                                 listener.onUidRulesChanged(uid, uidRules);
   1842                             } catch (RemoteException e) {
   1843                             }
   1844                         }
   1845                     }
   1846                     mListeners.finishBroadcast();
   1847                     return true;
   1848                 }
   1849                 case MSG_METERED_IFACES_CHANGED: {
   1850                     final String[] meteredIfaces = (String[]) msg.obj;
   1851                     final int length = mListeners.beginBroadcast();
   1852                     for (int i = 0; i < length; i++) {
   1853                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
   1854                         if (listener != null) {
   1855                             try {
   1856                                 listener.onMeteredIfacesChanged(meteredIfaces);
   1857                             } catch (RemoteException e) {
   1858                             }
   1859                         }
   1860                     }
   1861                     mListeners.finishBroadcast();
   1862                     return true;
   1863                 }
   1864                 case MSG_FOREGROUND_ACTIVITIES_CHANGED: {
   1865                     final int pid = msg.arg1;
   1866                     final int uid = msg.arg2;
   1867                     final boolean foregroundActivities = (Boolean) msg.obj;
   1868 
   1869                     synchronized (mRulesLock) {
   1870                         // because a uid can have multiple pids running inside, we need to
   1871                         // remember all pid states and summarize foreground at uid level.
   1872 
   1873                         // record foreground for this specific pid
   1874                         SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
   1875                         if (pidForeground == null) {
   1876                             pidForeground = new SparseBooleanArray(2);
   1877                             mUidPidForeground.put(uid, pidForeground);
   1878                         }
   1879                         pidForeground.put(pid, foregroundActivities);
   1880                         computeUidForegroundLocked(uid);
   1881                     }
   1882                     return true;
   1883                 }
   1884                 case MSG_PROCESS_DIED: {
   1885                     final int pid = msg.arg1;
   1886                     final int uid = msg.arg2;
   1887 
   1888                     synchronized (mRulesLock) {
   1889                         // clear records and recompute, when they exist
   1890                         final SparseBooleanArray pidForeground = mUidPidForeground.get(uid);
   1891                         if (pidForeground != null) {
   1892                             pidForeground.delete(pid);
   1893                             computeUidForegroundLocked(uid);
   1894                         }
   1895                     }
   1896                     return true;
   1897                 }
   1898                 case MSG_LIMIT_REACHED: {
   1899                     final String iface = (String) msg.obj;
   1900 
   1901                     maybeRefreshTrustedTime();
   1902                     synchronized (mRulesLock) {
   1903                         if (mMeteredIfaces.contains(iface)) {
   1904                             try {
   1905                                 // force stats update to make sure we have
   1906                                 // numbers that caused alert to trigger.
   1907                                 mNetworkStats.forceUpdate();
   1908                             } catch (RemoteException e) {
   1909                                 // ignored; service lives in system_server
   1910                             }
   1911 
   1912                             updateNetworkEnabledLocked();
   1913                             updateNotificationsLocked();
   1914                         }
   1915                     }
   1916                     return true;
   1917                 }
   1918                 case MSG_RESTRICT_BACKGROUND_CHANGED: {
   1919                     final boolean restrictBackground = msg.arg1 != 0;
   1920                     final int length = mListeners.beginBroadcast();
   1921                     for (int i = 0; i < length; i++) {
   1922                         final INetworkPolicyListener listener = mListeners.getBroadcastItem(i);
   1923                         if (listener != null) {
   1924                             try {
   1925                                 listener.onRestrictBackgroundChanged(restrictBackground);
   1926                             } catch (RemoteException e) {
   1927                             }
   1928                         }
   1929                     }
   1930                     mListeners.finishBroadcast();
   1931                     return true;
   1932                 }
   1933                 case MSG_ADVISE_PERSIST_THRESHOLD: {
   1934                     final long lowestRule = (Long) msg.obj;
   1935                     try {
   1936                         // make sure stats are recorded frequently enough; we aim
   1937                         // for 2MB threshold for 2GB/month rules.
   1938                         final long persistThreshold = lowestRule / 1000;
   1939                         mNetworkStats.advisePersistThreshold(persistThreshold);
   1940                     } catch (RemoteException e) {
   1941                         // ignored; service lives in system_server
   1942                     }
   1943                     return true;
   1944                 }
   1945                 case MSG_SCREEN_ON_CHANGED: {
   1946                     updateScreenOn();
   1947                     return true;
   1948                 }
   1949                 default: {
   1950                     return false;
   1951                 }
   1952             }
   1953         }
   1954     };
   1955 
   1956     private void setInterfaceQuota(String iface, long quotaBytes) {
   1957         try {
   1958             mNetworkManager.setInterfaceQuota(iface, quotaBytes);
   1959         } catch (IllegalStateException e) {
   1960             Log.wtf(TAG, "problem setting interface quota", e);
   1961         } catch (RemoteException e) {
   1962             // ignored; service lives in system_server
   1963         }
   1964     }
   1965 
   1966     private void removeInterfaceQuota(String iface) {
   1967         try {
   1968             mNetworkManager.removeInterfaceQuota(iface);
   1969         } catch (IllegalStateException e) {
   1970             Log.wtf(TAG, "problem removing interface quota", e);
   1971         } catch (RemoteException e) {
   1972             // ignored; service lives in system_server
   1973         }
   1974     }
   1975 
   1976     private void setUidNetworkRules(int uid, boolean rejectOnQuotaInterfaces) {
   1977         try {
   1978             mNetworkManager.setUidNetworkRules(uid, rejectOnQuotaInterfaces);
   1979         } catch (IllegalStateException e) {
   1980             Log.wtf(TAG, "problem setting uid rules", e);
   1981         } catch (RemoteException e) {
   1982             // ignored; service lives in system_server
   1983         }
   1984     }
   1985 
   1986     /**
   1987      * Control {@link IConnectivityManager#setPolicyDataEnable(int, boolean)}.
   1988      */
   1989     private void setPolicyDataEnable(int networkType, boolean enabled) {
   1990         try {
   1991             mConnManager.setPolicyDataEnable(networkType, enabled);
   1992         } catch (RemoteException e) {
   1993             // ignored; service lives in system_server
   1994         }
   1995     }
   1996 
   1997     private long getTotalBytes(NetworkTemplate template, long start, long end) {
   1998         try {
   1999             return mNetworkStats.getNetworkTotalBytes(template, start, end);
   2000         } catch (RuntimeException e) {
   2001             Slog.w(TAG, "problem reading network stats: " + e);
   2002             return 0;
   2003         } catch (RemoteException e) {
   2004             // ignored; service lives in system_server
   2005             return 0;
   2006         }
   2007     }
   2008 
   2009     private boolean isBandwidthControlEnabled() {
   2010         final long token = Binder.clearCallingIdentity();
   2011         try {
   2012             return mNetworkManager.isBandwidthControlEnabled();
   2013         } catch (RemoteException e) {
   2014             // ignored; service lives in system_server
   2015             return false;
   2016         } finally {
   2017             Binder.restoreCallingIdentity(token);
   2018         }
   2019     }
   2020 
   2021     /**
   2022      * Try refreshing {@link #mTime} when stale.
   2023      */
   2024     private void maybeRefreshTrustedTime() {
   2025         if (mTime.getCacheAge() > TIME_CACHE_MAX_AGE) {
   2026             mTime.forceRefresh();
   2027         }
   2028     }
   2029 
   2030     private long currentTimeMillis() {
   2031         return mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
   2032     }
   2033 
   2034     private static Intent buildAllowBackgroundDataIntent() {
   2035         return new Intent(ACTION_ALLOW_BACKGROUND);
   2036     }
   2037 
   2038     private static Intent buildSnoozeWarningIntent(NetworkTemplate template) {
   2039         final Intent intent = new Intent(ACTION_SNOOZE_WARNING);
   2040         intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
   2041         return intent;
   2042     }
   2043 
   2044     private static Intent buildNetworkOverLimitIntent(NetworkTemplate template) {
   2045         final Intent intent = new Intent();
   2046         intent.setComponent(new ComponentName(
   2047                 "com.android.systemui", "com.android.systemui.net.NetworkOverLimitActivity"));
   2048         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   2049         intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
   2050         return intent;
   2051     }
   2052 
   2053     private static Intent buildViewDataUsageIntent(NetworkTemplate template) {
   2054         final Intent intent = new Intent();
   2055         intent.setComponent(new ComponentName(
   2056                 "com.android.settings", "com.android.settings.Settings$DataUsageSummaryActivity"));
   2057         intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   2058         intent.putExtra(EXTRA_NETWORK_TEMPLATE, template);
   2059         return intent;
   2060     }
   2061 
   2062     @VisibleForTesting
   2063     public void addIdleHandler(IdleHandler handler) {
   2064         mHandler.getLooper().getQueue().addIdleHandler(handler);
   2065     }
   2066 
   2067     private static void collectKeys(SparseIntArray source, SparseBooleanArray target) {
   2068         final int size = source.size();
   2069         for (int i = 0; i < size; i++) {
   2070             target.put(source.keyAt(i), true);
   2071         }
   2072     }
   2073 
   2074     private static void collectKeys(SparseBooleanArray source, SparseBooleanArray target) {
   2075         final int size = source.size();
   2076         for (int i = 0; i < size; i++) {
   2077             target.put(source.keyAt(i), true);
   2078         }
   2079     }
   2080 
   2081     private static void dumpSparseBooleanArray(PrintWriter fout, SparseBooleanArray value) {
   2082         fout.print("[");
   2083         final int size = value.size();
   2084         for (int i = 0; i < size; i++) {
   2085             fout.print(value.keyAt(i) + "=" + value.valueAt(i));
   2086             if (i < size - 1) fout.print(",");
   2087         }
   2088         fout.print("]");
   2089     }
   2090 }
   2091