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