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